From f87869cd91bec1a683188914b931c3bb261be51a Mon Sep 17 00:00:00 2001 From: Uladzimir Karpenka Date: Mon, 25 May 2026 15:26:55 +0300 Subject: [PATCH] =?UTF-8?q?Add=20FlatProgressBar=20=E2=80=94=20canvas-rend?= =?UTF-8?q?ered=20cross-platform=20progress=20bar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces TProgressBar in TWisdomProgressDialog with TFlatProgressBar, drawn entirely via Canvas (plain rectangle, no native widget styling). Dialog now receives the active TAppTheme so both dark and light themes are applied consistently to background, label, and progress bar. Co-Authored-By: Claude Sonnet 4.6 --- FlatProgressBar.pas | 124 ++++++++++++++++++++++++++++++++++++++++++++ MainForm.pas | 28 ++++++---- ewsdr.lpi | 4 ++ 3 files changed, 145 insertions(+), 11 deletions(-) create mode 100644 FlatProgressBar.pas diff --git a/FlatProgressBar.pas b/FlatProgressBar.pas new file mode 100644 index 0000000..c9228cb --- /dev/null +++ b/FlatProgressBar.pas @@ -0,0 +1,124 @@ +unit FlatProgressBar; + +{ Custom progress bar with canvas rendering. + Use instead of TProgressBar where native widgetset styling is undesirable. } + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Controls, Graphics, Math, AppTheme; + +type + TFlatProgressBar = class(TGraphicControl) + private + FMin: Integer; + FMax: Integer; + FPosition: Integer; + FClrBG: TColor; + FClrTrack: TColor; + FClrFill: TColor; + FClrBorder: TColor; + procedure SetMin(V: Integer); + procedure SetMax(V: Integer); + procedure SetPosition(V: Integer); + protected + procedure Paint; override; + public + constructor Create(AOwner: TComponent); override; + procedure SetAppTheme(const T: TAppTheme); + + property Min: Integer read FMin write SetMin; + property Max: Integer read FMax write SetMax; + property Position: Integer read FPosition write SetPosition; + property Align; + property Anchors; + property Enabled; + property Visible; + end; + +implementation + +constructor TFlatProgressBar.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + Width := 200; + Height := 22; + FMin := 0; + FMax := 100; + FPosition := 0; + FClrBG := TColor($00181818); + FClrTrack := TColor($00323232); + FClrFill := TColor($00205018); + FClrBorder := TColor($00444444); +end; + +procedure TFlatProgressBar.SetAppTheme(const T: TAppTheme); +begin + FClrBG := T.Panel; + FClrTrack := T.SliderTrackEmpty; + FClrFill := T.SliderTrackFill; + FClrBorder := T.BtnBorderNorm; + Invalidate; +end; + +procedure TFlatProgressBar.SetMin(V: Integer); +begin + if FMin = V then Exit; + FMin := V; + if FPosition < FMin then FPosition := FMin; + Invalidate; +end; + +procedure TFlatProgressBar.SetMax(V: Integer); +begin + if FMax = V then Exit; + FMax := V; + if FPosition > FMax then FPosition := FMax; + Invalidate; +end; + +procedure TFlatProgressBar.SetPosition(V: Integer); +var C: Integer; +begin + C := EnsureRange(V, FMin, FMax); + if FPosition = C then Exit; + FPosition := C; + Invalidate; +end; + +procedure TFlatProgressBar.Paint; +var + R: TRect; + Range, TrackW, FillW: Integer; +begin + R := ClientRect; + + Canvas.Brush.Color := FClrBG; + Canvas.Brush.Style := bsSolid; + Canvas.Pen.Style := psClear; + Canvas.FillRect(R); + + Canvas.Brush.Color := FClrTrack; + Canvas.Pen.Color := FClrBorder; + Canvas.Pen.Style := psSolid; + Canvas.Pen.Width := 1; + Canvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom); + + Range := FMax - FMin; + if (Range > 0) and (FPosition > FMin) then + begin + TrackW := Width - 2; + FillW := (TrackW * (FPosition - FMin)) div Range; + FillW := EnsureRange(FillW, 0, TrackW); + if FillW > 0 then + begin + Canvas.Brush.Color := FClrFill; + Canvas.Pen.Style := psClear; + Canvas.FillRect(Rect(1, 1, 1 + FillW, Height - 1)); + end; + end; +end; + +end. diff --git a/MainForm.pas b/MainForm.pas index 29a17a0..256f636 100644 --- a/MainForm.pas +++ b/MainForm.pas @@ -24,7 +24,8 @@ interface uses Classes, SysUtils, StrUtils, FreqDisplay, DeviceForm, VfoOverlay, SampleRateOverlay, FlatButton, FlatSlider, FlatDropDown, AppTheme, Forms, Controls, Graphics, Dialogs, - StdCtrls, ExtCtrls, ComCtrls, Buttons, Menus, Math, Types, + StdCtrls, ExtCtrls, Buttons, Menus, Math, Types, + FlatProgressBar, LCLIntf, LCLType, GraphType, HPSDRProtocol, HPSDRNetwork, WDSP, WDSPEngine, AudioOutput, AudioInput, @@ -742,13 +743,14 @@ type TWisdomProgressDialog = class(TForm) private FInfoLabel: TLabel; - FProgress: TProgressBar; + FProgress: TFlatProgressBar; FTimer: TTimer; FThread: TWisdomBuildThread; FPhase: Integer; procedure TimerTick(Sender: TObject); public - constructor Create(AOwner: TComponent; AThread: TWisdomBuildThread); reintroduce; + constructor Create(AOwner: TComponent; AThread: TWisdomBuildThread; + const ATheme: TAppTheme); reintroduce; end; var @@ -783,7 +785,7 @@ begin end; constructor TWisdomProgressDialog.Create(AOwner: TComponent; - AThread: TWisdomBuildThread); + AThread: TWisdomBuildThread; const ATheme: TAppTheme); begin inherited CreateNew(AOwner); FThread := AThread; @@ -795,26 +797,27 @@ begin Position := poScreenCenter; BorderStyle := bsDialog; BorderIcons := []; - Color := CLR_BG; + Color := ATheme.BG; Font.Name := 'Courier New'; Font.Size := 9; - Font.Color := CLR_TEXT; + Font.Color := ATheme.Text; FInfoLabel := TLabel.Create(Self); FInfoLabel.Parent := Self; FInfoLabel.SetBounds(16, 16, 480, 40); FInfoLabel.AutoSize := False; FInfoLabel.WordWrap := True; - FInfoLabel.Font.Color := CLR_TEXT; + FInfoLabel.Font.Color := ATheme.Text; FInfoLabel.Caption := 'Creating FFTW wisdom for WDSP. This is done once and may take a while on the first run.'; - FProgress := TProgressBar.Create(Self); + FProgress := TFlatProgressBar.Create(Self); FProgress.Parent := Self; FProgress.SetBounds(16, 72, 480, 22); - FProgress.Min := 0; - FProgress.Max := 100; + FProgress.Min := 0; + FProgress.Max := 100; FProgress.Position := 0; + FProgress.SetAppTheme(ATheme); FTimer := TTimer.Create(Self); FTimer.Interval := 250; @@ -3686,7 +3689,10 @@ begin BuildThread := TWisdomBuildThread.Create(WisdomDir); try - Dlg := TWisdomProgressDialog.Create(Self, BuildThread); + if FLightTheme then + Dlg := TWisdomProgressDialog.Create(Self, BuildThread, LightTheme) + else + Dlg := TWisdomProgressDialog.Create(Self, BuildThread, DarkTheme); try Dlg.ShowModal; finally diff --git a/ewsdr.lpi b/ewsdr.lpi index 6eae773..618a90c 100644 --- a/ewsdr.lpi +++ b/ewsdr.lpi @@ -159,6 +159,10 @@ + + + +