feat(overlay): flat themed buttons + full theme support for slice flags

Share one button paint routine: extract TFlatButton.Paint into
PaintFlatButton(canvas, rect, colors) and call it from both TFlatButton
and VfoOverlay.DrawButton — flag buttons now render identically to the
left panel (flat fill + border, no gloss), using theme Btn* colors.

Theme the whole flag card: the structural CLR_* palette (card bg,
border, text, dim, accents, freq, meter bg) is now derived from the
active TAppTheme via ApplyThemeColors, so flags follow light/dark like
the rest of the UI. Status accents (TX/SPLIT) stay fixed on purpose and
use a fixed dark text over their bright badges. Theme is pushed to
flags from ApplyDarkTheme and on creation via WireOverlayEvents.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 14:04:21 +03:00
co-authored by Claude Opus 4.8
parent 3049f919a3
commit a3ac459abc
3 changed files with 98 additions and 90 deletions
+36 -22
View File
@@ -51,6 +51,14 @@ type
property Visible;
end;
// Отрисовка кнопки в стиле TFlatButton на произвольном канвасе/прямоугольнике.
// Используется и TFlatButton.Paint, и оверлеями, которые рендерятся в битмап
// (VfoOverlay) — чтобы вид кнопок был одинаковым по всей программе. Шрифт
// берётся текущий у канваса (вызывающий выставляет Name/Size заранее).
procedure PaintFlatButton(C: TCanvas; const R: TRect; const ACaption: string;
AActive, AHot: Boolean;
ClrNorm, ClrActive, ClrHot, ClrBorder, ClrText, ClrTextAct: TColor);
// Фабрика — аналог MakeBtn, возвращает TFlatButton
function MakeFlatBtn(AParent: TWinControl; const ACap: string;
ALeft, ATop, AW, AH: Integer;
@@ -85,39 +93,45 @@ begin
Invalidate;
end;
procedure TFlatButton.Paint;
procedure PaintFlatButton(C: TCanvas; const R: TRect; const ACaption: string;
AActive, AHot: Boolean;
ClrNorm, ClrActive, ClrHot, ClrBorder, ClrText, ClrTextAct: TColor);
const
CORNER = 3;
var
R: TRect;
TW, TH: Integer;
BG: TColor;
TW, TH: Integer;
begin
R := ClientRect;
if FActive then BG := FClrActive
else if FHot then BG := FClrHot
else BG := FClrNorm;
if AActive then BG := ClrActive
else if AHot then BG := ClrHot
else BG := ClrNorm;
// Фон со скруглёнными углами
Canvas.Brush.Color := BG;
Canvas.Brush.Style := bsSolid;
Canvas.Pen.Color := BG;
Canvas.Pen.Style := psSolid;
Canvas.RoundRect(R.Left, R.Top, R.Right, R.Bottom, CORNER * 2, CORNER * 2);
C.Brush.Color := BG;
C.Brush.Style := bsSolid;
C.Pen.Color := BG;
C.Pen.Style := psSolid;
C.RoundRect(R.Left, R.Top, R.Right, R.Bottom, CORNER * 2, CORNER * 2);
// Рамка
Canvas.Pen.Color := FClrBorder;
Canvas.Brush.Style := bsClear;
Canvas.RoundRect(R.Left, R.Top, R.Right - 1, R.Bottom - 1, CORNER * 2, CORNER * 2);
C.Pen.Color := ClrBorder;
C.Brush.Style := bsClear;
C.RoundRect(R.Left, R.Top, R.Right - 1, R.Bottom - 1, CORNER * 2, CORNER * 2);
// Текст
if FActive then Canvas.Font.Color := FClrTextAct
else Canvas.Font.Color := FClrText;
Canvas.Brush.Style := bsClear;
TW := Canvas.TextWidth(Caption);
TH := Canvas.TextHeight('A');
Canvas.TextOut((Width - TW) div 2, (Height - TH) div 2, Caption);
if AActive then C.Font.Color := ClrTextAct
else C.Font.Color := ClrText;
C.Brush.Style := bsClear;
TW := C.TextWidth(ACaption);
TH := C.TextHeight('A');
C.TextOut(R.Left + (R.Right - R.Left - TW) div 2,
R.Top + (R.Bottom - R.Top - TH) div 2, ACaption);
end;
procedure TFlatButton.Paint;
begin
PaintFlatButton(Canvas, ClientRect, Caption, FActive, FHot,
FClrNorm, FClrActive, FClrHot, FClrBorder, FClrText, FClrTextAct);
end;
procedure TFlatButton.MouseEnter;