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:
+51
-31
@@ -1,7 +1,8 @@
|
||||
unit FlatSlider;
|
||||
|
||||
{ Кастомный горизонтальный ползунок с тёмной темой — замена TTrackBar.
|
||||
Полностью отрисован через Canvas, одинаково выглядит на Windows и Linux. }
|
||||
{ Кастомный горизонтальный ползунок — замена TTrackBar.
|
||||
Полностью отрисован через Canvas, одинаково выглядит на Windows и Linux.
|
||||
Цвета настраиваемые: применяй SetThemeColors(T: TAppTheme) для смены темы. }
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
@@ -20,6 +21,14 @@ type
|
||||
FDragging: Boolean;
|
||||
FHot: Boolean;
|
||||
FOnChange: TNotifyEvent;
|
||||
// Цвета (настраиваются через SetThemeColors или напрямую)
|
||||
FClrBG: TColor;
|
||||
FClrTrackEmpty: TColor;
|
||||
FClrTrackFill: TColor;
|
||||
FClrThumbNorm: TColor;
|
||||
FClrThumbHot: TColor;
|
||||
FClrThumbDrag: TColor;
|
||||
FClrThumbBdr: TColor;
|
||||
procedure SetPosition(V: Integer);
|
||||
procedure SetMin(V: Integer);
|
||||
procedure SetMax(V: Integer);
|
||||
@@ -39,6 +48,11 @@ type
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
|
||||
// Применить набор цветов из темы
|
||||
procedure SetThemeColors(
|
||||
ABG, ATrackEmpty, ATrackFill,
|
||||
AThumbNorm, AThumbHot, AThumbDrag, AThumbBdr: TColor);
|
||||
|
||||
property Min: Integer read FMin write SetMin;
|
||||
property Max: Integer read FMax write SetMax;
|
||||
property Position: Integer read FPosition write SetPosition;
|
||||
@@ -51,17 +65,9 @@ type
|
||||
implementation
|
||||
|
||||
const
|
||||
THUMB_R = 6; // радиус ручки (px)
|
||||
TRACK_H = 4; // высота рельса (px)
|
||||
PAD = THUMB_R + 2; // боковой отступ чтобы ручка не вылезала
|
||||
|
||||
CLR_BG = TColor($00181818); // совпадает с CLR_PANEL
|
||||
CLR_TRACK_EMPTY = TColor($00323232);
|
||||
CLR_TRACK_FILL = TColor($00205018); // тёмно-зелёный, как тема
|
||||
CLR_THUMB_NORM = TColor($00407840);
|
||||
CLR_THUMB_HOT = TColor($0066BB66);
|
||||
CLR_THUMB_DRAG = TColor($0099EE99);
|
||||
CLR_THUMB_BDR = TColor($00122012);
|
||||
THUMB_R = 6;
|
||||
TRACK_H = 4;
|
||||
PAD = THUMB_R + 2;
|
||||
|
||||
constructor TFlatSlider.Create(AOwner: TComponent);
|
||||
begin
|
||||
@@ -73,11 +79,32 @@ begin
|
||||
FDragging := False;
|
||||
FHot := False;
|
||||
Cursor := crHandPoint;
|
||||
// Тёмная тема по умолчанию
|
||||
FClrBG := TColor($00181818);
|
||||
FClrTrackEmpty := TColor($00323232);
|
||||
FClrTrackFill := TColor($00205018);
|
||||
FClrThumbNorm := TColor($00407840);
|
||||
FClrThumbHot := TColor($0066BB66);
|
||||
FClrThumbDrag := TColor($0099EE99);
|
||||
FClrThumbBdr := TColor($00122012);
|
||||
end;
|
||||
|
||||
procedure TFlatSlider.SetThemeColors(
|
||||
ABG, ATrackEmpty, ATrackFill,
|
||||
AThumbNorm, AThumbHot, AThumbDrag, AThumbBdr: TColor);
|
||||
begin
|
||||
FClrBG := ABG;
|
||||
FClrTrackEmpty := ATrackEmpty;
|
||||
FClrTrackFill := ATrackFill;
|
||||
FClrThumbNorm := AThumbNorm;
|
||||
FClrThumbHot := AThumbHot;
|
||||
FClrThumbDrag := AThumbDrag;
|
||||
FClrThumbBdr := AThumbBdr;
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
procedure TFlatSlider.SetPosition(V: Integer);
|
||||
var
|
||||
C: Integer;
|
||||
var C: Integer;
|
||||
begin
|
||||
C := EnsureRange(V, FMin, FMax);
|
||||
if FPosition = C then Exit;
|
||||
@@ -102,10 +129,8 @@ begin
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
// Позиция значения → пиксельная X-координата ручки
|
||||
function TFlatSlider.PosToX(APos: Integer): Integer;
|
||||
var
|
||||
Range, TrackW: Integer;
|
||||
var Range, TrackW: Integer;
|
||||
begin
|
||||
Range := FMax - FMin;
|
||||
TrackW := Width - PAD * 2;
|
||||
@@ -116,10 +141,8 @@ begin
|
||||
Result := PAD + Round((APos - FMin) / Range * TrackW);
|
||||
end;
|
||||
|
||||
// Пиксельная X-координата → значение позиции
|
||||
function TFlatSlider.XToPos(AX: Integer): Integer;
|
||||
var
|
||||
Range, TrackW, RawX: Integer;
|
||||
var Range, TrackW, RawX: Integer;
|
||||
begin
|
||||
Range := FMax - FMin;
|
||||
TrackW := Width - PAD * 2;
|
||||
@@ -141,32 +164,29 @@ begin
|
||||
CY := Height div 2;
|
||||
TX := PosToX(FPosition);
|
||||
|
||||
Canvas.Brush.Color := CLR_BG;
|
||||
Canvas.Brush.Color := FClrBG;
|
||||
Canvas.Brush.Style := bsSolid;
|
||||
Canvas.Pen.Style := psClear;
|
||||
Canvas.FillRect(ClientRect);
|
||||
|
||||
// Рельс — весь
|
||||
TR := Rect(PAD, CY - TRACK_H div 2,
|
||||
Width - PAD, CY + (TRACK_H + 1) div 2);
|
||||
Canvas.Brush.Color := CLR_TRACK_EMPTY;
|
||||
Canvas.Brush.Color := FClrTrackEmpty;
|
||||
Canvas.RoundRect(TR.Left, TR.Top, TR.Right, TR.Bottom, TRACK_H, TRACK_H);
|
||||
|
||||
// Рельс — заполненная часть
|
||||
if not FReversed then begin FL := PAD; FR := TX; end
|
||||
else begin FL := TX; FR := Width - PAD; end;
|
||||
if FR > FL then
|
||||
begin
|
||||
Canvas.Brush.Color := CLR_TRACK_FILL;
|
||||
Canvas.Brush.Color := FClrTrackFill;
|
||||
Canvas.RoundRect(FL, TR.Top, FR, TR.Bottom, TRACK_H, TRACK_H);
|
||||
end;
|
||||
|
||||
// Ручка — круг
|
||||
if FDragging then ThC := CLR_THUMB_DRAG
|
||||
else if FHot then ThC := CLR_THUMB_HOT
|
||||
else ThC := CLR_THUMB_NORM;
|
||||
if FDragging then ThC := FClrThumbDrag
|
||||
else if FHot then ThC := FClrThumbHot
|
||||
else ThC := FClrThumbNorm;
|
||||
Canvas.Brush.Color := ThC;
|
||||
Canvas.Pen.Color := CLR_THUMB_BDR;
|
||||
Canvas.Pen.Color := FClrThumbBdr;
|
||||
Canvas.Pen.Style := psSolid;
|
||||
Canvas.Pen.Width := 1;
|
||||
Canvas.Ellipse(TX - THUMB_R, CY - THUMB_R,
|
||||
|
||||
Reference in New Issue
Block a user