mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 19:45:09 +00:00
fix(ui): на месте скрытой вкладки OC Control оставалась дыра в списке настроек
У Pluto/AD936x нет Open Collector выхода, и SetOCBackend гасил пункт «OC
Control» одним Visible. Но координаты левой колонки стояли прямо в вызовах
(MakeNavButton('OC Control', 404), следом 'QO-100', 436), поэтому соседи
оставались на своих местах, и между «Transverter» и «QO-100» зиял пустой
промежуток в 32 пикселя.
Убрана сама возможность такого расхождения: раскладку считает RelayoutNav
одним проходом по списку пунктов, пропуская скрытые, а call-site больше не
называет Top. Шаги вынесены в NAV_* рядом с прочими константами формы.
Заодно закрыт тот же дефект классом выше: заголовок секции, в которой не
осталось ни одной видимой кнопки, прячется вместе с ней. Сегодня это не
проявляется (OC Control — единственный прячущийся пункт, а в секции Radio есть
и другие), но следующий такой пункт уже не оставит висеть пустую шапку.
При всех видимых пунктах новые координаты совпадают со старыми до пикселя —
на openHPSDR раскладка не изменилась.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M37eCTZZ9aqppKWkZRxXkP
This commit is contained in:
+95
-34
@@ -119,6 +119,10 @@ type
|
||||
private
|
||||
// ---- Layout ----
|
||||
FNavPanel: TPanel;
|
||||
// Пункты левой колонки в порядке сверху вниз — заголовки секций (TLabel)
|
||||
// и кнопки (TFlatButton) вперемешку. Координаты им раздаёт RelayoutNav,
|
||||
// руками Top не ставим: пункт умеет прятаться (OC Control на Pluto).
|
||||
FNavItems: array of TControl;
|
||||
FContentPanel: TPanel;
|
||||
FFooterPanel: TPanel;
|
||||
FScrollHost: TPanel;
|
||||
@@ -608,8 +612,10 @@ type
|
||||
function MakeScrollPage: TScrollBox;
|
||||
procedure AddPageBottomSpace(APage: TScrollBox);
|
||||
procedure UpdatePageBottomSpace(APage: TScrollBox);
|
||||
procedure MakeNavSection(const Cap: string; ATop: Integer);
|
||||
function MakeNavButton(const Cap: string; ATop: Integer): TFlatButton;
|
||||
procedure AddNavItem(AItem: TControl);
|
||||
procedure MakeNavSection(const Cap: string);
|
||||
function MakeNavButton(const Cap: string): TFlatButton;
|
||||
procedure RelayoutNav;
|
||||
|
||||
procedure OnFFTSizeChange(Sender: TObject);
|
||||
procedure OnWindowChange(Sender: TObject);
|
||||
@@ -793,6 +799,14 @@ const
|
||||
SETTINGS_FOOTER_H = 52;
|
||||
SETTINGS_BOTTOM_SPACE = 24;
|
||||
|
||||
// Левая колонка навигации: раскладку считает RelayoutNav, а не call-site —
|
||||
// пункт умеет прятаться, и захардкоженные Top оставляли на его месте дыру.
|
||||
NAV_Y0 = 68; // верх первого заголовка секции
|
||||
NAV_BTN_H = 30; // высота кнопки пункта
|
||||
NAV_STEP = 32; // шаг между кнопками (высота + зазор)
|
||||
NAV_SECT_H = 18; // высота заголовка секции
|
||||
NAV_SECT_GAP = 8; // отступ перед заголовком следующей секции
|
||||
|
||||
// Первый пункт комбо аудио слайса = «как у приложения» (пустое имя в конфиге).
|
||||
SLICE_DEV_DEFAULT = 'Default (app output)';
|
||||
SLICE_DEV_NONE = 'None (app input)';
|
||||
@@ -1063,27 +1077,34 @@ begin
|
||||
DpiScale(SETTINGS_BOTTOM_SPACE));
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.MakeNavSection(const Cap: string; ATop: Integer);
|
||||
procedure TSettingsForm.AddNavItem(AItem: TControl);
|
||||
begin
|
||||
with TLabel.Create(Self) do
|
||||
begin
|
||||
Parent := FNavPanel;
|
||||
Caption := UpperCase(Cap);
|
||||
AutoSize := False;
|
||||
SetBounds(DpiScale(14), DpiScale(ATop), DpiScale(160), DpiScale(18));
|
||||
Layout := tlCenter;
|
||||
Font.Size := 8;
|
||||
Font.Style := [fsBold];
|
||||
Font.Color := CLR_TEXTDIM;
|
||||
end;
|
||||
SetLength(FNavItems, Length(FNavItems) + 1);
|
||||
FNavItems[High(FNavItems)] := AItem;
|
||||
end;
|
||||
|
||||
function TSettingsForm.MakeNavButton(const Cap: string; ATop: Integer): TFlatButton;
|
||||
procedure TSettingsForm.MakeNavSection(const Cap: string);
|
||||
var
|
||||
L: TLabel;
|
||||
begin
|
||||
L := TLabel.Create(Self);
|
||||
L.Parent := FNavPanel;
|
||||
L.Caption := UpperCase(Cap);
|
||||
L.AutoSize := False;
|
||||
L.SetBounds(DpiScale(14), 0, DpiScale(160), DpiScale(NAV_SECT_H));
|
||||
L.Layout := tlCenter;
|
||||
L.Font.Size := 8;
|
||||
L.Font.Style := [fsBold];
|
||||
L.Font.Color := CLR_TEXTDIM;
|
||||
AddNavItem(L);
|
||||
end;
|
||||
|
||||
function TSettingsForm.MakeNavButton(const Cap: string): TFlatButton;
|
||||
begin
|
||||
Result := TFlatButton.Create(Self);
|
||||
Result.Parent := FNavPanel;
|
||||
Result.Caption := Cap;
|
||||
Result.SetBounds(DpiScale(10), DpiScale(ATop), DpiScale(166), DpiScale(30));
|
||||
Result.SetBounds(DpiScale(10), 0, DpiScale(166), DpiScale(NAV_BTN_H));
|
||||
Result.Anchors := [akLeft, akTop, akRight];
|
||||
Result.OnClick := NavClick;
|
||||
Result.ClrNorm := CLR_PANEL;
|
||||
@@ -1094,6 +1115,39 @@ begin
|
||||
Result.ClrTextAct := CLR_ACCENT;
|
||||
Result.Font.Size := 9;
|
||||
Result.Font.Style := [];
|
||||
AddNavItem(Result);
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.RelayoutNav;
|
||||
// Раскладывает левую колонку сверху вниз, пропуская скрытые пункты: иначе на
|
||||
// месте спрятанной кнопки (OC Control у Pluto) остаётся дыра в списке.
|
||||
// Заголовок секции живёт ровно столько, сколько в ней есть видимая кнопка.
|
||||
var
|
||||
I, J, Y: Integer;
|
||||
HasVisible: Boolean;
|
||||
begin
|
||||
Y := NAV_Y0;
|
||||
for I := 0 to High(FNavItems) do
|
||||
if FNavItems[I] is TLabel then
|
||||
begin
|
||||
// Пустая секция заголовка не заслуживает.
|
||||
HasVisible := False;
|
||||
for J := I + 1 to High(FNavItems) do
|
||||
begin
|
||||
if FNavItems[J] is TLabel then Break;
|
||||
if FNavItems[J].Visible then begin HasVisible := True; Break; end;
|
||||
end;
|
||||
FNavItems[I].Visible := HasVisible;
|
||||
if not HasVisible then Continue;
|
||||
if Y > NAV_Y0 then Inc(Y, NAV_SECT_GAP);
|
||||
FNavItems[I].Top := DpiScale(Y);
|
||||
Inc(Y, NAV_SECT_H + 2);
|
||||
end
|
||||
else if FNavItems[I].Visible then
|
||||
begin
|
||||
FNavItems[I].Top := DpiScale(Y);
|
||||
Inc(Y, NAV_STEP);
|
||||
end;
|
||||
end;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -1132,26 +1186,28 @@ begin
|
||||
Font.Color := CLR_TEXTDIM;
|
||||
end;
|
||||
|
||||
MakeNavSection('General', 68);
|
||||
FNavAudio := MakeNavButton('Audio', 88);
|
||||
FNavDisplay := MakeNavButton('Display', 120);
|
||||
FNavSpectrum := MakeNavButton('Spectrum', 152);
|
||||
FNavWaterfall := MakeNavButton('Waterfall', 184);
|
||||
MakeNavSection('General');
|
||||
FNavAudio := MakeNavButton('Audio');
|
||||
FNavDisplay := MakeNavButton('Display');
|
||||
FNavSpectrum := MakeNavButton('Spectrum');
|
||||
FNavWaterfall := MakeNavButton('Waterfall');
|
||||
|
||||
MakeNavSection('Radio', 224);
|
||||
FNavTransmit := MakeNavButton('Transmit', 244);
|
||||
FNavPA := MakeNavButton('Power Amplifier', 276);
|
||||
FNavCalib := MakeNavButton('Calibration', 308);
|
||||
FNavAlex := MakeNavButton('Antenna / Alex', 340);
|
||||
FNavXvtr := MakeNavButton('Transverter', 372);
|
||||
FNavOC := MakeNavButton('OC Control', 404);
|
||||
FNavQO := MakeNavButton('QO-100', 436);
|
||||
MakeNavSection('Radio');
|
||||
FNavTransmit := MakeNavButton('Transmit');
|
||||
FNavPA := MakeNavButton('Power Amplifier');
|
||||
FNavCalib := MakeNavButton('Calibration');
|
||||
FNavAlex := MakeNavButton('Antenna / Alex');
|
||||
FNavXvtr := MakeNavButton('Transverter');
|
||||
FNavOC := MakeNavButton('OC Control');
|
||||
FNavQO := MakeNavButton('QO-100');
|
||||
|
||||
MakeNavSection('Integration', 476);
|
||||
FNavCAT := MakeNavButton('CAT', 496);
|
||||
FNavSlices := MakeNavButton('Slices', 528);
|
||||
FNavAdvanced := MakeNavButton('Advanced', 560);
|
||||
FNavDXCluster := MakeNavButton('DX Cluster', 592);
|
||||
MakeNavSection('Integration');
|
||||
FNavCAT := MakeNavButton('CAT');
|
||||
FNavSlices := MakeNavButton('Slices');
|
||||
FNavAdvanced := MakeNavButton('Advanced');
|
||||
FNavDXCluster := MakeNavButton('DX Cluster');
|
||||
|
||||
RelayoutNav;
|
||||
|
||||
FContentPanel := TPanel.Create(Self);
|
||||
FContentPanel.Parent := Self;
|
||||
@@ -6058,8 +6114,13 @@ procedure TSettingsForm.SetOCBackend(IsPluto: Boolean);
|
||||
// У Pluto/AD936x нет Open Collector выхода — вкладка целиком скрывается,
|
||||
// а не показывает пустое содержимое (в отличие от Antenna, где Pluto имеет
|
||||
// свою таблицу разъёмов).
|
||||
var
|
||||
Changed: Boolean;
|
||||
begin
|
||||
Changed := FNavOC.Visible <> (not IsPluto);
|
||||
FNavOC.Visible := not IsPluto;
|
||||
// Пункты ниже обязаны подтянуться — иначе на месте OC Control остаётся дыра.
|
||||
if Changed then RelayoutNav;
|
||||
if IsPluto and (FPageOC.Visible) then
|
||||
SelectPage(FPageAudio, FNavAudio);
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user