mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-26 04:47:35 +00:00
feat(overlay): redesign VfoOverlay in SmartSDR slice-flag style
Полный редизайн накладки поверх спектра: шапка (слайс-бейдж A/B, ширина фильтра, кликабельный SPLIT, индикатор TX), метр-ряд (индикаторы NR/NB/ANF/ SNB + сигнал-бар), крупная частота + S, нижний бар с fly-out пикерами. - Fly-out движок MODE/DSP/AUD (раскрываются под баром, карточка растёт): MODE — сетка режимов 4×2 + фильтры; DSP — NR/NB/SNB/ANF + AGC; AUD — выбор аудио-устройства вывода (задел под слайсы). - Слайдер громкости (click+drag) + mute; SPLIT-toggle; live TX-индикатор. - Все контролы подключены к RadioController (SetVolume/ToggleMute/SetSplit/ EnumOutputDevices→ApplyAudioDevice); wire в MainForm + HandleMouseUp, чтобы клик по накладке не уходил в спектр. - FormatFreq на Int64 (double накапливал ошибку в десятки Гц на ~10 ГГц QO-100). - S-метр ниже по высоте + плавный градиент по уровню dBm: тёмно-зелёный→ зелёный→жёлтый→красный (красный к ~S9+18). - Кэш+dirty рендер сохранён (CPU-паритет со старой накладкой), GL-путь через DrawOverlayBitmap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+70
-2
@@ -519,6 +519,12 @@ type
|
|||||||
procedure OnModeFilterSelect(Mode: Integer; FilterBW: Integer);
|
procedure OnModeFilterSelect(Mode: Integer; FilterBW: Integer);
|
||||||
procedure OnVfoOverlayDSPChange(NRMode, NBMode: Integer; SNBOn, ANFOn: Boolean);
|
procedure OnVfoOverlayDSPChange(NRMode, NBMode: Integer; SNBOn, ANFOn: Boolean);
|
||||||
procedure OnVfoOverlayAGCChange(AGCMode: Integer);
|
procedure OnVfoOverlayAGCChange(AGCMode: Integer);
|
||||||
|
procedure OnVfoOverlayVolume(Vol: Integer);
|
||||||
|
procedure OnVfoOverlayMute(Sender: TObject);
|
||||||
|
procedure OnVfoOverlayAudioDevice(DevIndex: Integer; const DevName: string);
|
||||||
|
procedure OnVfoOverlaySplit(Sender: TObject);
|
||||||
|
procedure PushVfoOverlayExtState;
|
||||||
|
procedure PushVfoOverlayAudioDevices;
|
||||||
procedure OnVfoOverlayInvalidate(Sender: TObject);
|
procedure OnVfoOverlayInvalidate(Sender: TObject);
|
||||||
procedure PbSpectrumDblClick(Sender: TObject);
|
procedure PbSpectrumDblClick(Sender: TObject);
|
||||||
procedure TrkDriveChange(Sender: TObject);
|
procedure TrkDriveChange(Sender: TObject);
|
||||||
@@ -956,6 +962,10 @@ begin
|
|||||||
FVfoOverlay.OnSelect := OnModeFilterSelect;
|
FVfoOverlay.OnSelect := OnModeFilterSelect;
|
||||||
FVfoOverlay.OnDSPChange := OnVfoOverlayDSPChange;
|
FVfoOverlay.OnDSPChange := OnVfoOverlayDSPChange;
|
||||||
FVfoOverlay.OnAGCChange := OnVfoOverlayAGCChange;
|
FVfoOverlay.OnAGCChange := OnVfoOverlayAGCChange;
|
||||||
|
FVfoOverlay.OnVolume := OnVfoOverlayVolume;
|
||||||
|
FVfoOverlay.OnMute := OnVfoOverlayMute;
|
||||||
|
FVfoOverlay.OnAudioDevice := OnVfoOverlayAudioDevice;
|
||||||
|
FVfoOverlay.OnSplit := OnVfoOverlaySplit;
|
||||||
FVfoOverlay.OnInvalidate := OnVfoOverlayInvalidate;
|
FVfoOverlay.OnInvalidate := OnVfoOverlayInvalidate;
|
||||||
FVfoOverlay.Visible := False;
|
FVfoOverlay.Visible := False;
|
||||||
FPanelHidden := False;
|
FPanelHidden := False;
|
||||||
@@ -3251,6 +3261,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
FVfoOverlay.UpdateSMeter(FController.FLastSMeter);
|
FVfoOverlay.UpdateSMeter(FController.FLastSMeter);
|
||||||
FVfoOverlay.UpdateVfo(FController.FVfoA);
|
FVfoOverlay.UpdateVfo(FController.FVfoA);
|
||||||
|
PushVfoOverlayExtState;
|
||||||
PositionVfoOverlay;
|
PositionVfoOverlay;
|
||||||
end;
|
end;
|
||||||
// Панорама и водопад теперь рисуются независимо по факту новых кадров.
|
// Панорама и водопад теперь рисуются независимо по факту новых кадров.
|
||||||
@@ -4501,6 +4512,12 @@ end;
|
|||||||
procedure TMainForm.PbSpectrumMouseUp(Sender: TObject; Button: TMouseButton;
|
procedure TMainForm.PbSpectrumMouseUp(Sender: TObject; Button: TMouseButton;
|
||||||
Shift: TShiftState; X, Y: Integer);
|
Shift: TShiftState; X, Y: Integer);
|
||||||
begin
|
begin
|
||||||
|
if Assigned(FVfoOverlay) and FVfoOverlay.HandleMouseUp(X, Y) then
|
||||||
|
begin
|
||||||
|
FSpecDrag := False;
|
||||||
|
PbSpectrum.Cursor := crDefault;
|
||||||
|
Exit; // клик/drag по накладке — не пускаем в спектр
|
||||||
|
end;
|
||||||
if Button = mbLeft then
|
if Button = mbLeft then
|
||||||
begin
|
begin
|
||||||
if (Abs(X - FSpecDragX0) < 4) then
|
if (Abs(X - FSpecDragX0) < 4) then
|
||||||
@@ -4989,11 +5006,13 @@ begin
|
|||||||
begin
|
begin
|
||||||
FLeftPanelW := PanelLeft.Width; // сохраняем реальную ширину (учитывает DPI на Win32)
|
FLeftPanelW := PanelLeft.Width; // сохраняем реальную ширину (учитывает DPI на Win32)
|
||||||
PanelLeft.Width := 0;
|
PanelLeft.Width := 0;
|
||||||
FVfoOverlay.Width := 260;
|
FVfoOverlay.Width := OVL_W;
|
||||||
FVfoOverlay.Height := 136; // OVL_H_NORM — расширяется сам при открытии AGC-пикера
|
FVfoOverlay.Height := FVfoOverlay.BaseHeight; // растёт сам при открытии fly-out
|
||||||
FVfoOverlay.SetState(FController.FMode, FController.FFilterBW, FController.FVfoA, FController.FLastSMeter);
|
FVfoOverlay.SetState(FController.FMode, FController.FFilterBW, FController.FVfoA, FController.FLastSMeter);
|
||||||
FVfoOverlay.SetDSPState(FController.FNRMode, FController.FNBMode, FController.FSNB, FController.FANF, FController.FAGCMode);
|
FVfoOverlay.SetDSPState(FController.FNRMode, FController.FNBMode, FController.FSNB, FController.FANF, FController.FAGCMode);
|
||||||
FVfoOverlay.Visible := True;
|
FVfoOverlay.Visible := True;
|
||||||
|
PushVfoOverlayExtState;
|
||||||
|
PushVfoOverlayAudioDevices;
|
||||||
PositionVfoOverlay;
|
PositionVfoOverlay;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -5098,6 +5117,55 @@ begin
|
|||||||
FController.SetAGCMode(AGCMode);
|
FController.SetAGCMode(AGCMode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.OnVfoOverlayVolume(Vol: Integer);
|
||||||
|
begin
|
||||||
|
FController.SetVolume(Vol);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.OnVfoOverlayMute(Sender: TObject);
|
||||||
|
begin
|
||||||
|
FController.ToggleMute;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.OnVfoOverlaySplit(Sender: TObject);
|
||||||
|
begin
|
||||||
|
FController.SetSplit(not FController.FSplitTxB);
|
||||||
|
PushVfoOverlayExtState;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.OnVfoOverlayAudioDevice(DevIndex: Integer; const DevName: string);
|
||||||
|
begin
|
||||||
|
ApplyAudioDevice(DevIndex, DevName);
|
||||||
|
PushVfoOverlayAudioDevices; // обновить подсветку текущего устройства
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.PushVfoOverlayExtState;
|
||||||
|
begin
|
||||||
|
if not (Assigned(FVfoOverlay) and FVfoOverlay.Visible) then Exit;
|
||||||
|
FVfoOverlay.SetExtState(FController.FVolume, FController.FMuted,
|
||||||
|
FController.FSplitTxB, FController.FTransmitting);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.PushVfoOverlayAudioDevices;
|
||||||
|
var
|
||||||
|
Names: TStringList;
|
||||||
|
Indices: array[0..63] of Integer;
|
||||||
|
Cnt, I: Integer;
|
||||||
|
Idx: array of Integer;
|
||||||
|
begin
|
||||||
|
if not (Assigned(FVfoOverlay) and Assigned(FController.FAudioOut)) then Exit;
|
||||||
|
Names := TStringList.Create;
|
||||||
|
try
|
||||||
|
Cnt := 0;
|
||||||
|
FController.FAudioOut.EnumOutputDevices(Names, Indices, Cnt);
|
||||||
|
SetLength(Idx, Cnt);
|
||||||
|
for I := 0 to Cnt - 1 do Idx[I] := Indices[I];
|
||||||
|
FVfoOverlay.SetAudioDevices(Names, Idx, FController.FAudioOutDevName);
|
||||||
|
finally
|
||||||
|
Names.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TMainForm.OnVfoOverlayInvalidate(Sender: TObject);
|
procedure TMainForm.OnVfoOverlayInvalidate(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
FSpectrumDirty := True;
|
FSpectrumDirty := True;
|
||||||
|
|||||||
+664
-404
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user