mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
add splitter
This commit is contained in:
+144
-7
@@ -233,6 +233,12 @@ type
|
|||||||
FSpectrumWidth: Integer;
|
FSpectrumWidth: Integer;
|
||||||
FSpectrumHeight: Integer;
|
FSpectrumHeight: Integer;
|
||||||
FWaterfallHeight:Integer;
|
FWaterfallHeight:Integer;
|
||||||
|
// ---- Splitter между спектром и водопадом ----
|
||||||
|
FSplitter: TPanel; // визуальная полоса-разделитель
|
||||||
|
FSplitterDrag: Boolean; // True = идёт перетаскивание
|
||||||
|
FSplitterDragY0: Integer; // Y мыши в начале перетаскивания (в координатах PanelRight)
|
||||||
|
FSplitterSH0: Integer; // FSpectrumHeight в начале перетаскивания
|
||||||
|
FSplitterRatio: Double; // соотношение высоты спектра (0.15..0.85), сохраняется
|
||||||
// Водопад: прямой массив пикселей BGRA + RawImage bitmap без IntfImage roundtrip
|
// Водопад: прямой массив пикселей BGRA + RawImage bitmap без IntfImage roundtrip
|
||||||
FWfPixels: array of LongWord; // W×H пикселей, строка 0 = верх (новейшая)
|
FWfPixels: array of LongWord; // W×H пикселей, строка 0 = верх (новейшая)
|
||||||
FWfBitmap: TBitmap;
|
FWfBitmap: TBitmap;
|
||||||
@@ -347,6 +353,7 @@ type
|
|||||||
BtnHidePanel: TFlatButton; // скрыть/показать левую панель
|
BtnHidePanel: TFlatButton; // скрыть/показать левую панель
|
||||||
PbSpectrum: TPaintBox;
|
PbSpectrum: TPaintBox;
|
||||||
PbRuler: TPaintBox; // полоса частотных меток между спектром и водопадом
|
PbRuler: TPaintBox; // полоса частотных меток между спектром и водопадом
|
||||||
|
PanelSplitter: TPanel; // перетаскиваемый разделитель спектр/водопад
|
||||||
PbWaterfall: TPaintBox;
|
PbWaterfall: TPaintBox;
|
||||||
|
|
||||||
// ---- Status bar ----
|
// ---- Status bar ----
|
||||||
@@ -502,6 +509,13 @@ type
|
|||||||
procedure SpectrumTimerTick(Sender: TObject);
|
procedure SpectrumTimerTick(Sender: TObject);
|
||||||
procedure RightPanelResize(Sender: TObject);
|
procedure RightPanelResize(Sender: TObject);
|
||||||
procedure AfterShowTick(Sender: TObject);
|
procedure AfterShowTick(Sender: TObject);
|
||||||
|
// Splitter handlers
|
||||||
|
procedure SplitterMouseDown(Sender: TObject; Button: TMouseButton;
|
||||||
|
Shift: TShiftState; X, Y: Integer);
|
||||||
|
procedure SplitterMouseMove(Sender: TObject; Shift: TShiftState;
|
||||||
|
X, Y: Integer);
|
||||||
|
procedure SplitterMouseUp(Sender: TObject; Button: TMouseButton;
|
||||||
|
Shift: TShiftState; X, Y: Integer);
|
||||||
|
|
||||||
published
|
published
|
||||||
// Обработчики событий формы — должны быть в published для RTTI/LFM
|
// Обработчики событий формы — должны быть в published для RTTI/LFM
|
||||||
@@ -821,6 +835,8 @@ begin
|
|||||||
FVfoOverlay.OnSelect := OnModeFilterSelect;
|
FVfoOverlay.OnSelect := OnModeFilterSelect;
|
||||||
FVfoOverlay.Visible := False;
|
FVfoOverlay.Visible := False;
|
||||||
FPanelHidden := False;
|
FPanelHidden := False;
|
||||||
|
FSplitterRatio := 0.40; // 40% спектр, 60% водопад по умолчанию
|
||||||
|
FSplitterDrag := False;
|
||||||
|
|
||||||
FSpectrumBitmap := TBitmap.Create;
|
FSpectrumBitmap := TBitmap.Create;
|
||||||
FWaterfallBitmap := TBitmap.Create;
|
FWaterfallBitmap := TBitmap.Create;
|
||||||
@@ -1331,6 +1347,17 @@ begin
|
|||||||
PbRuler.OnPaint := PbRulerPaint;
|
PbRuler.OnPaint := PbRulerPaint;
|
||||||
PbRuler.Cursor := crDefault;
|
PbRuler.Cursor := crDefault;
|
||||||
|
|
||||||
|
// ---- Splitter между спектром+линейкой и водопадом ----
|
||||||
|
PanelSplitter := TPanel.Create(Self);
|
||||||
|
PanelSplitter.Parent := PanelRight;
|
||||||
|
PanelSplitter.BevelOuter := bvNone;
|
||||||
|
PanelSplitter.Color := TColor($00303030);
|
||||||
|
PanelSplitter.Cursor := crVSplit;
|
||||||
|
PanelSplitter.Height := 5;
|
||||||
|
PanelSplitter.OnMouseDown := SplitterMouseDown;
|
||||||
|
PanelSplitter.OnMouseMove := SplitterMouseMove;
|
||||||
|
PanelSplitter.OnMouseUp := SplitterMouseUp;
|
||||||
|
|
||||||
PbWaterfall := TPaintBox.Create(Self);
|
PbWaterfall := TPaintBox.Create(Self);
|
||||||
PbWaterfall.Parent := PanelRight;
|
PbWaterfall.Parent := PanelRight;
|
||||||
PbWaterfall.OnPaint := PbWaterfallPaint;
|
PbWaterfall.OnPaint := PbWaterfallPaint;
|
||||||
@@ -1352,6 +1379,97 @@ begin
|
|||||||
ResizeSpectrumPanels;
|
ResizeSpectrumPanels;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
// Splitter — перетаскивание границы спектр/водопад
|
||||||
|
// Обновление размеров происходит только при отпускании мыши (MouseUp),
|
||||||
|
// чтобы исключить фризы во время перетаскивания.
|
||||||
|
// Во время перетаскивания рисуем только призрак-линию на PanelSplitter.
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
|
procedure TMainForm.SplitterMouseDown(Sender: TObject; Button: TMouseButton;
|
||||||
|
Shift: TShiftState; X, Y: Integer);
|
||||||
|
var
|
||||||
|
P: TPoint;
|
||||||
|
begin
|
||||||
|
if Button <> mbLeft then Exit;
|
||||||
|
FSplitterDrag := True;
|
||||||
|
FSplitterSH0 := FSpectrumHeight;
|
||||||
|
// Y в координатах PanelRight
|
||||||
|
P := PanelRight.ScreenToClient(PanelSplitter.ClientToScreen(Point(X, Y)));
|
||||||
|
FSplitterDragY0 := P.Y;
|
||||||
|
PanelSplitter.Color := TColor($005050A0); // подсветка при захвате
|
||||||
|
{$IFDEF WINDOWS}
|
||||||
|
SetCapture(PanelSplitter.Handle);
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.SplitterMouseMove(Sender: TObject; Shift: TShiftState;
|
||||||
|
X, Y: Integer);
|
||||||
|
var
|
||||||
|
P: TPoint;
|
||||||
|
DeltaY: Integer;
|
||||||
|
NewSH: Integer;
|
||||||
|
TopOff, AvailH: Integer;
|
||||||
|
const
|
||||||
|
RULER_H = 18;
|
||||||
|
SPLITTER_H = 5;
|
||||||
|
MIN_SH = 60;
|
||||||
|
MIN_WH = 40;
|
||||||
|
begin
|
||||||
|
if not FSplitterDrag then Exit;
|
||||||
|
P := PanelRight.ScreenToClient(PanelSplitter.ClientToScreen(Point(X, Y)));
|
||||||
|
DeltaY := P.Y - FSplitterDragY0;
|
||||||
|
|
||||||
|
TopOff := PanelSpanButtons.Height;
|
||||||
|
AvailH := PanelRight.ClientHeight - TopOff - RULER_H - SPLITTER_H;
|
||||||
|
if AvailH <= 0 then Exit;
|
||||||
|
|
||||||
|
NewSH := FSplitterSH0 + DeltaY;
|
||||||
|
if NewSH < MIN_SH then NewSH := MIN_SH;
|
||||||
|
if NewSH > AvailH - MIN_WH then NewSH := AvailH - MIN_WH;
|
||||||
|
|
||||||
|
// Только двигаем сплиттер визуально — без пересчёта битмапов
|
||||||
|
PanelSplitter.Top := TopOff + NewSH + RULER_H;
|
||||||
|
PbWaterfall.Top := TopOff + NewSH + RULER_H + SPLITTER_H;
|
||||||
|
PbWaterfall.Height := AvailH - NewSH;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.SplitterMouseUp(Sender: TObject; Button: TMouseButton;
|
||||||
|
Shift: TShiftState; X, Y: Integer);
|
||||||
|
var
|
||||||
|
P: TPoint;
|
||||||
|
DeltaY: Integer;
|
||||||
|
NewSH: Integer;
|
||||||
|
TopOff, AvailH: Integer;
|
||||||
|
const
|
||||||
|
RULER_H = 18;
|
||||||
|
SPLITTER_H = 5;
|
||||||
|
MIN_SH = 60;
|
||||||
|
MIN_WH = 40;
|
||||||
|
begin
|
||||||
|
if not FSplitterDrag then Exit;
|
||||||
|
FSplitterDrag := False;
|
||||||
|
{$IFDEF WINDOWS}
|
||||||
|
ReleaseCapture;
|
||||||
|
{$ENDIF}
|
||||||
|
PanelSplitter.Color := TColor($00303030); // обычный цвет
|
||||||
|
|
||||||
|
P := PanelRight.ScreenToClient(PanelSplitter.ClientToScreen(Point(X, Y)));
|
||||||
|
DeltaY := P.Y - FSplitterDragY0;
|
||||||
|
|
||||||
|
TopOff := PanelSpanButtons.Height;
|
||||||
|
AvailH := PanelRight.ClientHeight - TopOff - RULER_H - SPLITTER_H;
|
||||||
|
if AvailH <= 0 then Exit;
|
||||||
|
|
||||||
|
NewSH := FSplitterSH0 + DeltaY;
|
||||||
|
if NewSH < MIN_SH then NewSH := MIN_SH;
|
||||||
|
if NewSH > AvailH - MIN_WH then NewSH := AvailH - MIN_WH;
|
||||||
|
|
||||||
|
// Сохраняем новое соотношение и делаем полный пересчёт с перерисовкой
|
||||||
|
FSplitterRatio := NewSH / AvailH;
|
||||||
|
ResizeSpectrumPanels;
|
||||||
|
end;
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// Resize handler (normal method instead of anonymous procedure)
|
// Resize handler (normal method instead of anonymous procedure)
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
@@ -1398,8 +1516,14 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.ResizeSpectrumPanels;
|
procedure TMainForm.ResizeSpectrumPanels;
|
||||||
|
const
|
||||||
|
RULER_H = 18;
|
||||||
|
SPLITTER_H = 5;
|
||||||
|
MIN_SH = 60; // минимальная высота спектра
|
||||||
|
MIN_WH = 40; // минимальная высота водопада
|
||||||
var
|
var
|
||||||
RW, RH, SH, WH, TopOff: Integer;
|
RW, RH, SH, WH, TopOff: Integer;
|
||||||
|
AvailH: Integer;
|
||||||
begin
|
begin
|
||||||
if PanelRight = nil then Exit;
|
if PanelRight = nil then Exit;
|
||||||
RW := PanelRight.ClientWidth;
|
RW := PanelRight.ClientWidth;
|
||||||
@@ -1407,16 +1531,29 @@ begin
|
|||||||
TopOff := PanelSpanButtons.Height;
|
TopOff := PanelSpanButtons.Height;
|
||||||
// S-метр позиционируется отдельно в ResizeSMeter
|
// S-метр позиционируется отдельно в ResizeSMeter
|
||||||
ResizeSMeter;
|
ResizeSMeter;
|
||||||
RH := RH - TopOff;
|
AvailH := RH - TopOff - RULER_H - SPLITTER_H;
|
||||||
if RH < 10 then Exit;
|
if AvailH < (MIN_SH + MIN_WH) then Exit;
|
||||||
|
|
||||||
SH := RH * 4 div 10;
|
// Ограничиваем соотношение, чтобы каждая зона имела минимальный размер
|
||||||
WH := RH - SH - 18;
|
if FSplitterRatio < MIN_SH / AvailH then
|
||||||
if WH < 10 then WH := 10;
|
FSplitterRatio := MIN_SH / AvailH;
|
||||||
|
if FSplitterRatio > 1.0 - MIN_WH / AvailH then
|
||||||
|
FSplitterRatio := 1.0 - MIN_WH / AvailH;
|
||||||
|
|
||||||
|
SH := Round(AvailH * FSplitterRatio);
|
||||||
|
WH := AvailH - SH;
|
||||||
|
if WH < MIN_WH then WH := MIN_WH;
|
||||||
|
|
||||||
|
// Спектр
|
||||||
PbSpectrum.SetBounds(0, TopOff, RW, SH);
|
PbSpectrum.SetBounds(0, TopOff, RW, SH);
|
||||||
PbRuler.SetBounds (0, TopOff + SH, RW, 18);
|
// Линейка частот — всегда прижата к низу спектра
|
||||||
PbWaterfall.SetBounds(0, TopOff + SH + 18, RW, WH);
|
PbRuler.SetBounds(0, TopOff + SH, RW, RULER_H);
|
||||||
|
// Сплиттер — между линейкой и водопадом
|
||||||
|
if PanelSplitter <> nil then
|
||||||
|
PanelSplitter.SetBounds(0, TopOff + SH + RULER_H, RW, SPLITTER_H);
|
||||||
|
// Водопад — под сплиттером
|
||||||
|
PbWaterfall.SetBounds(0, TopOff + SH + RULER_H + SPLITTER_H, RW, WH);
|
||||||
|
|
||||||
PositionSpanOverlayButtons;
|
PositionSpanOverlayButtons;
|
||||||
|
|
||||||
// Обновляем переменные размеров
|
// Обновляем переменные размеров
|
||||||
|
|||||||
Reference in New Issue
Block a user