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:
2026-05-02 19:00:45 +03:00
co-authored by Claude Sonnet 4.6
parent f89b15730e
commit d9a2157719
8 changed files with 785 additions and 173 deletions
+66 -2
View File
@@ -5,7 +5,7 @@ unit DeviceForm;
interface
uses
Classes, SysUtils, FlatButton, Forms, Controls, Graphics, Dialogs,
Classes, SysUtils, FlatButton, AppTheme, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, ComCtrls, IniFiles;
// Декодирование типа платы (совпадает с MainForm.BoardTypeName)
@@ -94,6 +94,8 @@ type
public
constructor Create(AOwner: TComponent); override;
procedure SetTheme(const T: TAppTheme);
// Добавить найденное устройство (вызывается из MainForm при discovery)
procedure AddDiscovered(const IP, DisplayName: string; BoardType: Integer = 0);
procedure ClearDiscovered;
@@ -271,7 +273,69 @@ end;
procedure TDeviceDialog.ApplyTheme;
begin
// уже задано в BuildUI
end;
procedure TDeviceDialog.SetTheme(const T: TAppTheme);
procedure StyleBtn(B: TFlatButton; Accent: Boolean);
begin
B.ClrNorm := T.Panel;
B.ClrBorder := T.Border;
B.ClrHot := T.BG;
B.ClrActive := T.Panel;
B.ClrText := T.Text;
if Accent then B.ClrTextAct := T.FreqActive
else B.ClrTextAct := T.Text;
B.Font.Color := T.Text;
B.Invalidate;
end;
procedure WalkLabels(C: TWinControl);
var i: Integer; Ctrl: TControl;
begin
for i := 0 to C.ControlCount - 1 do
begin
Ctrl := C.Controls[i];
if Ctrl is TLabel then
TLabel(Ctrl).Font.Color := T.TextDim
else if Ctrl is TWinControl then
WalkLabels(TWinControl(Ctrl));
end;
end;
begin
Color := T.BG;
Font.Color := T.Text;
if PanelLeft <> nil then PanelLeft.Color := T.Panel;
if PanelRight <> nil then PanelRight.Color := T.Panel;
if LstSaved <> nil then begin
LstSaved.Color := T.BG;
LstSaved.Font.Color := T.Text;
end;
if LstFound <> nil then begin
LstFound.Color := T.BG;
LstFound.Font.Color := T.Text;
end;
if BtnAdd <> nil then StyleBtn(BtnAdd, False);
if BtnRemove <> nil then StyleBtn(BtnRemove, False);
if BtnSetAuto <> nil then StyleBtn(BtnSetAuto, False);
if BtnDiscover <> nil then StyleBtn(BtnDiscover, False);
if BtnAddFound <> nil then StyleBtn(BtnAddFound, False);
if BtnCancel <> nil then StyleBtn(BtnCancel, False);
if BtnConnect <> nil then StyleBtn(BtnConnect, True);
// Edit fields: white bg for light theme, dark bg for dark theme
if Integer(T.BG) > Integer(TColor($00808080)) then
begin
if EdName <> nil then begin EdName.Color := TColor($00FFFFFF); EdName.Font.Color := TColor($00202020); end;
if EdIP <> nil then begin EdIP.Color := TColor($00FFFFFF); EdIP.Font.Color := TColor($00202020); end;
end
else
begin
if EdName <> nil then begin EdName.Color := TColor($00121212); EdName.Font.Color := TColor($00E0E0E0); end;
if EdIP <> nil then begin EdIP.Color := TColor($00121212); EdIP.Font.Color := TColor($00E0E0E0); end;
end;
WalkLabels(Self);
Invalidate;
end;
procedure TDeviceDialog.LoadSaved;