lazarus/components/IdeInspector/maininspector.pas
martin e476e14b73 IdeInspector: 2.4.0 comp
git-svn-id: trunk@28708 -
2010-12-13 21:33:10 +00:00

828 lines
24 KiB
ObjectPascal

unit MainInspector;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, Buttons,
ComCtrls, Menus, StdCtrls, MenuIntf, ObjectInspector, PropEdits, types, typinfo,
LazIDEIntf, LazConfigStorage, BaseIDEIntf, LCLProc, IdeInspectKeyGrapper, math;
type
{ THistoryEntry }
THistoryEntry = class
private
FBaseDisplay: string;
public
Comp: TComponent;
Display: string;
IdentifierName: string;
TheUnitName: string;
FileName: string;
Line: Integer;
procedure Assign(Other: THistoryEntry);
procedure UpdateDisplayName;
end;
{ TIdeInspectForm }
TIdeInspectForm = class(TForm)
ComboHistory: TComboBox;
EditUnit: TEdit;
EditFile: TEdit;
ImageList1: TImageList;
menuFollowForm: TMenuItem;
menuFollowFrame: TMenuItem;
Panel1: TPanel;
Panel2: TPanel;
popComponent: TPopupMenu;
popSubComponent: TPopupMenu;
popControls: TPopupMenu;
popFollowType: TPopupMenu;
btnOpenFile: TSpeedButton;
btnSaveHist: TSpeedButton;
Splitter1: TSplitter;
TabControl1: TTabControl;
ToolBar1: TToolBar;
btnComponent: TToolButton;
btnSubComponent: TToolButton;
ToolButton1: TToolButton;
btnRemoveSelected: TToolButton;
ToolButton2: TToolButton;
btnControls: TToolButton;
ToolButton3: TToolButton;
ToolButton4: TToolButton;
btnEndModal: TToolButton;
sepModal: TToolButton;
btnKeepTop: TToolButton;
ToolButtonKey: TToolButton;
ToolButtonActiveType: TToolButton;
ToolButtonFollowActive: TToolButton;
TreeView1: TTreeView;
procedure btnControlsClick(Sender: TObject);
procedure btnEndModalClick(Sender: TObject);
procedure btnKeepTopClick(Sender: TObject);
procedure btnOpenFileClick(Sender: TObject);
procedure btnSaveHistClick(Sender: TObject);
procedure btnSubComponentClick(Sender: TObject);
procedure ComboHistoryChange(Sender: TObject);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormShow(Sender: TObject);
procedure menuFollowFormClick(Sender: TObject);
procedure menuFollowFrameClick(Sender: TObject);
procedure MenuItem1Click(Sender: TObject);
procedure btnComponentClick(Sender: TObject);
procedure popComponentPopup(Sender: TObject);
procedure popControlsPopup(Sender: TObject);
procedure popSubComponentPopup(Sender: TObject);
procedure btnRemoveSelectedClick(Sender: TObject);
procedure TabControl1Change(Sender: TObject);
procedure ToolButtonActiveTypeClick(Sender: TObject);
procedure ToolButtonFollowActiveClick(Sender: TObject);
procedure ToolButtonKeyClick(Sender: TObject);
procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
procedure TreeView1Click(Sender: TObject);
private
{ private declarations }
FSelected: TComponent;
FFollowFrames: Boolean;
FHistoryList: TList;
FCurEntry: THistoryEntry;
FIsUpdatingHistory: Boolean;
FConf: TConfigStorage;
FKeyGrabForm: TIdeInspectKeyGrabForm;
FShortCutKey: Word;
FShortCutShift: TShiftState;
procedure DoPropSelChanged(Sender: TObject);
protected
FPropertiesGrid: TCustomPropertiesGrid;
procedure UpdateTree;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure DoActiveFormChanged(Sender: TObject; Form: TCustomForm);
procedure DoActiveControChanged(Sender: TObject; LastControl: TControl);
procedure DoKeyDownBefore(Sender: TObject; var Key: Word; Shift: TShiftState);
function IndexOfCurrent: Integer;
procedure SetSelected(AComp: TComponent);
procedure UpdateCurrent; // set to Fselected
procedure DisplayCurrent;
procedure UpdateHistory(ForceAdd: Boolean = False);
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';
ideinspComponentsOwned = 'Components (Owned)';
ideinspRemoveSelectedItemSFromTree = 'Remove selected item(s) from tree';
ideinspControlsChildren = 'Controls (Children)';
ideinspInspectingNameClass = 'Inspecting %s';
ideinspIdeInspector = 'Ide Inspector';
procedure Register;
implementation
{$R *.lfm}
const
MAX_HIST_CNT = 25;
IDE_INSPECT_CONF_FILE = 'ide_inspector_config.xml';
ShiftStateNames: Array [TShiftStateEnum] of string =
('ssShift', 'ssAlt', 'ssCtrl',
'ssLeft', 'ssRight', 'ssMiddle', 'ssDouble',
// Extra additions
'ssMeta', 'ssSuper', 'ssHyper', 'ssAltGr', 'ssCaps', 'ssNum',
'ssScroll', 'ssTriple', 'ssQuad', 'ssExtra1', 'ssExtra2');
var
OriginalBackTraceStrFunc: TBackTraceStrFunc;
type
{ TExtMenuItem }
TExtMenuItem = class(TMenuItem)
private
FTheObject: TPersistent;
public
property TheObject: TPersistent read FTheObject write FTheObject;
end;
{ THistoryEntry }
procedure THistoryEntry.Assign(Other: THistoryEntry);
begin
Comp := Other.Comp;
FBaseDisplay := Other.FBaseDisplay;
Display := Other.Display;
TheUnitName := Other.TheUnitName;
IdentifierName := Other.IdentifierName;
Line := Other.Line;
FileName := Other.FileName;
end;
procedure THistoryEntry.UpdateDisplayName;
begin
if Comp <> nil then begin
FBaseDisplay := Comp.Name + ': ' + Comp.ClassName;
Display := FBaseDisplay + ' (' + IntToHex(PtrUInt(Comp), SizeOf(Pointer)*2) + ')';
end else
Display := FBaseDisplay;
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.ComboHistoryChange(Sender: TObject);
var
i: LongInt;
begin
if FIsUpdatingHistory then exit;
i := ComboHistory.ItemIndex;
// ignore current entry re-select
if i <= 0 then
exit;
if ComboHistory.Items.Count > FHistoryList.Count then begin
ComboHistory.Items.Delete(0); // the none-history curent entry
dec(i);
end;
FCurEntry.Assign(THistoryEntry(FHistoryList[i]));
if i > 0 then begin
FHistoryList.Move(i, 0);
ComboHistory.Items.Move(i, 0);
end;
if FCurEntry.Comp <> nil then
SetSelected(FCurEntry.Comp);
DisplayCurrent;
end;
procedure TIdeInspectForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
FConf.SetDeleteValue('IDEInspect/FormPos/Left', Left, 400);
FConf.SetDeleteValue('IDEInspect/FormPos/top', Top, 50);
FConf.SetDeleteValue('IDEInspect/FormPos/Heigh', Height, 520);
FConf.SetDeleteValue('IDEInspect/FormPos/Width', Width, 500);
FConf.WriteToDisk;
end;
procedure TIdeInspectForm.FormShow(Sender: TObject);
begin
Left := FConf.GetValue('IDEInspect/FormPos/Left', 400);
Top := FConf.GetValue('IDEInspect/FormPos/top', 50);
Height := Max(220, FConf.GetValue('IDEInspect/FormPos/Heigh', 520));
Width := Max(280, FConf.GetValue('IDEInspect/FormPos/Width', 500));
//if Screen.MonitorFromPoint(IdeInspectForm.ClientToScreen
// (Point(IdeInspectForm.Left, IdeInspectForm.Top))) = nil
//then
MakeFullyVisible;
end;
procedure TIdeInspectForm.DoPropSelChanged(Sender: TObject);
var
i: LongInt;
Row: TOIPropertyGridRow;
Method: TMethod;
s, s2, OName: string;
MethName: String;
begin
Row := FPropertiesGrid.GetActiveRow;
Method.Code := nil;;
if (Row <> nil) then begin
if (Row.Editor is TMethodPropertyEditor) then begin
Method := TMethodPropertyEditor(Row.Editor).GetMethodValue;
FPropertiesGrid.PropertyEditorHook.LookupRoot := nil; // prevent edit
end
else
FPropertiesGrid.PropertyEditorHook.LookupRoot := FSelected;
end;
if Method.Code = nil then begin
UpdateCurrent;
exit;
end;
If TObject(Method.Data) is TComponent then
OName := '('+TComponent(Method.Data).Name+')'
else
OName := '';
MethName := TObject(Method.Data).MethodName(Method.Code);
s := MethName;;
if s = '' then
s := IntToHex(QWord(PtrUint(Method.Code)), 2*SizeOf(Pointer));
s := TObject(Method.Data).ClassName + OName + '.' + s;
FCurEntry.Line := -1;
try
s2 := Trim(OriginalBackTraceStrFunc(Method.Code));
i := pos(' ', s2);
if (s2 <> '') and (s2[1] = '$') and (i > 0) then
s2 := copy(s2, i, length(s));
if s2<>'' then
s := s + ' ' + s2;
i := pos('line ', LowerCase(s));
if i > 0 then begin
s2 := Trim(copy(s, i+4, length(s2)));
i := pos(' ', s2)-1;
if i < 1 then i := length(s2);
FCurEntry.Line := StrToIntDef(copy(s2, 1, i), -1);
end;
except
end;
FCurEntry.Display := s;
FCurEntry.Comp := nil;
FCurEntry.TheUnitName := GetClassUnitName(TObject(Method.Data).ClassType);
FCurEntry.FileName := LazarusIDE.FindUnitFile(FCurEntry.TheUnitName, LazarusIDE);
if MethName <> '' then
FCurEntry.IdentifierName := TObject(Method.Data).ClassName + '.' + MethName
else
FCurEntry.IdentifierName := '';
UpdateHistory;
end;
procedure TIdeInspectForm.menuFollowFormClick(Sender: TObject);
begin
FFollowFrames := False;
ToolButtonActiveType.Caption := menuFollowForm.Caption;
ToolButtonFollowActive.Down := True;
FConf.SetDeleteValue('IDEInspect/FollowActive/Type', 0, 0);
FConf.WriteToDisk;
end;
procedure TIdeInspectForm.menuFollowFrameClick(Sender: TObject);
begin
FFollowFrames := True;
ToolButtonActiveType.Caption := menuFollowFrame.Caption;
ToolButtonFollowActive.Down := True;
FConf.SetDeleteValue('IDEInspect/FollowActive/Type', 1, 0);
FConf.WriteToDisk;
end;
procedure TIdeInspectForm.btnControlsClick(Sender: TObject);
begin
btnControls.CheckMenuDropdown;
end;
procedure TIdeInspectForm.btnEndModalClick(Sender: TObject);
begin
ModalResult := mrOK;
end;
procedure TIdeInspectForm.btnKeepTopClick(Sender: TObject);
begin
if btnKeepTop.Down then
FormStyle := fsStayOnTop
else
FormStyle := fsNormal;
FConf.SetDeleteValue('IDEInspect/FormPos/KeepTop', btnKeepTop.Down, False);
FConf.WriteToDisk;
end;
procedure TIdeInspectForm.btnOpenFileClick(Sender: TObject);
begin
if (FCurEntry.IdentifierName <> '') and
(LazarusIDE.DoOpenFileAndJumpToIdentifier
(EditFile.Text, FCurEntry.IdentifierName, -1, -1, [ofOnlyIfExists, ofRegularFile])
= mrOK)
then
exit;
if FCurEntry.Line > 0 then
LazarusIDE.DoOpenFileAndJumpToPos(EditFile.Text, Point(1,FCurEntry.Line), Max(FCurEntry.Line-1,1), -1, -1, [ofOnlyIfExists, ofRegularFile])
else
LazarusIDE.DoOpenEditorFile(EditFile.Text, -1, -1, [ofOnlyIfExists, ofRegularFile]);
end;
procedure TIdeInspectForm.btnSaveHistClick(Sender: TObject);
begin
UpdateHistory(True);
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.popControlsPopup(Sender: TObject);
var
i: Integer;
m: TExtMenuItem;
begin
popControls.Items.Clear;
if (FSelected = nil) or not(FSelected is TWinControl) then
exit;
for i := 0 to TWinControl(FSelected).ControlCount - 1 do begin
m := TExtMenuItem.Create(Self);
m.Caption := TWinControl(FSelected).Controls[i].Name +
' ['+TWinControl(FSelected).Controls[i].ClassName+']'+
' ('+IntToStr(TWinControl(FSelected).Controls[i].ComponentCount)+')';
m.TheObject := TWinControl(FSelected).Controls[i];
m.OnClick := @MenuItem1Click;
popControls.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.TabControl1Change(Sender: TObject);
begin
case TabControl1.TabIndex of
0: FPropertiesGrid.Filter := [low(TTypeKind)..high(TTypeKind)] - [tkMethod];
1: FPropertiesGrid.Filter := [tkMethod];
2: FPropertiesGrid.Filter := [];
end;
end;
procedure TIdeInspectForm.ToolButtonActiveTypeClick(Sender: TObject);
begin
ToolButtonActiveType.CheckMenuDropdown;
end;
procedure TIdeInspectForm.ToolButtonFollowActiveClick(Sender: TObject);
begin
if ToolButtonFollowActive.Down then
SetSelected(Self);
FConf.SetDeleteValue('IDEInspect/FollowActive/Enabled', ToolButtonFollowActive.Down, False);
FConf.WriteToDisk;
end;
procedure TIdeInspectForm.ToolButtonKeyClick(Sender: TObject);
var
i: TShiftStateEnum;
begin
FKeyGrabForm.KeyBox.Key := FShortCutKey;
FKeyGrabForm.KeyBox.ShiftState := FShortCutShift;
if FKeyGrabForm.ShowModal = mrOK then begin
FShortCutKey := FKeyGrabForm.KeyBox.Key;
FShortCutShift := FKeyGrabForm.KeyBox.ShiftState;
FConf.SetDeleteValue('IDEInspect/KeyShortCut/Key', FShortCutKey, 0);
for i := low(TShiftStateEnum) to high(TShiftStateEnum) do
FConf.SetDeleteValue('IDEInspect/KeyShortCut/' + ShiftStateNames[i],
i in FShortCutShift, False);
FConf.WriteToDisk;
end;
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.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 begin
TreeView1.Selected := nil;
exit;
end;
ANode := FindNode(FSelected);
ANode.Expanded := True;
ANode.Selected := True;
end;
procedure TIdeInspectForm.Notification(AComponent: TComponent; Operation: TOperation);
var
ANode: TTreeNode;
i: Integer;
f: Boolean;
begin
if (Operation = opRemove) and (FCurEntry <> nil) and (FCurEntry.Comp = AComponent) then begin
FCurEntry.Comp := nil;
FCurEntry.UpdateDisplayName;
DisplayCurrent;
end;
if (Operation = opRemove) and (FHistoryList <> nil) then begin
f := False;
for i := 0 to FHistoryList.Count - 1 do
if THistoryEntry(FHistoryList[i]).Comp = AComponent then begin
THistoryEntry(FHistoryList[i]).Comp := nil;
THistoryEntry(FHistoryList[i]).UpdateDisplayName;
f := True;
end;
if f then
UpdateHistory;
end;
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
else
if AComponent = FSelected then
SetSelected(nil);
end;
inherited Notification(AComponent, Operation);
end;
procedure TIdeInspectForm.DoActiveFormChanged(Sender: TObject; Form: TCustomForm);
begin
If (not ToolButtonFollowActive.Down) or (not Self.Visible) then
exit;
if Form <> Self then
SetSelected(Form);
end;
procedure TIdeInspectForm.DoActiveControChanged(Sender: TObject; LastControl: TControl);
begin
If (not ToolButtonFollowActive.Down) or (not FFollowFrames) or (not Self.Visible) then
exit;
if Screen.ActiveForm = Self then
exit;
if (Screen.ActiveControl <> nil) and (Screen.ActiveControl.Owner <> nil) then
SetSelected(Screen.ActiveControl.Owner);
end;
procedure TIdeInspectForm.DoKeyDownBefore(Sender: TObject; var Key: Word; Shift: TShiftState);
var
CurVisible: Boolean;
begin
if (Screen.ActiveForm = self) or (Screen.ActiveForm = FKeyGrabForm) then exit;
if FShortCutKey = 0 then exit;
if (FShortCutKey <> Key) or (FShortCutShift <> Shift) then
exit;
Key := 0;
if Application.ModalLevel = 0 then begin
Self.Show;
exit;
end;
CurVisible := Visible;
Close;
DestroyHandle;
btnOpenFile.Visible := False;
btnSaveHist.Visible := True;
btnEndModal.Visible := True;
sepModal.Visible := True;
sepModal.Left := 1;
btnEndModal.Left := 1;
btnRemoveSelected.Left := 2;
if Self. ShowModal <> mrOK then
CurVisible := False;
btnSaveHist.Visible := False;
btnOpenFile.Visible := True;
btnEndModal.Visible := False;
sepModal.Visible := False;
Visible := CurVisible;
end;
function TIdeInspectForm.IndexOfCurrent: Integer;
begin
if FCurEntry.Comp = nil then exit(-1);;
Result := FHistoryList.Count - 1;
while (Result >= 0) and (THistoryEntry(FHistoryList[Result]).Comp <> FCurEntry.Comp) do
dec(Result);
end;
procedure TIdeInspectForm.UpdateHistory(ForceAdd: Boolean = False);
var
i: Integer;
FNewHist: THistoryEntry;
CanAdd: Boolean;
begin
FIsUpdatingHistory := True;
CanAdd := (FCurEntry.Comp is TCustomForm) or (FCurEntry.Comp is TCustomFrame)
or ForceAdd;
i := -1;
if (FCurEntry.Comp <> nil) and CanAdd then begin
i := IndexOfCurrent;
if i < 0 then begin
FNewHist := THistoryEntry.Create;
FNewHist.Assign(FCurEntry);
FHistoryList.Insert(0, FNewHist);
while FHistoryList.Count > MAX_HIST_CNT do begin
THistoryEntry(FHistoryList[FHistoryList.Count - 1]).Free;
FHistoryList.Delete(FHistoryList.Count - 1);
end;
end
else begin
if i > 0 then
FHistoryList.Move(i, 0);
end;
end;
ComboHistory.Clear;
if (FHistoryList.Count = 0) or
(THistoryEntry(FHistoryList[0]).Display <> FCurEntry.Display)
then
ComboHistory.Items.Add(FCurEntry.Display);
for i := 0 to FHistoryList.Count - 1 do
ComboHistory.Items.Add(THistoryEntry(FHistoryList[i]).Display);
FIsUpdatingHistory := False;
DisplayCurrent;
end;
procedure TIdeInspectForm.SetSelected(AComp: TComponent);
begin
FSelected := AComp;
FPropertiesGrid.TIObject := FSelected;
btnSubComponent.Enabled := (FSelected <> nil) and (FSelected.ComponentCount > 0);
btnControls.Enabled := (FSelected <> nil) and
(FSelected is TWinControl) and (TWinControl(FSelected).ControlCount > 0);
UpdateTree;
UpdateCurrent;
end;
procedure TIdeInspectForm.UpdateCurrent;
begin
// keep date, if the component gets destroyed
if FCurEntry.Comp <> FSelected then begin
FCurEntry.Comp := FSelected;
FCurEntry.UpdateDisplayName;
if FSelected <> nil then begin
FCurEntry.TheUnitName := GetClassUnitName(FSelected.ClassType);
FCurEntry.FileName := LazarusIDE.FindUnitFile(FCurEntry.TheUnitName, LazarusIDE);
FCurEntry.IdentifierName := FSelected.ClassName;
FCurEntry.Line := -1;
end
else begin
FCurEntry.TheUnitName := '';
FCurEntry.FileName := '';
FCurEntry.IdentifierName := '';
FCurEntry.Line := -1;
end;
UpdateHistory;
end;
end;
procedure TIdeInspectForm.DisplayCurrent;
begin
FIsUpdatingHistory := True;
ComboHistory.Text := FCurEntry.Display;
EditUnit.Text := FCurEntry.TheUnitName;
EditFile.Text := FCurEntry.FileName;
if FCurEntry.Comp<> nil then
Caption := Format(ideinspInspectingNameClass, [FCurEntry.Display])
else
Caption := ideinspIdeInspector;
btnOpenFile.Enabled := EditFile.Text <> '';
FIsUpdatingHistory := False;
btnSaveHist.Enabled := (FCurEntry.Comp <> nil) and (IndexOfCurrent < 0);
end;
constructor TIdeInspectForm.Create(TheOwner: TComponent);
var
i: TShiftStateEnum;
begin
FKeyGrabForm := TIdeInspectKeyGrabForm.Create(Self);
FHistoryList := TList.Create;
FCurEntry := THistoryEntry.Create;
Screen.AddHandlerActiveFormChanged(@DoActiveFormChanged);
Screen.AddHandlerActiveControlChanged(@DoActiveControChanged);
Application.AddOnKeyDownBeforeHandler(@DoKeyDownBefore);
inherited Create(TheOwner);
FPropertiesGrid := TCustomPropertiesGrid.Create(Self);
with FPropertiesGrid do
begin
Name := 'FPropertiesGrid';
Parent := TabControl1;
Align := alClient;
SaveOnChangeTIObject := False;
OnSelectionChange := @DoPropSelChanged;
end;
btnComponent.Caption := ideinspQuickLinks;
btnSubComponent.Caption := ideinspComponentsOwned;
btnControls.Caption := ideinspControlsChildren;
btnRemoveSelected.Hint := ideinspRemoveSelectedItemSFromTree;
FConf := GetIDEConfigStorage(IDE_INSPECT_CONF_FILE, True);
FFollowFrames := FConf.GetValue('IDEInspect/FollowActive/Type', 0) > 0;
if FFollowFrames then
ToolButtonActiveType.Caption := menuFollowFrame.Caption
else
ToolButtonActiveType.Caption := menuFollowForm.Caption;
TabControl1Change(nil);
SetSelected(Application);
FShortCutKey := FConf.GetValue('IDEInspect/KeyShortCut/Key', 0);
FShortCutShift := [];
for i := low(TShiftStateEnum) to high(TShiftStateEnum) do
if FConf.GetValue('IDEInspect/KeyShortCut/' + ShiftStateNames[i], False) then
FShortCutShift := FShortCutShift + [i];
btnKeepTop.Down := FConf.GetValue('IDEInspect/FormPos/KeepTop', False);
ToolButtonFollowActive.Down := FConf.GetValue('IDEInspect/FollowActive/Enabled', False);
end;
destructor TIdeInspectForm.Destroy;
var
i: Integer;
begin
FreeAndNil(fConf);
Application.RemoveOnKeyDownBeforeHandler(@DoKeyDownBefore);
Screen.RemoveHandlerActiveControlChanged(@DoActiveControChanged);
Screen.RemoveHandlerActiveFormChanged(@DoActiveFormChanged);
for i := 0 to FHistoryList.Count - 1 do
THistoryEntry(FHistoryList[i]).Free;
FreeAndNil(FHistoryList);
FreeAndNil(FCurEntry);
FreeAndNil(TreeView1);
FreeAndNil(FKeyGrabForm);
inherited Destroy;
end;
procedure IDEMenuClicked(Sender: TObject);
begin
IdeInspectForm.Show;
end;
procedure Register;
begin
IdeInspectForm := TIdeInspectForm.Create(Application);
RegisterIDEMenuCommand(itmViewIDEInternalsWindows, 'mnuIdeInspector', ideinspInspectIDE, nil,
@IDEMenuClicked);
end;
initialization
OriginalBackTraceStrFunc := BackTraceStrFunc;
end.