feat(overlay): clickable TX badge with slice-select groundwork

TX-индикатор теперь кликабельный (хит HIT_TX → колбэк OnTxSelect) — задел
под выбор TX-слайса в мультислайсах. Три состояния цвета:
- передача идёт → красный;
- слайс выбран для TX → янтарный (CLR_TX_SEL);
- не выбран → нейтральный.

Новое состояние FTxSel прокидывается через SetExtState (пока True — один
слайс всегда TX-слайс). MainForm.OnVfoOverlayTxSelect — заглушка с TODO под
мультислайсы.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 17:10:34 +03:00
co-authored by Claude Opus 4.8
parent 6ad5f29657
commit 08c71c47ad
2 changed files with 31 additions and 10 deletions
+20 -9
View File
@@ -49,7 +49,8 @@ type
FVolume: Integer; // 0..100
FMuted: Boolean;
FSplit: Boolean;
FTx: Boolean;
FTx: Boolean; // передача идёт (красный)
FTxSel: Boolean; // этот слайс выбран для передачи (янтарный)
FSlice: Char; // буква слайса ('A')
FDevNames: TStringList; // имена устройств вывода
@@ -67,6 +68,7 @@ type
FOnMute: TNotifyEvent;
FOnAudioDevice: TAudioDeviceEvent;
FOnSplit: TNotifyEvent;
FOnTxSelect: TNotifyEvent;
FOnInvalidate: TNotifyEvent;
FHitRects: array[0..63] of TRect;
@@ -118,7 +120,7 @@ type
procedure SetState(AMode, ABW: Integer; AVfoHz, ASMeterDB: Double);
procedure SetDSPState(ANRMode, ANBMode: Integer; ASNBOn, AANFOn: Boolean;
AAGCMode: Integer);
procedure SetExtState(AVolume: Integer; AMuted, ASplit, ATx: Boolean);
procedure SetExtState(AVolume: Integer; AMuted, ASplit, ATx, ATxSel: Boolean);
procedure SetAudioDevices(Names: TStrings; const Indices: array of Integer;
const CurName: string);
procedure UpdateSMeter(DB: Double);
@@ -132,6 +134,7 @@ type
property OnMute: TNotifyEvent read FOnMute write FOnMute;
property OnAudioDevice: TAudioDeviceEvent read FOnAudioDevice write FOnAudioDevice;
property OnSplit: TNotifyEvent read FOnSplit write FOnSplit;
property OnTxSelect: TNotifyEvent read FOnTxSelect write FOnTxSelect;
property OnInvalidate: TNotifyEvent read FOnInvalidate write FOnInvalidate;
end;
@@ -155,6 +158,7 @@ const
HIT_MUTE = -23;
HIT_VOL = -24;
HIT_SPLIT = -25;
HIT_TX = -26;
HIT_AGC_PICK_BASE = 100000;
HIT_DEV_BASE = 200000;
@@ -184,7 +188,8 @@ const
CLR_FREQ = TColor($0050FF80);
CLR_SVAL = TColor($0030C8FF);
CLR_BAR_BG = TColor($00101010);
CLR_TX_ON = TColor($000030E0); // красный TX (BGR)
CLR_TX_ON = TColor($000030E0); // красный TX идёт (BGR)
CLR_TX_SEL = TColor($0010A8F0); // янтарный: слайс выбран для передачи
CLR_SPLIT_ON = TColor($0020C0FF); // оранжевый SPLIT
OVL_MODE_COUNT = 8;
@@ -326,7 +331,8 @@ begin
FModeFilter[3] := 500; FModeFilter[4] := 500; FModeFilter[5] := 11000;
FModeFilter[6] := 8000; FModeFilter[7] := 8000;
FNRMode := 0; FNBMode := 0; FSNBOn := False; FANFOn := False; FAGCMode := 0;
FVolume := 70; FMuted := False; FSplit := False; FTx := False; FSlice := 'A';
FVolume := 70; FMuted := False; FSplit := False; FTx := False;
FTxSel := True; FSlice := 'A';
FPanel := fpNone;
FVolDrag := False;
FDevNames := TStringList.Create;
@@ -710,10 +716,13 @@ begin
C.Font.Name := 'Courier New'; C.Font.Size := 8; C.Font.Style := [];
C.Font.Color := CLR_DIM; C.Brush.Style := bsClear;
C.TextOut(X + 22, CurY + 1, BWStr);
// TX badge (правый край)
// TX badge (правый край) — кликабельно: выбор TX-слайса.
// передача идёт → красный; слайс выбран для TX → янтарный; иначе → нейтральный.
R := Rect(W - PAD - 26, CurY, W - PAD, CurY + HDR_BADGE_H);
if FTx then DrawBadge(C, R, 'TX', CLR_TX_ON, clWhite)
else DrawBadge(C, R, 'TX', CLR_BTN_NORM, CLR_DIM);
if FTx then DrawBadge(C, R, 'TX', CLR_TX_ON, clWhite)
else if FTxSel then DrawBadge(C, R, 'TX', CLR_TX_SEL, CLR_CARD_BG)
else DrawBadge(C, R, 'TX', CLR_BTN_NORM, CLR_DIM);
RegisterHit(R, HIT_TX);
// SPLIT (левее TX) — кликабельно
R := Rect(W - PAD - 26 - 44, CurY, W - PAD - 26 - 4, CurY + HDR_BADGE_H);
if FSplit then DrawBadge(C, R, 'SPLIT', CLR_SPLIT_ON, CLR_CARD_BG)
@@ -847,6 +856,7 @@ begin
HIT_MUTE: begin FMuted := not FMuted; RequestInvalidate;
if Assigned(FOnMute) then FOnMute(Self); Exit; end;
HIT_SPLIT: begin if Assigned(FOnSplit) then FOnSplit(Self); Exit; end;
HIT_TX: begin if Assigned(FOnTxSelect) then FOnTxSelect(Self); Exit; end;
end;
// Устройство аудио
@@ -1055,14 +1065,15 @@ begin
RequestInvalidate;
end;
procedure TVfoOverlay.SetExtState(AVolume: Integer; AMuted, ASplit, ATx: Boolean);
procedure TVfoOverlay.SetExtState(AVolume: Integer; AMuted, ASplit, ATx, ATxSel: Boolean);
begin
if (AVolume = FVolume) and (AMuted = FMuted) and (ASplit = FSplit)
and (ATx = FTx) then Exit;
and (ATx = FTx) and (ATxSel = FTxSel) then Exit;
if not FVolDrag then FVolume := AVolume; // во время drag ведём сами
FMuted := AMuted;
FSplit := ASplit;
FTx := ATx;
FTxSel := ATxSel;
RequestInvalidate;
end;