From 45d0b49083fbfbcb1be4c92c7ab59aa9e8286071 Mon Sep 17 00:00:00 2001 From: mattias Date: Wed, 15 Feb 2012 14:57:15 +0000 Subject: [PATCH] LCL: TLazAccessibleObject: using a tree for children for faster search git-svn-id: trunk@35374 - --- lcl/controls.pp | 21 +++++++++++++-- lcl/include/control.inc | 60 +++++++++++++++++++---------------------- 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/lcl/controls.pp b/lcl/controls.pp index 45b9c06a65..c892af1beb 100644 --- a/lcl/controls.pp +++ b/lcl/controls.pp @@ -939,7 +939,7 @@ type procedure SetPosition(AValue: TPoint); procedure SetSize(AValue: TSize); protected - FChildren: TFPList; // of TLazAccessibleObject + FChildrenSortedForDataObject: TAvgLvlTree; // of TLazAccessibleObject FAccessibleDescription: TCaption; FAccessibleValue: TCaption; FAccessibleRole: TLazAccessibilityRole; @@ -961,7 +961,6 @@ type procedure InsertChildAccessibleObject(AObject: TLazAccessibleObject); procedure ClearChildAccessibleObjects; procedure RemoveChildAccessibleObject(AObject: TLazAccessibleObject; AFreeObject: Boolean = True); - function GetChildAccessibleObject(AIndex: Integer): TLazAccessibleObject; function GetChildAccessibleObjectWithDataObject(ADataObject: TObject): TLazAccessibleObject; function GetChildAccessibleObjectsCount: Integer; function GetSelectedChildAccessibleObject: TLazAccessibleObject; virtual; @@ -2556,6 +2555,9 @@ function DbgS(Phases: TControlAutoSizePhases): string; overload; operator := (AVariant: Variant): TCaption; +function CompareLazAccessibleObjectsByDataObject(o1, o2: Pointer): integer; +function CompareDataObjectWithLazAccessibleObject(o, ao: Pointer): integer; + // register (called by the package initialization in design mode) procedure Register; @@ -2794,6 +2796,21 @@ begin then SetFocus(AWinControl.FHandle); end; +function CompareLazAccessibleObjectsByDataObject(o1, o2: Pointer): integer; +var + AccObj1: TLazAccessibleObject absolute o1; + AccObj2: TLazAccessibleObject absolute o2; +begin + Result:=ComparePointers(AccObj1.DataObject,AccObj2.DataObject); +end; + +function CompareDataObjectWithLazAccessibleObject(o, ao: Pointer): integer; +var + AccObj: TLazAccessibleObject absolute ao; +begin + Result:=ComparePointers(o,AccObj.DataObject); +end; + procedure Register; begin RegisterComponents('Common Controls',[TImageList]); diff --git a/lcl/include/control.inc b/lcl/include/control.inc index 1e7b4730a5..eb77b8cd28 100644 --- a/lcl/include/control.inc +++ b/lcl/include/control.inc @@ -98,7 +98,7 @@ constructor TLazAccessibleObject.Create(AOwner: TControl); begin inherited Create;//(AOwner); OwnerControl := AOwner; - FChildren := TFPList.Create; + FChildrenSortedForDataObject := TAvgLvlTree.Create(@CompareDataObjectWithLazAccessibleObject); WSRegisterClass(); end; @@ -110,7 +110,8 @@ begin ClearChildAccessibleObjects(); if (WidgetsetClass <> nil) and (FHandle <> 0) then WidgetsetClass.DestroyHandle(Self); - FreeAndNil(FChildren); + FreeAndNil(FChildrenSortedForDataObject); + FreeAndNil(FChildrenSortedForDataObject); inherited Destroy; end; @@ -170,56 +171,50 @@ end; function TLazAccessibleObject.AddChildAccessibleObject: TLazAccessibleObject; begin Result := nil; - if FChildren = nil then Exit; + if FChildrenSortedForDataObject = nil then Exit; Result := TLazAccessibleObject.Create(OwnerControl); Result.Parent := Self; - FChildren.Add(Result); + FChildrenSortedForDataObject.Add(Result); //DebugLn('[TControl.AddChildAccessibleObject] Name=%s', [Name]); end; procedure TLazAccessibleObject.InsertChildAccessibleObject( AObject: TLazAccessibleObject); begin - if FChildren = nil then Exit; - FChildren.Add(AObject); + if FChildrenSortedForDataObject = nil then Exit; + FChildrenSortedForDataObject.Add(AObject); end; procedure TLazAccessibleObject.ClearChildAccessibleObjects; var i: Integer; lXObject: TLazAccessibleObject; + AVLNode: TAvgLvlTreeNode; begin - if FChildren = nil then Exit; + if FChildrenSortedForDataObject = nil then Exit; //DebugLn(Format('[TControl.ClearChildAccessibleObjects] Name=%s Count=%d', [Name, FAccessibleChildren.Count])); // Free only the non-control children - for i := 0 to FChildren.Count - 1 do - begin - lXObject := TLazAccessibleObject(FChildren.Items[i]); + AVLNode:=FChildrenSortedForDataObject.FindLowest; + while AVLNode<>nil do begin + lXObject := TLazAccessibleObject(AVLNode.Data); if lXObject.OwnerControl = OwnerControl then lXObject.Free; + AVLNode:=FChildrenSortedForDataObject.FindSuccessor(AVLNode); end; - FChildren.Clear; + FChildrenSortedForDataObject.Clear; end; procedure TLazAccessibleObject.RemoveChildAccessibleObject( AObject: TLazAccessibleObject; AFreeObject: Boolean = True); var lIndex: Integer; + Node: TAvgLvlTreeNode; begin - if FChildren = nil then Exit; - lIndex := FChildren.IndexOf(AObject); - if lIndex >= 0 then - begin - if AFreeObject then TLazAccessibleObject(FChildren.Items[lIndex]).Free; - FChildren.Delete(lIndex); - end; -end; - -function TLazAccessibleObject.GetChildAccessibleObject(AIndex: Integer): TLazAccessibleObject; -begin - Result := nil; - if FChildren = nil then Exit; - Result := TLazAccessibleObject(FChildren.Items[AIndex]); + if FChildrenSortedForDataObject = nil then Exit; + Node:=FChildrenSortedForDataObject.Find(AObject); + FChildrenSortedForDataObject.Delete(Node); + if (Node<>nil) and AFreeObject then + AObject.Free; end; function TLazAccessibleObject.GetChildAccessibleObjectWithDataObject( @@ -227,21 +222,20 @@ function TLazAccessibleObject.GetChildAccessibleObjectWithDataObject( var i: Integer; lCurObject: TLazAccessibleObject; + Node: TAvgLvlTreeNode; begin Result := nil; - if FChildren = nil then Exit; - for i := 0 to FChildren.Count - 1 do - begin - lCurObject := TLazAccessibleObject(FChildren.Items[i]); - if lCurObject.DataObject = ADataObject then Exit(lCurObject); - end; + if FChildrenSortedForDataObject = nil then Exit; + Node:=FChildrenSortedForDataObject.FindKey(ADataObject,@CompareDataObjectWithLazAccessibleObject); + if Node<>nil then + Result:=TLazAccessibleObject(Node.Data); end; function TLazAccessibleObject.GetChildAccessibleObjectsCount: Integer; begin Result := 0; - if FChildren = nil then Exit; - Result := FChildren.Count; + if FChildrenSortedForDataObject <> nil then + Result := FChildrenSortedForDataObject.Count; end; function TLazAccessibleObject.GetSelectedChildAccessibleObject: TLazAccessibleObject;