You've already forked lazarus-ccr
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8783 8e941d3f-bd1b-0410-a28a-d453659cc2b4
551 lines
15 KiB
ObjectPascal
551 lines
15 KiB
ObjectPascal
unit ExProgressbar;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
LCLIntf, LCLType, Classes, SysUtils, Graphics, Types, Controls,
|
|
ExtCtrls, ComCtrls;
|
|
|
|
type
|
|
TProgressBarBorderStyle = (bsNone, bsFlat, bsSunken, bsRaised, bsEtched);
|
|
TProgressbarDrawStyle = (pdsFlat, pdsGradient, pdsRounded, pdsShiny, pdsBevel);
|
|
TProgressbarTextMode = (tmNone, tmValue, tmPercent, tmValueAndPercent, tmCustom);
|
|
|
|
TProgressbarEx = class(TGraphicControl)
|
|
private
|
|
const
|
|
DEFAULT_BACKCOLOR = $E6E6E6;
|
|
DEFAULT_BARCOLOR = $06B025;
|
|
DEFAULT_GRADIENTENDCOLOR = $00FFFF;
|
|
DEFAULT_BORDERCOLOR = clSilver;
|
|
DEFAULT_MARQUEELENGTH = 120;
|
|
DEFAULT_MARQUEESPEED = 8;
|
|
private
|
|
FBorderStyle: TProgressBarBorderStyle;
|
|
FCaption: String;
|
|
FColors: array[0..3] of TColor;
|
|
FDrawStyle: TProgressBarDrawStyle;
|
|
FMarqueePosition: Integer;
|
|
FMarqueeLength: Integer;
|
|
FMarqueeSpeed: Integer;
|
|
FMax: Integer;
|
|
FMin: Integer;
|
|
FOrientation: TProgressBarOrientation; // (pbHorizontal, pbVertical, pbRightToLeft, pbTopDown)
|
|
FPosition: Integer;
|
|
FStyle: TProgressBarStyle; // (pbstNormal, pbstMarquee)
|
|
FTextMode: TProgressBarTextMode;
|
|
FTimer: TTimer;
|
|
function GetColors(AIndex: Integer): TColor;
|
|
procedure SetBorderStyle(AValue: TProgressBarBorderStyle);
|
|
procedure SetCaption(AValue: String);
|
|
procedure SetColors(AIndex: Integer; AValue: TColor);
|
|
procedure SetDrawStyle(AValue: TProgressbarDrawStyle);
|
|
procedure SetMax(AValue: Integer);
|
|
procedure SetMin(AValue: Integer);
|
|
procedure SetOrientation(AValue: TProgressbarOrientation);
|
|
procedure SetPosition(AValue: Integer);
|
|
procedure SetStyle(AValue: TProgressbarStyle);
|
|
procedure SetTextMode(AValue: TProgressBarTextMode);
|
|
procedure TimerHandler(Sender: TObject);
|
|
protected
|
|
procedure DoAutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
|
|
const AXProportion, AYProportion: Double); override;
|
|
function GetBarRect: TRect;
|
|
function GetCaptionText: String;
|
|
class function GetControlClassDefaultSize: TSize; override;
|
|
function IsHorizontal(AOrientation: TProgressbarOrientation): Boolean;
|
|
procedure Paint; override;
|
|
procedure SetAutoSize(AValue: Boolean); override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
published
|
|
property BackColor: TColor index 0 read GetColors write SetColors default DEFAULT_BACKCOLOR;
|
|
property BorderColor: TColor index 1 read GetColors write SetColors default DEFAULT_BORDERCOLOR;
|
|
property BorderStyle: TProgressbarBorderStyle read FBorderSTyle write SetBorderStyle default bsFlat;
|
|
property BarColor: TColor index 2 read GetColors write SetColors default DEFAULT_BARCOLOR;
|
|
property GradientEndColor: TColor index 3 read GetColors write SetColors default DEFAULT_GRADIENTENDCOLOR;
|
|
property Caption: String read FCaption write SetCaption;
|
|
property DrawStyle: TProgressbarDrawStyle read FDrawStyle write SetDrawStyle default pdsFlat;
|
|
property MarqueeLength: Integer read FMarqueeLength write FMarqueeLength default DEFAULT_MARQUEELENGTH;
|
|
property MarqueeSpeed: Integer read FMarqueeSpeed write FMarqueeSpeed default DEFAULT_MARQUEESPEED;
|
|
property Max: Integer read FMax write SetMax default 100;
|
|
property Min: Integer read FMin write SetMin default 0;
|
|
property Orientation: TProgressbarOrientation read FOrientation write SetOrientation default pbHorizontal;
|
|
property Position: Integer read FPosition write SetPosition default 0;
|
|
property Style: TProgressbarStyle read FStyle write SetStyle default pbstNormal;
|
|
property TextMode: TProgressBarTextMode read FTextMode write SetTextMode default tmNone;
|
|
|
|
property Align;
|
|
property Anchors;
|
|
property AutoSize;
|
|
property BorderSpacing;
|
|
property Constraints;
|
|
property Font;
|
|
property Hint;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property ShowHint;
|
|
property Visible;
|
|
|
|
property OnPaint;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
GraphUtil;
|
|
|
|
constructor TProgressbarEx.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
ControlStyle := ControlStyle - [csSetCaption];
|
|
|
|
FBorderStyle := bsFlat;
|
|
|
|
FCaption := '';
|
|
FColors[0] := DEFAULT_BACKCOLOR;
|
|
FColors[1] := DEFAULT_BORDERCOLOR;
|
|
FColors[2] := DEFAULT_BARCOLOR;
|
|
FColors[3] := DEFAULT_GRADIENTENDCOLOR;
|
|
FMarqueeLength := DEFAULT_MARQUEELENGTH;
|
|
FMarqueeSpeed := DEFAULT_MARQUEESPEED;
|
|
FMax := 100;
|
|
FStyle := pbstNormal;
|
|
|
|
FTimer := TTimer.Create(self);
|
|
FTimer.Interval := 25;
|
|
FTimer.OnTimer := @TimerHandler;
|
|
FTimer.Enabled := false;
|
|
|
|
with GetControlClassDefaultSize do
|
|
SetInitialBounds(0, 0, CX, CY);
|
|
end;
|
|
|
|
procedure TProgressbarEx.DoAutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
|
|
const AXProportion, AYProportion: Double);
|
|
begin
|
|
inherited;
|
|
if AMode in [lapAutoAdjustWithoutHorizontalScrolling, lapAutoAdjustForDPI] then
|
|
FMarqueeLength := round(DEFAULT_MARQUEELENGTH * AXProportion);
|
|
end;
|
|
|
|
function TProgressBarEx.GetBarRect: TRect;
|
|
var
|
|
fraction: Double;
|
|
begin
|
|
Result := Rect(0, 0, Width, Height);
|
|
case FBorderStyle of
|
|
bsNone: ;
|
|
bsEtched: InflateRect(Result, -2, -2);
|
|
else InflateRect(Result, -1, -1);
|
|
end;
|
|
fraction := (FPosition - FMin) / (FMax - FMin);
|
|
case FStyle of
|
|
pbstNormal:
|
|
begin
|
|
if FMax = FMin then
|
|
exit(Rect(0, 0, 0, 0));
|
|
case FOrientation of
|
|
pbHorizontal: Result.Right := round(fraction * (Width - 1));
|
|
pbRightToLeft: Result.Left := Result.Right - round(fraction * (Width - 1));
|
|
pbVertical: Result.Top := Result.Bottom - round(fraction * (Height - 1));
|
|
pbTopDown: Result.Bottom := round(fraction * (Height - 1));
|
|
end;
|
|
end;
|
|
pbstMarquee:
|
|
case FOrientation of
|
|
pbHorizontal:
|
|
begin
|
|
Result.Right := FMarqueePosition;
|
|
Result.Left := Result.Right - FMarqueeLength;
|
|
end;
|
|
pbRightToLeft:
|
|
begin
|
|
Result.Left := Result.Right - FMarqueePosition;
|
|
Result.Right := Result.Left + FMarqueelength;
|
|
end;
|
|
pbVertical:
|
|
begin
|
|
Result.Top := Result.Bottom - FMarqueePosition;
|
|
Result.Bottom := Result.Top + FMarqueeLength;
|
|
end;
|
|
pbTopDown:
|
|
begin
|
|
Result.Bottom := FMarqueePosition;
|
|
Result.Top := Result.Bottom - FMarqueeLength;
|
|
end;
|
|
end;
|
|
end;
|
|
if IsHorizontal(FOrientation) then
|
|
begin
|
|
if Result.Right >= Width - 1 then Result.Right := Width - 1;
|
|
if Result.Left < 1 then Result.Left := 1;
|
|
end else
|
|
begin
|
|
if Result.Bottom >= Height - 1 then Result.Bottom := Height - 1;
|
|
if Result.Top < 1 then Result.Top := 1;
|
|
end;
|
|
end;
|
|
|
|
function TProgressbarEx.GetCaptionText: String;
|
|
var
|
|
posValue: Double;
|
|
begin
|
|
if FStyle = pbstMarquee then
|
|
Result := FCaption
|
|
else
|
|
begin
|
|
Result := '';
|
|
case FTextMode of
|
|
tmValue:
|
|
if FCaption = '' then
|
|
Result := IntToStr(FPosition)
|
|
else
|
|
Result := Format(FCaption, [FPosition]);
|
|
tmPercent:
|
|
if FMax <> FMin then
|
|
begin
|
|
posValue := (FPosition - FMin) / (FMax - FMin) * 100.0;
|
|
if (FCaption = '') then
|
|
Result := Format('%.0f%%', [posValue])
|
|
else
|
|
Result := Format(FCaption, [posValue]);
|
|
end else
|
|
exit;
|
|
tmValueAndPercent:
|
|
if FMax <> FMin then
|
|
begin
|
|
posValue := (FPosition - FMin) / (FMax - FMin) * 100.0;
|
|
if FCaption = '' then
|
|
Result := Format('%0:d (%1:.0f%%)', [FPosition, posValue])
|
|
else
|
|
Result := Format(FCaption, [FPosition, posValue]);
|
|
end else
|
|
exit;
|
|
tmCustom:
|
|
Result := FCaption;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TProgressbarEx.GetColors(AIndex: Integer): TColor;
|
|
begin
|
|
Result := FColors[AIndex];
|
|
end;
|
|
|
|
class function TProgressbarEx.GetControlClassDefaultSize: TSize;
|
|
begin
|
|
Result.CX := 200;
|
|
Result.CY := 20;
|
|
end;
|
|
|
|
function TProgressbarEx.IsHorizontal(AOrientation: TProgressbarOrientation): Boolean;
|
|
begin
|
|
Result := (AOrientation in [pbHorizontal, pbRightToLeft]);
|
|
end;
|
|
|
|
procedure TProgressbarEx.Paint;
|
|
var
|
|
R, R1, R2: TRect;
|
|
FontAngle: Integer;
|
|
txt: String;
|
|
txtSize: TSize;
|
|
isHor: Boolean;
|
|
col1, col2, col3: TColor;
|
|
begin
|
|
isHor := IsHorizontal(FOrientation);
|
|
|
|
// Draw background with border
|
|
Canvas.Brush.Style := bsSolid;
|
|
Canvas.Brush.Color := BackColor;
|
|
R := Rect(0, 0, Width, Height);
|
|
if FBorderStyle = bsNone then
|
|
Canvas.FillRect(R)
|
|
else
|
|
if FBorderStyle = bsFlat then
|
|
begin
|
|
Canvas.Pen.Color := BorderColor;
|
|
Canvas.Rectangle(R);
|
|
end else
|
|
begin
|
|
case FBorderStyle of
|
|
bsSunken:
|
|
DrawEdge(Canvas.Handle, R, BDR_SUNKENOUTER, BF_RECT);
|
|
bsRaised:
|
|
DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_RECT);
|
|
bsEtched:
|
|
begin
|
|
DrawEdge(Canvas.Handle, R, EDGE_ETCHED, BF_RECT);
|
|
InflateRect(R, -1, -1);
|
|
end;
|
|
end;
|
|
InflateRect(R, -1, -1);
|
|
Canvas.FillRect(R);
|
|
end;
|
|
|
|
// Draw bar
|
|
R := GetBarRect;
|
|
if isHor then
|
|
FontAngle := 0
|
|
else
|
|
FontAngle := 900;
|
|
case FDrawStyle of
|
|
pdsFlat:
|
|
begin
|
|
Canvas.Brush.Color := BarColor;
|
|
Canvas.FillRect(R);
|
|
end;
|
|
pdsGradient:
|
|
begin
|
|
case FOrientation of
|
|
pbHorizontal:
|
|
Canvas.GradientFill(R, BarColor, GradientEndColor, gdHorizontal);
|
|
pbVertical:
|
|
Canvas.GradientFill(R, GradientEndColor, barColor, gdVertical);
|
|
pbRightToLeft:
|
|
Canvas.GradientFill(R, GradientEndColor, BarColor, gdHorizontal);
|
|
pbTopDown:
|
|
Canvas.GradientFill(R, BarColor, GradientEndColor, gdVertical);
|
|
end;
|
|
end;
|
|
pdsRounded:
|
|
begin
|
|
col2 := BarColor;
|
|
col1 := GetHighlightColor(col2, 60);
|
|
col3 := GetShadowColor(col2, -60);
|
|
R1 := R;
|
|
R2 := R;
|
|
if isHor then
|
|
begin
|
|
R1.Bottom := R.Top + R.Height div 2;
|
|
R2.Top := R1.Bottom;
|
|
Canvas.GradientFill(R1, col1, col2, gdVertical);
|
|
Canvas.GradientFill(R2, col2, col3, gdVertical);
|
|
end else
|
|
begin
|
|
R1.Right := R.Left + R.Width div 2;
|
|
R2.Left := R1.Right;
|
|
Canvas.GradientFill(R1, col1, col2, gdHorizontal);
|
|
Canvas.GradientFill(R2, col2, col3, gdHorizontal);
|
|
end;
|
|
end;
|
|
pdsShiny:
|
|
begin
|
|
col1 := GetHighlightColor(BarColor, 50);
|
|
col2 := GetHighlightColor(BarColor, 25);
|
|
col3 := GetShadowColor(BarColor, -20);
|
|
R1 := R;
|
|
R2 := R;
|
|
if isHor then
|
|
begin
|
|
R1.Bottom := R.Top + R.Height div 3;
|
|
R2.Top := R1.Bottom ;
|
|
Canvas.GradientFill(R1, col1, col2, gdVertical);
|
|
Canvas.GradientFill(R2, BarColor, col3, gdVertical);
|
|
end else
|
|
begin
|
|
R1 := R;
|
|
R1.Right := R.Left + R.Width div 3;
|
|
R2.Left := R1.Right;
|
|
Canvas.GradientFill(R1, col1, col2, gdHorizontal);
|
|
Canvas.GradientFill(R2, BarColor, col3, gdHorizontal);
|
|
end;
|
|
end;
|
|
pdsBevel:
|
|
begin
|
|
col1 := BarColor;
|
|
Canvas.Brush.Color := col1;
|
|
inc(R.Right);
|
|
Canvas.FillRect(R);
|
|
col2 := GetShadowColor(col1, -30);
|
|
col1 := GetHighlightColor(col1, 30);
|
|
R1 := R;
|
|
InflateRect(R1, -1, -1);
|
|
R2 := R;
|
|
InflateRect(R2, -2, -2);
|
|
Canvas.Pen.Color := col1;
|
|
Canvas.Line(R1.Right, R1.Top, R1.Left, R1.Top);
|
|
Canvas.Line(R2.Right, R2.Top, R2.Left, R2.Top);
|
|
Canvas.Line(R1.Left, R.Top, R1.Left, R1.Bottom);
|
|
Canvas.Line(R2.Left, R2.Top, R2.Left, R2.Bottom);
|
|
Canvas.Pen.Color := col2;
|
|
Canvas.Line(R1.Left, R1.Bottom, R1.Right, R1.Bottom);
|
|
Canvas.Line(R2.Left, R2.Bottom, R2.Right, R2.Bottom);
|
|
Canvas.Line(R1.Right, R1.Bottom, R1.Right, R1.Top);
|
|
Canvas.Line(R2.Right, R2.Bottom, R2.Right, R2.Top);
|
|
end;
|
|
else
|
|
raise Exception.Create('DrawStyle not implemented.');
|
|
end;
|
|
|
|
// Draw text
|
|
if FTextMode <> tmNone then
|
|
begin
|
|
txt := GetCaptionText;
|
|
txtSize := Canvas.TextExtent(txt);
|
|
Canvas.Font.Assign(Font);
|
|
Canvas.Font.Orientation := fontAngle;
|
|
Canvas.Brush.Style := bsClear;
|
|
R := Rect(0, 0, Width, Height);
|
|
if isHor then
|
|
Canvas.TextOut((Width - txtSize.CX) div 2, (Height - txtSize.CY) div 2, txt)
|
|
else
|
|
Canvas.TextOut((Width - txtSize.CY) div 2, R.Bottom - (Height - txtSize.CX) div 2, txt);
|
|
end;
|
|
|
|
inherited;
|
|
end;
|
|
|
|
procedure TProgressBarEx.SetAutoSize(AValue: Boolean);
|
|
var
|
|
bmp: TBitmap;
|
|
fh: Integer;
|
|
begin
|
|
inherited;
|
|
if AutoSize then
|
|
begin
|
|
bmp := TBitmap.Create;
|
|
try
|
|
bmp.SetSize(1, 1);
|
|
bmp.Canvas.Font.Assign(Font);
|
|
fh := bmp.Canvas.TextHeight('Tg');
|
|
finally
|
|
bmp.Free;
|
|
end;
|
|
inc(fh, 8);
|
|
if IsHorizontal(FOrientation) then
|
|
Height := fh
|
|
else
|
|
Width := fh;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TProgressBarEx.SetBorderStyle(AValue: TProgressBarBorderStyle);
|
|
begin
|
|
if FBorderStyle = AValue then
|
|
exit;
|
|
FBorderStyle := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TProgressbarEx.SetCaption(AValue: String);
|
|
begin
|
|
if FCaption = AValue then
|
|
exit;
|
|
FCaption := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TProgressbarEx.SetColors(AIndex: Integer; AValue: TColor);
|
|
begin
|
|
if FColors[AIndex] = AValue then
|
|
exit;
|
|
FColors[AIndex] := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TProgressbarEx.SetDrawStyle(AValue: TProgressbarDrawStyle);
|
|
begin
|
|
if FDrawStyle = AValue then
|
|
exit;
|
|
FDrawStyle := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TProgressbarEx.SetMax(AValue: Integer);
|
|
begin
|
|
if FMax = AValue then
|
|
exit;
|
|
FMax := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TProgressbarEx.SetMin(AValue: Integer);
|
|
begin
|
|
if FMin = AValue then
|
|
exit;
|
|
FMin := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TProgressbarEx.SetOrientation(AValue: TProgressbarOrientation);
|
|
var
|
|
rotate: Boolean;
|
|
begin
|
|
if FOrientation = AValue then
|
|
exit;
|
|
rotate := IsHorizontal(AValue) xor IsHorizontal(FOrientation);
|
|
FOrientation := AValue;
|
|
if rotate then
|
|
SetBounds(Left, Top, Height, Width)
|
|
else
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TProgressbarEx.SetPosition(AValue: Integer);
|
|
begin
|
|
if FPosition = AValue then
|
|
exit;
|
|
if AValue > FMax then
|
|
FPosition := FMax
|
|
else if AValue < FMin then
|
|
FPosition := FMin
|
|
else
|
|
FPosition := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TProgressbarEx.SetStyle(AValue: TProgressbarStyle);
|
|
begin
|
|
if FStyle = AValue then
|
|
exit;
|
|
FStyle := AValue;
|
|
case FStyle of
|
|
pbstNormal:
|
|
begin
|
|
FPosition := FMin;
|
|
FTimer.Enabled := false;
|
|
end;
|
|
pbstMarquee:
|
|
begin
|
|
FMarqueePosition := 0;
|
|
FTimer.Enabled := true;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TProgressBarEx.SetTextMode(AValue: TProgressBarTextMode);
|
|
begin
|
|
if FTextMode = AValue then
|
|
exit;
|
|
FTextMode := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TProgressbarEx.TimerHandler(Sender: TObject);
|
|
begin
|
|
inc(FMarqueePosition, FMarqueeSpeed);
|
|
if IsHorizontal(FOrientation) then
|
|
begin
|
|
if (FMarqueePosition - FMarqueeLength > Width) and (FMarqueeSpeed > 0) then
|
|
FMarqueePosition := 0
|
|
else
|
|
if (FMarqueePosition < 0) and (FMarqueeSpeed < 0) then
|
|
FMarqueePosition := Width + FMarqueeLength;
|
|
end else
|
|
begin
|
|
if (FMarqueePosition - FMarqueeLength > Height) and (FMarqueeSpeed > 0) then
|
|
FMarqueePosition := 0
|
|
else
|
|
if (FMarqueePosition < 0) and (FMarqueeSpeed < 0) then
|
|
FMarqueePosition := Height + FMarqueeLength;
|
|
end;
|
|
Invalidate;
|
|
end;
|
|
|
|
end.
|
|
|