28
27
{ $DEFINE CHECK_POSITION}
29
{ TLazAccessibleObjectEnumerator }
31
function TLazAccessibleObjectEnumerator.GetCurrent: TLazAccessibleObject;
33
Result:=TLazAccessibleObject(FCurrent.Data);
36
{ TLazAccessibleObject }
38
function TLazAccessibleObject.GetHandle: PtrInt;
40
WidgetsetClass: TWSLazAccessibleObjectClass;
42
WidgetsetClass := TWSLazAccessibleObjectClass(GetWSLazAccessibleObject());
43
if (WidgetsetClass <> nil) and (FHandle = 0) then
45
FHandle := WidgetsetClass.CreateHandle(Self);
51
function TLazAccessibleObject.GetAccessibleValue: TCaption;
53
Result := FAccessibleValue;
56
function TLazAccessibleObject.GetPosition: TPoint;
58
if (OwnerControl <> nil) and (OwnerControl.GetAccessibleObject() = Self) then
60
Result := Point(OwnerControl.Left, OwnerControl.Top);
66
function TLazAccessibleObject.GetSize: TSize;
68
if (OwnerControl <> nil) and (OwnerControl.GetAccessibleObject() = Self) then
70
Result := Types.Size(OwnerControl.Width, OwnerControl.Height);
76
procedure TLazAccessibleObject.SetHandle(AValue: PtrInt);
78
if AValue = FHandle then Exit;
83
procedure TLazAccessibleObject.SetPosition(AValue: TPoint);
85
WidgetsetClass: TWSLazAccessibleObjectClass;
87
if (FPosition.X=AValue.X) and (FPosition.Y=AValue.Y) then Exit;
89
WidgetsetClass := TWSLazAccessibleObjectClass(GetWSLazAccessibleObject());
90
WidgetsetClass.SetPosition(Self, AValue);
93
procedure TLazAccessibleObject.SetSize(AValue: TSize);
95
WidgetsetClass: TWSLazAccessibleObjectClass;
97
if (FSize.CX=AValue.CX) and (FSize.CY=AValue.CY) then Exit;
99
WidgetsetClass := TWSLazAccessibleObjectClass(GetWSLazAccessibleObject());
100
WidgetsetClass.SetSize(Self, AValue);
103
class procedure TLazAccessibleObject.WSRegisterClass;
105
// inherited WSRegisterClass;
106
RegisterLazAccessibleObject;
109
constructor TLazAccessibleObject.Create(AOwner: TControl);
111
inherited Create;//(AOwner);
112
OwnerControl := AOwner;
113
FChildrenSortedForDataObject := TAvgLvlTree.Create(@CompareDataObjectWithLazAccessibleObject);
117
destructor TLazAccessibleObject.Destroy;
119
WidgetsetClass: TWSLazAccessibleObjectClass;
121
WidgetsetClass := TWSLazAccessibleObjectClass(GetWSLazAccessibleObject());
122
ClearChildAccessibleObjects();
123
if (WidgetsetClass <> nil) and (FHandle <> 0) then
124
WidgetsetClass.DestroyHandle(Self);
125
FreeAndNil(FChildrenSortedForDataObject);
129
function TLazAccessibleObject.HandleAllocated: Boolean;
131
Result := FHandle <> 0;
134
procedure TLazAccessibleObject.InitializeHandle;
136
WidgetsetClass: TWSLazAccessibleObjectClass;
138
WidgetsetClass := TWSLazAccessibleObjectClass(GetWSLazAccessibleObject());
139
WidgetsetClass.SetAccessibleDescription(Self, FAccessibleDescription);
140
WidgetsetClass.SetAccessibleValue(Self, FAccessibleValue);
141
WidgetsetClass.SetAccessibleRole(Self, FAccessibleRole);
144
procedure TLazAccessibleObject.SetAccessibleDescription(const ADescription: TCaption);
146
WidgetsetClass: TWSLazAccessibleObjectClass;
148
if FAccessibleDescription=ADescription then Exit;
149
FAccessibleDescription := ADescription;
150
WidgetsetClass := TWSLazAccessibleObjectClass(GetWSLazAccessibleObject());
151
WidgetsetClass.SetAccessibleDescription(Self, ADescription);
154
procedure TLazAccessibleObject.SetAccessibleValue(const AValue: TCaption);
156
WidgetsetClass: TWSLazAccessibleObjectClass;
158
if FAccessibleValue=AValue then Exit;
159
FAccessibleValue := AValue;
160
WidgetsetClass := TWSLazAccessibleObjectClass(GetWSLazAccessibleObject());
161
WidgetsetClass.SetAccessibleValue(Self, AValue);
164
procedure TLazAccessibleObject.SetAccessibleRole(const ARole: TLazAccessibilityRole);
166
WidgetsetClass: TWSLazAccessibleObjectClass;
168
if FAccessibleRole=ARole then Exit;
169
FAccessibleRole := ARole;
170
WidgetsetClass := TWSLazAccessibleObjectClass(GetWSLazAccessibleObject());
171
WidgetsetClass.SetAccessibleRole(Self, ARole);
174
function TLazAccessibleObject.FindOwnerWinControl: TWinControl;
177
if (OwnerControl <> nil) and (OwnerControl is TWinControl) then Exit(OwnerControl as TWinControl);
178
if Self.Parent = nil then Exit;
179
Result := Self.Parent.FindOwnerWinControl();
182
function TLazAccessibleObject.AddChildAccessibleObject: TLazAccessibleObject;
185
if FChildrenSortedForDataObject = nil then Exit;
186
Result := TLazAccessibleObject.Create(OwnerControl);
187
Result.Parent := Self;
188
FChildrenSortedForDataObject.Add(Result);
189
//DebugLn('[TControl.AddChildAccessibleObject] Name=%s', [Name]);
192
procedure TLazAccessibleObject.InsertChildAccessibleObject(
193
AObject: TLazAccessibleObject);
195
if FChildrenSortedForDataObject = nil then Exit;
196
FChildrenSortedForDataObject.Add(AObject);
199
procedure TLazAccessibleObject.ClearChildAccessibleObjects;
201
lXObject: TLazAccessibleObject;
202
AVLNode: TAvgLvlTreeNode;
204
if FChildrenSortedForDataObject = nil then Exit;
205
//DebugLn(Format('[TControl.ClearChildAccessibleObjects] Name=%s Count=%d', [Name, FAccessibleChildren.Count]));
206
// Free only the non-control children
207
AVLNode:=FChildrenSortedForDataObject.FindLowest;
208
while AVLNode<>nil do begin
209
lXObject := TLazAccessibleObject(AVLNode.Data);
210
if lXObject.OwnerControl = OwnerControl then
212
AVLNode:=FChildrenSortedForDataObject.FindSuccessor(AVLNode);
214
FChildrenSortedForDataObject.Clear;
217
procedure TLazAccessibleObject.RemoveChildAccessibleObject(
218
AObject: TLazAccessibleObject; AFreeObject: Boolean = True);
220
Node: TAvgLvlTreeNode;
222
if FChildrenSortedForDataObject = nil then Exit;
223
Node:=FChildrenSortedForDataObject.Find(AObject);
224
if Node=nil then exit;
225
FChildrenSortedForDataObject.Delete(Node);
230
function TLazAccessibleObject.GetChildAccessibleObjectWithDataObject(
231
ADataObject: TObject): TLazAccessibleObject;
233
Node: TAvgLvlTreeNode;
236
if FChildrenSortedForDataObject = nil then Exit;
237
Node:=FChildrenSortedForDataObject.FindKey(ADataObject,@CompareDataObjectWithLazAccessibleObject);
239
Result:=TLazAccessibleObject(Node.Data);
242
function TLazAccessibleObject.GetChildAccessibleObjectsCount: Integer;
245
if FChildrenSortedForDataObject <> nil then
246
Result := FChildrenSortedForDataObject.Count;
249
function TLazAccessibleObject.GetChildAccessibleObject(AIndex: Integer): TLazAccessibleObject;
251
lNode: TAvgLvlTreeNode = nil;
254
if AIndex = 0 then lNode := FChildrenSortedForDataObject.FindLowest()
255
else if AIndex = GetChildAccessibleObjectsCount()-1 then
256
lNode := FChildrenSortedForDataObject.FindHighest()
257
else if AIndex = FLastSearchIndex then lNode := FLastSearchNode
258
else if AIndex = FLastSearchIndex+1 then
259
lNode := FChildrenSortedForDataObject.FindSuccessor(FLastSearchNode)
260
else if AIndex = FLastSearchIndex-1 then
261
lNode := FChildrenSortedForDataObject.FindPrecessor(FLastSearchNode);
263
if lNode = nil then Exit;
265
Result := TLazAccessibleObject(lNode.Data);
268
function TLazAccessibleObject.GetFirstChildAccessibleObject: TLazAccessibleObject;
271
FLastSearchInSubcontrols := False;
272
if GetChildAccessibleObjectsCount() > 0 then
273
Result := GetChildAccessibleObject(0)
274
else if (OwnerControl <> nil) and (OwnerControl is TWinControl) then
276
FLastSearchIndex := 1;
277
FLastSearchInSubcontrols := True;
278
if (TWinControl(OwnerControl).ControlCount > 0) then
279
Result := TWinControl(OwnerControl).Controls[0].GetAccessibleObject();
283
function TLazAccessibleObject.GetNextChildAccessibleObject: TLazAccessibleObject;
286
if not FLastSearchInSubcontrols then
288
if GetChildAccessibleObjectsCount() < FLastSearchIndex then
289
Result := GetChildAccessibleObject(FLastSearchIndex)
290
else if (OwnerControl <> nil) and (OwnerControl is TWinControl) then
292
FLastSearchIndex := 1;
293
FLastSearchInSubcontrols := True;
294
Result := TWinControl(OwnerControl).Controls[0].GetAccessibleObject();
299
if TWinControl(OwnerControl).ControlCount > FLastSearchIndex then
301
Result := TWinControl(OwnerControl).Controls[FLastSearchIndex].GetAccessibleObject();
302
Inc(FLastSearchIndex);
307
function TLazAccessibleObject.GetSelectedChildAccessibleObject: TLazAccessibleObject;
310
if OwnerControl = nil then Exit;
311
Result := OwnerControl.GetSelectedChildAccessibleObject();
314
function TLazAccessibleObject.GetChildAccessibleObjectAtPos(APos: TPoint): TLazAccessibleObject;
317
if OwnerControl = nil then Exit;
318
Result := OwnerControl.GetChildAccessibleObjectAtPos(APos);
321
function TLazAccessibleObject.GetEnumerator: TLazAccessibleObjectEnumerator;
323
Result:=TLazAccessibleObjectEnumerator.Create(FChildrenSortedForDataObject);
30
326
{------------------------------------------------------------------------------
31
327
TControl.AdjustSize
654
953
and (not (csNoDesignVisible in ControlStyle))));
956
{------------------------------------------------------------------------------
957
Method: TControl.IsEnabled
961
Returns True only if both TControl and it's parent hierarchy are enabled.
962
Used internally by TGraphicControls for painting and various states during
964
------------------------------------------------------------------------------}
965
function TControl.IsEnabled: Boolean;
967
TheControl: TControl;
971
Result := TheControl.Enabled;
972
TheControl := TheControl.Parent;
973
until (TheControl = nil) or (not Result);
976
{------------------------------------------------------------------------------
977
Method: TControl.IsParentColor
981
Used at places where we need to check ParentColor property from TControl.
982
Property is protected, so this function avoids hacking to get
983
protected property value.
984
------------------------------------------------------------------------------}
985
function TControl.IsParentColor: Boolean;
987
Result := FParentColor;
990
{------------------------------------------------------------------------------
991
Method: TControl.IsParentFont
995
Used at places where we need to check ParentFont property from TControl.
996
Property is protected, so this function avoids hacking to get
997
protected property value.
998
------------------------------------------------------------------------------}
999
function TControl.IsParentFont: Boolean;
1001
Result := FParentFont;
657
1004
function TControl.FormIsUpdating: boolean;
659
1006
Result := Assigned(Parent) and Parent.FormIsUpdating;
2538
2968
else if csDestroying in ComponentState then debugln('csDestroying')
2539
2969
else if cfLoading in FControlFlags then debugln('cfLoading')
2540
2970
else if not IsControlVisible then debugln('not IsControlVisible')
2541
else if not AutoSizeCheckParent then debugln('not AutoSizeCheckParent')
2971
else if AutoSizeDelayedHandle then debugln('AutoSizeDelayedHandle')
2542
2972
else if ((Parent<>nil) and Parent.AutoSizeDelayed) then debugln('Parent.AutoSizeDelayed')
2543
2973
else debugln('?');
2548
function TControl.AutoSizeCheckParent: Boolean;
2550
Result := Parent <> nil;
2553
{------------------------------------------------------------------------------
2554
TControl SetBoundsRect
2978
function TControl.AutoSizeDelayedReport: string;
2980
if (FAutoSizingLockCount>0) then
2981
Result:='FAutoSizingLockCount='+dbgs(FAutoSizingLockCount)
2982
else if csLoading in ComponentState then
2984
else if csDestroying in ComponentState then
2985
Result:='csDestroying'
2986
else if cfLoading in FControlFlags then
2988
else if IsControlVisible then
2989
Result:='not IsControlVisible'
2990
else if AutoSizeDelayedHandle then
2991
Result:='AutoSizeDelayedHandle'
2992
else if Parent<>nil then
2993
Result:=Parent.AutoSizeDelayedReport
2998
{------------------------------------------------------------------------------
2999
TControl AutoSizeDelayedHandle
3001
Returns true if AutoSize should be skipped / delayed because of its handle.
3002
A TControl does not have a handle, so it needs a parent.
3003
------------------------------------------------------------------------------}
3004
function TControl.AutoSizeDelayedHandle: Boolean;
3006
Result := Parent = nil;
3009
{------------------------------------------------------------------------------
3010
TControl SetBoundsRect
2555
3011
------------------------------------------------------------------------------}
2556
3012
procedure TControl.SetBoundsRect(const ARect: TRect);
3016
3461
if (FLastResizeWidth<>Width) or (FLastResizeHeight<>Height)
3017
3462
or (FLastResizeClientWidth<>ClientWidth)
3018
3463
or (FLastResizeClientHeight<>ClientHeight) then begin
3019
//if AnsiCompareText('NOTEBOOK',Name)=0 then
3020
{DebugLn(['[TControl.Resize] ',Name,':',ClassName,
3021
' Last=',FLastResizeWidth,',',FLastResizeHeight,
3022
' LastClient=',FLastResizeClientWidth,',',FLastResizeClientHeight,
3023
' New=',Width,',',Height,
3024
' NewClient=',ClientWidth,',',ClientHeight]);}
3464
{if CompareText('SubPanel',Name)=0 then begin
3465
DebugLn(['[TControl.Resize] ',Name,':',ClassName,
3466
' Last=',FLastResizeWidth,',',FLastResizeHeight,
3467
' LastClient=',FLastResizeClientWidth,',',FLastResizeClientHeight,
3468
' New=',Width,',',Height,
3469
' NewClient=',ClientWidth,',',ClientHeight]);
3025
3472
FLastResizeWidth:=Width;
3026
3473
FLastResizeHeight:=Height;
3027
3474
FLastResizeClientWidth:=ClientWidth;
3226
3684
OldAlign: TAlign;
3227
3685
a: TAnchorKind;
3686
OldBaseBounds: TRect;
3229
3688
if FAlign = Value then exit;
3230
//DebugLn(['TControl.SetAlign ',DbgSName(Self),' Old=',AlignNames[FAlign],' New=',AlignNames[Value],' ',Anchors<>AnchorAlign[FAlign]]);
3689
//DebugLn(['TControl.SetAlign ',DbgSName(Self),' Old=',DbgS(FAlign),' New=',DbgS(Value),' ',Anchors<>AnchorAlign[FAlign]]);
3690
DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TControl.setalign'){$ENDIF};
3691
OldBaseBounds:=BaseBounds;
3231
3692
OldAlign := FAlign;
3232
3693
FAlign := Value;
3233
for a:=low(TAnchorKind) to High(TAnchorKind) do
3235
if not (a in AnchorAlign[FAlign]) then continue;
3236
AnchorSide[a].Control:=nil;
3237
AnchorSide[a].Side:=asrTop;
3694
if (not (csLoading in ComponentState))
3695
and (Align in [alLeft,alTop,alRight,alBottom,alClient]) then begin
3696
// Align for alLeft,alTop,alRight,alBottom,alClient takes precedence
3697
// over AnchorSides => clean up
3698
for a:=low(TAnchorKind) to High(TAnchorKind) do
3700
if not (a in AnchorAlign[FAlign]) then continue;
3701
AnchorSide[a].Control:=nil;
3702
AnchorSide[a].Side:=asrTop;
3239
// if anchors were on default then change them to new default
3240
// This is done for Delphi compatibility.
3706
// - if anchors had default values then change them to new default values
3707
// This is done for Delphi compatibility.
3708
// - Anchors are not stored if they are AnchorAlign[Align]
3241
3709
if (Anchors = AnchorAlign[OldAlign]) and (Anchors <> AnchorAlign[FAlign]) then
3242
Anchors := AnchorAlign[FAlign]
3710
Anchors := AnchorAlign[FAlign];
3711
if not (csLoading in ComponentState) then
3712
BoundsRect:=OldBaseBounds;
3713
//DebugLn(['TControl.SetAlign ',DbgSName(Self),' Cur=',DbgS(FAlign),' New=',DbgS(Value),' ',Anchors<>AnchorAlign[FAlign],' Anchors=',dbgs(Anchors)]);
3714
EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TControl.setalign'){$ENDIF};
3247
3717
{------------------------------------------------------------------------------
3295
3772
NewBaseParentClientSize:=Size(0,0);
3297
3774
NewBaseParentClientSize:=FBaseParentClientSize;
3298
if CompareRect(@NewBaseBounds,@FBaseBounds)
3299
and (NewBaseParentClientSize.cx=FBaseParentClientSize.cx)
3300
and (NewBaseParentClientSize.cy=FBaseParentClientSize.cy)
3302
//if csDesigning in ComponentState then
3303
{$IFDEF CHECK_POSITION}
3304
if CheckPosition(Self) then
3305
DebugLn(['TControl.UpdateBaseBounds '+DbgSName(Self),
3306
' OldBounds='+dbgs(FBaseBounds),
3307
' OldParentClientSize='+dbgs(FBaseParentClientSize),
3308
' NewBounds='+dbgs(NewBaseBounds),
3309
' NewParentClientSize='+dbgs(NewBaseParentClientSize),
3312
FBaseBounds:=NewBaseBounds;
3776
if (not CompareRect(@NewBaseBounds,@FBaseBounds))
3777
or (NewBaseParentClientSize.cx<>FBaseParentClientSize.cx)
3778
or (NewBaseParentClientSize.cy<>FBaseParentClientSize.cy)
3780
//if csDesigning in ComponentState then
3781
{$IFDEF CHECK_POSITION}
3782
if CheckPosition(Self) then
3783
DebugLn(['TControl.UpdateBaseBounds '+DbgSName(Self),
3784
' OldBounds='+dbgs(FBaseBounds),
3785
' OldParentClientSize='+dbgs(FBaseParentClientSize),
3786
' NewBounds='+dbgs(NewBaseBounds),
3787
' NewParentClientSize='+dbgs(NewBaseParentClientSize),
3791
FBaseBounds:=NewBaseBounds;
3792
FBaseParentClientSize:=NewBaseParentClientSize;
3313
3794
Include(FControlFlags,cfBaseBoundsValid);
3314
FBaseParentClientSize:=NewBaseParentClientSize;
3317
3797
procedure TControl.WriteLayoutDebugReport(const Prefix: string);
3822
procedure TControl.AutoAdjustLayout(AMode: TLayoutAdjustmentPolicy;
3823
const AFromDPI, AToDPI, AOldFormWidth, ANewFormWidth: Integer);
3825
lXProportion, lYProportion: Double;
3826
NewLeft, NewTop, NewHeight, NewWidth: Integer;
3827
lMode: TLayoutAdjustmentPolicy;
3829
// First resolve ladDefault
3831
if lMode = lapDefault then lMode := Application.LayoutAdjustmentPolicy;
3833
// X-axis adjustment proportion
3834
if lMode = lapAutoAdjustWithoutHorizontalScrolling then
3836
if AOldFormWidth > 0 then lXProportion := ANewFormWidth / AOldFormWidth
3837
else lXProportion := 1.0;
3839
else if lMode = lapAutoAdjustForDPI then
3841
if AFromDPI > 0 then lXProportion := AToDPI / AFromDPI
3842
else lXProportion := 1.0;
3845
// y-axis adjustment proportion
3846
if AFromDPI > 0 then lYProportion := AToDPI / AFromDPI
3847
else lYProportion := 1.0;
3849
// Apply the changes
3850
if (lMode = lapAutoAdjustWithoutHorizontalScrolling) or
3851
(lMode = lapAutoAdjustForDPI) then
3853
if ShouldAutoAdjustLeftAndTop then
3855
NewLeft := Round(Left * lXProportion);
3856
NewTop := Round(Top * lYProportion);
3863
if ShouldAutoAdjustWidthAndHeight then
3865
NewWidth := Round(Width * lXProportion);
3866
NewHeight := Round(Height * lYProportion);
3870
// Give a shake at the autosize to recalculate font sizes for example
3871
if AutoSize then AdjustSize();
3873
NewHeight := Height;
3875
SetBounds(NewLeft, NewTop, NewWidth, NewHeight);
3879
// The layout should only be auto-adjusted for controls with the most simple
3880
// default absolute positioning
3881
function TControl.ShouldAutoAdjustLeftAndTop: Boolean;
3883
Result := (Align = alNone) and (Anchors = [akTop, akLeft]) and (Parent <> nil);
3886
function TControl.ShouldAutoAdjustWidthAndHeight: Boolean;
3888
Result := (Align = alNone) and (Anchors = [akTop, akLeft]) and (AutoSize = False);
3342
3891
procedure TControl.UpdateAnchorRules;
3344
3893
UpdateBaseBounds(true,true,false);