View Issue Details

IDProjectCategoryView StatusLast Update
0012155LazarusLCLpublic2018-07-19 17:46
ReporterMartin FriebeAssigned ToBart Broersma 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version0.9.25 (SVN)Product Build 
Target VersionFixed in Version1.4 
Summary0012155: TEditButton aligns incorrect (glyph is not taken into account)
DescriptionIf TeditButton or any subclass (TFilenameEdit, TDirectoryEdit) uses align alBottom, top, right or alClient then the button is not taken into account for calculating the width.
The glyph will be outside the visible area

To Reproduce:
- put a TEditButton on a form (glyph is visible)
- set align := alBottom
=> glyph is outside the visible area, The Edit itself aligns with with the borders of parent.
Additional InformationOnly tested under Windows. Probably all widgetsets
TagsTEditButton
Fixed in Revisionr44623
LazTarget1.4
Widgetset
Attached Files
  • 0001-LCL-improvements-for-TEditButton-by-Flavio-Etrusco.patch (12,598 bytes)
    From d559aa13f7ef95bf92047441941c4adfc4a3d4d4 Mon Sep 17 00:00:00 2001
    From: juha <juha.manninen62@gmail.com>
    Date: Sat, 15 Mar 2014 15:41:01 +0200
    Subject: [PATCH] =?UTF-8?q?LCL:=20improvements=20for=20TEditButton=20by=20Fl?=
     =?UTF-8?q?=C3=A1vio=20Etrusco.=20Uses=20BorderSpacing=20to=20solve=20the=20?=
     =?UTF-8?q?alignment=20issues.?=
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    ---
     lcl/controls.pp |  139 ++++++++++++++++---------------------------------------
     lcl/editbtn.pas |   60 +++++++++++++++++++++++-
     2 files changed, 99 insertions(+), 100 deletions(-)
    
    diff --git a/lcl/controls.pp b/lcl/controls.pp
    index 6411868..3138730 100644
    --- a/lcl/controls.pp
    +++ b/lcl/controls.pp
    @@ -686,31 +686,21 @@ type
       TControlBorderSpacing = class(TPersistent)
       private
         FAround: TSpacingSize;
    -    FBottom: TSpacingSize;
         FCellAlignHorizontal: TControlCellAlign;
         FCellAlignVertical: TControlCellAlign;
         FControl: TControl;
         FInnerBorder: Integer;
    -    FLeft: TSpacingSize;
         FOnChange: TNotifyEvent;
    -    FRight: TSpacingSize;
    -    FTop: TSpacingSize;
    +    FSides: array [TAnchorKind] of TSpacingSize;
         FDefault: PControlBorderSpacingDefault;
         function IsAroundStored: boolean;
    -    function IsBottomStored: boolean;
         function IsInnerBorderStored: boolean;
    -    function IsLeftStored: boolean;
    -    function IsRightStored: boolean;
    -    function IsTopStored: boolean;
    +    function IsSideStored(Kind: TAnchorKind): boolean;
         procedure SetAround(const AValue: TSpacingSize);
    -    procedure SetBottom(const AValue: TSpacingSize);
         procedure SetCellAlignHorizontal(const AValue: TControlCellAlign);
         procedure SetCellAlignVertical(const AValue: TControlCellAlign);
         procedure SetInnerBorder(const AValue: Integer);
    -    procedure SetLeft(const AValue: TSpacingSize);
    -    procedure SetRight(const AValue: TSpacingSize);
         procedure SetSpace(Kind: TAnchorKind; const AValue: integer);
    -    procedure SetTop(const AValue: TSpacingSize);
       protected
         procedure Change(InnerSpaceChanged: Boolean); virtual;
       public
    @@ -718,18 +708,18 @@ type
         procedure Assign(Source: TPersistent); override;
         procedure AssignTo(Dest: TPersistent); override;
         function IsEqual(Spacing: TControlBorderSpacing): boolean;
    -    procedure GetSpaceAround(var SpaceAround: TRect);
    -    function GetSideSpace(Kind: TAnchorKind): Integer; // Around+GetSpace
    -    function GetSpace(Kind: TAnchorKind): Integer;
    +    procedure GetSpaceAround(out SpaceAround: TRect); virtual;
    +    function GetSideSpace(Kind: TAnchorKind): Integer; virtual; // Around+GetSpace
    +    function GetSpace(Kind: TAnchorKind): TSpacingSize;
       public
         property Control: TControl read FControl;
    -    property Space[Kind: TAnchorKind]: integer read GetSpace write SetSpace;
    +    property Space[Kind: TAnchorKind]: TSpacingSize read GetSpace write SetSpace;
       published
         property OnChange: TNotifyEvent read FOnChange write FOnChange;
    -    property Left: TSpacingSize read FLeft write SetLeft stored IsLeftStored;
    -    property Top: TSpacingSize read FTop write SetTop stored IsTopStored;
    -    property Right: TSpacingSize read FRight write SetRight stored IsRightStored;
    -    property Bottom: TSpacingSize read FBottom write SetBottom stored IsBottomStored;
    +    property Left: TSpacingSize index akLeft read FSides[akLeft] write SetSpace stored IsSideStored;
    +    property Top: TSpacingSize index akTop read FSides[akTop] write SetSpace stored IsSideStored;
    +    property Right: TSpacingSize index akRight read FSides[akRight] write SetSpace stored IsSideStored;
    +    property Bottom: TSpacingSize index akBottom read FSides[akBottom] write SetSpace stored IsSideStored;
         property Around: TSpacingSize read FAround write SetAround stored IsAroundStored;
         property InnerBorder: Integer read FInnerBorder write SetInnerBorder stored IsInnerBorderStored default 0;
         property CellAlignHorizontal: TControlCellAlign read FCellAlignHorizontal write SetCellAlignHorizontal default ccaFill;
    @@ -3256,13 +3246,6 @@ begin
       else Result := FAround <> FDefault^.Around;
     end;
     
    -function TControlBorderSpacing.IsBottomStored: boolean;
    -begin
    -  if FDefault = nil
    -  then Result := FBottom <> 0
    -  else Result := FBottom <> FDefault^.Bottom;
    -end;
    -
     function TControlBorderSpacing.IsInnerBorderStored: boolean;
     begin
       if Control <> nil then
    @@ -3271,32 +3254,21 @@ begin
         Result:=True;
     end;
     
    -function TControlBorderSpacing.IsLeftStored: boolean;
    -begin
    -  if FDefault = nil
    -  then Result := FLeft <> 0
    -  else Result := FLeft <> FDefault^.Left;
    -end;
    -
    -function TControlBorderSpacing.IsRightStored: boolean;
    -begin
    -  if FDefault = nil
    -  then Result := FRight <> 0
    -  else Result := FRight <> FDefault^.Right;
    -end;
    -
    -function TControlBorderSpacing.IsTopStored: boolean;
    +function TControlBorderSpacing.IsSideStored(Kind: TAnchorKind): boolean;
    +var
    +  DefaultValue: TSpacingSize;
     begin
       if FDefault = nil
    -  then Result := FTop <> 0
    -  else Result := FTop <> FDefault^.Top;
    -end;
    -
    -procedure TControlBorderSpacing.SetBottom(const AValue: TSpacingSize);
    -begin
    -  if FBottom=AValue then exit;
    -  FBottom:=AValue;
    -  Change(false);
    +  then Result := FSides[Kind] <> 0
    +  else begin
    +    case Kind of
    +      akLeft: DefaultValue := FDefault^.Left;
    +      akTop: DefaultValue := FDefault^.Top;
    +      akRight: DefaultValue := FDefault^.Right;
    +      akBottom: DefaultValue := FDefault^.Bottom;
    +    end;
    +    Result := FSides[Kind] <> DefaultValue;
    +  end;
     end;
     
     procedure TControlBorderSpacing.SetCellAlignHorizontal(
    @@ -3323,35 +3295,11 @@ begin
       Change(true);
     end;
     
    -procedure TControlBorderSpacing.SetLeft(const AValue: TSpacingSize);
    -begin
    -  if FLeft=AValue then exit;
    -  FLeft:=AValue;
    -  Change(false);
    -end;
    -
    -procedure TControlBorderSpacing.SetRight(const AValue: TSpacingSize);
    -begin
    -  if FRight=AValue then exit;
    -  FRight:=AValue;
    -  Change(false);
    -end;
    -
     procedure TControlBorderSpacing.SetSpace(Kind: TAnchorKind;
       const AValue: integer);
     begin
    -  case Kind of
    -  akLeft: Left:=AValue;
    -  akTop: Top:=AValue;
    -  akBottom: Bottom:=AValue;
    -  akRight: Right:=AValue;
    -  end;
    -end;
    -
    -procedure TControlBorderSpacing.SetTop(const AValue: TSpacingSize);
    -begin
    -  if FTop=AValue then exit;
    -  FTop:=AValue;
    +  if FSides[Kind]=AValue then exit;
    +  FSides[Kind]:=AValue;
       Change(false);
     end;
     
    @@ -3361,10 +3309,10 @@ begin
       FDefault := ADefault;
       if ADefault <> nil then
       begin
    -    FLeft := ADefault^.Left;
    -    FRight := ADefault^.Right;
    -    FTop := ADefault^.Top;
    -    FBottom := ADefault^.Bottom;
    +    FSides[akLeft] := ADefault^.Left;
    +    FSides[akRight] := ADefault^.Right;
    +    FSides[akTop] := ADefault^.Top;
    +    FSides[akBottom] := ADefault^.Bottom;
         FAround := ADefault^.Around;
       end;
       FCellAlignHorizontal := ccaFill;
    @@ -3381,15 +3329,15 @@ begin
         if IsEqual(SrcSpacing) then exit;
     
         FAround:=SrcSpacing.Around;
    -    FBottom:=SrcSpacing.Bottom;
    -    FLeft:=SrcSpacing.Left;
    -    FRight:=SrcSpacing.Right;
    -    FTop:=SrcSpacing.Top;
    +    FSides[akBottom]:=SrcSpacing.Bottom;
    +    FSides[akLeft]:=SrcSpacing.Left;
    +    FSides[akRight]:=SrcSpacing.Right;
    +    FSides[akTop]:=SrcSpacing.Top;
         FInnerBorder:=SrcSpacing.InnerBorder;
         FCellAlignHorizontal:=SrcSpacing.CellAlignHorizontal;
         FCellAlignVertical:=SrcSpacing.CellAlignVertical;
     
    -    Change(false);
    +    Change(True);
       end else
         inherited Assign(Source);
     end;
    @@ -3403,13 +3351,13 @@ function TControlBorderSpacing.IsEqual(Spacing: TControlBorderSpacing
       ): boolean;
     begin
       Result:=(FAround=Spacing.Around)
    -      and (FBottom=Spacing.Bottom)
    -      and (FLeft=Spacing.Left)
    -      and (FRight=Spacing.Right)
    -      and (FTop=Spacing.Top);
    +      and (Bottom=Spacing.Bottom)
    +      and (Left=Spacing.Left)
    +      and (Right=Spacing.Right)
    +      and (Top=Spacing.Top);
     end;
     
    -procedure TControlBorderSpacing.GetSpaceAround(var SpaceAround: TRect);
    +procedure TControlBorderSpacing.GetSpaceAround(out SpaceAround: TRect);
     begin
       SpaceAround.Left:=Left+Around;
       SpaceAround.Top:=Top+Around;
    @@ -3423,14 +3371,9 @@ begin
       Result:=Around+GetSpace(Kind);
     end;
     
    -function TControlBorderSpacing.GetSpace(Kind: TAnchorKind): Integer;
    +function TControlBorderSpacing.GetSpace(Kind: TAnchorKind): TSpacingSize;
     begin
    -  case Kind of
    -  akLeft: Result:=Left;
    -  akTop: Result:=Top;
    -  akRight: Result:=Right;
    -  akBottom: Result:=Bottom;
    -  end;
    +  Result:=FSides[Kind];
     end;
     
     procedure TControlBorderSpacing.Change(InnerSpaceChanged: Boolean);
    diff --git a/lcl/editbtn.pas b/lcl/editbtn.pas
    index e927212..bfcce1f 100644
    --- a/lcl/editbtn.pas
    +++ b/lcl/editbtn.pas
    @@ -63,6 +63,7 @@ type
         procedure CheckButtonVisible;
         function CalcButtonVisible: boolean; virtual;
         function CalcButtonEnabled: Boolean; virtual;
    +    function CreateControlBorderSpacing: TControlBorderSpacing; override;
         function GetReadOnly: Boolean; override;
         function GetDefaultGlyph: TBitmap; virtual;
         function GetDefaultGlyphName: String; virtual;
    @@ -72,6 +73,7 @@ type
         procedure DoButtonClick (Sender: TObject); virtual;
         procedure Loaded; override;
         procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    +    procedure DoOnChangeBounds; override;
         procedure CMVisibleChanged(var Msg: TLMessage); message CM_VISIBLECHANGED;
         procedure CMEnabledChanged(var Msg: TLMessage); message CM_ENABLEDCHANGED;
         procedure CMBiDiModeChanged(var Message: TLMessage); message CM_BIDIMODECHANGED;
    @@ -86,10 +88,20 @@ type
       public
         constructor Create(AOwner: TComponent); override;
         destructor Destroy; override;
    +    function ChildClassAllowed(ChildClass: TClass): boolean; override;
         property Flat: Boolean read GetFlat write SetFlat default False;
         property ButtonOnlyWhenFocused: Boolean read FButtonNeedsFocus write SetButtonNeedsFocus default False;
       end;
     
    +  { TEditButtonSpacing }
    +
    +  TEditButtonSpacing = class(TControlBorderSpacing)
    +  public
    +    constructor Create(OwnerControl: TCustomEditButton);
    +    procedure GetSpaceAround(out SpaceAround: TRect); override;
    +    function GetSideSpace(Kind: TAnchorKind): Integer; override;
    +  end;
    +
       { TEditButton }
     
       TEditButton = class(TCustomEditButton)
    @@ -659,6 +671,11 @@ begin
       inherited Destroy;
     end;
     
    +function TCustomEditButton.ChildClassAllowed(ChildClass: TClass): boolean;
    +begin
    +  Result := ChildClass = TSpeedButton;
    +end;
    +
     procedure TCustomEditButton.SetGlyph(Pic: TBitmap);
     Begin
       FButton.Glyph:=Pic;
    @@ -762,6 +779,12 @@ begin
         FButton := nil;
     end;
     
    +procedure TCustomEditButton.DoOnChangeBounds;
    +begin
    +  inherited;
    +  DoPositionButton;
    +end;
    +
     procedure TCustomEditButton.CMVisibleChanged(var Msg: TLMessage);
     begin
       inherited CMVisibleChanged(Msg);
    @@ -880,6 +903,11 @@ begin
       Result := not FIsReadOnly and Enabled;
     end;
     
    +function TCustomEditButton.CreateControlBorderSpacing: TControlBorderSpacing;
    +begin
    +  Result := TEditButtonSpacing.Create(Self);
    +end;
    +
     procedure TCustomEditButton.SetReadOnly(AValue: Boolean);
     begin
       FIsReadOnly := AValue;
    @@ -893,9 +921,9 @@ begin
       if FButton = nil then exit;
       FButton.Parent := Parent;
       if BiDiMode = bdLeftToRight then
    -    FButton.AnchorToCompanion(akLeft,0,Self)
    +    FButton.SetBounds(Left + Width, Top, Height, Height)
       else
    -    FButton.AnchorToCompanion(akRight,0,Self);
    +    FButton.SetBounds(0, Top, Height, Height);
     end;
     
     procedure TCustomEditButton.WMSetFocus(var Message: TLMSetFocus);
    @@ -904,6 +932,34 @@ begin
       inherited;
     end;
     
    +{ TEditButtonSpacing }
    +
    +constructor TEditButtonSpacing.Create(OwnerControl: TCustomEditButton);
    +begin
    +  inherited Create(OwnerControl);
    +end;
    +
    +procedure TEditButtonSpacing.GetSpaceAround(out SpaceAround: TRect);
    +begin
    +  inherited GetSpaceAround(SpaceAround);
    +  if Control.BiDiMode = bdLeftToRight then
    +    Inc(SpaceAround.Right, TCustomEditButton(Control).ButtonWidth)
    +  else
    +    Inc(SpaceAround.Left, TCustomEditButton(Control).ButtonWidth)
    +end;
    +
    +function TEditButtonSpacing.GetSideSpace(Kind: TAnchorKind): Integer;
    +begin
    +  Result := inherited GetSideSpace(Kind);
    +  if Kind = akRight then
    +  begin
    +    if Control.BiDiMode = bdLeftToRight then
    +      Inc(Result, TCustomEditButton(Control).ButtonWidth);
    +  end
    +  else if (Kind = akLeft) and (Control.BiDiMode <> bdLeftToRight) then
    +    Inc(Result, TCustomEditButton(Control).ButtonWidth);
    +end;
    +
     { TCustomControlFilterEdit }
     
     constructor TCustomControlFilterEdit.Create(AOwner: TComponent);
    -- 
    1.7.10.4
    
    

Relationships

has duplicate 0020502 resolvedVincent Snijders Width of TFileNameEdit, TDirectoryEdit 
has duplicate 0017349 closedBart Broersma TCustomEditButon SetAlign hide Button 
has duplicate 0020168 resolvedJuha Manninen TDateEdit has doesn't select calendar button is designer 
related to 0023029 closedBart Broersma Bad anchoring of TEditButton 

Activities

Graeme Geldenhuys

2009-05-23 10:11

reporter   ~0027886

I can confirm, I had the same problem with DirectoryEdit in the "Project Templates - Variables" dialog. Setting normal allignment settings doesn't take the associated button in account.

Even when selecting the DirectoryEdit in the form designer, the button part is not selected, only the editbox section is.

Flávio Etrusco (notifications not working)

2011-08-08 20:52

developer   ~0050619

Last edited: 2011-08-08 22:47

It doesn't seem too difficult to hack a fix using BorderSpacing, but I'd rather change the behavior and place the button inside the editbox...

Zeljan Rikalo

2011-10-28 09:29

developer   ~0053534

And for that we need TextMargins from WS.
Indeed.

Zeljan Rikalo

2012-02-11 20:10

developer   ~0056763

And I don't know how to fix it under gtk2.
If I add button inside GtkEntry it's not visible .. works fine with Qt.
Maybe gtk2 paints it after GtkEntry is painted so that could be real problem.

Mattias Gaertner

2012-06-18 23:59

manager   ~0060618

The best solution is to redesign TEditButton as an edit and a button in a panel. I started it as proof of concept in examples/groupedcontrols.
This will break all current workarounds, so it will not be done for 1.0.

Juha Manninen

2014-03-15 14:59

developer  

0001-LCL-improvements-for-TEditButton-by-Flavio-Etrusco.patch (12,598 bytes)
From d559aa13f7ef95bf92047441941c4adfc4a3d4d4 Mon Sep 17 00:00:00 2001
From: juha <juha.manninen62@gmail.com>
Date: Sat, 15 Mar 2014 15:41:01 +0200
Subject: [PATCH] =?UTF-8?q?LCL:=20improvements=20for=20TEditButton=20by=20Fl?=
 =?UTF-8?q?=C3=A1vio=20Etrusco.=20Uses=20BorderSpacing=20to=20solve=20the=20?=
 =?UTF-8?q?alignment=20issues.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lcl/controls.pp |  139 ++++++++++++++++---------------------------------------
 lcl/editbtn.pas |   60 +++++++++++++++++++++++-
 2 files changed, 99 insertions(+), 100 deletions(-)

diff --git a/lcl/controls.pp b/lcl/controls.pp
index 6411868..3138730 100644
--- a/lcl/controls.pp
+++ b/lcl/controls.pp
@@ -686,31 +686,21 @@ type
   TControlBorderSpacing = class(TPersistent)
   private
     FAround: TSpacingSize;
-    FBottom: TSpacingSize;
     FCellAlignHorizontal: TControlCellAlign;
     FCellAlignVertical: TControlCellAlign;
     FControl: TControl;
     FInnerBorder: Integer;
-    FLeft: TSpacingSize;
     FOnChange: TNotifyEvent;
-    FRight: TSpacingSize;
-    FTop: TSpacingSize;
+    FSides: array [TAnchorKind] of TSpacingSize;
     FDefault: PControlBorderSpacingDefault;
     function IsAroundStored: boolean;
-    function IsBottomStored: boolean;
     function IsInnerBorderStored: boolean;
-    function IsLeftStored: boolean;
-    function IsRightStored: boolean;
-    function IsTopStored: boolean;
+    function IsSideStored(Kind: TAnchorKind): boolean;
     procedure SetAround(const AValue: TSpacingSize);
-    procedure SetBottom(const AValue: TSpacingSize);
     procedure SetCellAlignHorizontal(const AValue: TControlCellAlign);
     procedure SetCellAlignVertical(const AValue: TControlCellAlign);
     procedure SetInnerBorder(const AValue: Integer);
-    procedure SetLeft(const AValue: TSpacingSize);
-    procedure SetRight(const AValue: TSpacingSize);
     procedure SetSpace(Kind: TAnchorKind; const AValue: integer);
-    procedure SetTop(const AValue: TSpacingSize);
   protected
     procedure Change(InnerSpaceChanged: Boolean); virtual;
   public
@@ -718,18 +708,18 @@ type
     procedure Assign(Source: TPersistent); override;
     procedure AssignTo(Dest: TPersistent); override;
     function IsEqual(Spacing: TControlBorderSpacing): boolean;
-    procedure GetSpaceAround(var SpaceAround: TRect);
-    function GetSideSpace(Kind: TAnchorKind): Integer; // Around+GetSpace
-    function GetSpace(Kind: TAnchorKind): Integer;
+    procedure GetSpaceAround(out SpaceAround: TRect); virtual;
+    function GetSideSpace(Kind: TAnchorKind): Integer; virtual; // Around+GetSpace
+    function GetSpace(Kind: TAnchorKind): TSpacingSize;
   public
     property Control: TControl read FControl;
-    property Space[Kind: TAnchorKind]: integer read GetSpace write SetSpace;
+    property Space[Kind: TAnchorKind]: TSpacingSize read GetSpace write SetSpace;
   published
     property OnChange: TNotifyEvent read FOnChange write FOnChange;
-    property Left: TSpacingSize read FLeft write SetLeft stored IsLeftStored;
-    property Top: TSpacingSize read FTop write SetTop stored IsTopStored;
-    property Right: TSpacingSize read FRight write SetRight stored IsRightStored;
-    property Bottom: TSpacingSize read FBottom write SetBottom stored IsBottomStored;
+    property Left: TSpacingSize index akLeft read FSides[akLeft] write SetSpace stored IsSideStored;
+    property Top: TSpacingSize index akTop read FSides[akTop] write SetSpace stored IsSideStored;
+    property Right: TSpacingSize index akRight read FSides[akRight] write SetSpace stored IsSideStored;
+    property Bottom: TSpacingSize index akBottom read FSides[akBottom] write SetSpace stored IsSideStored;
     property Around: TSpacingSize read FAround write SetAround stored IsAroundStored;
     property InnerBorder: Integer read FInnerBorder write SetInnerBorder stored IsInnerBorderStored default 0;
     property CellAlignHorizontal: TControlCellAlign read FCellAlignHorizontal write SetCellAlignHorizontal default ccaFill;
@@ -3256,13 +3246,6 @@ begin
   else Result := FAround <> FDefault^.Around;
 end;
 
-function TControlBorderSpacing.IsBottomStored: boolean;
-begin
-  if FDefault = nil
-  then Result := FBottom <> 0
-  else Result := FBottom <> FDefault^.Bottom;
-end;
-
 function TControlBorderSpacing.IsInnerBorderStored: boolean;
 begin
   if Control <> nil then
@@ -3271,32 +3254,21 @@ begin
     Result:=True;
 end;
 
-function TControlBorderSpacing.IsLeftStored: boolean;
-begin
-  if FDefault = nil
-  then Result := FLeft <> 0
-  else Result := FLeft <> FDefault^.Left;
-end;
-
-function TControlBorderSpacing.IsRightStored: boolean;
-begin
-  if FDefault = nil
-  then Result := FRight <> 0
-  else Result := FRight <> FDefault^.Right;
-end;
-
-function TControlBorderSpacing.IsTopStored: boolean;
+function TControlBorderSpacing.IsSideStored(Kind: TAnchorKind): boolean;
+var
+  DefaultValue: TSpacingSize;
 begin
   if FDefault = nil
-  then Result := FTop <> 0
-  else Result := FTop <> FDefault^.Top;
-end;
-
-procedure TControlBorderSpacing.SetBottom(const AValue: TSpacingSize);
-begin
-  if FBottom=AValue then exit;
-  FBottom:=AValue;
-  Change(false);
+  then Result := FSides[Kind] <> 0
+  else begin
+    case Kind of
+      akLeft: DefaultValue := FDefault^.Left;
+      akTop: DefaultValue := FDefault^.Top;
+      akRight: DefaultValue := FDefault^.Right;
+      akBottom: DefaultValue := FDefault^.Bottom;
+    end;
+    Result := FSides[Kind] <> DefaultValue;
+  end;
 end;
 
 procedure TControlBorderSpacing.SetCellAlignHorizontal(
@@ -3323,35 +3295,11 @@ begin
   Change(true);
 end;
 
-procedure TControlBorderSpacing.SetLeft(const AValue: TSpacingSize);
-begin
-  if FLeft=AValue then exit;
-  FLeft:=AValue;
-  Change(false);
-end;
-
-procedure TControlBorderSpacing.SetRight(const AValue: TSpacingSize);
-begin
-  if FRight=AValue then exit;
-  FRight:=AValue;
-  Change(false);
-end;
-
 procedure TControlBorderSpacing.SetSpace(Kind: TAnchorKind;
   const AValue: integer);
 begin
-  case Kind of
-  akLeft: Left:=AValue;
-  akTop: Top:=AValue;
-  akBottom: Bottom:=AValue;
-  akRight: Right:=AValue;
-  end;
-end;
-
-procedure TControlBorderSpacing.SetTop(const AValue: TSpacingSize);
-begin
-  if FTop=AValue then exit;
-  FTop:=AValue;
+  if FSides[Kind]=AValue then exit;
+  FSides[Kind]:=AValue;
   Change(false);
 end;
 
@@ -3361,10 +3309,10 @@ begin
   FDefault := ADefault;
   if ADefault <> nil then
   begin
-    FLeft := ADefault^.Left;
-    FRight := ADefault^.Right;
-    FTop := ADefault^.Top;
-    FBottom := ADefault^.Bottom;
+    FSides[akLeft] := ADefault^.Left;
+    FSides[akRight] := ADefault^.Right;
+    FSides[akTop] := ADefault^.Top;
+    FSides[akBottom] := ADefault^.Bottom;
     FAround := ADefault^.Around;
   end;
   FCellAlignHorizontal := ccaFill;
@@ -3381,15 +3329,15 @@ begin
     if IsEqual(SrcSpacing) then exit;
 
     FAround:=SrcSpacing.Around;
-    FBottom:=SrcSpacing.Bottom;
-    FLeft:=SrcSpacing.Left;
-    FRight:=SrcSpacing.Right;
-    FTop:=SrcSpacing.Top;
+    FSides[akBottom]:=SrcSpacing.Bottom;
+    FSides[akLeft]:=SrcSpacing.Left;
+    FSides[akRight]:=SrcSpacing.Right;
+    FSides[akTop]:=SrcSpacing.Top;
     FInnerBorder:=SrcSpacing.InnerBorder;
     FCellAlignHorizontal:=SrcSpacing.CellAlignHorizontal;
     FCellAlignVertical:=SrcSpacing.CellAlignVertical;
 
-    Change(false);
+    Change(True);
   end else
     inherited Assign(Source);
 end;
@@ -3403,13 +3351,13 @@ function TControlBorderSpacing.IsEqual(Spacing: TControlBorderSpacing
   ): boolean;
 begin
   Result:=(FAround=Spacing.Around)
-      and (FBottom=Spacing.Bottom)
-      and (FLeft=Spacing.Left)
-      and (FRight=Spacing.Right)
-      and (FTop=Spacing.Top);
+      and (Bottom=Spacing.Bottom)
+      and (Left=Spacing.Left)
+      and (Right=Spacing.Right)
+      and (Top=Spacing.Top);
 end;
 
-procedure TControlBorderSpacing.GetSpaceAround(var SpaceAround: TRect);
+procedure TControlBorderSpacing.GetSpaceAround(out SpaceAround: TRect);
 begin
   SpaceAround.Left:=Left+Around;
   SpaceAround.Top:=Top+Around;
@@ -3423,14 +3371,9 @@ begin
   Result:=Around+GetSpace(Kind);
 end;
 
-function TControlBorderSpacing.GetSpace(Kind: TAnchorKind): Integer;
+function TControlBorderSpacing.GetSpace(Kind: TAnchorKind): TSpacingSize;
 begin
-  case Kind of
-  akLeft: Result:=Left;
-  akTop: Result:=Top;
-  akRight: Result:=Right;
-  akBottom: Result:=Bottom;
-  end;
+  Result:=FSides[Kind];
 end;
 
 procedure TControlBorderSpacing.Change(InnerSpaceChanged: Boolean);
diff --git a/lcl/editbtn.pas b/lcl/editbtn.pas
index e927212..bfcce1f 100644
--- a/lcl/editbtn.pas
+++ b/lcl/editbtn.pas
@@ -63,6 +63,7 @@ type
     procedure CheckButtonVisible;
     function CalcButtonVisible: boolean; virtual;
     function CalcButtonEnabled: Boolean; virtual;
+    function CreateControlBorderSpacing: TControlBorderSpacing; override;
     function GetReadOnly: Boolean; override;
     function GetDefaultGlyph: TBitmap; virtual;
     function GetDefaultGlyphName: String; virtual;
@@ -72,6 +73,7 @@ type
     procedure DoButtonClick (Sender: TObject); virtual;
     procedure Loaded; override;
     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
+    procedure DoOnChangeBounds; override;
     procedure CMVisibleChanged(var Msg: TLMessage); message CM_VISIBLECHANGED;
     procedure CMEnabledChanged(var Msg: TLMessage); message CM_ENABLEDCHANGED;
     procedure CMBiDiModeChanged(var Message: TLMessage); message CM_BIDIMODECHANGED;
@@ -86,10 +88,20 @@ type
   public
     constructor Create(AOwner: TComponent); override;
     destructor Destroy; override;
+    function ChildClassAllowed(ChildClass: TClass): boolean; override;
     property Flat: Boolean read GetFlat write SetFlat default False;
     property ButtonOnlyWhenFocused: Boolean read FButtonNeedsFocus write SetButtonNeedsFocus default False;
   end;
 
+  { TEditButtonSpacing }
+
+  TEditButtonSpacing = class(TControlBorderSpacing)
+  public
+    constructor Create(OwnerControl: TCustomEditButton);
+    procedure GetSpaceAround(out SpaceAround: TRect); override;
+    function GetSideSpace(Kind: TAnchorKind): Integer; override;
+  end;
+
   { TEditButton }
 
   TEditButton = class(TCustomEditButton)
@@ -659,6 +671,11 @@ begin
   inherited Destroy;
 end;
 
+function TCustomEditButton.ChildClassAllowed(ChildClass: TClass): boolean;
+begin
+  Result := ChildClass = TSpeedButton;
+end;
+
 procedure TCustomEditButton.SetGlyph(Pic: TBitmap);
 Begin
   FButton.Glyph:=Pic;
@@ -762,6 +779,12 @@ begin
     FButton := nil;
 end;
 
+procedure TCustomEditButton.DoOnChangeBounds;
+begin
+  inherited;
+  DoPositionButton;
+end;
+
 procedure TCustomEditButton.CMVisibleChanged(var Msg: TLMessage);
 begin
   inherited CMVisibleChanged(Msg);
@@ -880,6 +903,11 @@ begin
   Result := not FIsReadOnly and Enabled;
 end;
 
+function TCustomEditButton.CreateControlBorderSpacing: TControlBorderSpacing;
+begin
+  Result := TEditButtonSpacing.Create(Self);
+end;
+
 procedure TCustomEditButton.SetReadOnly(AValue: Boolean);
 begin
   FIsReadOnly := AValue;
@@ -893,9 +921,9 @@ begin
   if FButton = nil then exit;
   FButton.Parent := Parent;
   if BiDiMode = bdLeftToRight then
-    FButton.AnchorToCompanion(akLeft,0,Self)
+    FButton.SetBounds(Left + Width, Top, Height, Height)
   else
-    FButton.AnchorToCompanion(akRight,0,Self);
+    FButton.SetBounds(0, Top, Height, Height);
 end;
 
 procedure TCustomEditButton.WMSetFocus(var Message: TLMSetFocus);
@@ -904,6 +932,34 @@ begin
   inherited;
 end;
 
+{ TEditButtonSpacing }
+
+constructor TEditButtonSpacing.Create(OwnerControl: TCustomEditButton);
+begin
+  inherited Create(OwnerControl);
+end;
+
+procedure TEditButtonSpacing.GetSpaceAround(out SpaceAround: TRect);
+begin
+  inherited GetSpaceAround(SpaceAround);
+  if Control.BiDiMode = bdLeftToRight then
+    Inc(SpaceAround.Right, TCustomEditButton(Control).ButtonWidth)
+  else
+    Inc(SpaceAround.Left, TCustomEditButton(Control).ButtonWidth)
+end;
+
+function TEditButtonSpacing.GetSideSpace(Kind: TAnchorKind): Integer;
+begin
+  Result := inherited GetSideSpace(Kind);
+  if Kind = akRight then
+  begin
+    if Control.BiDiMode = bdLeftToRight then
+      Inc(Result, TCustomEditButton(Control).ButtonWidth);
+  end
+  else if (Kind = akLeft) and (Control.BiDiMode <> bdLeftToRight) then
+    Inc(Result, TCustomEditButton(Control).ButtonWidth);
+end;
+
 { TCustomControlFilterEdit }
 
 constructor TCustomControlFilterEdit.Create(AOwner: TComponent);
-- 
1.7.10.4

Juha Manninen

2014-03-15 15:04

developer   ~0073724

I uploaded an old patch from Flávio Etrusco. It uses BorderSpacing to solve the alignment issues in a clever way, but unfortunately creates a recursive loop in LCL layout system. I have no idea about how difficult it would be to fix.

Vojtech Cihak

2014-03-15 19:38

reporter   ~0073733

Last edited: 2014-03-15 20:01

View 2 revisions

I support this. My attempt to redesign TEditButton to grouped control is IMO impasse. It had overhead, it was too complex and I didn't know how to solve some functionality (like messages). This my implementation is now available with define "NewEditButton" but I think it should be removed and Flávio's patch should be improved and accepted instead.
As Juha observed some time ago, original Flávio's patch fails when TEditButton is placed on TPanel.
Unfortunately, I have not enough LCL knowlegdes to finish it.

Juha Manninen

2014-03-16 12:32

developer   ~0073739

Last edited: 2014-03-16 12:34

View 2 revisions

I removed the "NewEditButton" code. I thought somebody would test and improve it but it did not happen.
I think Mattias would need to check the BorderSpacing issue in Flávio's solution. I don't have enough knowledge.

Now there is another candidate. See:
  http://forum.lazarus.freepascal.org/index.php/topic,23923
IMO he got the event passing right. Let's see what comes up.

Bart Broersma

2014-03-22 15:56

developer   ~0073891

I will try to re-implement this control based upon the code mentioned in the previous note.

Bart Broersma

2014-04-03 11:22

developer   ~0074138

Please test with r44590 or later and built with -dUSEBUTTONEDIT and report back.

Bart Broersma

2014-04-06 17:49

developer   ~0074175

Please close if OK.

Issue History

Date Modified Username Field Change
2008-09-15 23:19 Martin Friebe New Issue
2008-09-15 23:19 Martin Friebe LazTarget => -
2008-09-16 04:46 Paul Ishenin Status new => assigned
2008-09-16 04:46 Paul Ishenin Assigned To => Mattias Gaertner
2008-09-16 04:46 Paul Ishenin LazTarget - => 1.0
2009-05-23 10:11 Graeme Geldenhuys Note Added: 0027886
2011-08-08 20:52 Flávio Etrusco (notifications not working) Note Added: 0050619
2011-08-08 22:47 Flávio Etrusco (notifications not working) Note Edited: 0050619
2011-10-17 23:59 Juha Manninen Relationship added has duplicate 0020502
2011-10-28 09:25 Juha Manninen Relationship added related to 0017349
2011-10-28 09:29 Zeljan Rikalo Note Added: 0053534
2011-10-28 09:32 Juha Manninen Relationship added has duplicate 0020168
2011-10-28 14:10 Flávio Etrusco (notifications not working) Note Added: 0053547
2012-02-10 09:21 Zeljan Rikalo Tag Attached: TEditButton
2012-02-11 20:10 Zeljan Rikalo Note Added: 0056763
2012-06-18 23:59 Mattias Gaertner LazTarget 1.0 => 1.2
2012-06-18 23:59 Mattias Gaertner Note Added: 0060618
2012-09-30 13:37 Juha Manninen Relationship added related to 0023029
2013-12-30 15:13 Juha Manninen LazTarget 1.2 => 1.4
2014-03-15 14:58 Juha Manninen Assigned To Mattias Gaertner => Juha Manninen
2014-03-15 14:59 Juha Manninen File Added: 0001-LCL-improvements-for-TEditButton-by-Flavio-Etrusco.patch
2014-03-15 15:04 Juha Manninen Note Added: 0073724
2014-03-15 19:38 Vojtech Cihak Note Added: 0073733
2014-03-15 20:01 Vojtech Cihak Note Edited: 0073733 View Revisions
2014-03-16 12:32 Juha Manninen Note Added: 0073739
2014-03-16 12:34 Juha Manninen Note Edited: 0073739 View Revisions
2014-03-22 15:55 Bart Broersma Assigned To Juha Manninen => Bart Broersma
2014-03-22 15:56 Bart Broersma Note Added: 0073891
2014-04-03 11:22 Bart Broersma Note Added: 0074138
2014-04-03 11:22 Bart Broersma Status assigned => feedback
2014-04-06 17:49 Bart Broersma Fixed in Revision => r44623
2014-04-06 17:49 Bart Broersma Note Added: 0074175
2014-04-06 17:49 Bart Broersma Status feedback => resolved
2014-04-06 17:49 Bart Broersma Fixed in Version => 1.4
2014-04-06 17:49 Bart Broersma Resolution open => fixed
2014-04-07 15:57 Bart Broersma Relationship replaced has duplicate 0017349
2018-07-19 17:46 Martin Friebe Status resolved => closed