spktoolbar: Fix dropdown arrows in Linux

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6162 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz 2018-01-31 21:44:46 +00:00
parent f1bb94b862
commit dcc90b77e4
4 changed files with 84 additions and 51 deletions

View File

@ -526,8 +526,6 @@ begin
end; end;
constructor TSpkToolbar.Create(AOwner: TComponent); constructor TSpkToolbar.Create(AOwner: TComponent);
var
DesignDPI: Integer;
begin begin
inherited Create(AOwner); inherited Create(AOwner);
@ -1812,7 +1810,7 @@ begin
LargeButtonMinWidth := round(LARGEBUTTON_MIN_WIDTH * AXProportion); LargeButtonMinWidth := round(LARGEBUTTON_MIN_WIDTH * AXProportion);
LargeButtonRadius := LARGEBUTTON_RADIUS; LargeButtonRadius := LARGEBUTTON_RADIUS;
LargeButtonBorderSize := round(LARGEBUTTON_BORDER_SIZE * AXProportion); LargeButtonBorderSize := round(LARGEBUTTON_BORDER_SIZE * AXProportion);
LargeButtonChevronHMargin := round(LARGEBUTTON_CHEVRON_HMARGIN * AXProportion); LargeButtonChevronVMargin := round(LARGEBUTTON_CHEVRON_VMARGIN * AYProportion);
LargeButtonCaptionTopRail := round(LARGEBUTTON_CAPTION_TOP_RAIL * AYProportion); LargeButtonCaptionTopRail := round(LARGEBUTTON_CAPTION_TOP_RAIL * AYProportion);
LargeButtonCaptionButtomRail := round(LARGEBUTTON_CAPTION_BOTTOM_RAIL * AYProportion); LargeButtonCaptionButtomRail := round(LARGEBUTTON_CAPTION_BOTTOM_RAIL * AYProportion);

View File

@ -16,7 +16,7 @@ unit spkt_Buttons;
interface interface
uses uses
Graphics, Classes, Controls, Menus, ActnList, Math, Graphics, Classes, Types, Controls, Menus, ActnList, Math,
Dialogs, ImgList, Forms, Dialogs, ImgList, Forms,
SpkGUITools, SpkGraphTools, SpkMath, SpkGUITools, SpkGraphTools, SpkMath,
spkt_Const, spkt_BaseItem, spkt_Exceptions, spkt_Tools; spkt_Const, spkt_BaseItem, spkt_Exceptions, spkt_Tools;
@ -84,13 +84,13 @@ type
FAllowAllUp: Boolean; FAllowAllUp: Boolean;
FDropdownMenu: TPopupMenu; FDropdownMenu: TPopupMenu;
// *** Obs³uga rysowania *** // *** Drawing support ***
/// <summary>Zadaniem metody w odziedziczonych klasach jest obliczenie // The task of the method in inherited classes is to calculate the
/// rectów przycisku i menu dropdown w zale¿noœci od FButtonState</summary> // button's rectangle and the dropdown menu depending on FButtonState
procedure CalcRects; virtual; abstract; procedure CalcRects; virtual; abstract;
function GetDropdownPoint: T2DIntPoint; virtual; abstract; function GetDropdownPoint: T2DIntPoint; virtual; abstract;
// *** Obs³uga akcji *** // *** Action support ***
procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); virtual; procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); virtual;
procedure Click; virtual; procedure Click; virtual;
procedure DoActionChange(Sender: TObject); procedure DoActionChange(Sender: TObject);
@ -99,6 +99,8 @@ type
function SiblingsChecked: Boolean; virtual; function SiblingsChecked: Boolean; virtual;
procedure UncheckSiblings; virtual; procedure UncheckSiblings; virtual;
procedure DrawDropdownArrow(ABuffer: TBitmap; ARect: TRect; AColor: TColor);
// Getters and Setters // Getters and Setters
function GetChecked: Boolean; virtual; function GetChecked: Boolean; virtual;
procedure SetAction(const Value: TBasicAction); virtual; procedure SetAction(const Value: TBasicAction); virtual;
@ -201,7 +203,9 @@ type
implementation implementation
uses uses
LCLType, LCLIntf, LCLProc, SysUtils, spkt_Pane, spkt_Appearance; LCLType, LCLIntf, LCLProc, SysUtils, Themes,
spkt_Pane, spkt_Appearance;
{ TSpkButtonActionLink } { TSpkButtonActionLink }
@ -374,6 +378,38 @@ begin
ActionChange(Sender, False); ActionChange(Sender, False);
end; end;
procedure TSpkBaseButton.DrawDropdownArrow(ABuffer: TBitmap; ARect: TRect;
AColor: TColor);
const
w = 8;
h = 8;
var
details: TThemedElementDetails;
arrowState: TThemedToolBar;
P: array[0..3] of TPoint;
wsc, hsc: Integer;
begin
if ThemeServices.ThemesEnabled then begin
if Enabled then
arrowState := ttbSplitButtonDropdownNormal
else
arrowState := ttbSplitButtonDropDownDisabled;
details := ThemeServices.GetElementDetails(arrowState);
ThemeServices.DrawElement(ABuffer.Canvas.Handle, details, ARect);
end else begin
wsc := ScaleX(w, DesignDPI); // 0 1
hsc := ScaleY(h, DesignDPI); // 2
P[2].x := ARect.Left + (ARect.Right - ARect.Left) div 2;
P[2].y := ARect.Top + (ARect.Bottom - ARect.Top + hsc) div 2 - 1;
P[0] := Point(P[2].x - wsc div 2, P[2].y - hsc div 2);
P[1] := Point(P[2].x + wsc div 2, P[0].y);
P[3] := P[0];
ABuffer.Canvas.Brush.Color := AColor;
ABuffer.Canvas.Pen.Style := psClear;
ABuffer.Canvas.Polygon(P);
end;
end;
function TSpkBaseButton.GetAction: TBasicAction; function TSpkBaseButton.GetAction: TBasicAction;
begin begin
if Assigned(FActionLink) then if Assigned(FActionLink) then
@ -908,6 +944,7 @@ var
s: String; s: String;
P: T2DIntPoint; P: T2DIntPoint;
drawBtn: Boolean; drawBtn: Boolean;
R: TRect;
begin begin
if FToolbarDispatch = nil then if FToolbarDispatch = nil then
exit; exit;
@ -1102,29 +1139,24 @@ begin
TGUITools.DrawText(ABuffer.Canvas, x, y, s, fontColor, ClipRect); TGUITools.DrawText(ABuffer.Canvas, x, y, s, fontColor, ClipRect);
end else end else
begin begin
// Tekst nie z³amany // The text is not broken
x := FButtonRect.Left + (FButtonRect.Width - ABuffer.Canvas.Textwidth(FCaption)) div 2; x := FButtonRect.Left + (FButtonRect.Width - ABuffer.Canvas.Textwidth(FCaption)) div 2;
y := FRect.Top + LargeButtonCaptionTopRail - txtHeight div 2; y := FRect.Top + LargeButtonCaptionTopRail - txtHeight div 2;
TGUITools.DrawText(ABuffer.Canvas, x, y, FCaption, FontColor, ClipRect); TGUITools.DrawText(ABuffer.Canvas, x, y, FCaption, FontColor, ClipRect);
end; end;
// Chevron // Dropdown arrow
ABuffer.Canvas.Font.Charset := DEFAULT_CHARSET;
ABuffer.Canvas.Font.Name := 'Marlett';
ABuffer.Canvas.Font.Style := [];
ABuffer.Canvas.Font.Orientation := 0;
if FButtonKind = bkDropdown then if FButtonKind = bkDropdown then
begin begin
x := FButtonRect.Left + (FButtonRect.width - ABuffer.Canvas.Textwidth('u')) div 2; y := FButtonRect.Bottom - ABuffer.Canvas.TextHeight('Tg') - 1;
y := FButtonRect.bottom - ABuffer.Canvas.Textheight('u') - LargeButtonChevronHMargin; R := Classes.Rect(FButtonRect.Left, y, FButtonRect.Right, FButtonRect.Bottom);
TGUITools.DrawText(ABuffer.Canvas, x, y, 'u', FontColor, ClipRect); DrawDropdownArrow(ABuffer, R, fontcolor);
end else end else
if FButtonKind = bkButtonDropdown then if FButtonKind = bkButtonDropdown then
begin begin
x := FDropdownRect.Left + (FDropdownRect.width - ABuffer.Canvas.Textwidth('u')) div 2; y := FDropdownRect.Bottom - ABuffer.Canvas.TextHeight('Tg') - 1;
y := FDropdownRect.bottom - ABuffer.Canvas.Textheight('u') - LargeButtonChevronHMargin; R := Classes.Rect(FDropdownRect.Left, y, FDropDownRect.Right, FDropdownRect.Bottom);
TGUITools.DrawText(ABuffer.Canvas, x, y, 'u', FontColor, ClipRect); DrawDropdownArrow(ABuffer, R, fontcolor);
end; end;
end; end;
@ -1427,6 +1459,8 @@ var
cornerRadius: Integer; cornerRadius: Integer;
imgList: TImageList; imgList: TImageList;
drawBtn: Boolean; drawBtn: Boolean;
R: TRect;
dx: Integer;
begin begin
if (FToolbarDispatch = nil) or (FAppearance = nil) then if (FToolbarDispatch = nil) or (FAppearance = nil) then
exit; exit;
@ -1608,29 +1642,18 @@ begin
end; end;
end; end;
// Chevron // Dropdown arrow
ABuffer.Canvas.Font.Charset := DEFAULT_CHARSET; if FButtonKind in [bkDropdown, bkButtonDropdown] then begin
ABuffer.Canvas.Font.Name := 'Marlett'; dx := SmallButtonDropdownWidth;
ABuffer.Canvas.Font.Style := []; if FGroupBehaviour in [gbBeginsGroup, gbContinuesGroup] then
ABuffer.Canvas.Font.Orientation := 0; inc(dx, SmallButtonHalfBorderWidth)
else
inc(dx, SmallButtonBorderWidth);
if FButtonKind = bkDropdown then if FButtonKind = bkDropdown then
begin R := Classes.Rect(FButtonRect.Right-dx, FButtonRect.Top, FButtonRect.Right, FButtonRect.Bottom)
if FGroupBehaviour in [gbBeginsGroup, gbContinuesGroup] then
x := FButtonRect.Right - SmallButtonHalfBorderWidth - (SmallButtonDropdownWidth + ABuffer.Canvas.Textwidth('u')) div 2 + 1
else else
x := FButtonRect.Right - SmallButtonBorderWidth - (SmallButtonDropdownWidth + ABuffer.Canvas.Textwidth('u')) div 2 + 1; R := Classes.Rect(FDropdownRect.Right-dx, FDropdownRect.Top, FDropdownRect.Right, FDropdownRect.Bottom);
y := FButtonRect.top + (FButtonRect.height - ABuffer.Canvas.Textheight('u')) div 2; DrawdropdownArrow(ABuffer, R, fontcolor);
TGUITools.DrawText(ABuffer.Canvas, x, y, 'u', fontColor, ClipRect);
end else
if FButtonKind = bkButtonDropdown then
begin
if FGroupBehaviour in [gbBeginsGroup, gbContinuesGroup] then
x := FDropdownRect.Right - SmallButtonHalfBorderWidth - (SmallButtonDropdownWidth + ABuffer.Canvas.Textwidth('u')) div 2 + 1
else
x := FDropdownRect.Right - SmallButtonBorderWidth - (SmallButtonDropdownWidth + ABuffer.Canvas.Textwidth('u')) div 2 + 1;
y := FDropdownRect.top + (FDropdownRect.Height - ABuffer.Canvas.Textheight('u')) div 2;
TGUITools.DrawText(ABuffer.Canvas, x, y, 'u', FontColor, ClipRect);
end; end;
end; end;

View File

@ -24,6 +24,9 @@ const
DPI_AWARE = false; // use lcl scaling instead DPI_AWARE = false; // use lcl scaling instead
{$ENDIF} {$ENDIF}
var
DesignDPI: Integer;
procedure SpkInitLayoutConsts(FromDPI: Integer; ToDPI: Integer = 0); procedure SpkInitLayoutConsts(FromDPI: Integer; ToDPI: Integer = 0);
function SpkScaleX(Size: Integer; FromDPI: Integer; ToDPI: Integer = 0): integer; function SpkScaleX(Size: Integer; FromDPI: Integer; ToDPI: Integer = 0): integer;
function SpkScaleY(Size: Integer; FromDPI: Integer; ToDPI: Integer = 0): integer; function SpkScaleY(Size: Integer; FromDPI: Integer; ToDPI: Integer = 0): integer;
@ -39,7 +42,7 @@ const
LARGEBUTTON_MIN_WIDTH = 24; LARGEBUTTON_MIN_WIDTH = 24;
LARGEBUTTON_RADIUS = 4; LARGEBUTTON_RADIUS = 4;
LARGEBUTTON_BORDER_SIZE = 2; LARGEBUTTON_BORDER_SIZE = 2;
LARGEBUTTON_CHEVRON_HMARGIN = 4; LARGEBUTTON_CHEVRON_VMARGIN = 2;
LARGEBUTTON_CAPTION_TOP_RAIL = 45; LARGEBUTTON_CAPTION_TOP_RAIL = 45;
LARGEBUTTON_CAPTION_BOTTOM_RAIL = 58; LARGEBUTTON_CAPTION_BOTTOM_RAIL = 58;
@ -151,7 +154,7 @@ var
LargeButtonMinWidth: Integer; LargeButtonMinWidth: Integer;
LargeButtonRadius: Integer; LargeButtonRadius: Integer;
LargeButtonBorderSize: Integer; LargeButtonBorderSize: Integer;
LargeButtonChevronHMargin: Integer; LargeButtonChevronVMargin: Integer;
LargeButtonCaptionTopRail: Integer; LargeButtonCaptionTopRail: Integer;
LargeButtonCaptionButtomRail: Integer; LargeButtonCaptionButtomRail: Integer;
@ -268,9 +271,12 @@ var
implementation implementation
uses uses
LCLType; LCLType, Types, Themes;
procedure SpkInitLayoutConsts(FromDPI: Integer; ToDPI: Integer = 0); procedure SpkInitLayoutConsts(FromDPI: Integer; ToDPI: Integer = 0);
var
detail: TThemedElementDetails;
detailSize: TSize;
begin begin
if not DPI_AWARE then if not DPI_AWARE then
ToDPI := FromDPI; ToDPI := FromDPI;
@ -285,7 +291,7 @@ begin
LargeButtonMinWidth := SpkScaleX(LARGEBUTTON_MIN_WIDTH, FromDPI, ToDPI); LargeButtonMinWidth := SpkScaleX(LARGEBUTTON_MIN_WIDTH, FromDPI, ToDPI);
LargeButtonRadius := LARGEBUTTON_RADIUS; LargeButtonRadius := LARGEBUTTON_RADIUS;
LargeButtonBorderSize := SpkScaleX(LARGEBUTTON_BORDER_SIZE, FromDPI, ToDPI); LargeButtonBorderSize := SpkScaleX(LARGEBUTTON_BORDER_SIZE, FromDPI, ToDPI);
LargeButtonChevronHMargin := SpkScaleX(LARGEBUTTON_CHEVRON_HMARGIN, FromDPI, ToDPI); LargeButtonChevronVMargin := SpkScaleY(LARGEBUTTON_CHEVRON_VMARGIN, FromDPI, ToDPI);
LargeButtonCaptionTopRail := SpkScaleY(LARGEBUTTON_CAPTION_TOP_RAIL, FromDPI, ToDPI); LargeButtonCaptionTopRail := SpkScaleY(LARGEBUTTON_CAPTION_TOP_RAIL, FromDPI, ToDPI);
LargeButtonCaptionButtomRail := SpkScaleY(LARGEBUTTON_CAPTION_BOTTOM_RAIL, FromDPI, ToDPI); LargeButtonCaptionButtomRail := SpkScaleY(LARGEBUTTON_CAPTION_BOTTOM_RAIL, FromDPI, ToDPI);
@ -297,6 +303,12 @@ begin
SmallButtonRadius := SMALLBUTTON_RADIUS; SmallButtonRadius := SMALLBUTTON_RADIUS;
SmallButtonMinWidth := 2 * SmallButtonPadding + SmallButtonGlyphWidth; SmallButtonMinWidth := 2 * SmallButtonPadding + SmallButtonGlyphWidth;
// Make sure that dropdown button is not too narrow
detail := ThemeServices.GetElementDetails(ttbSplitButtonDropDownNormal);
detailsize := ThemeServices.GetDetailSize(detail);
if SmallButtonDropdownWidth < detailSize.CX then
SmallButtondropdownWidth := detailSize.CX;
MaxElementHeight := SpkScaleY(MAX_ELEMENT_HEIGHT, FromDPI, ToDPI); MaxElementHeight := SpkScaleY(MAX_ELEMENT_HEIGHT, FromDPI, ToDPI);
PaneRowHeight := SpkScaleY(PANE_ROW_HEIGHT, FromDPI, ToDPI); PaneRowHeight := SpkScaleY(PANE_ROW_HEIGHT, FromDPI, ToDPI);
PaneFullRowHeight := 3 * PaneRowHeight; PaneFullRowHeight := 3 * PaneRowHeight;

View File

@ -5,8 +5,8 @@ unit spkt_Tools;
(******************************************************************************* (*******************************************************************************
* * * *
* Plik: spkt_Tools.pas * * Unit: spkt_Tools.pas *
* Opis: Klasy narzêdziowe u³atwiaj¹ce renderowanie toolbara. * * Description: Tool classes for easier rendering of the toolbar. *
* Copyright: (c) 2009 by Spook. * * Copyright: (c) 2009 by Spook. *
* License: Modified LGPL (with linking exception, like Lazarus LCL) * * License: Modified LGPL (with linking exception, like Lazarus LCL) *
' See "license.txt" in this installation * ' See "license.txt" in this installation *