mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-28 22:33:41 +02:00
364 lines
11 KiB
ObjectPascal
364 lines
11 KiB
ObjectPascal
{ $Id$ }
|
|
{
|
|
/***************************************************************************
|
|
findcomponent.pas
|
|
--------------------
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
***************************************************************************
|
|
* *
|
|
* This source is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This code is distributed in the hope that it will be useful, but *
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
* General Public License for more details. *
|
|
* *
|
|
* A copy of the GNU General Public License is available on the World *
|
|
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
|
* obtain it by writing to the Free Software Foundation, *
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
* *
|
|
***************************************************************************
|
|
|
|
Author: Marius
|
|
|
|
Abstract:
|
|
A dialog to quickly find components and create the found components
|
|
directly on the designed form. This avoids a lot of scrolling in my
|
|
already overfull palette (i love having the lazarus sources!).
|
|
}
|
|
unit ComponentList;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, LCLProc, LResources, Forms, Controls, Graphics, Dialogs,
|
|
StdCtrls, Buttons, FormEditingIntf, LazarusIDEStrConsts, ExtCtrls, ComCtrls,
|
|
ComponentPalette, ComponentReg, PackageDefs, ExtDlgs, FormEditor, PropEdits,
|
|
LCLType, Menus, ButtonPanel, IDEWindowIntf;
|
|
|
|
type
|
|
{ TComponentListForm }
|
|
|
|
TComponentListForm = class(TForm)
|
|
ButtonPanel: TButtonPanel;
|
|
LabelSearch: TLabel;
|
|
ListboxComponents: TListBox;
|
|
PageControl: TPageControl;
|
|
Panel3: TPanel;
|
|
Panel5: TPanel;
|
|
Panel6: TPanel;
|
|
Panel7: TPanel;
|
|
PatternEdit: TEdit;
|
|
TabSheetInheritance: TTabSheet;
|
|
TabSheetListBox: TTabSheet;
|
|
TabSheetPaletteTree: TTabSheet;
|
|
TreeInheritance: TTreeView;
|
|
TreePallette: TTreeView;
|
|
procedure FormShow(Sender: TObject);
|
|
procedure ListboxComponentsDblClick(Sender: TObject);
|
|
procedure TreeInheritanceDblClick ( Sender: TObject ) ;
|
|
procedure TreePalletteDblClick(Sender: TObject);
|
|
procedure UpdateComponentSelection(Sender: TObject);
|
|
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
|
|
procedure PatternEditChange(Sender: TObject);
|
|
procedure Timer1Timer(Sender: TObject);
|
|
private
|
|
FTimer: TTimer;
|
|
Processing: boolean;
|
|
FComponentList: TFPList;
|
|
procedure FindAllLazarusComponents;
|
|
procedure AddSelectedComponent(AComponent: TRegisteredComponent);
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
var
|
|
ComponentListForm: TComponentListForm;
|
|
|
|
implementation
|
|
|
|
|
|
{ TComponentListForm }
|
|
|
|
constructor TComponentListForm.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FTimer := TTimer.Create(nil);
|
|
FTimer.Interval := 500;
|
|
FTimer.Enabled := false;
|
|
FTimer.OnTimer := @Timer1Timer;
|
|
FComponentList := TFPList.Create;
|
|
|
|
ButtonPanel.CloseButton.Cancel := True;
|
|
|
|
//Translations..
|
|
LabelSearch.Caption := lisMenuFind;
|
|
Caption := lisCmpLstComponents;
|
|
TabSheetListBox.Caption := lisCmpLstList;
|
|
TabSheetPaletteTree.Caption := lisCmpLstPalette;
|
|
TabSheetInheritance.Caption := lisCmpLstInheritance;
|
|
|
|
//PLEASE add a defaultpage property in TPagecontrol
|
|
PageControl.ActivePage := TabSheetListBox;
|
|
|
|
FindAllLazarusComponents;
|
|
UpdateComponentSelection(nil);
|
|
IDEDialogLayoutList.ApplyLayout(Self);
|
|
end;
|
|
|
|
destructor TComponentListForm.Destroy;
|
|
begin
|
|
IDEDialogLayoutList.SaveLayout(Self);
|
|
ComponentListForm := nil;
|
|
FComponentList.Free;
|
|
FTimer.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TComponentListForm.FindAllLazarusComponents;
|
|
//Collect all available components (excluding hidden)
|
|
var
|
|
AComponent: TRegisteredComponent;
|
|
APage: TBaseComponentPage;
|
|
i, j: Integer;
|
|
begin
|
|
if Assigned(IDEComponentPalette)
|
|
then begin
|
|
for i := 0 to IDEComponentPalette.Count-1 do
|
|
begin
|
|
APage := IDEComponentPalette.Pages[i];
|
|
if not APage.Visible then continue;
|
|
for j := 0 to APage.Count-1 do
|
|
begin
|
|
AComponent := APage.Items[j];
|
|
if not AComponent.Visible then continue;
|
|
if AComponent.PageName='' then continue;
|
|
FComponentList.Add(AComponent);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TComponentListForm.UpdateComponentSelection(Sender: TObject);
|
|
//Apply the filter and fill the three tabsheets
|
|
var
|
|
AComponent: TRegisteredComponent;
|
|
AFilter, AClassName: string;
|
|
AClassList, List: TStringlist;
|
|
i, j, AIndex: Integer;
|
|
ANode: TTreeNode;
|
|
AClass: TClass;
|
|
begin
|
|
if Processing
|
|
then exit;
|
|
Processing := true;
|
|
FTimer.Enabled := false;
|
|
Screen.Cursor := crHourGlass;
|
|
try
|
|
AFilter := UpperCase(PatternEdit.Text);
|
|
|
|
//First tabsheet (ListboxComponents)
|
|
ListboxComponents.Items.BeginUpdate;
|
|
try
|
|
ListboxComponents.Items.Clear;
|
|
for i := 0 to FComponentList.Count-1 do
|
|
begin
|
|
AComponent := TRegisteredComponent(FComponentList[i]);
|
|
AClassName := AComponent.ComponentClass.ClassName;
|
|
if (AFilter='') or (Pos(AFilter, UpperCase(AClassName))>0)
|
|
then ListboxComponents.Items.AddObject(AClassName, AComponent);
|
|
end;
|
|
finally
|
|
ListboxComponents.Items.EndUpdate;
|
|
end;
|
|
|
|
//Second tabsheet (palette layout)
|
|
TreePallette.BeginUpdate;
|
|
try
|
|
TreePallette.Items.Clear;
|
|
for i := 0 to FComponentList.Count-1 do
|
|
begin
|
|
AComponent := TRegisteredComponent(FComponentList[i]);
|
|
AClassName := AComponent.ComponentClass.ClassName;
|
|
if (AFilter='') or (Pos(AFilter, UpperCase(AClassName))>0)
|
|
then begin
|
|
//find out parent node
|
|
ANode := TreePallette.Items.FindTopLvlNode(AComponent.PageName);
|
|
if ANode = nil
|
|
then ANode := TreePallette.Items.AddChild(nil, AComponent.PageName);
|
|
//add the item
|
|
TreePallette.Items.AddChildObject(ANode, AClassName, AComponent);
|
|
end;
|
|
end;
|
|
TreePallette.FullExpand;
|
|
finally
|
|
TreePallette.EndUpdate;
|
|
end;
|
|
|
|
|
|
//Third tabsheet (component inheritence)
|
|
List := TStringlist.Create;
|
|
AClassList:= TStringlist.Create;
|
|
TreeInheritance.Items.BeginUpdate;
|
|
try
|
|
TreeInheritance.Items.Clear;
|
|
AClassList.Sorted := true;
|
|
AClassList.CaseSensitive := false;
|
|
AClassList.Duplicates := dupIgnore;
|
|
|
|
for i := 0 to FComponentList.Count-1 do
|
|
begin
|
|
AComponent := TRegisteredComponent(FComponentList[i]);
|
|
AClassName := AComponent.ComponentClass.ClassName;
|
|
if (AFilter='') or (Pos(AFilter, UpperCase(AClassName))>0)then
|
|
begin
|
|
|
|
// walk down to parent, stop on tcomponent, since components are at least
|
|
// a tcomponent descendant
|
|
List.Clear;
|
|
AClass := AComponent.ComponentClass;
|
|
while (AClass.ClassInfo <> nil) and (AClass.ClassType <> TComponent.ClassType) do
|
|
begin
|
|
List.AddObject(AClass.ClassName, TObject(AClass));
|
|
AClass := AClass.ClassParent;
|
|
end;
|
|
|
|
//build the tree
|
|
for j := List.Count - 1 downto 0 do
|
|
begin
|
|
AClass := TClass(List.Objects[j]);
|
|
AClassName := List[j];
|
|
|
|
if not AClassList.Find(AClassName, AIndex)
|
|
then begin
|
|
//find out parent position
|
|
if Assigned(AClass.ClassParent) and AClassList.Find(AClass.ClassParent.ClassName, AIndex)
|
|
then ANode := TTreeNode(AClassList.Objects[AIndex])
|
|
else ANode := nil;
|
|
|
|
//add the item
|
|
if AClassName <> AComponent.ComponentClass.ClassName
|
|
then ANode := TreeInheritance.Items.AddChild(ANode, AClassName)
|
|
else ANode := TreeInheritance.Items.AddChildObject(ANode, AClassName, AComponent);
|
|
AClassList.AddObject(AClassName, ANode);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
TreeInheritance.AlphaSort;
|
|
TreeInheritance.FullExpand;
|
|
finally
|
|
List.Free;
|
|
AClassList.Free;
|
|
TreeInheritance.Items.EndUpdate;
|
|
end;
|
|
|
|
finally
|
|
Screen.Cursor := crDefault;
|
|
Processing := false;
|
|
end;
|
|
end;
|
|
|
|
procedure TComponentListForm.AddSelectedComponent(AComponent: TRegisteredComponent ) ;
|
|
//Add the DblClicked component to the current designed form
|
|
var
|
|
CompIntf, ParentCI: TIComponentInterface;
|
|
TypeClass: TComponentClass;
|
|
X, Y: integer;
|
|
begin
|
|
if not Assigned(AComponent)
|
|
then Exit;
|
|
if not Assigned(FormEditingHook)
|
|
then Exit;
|
|
//TComponentPalette(IDEComponentPalette).Selected := AComponent;
|
|
|
|
TypeClass:=AComponent.ComponentClass;
|
|
ParentCI:=FormEditingHook.GetDefaultComponentParent(TypeClass);
|
|
if ParentCI=nil
|
|
then exit;
|
|
|
|
//Would be lovely if it would only select the component as if it was
|
|
//clicked in the pallette bar so you can drop it on your own position.
|
|
if not FormEditingHook.GetDefaultComponentPosition(TypeClass,ParentCI,X,Y)
|
|
then exit;
|
|
|
|
CompIntf:=FormEditingHook.CreateComponent(ParentCI,TypeClass,'',X,Y,0,0);
|
|
if Assigned(CompIntf)
|
|
then GlobalDesignHook.PersistentAdded(CompIntf.Component,true);
|
|
end;
|
|
|
|
procedure TComponentListForm.ListboxComponentsDblClick(Sender: TObject);
|
|
begin
|
|
AddSelectedComponent(TRegisteredComponent(ListboxComponents.Items.Objects[ListboxComponents.ItemIndex]));
|
|
end;
|
|
|
|
procedure TComponentListForm.TreePalletteDblClick(Sender: TObject);
|
|
var
|
|
AComponent: TRegisteredComponent;
|
|
begin
|
|
if not Assigned(TreePallette.Selected)
|
|
then exit;
|
|
AComponent := TRegisteredComponent(TreePallette.Selected.Data);
|
|
if not Assigned(AComponent)
|
|
then exit;
|
|
|
|
AddSelectedComponent(AComponent);
|
|
end;
|
|
|
|
procedure TComponentListForm.TreeInheritanceDblClick(Sender:TObject);
|
|
var
|
|
AComponent: TRegisteredComponent;
|
|
begin
|
|
if not Assigned(TreeInheritance.Selected)
|
|
then exit;
|
|
AComponent := TRegisteredComponent(TreeInheritance.Selected.Data);
|
|
if not Assigned(AComponent)
|
|
then exit;
|
|
AddSelectedComponent(AComponent);
|
|
end;
|
|
|
|
procedure TComponentListForm.FormShow(Sender: TObject);
|
|
begin
|
|
if PatternEdit.Canfocus
|
|
then PatternEdit.SetFocus;
|
|
end;
|
|
|
|
procedure TComponentListForm.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
|
|
//Close the form on escape key like every other IDE dialog does
|
|
begin
|
|
if Key=VK_ESCAPE
|
|
then Close;
|
|
end;
|
|
|
|
procedure TComponentListForm.PatternEditChange(Sender: TObject);
|
|
begin
|
|
//Reset for proper delay
|
|
FTimer.Enabled := false;
|
|
FTimer.Enabled := true;
|
|
end;
|
|
|
|
procedure TComponentListForm.Timer1Timer(Sender: TObject);
|
|
begin
|
|
UpdateComponentSelection(nil);
|
|
end;
|
|
|
|
|
|
|
|
initialization
|
|
{$I componentlist.lrs}
|
|
|
|
end.
|
|
|