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:
+145
-8
@@ -233,6 +233,12 @@ type
|
||||
FSpectrumWidth: Integer;
|
||||
FSpectrumHeight: 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
|
||||
FWfPixels: array of LongWord; // W×H пикселей, строка 0 = верх (новейшая)
|
||||
FWfBitmap: TBitmap;
|
||||
@@ -347,6 +353,7 @@ type
|
||||
BtnHidePanel: TFlatButton; // скрыть/показать левую панель
|
||||
PbSpectrum: TPaintBox;
|
||||
PbRuler: TPaintBox; // полоса частотных меток между спектром и водопадом
|
||||
PanelSplitter: TPanel; // перетаскиваемый разделитель спектр/водопад
|
||||
PbWaterfall: TPaintBox;
|
||||
|
||||
// ---- Status bar ----
|
||||
@@ -502,6 +509,13 @@ type
|
||||
procedure SpectrumTimerTick(Sender: TObject);
|
||||
procedure RightPanelResize(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 для RTTI/LFM
|
||||
@@ -821,6 +835,8 @@ begin
|
||||
FVfoOverlay.OnSelect := OnModeFilterSelect;
|
||||
FVfoOverlay.Visible := False;
|
||||
FPanelHidden := False;
|
||||
FSplitterRatio := 0.40; // 40% спектр, 60% водопад по умолчанию
|
||||
FSplitterDrag := False;
|
||||
|
||||
FSpectrumBitmap := TBitmap.Create;
|
||||
FWaterfallBitmap := TBitmap.Create;
|
||||
@@ -1331,6 +1347,17 @@ begin
|
||||
PbRuler.OnPaint := PbRulerPaint;
|
||||
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.Parent := PanelRight;
|
||||
PbWaterfall.OnPaint := PbWaterfallPaint;
|
||||
@@ -1352,6 +1379,97 @@ begin
|
||||
ResizeSpectrumPanels;
|
||||
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)
|
||||
// ===========================================================================
|
||||
@@ -1398,8 +1516,14 @@ begin
|
||||
end;
|
||||
|
||||
procedure TMainForm.ResizeSpectrumPanels;
|
||||
const
|
||||
RULER_H = 18;
|
||||
SPLITTER_H = 5;
|
||||
MIN_SH = 60; // минимальная высота спектра
|
||||
MIN_WH = 40; // минимальная высота водопада
|
||||
var
|
||||
RW, RH, SH, WH, TopOff: Integer;
|
||||
AvailH: Integer;
|
||||
begin
|
||||
if PanelRight = nil then Exit;
|
||||
RW := PanelRight.ClientWidth;
|
||||
@@ -1407,16 +1531,29 @@ begin
|
||||
TopOff := PanelSpanButtons.Height;
|
||||
// S-метр позиционируется отдельно в ResizeSMeter
|
||||
ResizeSMeter;
|
||||
RH := RH - TopOff;
|
||||
if RH < 10 then Exit;
|
||||
AvailH := RH - TopOff - RULER_H - SPLITTER_H;
|
||||
if AvailH < (MIN_SH + MIN_WH) then Exit;
|
||||
|
||||
SH := RH * 4 div 10;
|
||||
WH := RH - SH - 18;
|
||||
if WH < 10 then WH := 10;
|
||||
// Ограничиваем соотношение, чтобы каждая зона имела минимальный размер
|
||||
if FSplitterRatio < MIN_SH / AvailH then
|
||||
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);
|
||||
// Линейка частот — всегда прижата к низу спектра
|
||||
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);
|
||||
|
||||
PbSpectrum.SetBounds(0, TopOff, RW, SH);
|
||||
PbRuler.SetBounds (0, TopOff + SH, RW, 18);
|
||||
PbWaterfall.SetBounds(0, TopOff + SH + 18, RW, WH);
|
||||
PositionSpanOverlayButtons;
|
||||
|
||||
// Обновляем переменные размеров
|
||||
|
||||
Reference in New Issue
Block a user