home *** CD-ROM | disk | FTP | other *** search
/ PC Expert 29 / Pce29cd.iso / RUNIMAGE / DELPHI40 / DEMOS / EXPERTS / PRJEXPL.PAS < prev    next >
Pascal/Delphi Source File  |  1998-06-16  |  30KB  |  1,029 lines

  1. { Project Explorer
  2.  
  3.   This demo shows how to use many of the new APIs available in the Tools API.
  4.  
  5.   What it demos:
  6.     How to get notified when certain events occur in Delphi.
  7.     Add a menu item to an arbitrary location in the Delphi main menu tree.
  8.     How to obtain and use interfaces to the for the form designer.
  9.     Accessing components on the form and get and set properties.
  10. }
  11.  
  12. unit PrjExpl;
  13.  
  14. interface
  15.  
  16. uses
  17.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  18.   IniFiles, ComCtrls, EditIntf, ExptIntf, ToolIntf, Menus, VirtIntf;
  19.  
  20. type
  21.   TProjectExplorer = class(TForm)
  22.     TreeView1: TTreeView;
  23.     StatusBar1: TStatusBar;
  24.     PopupMenu1: TPopupMenu;
  25.     EditItem: TMenuItem;
  26.     SelectItem: TMenuItem;
  27.     N1: TMenuItem;
  28.     RenameItem: TMenuItem;
  29.     DeleteItem: TMenuItem;
  30.     procedure FormCreate(Sender: TObject);
  31.     procedure FormDestroy(Sender: TObject);
  32.     procedure TreeView1Expanding(Sender: TObject; Node: TTreeNode;
  33.       var AllowExpansion: Boolean);
  34.     procedure TreeView1KeyPress(Sender: TObject; var Key: Char);
  35.     procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
  36.     procedure TreeView1Editing(Sender: TObject; Node: TTreeNode;
  37.       var AllowEdit: Boolean);
  38.     procedure TreeView1Edited(Sender: TObject; Node: TTreeNode;
  39.       var NewText: string);
  40.     procedure EditItemClick(Sender: TObject);
  41.     procedure PopupMenu1Popup(Sender: TObject);
  42.     procedure RenameItemClick(Sender: TObject);
  43.     procedure SelectItemClick(Sender: TObject);
  44.     procedure DeleteItemClick(Sender: TObject);
  45.   private
  46.     procedure SaveWindowState(Desktop: TIniFile);
  47.     procedure LoadWindowState(Desktop: TIniFile);
  48.   public
  49.     { Public declarations }
  50.   end;
  51.  
  52.   TFormBrowserExpert = class;
  53.   TModuleNotifier = class;
  54.  
  55.   TModuleEntry = class
  56.     FileName: string;
  57.     UnitName: string;
  58.     FormName: string;
  59.     ModuleNode: TTreeNode;
  60.     FormNode: TTreeNode;
  61.     ModuleInterface: TIModuleInterface;
  62.     ModuleNotifier: TModuleNotifier;
  63.     FormHandle: Pointer;
  64.     constructor Create(const AFileName, AUnitName, AFormName: string);
  65.     destructor Destroy; override;
  66.   end;
  67.  
  68.   TAddInNotifier = class(TIAddInNotifier)
  69.   private
  70.     FFormBrowser: TFormBrowserExpert;
  71.   public
  72.     constructor Create(AFormBrowser: TFormBrowserExpert);
  73.     procedure FileNotification(NotifyCode: TFileNotification;
  74.       const FileName: string; var Cancel: Boolean); override;
  75.     procedure EventNotification(NotifyCode: TEventNotification;
  76.       var Cancel: Boolean); override;
  77.   end;
  78.  
  79.   TModuleNotifier = class(TIModuleNotifier)
  80.   private
  81.     FFormBrowser: TFormBrowserExpert;
  82.     FModuleEntry: TModuleEntry;
  83.   public
  84.     constructor Create(AFormBrowser: TFormBrowserExpert; ModuleEntry: TModuleEntry);
  85.     destructor Destroy; override;
  86.     procedure Notify(NotifyCode: TNotifyCode); override;
  87.     procedure ComponentRenamed(ComponentHandle: Pointer;
  88.       const OldName, NewName: string); override;
  89.   end;
  90.  
  91.   TProjectNotifier = class(TIModuleNotifier)
  92.   private
  93.     FFormBrowser: TFormBrowserExpert;
  94.   public
  95.     constructor Create(AFormBrowser: TFormBrowserExpert);
  96.     procedure Notify(NotifyCode: TNotifyCode); override;
  97.     procedure ComponentRenamed(ComponentHandle: Pointer;
  98.       const OldName, NewName: string); override;
  99.   end;
  100.  
  101.   TFormBrowserExpert = class(TIExpert)
  102.   private
  103.     ViewProjectExplorerItem: TIMenuItemIntf;
  104.     AddInNotifier: TAddInNotifier;
  105.     ProjectNotifier: TProjectNotifier;
  106.     ProjectModule: TIModuleInterface;
  107.     ModuleList: TStringList;
  108.   public
  109.     constructor Create;
  110.     destructor Destroy; override;
  111.     function EnumProc(const FileName, UnitName, FormName: string): Boolean;
  112.     procedure OpenProject(const FileName: string);
  113.     procedure CloseProject;
  114.     procedure AddedToProject(const FileName: string);
  115.     procedure RemovedFromProject(const FileName: string);
  116.     procedure LoadDesktop(const FileName: string);
  117.     procedure SaveDesktop(const FileName: string);
  118.     procedure ViewProjectExplorerClick(Sender: TIMenuItemIntf);
  119.     function GetName: string; override;
  120.     function GetStyle: TExpertStyle; override;
  121.     function GetIDString: string; override;
  122.     function GetAuthor: string; override;
  123.     function GetComment: string; override;
  124.     function GetPage: string; override;
  125.     function GetGlyph: HICON; override;
  126.     function GetState: TExpertState; override;
  127.     function GetMenuText: string; override;
  128.     procedure Execute; override;
  129.   end;
  130.  
  131. var
  132.   ProjectExplorer: TProjectExplorer = nil;
  133.   FormBrowserExpert: TFormBrowserExpert = nil;
  134.  
  135. function InitExpert(ToolServices: TIToolServices; RegisterProc: TExpertRegisterProc;
  136.   var Terminate: TExpertTerminateProc): Boolean; stdcall;
  137.  
  138. implementation
  139.  
  140. {$R *.DFM}
  141. {$I PRJEXPL.INC}
  142.  
  143. function GetComponentName(Component: TIComponentInterface): string;
  144. begin
  145.   Result := '';
  146.   Component.GetPropValueByName('Name', Result);  
  147. end;
  148.  
  149. procedure SetComponentName(Component: TIComponentInterface; const Value: string);
  150. begin
  151.   Component.SetPropByName('Name', Value);
  152. end;
  153.  
  154. procedure CreateForm(InstanceClass: TComponentClass; var Reference);
  155. begin
  156.   if TComponent(Reference) = nil then
  157.   begin
  158.     TComponent(Reference) := TComponent(InstanceClass.NewInstance);
  159.     try
  160.       TComponent(Reference).Create(Application);
  161.     except
  162.       TComponent(Reference) := nil;
  163.       TComponent(Reference).Free;
  164.       raise
  165.     end;
  166.   end;
  167. end;
  168.  
  169. { TModuleEntry }
  170.  
  171. constructor TModuleEntry.Create(const AFileName, AUnitName, AFormName: string);
  172. begin
  173.   FileName := AFileName;
  174.   UnitName := AUnitName;
  175.   FormName := AFormName;
  176. end;
  177.  
  178. destructor TModuleEntry.Destroy;
  179. begin
  180.   ModuleNotifier.Free;
  181.   ModuleInterface.Free;
  182.   inherited Destroy;
  183. end;
  184.  
  185. { TAddInNotifier }
  186.  
  187. constructor TAddInNotifier.Create(AFormBrowser: TFormBrowserExpert);
  188. begin
  189.   inherited Create;
  190.   FFormBrowser := AFormBrowser;
  191. end;
  192.  
  193. procedure TAddInNotifier.FileNotification(NotifyCode: TFileNotification;
  194.   const FileName: string; var Cancel: Boolean);
  195. begin
  196.   if ProjectExplorer <> nil then
  197.     if NotifyCode = fnProjectOpened then
  198.       FFormBrowser.OpenProject(FileName)
  199.     else if NotifyCode = fnAddedToProject then
  200.       FFormBrowser.AddedToProject(FileName)
  201.     else if NotifyCode = fnRemovedFromProject then
  202.       FFormBrowser.RemovedFromProject(FileName);  
  203.   if NotifyCode = fnProjectDesktopLoad then
  204.     FFormBrowser.LoadDesktop(FileName)
  205.   else if NotifyCode = fnProjectDesktopSave then
  206.     FFormBrowser.SaveDesktop(FileName);
  207. end;
  208.  
  209. procedure TAddInNotifier.EventNotification(NotifyCode: TEventNotification;
  210.   var Cancel: Boolean);
  211. begin
  212. end;
  213.  
  214. function FindNode(TreeView: TCustomTreeView; Node: TTreeNode;
  215.   ComponentHandle: Pointer): TTreeNode;
  216.  
  217.   function SearchNodes(Node: TTreeNode): TTreeNode;
  218.   var
  219.     ChildNode: TTreeNode;
  220.   begin
  221.     Result := nil;
  222.     if Node.Data = ComponentHandle then
  223.       Result := Node
  224.     else
  225.     begin
  226.       ChildNode := Node.GetFirstChild;
  227.       while ChildNode <> nil do
  228.       begin
  229.         Result := SearchNodes(ChildNode);
  230.         if Result <> nil then
  231.           Break
  232.         else ChildNode := Node.GetNextChild(ChildNode);
  233.       end;
  234.     end;
  235.   end;
  236.  
  237. begin
  238.   if Node = nil then Node := TTreeView(TreeView).Items.GetFirstNode;
  239.   Result := SearchNodes(Node);
  240. end;
  241.  
  242. { TModuleNotifier }
  243.  
  244. constructor TModuleNotifier.Create(AFormBrowser: TFormBrowserExpert; ModuleEntry: TModuleEntry);
  245. begin
  246.   inherited Create;
  247.   FFormBrowser := AFormBrowser;
  248.   FModuleEntry := ModuleEntry;
  249.   FModuleEntry.ModuleInterface.AddNotifier(Self);
  250. end;
  251.  
  252. destructor TModuleNotifier.Destroy;
  253. begin
  254.   with FModuleEntry do
  255.   begin
  256.     ModuleInterface.RemoveNotifier(Self);
  257.     ModuleNotifier := nil;
  258.     ModuleInterface := nil;
  259.     FormHandle := nil;
  260.   end;
  261.   inherited Destroy;
  262. end;
  263.  
  264. procedure TModuleNotifier.Notify(NotifyCode: TNotifyCode);
  265. begin
  266.   if NotifyCode = ncModuleDeleted then
  267.   begin
  268.     with FModuleEntry do
  269.       if FormNode <> nil then
  270.       begin
  271.         FormNode.DeleteChildren;
  272.         FormNode.HasChildren := True;
  273.       end;
  274.     Free;
  275.   end;
  276. end;
  277.  
  278. procedure TModuleNotifier.ComponentRenamed(ComponentHandle: Pointer;
  279.   const OldName, NewName: string);
  280. var
  281.   Component, ParentComponent: TIComponentInterface;
  282.   Node, ParentNode: TTreeNode;
  283. begin
  284.   try
  285.     with FModuleEntry do
  286.       if ComponentHandle = FormHandle then
  287.         Node := FormNode
  288.       else Node := FindNode(FormNode.TreeView, FormNode, ComponentHandle);
  289.     if (Node <> nil) and (NewName <> '') then
  290.       Node.Text := NewName
  291.     else if (Node <> nil) and (NewName = '') then
  292.       Node.Free
  293.     else if (Node = nil) and (NewName <> '') then
  294.       with FModuleEntry.ModuleInterface.GetFormInterface do
  295.       try
  296.         Component := GetComponentFromHandle(ComponentHandle);
  297.         if Component <> nil then
  298.           try
  299.             ParentNode := FModuleEntry.FormNode;
  300.             if Component.IsTControl then
  301.             begin
  302.               ParentComponent := GetCreateParent;
  303.               try
  304.                 if ParentComponent.GetComponentHandle <> FModuleEntry.FormHandle then
  305.                   ParentNode := FindNode(FModuleEntry.FormNode.TreeView,
  306.                     FModuleEntry.FormNode, ParentComponent.GetComponentHandle);
  307.               finally
  308.                 ParentComponent.Free;
  309.               end;
  310.             end;
  311.             if ParentNode <> nil then
  312.               ParentNode.Owner.AddChildObject(ParentNode, NewName,
  313.                 ComponentHandle).MakeVisible;
  314.           finally
  315.             Component.Free;
  316.           end;
  317.       finally
  318.         Free;
  319.       end;
  320.   except
  321.   end;
  322. end;
  323.  
  324. { TProjectNotifier }
  325.  
  326. constructor TProjectNotifier.Create(AFormBrowser: TFormBrowserExpert);
  327. begin
  328.   inherited Create;
  329.   FFormBrowser := AFormBrowser;
  330. end;
  331.  
  332. procedure TProjectNotifier.Notify(NotifyCode: TNotifyCode);
  333. begin
  334.   if NotifyCode = ncModuleDeleted then
  335.   begin
  336.     if ProjectExplorer <> nil then ProjectExplorer.Hide;
  337.     FFormBrowser.CloseProject;
  338.   end;
  339. end;
  340.  
  341. procedure TProjectNotifier.ComponentRenamed(ComponentHandle: Pointer;
  342.   const OldName, NewName: string);
  343. begin
  344. //  Nothing to do here but needs to be overridden anyway
  345. end;
  346.  
  347. { TFormBrowserExpert }
  348.  
  349. constructor TFormBrowserExpert.Create;
  350. var
  351.   MainMenu: TIMainMenuIntf;
  352.   ProjManMenu: TIMenuItemIntf;
  353.   ViewMenu: TIMenuItemIntf;
  354.   MenuItems: TIMenuItemIntf;
  355. begin
  356.   inherited Create;
  357.   ModuleList := TStringList.Create;
  358.   MainMenu := ToolServices.GetMainMenu;
  359.   if MainMenu <> nil then
  360.   try
  361.     MenuItems := MainMenu.GetMenuItems;
  362.     if MenuItems <> nil then
  363.     try
  364.       ProjManMenu := MainMenu.FindMenuItem('ViewPrjMgrItem');
  365.       if ProjManMenu <> nil then
  366.       try
  367.         ViewMenu := ProjManMenu.GetParent;
  368.         if ViewMenu <> nil then
  369.         try
  370.           ViewProjectExplorerItem := ViewMenu.InsertItem(ProjManMenu.GetIndex + 1,
  371.             sMenuItemCaption, 'ViewProjectExplorerItem', '', 0, 0, 0,
  372.             [mfVisible, mfEnabled], ViewProjectExplorerClick);
  373.         finally
  374.           ViewMenu.Free;
  375.         end;
  376.       finally
  377.         ProjManMenu.Free;
  378.       end;
  379.     finally
  380.       MenuItems.Free;
  381.     end;
  382.   finally
  383.     MainMenu.Free;
  384.   end;
  385.   AddInNotifier := TAddInNotifier.Create(Self);
  386.   ToolServices.AddNotifier(AddInNotifier);
  387. end;
  388.  
  389. destructor TFormBrowserExpert.Destroy;
  390. begin
  391.   ToolServices.RemoveNotifier(AddInNotifier);
  392.   CloseProject;
  393.   ViewProjectExplorerItem.Free;
  394.   AddInNotifier.Free;
  395.   ModuleList.Free;
  396.   inherited Destroy;
  397. end;
  398.  
  399. function TFormBrowserExpert.EnumProc(const FileName, UnitName,
  400.   FormName: string): Boolean;
  401. begin
  402.   ModuleList.AddObject(UnitName,
  403.     TModuleEntry.Create(FileName, UnitName, FormName));
  404.   Result := True;
  405. end;
  406.  
  407. function ProjEnumProc(Param: Pointer; const FileName, UnitName,
  408.   FormName: string): Boolean; stdcall;
  409. begin
  410.   try
  411.     Result := TFormBrowserExpert(Param).EnumProc(FileName, UnitName, FormName);
  412.   except
  413.     Result := False;
  414.   end;
  415. end;
  416.  
  417. procedure TFormBrowserExpert.OpenProject(const FileName: string);
  418. var
  419.   I: Integer;
  420.   Node: TTreeNode;
  421. begin
  422.   CloseProject;
  423.   ToolServices.EnumProjectUnits(ProjEnumProc, Self);
  424.   ProjectModule := ToolServices.GetModuleInterface(FileName);
  425.   if ProjectModule <> nil then
  426.   begin
  427.     ProjectNotifier := TProjectNotifier.Create(Self);
  428.     ProjectModule.AddNotifier(ProjectNotifier);
  429.     if (ProjectExplorer <> nil) and (ModuleList.Count > 0) then
  430.       with ProjectExplorer, ToolServices do
  431.       begin
  432.         with TModuleEntry(ModuleList.Objects[0]) do
  433.         begin
  434.           Node := TreeView1.Items.Add(nil, UnitName);
  435.           ModuleNode := Node;
  436.         end;
  437.         for I := 1 to ModuleList.Count - 1 do
  438.           with TModuleEntry(ModuleList.Objects[I]) do
  439.             if UnitName <> '' then
  440.             begin
  441.               ModuleNode := TreeView1.Items.AddChildObject(Node, UnitName,
  442.                 ModuleList.Objects[I]);
  443.               if FormName <> '' then
  444.               begin
  445.                 FormNode := TreeView1.Items.AddChildObject(ModuleNode, FormName,
  446.                   ModuleList.Objects[I]);
  447.                 FormNode.HasChildren := True;
  448.               end;
  449.             end;
  450.         Node.Expanded := True;
  451.       end;
  452.   end;
  453. end;
  454.  
  455. procedure TFormBrowserExpert.CloseProject;
  456. var
  457.   I: Integer;
  458. begin
  459.   if ProjectModule <> nil then
  460.   begin
  461.     if ProjectExplorer <> nil then
  462.       ProjectExplorer.TreeView1.Items.Clear;
  463.     for I := 0 to ModuleList.Count - 1 do
  464.       TModuleEntry(ModuleList.Objects[I]).Free;
  465.     ModuleList.Clear;
  466.     ProjectModule.RemoveNotifier(ProjectNotifier);
  467.     ProjectNotifier.Free;
  468.     ProjectModule.Free;
  469.     ProjectNotifier := nil;
  470.     ProjectModule := nil;
  471.   end;
  472. end;
  473.  
  474. function FindNewProjectItem(Param: Pointer; const ModFileName, ModUnitName,
  475.   ModFormName: string): Boolean; stdcall;
  476. begin
  477.   try
  478.     with TModuleEntry(Param) do
  479.       if AnsiCompareText(FileName, ModFileName) = 0 then
  480.       begin
  481.         Result := False;
  482.         UnitName := ModUnitName;
  483.         FormName := ModFormName;
  484.       end else Result := True;
  485.   except
  486.     Result := False;
  487.   end;
  488. end;
  489.  
  490. procedure TFormBrowserExpert.AddedToProject(const FileName: string);
  491. var
  492.   NewModuleEntry: TModuleEntry;
  493. begin
  494.   if ModuleList.Count > 0 then
  495.   begin
  496.     NewModuleEntry := TModuleEntry.Create(FileName, '', '');
  497.     ToolServices.EnumProjectUnits(FindNewProjectItem, NewModuleEntry);
  498.     ModuleList.AddObject(FileName, NewModuleEntry);
  499.     if ProjectExplorer <> nil then
  500.       with ProjectExplorer, NewModuleEntry do
  501.       begin
  502.         ModuleNode :=
  503.           TreeView1.Items.AddChildObject(TModuleEntry(ModuleList.Objects[0]).ModuleNode,
  504.           NewModuleEntry.UnitName, NewModuleEntry);
  505.         if FormName <> '' then
  506.         begin
  507.           FormNode := TreeView1.Items.AddChildObject(NewModuleEntry.ModuleNode,
  508.             FormName, NewModuleEntry);
  509.           FormNode.HasChildren := True;
  510.         end;
  511.       end;
  512.   end;
  513. end;
  514.  
  515. procedure TFormBrowserExpert.RemovedFromProject(const FileName: string);
  516. var
  517.   I: Integer;
  518.   ModuleEntry: TModuleEntry;
  519. begin
  520.   for I := 0 to ModuleList.Count - 1 do
  521.   begin
  522.     ModuleEntry := TModuleEntry(ModuleList.Objects[I]);
  523.     if AnsiCompareText(ModuleEntry.FileName, FileName) = 0 then
  524.     begin
  525.       ModuleList.Delete(I);
  526.       ModuleEntry.ModuleNode.Free;
  527.       ModuleEntry.Free;
  528.       Break;
  529.     end;
  530.   end;
  531. end;
  532.  
  533. const
  534.   isProjectFormViewer = 'ProjectExplorer';
  535.  
  536.   ivCreate = 'Create';
  537.   ivVisible = 'Visible';
  538.   ivState = 'State';
  539.   ivTop = 'Top';
  540.   ivLeft = 'Left';
  541.   ivWidth = 'Width';
  542.   ivHeight = 'Height';
  543.   ivMaxLeft = 'MaxLeft';
  544.   ivMaxTop = 'MaxTop';
  545.   ivMaxWidth = 'MaxWidth';
  546.   ivMaxHeight = 'MaxHeight';
  547.  
  548. procedure TFormBrowserExpert.LoadDesktop(const FileName: string);
  549. var
  550.   Desktop: TIniFile;
  551. begin
  552.   Desktop := TIniFile.Create(FileName);
  553.   try
  554.     if DeskTop.ReadBool(isProjectFormViewer, ivCreate, False) then
  555.     begin
  556.       CreateForm(TProjectExplorer, ProjectExplorer);
  557.       ProjectExplorer.LoadWindowState(Desktop);
  558.     end else if ProjectExplorer <> nil then ProjectExplorer.Hide;
  559.   finally
  560.     Desktop.Free;
  561.   end;
  562. end;
  563.  
  564. procedure TFormBrowserExpert.SaveDesktop(const FileName: string);
  565. var
  566.   Desktop: TIniFile;
  567. begin
  568.   Desktop := TIniFile.Create(FileName);
  569.   try
  570.     if ProjectExplorer <> nil then ProjectExplorer.SaveWindowState(Desktop);
  571.   finally
  572.     Desktop.Free;
  573.   end;
  574. end;
  575.  
  576. procedure TFormBrowserExpert.ViewProjectExplorerClick(Sender: TIMenuItemIntf);
  577. begin
  578.   CreateForm(TProjectExplorer, ProjectExplorer);
  579.   ProjectExplorer.Show;
  580. end;
  581.  
  582. function TFormBrowserExpert.GetName: string;
  583. begin
  584.   Result := sExpertName;
  585. end;
  586.  
  587. function TFormBrowserExpert.GetStyle: TExpertStyle;
  588. begin
  589.   Result := esAddIn;
  590. end;
  591.  
  592. function TFormBrowserExpert.GetIDString: string;
  593. begin
  594.   Result := 'Borland.ProjectExplorer';
  595. end;
  596.  
  597. function TFormBrowserExpert.GetAuthor: string;
  598. begin
  599. end;
  600.  
  601. function TFormBrowserExpert.GetComment: string;
  602. begin
  603. end;
  604.  
  605. function TFormBrowserExpert.GetPage: string;
  606. begin
  607. end;
  608.  
  609. function TFormBrowserExpert.GetGlyph: HICON;
  610. begin
  611.   Result := 0;
  612. end;
  613.  
  614. function TFormBrowserExpert.GetState: TExpertState;
  615. begin
  616.   Result := [];
  617. end;
  618.  
  619. function TFormBrowserExpert.GetMenuText: string;
  620. begin
  621. end;
  622.  
  623. procedure TFormBrowserExpert.Execute;
  624. begin
  625. end;
  626.  
  627. { TProjectExplorer }
  628.  
  629. procedure TProjectExplorer.FormCreate(Sender: TObject);
  630. var
  631.   ProjectName: string;
  632. begin
  633.   ProjectName := ToolServices.GetProjectName;
  634.   if ProjectName <> '' then
  635.     FormBrowserExpert.OpenProject(ProjectName);
  636. end;
  637.  
  638. procedure TProjectExplorer.FormDestroy(Sender: TObject);
  639. begin
  640.   ProjectExplorer := nil;
  641. end;
  642.  
  643. function OpenModule(ModuleEntry: TModuleEntry; Ask: Boolean): Boolean;
  644. begin
  645.   with ModuleEntry do
  646.   begin
  647.     Result := False;
  648.     if ModuleInterface = nil then
  649.     begin
  650.       if not ToolServices.IsFileOpen(FileName) then
  651.         if not Ask or (MessageDlg(Format(sFileNotLoaded, [FileName]),
  652.           mtConfirmation, [mbYes, mbNo], 0) = mrYes) then
  653.         begin
  654.           if not ToolServices.OpenFile(FileName) then Exit;
  655.         end else Exit;
  656.       ModuleInterface := ToolServices.GetModuleInterface(FileName);
  657.       ModuleNotifier := TModuleNotifier.Create(FormBrowserExpert, ModuleEntry);
  658.       Result := True;
  659.     end else Result := True;
  660.   end;
  661. end;
  662.  
  663. procedure AddChildControl(Node: TTreeNode; IsRoot: Boolean; Component: TIComponentInterface); forward;
  664.  
  665. function GetChildProc(Param: Pointer; Component: TIComponentInterface): Boolean; stdcall;
  666. begin
  667.   try
  668.     try
  669.       AddChildControl(TTreeNode(Param), False, Component);
  670.     finally
  671.       Component.Free; // Release the component interface.
  672.     end;    
  673.     Result := True;
  674.   except
  675.     Result := False;
  676.   end;
  677. end;
  678.  
  679. procedure AddChildControl(Node: TTreeNode; IsRoot: Boolean; Component: TIComponentInterface);
  680. var
  681.   ChildNode: TTreeNode;
  682. begin
  683.   if IsRoot then
  684.     ChildNode := Node
  685.   else ChildNode := ProjectExplorer.TreeView1.Items.AddChildObject(Node,
  686.     GetComponentName(Component), Component.GetComponentHandle);
  687.   Component.GetChildren(ChildNode, GetChildProc);
  688. end;
  689.  
  690. procedure TProjectExplorer.TreeView1Expanding(Sender: TObject;
  691.   Node: TTreeNode; var AllowExpansion: Boolean);
  692. var
  693.   ModuleEntry: TModuleEntry;
  694.   Component: TIComponentInterface;
  695. begin
  696.   if Node.Level = 2 then
  697.   begin
  698.     ModuleEntry := TModuleEntry(Node.Data);
  699.     with ModuleEntry do
  700.     begin
  701.       if ModuleInterface = nil then
  702.         if OpenModule(ModuleEntry, True) then
  703.         begin
  704.           TreeView1.Items.BeginUpdate;
  705.           try
  706.             with ModuleInterface.GetFormInterface do
  707.             try
  708.               Component := GetFormComponent;
  709.               try
  710.                 FormHandle := Component.GetComponentHandle;
  711.                 AddChildControl(Node, True, Component);
  712.               finally
  713.                 Component.Free;
  714.               end;
  715.             finally
  716.               Free;
  717.             end;
  718.           finally
  719.             TreeView1.Items.EndUpdate;
  720.           end;
  721.           if Node.GetFirstChild = nil then
  722.             Node.HasChildren := False;
  723.         end;
  724.     end;
  725.   end;
  726. end;
  727.  
  728. procedure TProjectExplorer.TreeView1KeyPress(Sender: TObject; var Key: Char);
  729. begin
  730.   with TreeView1 do
  731.     if not IsEditing and (Selected <> nil) and (Selected.Level < 3) and
  732.       (Key = '*') then Key := #0;
  733. end;
  734.  
  735. function GetModuleEntry(Node: TTreeNode): TModuleEntry;
  736. begin
  737.   while Node.Level > 2 do
  738.     Node := Node.Parent;
  739.   Result := TModuleEntry(Node.Data);
  740. end;
  741.  
  742. function GetNodeComponent(Node: TTreeNode): TIComponentInterface;
  743. var
  744.   ModuleEntry: TModuleEntry;
  745.   FormInterface: TIFormInterface;
  746.   Handle: Pointer;
  747. begin
  748.   Result := nil;
  749.   if (Node <> nil) and (Node.Level >= 2) then
  750.   begin
  751.     ModuleEntry := GetModuleEntry(Node);
  752.     if ModuleEntry.ModuleInterface <> nil then
  753.     begin
  754.       FormInterface := ModuleEntry.ModuleInterface.GetFormInterface;
  755.       try
  756.         if Node.Level = 2 then
  757.           Handle := ModuleEntry.FormHandle
  758.         else Handle := Node.Data;
  759.         Result := FormInterface.GetComponentFromHandle(Handle);
  760.       finally
  761.         FormInterface.Free;
  762.       end;
  763.     end;
  764.   end;
  765. end;
  766.  
  767. procedure TProjectExplorer.TreeView1Change(Sender: TObject; Node: TTreeNode);
  768. var
  769.   ModuleEntry: TModuleEntry;
  770.   Component: TIComponentInterface;
  771. begin
  772.   if Node = nil then Exit;
  773.   if Node.Level > 2 then
  774.   begin
  775.     Component := GetNodeComponent(Node);
  776.     if Component <> nil then
  777.     try
  778.       StatusBar1.SimpleText := Component.GetComponentType;
  779.     finally
  780.       Component.Free;
  781.     end else StatusBar1.SimpleText := '';
  782.   end else if (Node.Level = 1) or (Node.Level = 2) then
  783.   begin
  784.     ModuleEntry := TModuleEntry(Node.Data);
  785.     if Node.Level = 1 then
  786.       StatusBar1.SimpleText := ModuleEntry.FileName
  787.     else StatusBar1.SimpleText := ChangeFileExt(ModuleEntry.FileName, '.dfm');
  788.   end else if Node.Level = 0 then
  789.     if FormBrowserExpert.ProjectModule <> nil then
  790.       with FormBrowserExpert.ProjectModule.GetEditorInterface do
  791.       try
  792.         StatusBar1.SimpleText := FileName;
  793.       finally
  794.         Free;
  795.       end;
  796. end;
  797.  
  798. procedure TProjectExplorer.TreeView1Editing(Sender: TObject; Node: TTreeNode;
  799.   var AllowEdit: Boolean);
  800. var
  801.   Component: TIComponentInterface;
  802. begin
  803.   if Node <> nil then
  804.   begin
  805.     Component := GetNodeComponent(Node);
  806.     try
  807.       if (Node.Level < 2) or (Component = nil) then
  808.         AllowEdit := False;
  809.     finally
  810.       Component.Free;
  811.     end;
  812.   end;        
  813. end;
  814.  
  815. procedure TProjectExplorer.TreeView1Edited(Sender: TObject; Node: TTreeNode;
  816.   var Newtext: string);
  817. var
  818.   Component: TIComponentInterface;
  819. begin
  820.   if Node.Level >= 2 then
  821.   begin
  822.     Component := GetNodeComponent(Node);
  823.     try
  824.       SetComponentName(Component, NewText);
  825.     finally
  826.       Component.Free;
  827.     end;
  828.     NewText := Node.Text;
  829.   end;
  830. end;
  831.  
  832. procedure TProjectExplorer.PopupMenu1Popup(Sender: TObject);
  833. var
  834.   Node: TTreeNode;
  835.   NodeComponent: TIComponentInterface;
  836. begin
  837.   Node := TreeView1.Selected;
  838.   EditItem.Enabled := Node <> nil;
  839.   NodeComponent := GetNodeComponent(Node);
  840.   try
  841.     SelectItem.Enabled := (Node <> nil) and (Node.Level > 1) and
  842.       (NodeComponent <> nil);
  843.     RenameItem.Enabled := (Node <> nil) and (Node.Level > 1) and
  844.       (NodeComponent <> nil);
  845.     DeleteItem.Enabled := (Node <> nil) and (Node.Level > 2) and
  846.       (NodeComponent <> nil);
  847.   finally
  848.     NodeComponent.Free;
  849.   end;
  850. end;
  851.  
  852. procedure TProjectExplorer.EditItemClick(Sender: TObject);
  853. var
  854.   Node: TTreeNode;
  855.   ModuleEntry: TModuleEntry;
  856.   Component: TIComponentInterface;
  857. begin
  858.   Node := TreeView1.Selected;
  859.   if Node <> nil then
  860.     if Node.Level >= 2 then
  861.     begin
  862.       ModuleEntry := GetModuleEntry(Node);
  863.       Component := GetNodeComponent(Node);
  864.       try
  865.         if (Node.Level = 2) and (Component = nil) then
  866.         begin
  867.           if OpenModule(ModuleEntry, False) then
  868.             ModuleEntry.ModuleInterface.ShowForm;
  869.         end else if Component <> nil then
  870.         begin
  871.           Component.Select;
  872.           Component.Focus;
  873.         end;
  874.       finally
  875.         Component.Free;
  876.       end;
  877.     end else if Node.Level = 1 then
  878.     begin
  879.       ModuleEntry := TModuleEntry(Node.Data);
  880.       if OpenModule(ModuleEntry, False) then
  881.         ModuleEntry.ModuleInterface.ShowSource;
  882.     end else if Node.Level = 0 then
  883.       if FormBrowserExpert.ProjectModule <> nil then
  884.         FormBrowserExpert.ProjectModule.ShowSource;
  885. end;
  886.  
  887. procedure TProjectExplorer.SelectItemClick(Sender: TObject);
  888. var
  889.   Node: TTreeNode;
  890.   Component: TIComponentInterface;
  891. begin
  892.   Node := TreeView1.Selected;
  893.   if Node <> nil then
  894.     if Node.Level >= 2 then
  895.     begin
  896.       Component := GetNodeComponent(Node);
  897.       try
  898.         Component.Select;
  899.       finally
  900.         Component.Free;
  901.       end;
  902.     end;
  903. end;
  904.  
  905. procedure TProjectExplorer.RenameItemClick(Sender: TObject);
  906. var
  907.   Node: TTreeNode;
  908. begin
  909.   Node := TreeView1.Selected;
  910.   if Node <> nil then Node.EditText;
  911. end;
  912.  
  913. procedure TProjectExplorer.DeleteItemClick(Sender: TObject);
  914. var
  915.   Node: TTreeNode;
  916.   Component: TIComponentInterface;
  917. begin
  918.   Node := TreeView1.Selected;
  919.   if Node <> nil then
  920.     if Node.Level > 2 then
  921.     begin
  922.       Component := GetNodeComponent(Node);
  923.       try
  924.         Component.Delete;
  925.       finally
  926.         Component.Free;
  927.       end;
  928.     end;
  929. end;
  930.  
  931. procedure TProjectExplorer.SaveWindowState(Desktop: TIniFile);
  932. var
  933.   WindowPlacement: TWindowPlacement;
  934. begin
  935.   if Visible then with Desktop do
  936.   begin
  937.     WriteBool(isProjectFormViewer, ivCreate, True);
  938.     WriteBool(isProjectFormViewer, ivVisible, Visible);
  939.     WriteInteger(isProjectFormViewer, ivState, Ord(WindowState));
  940.  
  941.     if WindowState in [wsMinimized, wsMaximized] then  { 3.1 only }
  942.     begin
  943.       WindowPlacement.length := SizeOf(WindowPlacement);
  944.       GetWindowPlacement(Handle, @WindowPlacement);
  945.       with WindowPlacement.rcNormalPosition do
  946.       begin
  947.         WriteInteger(isProjectFormViewer, ivLeft, left);
  948.         WriteInteger(isProjectFormViewer, ivTop, top);
  949.         WriteInteger(isProjectFormViewer, ivWidth, right - left);
  950.         WriteInteger(isProjectFormViewer, ivHeight, bottom - top);
  951.         WriteInteger(isProjectFormViewer, ivMaxLeft, WindowPlacement.ptMaxPosition.x);
  952.         WriteInteger(isProjectFormViewer, ivMaxTop, WindowPlacement.ptMaxPosition.y);
  953.         if WindowState = wsMaximized then
  954.         begin
  955.           WriteInteger(isProjectFormViewer, ivMaxWidth, Width);
  956.           WriteInteger(isProjectFormViewer, ivMaxHeight, Height);
  957.         end;
  958.       end;
  959.     end
  960.     else
  961.     begin
  962.       WriteInteger(isProjectFormViewer, ivLeft, Left);
  963.       WriteInteger(isProjectFormViewer, ivTop, Top);
  964.       WriteInteger(isProjectFormViewer, ivWidth, Width);
  965.       WriteInteger(isProjectFormViewer, ivHeight, Height);
  966.     end;
  967.   end;
  968. end;
  969.  
  970. procedure TProjectExplorer.LoadWindowState(Desktop: TIniFile);
  971. var
  972.   X, Y, W, H: Integer;
  973.   Visible: Boolean;
  974.   WindowState: TWindowState;
  975.   WindowPlacement: TWindowPlacement;
  976. begin
  977.   if Desktop.ReadBool(isProjectFormViewer, ivCreate, False) then with Desktop do
  978.   begin
  979.     Position := poDesigned;
  980.     Visible := ReadBool(isProjectFormViewer, ivVisible, False);
  981.     WindowState := TWindowState(ReadInteger(isProjectFormViewer, ivState, Ord(wsNormal)));
  982.     X := ReadInteger(isProjectFormViewer, ivLeft, Left);
  983.     Y := ReadInteger(isProjectFormViewer, ivTop, Top);
  984.     W := ReadInteger(isProjectFormViewer, ivWidth, Width);
  985.     H := ReadInteger(isProjectFormViewer, ivHeight, Height);
  986.  
  987.     with WindowPlacement do
  988.     begin
  989.       length := SizeOf(WindowPlacement);
  990.       rcNormalPosition.left := X;
  991.       rcNormalPosition.top := Y;
  992.       rcNormalPosition.right := X + W;
  993.       rcNormalPosition.bottom := Y + H;
  994.       ptMaxPosition.x := ReadInteger(isProjectFormViewer, ivMaxLeft, -GetSystemMetrics(SM_CXFRAME));
  995.       ptMaxPosition.y := ReadInteger(isProjectFormViewer, ivMaxTop, -GetSystemMetrics(SM_CYFRAME));
  996.       case WindowState of
  997.         wsMinimized: showCmd := SW_SHOWMINIMIZED;
  998.         wsMaximized: showCmd := SW_SHOWMAXIMIZED;
  999.         wsNormal: showCmd := SW_NORMAL;
  1000.       end;
  1001.       flags := 0;
  1002.     end;
  1003.     SetWindowPlacement(Handle, @WindowPlacement);
  1004.     if WindowState = wsMaximized then
  1005.     begin
  1006.       W := ReadInteger(isProjectFormViewer, ivMaxWidth, Width);
  1007.       H := ReadInteger(isProjectFormViewer, ivMaxHeight, Height);
  1008.       SetBounds(Left, Top, W, H);
  1009.     end;
  1010.     Self.Visible := Visible;
  1011.   end;
  1012. end;
  1013.  
  1014. function InitExpert(ToolServices: TIToolServices; RegisterProc: TExpertRegisterProc;
  1015.   var Terminate: TExpertTerminateProc): Boolean;
  1016. begin
  1017.   Result := True;
  1018.   try
  1019.     ExptIntf.ToolServices := ToolServices;
  1020.     Application.Handle := ToolServices.GetParentHandle;
  1021.     FormBrowserExpert := TFormBrowserExpert.Create;
  1022.     RegisterProc(FormBrowserExpert);
  1023.   except
  1024.     ToolServices.RaiseException(ReleaseException);
  1025.   end;
  1026. end;
  1027.  
  1028. end.
  1029.