IDE-Inspector: New package to allow live browsing of the IDE's forms and components

git-svn-id: trunk@27767 -
This commit is contained in:
martin 2010-10-20 05:40:36 +00:00
parent 8cb78fd8e6
commit 5aaab6fd72
5 changed files with 477 additions and 0 deletions

4
.gitattributes vendored
View File

@ -4,6 +4,10 @@
/COPYING.modifiedLGPL.txt -text svneol=unset#application/octet-stream
/COPYING.txt svneol=native#text/plain
/README.txt svneol=native#text/plain
components/IdeInspector/ideinspector.lpk svneol=native#text/xml
components/IdeInspector/ideinspector.pas svneol=native#text/pascal
components/IdeInspector/maininspector.lfm svneol=native#text/plain
components/IdeInspector/maininspector.pas svneol=native#text/pascal
components/README.txt svneol=native#text/plain
components/aggpas/Agg2DDemo.dpr svneol=native#text/plain
components/aggpas/aa_demo.dpr svneol=native#text/plain

View File

@ -0,0 +1,54 @@
<?xml version="1.0"?>
<CONFIG>
<Package Version="3">
<PathDelim Value="\"/>
<Name Value="IdeInspector"/>
<Author Value="M Friebe"/>
<CompilerOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<SearchPaths>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<GenerateDwarf Value="True"/>
<UseHeaptrc Value="True"/>
</Debugging>
</Linking>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Description Value="Inspect the internals of the IDE.
&quot;Here be dragons&quot; Be careful and save your data first"/>
<License Value="LGPL, same as LCL"/>
<Version Minor="1"/>
<Files Count="1">
<Item1>
<Filename Value="maininspector.pas"/>
<HasRegisterProc Value="True"/>
<UnitName Value="MainInspector"/>
</Item1>
</Files>
<Type Value="RunAndDesignTime"/>
<RequiredPkgs Count="3">
<Item1>
<PackageName Value="LCL"/>
</Item1>
<Item2>
<PackageName Value="IDEIntf"/>
</Item2>
<Item3>
<PackageName Value="FCL"/>
<MinVersion Major="1" Valid="True"/>
</Item3>
</RequiredPkgs>
<UsageOptions>
<UnitPath Value="$(PkgOutDir)"/>
</UsageOptions>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
</Package>
</CONFIG>

View File

@ -0,0 +1,21 @@
{ This file was automatically created by Lazarus. Do not edit!
This source is only used to compile and install the package.
}
unit IdeInspector;
interface
uses
MainInspector, LazarusPackageIntf;
implementation
procedure Register;
begin
RegisterUnit('MainInspector', @MainInspector.Register);
end;
initialization
RegisterPackage('IdeInspector', @Register);
end.

View File

@ -0,0 +1,123 @@
object IdeInspectForm: TIdeInspectForm
Left = 2033
Height = 479
Top = 182
Width = 498
Caption = 'IdeInspectForm'
ClientHeight = 479
ClientWidth = 498
Position = poDefault
LCLVersion = '0.9.29'
object ToolBar1: TToolBar
Left = 0
Height = 26
Top = 0
Width = 498
Caption = 'ToolBar1'
EdgeBorders = [ebBottom]
Images = ImageList1
ParentShowHint = False
ShowCaptions = True
ShowHint = True
TabOrder = 0
object btnComponent: TToolButton
Left = 32
Top = 0
AutoSize = True
DropdownMenu = popComponent
OnClick = btnComponentClick
Style = tbsDropDown
end
object btnSubComponent: TToolButton
Left = 67
Top = 0
AutoSize = True
DropdownMenu = popSubComponent
OnClick = btnSubComponentClick
Style = tbsDropDown
end
object ToolButton1: TToolButton
Left = 24
Top = 0
Width = 8
Caption = 'ToolButton1'
Style = tbsSeparator
end
object btnRemoveSelected: TToolButton
Left = 1
Top = 0
ImageIndex = 0
OnClick = btnRemoveSelectedClick
end
end
object TreeView1: TTreeView
Left = 0
Height = 453
Top = 26
Width = 217
Align = alLeft
DefaultItemHeight = 17
HideSelection = False
ReadOnly = True
RightClickSelect = True
TabOrder = 1
OnChange = TreeView1Change
OnClick = TreeView1Click
Options = [tvoAutoItemHeight, tvoKeepCollapsedNodes, tvoReadOnly, tvoRightClickSelect, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips, tvoThemedDraw]
end
object Splitter1: TSplitter
Left = 217
Height = 453
Top = 26
Width = 5
end
object popComponent: TPopupMenu
OnPopup = popComponentPopup
left = 80
top = 40
end
object popSubComponent: TPopupMenu
OnPopup = popSubComponentPopup
left = 192
top = 40
end
object ImageList1: TImageList
left = 290
top = 130
Bitmap = {
4C69010000001000000010000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006360
F80AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF007774FF1F7774
FF2BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00625FF82B5D5B
F76F5956F53EFFFFFF00FFFFFF00FFFFFF00FFFFFF007774FF1F7A77FFFF7976
FEFF726FFD2BFFFFFF00FFFFFF00FFFFFF00FFFFFF00615EF82B6461F8FF6A68
F9FF5451F3A84F4DF229FFFFFF00FFFFFF007774FF1F7A77FFFF817EFFFF817E
FEFF7471FDFF6C69FB2BFFFFFF00FFFFFF00605DF72B625FF8FF6F6DFBFF7E7C
FFFF625FF8FF4A47F06F4542EE02FFFFFF007673FF087471FEFD7D7AFEFF8A87
FFFF7C79FDFF6C69FBFF6361F92B5F5CF72B615EF8FF6E6CFAFF7D7AFFFF615F
F7FF4946F0FC4441EE05FFFFFF00FFFFFF00FFFFFF00716EFD086E6BFCFC7774
FDFF8682FFFF7673FCFF6462F8FF605DF7FF6D6AFAFF7B79FFFF605DF7FF4845
EFFC4341EE08FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006967FB086663
F9FC706DFBFF807EFFFF7E7BFFFF7C79FFFF7977FFFF5E5CF7FF4744EFFC4240
EE08FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00615E
F8085D5AF6FD7D79FFFF5E5BFFFF5B58FFFF7674FFFF4643EFFD413FED08FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005C59
F62B5D5BF7FF7976FFFF5956FFFF5754FFFF7270FFFF4846F0FF3C39EB2BFFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005B58F62B5C5A
F6FF6764FAFF7472FFFF7370FFFF706EFFFF6E6CFFFF5755F7FF3F3DEEFF3230
E82BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005A57F52B5B59F6FF6663
FAFF7471FFFF5A58F6FF4341EEFC3E3CECFD504DF4FF6867FFFF504EF5FF3634
EBFF2A27E52BFFFFFF00FFFFFF00FFFFFF005956F52B5B58F6FF6562FAFF7170
FFFF5956F6FF4240EEFC3E3BEC083937EB083532E9FC4745F2FF6362FFFF4A48
F4FF2F2DE9FF2220E32BFFFFFF00FFFFFF005451F3415856F5FF6361FAFF5855
F6FF413FEDFC3D3AEC08FFFFFF00FFFFFF00302DE7082C2AE6FC413FF1FF4C4A
F6FF312FEAFF1F1DE241FFFFFF00FFFFFF00FFFFFF004A47F0414F4CF2FF403E
EDFD3C39EB08FFFFFF00FFFFFF00FFFFFF00FFFFFF002725E5082422E4FC312F
EAFF1F1DE241FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003F3DED413B38
EB08FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00211FE3081E1C
E241FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00
}
end
end

View File

@ -0,0 +1,275 @@
unit MainInspector;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, Buttons,
ComCtrls, Menus, MenuIntf, ObjectInspector, types;
type
{ TIdeInspectForm }
TIdeInspectForm = class(TForm)
ImageList1: TImageList;
popComponent: TPopupMenu;
popSubComponent: TPopupMenu;
Splitter1: TSplitter;
ToolBar1: TToolBar;
btnComponent: TToolButton;
btnSubComponent: TToolButton;
ToolButton1: TToolButton;
btnRemoveSelected: TToolButton;
TreeView1: TTreeView;
procedure btnSubComponentClick(Sender: TObject);
procedure MenuItem1Click(Sender: TObject);
procedure btnComponentClick(Sender: TObject);
procedure popComponentPopup(Sender: TObject);
procedure popSubComponentPopup(Sender: TObject);
procedure btnRemoveSelectedClick(Sender: TObject);
procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
procedure TreeView1Click(Sender: TObject);
private
{ private declarations }
protected
FPropertiesGrid: TCustomPropertiesGrid;
FSelected: TComponent;
procedure SetSelected(AComp: TComponent);
procedure UpdateTree;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
public
{ public declarations }
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
end;
var
IdeInspectForm: TIdeInspectForm;
resourcestring
ideinspInspectIDE = 'Inspect IDE';
ideinspApplcicationComponents = 'Applcication.Components';
ideinspScreenForms = 'Screen.Forms';
ideinspQuickLinks = 'Quick links';
ideinspChildren = 'Children';
ideinspRemoveSelectedItemSFromTree = 'Remove selected item(s) from tree';
procedure Register;
implementation
{$R *.lfm}
type
{ TExtMenuItem }
TExtMenuItem = class(TMenuItem)
private
FTheObject: TPersistent;
public
property TheObject: TPersistent read FTheObject write FTheObject;
end;
{ TIdeInspectForm }
procedure TIdeInspectForm.MenuItem1Click(Sender: TObject);
begin
SetSelected(TComponent(TExtMenuItem(Sender).TheObject));
end;
procedure TIdeInspectForm.btnSubComponentClick(Sender: TObject);
begin
btnSubComponent.CheckMenuDropdown;
end;
procedure TIdeInspectForm.btnComponentClick(Sender: TObject);
begin
btnComponent.CheckMenuDropdown;
end;
procedure TIdeInspectForm.popComponentPopup(Sender: TObject);
var
m: TExtMenuItem;
i: Integer;
begin
popComponent.Items.Clear;
m := TExtMenuItem.Create(Self);
m.Caption := ideinspApplcicationComponents + ' (' + IntToStr(Application.ComponentCount) + ')' ;
m.Enabled := False;
popComponent.Items.Add(m);
for i := 0 to Application.ComponentCount - 1 do begin
m := TExtMenuItem.Create(Self);
m.Caption := Application.Components[i].Name +
' ['+Application.Components[i].ClassName+']'+
' ('+IntToStr(Application.Components[i].ComponentCount)+')';
m.TheObject := Application.Components[i];
m.OnClick := @MenuItem1Click;
popComponent.Items.Add(m);
end;
m := TExtMenuItem.Create(Self);
m.Caption := ideinspScreenForms + ' (' + IntToStr(Screen.FormCount) + ')' ;
m.Enabled := False;
popComponent.Items.Add(m);
for i := 0 to Screen.FormCount - 1 do begin
m := TExtMenuItem.Create(Self);
m.Caption := Screen.Forms[i].Name +
' ['+Screen.Forms[i].ClassName+']'+
' ('+IntToStr(Screen.Forms[i].ComponentCount)+')';
m.TheObject := Screen.Forms[i];
m.OnClick := @MenuItem1Click;
popComponent.Items.Add(m);
end;
end;
procedure TIdeInspectForm.popSubComponentPopup(Sender: TObject);
var
i: Integer;
m: TExtMenuItem;
begin
popSubComponent.Items.Clear;
for i := 0 to FSelected.ComponentCount - 1 do begin
m := TExtMenuItem.Create(Self);
m.Caption := FSelected.Components[i].Name +
' ['+FSelected.Components[i].ClassName+']'+
' ('+IntToStr(FSelected.Components[i].ComponentCount)+')';
m.TheObject := FSelected.Components[i];
m.OnClick := @MenuItem1Click;
popSubComponent.Items.Add(m);
end;
end;
procedure TIdeInspectForm.btnRemoveSelectedClick(Sender: TObject);
begin
if TreeView1.Selected = nil then
exit;
if TreeView1.Selected.Parent <> nil then
SetSelected(TComponent(TreeView1.Selected.Parent.Data))
else
SetSelected(nil);
TreeView1.Selected.Delete;
UpdateTree;
end;
procedure TIdeInspectForm.TreeView1Change(Sender: TObject; Node: TTreeNode);
begin
TreeView1Click(nil);
end;
procedure TIdeInspectForm.TreeView1Click(Sender: TObject);
begin
if (TreeView1.Selected = nil) or (TreeView1.Selected.Data = nil) then
exit;
SetSelected(TComponent(TreeView1.Selected.Data));
end;
procedure TIdeInspectForm.SetSelected(AComp: TComponent);
begin
FSelected := AComp;
FPropertiesGrid.TIObject := FSelected;
btnSubComponent.Enabled := (FSelected <> nil) and (FSelected.ComponentCount > 0);
UpdateTree;
end;
procedure TIdeInspectForm.UpdateTree;
function FindNode(AComp: TComponent): TTreeNode;
var
AParent: TTreeNode;
begin
Result := TreeView1.Items.FindNodeWithData(AComp);
if Result = nil then begin
if AComp.Owner <> nil then begin
AParent := FindNode(AComp.Owner);
Result := AParent.TreeNodes.AddChildObject
(AParent,
AComp.Name + ': ' + AComp.ClassName
+ ' ('+IntToStr(AComp.ComponentCount)+')'
+ ' ' + IntToHex(PtrUInt(AComp), 8),
AComp);
end else begin
Result := TreeView1.Items.AddObject
(nil,
AComp.Name + ': ' + AComp.ClassName
+ ' ('+IntToStr(AComp.ComponentCount)+')'
+ ' ' + IntToHex(PtrUInt(AComp), 8),
AComp);
end;
AComp.FreeNotification(Self);
end;
end;
var
ANode: TTreeNode;
begin
if FSelected = nil then exit;
ANode := FindNode(FSelected);
ANode.Expanded := True;
ANode.Selected := True;
end;
procedure TIdeInspectForm.Notification(AComponent: TComponent; Operation: TOperation);
var
ANode: TTreeNode;
begin
if (Operation = opRemove) and (TreeView1 <> nil) then begin
ANode := TreeView1.Items.FindNodeWithData(AComponent);
if ANode <> nil then begin
ANode.DeleteChildren;
if (AComponent = FSelected) or (TreeView1.Items.FindNodeWithData(FSelected) = nil) then begin
if ANode.Parent <> nil then
SetSelected(TComponent(ANode.Parent.Data))
else
SetSelected(nil);
end;
ANode.Delete;
UpdateTree;
end;
end;
inherited Notification(AComponent, Operation);
end;
constructor TIdeInspectForm.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
FPropertiesGrid := TCustomPropertiesGrid.Create(Self);
with FPropertiesGrid do
begin
Name := 'FPropertiesGrid';
Parent := self;
Align := alClient;
BorderSpacing.Around := 6;
end;
btnComponent.Caption := ideinspQuickLinks;
btnSubComponent.Caption := ideinspChildren;
btnRemoveSelected.Hint := ideinspRemoveSelectedItemSFromTree;
SetSelected(Application);
end;
destructor TIdeInspectForm.Destroy;
begin
FreeAndNil(TreeView1);
inherited Destroy;
end;
procedure IDEMenuClicked(Sender: TObject);
begin
if not Assigned(IdeInspectForm) then begin
IdeInspectForm := TIdeInspectForm.Create(Application);
end;
IdeInspectForm.Show;
end;
procedure Register;
begin
RegisterIDEMenuCommand(itmViewIDEInternalsWindows, 'mnuIdeInspector', ideinspInspectIDE, nil,
@IDEMenuClicked);
end;
end.