SpkToolbar: Support RTL layout of buttons within panes.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8956 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2023-10-13 09:33:12 +00:00
parent d3bbef0991
commit 2ff41ccea4
2 changed files with 95 additions and 24 deletions

View File

@ -1807,7 +1807,7 @@ begin
fontColor := TColorTools.ColorToGrayscale(fontColor); fontColor := TColorTools.ColorToGrayscale(fontColor);
// Text // Text
if FShowCaption then if FShowCaption and (FCaption <> '') then
begin begin
ABuffer.Canvas.Font.Assign(FAppearance.Element.CaptionFont); ABuffer.Canvas.Font.Assign(FAppearance.Element.CaptionFont);
ABuffer.Canvas.Font.Color := fontColor; ABuffer.Canvas.Font.Color := fontColor;

View File

@ -74,6 +74,7 @@ type
// *** Generating a layout of elements *** // *** Generating a layout of elements ***
function GenerateLayout: TSpkPaneItemsLayout; function GenerateLayout: TSpkPaneItemsLayout;
function IsRightToLeft: Boolean;
// *** Designtime and LFM support *** // *** Designtime and LFM support ***
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
@ -100,6 +101,8 @@ type
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
destructor Destroy; override; destructor Destroy; override;
function GetRootComponent: TComponent;
// *** Mouse support *** // *** Mouse support ***
procedure MouseLeave; procedure MouseLeave;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
@ -645,11 +648,13 @@ var
ItemSize: TSpkItemSize; ItemSize: TSpkItemSize;
ForceNewColumn: boolean; ForceNewColumn: boolean;
LastX: integer; LastX: integer;
MaxRowX: integer; EndRowX: integer;
ColumnX: integer; ColumnX: integer;
rows: Integer; rows: Integer;
sgn: Integer;
ItemWidth: Integer; ItemWidth: Integer;
tmpRect: T2DIntRect; tmpRect: T2DIntRect;
isRTL: Boolean;
begin begin
Result.Rects := Default(T2DIntRectArray); Result.Rects := Default(T2DIntRectArray);
@ -659,6 +664,9 @@ begin
if FItems.Count = 0 then if FItems.Count = 0 then
exit; exit;
isRTL := IsRightToLeft;
sgn := IfThen(isRTL, -1, +1);
// Note: the algorithm is structured in such a way that three of them, // Note: the algorithm is structured in such a way that three of them,
// CurrentColumn, CurrentRow and CurrentItem, point to an element that // CurrentColumn, CurrentRow and CurrentItem, point to an element that
// is not yet present (just after the recently added element). // is not yet present (just after the recently added element).
@ -735,19 +743,19 @@ begin
Result.Rects[i].Create(-1, -1, -1, -1); Result.Rects[i].Create(-1, -1, -1, -1);
{$ENDIF} {$ENDIF}
MaxRowX := 0; EndRowX := 0;
// Now, we iterate through the layout, fixing the recit. // Now, we iterate through the layout, fixing the recit.
for c := 0 to High(Layout) do for c := 0 to High(Layout) do
begin begin
if c>0 then if c>0 then
begin begin
LastX := MaxRowX + PaneColumnSpacer; LastX := EndRowX + sgn * PaneColumnSpacer;
MaxRowX := LastX; EndRowX := LastX;
end end
else else
begin begin
LastX := MaxRowX; LastX := EndRowX;
end; end;
ColumnX := LastX; ColumnX := LastX;
@ -767,30 +775,56 @@ begin
begin begin
tmpRect.Top := PaneFullRowTopPadding; tmpRect.Top := PaneFullRowTopPadding;
tmpRect.Bottom := tmpRect.Top + PaneFullRowHeight - 1; tmpRect.Bottom := tmpRect.Top + PaneFullRowHeight - 1;
if isRTL then
begin
tmpRect.Right := LastX;
tmpRect.Left := LastX - ItemWidth + 1;
LastX := tmpRect.Left - 1;
if lastX < EndRowX then
EndRowX := LastX;
end else
begin
tmpRect.Left := LastX; tmpRect.Left := LastX;
tmpRect.Right := LastX + ItemWidth - 1; tmpRect.Right := LastX + ItemWidth - 1;
LastX := tmpRect.Right + 1; LastX := tmpRect.Right + 1;
if LastX > MaxRowX then if LastX > EndRowX then
MaxRowX := LastX; EndRowX := LastX;
end;
end end
else else
begin begin
if ItemGroupBehaviour in [gbContinuesGroup, gbEndsGroup] then if ItemGroupBehaviour in [gbContinuesGroup, gbEndsGroup] then
begin
if isRTL then
begin
tmpRect.Right := LastX;
tmpRect.Left := tmpRect.Right - ItemWidth + 1;
end else
begin begin
tmpRect.Left := LastX; tmpRect.Left := LastX;
tmpRect.Right := tmpRect.Left + ItemWidth - 1; tmpRect.Right := tmpRect.Left + ItemWidth - 1;
end;
end end
else else
begin begin
// If the element is not the first one, it must be offset by // If the element is not the first one, it must be offset by
// the margin from the previous one // the margin from the previous one
if isRTL then
begin
if i > 0 then
tmpRect.Right := LastX - PaneGroupSpacer
else
tmpRect.Right := LastX;
tmpRect.Left := tmpRect.Right - ItemWidth + 1;
end else
begin
if i>0 then if i>0 then
tmpRect.Left := LastX + PaneGroupSpacer tmpRect.Left := LastX + PaneGroupSpacer
else else
tmpRect.Left := LastX; tmpRect.Left := LastX;
tmpRect.Right := tmpRect.Left + ItemWidth - 1; tmpRect.Right := tmpRect.Left + ItemWidth - 1;
end; end;
end;
{$REGION 'Calculation of tmpRect.top and bottom'} {$REGION 'Calculation of tmpRect.top and bottom'}
case rows of case rows of
@ -825,18 +859,37 @@ begin
end; end;
{$ENDREGION} {$ENDREGION}
if isRTL then
begin
LastX := tmpRect.Left - 1;
if LastX < EndRowX then
EndRowX := LastX;
end else
begin
LastX := tmpRect.right + 1; LastX := tmpRect.right + 1;
if LastX > MaxRowX then if LastX > EndRowX then
MaxRowX:=LastX; EndRowX := LastX;
end;
end; end;
Result.Rects[Layout[c][r][i]] := tmpRect; Result.Rects[Layout[c][r][i]] := tmpRect;
end; end;
end; end;
end; end;
// At this point, MaxRowX points to the first pixel behind the most
// At this point, EndRowX points to the first pixel behind the most
// right-hand element - ergo is equal to the width of the entire layout. // right-hand element - ergo is equal to the width of the entire layout.
Result.Width := MaxRowX; // (In case of Right-to-left EndRowX points to the first pixel BEFORE the
// most left-hand element)
Result.Width := abs(EndRowX);
// In case of RTL we must move the rects to the right of the pane;
// they have negative x coordinates so far.
if isRTL then
for c := 0 to High(Layout) do
for r := 0 to High(Layout[c]) do
for i := 0 to High(Layout[c, r]) do
Result.Rects[Layout[c,r,i]].Move(Result.Width, 0);
end; end;
procedure TSpkPane.GetChildren(Proc: TGetChildProc; Root: TComponent); procedure TSpkPane.GetChildren(Proc: TGetChildProc; Root: TComponent);
@ -848,6 +901,19 @@ begin
Proc(FItems.Items[i]); Proc(FItems.Items[i]);
end; end;
function TSpkPane.GetRootComponent: TComponent;
var
tab: TSpkBaseItem;
begin
Result := nil;
if Collection <> nil then
tab := TSpkBaseItem(Collection.RootComponent)
else
exit;
if (tab <> nil) and (tab.Collection <> nil) then
Result := tab.Collection.RootComponent;
end;
function TSpkPane.GetWidth: integer; function TSpkPane.GetWidth: integer;
var var
tmpBitmap: TBitmap; tmpBitmap: TBitmap;
@ -886,6 +952,11 @@ begin
Result := Max(PaneCaptionWidth, PaneElementsWidth); Result := Max(PaneCaptionWidth, PaneElementsWidth);
end; end;
function TSpkPane.IsRightToLeft: Boolean;
begin
Result := (GetRootComponent as TControl).IsRightToLeft;
end;
procedure TSpkPane.Loaded; procedure TSpkPane.Loaded;
begin begin
inherited; inherited;