100 lines
3.1 KiB
ObjectPascal
100 lines
3.1 KiB
ObjectPascal
unit BidiUtils;
|
|
|
|
{
|
|
Inno Setup
|
|
Copyright (C) 1997-2024 Jordan Russell
|
|
Portions by Martijn Laan
|
|
For conditions of distribution and use, see LICENSE.TXT.
|
|
|
|
Bidi utility functions
|
|
}
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, SysUtils, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
|
|
|
|
procedure FlipControls(const AParentCtl: TWinControl);
|
|
procedure FlipRect(var Rect: TRect; const ParentRect: TRect; const UseRightToLeft: Boolean);
|
|
function IsParentFlipped(const AControl: TControl): Boolean;
|
|
function IsParentRightToLeft(const AControl: TControl): Boolean;
|
|
function SetBiDiStyles(const AControl: TControl; var AParams: TCreateParams): Boolean;
|
|
|
|
var
|
|
{ These two callbacks should be set by the caller. Inno Setup: set by the Setup.SetupForm unit: }
|
|
IsParentFlippedFunc: function(AControl: TControl): Boolean;
|
|
IsParentRightToLeftFunc: function(AControl: TControl): Boolean;
|
|
|
|
implementation
|
|
|
|
procedure FlipRect(var Rect: TRect; const ParentRect: TRect; const UseRightToLeft: Boolean);
|
|
var
|
|
W: Integer;
|
|
begin
|
|
if UseRightToLeft then begin
|
|
W := Rect.Right - Rect.Left;
|
|
Rect.Left := ParentRect.Right - (Rect.Left - ParentRect.Left) - W;
|
|
Rect.Right := Rect.Left + W;
|
|
end;
|
|
end;
|
|
|
|
function IsParentFlipped(const AControl: TControl): Boolean;
|
|
begin
|
|
if Assigned(IsParentFlippedFunc) then
|
|
Result := IsParentFlippedFunc(AControl)
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
function IsParentRightToLeft(const AControl: TControl): Boolean;
|
|
begin
|
|
if Assigned(IsParentRightToLeftFunc) then
|
|
Result := IsParentRightToLeftFunc(AControl)
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
function SetBiDiStyles(const AControl: TControl; var AParams: TCreateParams): Boolean;
|
|
begin
|
|
Result := IsParentRightToLeft(AControl);
|
|
if Result then
|
|
AParams.ExStyle := AParams.ExStyle or (WS_EX_RTLREADING or WS_EX_LEFTSCROLLBAR or WS_EX_RIGHT);
|
|
end;
|
|
|
|
type
|
|
TControlAccess = class(TControl);
|
|
|
|
procedure FlipControls(const AParentCtl: TWinControl);
|
|
var
|
|
ParentWidth, I: Integer;
|
|
Ctl: TControl;
|
|
begin
|
|
if AParentCtl.ControlCount = 0 then
|
|
Exit;
|
|
AParentCtl.DisableAlign;
|
|
try
|
|
ParentWidth := AParentCtl.ClientWidth;
|
|
for I := 0 to AParentCtl.ControlCount-1 do begin
|
|
Ctl := AParentCtl.Controls[I];
|
|
if (akLeft in Ctl.Anchors) and not (akRight in Ctl.Anchors) then
|
|
Ctl.Anchors := Ctl.Anchors - [akLeft] + [akRight]
|
|
else if not (akLeft in Ctl.Anchors) and (akRight in Ctl.Anchors) then begin
|
|
{ Before we can set Anchors to [akLeft, akTop] (which has a special
|
|
'no anchors' meaning to VCL), we first need to update the Explicit*
|
|
properties so the control doesn't get moved back to an old position. }
|
|
if Ctl.Anchors = [akTop, akRight] then
|
|
TControlAccess(Ctl).UpdateExplicitBounds;
|
|
Ctl.Anchors := Ctl.Anchors - [akRight] + [akLeft];
|
|
end;
|
|
Ctl.Left := ParentWidth - Ctl.Width - Ctl.Left;
|
|
end;
|
|
finally
|
|
AParentCtl.EnableAlign;
|
|
end;
|
|
for I := 0 to AParentCtl.ControlCount-1 do
|
|
if AParentCtl.Controls[I] is TWinControl then
|
|
FlipControls(TWinControl(AParentCtl.Controls[I]));
|
|
end;
|
|
|
|
end.
|