mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-19 12:29:30 +02:00
Merged revision(s) 62628 #d47d48cd56, 62633 #6483f57d33 from trunk:
TAChart: Fix painting of checkboxes in TChartListBox on COCOA. ........ TAChart: Fix drawing of checkboxes/radiobuttons on Cocoa, part 2. ........ git-svn-id: branches/fixes_2_0@62823 -
This commit is contained in:
parent
b8f25955d0
commit
43998ec941
@ -20,14 +20,19 @@
|
||||
|
||||
unit TAChartListbox;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$MODE objfpc}{$H+}
|
||||
|
||||
{$IFDEF DARWIN}
|
||||
{$DEFINE USE_BITMAPS}
|
||||
{$ENDIF}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, Controls, StdCtrls,
|
||||
Classes, Controls, StdCtrls, Types,
|
||||
TAChartUtils, TACustomSeries, TALegend, TAGraph;
|
||||
|
||||
|
||||
type
|
||||
TChartListbox = class;
|
||||
|
||||
@ -51,7 +56,10 @@ type
|
||||
TChartListbox = class(TCustomListbox)
|
||||
private
|
||||
FChart: TChart;
|
||||
FCheckBoxSize: TSize;
|
||||
FCheckStyle: TCheckBoxesStyle;
|
||||
FDown: Boolean;
|
||||
FHot: Boolean;
|
||||
FLegendItems: TChartLegendItems;
|
||||
FListener: TListener;
|
||||
FOnAddSeries: TChartListboxAddSeriesEvent;
|
||||
@ -77,8 +85,10 @@ type
|
||||
procedure DrawItem(
|
||||
AIndex: Integer; ARect: TRect; AState: TOwnerDrawState); override;
|
||||
procedure KeyDown(var AKey: Word; AShift: TShiftState); override;
|
||||
procedure MouseDown(
|
||||
AButton: TMouseButton; AShift: TShiftState; AX, AY: Integer); override;
|
||||
procedure MouseDown(AButton: TMouseButton; AShift: TShiftState; AX, AY: Integer); override;
|
||||
procedure MouseEnter; override;
|
||||
procedure MouseLeave; override;
|
||||
procedure MouseUp(AButton: TMouseButton; AShift: TShiftState; AX, AY: Integer); override;
|
||||
protected
|
||||
procedure CalcRects(
|
||||
const AItemRect: TRect; out ACheckboxRect, ASeriesIconRect: TRect);
|
||||
@ -185,11 +195,49 @@ uses
|
||||
Graphics, Math, LCLIntf, LCLType, SysUtils, Themes,
|
||||
TACustomSource, TADrawerCanvas, TADrawUtils, TAEnumerators, TAGeometry;
|
||||
|
||||
procedure Register;
|
||||
type
|
||||
TThemedStatesUsed = {%H-}tbRadioButtonUnCheckedNormal..tbCheckboxCheckedDisabled;
|
||||
|
||||
{$IFDEF USE_BITMAPS}
|
||||
var
|
||||
ThemedBitmaps: Array[TThemedStatesUsed] of TBitmap;
|
||||
|
||||
function CreateBitmap(AThemedButton: TThemedButton; ABkColor: TColor): TBitmap;
|
||||
var
|
||||
s: TSize;
|
||||
details: TThemedElementDetails;
|
||||
begin
|
||||
RegisterComponents(CHART_COMPONENT_IDE_PAGE, [TChartListbox]);
|
||||
Result := ThemedBitmaps[AThemedButton];
|
||||
if Assigned(Result) and (Result.Canvas.Pixels[0, 0] = ABkColor) then
|
||||
exit;
|
||||
FreeAndNil(Result);
|
||||
Result := TBitmap.Create;
|
||||
details := ThemeServices.GetElementDetails(AThemedButton);
|
||||
s := ThemeServices.GetDetailSize(details);
|
||||
Result.SetSize(s.CX, s.CY);
|
||||
Result.Canvas.Brush.Color := ABkColor;
|
||||
Result.Canvas.FillRect(0, 0, Result.Width, Result.Height);
|
||||
ThemeServices.DrawElement(Result.Canvas.Handle, details, Rect(0, 0, Result.Width, Result.Height));
|
||||
ThemedBitmaps[AThemedButton] := Result;
|
||||
end;
|
||||
|
||||
procedure InitBitmaps;
|
||||
var
|
||||
tb: TThemedButton;
|
||||
begin
|
||||
for tb in TThemedStatesUsed do
|
||||
ThemedBitmaps[tb] := nil;
|
||||
end;
|
||||
|
||||
procedure FreeBitmaps;
|
||||
var
|
||||
tb: TThemedButton;
|
||||
begin
|
||||
for tb in TThemedStatesUsed do
|
||||
FreeAndNil(ThemedBitmaps[tb]);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
{ TChartListbox }
|
||||
|
||||
constructor TChartListbox.Create(AOwner: TComponent);
|
||||
@ -211,17 +259,18 @@ procedure TChartListbox.CalcRects(
|
||||
const AItemRect: TRect; out ACheckboxRect, ASeriesIconRect: TRect);
|
||||
{ based on the rect of a listbox item, calculates the locations of the
|
||||
checkbox and of the series icon }
|
||||
const
|
||||
MARGIN = 4;
|
||||
var
|
||||
w, x: Integer;
|
||||
x: Integer;
|
||||
begin
|
||||
ACheckBoxRect := ZeroRect;
|
||||
ASeriesIconRect := ZeroRect;
|
||||
|
||||
w := Canvas.TextHeight('Tg');
|
||||
x := 4;
|
||||
x := AItemRect.Left + MARGIN;
|
||||
if cloShowCheckboxes in Options then begin
|
||||
with AItemRect do
|
||||
ACheckboxRect := Bounds(Left + 4, (Top + Bottom - w) div 2, w, w);
|
||||
ACheckBoxRect := Rect(0, 0, FCheckboxSize.CX, FCheckboxSize.CY);
|
||||
OffsetRect(ACheckboxRect, x, (AItemRect.Top + AItemRect.Bottom - FCheckboxSize.CY) div 2);
|
||||
if cloShowIcons in Options then
|
||||
x += ACheckboxRect.Right;
|
||||
end
|
||||
@ -285,44 +334,67 @@ begin
|
||||
ClickedSeriesIcon(FSeriesIconClicked);
|
||||
end;
|
||||
|
||||
function GetThemedButtonOffset(Hot, Pressed, Disabled: Boolean): Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
if Disabled then
|
||||
Result := 3
|
||||
else if Hot then
|
||||
Result := 1
|
||||
else if Pressed then
|
||||
Result := 2;
|
||||
end;
|
||||
|
||||
procedure TChartListbox.DrawItem(
|
||||
AIndex: Integer; ARect: TRect; AState: TOwnerDrawState);
|
||||
{ draws the listbox item }
|
||||
const
|
||||
UNTHEMED_FLAGS: array [TCheckboxesStyle, Boolean] of Integer = (
|
||||
(DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED),
|
||||
(DFCS_BUTTONRADIO, DFCS_BUTTONRADIO or DFCS_CHECKED)
|
||||
);
|
||||
THEMED_FLAGS: array [TCheckboxesStyle, Boolean] of TThemedButton = (
|
||||
THEMED_BASE: array [TCheckboxesStyle, Boolean] of TThemedButton = (
|
||||
(tbCheckBoxUncheckedNormal, tbCheckBoxCheckedNormal),
|
||||
(tbRadioButtonUnCheckedNormal, tbRadioButtonCheckedNormal)
|
||||
);
|
||||
var
|
||||
id: IChartDrawer;
|
||||
rcb, ricon: TRect;
|
||||
te: TThemedElementDetails;
|
||||
x: Integer;
|
||||
ch: Boolean;
|
||||
tb: TThemedButton;
|
||||
tbBase, tbOffs: Integer;
|
||||
{$IFDEF USE_BITMAPS}
|
||||
bmp: TBitmap;
|
||||
{$ELSE}
|
||||
ted: TThemedElementDetails;
|
||||
{$ENDIF}
|
||||
begin
|
||||
if Assigned(OnDrawItem) then begin
|
||||
OnDrawItem(Self, AIndex, ARect, AState);
|
||||
exit;
|
||||
end;
|
||||
|
||||
if (FChart = nil) or not InRange(AIndex, 0, Count - 1) then
|
||||
exit;
|
||||
|
||||
Canvas.FillRect(ARect);
|
||||
if cloShowCheckboxes in Options then begin
|
||||
tbBase := ord(THEMED_BASE[FCheckStyle, Checked[AIndex]]);
|
||||
tbOffs := GetThemedButtonOffset(FHot, FDown, false);
|
||||
tb := TThemedButton(ord(tbBase) + tbOffs);
|
||||
{$IFDEF USE_BITMAPS}
|
||||
bmp := CreateBitmap(tb, Canvas.Brush.Color);
|
||||
FCheckboxSize := Size(bmp.Width, bmp.Height);
|
||||
{$ELSE}
|
||||
ted := ThemeServices.GetElementDetails(tb);
|
||||
FCheckboxSize := ThemeServices.GetDetailSize(ted);
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
CalcRects(ARect, rcb, ricon);
|
||||
|
||||
if cloShowCheckboxes in Options then begin
|
||||
ch := Checked[AIndex];
|
||||
if ThemeServices.ThemesEnabled then begin
|
||||
te := ThemeServices.GetElementDetails(THEMED_FLAGS[FCheckStyle, ch]);
|
||||
ThemeServices.DrawElement(Canvas.Handle, te, rcb);
|
||||
end
|
||||
else
|
||||
DrawFrameControl(
|
||||
Canvas.Handle, rcb, DFC_BUTTON, UNTHEMED_FLAGS[FCheckStyle, ch]);
|
||||
{$IFDEF USE_BITMAPS}
|
||||
Canvas.Draw(rcb.Left, rcb.Top, bmp);
|
||||
{$ELSE}
|
||||
ThemeServices.DrawElement(Canvas.Handle, ted, rcb);
|
||||
{$ENDIF}
|
||||
x := rcb.Right;
|
||||
end
|
||||
else
|
||||
@ -426,8 +498,6 @@ begin
|
||||
AHeight := Max(AHeight, GetSystemMetrics(SM_CYMENUCHECK) + 2);
|
||||
end;
|
||||
|
||||
procedure TChartListbox.MouseDown(
|
||||
AButton: TMouseButton; AShift: TShiftState; AX, AY: Integer);
|
||||
{ standard MouseDown handler: checks if the click occured on the checkbox,
|
||||
on the series icon, or on the text.
|
||||
The visibility state of the item's series is changed when clicking on the
|
||||
@ -437,11 +507,14 @@ procedure TChartListbox.MouseDown(
|
||||
An event OnItemClick is generated when the click occured neither on the
|
||||
checkbox nor the series icon.
|
||||
}
|
||||
procedure TChartListbox.MouseDown(
|
||||
AButton: TMouseButton; AShift: TShiftState; AX, AY: Integer);
|
||||
var
|
||||
rcb, ricon: TRect;
|
||||
index: Integer;
|
||||
p: TPoint;
|
||||
begin
|
||||
FDown := true;
|
||||
FSeriesIconClicked := -1;
|
||||
try
|
||||
if AButton <> mbLeft then exit;
|
||||
@ -461,6 +534,24 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TChartListbox.MouseEnter;
|
||||
begin
|
||||
FHot := true;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TChartListbox.MouseLeave;
|
||||
begin
|
||||
FHot := false;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TChartListBox.MouseUp(
|
||||
AButton: TMouseButton; AShift: TShiftState; AX, AY: Integer);
|
||||
begin
|
||||
FDown := false;
|
||||
inherited;
|
||||
end;
|
||||
procedure TChartListbox.Notification(AComponent: TComponent; AOperation: TOperation);
|
||||
begin
|
||||
if (AOperation = opRemove) and (AComponent = FChart) then
|
||||
@ -610,5 +701,18 @@ begin
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
procedure Register;
|
||||
begin
|
||||
RegisterComponents(CHART_COMPONENT_IDE_PAGE, [TChartListbox]);
|
||||
end;
|
||||
|
||||
{$IFDEF USE_BITMAPS}
|
||||
initialization
|
||||
InitBitmaps;
|
||||
|
||||
finalization
|
||||
FreeBitmaps;
|
||||
{$ENDIF}
|
||||
|
||||
end.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user