Files
ewsdr/AppTheme.pas
T
ew8bakandClaude Sonnet 4.6 d9a2157719 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>
2026-05-02 19:00:45 +03:00

304 lines
12 KiB
ObjectPascal

unit AppTheme;
{ Цветовые темы приложения EWSDR.
Определяет TAppTheme — запись со всеми цветами интерфейса.
Два конструктора: DarkTheme() и LightTheme(). }
{$mode objfpc}{$H+}
interface
uses Graphics;
type
TAppTheme = record
// Форма / панели
BG, Panel, Border: TColor;
// Текст
Text, TextDim: TColor;
// Обычные кнопки (StyleButton)
BtnNorm, BtnActive, BtnHot: TColor;
BtnBorderNorm, BtnBorderActive: TColor;
BtnText, BtnTextActive: TColor;
// Кнопки SPAN / VFO-copy / HidePanel (StyleSpanButton)
SpanNorm, SpanActive: TColor;
SpanBorder: TColor;
SpanText: TColor;
// Кнопки тулбара (Discover / StartStop)
TbDiscoverNorm, TbDiscoverHot, TbDiscoverBorder: TColor;
TbDiscoverText: TColor;
TbStartNorm, TbStartBorder, TbStartText: TColor;
// VFO-select кнопка — активный VFO
VfoSelActNorm, VfoSelActBorder: TColor;
VfoSelActText, VfoSelActTextAct: TColor;
// VFO-select кнопка — неактивный VFO
VfoSelInaNorm, VfoSelInaBorder: TColor;
VfoSelInaText, VfoSelInaTextAct: TColor;
// VFO-TX кнопка — активна (TX на этом VFO)
VfoTxActNorm, VfoTxActBorder: TColor;
VfoTxActText: TColor;
// VFO-TX кнопка — неактивна
VfoTxInaNorm, VfoTxInaBorder: TColor;
VfoTxInaText: TColor;
// Дисплей частоты
FreqActive, FreqDim: TColor;
// Индикаторы (S-meter, мощность)
MeterOn, MeterOvr: TColor;
Amber: TColor;
// Спектр — фон и сетка
SpecGradTop, SpecGradBot: TColor;
SpecLabelBand: TColor;
SpecLabelText: TColor;
SpecGrid: TColor;
// Спектр — сигнал и маркеры
SpecLine: TColor;
SpecFilter: TColor;
SpecFilterEdge: TColor;
SpecAgcColor: TColor;
SpecAgcHangColor: TColor;
SpecVfoCursor: TColor;
// Спектр — градиент заливки (каналы Blue/Green/Red в сыром пикселе)
SpecGradB, SpecGradG, SpecGradR: Byte; // при Alpha=200
// Линейка частот
RulerGradTop, RulerGradBot: TColor;
RulerBorder: TColor;
RulerText: TColor;
RulerVfo: TColor;
// Ползунки
SliderBG: TColor;
SliderTrackEmpty: TColor;
SliderTrackFill: TColor;
SliderThumbNorm: TColor;
SliderThumbHot: TColor;
SliderThumbDrag: TColor;
SliderThumbBdr: TColor;
// S-метр (широкий)
SMeterBG: TColor;
SMeterBarGreen: TColor;
SMeterBarOver: TColor;
SMeterPeakMarker: TColor;
SMeterTickGreen: TColor;
SMeterTickWhite: TColor;
SMeterTickBlue: TColor;
SMeterLabelDbm: TColor;
SMeterLabelS: TColor;
SMeterScaleDbm: TColor;
SMeterScaleSGreen: TColor;
SMeterScaleSBlue: TColor;
SMeterBdr: TColor;
SMeterDivider: TColor;
end;
function DarkTheme: TAppTheme;
function LightTheme: TAppTheme;
implementation
function DarkTheme: TAppTheme;
begin
FillChar(Result, SizeOf(Result), 0);
Result.BG := TColor($00101010);
Result.Panel := TColor($00181818);
Result.Border := TColor($00303030);
Result.Text := TColor($00CCCCCC);
Result.TextDim := TColor($00666666);
Result.BtnNorm := TColor($001A1A1A);
Result.BtnActive := TColor($000C3010);
Result.BtnHot := TColor($00282828);
Result.BtnBorderNorm := TColor($00444444);
Result.BtnBorderActive := TColor($00387838);
Result.BtnText := TColor($00CCCCCC);
Result.BtnTextActive := TColor($0000FF88);
Result.SpanNorm := TColor($00543F18);
Result.SpanActive := TColor($00624B1D);
Result.SpanBorder := TColor($00685624);
Result.SpanText := TColor($00D8E6EE);
Result.TbDiscoverNorm := TColor($00101828);
Result.TbDiscoverHot := TColor($00182038);
Result.TbDiscoverBorder := TColor($00304860);
Result.TbDiscoverText := TColor($0090B8D0);
Result.TbStartNorm := TColor($00101810);
Result.TbStartBorder := TColor($00304830);
Result.TbStartText := TColor($0090C090);
Result.VfoSelActNorm := TColor($00101C10);
Result.VfoSelActBorder := TColor($004A7A4A);
Result.VfoSelActText := TColor($0060B860);
Result.VfoSelActTextAct := TColor($0040FF60);
Result.VfoSelInaNorm := TColor($001A1A1A);
Result.VfoSelInaBorder := TColor($00404040);
Result.VfoSelInaText := TColor($00666666);
Result.VfoSelInaTextAct := TColor($00CCCCCC);
Result.VfoTxActNorm := TColor($00000060);
Result.VfoTxActBorder := TColor($001010B0);
Result.VfoTxActText := TColor($00C8D8FF);
Result.VfoTxInaNorm := TColor($00303030);
Result.VfoTxInaBorder := TColor($00404040);
Result.VfoTxInaText := TColor($00808080);
Result.FreqActive := TColor($0000FF00);
Result.FreqDim := TColor($00007800);
Result.MeterOn := TColor($0000CC44);
Result.MeterOvr := TColor($000000CC);
Result.Amber := TColor($0000AAFF);
Result.SpecGradTop := TColor($0020160B);
Result.SpecGradBot := TColor($006C4F1F);
Result.SpecLabelBand := TColor($00543F18);
Result.SpecLabelText := TColor($00A8C9D9);
Result.SpecGrid := TColor($00685624);
Result.SpecLine := TColor($0040FF80);
Result.SpecFilter := TColor($006A4E22);
Result.SpecFilterEdge := TColor($0040FFCC);
Result.SpecAgcColor := TColor($0000AAFF);
Result.SpecAgcHangColor := TColor($00FFCC00);
Result.SpecVfoCursor := TColor($0000AAFF);
Result.SpecGradB := 100; Result.SpecGradG := 200; Result.SpecGradR := 0;
Result.RulerGradTop := TColor($00372A12);
Result.RulerGradBot := TColor($00705A2A);
Result.RulerBorder := TColor($00685624);
Result.RulerText := TColor($00C8D8E2);
Result.RulerVfo := TColor($0000FF80);
Result.SliderBG := TColor($00181818);
Result.SliderTrackEmpty := TColor($00323232);
Result.SliderTrackFill := TColor($00205018);
Result.SliderThumbNorm := TColor($00407840);
Result.SliderThumbHot := TColor($0066BB66);
Result.SliderThumbDrag := TColor($0099EE99);
Result.SliderThumbBdr := TColor($00122012);
Result.SMeterBG := TColor($00181818);
Result.SMeterBarGreen := TColor($00091F00);
Result.SMeterBarOver := TColor($00091528);
Result.SMeterPeakMarker := TColor($00F8F8FF);
Result.SMeterTickGreen := TColor($00708070);
Result.SMeterTickWhite := TColor($00E0E0DC);
Result.SMeterTickBlue := TColor($0070A090);
Result.SMeterLabelDbm := TColor($0096D8DC);
Result.SMeterLabelS := TColor($00F0F0F0);
Result.SMeterScaleDbm := TColor($00D0DCDC);
Result.SMeterScaleSGreen:= TColor($00E0E0E0);
Result.SMeterScaleSBlue := TColor($0090D090);
Result.SMeterBdr := TColor($00303028);
Result.SMeterDivider := TColor($00404040);
end;
function LightTheme: TAppTheme;
begin
FillChar(Result, SizeOf(Result), 0);
// Фон — тёплый белый, панели — тёплый светло-серый
Result.BG := TColor($00F0EEE8);
Result.Panel := TColor($00E8E6E0);
Result.Border := TColor($00B8B4AC);
Result.Text := TColor($00181410);
Result.TextDim := TColor($00706860);
// Обычные кнопки — светло-серые, активная — светло-зелёная
Result.BtnNorm := TColor($00DCDAD4);
Result.BtnActive := TColor($00B8D8B8);
Result.BtnHot := TColor($00CFCDC6);
Result.BtnBorderNorm := TColor($00A8A4A0);
Result.BtnBorderActive := TColor($00407840);
Result.BtnText := TColor($00181410);
Result.BtnTextActive := TColor($00004800);
// Span/VFO-copy — тёплый тан/пергамент
Result.SpanNorm := TColor($00D4C8A0);
Result.SpanActive := TColor($00C0B488);
Result.SpanBorder := TColor($00A09070);
Result.SpanText := TColor($00302010);
// Тулбар — более насыщенные оттенки
Result.TbDiscoverNorm := TColor($00C8D8E8);
Result.TbDiscoverHot := TColor($00B8CCE0);
Result.TbDiscoverBorder := TColor($00789CB8);
Result.TbDiscoverText := TColor($00284860);
Result.TbStartNorm := TColor($00C8E0C8);
Result.TbStartBorder := TColor($00609860);
Result.TbStartText := TColor($00204820);
// VFO-select активный — зелёная подсветка
Result.VfoSelActNorm := TColor($00C0E0C0);
Result.VfoSelActBorder := TColor($00508050);
Result.VfoSelActText := TColor($00205020);
Result.VfoSelActTextAct := TColor($00006600);
// VFO-select неактивный — нейтральный
Result.VfoSelInaNorm := TColor($00DCDAD4);
Result.VfoSelInaBorder := TColor($00A8A4A0);
Result.VfoSelInaText := TColor($00706860);
Result.VfoSelInaTextAct := TColor($00181410);
// VFO-TX — синеватый акцент
Result.VfoTxActNorm := TColor($00C0CCEC);
Result.VfoTxActBorder := TColor($006070C0);
Result.VfoTxActText := TColor($00102060);
Result.VfoTxInaNorm := TColor($00DCDAD4);
Result.VfoTxInaBorder := TColor($00A8A4A0);
Result.VfoTxInaText := TColor($00706860);
// Дисплей частоты — насыщенный зелёный
Result.FreqActive := TColor($00005500);
Result.FreqDim := TColor($00447044);
// Индикаторы
Result.MeterOn := TColor($00006820);
Result.MeterOvr := TColor($00AA1010);
Result.Amber := TColor($00904000);
// Спектр — светлый пергаментный фон, тёмно-зелёный сигнал
Result.SpecGradTop := TColor($00E8E4D8);
Result.SpecGradBot := TColor($00D0CCBE);
Result.SpecLabelBand := TColor($00D8D4C8);
Result.SpecLabelText := TColor($00404038);
Result.SpecGrid := TColor($00B8B4A4);
Result.SpecLine := TColor($00006400); // тёмно-зелёная линия
Result.SpecFilter := TColor($00C8DCC8); // светло-зелёная полоса фильтра
Result.SpecFilterEdge := TColor($00407840);
Result.SpecAgcColor := TColor($00904000); // тёмно-оранжевый AGC
Result.SpecAgcHangColor := TColor($00802000);
Result.SpecVfoCursor := TColor($00004800);
// Пиксели градиента: тёмно-зелёный (B=0, G=80, R=10 при Alpha=200)
Result.SpecGradB := 0; Result.SpecGradG := 80; Result.SpecGradR := 10;
// Линейка — тёплый пергамент
Result.RulerGradTop := TColor($00DDD8CC);
Result.RulerGradBot := TColor($00C8C2B4);
Result.RulerBorder := TColor($00A09878);
Result.RulerText := TColor($00302820);
Result.RulerVfo := TColor($00006800);
// Ползунки — светлые с зелёным акцентом
Result.SliderBG := TColor($00E8E6E0);
Result.SliderTrackEmpty := TColor($00CCCAC4);
Result.SliderTrackFill := TColor($0080AA80);
Result.SliderThumbNorm := TColor($00508050);
Result.SliderThumbHot := TColor($003D9040);
Result.SliderThumbDrag := TColor($0028A830);
Result.SliderThumbBdr := TColor($00183018);
// S-метр — светлый
Result.SMeterBG := TColor($00ECE8E0);
Result.SMeterBarGreen := TColor($00C0EAC0);
Result.SMeterBarOver := TColor($00EAC0C0);
Result.SMeterPeakMarker := TColor($00181010);
Result.SMeterTickGreen := TColor($00508050);
Result.SMeterTickWhite := TColor($00282018);
Result.SMeterTickBlue := TColor($00406880);
Result.SMeterLabelDbm := TColor($00204860);
Result.SMeterLabelS := TColor($00201810);
Result.SMeterScaleDbm := TColor($00304848);
Result.SMeterScaleSGreen:= TColor($00204020);
Result.SMeterScaleSBlue := TColor($00204050);
Result.SMeterBdr := TColor($00A0A090);
Result.SMeterDivider := TColor($00B0ACA0);
end;
end.