mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-17 07:49:27 +02:00
ideintf: ComponentTreeView: a generic way to create subtrees from child components (patch from Alexander S. Klenin, issue #0013217)
git-svn-id: trunk@18782 -
This commit is contained in:
parent
0265fae03f
commit
cf81a4cbf8
@ -28,7 +28,7 @@ unit ComponentTreeView;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, LCLProc, AvgLvlTree, Controls, ComCtrls, PropEdits, Menus,
|
Classes, SysUtils, LCLProc, AvgLvlTree, Controls, ComCtrls, PropEdits,
|
||||||
ExtCtrls, LResources;
|
ExtCtrls, LResources;
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -72,6 +72,23 @@ type
|
|||||||
Added: boolean;
|
Added: boolean;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TComponentWalker }
|
||||||
|
|
||||||
|
TComponentWalker = class
|
||||||
|
FTreeView: TComponentTreeView;
|
||||||
|
FCandidates: TAvgLvlTree;
|
||||||
|
FRootComponent: TComponent;
|
||||||
|
FNode: TTreeNode;
|
||||||
|
public
|
||||||
|
constructor Create(
|
||||||
|
ATreeView: TComponentTreeView; ACandidates: TAvgLvlTree;
|
||||||
|
ARootComponent: TComponent; ANode: TTreeNode);
|
||||||
|
|
||||||
|
procedure Walk(AComponent: TComponent);
|
||||||
|
end;
|
||||||
|
|
||||||
|
TComponentAccessor = class(TComponent);
|
||||||
|
|
||||||
function CompareComponentCandidates(
|
function CompareComponentCandidates(
|
||||||
Candidate1, Candidate2: TComponentCandidate): integer;
|
Candidate1, Candidate2: TComponentCandidate): integer;
|
||||||
begin
|
begin
|
||||||
@ -84,6 +101,42 @@ begin
|
|||||||
Result := ComparePointers(APersistent, Candidate.APersistent);
|
Result := ComparePointers(APersistent, Candidate.APersistent);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TComponentWalker }
|
||||||
|
|
||||||
|
constructor TComponentWalker.Create(ATreeView: TComponentTreeView;
|
||||||
|
ACandidates: TAvgLvlTree; ARootComponent: TComponent; ANode: TTreeNode);
|
||||||
|
begin
|
||||||
|
FTreeView := ATreeView;
|
||||||
|
FCandidates := ACandidates;
|
||||||
|
FRootComponent := ARootComponent;
|
||||||
|
FNode := ANode;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TComponentWalker.Walk(AComponent: TComponent);
|
||||||
|
var
|
||||||
|
oldNode: TTreeNode;
|
||||||
|
candidate: TComponentCandidate;
|
||||||
|
avlNode: TAvgLvlTreeNode;
|
||||||
|
begin
|
||||||
|
if GetLookupRootForComponent(AComponent) <> FRootComponent then exit;
|
||||||
|
avlNode := FCandidates.FindKey(
|
||||||
|
AComponent, TListSortCompare(@ComparePersistentWithComponentCandidate));
|
||||||
|
if avlNode = nil then exit;
|
||||||
|
candidate := TComponentCandidate(avlNode.Data);
|
||||||
|
if candidate.Added then exit;
|
||||||
|
candidate.Added := true;
|
||||||
|
|
||||||
|
oldNode := FNode;
|
||||||
|
FNode := FTreeView.Items.AddChild(FNode, FTreeView.CreateNodeCaption(AComponent));
|
||||||
|
FNode.Data := AComponent;
|
||||||
|
FNode.ImageIndex := FTreeView.GetImageFor(AComponent);
|
||||||
|
FNode.SelectedIndex := FNode.ImageIndex;
|
||||||
|
FNode.MultiSelected := FTreeView.Selection.IndexOf(AComponent) >= 0;
|
||||||
|
TComponentAccessor(AComponent).GetChildren(@Walk, FRootComponent);
|
||||||
|
FNode := oldNode;
|
||||||
|
FNode.Expanded := true;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TComponentTreeView }
|
{ TComponentTreeView }
|
||||||
|
|
||||||
procedure TComponentTreeView.SetSelection(
|
procedure TComponentTreeView.SetSelection(
|
||||||
@ -275,60 +328,16 @@ var
|
|||||||
Candidates: TAvgLvlTree;
|
Candidates: TAvgLvlTree;
|
||||||
RootComponent: TComponent;
|
RootComponent: TComponent;
|
||||||
|
|
||||||
procedure AddChildControls(AControl: TWinControl; ANode: TTreeNode);
|
procedure AddChildren(AComponent: TComponent; ANode: TTreeNode);
|
||||||
var
|
var
|
||||||
i: Integer;
|
walker: TComponentWalker;
|
||||||
CurControl: TControl;
|
|
||||||
NewNode: TTreeNode;
|
|
||||||
Candidate: TComponentCandidate;
|
|
||||||
AVLNode: TAvgLvlTreeNode;
|
|
||||||
begin
|
begin
|
||||||
if AControl=nil then exit;
|
walker := TComponentWalker.Create(Self, Candidates, RootComponent, ANode);
|
||||||
for i:=0 to AControl.ControlCount-1 do begin
|
try
|
||||||
CurControl:=AControl.Controls[i];
|
TComponentAccessor(AComponent).GetChildren(@walker.Walk, RootComponent);
|
||||||
if GetLookupRootForComponent(CurControl)<>RootComponent then continue;
|
finally
|
||||||
AVLNode:=Candidates.FindKey(CurControl,
|
walker.Free;
|
||||||
TListSortCompare(@ComparePersistentWithComponentCandidate));
|
|
||||||
if AVLNode=nil then continue;
|
|
||||||
Candidate:=TComponentCandidate(AVLNode.Data);
|
|
||||||
if Candidate.Added then continue;
|
|
||||||
Candidate.Added:=true;
|
|
||||||
NewNode:=Items.AddChild(ANode,CreateNodeCaption(CurControl));
|
|
||||||
NewNode.Data:=CurControl;
|
|
||||||
NewNode.ImageIndex:=GetImageFor(CurControl);
|
|
||||||
NewNode.SelectedIndex:=NewNode.ImageIndex;
|
|
||||||
NewNode.MultiSelected:=Selection.IndexOf(CurControl)>=0;
|
|
||||||
if CurControl is TWinControl then
|
|
||||||
AddChildControls(TWinControl(CurControl),NewNode);
|
|
||||||
end;
|
end;
|
||||||
ANode.Expanded:=true;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure AddMenuItemChilds(AMenuItem: TMenuItem; ANode: TTreeNode);
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
CurMenuItem: TMenuItem;
|
|
||||||
NewNode: TTreeNode;
|
|
||||||
Candidate: TComponentCandidate;
|
|
||||||
AVLNode: TAvgLvlTreeNode;
|
|
||||||
begin
|
|
||||||
if AMenuItem=nil then exit;
|
|
||||||
for i:=0 to AMenuItem.Count-1 do begin
|
|
||||||
CurMenuItem:=AMenuItem.Items[i];
|
|
||||||
if CurMenuItem.Owner<>RootComponent then continue;
|
|
||||||
AVLNode:=Candidates.FindKey(CurMenuItem,
|
|
||||||
TListSortCompare(@ComparePersistentWithComponentCandidate));
|
|
||||||
Candidate:=TComponentCandidate(AVLNode.Data);
|
|
||||||
if Candidate.Added then continue;
|
|
||||||
Candidate.Added:=true;
|
|
||||||
NewNode:=Items.AddChild(ANode,CreateNodeCaption(CurMenuItem));
|
|
||||||
NewNode.Data:=CurMenuItem;
|
|
||||||
NewNode.ImageIndex:=1;
|
|
||||||
NewNode.SelectedIndex:=NewNode.ImageIndex;
|
|
||||||
NewNode.MultiSelected:=Selection.IndexOf(CurMenuItem)>=0;
|
|
||||||
AddMenuItemChilds(CurMenuItem,NewNode);
|
|
||||||
end;
|
|
||||||
ANode.Expanded:=true;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddCandidates(OwnerComponent: TComponent);
|
procedure AddCandidates(OwnerComponent: TComponent);
|
||||||
@ -360,9 +369,7 @@ var
|
|||||||
i: Integer;
|
i: Integer;
|
||||||
AComponent: TComponent;
|
AComponent: TComponent;
|
||||||
RootNode: TTreeNode;
|
RootNode: TTreeNode;
|
||||||
AControl: TControl;
|
|
||||||
AVLNode: TAvgLvlTreeNode;
|
AVLNode: TAvgLvlTreeNode;
|
||||||
AMenu: TMenu;
|
|
||||||
Candidate: TComponentCandidate;
|
Candidate: TComponentCandidate;
|
||||||
begin
|
begin
|
||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
@ -397,31 +404,18 @@ begin
|
|||||||
AVLNode:=Candidates.FindKey(AComponent,
|
AVLNode:=Candidates.FindKey(AComponent,
|
||||||
TListSortCompare(@ComparePersistentWithComponentCandidate));
|
TListSortCompare(@ComparePersistentWithComponentCandidate));
|
||||||
Candidate:=TComponentCandidate(AVLNode.Data);
|
Candidate:=TComponentCandidate(AVLNode.Data);
|
||||||
if Candidate.Added then
|
if Candidate.Added or
|
||||||
|
AComponent.HasParent and
|
||||||
|
(AComponent.GetParentComponent <> nil) and
|
||||||
|
(AComponent.GetParentComponent <> RootComponent) then
|
||||||
continue;
|
continue;
|
||||||
if AComponent is TControl then begin
|
|
||||||
AControl:=TControl(AComponent);
|
|
||||||
if (AControl.Parent<>nil) and (AControl.Parent<>RootComponent) then
|
|
||||||
// grand child controls will be added recursively, not here
|
|
||||||
continue;
|
|
||||||
end
|
|
||||||
else if (AComponent is TMenuItem) then begin
|
|
||||||
AMenu:=TMenuItem(AComponent).GetParentMenu;
|
|
||||||
if (AMenu<>nil) and (AMenu.Owner=RootComponent) then
|
|
||||||
// child menuitems will be added recursively, not here
|
|
||||||
continue;
|
|
||||||
end;
|
|
||||||
Candidate.Added:=true;
|
Candidate.Added:=true;
|
||||||
NewNode:=Items.AddChild(RootNode,CreateNodeCaption(AComponent));
|
NewNode:=Items.AddChild(RootNode,CreateNodeCaption(AComponent));
|
||||||
NewNode.Data:=AComponent;
|
NewNode.Data:=AComponent;
|
||||||
NewNode.ImageIndex:=GetImageFor(AComponent);
|
NewNode.ImageIndex:=GetImageFor(AComponent);
|
||||||
NewNode.SelectedIndex:=NewNode.ImageIndex;
|
NewNode.SelectedIndex:=NewNode.ImageIndex;
|
||||||
NewNode.MultiSelected:=Selection.IndexOf(AComponent)>=0;
|
NewNode.MultiSelected:=Selection.IndexOf(AComponent)>=0;
|
||||||
if AComponent is TWinControl then
|
AddChildren(AComponent, NewNode);
|
||||||
AddChildControls(TWinControl(AComponent),NewNode)
|
|
||||||
else if (AComponent is TMenu) then begin
|
|
||||||
AddMenuItemChilds(TMenu(AComponent).Items,NewNode);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
|
Loading…
Reference in New Issue
Block a user