lazarus/ide/componentlist.pas

886 lines
28 KiB
ObjectPascal

{
***************************************************************************
* *
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. *
* *
***************************************************************************
Author: Marius
Modified by Juha Manninen, Balazs Szekely
Abstract:
A dialog to quickly find components and to add the found component
to the designed form.
}
unit ComponentList;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,
// LCL
LCLType, Forms, Controls, Graphics, StdCtrls, ExtCtrls, ComCtrls, Menus, Buttons,
Dialogs, ImgList,
// LazUtils
LazLoggerBase, LazUTF8, LazFileCache, AvgLvlTree,
// LazControls
TreeFilterEdit,
// BuildIntf
ComponentReg,
// IdeIntf
FormEditingIntf, IDEImagesIntf, PropEdits, MenuIntf, LazIDEIntf, TextTools,
// IDE
LazarusIDEStrConsts, ComponentPalette, PackageDefs, IDEOptionDefs, EnvGuiOptions,
Designer;
const
ComponentListMenuRootName = 'ComponentList';
var
// menu section CompListMenuSectionOpen
CompListMenuOpenUnit: TIDEMenuCommand;
CompListMenuOpenPackage: TIDEMenuCommand;
// menu section CompListMenuSectionExpand
CompListMenuExpand: TIDEMenuCommand;
CompListMenuExpandAll: TIDEMenuCommand;
// menu section CompListMenuSectionCollapse
CompListMenuCollapse: TIDEMenuCommand;
CompListMenuCollapseAll: TIDEMenuCommand;
type
{ TComponentListForm }
TComponentListForm = class(TForm)
chbKeepOpen: TCheckBox;
ButtonPanel: TPanel;
OKButton: TButton;
LabelSearch: TLabel;
PageControl: TPageControl;
FilterPanel: TPanel;
ListTree: TTreeView;
PalletteTree: TTreeView;
InheritanceTree: TTreeView;
pnPaletteTree: TPanel;
Panel6: TPanel;
Panel7: TPanel;
CompListPopupMenu: TPopupMenu;
TabSheetPaletteTree: TTabSheet;
TabSheetInheritance: TTabSheet;
TabSheetList: TTabSheet;
tmDeselect: TTimer;
TreeFilterEd: TTreeFilterEdit;
SelectionToolButton: TSpeedButton;
procedure chbKeepOpenChange(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure TreeMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ListTreeSelectionChanged(Sender: TObject);
procedure miCollapseAllClick(Sender: TObject);
procedure miCollapseClick(Sender: TObject);
procedure miExpandAllClick(Sender: TObject);
procedure miExpandClick(Sender: TObject);
procedure OKButtonClick(Sender: TObject);
procedure ComponentsDblClick(Sender: TObject);
procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
procedure CompListPopupMenuPopup(Sender: TObject);
procedure tmDeselectTimer(Sender: TObject);
procedure TreeFilterEdAfterFilter(Sender: TObject);
procedure PageControlChange(Sender: TObject);
function TreeFilterEdFilterItemEx(const ACaption: string;
{%H-}ItemData: Pointer; out Done: Boolean): Boolean;
procedure TreeFilterEdKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure TreeKeyPress(Sender: TObject; var Key: char);
procedure FormKeyDown(Sender: TObject; var Key: Word; {%H-}Shift: TShiftState);
procedure SelectionToolButtonClick(Sender: TObject);
private
FOnOpenPackage: TNotifyEvent;
FOnOpenUnit: TNotifyEvent;
FOnClassSelected: TNotifyEvent;
PrevChangeStamp: Integer;
FInitialized: Boolean;
FIgnoreSelection: Boolean;
FPageControlChange: Boolean;
FActiveTree: TTreeView;
FAddCompNewLeft, FAddCompNewTop: Integer;
FAddCompNewParent: TComponent;
procedure ClearSelection;
procedure ComponentWasAdded({%H-}ALookupRoot, {%H-}AComponent: TComponent;
{%H-}ARegisteredComponent: TRegisteredComponent);
procedure miOpenPackage(Sender: TObject);
procedure miOpenUnit(Sender: TObject);
procedure SelectionWasChanged;
procedure AddComponentInheritanceNodes(ClassToNodeTree: TPointerToPointerTree; Comp: TRegisteredComponent);
procedure UpdateComponents;
procedure UpdateButtonState;
function IsDocked: Boolean;
procedure AddSelectedComponent(ASaveSelection: boolean = false; AAddNeighboring: boolean = false);
protected
procedure UpdateShowing; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function GetSelectedComponent: TRegisteredComponent;
function GetSelectedPkgComp: TPkgComponent;
property OnOpenPackage: TNotifyEvent read FOnOpenPackage write FOnOpenPackage;
property OnOpenUnit: TNotifyEvent read FOnOpenUnit write FOnOpenUnit;
property OnClassSelected: TNotifyEvent read FOnClassSelected write FOnClassSelected;
end;
var
ComponentListForm: TComponentListForm;
procedure RegisterStandardComponentListMenuItems;
implementation
{$R *.lfm}
procedure RegisterStandardComponentListMenuItems;
var
AParent: TIDEMenuSection;
begin
ComponentListMenuRoot := RegisterIDEMenuRoot(ComponentListMenuRootName);
// register the section for open
CompListMenuSectionOpen:=RegisterIDEMenuSection(ComponentListMenuRoot,'Open');
AParent:=CompListMenuSectionOpen;
CompListMenuOpenUnit:=RegisterIDEMenuCommand(AParent,'Open Unit','Open Unit');// resourcestring is set later
CompListMenuOpenPackage:=RegisterIDEMenuCommand(AParent,'Open Package','Open Package'); // resourcestring is set later
// register the section for expand
CompListMenuSectionExpand:=RegisterIDEMenuSection(ComponentListMenuRoot,'Expand');
AParent:=CompListMenuSectionExpand;
CompListMenuExpand:=RegisterIDEMenuCommand(AParent, 'Expand', lisExpand);
CompListMenuExpandAll:=RegisterIDEMenuCommand(AParent, 'Expand All', lisExpandAll2);
// register the section for collapse
CompListMenuSectionCollapse:=RegisterIDEMenuSection(ComponentListMenuRoot,'Collapse');
AParent:=CompListMenuSectionCollapse;
CompListMenuCollapse:=RegisterIDEMenuCommand(AParent, 'Collapse', lisCollapse);
CompListMenuCollapseAll:=RegisterIDEMenuCommand(AParent, 'Collapse All',lisCollapseAll2);
end;
function GetSelectedDesignComponent: TComponent;
var
ASelections: TPersistentSelectionList;
begin
Result := nil;
ASelections := TPersistentSelectionList.Create;
try
GlobalDesignHook.GetSelection(ASelections);
if (ASelections.Count > 0) and (ASelections[0] is TComponent) then
Result := TComponent(ASelections[0])
else if GlobalDesignHook.LookupRoot is TComponent then
Result := TComponent(GlobalDesignHook.LookupRoot);
finally
ASelections.Free;
end;
end;
function GetSelectedTreeComp(aTree: TTreeView): TRegisteredComponent;
begin
if Assigned(aTree.Selected) then
Result := TRegisteredComponent(aTree.Selected.Data)
else
Result := nil;
end;
function GetRegCompClassname(RegComp: TRegisteredComponent): string;
begin
Result:=RegComp.ComponentClass.ClassName;
if RegComp.HasAmbiguousClassName then
Result:=Result+'('+RegComp.ComponentClass.UnitName+')';
end;
procedure SelectTreeComp(aTree: TTreeView);
var
Node: TTreeNode;
begin
with IDEComponentPalette do
if Assigned(Selected) then
Node := aTree.Items.FindNodeWithText(GetRegCompClassname(Selected))
else
Node := Nil;
aTree.Selected := Node;
if aTree.Selected <> nil then
aTree.Selected.MakeVisible;
end;
{ TComponentListForm }
constructor TComponentListForm.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Name:=NonModalIDEWindowNames[nmiwComponentList];
FActiveTree := ListTree;
IDEImages.AssignImage(SelectionToolButton, 'tmouse');
with SelectionToolButton do begin
ShowHint := EnvironmentGuiOpts.ShowHintsForComponentPalette;
Width := ComponentPaletteBtnWidth;
BorderSpacing.Around := (FilterPanel.Height - ComponentPaletteImageHeight) div 2;
end;
//Translations
LabelSearch.Caption := lisMenuFind;
Caption := lisCmpLstComponents;
TabSheetList.Caption := lisCmpLstList;
TabSheetPaletteTree.Caption := lisCmpLstPalette;
TabSheetInheritance.Caption := lisCmpLstInheritance;
OKButton.Caption := lisUse;
chbKeepOpen.Caption := lisKeepOpen;
SelectionToolButton.Hint := lisSelectionTool;
ListTree.Images := TPaletteComponent.Images;
PalletteTree.Images := TPaletteComponent.Images;
InheritanceTree.Images := TPaletteComponent.Images;
if Assigned(IDEComponentPalette) then
begin
UpdateComponents;
TreeFilterEd.InvalidateFilter;
IDEComponentPalette.AddHandlerComponentAdded(@ComponentWasAdded);
IDEComponentPalette.AddHandlerSelectionChanged(@SelectionWasChanged);
IDEComponentPalette.AddHandlerUpdated(@UpdateComponents);
end;
chbKeepOpen.Checked := EnvironmentGuiOpts.ComponentListKeepOpen;
PageControl.PageIndex := EnvironmentGuiOpts.ComponentListPageIndex;
PageControlChange(Nil);
end;
destructor TComponentListForm.Destroy;
begin
if Assigned(IDEComponentPalette) then begin
IDEComponentPalette.RemoveHandlerUpdated(@UpdateComponents);
IDEComponentPalette.RemoveHandlerSelectionChanged(@SelectionWasChanged);
IDEComponentPalette.RemoveHandlerComponentAdded(@ComponentWasAdded);
end;
ComponentListForm := nil;
inherited Destroy;
end;
procedure TComponentListForm.AddSelectedComponent(ASaveSelection: boolean; AAddNeighboring: boolean);
var
AComponent: TRegisteredComponent;
NewParent: TComponent;
CurDesigner: TDesigner;
lOldEvent: TOnComponentAdded;
TypeClass: TComponentClass;
begin
AComponent := GetSelectedComponent;
NewParent := GetSelectedDesignComponent;
// get parent component of neighboring component
if AAddNeighboring and assigned(NewParent) then
begin
if (not (NewParent is TCustomForm)) and
(not (NewParent is TCustomFrame)) then
begin
if NewParent.HasParent then
NewParent := NewParent.GetParentComponent;
end;
end;
if NewParent = nil then
Exit;
// get designer
CurDesigner := TDesigner(FindRootDesigner(NewParent));
if CurDesigner = nil then
Exit;
// get component class (e.g. display dialog to select TFrame)
TypeClass := AComponent.GetCreationClass;
if TypeClass = nil then
Exit;
// check parent
CurDesigner.AddComponentCheckParent(NewParent, NewParent, nil, TypeClass);
if NewParent = nil then
Exit;
// calculate offset
if FAddCompNewParent <> NewParent then
begin
FAddCompNewLeft := 0;
FAddCompNewTop := 0;
FAddCompNewParent := NewParent;
end;
Inc(FAddCompNewLeft, EnvironmentGuiOpts.GridSizeX);
Inc(FAddCompNewTop, EnvironmentGuiOpts.GridSizeY);
// add component
if ASaveSelection then
begin
lOldEvent := CurDesigner.OnComponentAdded; // save event
CurDesigner.OnComponentAdded := nil; // clear event
CurDesigner.AddComponent(AComponent, TypeClass, NewParent, FAddCompNewLeft, FAddCompNewTop, 0, 0);
CurDesigner.OnComponentAdded := lOldEvent; // restore event
end else begin
CurDesigner.AddComponent(AComponent, TypeClass, NewParent, FAddCompNewLeft, FAddCompNewTop, 0, 0);
end;
end;
procedure TComponentListForm.chbKeepOpenChange(Sender: TObject);
begin
EnvironmentGuiOpts.ComponentListKeepOpen := chbKeepOpen.Checked;
end;
procedure TComponentListForm.FormShow(Sender: TObject);
begin
//DebugLn(['*** TComponentListForm.FormShow, Parent=', Parent, ', Parent.Parent=', ParentParent]);
ButtonPanel.Visible := not IsDocked;
if ButtonPanel.Visible then
begin // ComponentList is undocked
PageControl.AnchorSideBottom.Side := asrTop;
UpdateButtonState;
if TreeFilterEd.CanSetFocus then // Focus filter if window is undocked and top parent can focus
TreeFilterEd.SetFocus;
TreeFilterEd.SelectAll;
end
else // ComponentList is docked
PageControl.AnchorSideBottom.Side := asrBottom;
end;
procedure TComponentListForm.ClearSelection;
begin
ListTree.Selected := Nil;
PalletteTree.Selected := Nil;
InheritanceTree.Selected := Nil;
end;
function TComponentListForm.GetSelectedComponent: TRegisteredComponent;
begin
Result := nil;
if ListTree.IsVisible then
Result := GetSelectedTreeComp(ListTree)
else if PalletteTree.IsVisible then
Result := GetSelectedTreeComp(PalletteTree)
else if InheritanceTree.IsVisible then
Result := GetSelectedTreeComp(InheritanceTree)
end;
function TComponentListForm.GetSelectedPkgComp: TPkgComponent;
begin
Result:=GetSelectedComponent as TPkgComponent;
end;
function TComponentListForm.IsDocked: Boolean;
begin
Result := (HostDockSite<>Nil) and (HostDockSite.Parent<>Nil);
end;
procedure TComponentListForm.ComponentWasAdded(ALookupRoot, AComponent: TComponent;
ARegisteredComponent: TRegisteredComponent);
begin
ClearSelection;
UpdateButtonState;
end;
procedure TComponentListForm.miOpenPackage(Sender: TObject);
var
PkgComponent: TPkgComponent;
begin
PkgComponent:=GetSelectedPkgComp;
if (PkgComponent=nil) or (PkgComponent.PkgFile=nil)
or (PkgComponent.PkgFile.LazPackage=nil) then exit;
if Assigned(OnOpenPackage) then
OnOpenPackage(PkgComponent.PkgFile.LazPackage);
end;
procedure TComponentListForm.miOpenUnit(Sender: TObject);
var
PkgComponent: TPkgComponent;
begin
PkgComponent:=GetSelectedPkgComp;
if (PkgComponent=nil) or (PkgComponent.PkgFile=nil)
or (PkgComponent.PkgFile.LazPackage=nil) then exit;
if Assigned(OnOpenUnit) then
OnOpenUnit(PkgComponent);
end;
procedure TComponentListForm.SelectionWasChanged;
begin
SelectionToolButton.Down := (IDEComponentPalette.Selected = nil);
if FIgnoreSelection then
Exit;
if ListTree.IsVisible then
SelectTreeComp(ListTree)
else if PalletteTree.IsVisible then
SelectTreeComp(PalletteTree)
else if InheritanceTree.IsVisible then
SelectTreeComp(InheritanceTree)
end;
procedure TComponentListForm.UpdateButtonState;
begin
OKButton.Enabled := Assigned(GetSelectedComponent);
end;
procedure TComponentListForm.UpdateShowing;
begin
if (ButtonPanel<>nil) and ButtonPanel.Visible then
UpdateButtonState;
inherited UpdateShowing;
end;
procedure TComponentListForm.AddComponentInheritanceNodes(
ClassToNodeTree: TPointerToPointerTree; Comp: TRegisteredComponent);
// Walk down to parent, stop on TComponent,
// since components are at least TComponent descendants.
var
InheritanceList: TFPList;
aClass: TClass;
Node, ParentNode: TTreeNode;
aClassName: string;
i: Integer;
II: TImageIndex;
CurRegComp: TRegisteredComponent;
begin
InheritanceList := TFPList.Create;
try
aClass := Comp.ComponentClass;
while (aClass.ClassInfo <> nil) and (aClass.ClassType <> TComponent.ClassType) do
begin
InheritanceList.Add(TObject(aClass));
aClass := aClass.ClassParent;
end;
// Build the tree
ParentNode:=nil;
for i := InheritanceList.Count - 1 downto 0 do
begin
aClass := TClass(InheritanceList[i]);
Node:=TTreeNode(ClassToNodeTree[aClass]);
if Node=nil then
begin
if aClass=Comp.ComponentClass then
CurRegComp:=Comp
else
CurRegComp:=IDEComponentPalette.FindRegComponent(aClass);
if CurRegComp<>nil then
aClassName:=GetRegCompClassname(CurRegComp)
else
aClassName:=aClass.ClassName;
// Add the node
Node := InheritanceTree.Items.AddChildObject(ParentNode, aClassName, CurRegComp);
ClassToNodeTree[aClass]:=Node;
if CurRegComp is TPaletteComponent then
II := TPaletteComponent(CurRegComp).ImageIndex
else
II := -1;
if II>=0 then
begin
Node.ImageIndex := II;
Node.SelectedIndex := II;
end;
end;
ParentNode:=Node;
end;
finally
InheritanceList.Free;
end;
end;
procedure TComponentListForm.UpdateComponents;
// Fill all three tabsheets: Flat list, Palette layout and Component inheritence.
var
Pg: TBaseComponentPage;
Comps: TRegisteredCompList;
Comp: TRegisteredComponent;
ParentNode: TTreeNode;
AListNode: TTreeNode;
APaletteNode: TTreeNode;
i, j: Integer;
CurIcon: TImageIndex;
aClassName: String;
aClassToTreeNode: TPointerToPointerTree;
begin
if [csDestroying,csLoading]*ComponentState<>[] then exit;
Screen.BeginWaitCursor;
ListTree.BeginUpdate;
PalletteTree.BeginUpdate;
InheritanceTree.Items.BeginUpdate;
aClassToTreeNode := TPointerToPointerTree.Create;
try
ListTree.Items.Clear;
PalletteTree.Items.Clear;
InheritanceTree.Items.Clear;
// ParentInheritence := InheritanceTree.Items.Add(nil, 'TComponent');
// FClassList.AddObject('TComponent', ParentInheritence);
// Iterate all pages
for i := 0 to IDEComponentPalette.Pages.Count-1 do
begin
Pg := IDEComponentPalette.Pages[i];
if not Pg.Visible then Continue;
Comps := IDEComponentPalette.RefUserCompsForPage(Pg.PageName);
// Palette layout Page header
ParentNode := PalletteTree.Items.AddChild(nil, Pg.PageName);
// Iterate components of one page
for j := 0 to Comps.Count-1 do begin
Comp := Comps[j];
if not Comp.Visible then Continue;
aClassName := GetRegCompClassname(Comp);
// Flat list item
AListNode := ListTree.Items.AddChildObject(Nil, aClassName, Comp);
// Palette layout item
APaletteNode := PalletteTree.Items.AddChildObject(ParentNode, aClassName, Comp);
if Comp is TPaletteComponent then
CurIcon := TPaletteComponent(Comp).ImageIndex
else
CurIcon := -1;
if CurIcon>=0 then
begin
AListNode.ImageIndex := CurIcon;
AListNode.SelectedIndex := AListNode.ImageIndex;
APaletteNode.ImageIndex := AListNode.ImageIndex;
APaletteNode.SelectedIndex := AListNode.ImageIndex;
end;
// Component inheritence item
AddComponentInheritanceNodes(aClassToTreeNode,Comp);
end;
end;
InheritanceTree.AlphaSort;
{$IFnDEF NoComponentListTreeExpand}
InheritanceTree.FullExpand; // Some users may not want the trees expanded.
PalletteTree.FullExpand;
{$ENDIF}
PrevChangeStamp := IDEComponentPalette.ChangeStamp;
finally
aClassToTreeNode.Free;
InheritanceTree.Items.EndUpdate;
PalletteTree.EndUpdate;
ListTree.EndUpdate;
Screen.EndWaitCursor;
end;
end;
procedure TComponentListForm.TreeFilterEdAfterFilter(Sender: TObject);
begin
if TreeFilterEd.Filter = '' then
IDEComponentPalette.SetSelectedComp(nil, False);
UpdateButtonState;
end;
procedure TComponentListForm.ComponentsDblClick(Sender: TObject);
// This is used for all 3 treeviews
begin
OKButtonClick(nil); // Select and close this form
end;
procedure TComponentListForm.ListTreeSelectionChanged(Sender: TObject);
var
AComponent: TRegisteredComponent;
begin
UpdateButtonState;
if FInitialized then
begin
if FPageControlChange then
Exit;
AComponent:=GetSelectedComponent;
if AComponent<>nil then
IDEComponentPalette.SetSelectedComp(AComponent, ssShift in GetKeyShiftState)
else
begin
FIgnoreSelection := True;
IDEComponentPalette.SetSelectedComp(nil, False);
FIgnoreSelection := False;
end;
end
else begin
// Only run once when the IDE starts.
FInitialized := True;
IDEComponentPalette.SetSelectedComp(nil, False);
ListTree.Selected := Nil;
PalletteTree.Selected := Nil;
InheritanceTree.Selected := Nil;
end
end;
procedure TComponentListForm.TreeMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
// ignore right click to bring up context menu
if (Button <> mbLeft) or IsDocked or chbKeepOpen.Checked then Exit;
// show form editor
if assigned(OnClassSelected) then
OnClassSelected(self);
end;
procedure TComponentListForm.TreeKeyPress(Sender: TObject; var Key: char);
// This is used for all 3 treeviews
begin
if Key = Char(VK_RETURN) then
ComponentsDblClick(Sender);
end;
procedure TComponentListForm.PageControlChange(Sender: TObject);
begin
//DebugLn(['TComponentListForm.PageControlChange: Start']);
FPageControlChange := True;
case PageControl.PageIndex of
0: begin
TreeFilterEd.FilteredTreeview := ListTree;
FActiveTree := ListTree;
end;
1: begin
TreeFilterEd.FilteredTreeview := PalletteTree;
FActiveTree := PalletteTree;
end;
2: begin
TreeFilterEd.FilteredTreeview := InheritanceTree;
FActiveTree := InheritanceTree;
end;
end;
EnvironmentGuiOpts.ComponentListPageIndex := PageControl.PageIndex;
FActiveTree.BeginUpdate;
tmDeselect.Enabled := True;
end;
function TComponentListForm.TreeFilterEdFilterItemEx(const ACaption: string;
ItemData: Pointer; out Done: Boolean): Boolean;
begin
Done := true;
result := MultiWordSearch(TreeFilterEd.Text, ACaption);
end;
procedure TComponentListForm.TreeFilterEdKeyDown(Sender: TObject;
var Key: Word; Shift: TShiftState);
var
c: char;
begin
if KeyToQWERTY(Key, Shift, c) then
TreeFilterEd.SelText := c;
end;
procedure TComponentListForm.tmDeselectTimer(Sender: TObject);
begin
tmDeselect.Enabled := False;
FActiveTree.Selected := nil;
SelectionWasChanged;
FActiveTree.EndUpdate;
FPageControlChange := False;
end;
procedure TComponentListForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
ClearSelection;
IDEComponentPalette.Selected := Nil;
end;
procedure TComponentListForm.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
AComponent: TRegisteredComponent;
begin
// add a neighboring component and leave focus on the selected component
if (Key = VK_RETURN) and (Shift = [ssCtrl]) then
begin
AComponent := GetSelectedComponent;
if AComponent <> nil then
AddSelectedComponent(true, true);
if TreeFilterEd.CanSetFocus then // not necessarily here?
TreeFilterEd.SetFocus;
Key := 0;
exit;
end;
// add a child component and leave focus on the selected component
if (Key = VK_RETURN) and (Shift = [ssShift]) then
begin
AComponent := GetSelectedComponent;
if AComponent <> nil then
AddSelectedComponent(true);
if TreeFilterEd.CanSetFocus then // not necessarily here?
TreeFilterEd.SetFocus;
Key := 0;
exit;
end;
// close
if (Key = VK_ESCAPE) and (Shift = []) then
begin
if (IDEComponentPalette.Selected = nil) and not IsDocked then
Close // close only if no component is selected
else
ClearSelection; // unselect if component is selected
Key := 0;
exit;
end;
// set focus on filter
if (Key = VK_F) and (Shift = [ssCtrl]) then
begin
if TreeFilterEd.CanSetFocus then // not necessarily here?
TreeFilterEd.SetFocus;
Key := 0;
exit;
end;
// select tab - [Ctrl+Tab] and [Ctrl+Shift+Tab]
if (Key = VK_TAB) and ((Shift = [ssCtrl]) or (Shift = [ssCtrl, ssShift])) then
begin
with PageControl do
if Shift = [ssCtrl]
then PageIndex := ( PageIndex + 1) mod PageCount
else PageIndex := (PageCount + PageIndex - 1) mod PageCount; // add "PageCount" - so that there is no negative number
PageControlChange(Sender);
Key := 0;
exit;
end;
end;
procedure TComponentListForm.OKButtonClick(Sender: TObject);
// Select component from palette and close this form. User can insert the component.
var
AComponent: TRegisteredComponent;
OldFocusedControl: TWinControl;
begin
AComponent := GetSelectedComponent;
if AComponent=nil then
Exit;
OldFocusedControl := Screen.ActiveControl;
AddSelectedComponent;
if (OldFocusedControl<>nil) and OldFocusedControl.CanSetFocus then
OldFocusedControl.SetFocus; // AddComponent in docked mode steals focus to designer, get it back
if IsDocked or chbKeepOpen.Checked then Exit;
Close;
end;
procedure TComponentListForm.miCollapseAllClick(Sender: TObject);
begin
TreeFilterEd.FilteredTreeview.FullCollapse;
end;
procedure TComponentListForm.miCollapseClick(Sender: TObject);
var
Node: TTreeNode;
begin
Node := TreeFilterEd.FilteredTreeview.Selected;
if Node = nil then
Exit;
if (Node.Level > 0) and (Node.HasChildren = False) then
Node := Node.Parent;
Node.Collapse(True);
end;
procedure TComponentListForm.miExpandAllClick(Sender: TObject);
begin
TreeFilterEd.FilteredTreeview.FullExpand;
end;
procedure TComponentListForm.miExpandClick(Sender: TObject);
var
Node: TTreeNode;
begin
Node := TreeFilterEd.FilteredTreeview.Selected;
if Node = nil then
Exit;
if (Node.Level > 0) and (Node.HasChildren = False) then
Node := Node.Parent;
Node.Expand(True);
end;
procedure TComponentListForm.CompListPopupMenuPopup(Sender: TObject);
var
Node: TTreeNode;
PkgComponent: TPkgComponent;
APackage: TLazPackage;
PkgFile: TPkgFile;
ShownFilename, UnitFilename: String;
begin
//debugln(['TComponentListForm.CompListPopupMenuPopup ']);
ComponentListMenuRoot.MenuItem:=CompListPopupMenu.Items;
// expand/collapse
if (PageControl.ActivePage=TabSheetPaletteTree)
or (PageControl.ActivePage=TabSheetInheritance) then
begin
Node := TreeFilterEd.FilteredTreeview.Selected;
if Node = nil then
begin
CompListMenuExpand.Enabled := False;
CompListMenuCollapse.Enabled := False;
end
else
begin
CompListMenuExpand.Enabled := (Node.HasChildren) and (not Node.Expanded);
CompListMenuCollapse.Enabled := (Node.HasChildren) and (Node.Expanded);
end;
CompListMenuExpand.Visible := true;
CompListMenuExpandAll.Visible := true;
CompListMenuCollapse.Visible := true;
CompListMenuCollapseAll.Visible := true;
CompListMenuExpand.OnClick:=@miExpandClick;
CompListMenuExpandAll.OnClick:=@miExpandAllClick;
CompListMenuCollapse.OnClick:=@miCollapseClick;
CompListMenuCollapseAll.OnClick:=@miCollapseAllClick;
end else begin
CompListMenuExpand.Visible := false;
CompListMenuExpandAll.Visible := false;
CompListMenuCollapse.Visible := false;
CompListMenuCollapseAll.Visible := false;
end;
// open unit/package
PkgComponent:=GetSelectedPkgComp;
if (PkgComponent=nil) or (PkgComponent.PkgFile=nil) then
begin
CompListMenuOpenUnit.Caption:=lisOpenUnit;
CompListMenuOpenUnit.Visible:=false;
CompListMenuOpenPackage.Caption:=lisOpenPackage3;
CompListMenuOpenPackage.Visible:=false;
end else begin
PkgFile:=PkgComponent.PkgFile;
APackage:=PkgFile.LazPackage;
CompListMenuOpenPackage.Caption:=Format(lisCPOpenPackage, [APackage.IDAsString]);
CompListMenuOpenPackage.Visible:=true;
CompListMenuOpenPackage.OnClick:=@miOpenPackage;
ShownFilename:=PkgFile.Filename;
UnitFilename:=PkgFile.GetFullFilename;
if not FileExistsCached(UnitFilename) then begin
UnitFilename:=LazarusIDE.FindSourceFile(ExtractFilename(UnitFilename),
APackage.Directory,[]);
if FileExists(UnitFilename) then
UnitFilename:=ShownFilename;
end;
CompListMenuOpenUnit.Caption:=Format(lisCPOpenUnit, [ShownFilename]);
CompListMenuOpenUnit.Enabled:=FileExistsCached(UnitFilename);
CompListMenuOpenUnit.Visible:=true;
CompListMenuOpenUnit.OnClick:=@miOpenUnit;
end;
end;
procedure TComponentListForm.SelectionToolButtonClick(Sender: TObject);
begin
SelectionToolButton.Down := True;
IDEComponentPalette.SetSelectedComp(nil, False);
if IsDocked or chbKeepOpen.Checked then Exit;
// show form editor
if assigned(OnClassSelected) then
OnClassSelected(self);
end;
end.