mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +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
|
private
|
||||||
// ---- Layout ----
|
// ---- Layout ----
|
||||||
FNavPanel: TPanel;
|
FNavPanel: TPanel;
|
||||||
|
// Пункты левой колонки в порядке сверху вниз — заголовки секций (TLabel)
|
||||||
|
// и кнопки (TFlatButton) вперемешку. Координаты им раздаёт RelayoutNav,
|
||||||
|
// руками Top не ставим: пункт умеет прятаться (OC Control на Pluto).
|
||||||
|
FNavItems: array of TControl;
|
||||||
FContentPanel: TPanel;
|
FContentPanel: TPanel;
|
||||||
FFooterPanel: TPanel;
|
FFooterPanel: TPanel;
|
||||||
FScrollHost: TPanel;
|
FScrollHost: TPanel;
|
||||||
@@ -608,8 +612,10 @@ type
|
|||||||
function MakeScrollPage: TScrollBox;
|
function MakeScrollPage: TScrollBox;
|
||||||
procedure AddPageBottomSpace(APage: TScrollBox);
|
procedure AddPageBottomSpace(APage: TScrollBox);
|
||||||
procedure UpdatePageBottomSpace(APage: TScrollBox);
|
procedure UpdatePageBottomSpace(APage: TScrollBox);
|
||||||
procedure MakeNavSection(const Cap: string; ATop: Integer);
|
procedure AddNavItem(AItem: TControl);
|
||||||
function MakeNavButton(const Cap: string; ATop: Integer): TFlatButton;
|
procedure MakeNavSection(const Cap: string);
|
||||||
|
function MakeNavButton(const Cap: string): TFlatButton;
|
||||||
|
procedure RelayoutNav;
|
||||||
|
|
||||||
procedure OnFFTSizeChange(Sender: TObject);
|
procedure OnFFTSizeChange(Sender: TObject);
|
||||||
procedure OnWindowChange(Sender: TObject);
|
procedure OnWindowChange(Sender: TObject);
|
||||||
@@ -793,6 +799,14 @@ const
|
|||||||
SETTINGS_FOOTER_H = 52;
|
SETTINGS_FOOTER_H = 52;
|
||||||
SETTINGS_BOTTOM_SPACE = 24;
|
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_DEFAULT = 'Default (app output)';
|
||||||
SLICE_DEV_NONE = 'None (app input)';
|
SLICE_DEV_NONE = 'None (app input)';
|
||||||
@@ -1063,27 +1077,34 @@ begin
|
|||||||
DpiScale(SETTINGS_BOTTOM_SPACE));
|
DpiScale(SETTINGS_BOTTOM_SPACE));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSettingsForm.MakeNavSection(const Cap: string; ATop: Integer);
|
procedure TSettingsForm.AddNavItem(AItem: TControl);
|
||||||
begin
|
begin
|
||||||
with TLabel.Create(Self) do
|
SetLength(FNavItems, Length(FNavItems) + 1);
|
||||||
begin
|
FNavItems[High(FNavItems)] := AItem;
|
||||||
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;
|
|
||||||
end;
|
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
|
begin
|
||||||
Result := TFlatButton.Create(Self);
|
Result := TFlatButton.Create(Self);
|
||||||
Result.Parent := FNavPanel;
|
Result.Parent := FNavPanel;
|
||||||
Result.Caption := Cap;
|
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.Anchors := [akLeft, akTop, akRight];
|
||||||
Result.OnClick := NavClick;
|
Result.OnClick := NavClick;
|
||||||
Result.ClrNorm := CLR_PANEL;
|
Result.ClrNorm := CLR_PANEL;
|
||||||
@@ -1094,6 +1115,39 @@ begin
|
|||||||
Result.ClrTextAct := CLR_ACCENT;
|
Result.ClrTextAct := CLR_ACCENT;
|
||||||
Result.Font.Size := 9;
|
Result.Font.Size := 9;
|
||||||
Result.Font.Style := [];
|
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;
|
end;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -1132,26 +1186,28 @@ begin
|
|||||||
Font.Color := CLR_TEXTDIM;
|
Font.Color := CLR_TEXTDIM;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
MakeNavSection('General', 68);
|
MakeNavSection('General');
|
||||||
FNavAudio := MakeNavButton('Audio', 88);
|
FNavAudio := MakeNavButton('Audio');
|
||||||
FNavDisplay := MakeNavButton('Display', 120);
|
FNavDisplay := MakeNavButton('Display');
|
||||||
FNavSpectrum := MakeNavButton('Spectrum', 152);
|
FNavSpectrum := MakeNavButton('Spectrum');
|
||||||
FNavWaterfall := MakeNavButton('Waterfall', 184);
|
FNavWaterfall := MakeNavButton('Waterfall');
|
||||||
|
|
||||||
MakeNavSection('Radio', 224);
|
MakeNavSection('Radio');
|
||||||
FNavTransmit := MakeNavButton('Transmit', 244);
|
FNavTransmit := MakeNavButton('Transmit');
|
||||||
FNavPA := MakeNavButton('Power Amplifier', 276);
|
FNavPA := MakeNavButton('Power Amplifier');
|
||||||
FNavCalib := MakeNavButton('Calibration', 308);
|
FNavCalib := MakeNavButton('Calibration');
|
||||||
FNavAlex := MakeNavButton('Antenna / Alex', 340);
|
FNavAlex := MakeNavButton('Antenna / Alex');
|
||||||
FNavXvtr := MakeNavButton('Transverter', 372);
|
FNavXvtr := MakeNavButton('Transverter');
|
||||||
FNavOC := MakeNavButton('OC Control', 404);
|
FNavOC := MakeNavButton('OC Control');
|
||||||
FNavQO := MakeNavButton('QO-100', 436);
|
FNavQO := MakeNavButton('QO-100');
|
||||||
|
|
||||||
MakeNavSection('Integration', 476);
|
MakeNavSection('Integration');
|
||||||
FNavCAT := MakeNavButton('CAT', 496);
|
FNavCAT := MakeNavButton('CAT');
|
||||||
FNavSlices := MakeNavButton('Slices', 528);
|
FNavSlices := MakeNavButton('Slices');
|
||||||
FNavAdvanced := MakeNavButton('Advanced', 560);
|
FNavAdvanced := MakeNavButton('Advanced');
|
||||||
FNavDXCluster := MakeNavButton('DX Cluster', 592);
|
FNavDXCluster := MakeNavButton('DX Cluster');
|
||||||
|
|
||||||
|
RelayoutNav;
|
||||||
|
|
||||||
FContentPanel := TPanel.Create(Self);
|
FContentPanel := TPanel.Create(Self);
|
||||||
FContentPanel.Parent := Self;
|
FContentPanel.Parent := Self;
|
||||||
@@ -6058,8 +6114,13 @@ procedure TSettingsForm.SetOCBackend(IsPluto: Boolean);
|
|||||||
// У Pluto/AD936x нет Open Collector выхода — вкладка целиком скрывается,
|
// У Pluto/AD936x нет Open Collector выхода — вкладка целиком скрывается,
|
||||||
// а не показывает пустое содержимое (в отличие от Antenna, где Pluto имеет
|
// а не показывает пустое содержимое (в отличие от Antenna, где Pluto имеет
|
||||||
// свою таблицу разъёмов).
|
// свою таблицу разъёмов).
|
||||||
|
var
|
||||||
|
Changed: Boolean;
|
||||||
begin
|
begin
|
||||||
|
Changed := FNavOC.Visible <> (not IsPluto);
|
||||||
FNavOC.Visible := not IsPluto;
|
FNavOC.Visible := not IsPluto;
|
||||||
|
// Пункты ниже обязаны подтянуться — иначе на месте OC Control остаётся дыра.
|
||||||
|
if Changed then RelayoutNav;
|
||||||
if IsPluto and (FPageOC.Visible) then
|
if IsPluto and (FPageOC.Visible) then
|
||||||
SelectPage(FPageAudio, FNavAudio);
|
SelectPage(FPageAudio, FNavAudio);
|
||||||
end;
|
end;
|
||||||
|
|||||||
Reference in New Issue
Block a user