style(pluto): причёсана таблица разъёмов на вкладке Antenna

- шапка колонок: «RX»/«TX» по центру своей пары, номера разъёмов отдельной
  строкой ниже (не налезают на рамку группы);
- строки трансвертеров пакуются подряд (раньше выключенные слоты занимали
  место → дыра между ADS-B и QO-100), высота группы — по последней видимой;
- RX- и TX-пары разнесены, шире колонка названий, крупнее шаг строки;
- дим-заголовок «Transverters» над секцией слотов.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 21:33:05 +03:00
co-authored by Claude Opus 4.8
parent 9dd38e1dd3
commit b42da10ecf
+72 -35
View File
@@ -244,6 +244,7 @@ type
FAntXvtrTx: array[0..CFG_XVTR_COUNT-1, 0..1] of TFlatRadioButton;
FAntXvtrRow: array[0..CFG_XVTR_COUNT-1] of TPanel; // строка слота (скрыта, если выкл.)
FAntXvtrLbl: array[0..CFG_XVTR_COUNT-1] of TLabel;
FAntXvtrHdr: TLabel; // «Transverters» — виден при хотя бы одном включённом
FAnt936x: TAD936xAnt;
// Current Alex config state
FAlexConfig: TAlexSettings;
@@ -3001,12 +3002,14 @@ const
TX3_X = PAD + 360;
DNTX_X = PAD + 398;
GRP_W = DNTX_X + 80;
// Таблица разъёмов AD936x (Pluto/LibreSDR) — та же сетка, свои колонки.
ANT_RX1_X = PAD + 90;
ANT_RX2_X = PAD + 116;
ANT_TX1_X = PAD + 160;
ANT_TX2_X = PAD + 186;
ANT_GRP_W = ANT_TX2_X + 60;
// Таблица разъёмов AD936x (Pluto/LibreSDR): диапазон | RX 1/2 | TX 1/2.
ANT_ROW_H = 26;
ANT_HDR_H = 34; // строка «RX / TX» + подстрока «1 2» под ней
ANT_RX1_X = PAD + 96;
ANT_RX2_X = ANT_RX1_X + 34;
ANT_TX1_X = ANT_RX2_X + 52;
ANT_TX2_X = ANT_TX1_X + 34;
ANT_GRP_W = ANT_TX2_X + 42;
GRP_H = GRP_TITLE_H + HDR1_H + HDR2_H + BANDS * ROW_H + PAD;
DATA_Y0 = GRP_TITLE_H + HDR1_H + HDR2_H + 4;
TXGRP_H = GRP_TITLE_H + 4 * 28 + PAD;
@@ -3202,52 +3205,56 @@ begin
// показывается вместо них (SetAntennaBackend).
FPlutoAntGrp := MakeGroupPanel(FPageAlex, 'Antenna Ports',
MARGIN, 86, ANT_GRP_W,
GRP_TITLE_H + HDR2_H + (CFG_BAND_COUNT + CFG_XVTR_COUNT) * ROW_H + PAD);
GRP_TITLE_H + ANT_HDR_H + (CFG_BAND_COUNT + 1 + CFG_XVTR_COUNT) * ANT_ROW_H + PAD);
FPlutoAntGrp.Visible := False;
MkAntHdr(FPlutoAntGrp, 'RX', ANT_RX1_X - 4, GRP_TITLE_H - 2);
MkAntHdr(FPlutoAntGrp, 'TX', ANT_TX1_X - 4, GRP_TITLE_H - 2);
MkAntHdr(FPlutoAntGrp, '1', ANT_RX1_X + 4, GRP_TITLE_H + 14);
MkAntHdr(FPlutoAntGrp, '2', ANT_RX2_X + 4, GRP_TITLE_H + 14);
MkAntHdr(FPlutoAntGrp, '1', ANT_TX1_X + 4, GRP_TITLE_H + 14);
MkAntHdr(FPlutoAntGrp, '2', ANT_TX2_X + 4, GRP_TITLE_H + 14);
// Шапка колонок: «RX»/«TX» над своей парой, под ними номера разъёмов.
Y := GRP_TITLE_H + 4;
MkAntHdr(FPlutoAntGrp, 'RX', (ANT_RX1_X + ANT_RX2_X) div 2 - 2, Y);
MkAntHdr(FPlutoAntGrp, 'TX', (ANT_TX1_X + ANT_TX2_X) div 2 - 2, Y);
MkAntHdr(FPlutoAntGrp, '1', ANT_RX1_X + 5, Y + 16);
MkAntHdr(FPlutoAntGrp, '2', ANT_RX2_X + 5, Y + 16);
MkAntHdr(FPlutoAntGrp, '1', ANT_TX1_X + 5, Y + 16);
MkAntHdr(FPlutoAntGrp, '2', ANT_TX2_X + 5, Y + 16);
Y := GRP_TITLE_H + HDR2_H + 4;
Y := GRP_TITLE_H + ANT_HDR_H;
for b := 0 to CFG_BAND_COUNT - 1 do
begin
// Пустой слот VU-плана (12-й у HF) не рисуем — строка остаётся пустой.
if BandName(b, True) <> '' then
begin
MkAntLbl(FPlutoAntGrp, BandName(b, True), BAND_X, Y + 2);
RxGrp := MkRbGroup(FPlutoAntGrp, ANT_RX1_X, Y, 60);
FAntRx[b, 0] := MkAntRb(RxGrp, 0);
FAntRx[b, 1] := MkAntRb(RxGrp, ANT_RX2_X - ANT_RX1_X);
TxGrp := MkRbGroup(FPlutoAntGrp, ANT_TX1_X, Y, 60);
FAntTx[b, 0] := MkAntRb(TxGrp, 0);
FAntTx[b, 1] := MkAntRb(TxGrp, ANT_TX2_X - ANT_TX1_X);
end;
Inc(Y, ROW_H);
if BandName(b, True) = '' then Continue; // пустой слот плана — не строка
MkAntLbl(FPlutoAntGrp, BandName(b, True), BAND_X, Y + 3);
RxGrp := MkRbGroup(FPlutoAntGrp, ANT_RX1_X, Y, ANT_RX2_X - ANT_RX1_X + 24);
FAntRx[b, 0] := MkAntRb(RxGrp, 0);
FAntRx[b, 1] := MkAntRb(RxGrp, ANT_RX2_X - ANT_RX1_X);
TxGrp := MkRbGroup(FPlutoAntGrp, ANT_TX1_X, Y, ANT_TX2_X - ANT_TX1_X + 24);
FAntTx[b, 0] := MkAntRb(TxGrp, 0);
FAntTx[b, 1] := MkAntRb(TxGrp, ANT_TX2_X - ANT_TX1_X);
Inc(Y, ANT_ROW_H);
end;
// Слоты трансвертеров: строка на слот, показываем только включённые
// (LoadAnt936x подставит имя и видимость).
// Секция трансвертеров: заголовок + строка на слот. Видимость и вертикальную
// упаковку (только включённые слоты, без дыр) делает LoadAnt936x.
FAntXvtrHdr := MkAntLbl(FPlutoAntGrp, 'Transverters', BAND_X, Y + 6);
FAntXvtrHdr.Font.Color := CLR_TEXTDIM;
FAntXvtrHdr.Visible := False;
Inc(Y, ANT_ROW_H);
for b := 0 to CFG_XVTR_COUNT - 1 do
begin
FAntXvtrRow[b] := TPanel.Create(Self);
FAntXvtrRow[b].Parent := FPlutoAntGrp;
FAntXvtrRow[b].SetBounds(0, Y, ANT_GRP_W, ROW_H);
FAntXvtrRow[b].SetBounds(0, Y, ANT_GRP_W, ANT_ROW_H);
FAntXvtrRow[b].BevelOuter := bvNone;
FAntXvtrRow[b].Color := CLR_PANEL;
FAntXvtrRow[b].Caption := '';
FAntXvtrRow[b].Visible := False;
FAntXvtrLbl[b] := MkAntLbl(FAntXvtrRow[b], '', BAND_X, 2);
RxGrp := MkRbGroup(FAntXvtrRow[b], ANT_RX1_X, 0, 60);
FAntXvtrLbl[b] := MkAntLbl(FAntXvtrRow[b], '', BAND_X, 3);
RxGrp := MkRbGroup(FAntXvtrRow[b], ANT_RX1_X, 0, ANT_RX2_X - ANT_RX1_X + 24);
FAntXvtrRx[b, 0] := MkAntRb(RxGrp, 0);
FAntXvtrRx[b, 1] := MkAntRb(RxGrp, ANT_RX2_X - ANT_RX1_X);
TxGrp := MkRbGroup(FAntXvtrRow[b], ANT_TX1_X, 0, 60);
TxGrp := MkRbGroup(FAntXvtrRow[b], ANT_TX1_X, 0, ANT_TX2_X - ANT_TX1_X + 24);
FAntXvtrTx[b, 0] := MkAntRb(TxGrp, 0);
FAntXvtrTx[b, 1] := MkAntRb(TxGrp, ANT_TX2_X - ANT_TX1_X);
Inc(Y, ROW_H);
Inc(Y, ANT_ROW_H);
end;
finally
FLoading := False;
@@ -3281,8 +3288,14 @@ begin
end;
procedure TSettingsForm.LoadAnt936x(const A: TAD936xAnt; const X: TXvtrSettings);
// Таблица разъёмов + строки трансвертеров (видимы только включённые слоты).
var b: Integer;
// Таблица разъёмов + секция трансвертеров. Строки выключенных слотов не просто
// прячутся, а исключаются из раскладки (иначе между диапазонами и QO-100 зияла
// дыра в 8 строк); высота группы считается по фактическому числу строк.
const
ANT_ROW_H = 26;
PAD = 12;
var
b, Y, NVis, Bands: Integer;
begin
FLoading := True;
try
@@ -3295,10 +3308,16 @@ begin
FAntTx[b, 0].Checked := A.TxAnt[b] = 0;
FAntTx[b, 1].Checked := A.TxAnt[b] = 1;
end;
// Первая строка трансвертеров — сразу под заголовком секции.
if FAntXvtrHdr <> nil then Y := FAntXvtrHdr.Top + ANT_ROW_H - 6
else Y := 0;
NVis := 0;
for b := 0 to CFG_XVTR_COUNT - 1 do
begin
if FAntXvtrRow[b] = nil then Continue;
FAntXvtrRow[b].Visible := X.Entries[b].Enabled;
if not X.Entries[b].Enabled then Continue;
if X.Entries[b].ButtonText <> '' then
FAntXvtrLbl[b].Caption := string(X.Entries[b].ButtonText)
else
@@ -3307,6 +3326,24 @@ begin
FAntXvtrRx[b, 1].Checked := A.XvtrRxAnt[b] = 1;
FAntXvtrTx[b, 0].Checked := A.XvtrTxAnt[b] = 0;
FAntXvtrTx[b, 1].Checked := A.XvtrTxAnt[b] = 1;
FAntXvtrRow[b].Top := Y; // упаковка подряд, без дыр от выключенных слотов
Inc(Y, ANT_ROW_H);
Inc(NVis);
end;
if FAntXvtrHdr <> nil then FAntXvtrHdr.Visible := NVis > 0;
// Высота группы — по последней видимой строке (иначе внизу пустое поле).
if FPlutoAntGrp <> nil then
begin
if NVis = 0 then
begin
Bands := 0;
for b := 0 to CFG_BAND_COUNT - 1 do
if FAntRx[b, 0] <> nil then Inc(Bands);
Y := FPlutoAntGrp.Height - PAD; // fallback, если заголовка нет
if (FAntXvtrHdr <> nil) and (Bands > 0) then Y := FAntXvtrHdr.Top - 6;
end;
FPlutoAntGrp.Height := Y + PAD;
end;
finally
FLoading := False;