feat(slices): per-pan tuning wheel and per-slice RX mute on TX

Mouse wheel over an extra panadapter now retunes that pan's primary
slice (first created on that receiver) instead of the main VFO; a slice
flag under the cursor still wins, pan 0 keeps driving the VFO.

Slice flags get a clickable RXM badge: RX audio of the slice is muted
while transmitting (default), so the operator no longer hears himself on
every slice in full duplex. State persists with the workspace.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 22:35:19 +03:00
co-authored by Claude Opus 4.8
parent fa5a95ca5d
commit 28ae832b71
5 changed files with 112 additions and 8 deletions
+18
View File
@@ -275,6 +275,7 @@ type
function SliceAtPixel(X: Integer): Integer;
// SliceId флага под курсором мыши (прямоугольник оверлея; 0 = нет).
function SliceUnderCursor: Integer;
function CursorOverDisplay: Boolean; // курсор над спектром/водопадом пана
// Единый packing всех флагов (A+B+) в один ряд, без наездов.
procedure LayoutFlags;
// Флаг A виден: панель хозяина скрыта (MainFlagPinned) ИЛИ есть слайсы B+.
@@ -1142,6 +1143,22 @@ begin
end;
end;
// Курсор над спектром/водопадом этого пана? (колесо крутит «его» частоту)
function TPanafallPanel.CursorOverDisplay: Boolean;
function Over(C: TControl): Boolean;
var P: TPoint;
begin
Result := False;
if (C = nil) or (not C.Visible) then Exit;
P := C.ScreenToClient(Mouse.CursorPos);
Result := (P.X >= 0) and (P.Y >= 0) and (P.X < C.Width) and (P.Y < C.Height);
end;
begin
Result := Over(FPbSpectrum) or Over(FPbWaterfall);
end;
// Флаг слайса под курсором мыши (в клиентских координатах спектра)?
function TPanafallPanel.SliceUnderCursor: Integer;
var P: TPoint; i: Integer; O: TVfoOverlay;
@@ -1321,6 +1338,7 @@ begin
O.SetExtState(Round(S.Volume * 100), S.Muted, False,
FController.FTransmitting and (FController.FTxSliceId = SliceId),
FController.FTxSliceId = SliceId);
O.SetRxMuteTxState(S.RxMuteOnTx); // бейдж RXM
// Список аудио-устройств (общий PA-список) + текущее устройство слайса.
if Assigned(FController.FAudioOut) then
begin