mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
add light/dark theme with global persistence
- AppTheme.pas: новый файл, TAppTheme record + DarkTheme()/LightTheme() - FlatSlider: цвета через SetThemeColors вместо хардкода - SpectrumView: все цвета из TAppTheme (SetTheme) - SettingsForm: ApplyTheme(T) с рекурсивным обходом контролов - DeviceForm: SetTheme(T) — перекраска всех элементов включая TEdit - Settings: SaveTheme/LoadTheme в корневой секции preferences (не привязано к устройству) - MainForm: тема загружается при старте, сохраняется при изменении Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+101
-14
@@ -27,7 +27,7 @@ uses
|
||||
Classes, SysUtils, Math,
|
||||
Forms, Controls, Graphics, Dialogs,
|
||||
StdCtrls, ExtCtrls, Spin,
|
||||
FlatButton, AudioOutput, AudioInput;
|
||||
FlatButton, AudioOutput, AudioInput, AppTheme;
|
||||
|
||||
type
|
||||
// PA: MaxPower в Вт, BandCal[0..10] — калибровка 38.8..100.0 на диапазон
|
||||
@@ -43,6 +43,7 @@ type
|
||||
TOnAudioInDevChange = procedure(DevIndex: Integer; const DevName: string) of object;
|
||||
TOnVisibilityChange = procedure(ShowSpectrum, ShowWaterfall: Boolean) of object;
|
||||
TOnFPSChange = procedure(FPS: Integer) of object;
|
||||
TOnThemeChange = procedure(LightTheme: Boolean) of object;
|
||||
TOnCATChange = procedure(
|
||||
const SerEnabled: array of Boolean;
|
||||
const SerPort: array of string;
|
||||
@@ -101,6 +102,7 @@ type
|
||||
FChkShowSpectrum: TCheckBox;
|
||||
FChkShowWaterfall: TCheckBox;
|
||||
FCmbFPS: TComboBox;
|
||||
FChkLightTheme: TCheckBox;
|
||||
|
||||
// ---- PA Settings tab controls ----
|
||||
FEdMaxPower: TSpinEdit;
|
||||
@@ -129,6 +131,7 @@ type
|
||||
FOnAudioInDevChange: TOnAudioInDevChange;
|
||||
FOnVisibilityChange: TOnVisibilityChange;
|
||||
FOnFPSChange: TOnFPSChange;
|
||||
FOnThemeChange: TOnThemeChange;
|
||||
|
||||
FLoading: Boolean;
|
||||
|
||||
@@ -138,7 +141,7 @@ type
|
||||
procedure BuildRX1Tab;
|
||||
procedure BuildPATab;
|
||||
procedure BuildCATTab;
|
||||
procedure ApplyTheme;
|
||||
procedure ApplyTheme(const T: TAppTheme);
|
||||
procedure NavClick(Sender: TObject);
|
||||
procedure SelectPage(APage: TWinControl; ANav: TFlatButton);
|
||||
|
||||
@@ -167,6 +170,7 @@ type
|
||||
procedure OnTXDevChange(Sender: TObject);
|
||||
procedure OnVisibilityChkChange(Sender: TObject);
|
||||
procedure OnFPSCmbChange(Sender: TObject);
|
||||
procedure OnLightThemeChkChange(Sender: TObject);
|
||||
procedure OnMaxPowerChange(Sender: TObject);
|
||||
procedure OnBandCalChange(Sender: TObject);
|
||||
procedure OnCATSerialChange(Sender: TObject);
|
||||
@@ -203,6 +207,7 @@ type
|
||||
procedure RefreshAudioDevices(AudioOut: TAudioOutput; AudioIn: TAudioInput);
|
||||
procedure LoadVisibility(ShowSpectrum, ShowWaterfall: Boolean);
|
||||
procedure LoadFPS(FPS: Integer);
|
||||
procedure LoadLightTheme(ALight: Boolean);
|
||||
procedure LoadPASettings(MaxPower: Double; const BandCal: array of Double);
|
||||
procedure LoadCATSettings(
|
||||
const SerEnabled: array of Boolean;
|
||||
@@ -219,6 +224,7 @@ type
|
||||
property OnAudioInDevChange: TOnAudioInDevChange read FOnAudioInDevChange write FOnAudioInDevChange;
|
||||
property OnVisibilityChange: TOnVisibilityChange read FOnVisibilityChange write FOnVisibilityChange;
|
||||
property OnFPSChange: TOnFPSChange read FOnFPSChange write FOnFPSChange;
|
||||
property OnThemeChange: TOnThemeChange read FOnThemeChange write FOnThemeChange;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@@ -287,7 +293,7 @@ begin
|
||||
FLoading := False;
|
||||
FRXDevCount := 0;
|
||||
BuildUI;
|
||||
ApplyTheme;
|
||||
ApplyTheme(DarkTheme);
|
||||
end;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -611,6 +617,18 @@ begin
|
||||
for i := 0 to High(FPS_NAMES) do
|
||||
FCmbFPS.Items.Add(FPS_NAMES[i]);
|
||||
FCmbFPS.ItemIndex := 8;
|
||||
|
||||
Grp := MakeGroupPanel(FPageDisplay, 'Appearance', MARGIN, 292, 650, 68);
|
||||
|
||||
FChkLightTheme := TCheckBox.Create(Self);
|
||||
FChkLightTheme.Parent := Grp;
|
||||
FChkLightTheme.Caption := 'Light theme';
|
||||
FChkLightTheme.SetBounds(PAD, R1, CHKW, 22);
|
||||
FChkLightTheme.Checked := False;
|
||||
FChkLightTheme.Font.Color := CLR_TEXT;
|
||||
FChkLightTheme.Font.Name := UI_FONT;
|
||||
FChkLightTheme.Font.Size := 9;
|
||||
FChkLightTheme.OnChange := OnLightThemeChkChange;
|
||||
end;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -888,18 +906,66 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.ApplyTheme;
|
||||
procedure TSettingsForm.ApplyTheme(const T: TAppTheme);
|
||||
|
||||
procedure StyleBtn(B: TFlatButton);
|
||||
begin
|
||||
B.ClrNorm := T.Panel;
|
||||
B.ClrBorder := T.Panel;
|
||||
B.ClrHot := T.BG;
|
||||
B.ClrActive := T.Panel;
|
||||
B.ClrText := T.Text;
|
||||
B.ClrTextAct := T.FreqActive;
|
||||
B.Invalidate;
|
||||
end;
|
||||
|
||||
procedure WalkControls(C: TWinControl);
|
||||
var i: Integer; Ctrl: TControl;
|
||||
begin
|
||||
for i := 0 to C.ControlCount - 1 do
|
||||
begin
|
||||
Ctrl := C.Controls[i];
|
||||
if Ctrl is TFlatButton then
|
||||
StyleBtn(TFlatButton(Ctrl))
|
||||
else if Ctrl is TScrollBox then
|
||||
begin
|
||||
TScrollBox(Ctrl).Color := T.BG;
|
||||
WalkControls(TScrollBox(Ctrl));
|
||||
end
|
||||
else if Ctrl is TPanel then
|
||||
begin
|
||||
if TPanel(Ctrl).Height = 1 then
|
||||
TPanel(Ctrl).Color := T.Border
|
||||
else
|
||||
TPanel(Ctrl).Color := T.Panel;
|
||||
WalkControls(TPanel(Ctrl));
|
||||
end
|
||||
else if Ctrl is TLabel then
|
||||
begin
|
||||
if Ctrl.Font.Size >= 12 then
|
||||
TLabel(Ctrl).Font.Color := T.Text
|
||||
else if fsBold in Ctrl.Font.Style then
|
||||
TLabel(Ctrl).Font.Color := T.FreqActive
|
||||
else
|
||||
TLabel(Ctrl).Font.Color := T.TextDim;
|
||||
end
|
||||
else if Ctrl is TCheckBox then
|
||||
TCheckBox(Ctrl).Font.Color := T.Text
|
||||
else if Ctrl is TListBox then
|
||||
begin
|
||||
TListBox(Ctrl).Color := T.BG;
|
||||
TListBox(Ctrl).Font.Color := T.Text;
|
||||
end
|
||||
else if Ctrl is TWinControl then
|
||||
WalkControls(TWinControl(Ctrl));
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
Color := CLR_BG;
|
||||
if Assigned(FNavPanel) then FNavPanel.Color := TColor($00151515);
|
||||
if Assigned(FContentPanel) then FContentPanel.Color := CLR_BG;
|
||||
if Assigned(FPageAudio) then FPageAudio.Color := CLR_BG;
|
||||
if Assigned(FPageDisplay) then FPageDisplay.Color := CLR_BG;
|
||||
if Assigned(FPageSpectrum) then FPageSpectrum.Color := CLR_BG;
|
||||
if Assigned(FPageWaterfall) then FPageWaterfall.Color := CLR_BG;
|
||||
if Assigned(FPagePA) then FPagePA.Color := CLR_BG;
|
||||
if Assigned(FPageAdvanced) then FPageAdvanced.Color := CLR_BG;
|
||||
if Assigned(FPageCAT) then FPageCAT.Color := CLR_BG;
|
||||
Color := T.BG;
|
||||
Font.Color := T.Text;
|
||||
WalkControls(Self);
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -1265,6 +1331,15 @@ begin
|
||||
FOnVisibilityChange(FChkShowSpectrum.Checked, FChkShowWaterfall.Checked);
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.OnLightThemeChkChange(Sender: TObject);
|
||||
begin
|
||||
if FLoading then Exit;
|
||||
if FChkLightTheme.Checked then ApplyTheme(LightTheme)
|
||||
else ApplyTheme(DarkTheme);
|
||||
if Assigned(FOnThemeChange) then
|
||||
FOnThemeChange(FChkLightTheme.Checked);
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.OnFPSCmbChange(Sender: TObject);
|
||||
var
|
||||
Idx: Integer;
|
||||
@@ -1291,6 +1366,18 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.LoadLightTheme(ALight: Boolean);
|
||||
begin
|
||||
FLoading := True;
|
||||
try
|
||||
FChkLightTheme.Checked := ALight;
|
||||
finally
|
||||
FLoading := False;
|
||||
end;
|
||||
if ALight then ApplyTheme(LightTheme)
|
||||
else ApplyTheme(DarkTheme);
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.LoadPASettings(MaxPower: Double;
|
||||
const BandCal: array of Double);
|
||||
var i, n: Integer;
|
||||
|
||||
Reference in New Issue
Block a user