TB2DsgnItemEditor.pas 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401
  1. unit TB2DsgnItemEditor;
  2. {
  3. Toolbar2000
  4. Copyright (C) 1998-2005 by Jordan Russell
  5. All rights reserved.
  6. The contents of this file are subject to the "Toolbar2000 License"; you may
  7. not use or distribute this file except in compliance with the
  8. "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in
  9. TB2k-LICENSE.txt or at:
  10. http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt
  11. Alternatively, the contents of this file may be used under the terms of the
  12. GNU General Public License (the "GPL"), in which case the provisions of the
  13. GPL are applicable instead of those in the "Toolbar2000 License". A copy of
  14. the GPL may be found in GPL-LICENSE.txt or at:
  15. http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt
  16. If you wish to allow use of your version of this file only under the terms of
  17. the GPL and not to allow others to use your version of this file under the
  18. "Toolbar2000 License", indicate your decision by deleting the provisions
  19. above and replace them with the notice and other provisions required by the
  20. GPL. If you do not delete the provisions above, a recipient may use your
  21. version of this file under either the "Toolbar2000 License" or the GPL.
  22. $jrsoftware: tb2k/Source/TB2DsgnItemEditor.pas,v 1.55 2005/01/27 06:48:53 jr Exp $
  23. }
  24. interface
  25. {$I TB2Ver.inc}
  26. uses
  27. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  28. StdCtrls, ExtCtrls, Buttons, ComCtrls, ImgList, Menus,
  29. TB2Item, TB2Toolbar, TB2Dock,
  30. {$IFDEF JR_D6}
  31. DesignWindows, DesignEditors, DesignIntf;
  32. {$ELSE}
  33. DsgnIntf, DsgnWnds, LibIntf;
  34. {$ENDIF}
  35. type
  36. TTBItemEditForm = class(TDesignWindow)
  37. TreeView: TTreeView;
  38. ListView: TListView;
  39. Splitter1: TSplitter;
  40. Toolbar: TTBToolbar;
  41. NewSubmenuButton: TTBItem;
  42. NewItemButton: TTBItem;
  43. NewSepButton: TTBItem;
  44. DeleteButton: TTBItem;
  45. TBSeparatorItem1: TTBSeparatorItem;
  46. TBPopupMenu1: TTBPopupMenu;
  47. TBItemContainer1: TTBItemContainer;
  48. ToolbarItems: TTBSubmenuItem;
  49. CopyButton: TTBItem;
  50. CutButton: TTBItem;
  51. PasteButton: TTBItem;
  52. MoreMenu: TTBSubmenuItem;
  53. TBSeparatorItem2: TTBSeparatorItem;
  54. TBSubmenuItem1: TTBSubmenuItem;
  55. TConvertMenu: TTBItem;
  56. TBSeparatorItem3: TTBSeparatorItem;
  57. MoveUpButton: TTBItem;
  58. MoveDownButton: TTBItem;
  59. procedure FormClose(Sender: TObject; var Action: TCloseAction);
  60. procedure TreeViewChange(Sender: TObject; Node: TTreeNode);
  61. procedure NewSubmenuButtonClick(Sender: TObject);
  62. procedure NewItemButtonClick(Sender: TObject);
  63. procedure ListViewChange(Sender: TObject; Item: TListItem;
  64. Change: TItemChange);
  65. procedure DeleteButtonClick(Sender: TObject);
  66. procedure NewSepButtonClick(Sender: TObject);
  67. procedure ListViewDragOver(Sender, Source: TObject; X, Y: Integer;
  68. State: TDragState; var Accept: Boolean);
  69. procedure ListViewDragDrop(Sender, Source: TObject; X, Y: Integer);
  70. procedure TreeViewEnter(Sender: TObject);
  71. procedure TreeViewDragDrop(Sender, Source: TObject; X, Y: Integer);
  72. procedure TreeViewDragOver(Sender, Source: TObject; X, Y: Integer;
  73. State: TDragState; var Accept: Boolean);
  74. procedure CopyButtonClick(Sender: TObject);
  75. procedure ListViewKeyDown(Sender: TObject; var Key: Word;
  76. Shift: TShiftState);
  77. procedure CutButtonClick(Sender: TObject);
  78. procedure PasteButtonClick(Sender: TObject);
  79. procedure FormActivate(Sender: TObject);
  80. procedure ListViewKeyPress(Sender: TObject; var Key: Char);
  81. procedure ListViewDblClick(Sender: TObject);
  82. procedure ListViewEnter(Sender: TObject);
  83. procedure TreeViewKeyDown(Sender: TObject; var Key: Word;
  84. Shift: TShiftState);
  85. procedure TConvertMenuClick(Sender: TObject);
  86. procedure TreeViewKeyPress(Sender: TObject; var Key: Char);
  87. procedure MoveUpButtonClick(Sender: TObject);
  88. procedure MoveDownButtonClick(Sender: TObject);
  89. private
  90. FParentComponent: TComponent;
  91. FRootItem, FSelParentItem: TTBCustomItem;
  92. FNotifyItemList: TList;
  93. FSettingSel, FRebuildingTree, FRebuildingList: Integer;
  94. function AddListViewItem(const Index: Integer;
  95. const Item: TTBCustomItem): TListItem;
  96. procedure Copy;
  97. procedure CreateNewItem(const AClass: TTBCustomItemClass);
  98. procedure Cut;
  99. procedure Delete;
  100. procedure DeleteItem(const Item: TTBCustomItem);
  101. function GetItemTreeCaption(AItem: TTBCustomItem): String;
  102. procedure GetSelItemList(const AList: TList);
  103. procedure ItemNotification(Ancestor: TTBCustomItem; Relayed: Boolean;
  104. Action: TTBItemChangedAction; Index: Integer; Item: TTBCustomItem);
  105. procedure MoreItemClick(Sender: TObject);
  106. procedure MoveItem(CurIndex, NewIndex: Integer);
  107. procedure Paste;
  108. procedure RebuildList;
  109. procedure RebuildTree;
  110. procedure SelectInObjectInspector(AList: TList);
  111. procedure SetSelParentItem(ASelParentItem: TTBCustomItem);
  112. function TreeViewDragHandler(Sender, Source: TObject; X, Y: Integer;
  113. Drop: Boolean): Boolean;
  114. procedure UnregisterAllNotifications;
  115. protected
  116. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  117. function UniqueName(Component: TComponent): String; override;
  118. public
  119. constructor Create(AOwner: TComponent); override;
  120. destructor Destroy; override;
  121. {$IFDEF JR_D6}
  122. function EditAction(Action: TEditAction): Boolean; override;
  123. {$ELSE}
  124. procedure EditAction(Action: TEditAction); override;
  125. {$ENDIF}
  126. function GetEditState: TEditState; override;
  127. end;
  128. TTBItemsEditor = class(TDefaultEditor)
  129. public
  130. procedure Edit; override;
  131. procedure ExecuteVerb(Index: Integer); override;
  132. function GetVerb(Index: Integer): String; override;
  133. function GetVerbCount: Integer; override;
  134. end;
  135. TTBItemsPropertyEditor = class(TStringProperty)
  136. public
  137. procedure Edit; override;
  138. function GetAttributes: TPropertyAttributes; override;
  139. function GetValue: String; override;
  140. end;
  141. procedure TBRegisterItemClass(AClass: TTBCustomItemClass;
  142. const ACaption: String; ResInstance: HINST);
  143. type
  144. TTBDsgnEditorHook = procedure(Sender: TTBItemEditForm) of object;
  145. procedure TBRegisterDsgnEditorHook(Hook: TTBDsgnEditorHook);
  146. procedure TBUnregisterDsgnEditorHook(Hook: TTBDsgnEditorHook);
  147. implementation
  148. {$R *.DFM}
  149. uses
  150. TypInfo, CommCtrl, TB2Version, TB2Common, TB2DsgnConverter;
  151. type
  152. {}TTBCustomItemAccess = class(TTBCustomItem);
  153. {}TControlAccess = class(TControl);
  154. {$IFNDEF JR_D5}
  155. TDesignerSelectionList = TComponentList;
  156. {$ENDIF}
  157. {$IFDEF JR_D6}
  158. TDesignerSelectionList = IDesignerSelections;
  159. {$ENDIF}
  160. PItemClassInfo = ^TItemClassInfo;
  161. TItemClassInfo = record
  162. ItemClass: TTBCustomItemClass;
  163. Caption: String;
  164. ImageIndex: Integer;
  165. end;
  166. var
  167. ItemClasses: TList;
  168. ItemImageList: TImageList;
  169. EditFormHooks: TList;
  170. {$IFNDEF JR_D6}
  171. function CreateSelectionList: TDesignerSelectionList;
  172. begin
  173. Result := TDesignerSelectionList.Create;
  174. end;
  175. {$ENDIF}
  176. procedure FreeItemClasses;
  177. var
  178. I: Integer;
  179. IC: TList;
  180. begin
  181. if ItemClasses = nil then Exit;
  182. IC := ItemClasses;
  183. ItemClasses := nil;
  184. for I := IC.Count-1 downto 0 do
  185. Dispose(PItemClassInfo(IC[I]));
  186. IC.Free;
  187. end;
  188. procedure UnregisterModuleItemClasses(AModule: NativeInt);
  189. var
  190. I: Integer;
  191. Info: PItemClassInfo;
  192. begin
  193. I := 0;
  194. while I < ItemClasses.Count do begin
  195. Info := ItemClasses[I];
  196. if FindClassHInstance(Info.ItemClass) = HINST(AModule) then begin
  197. ItemClasses.Delete(I);
  198. Dispose(Info);
  199. end
  200. else
  201. Inc(I);
  202. end;
  203. { Note: TTBItemEditForm also holds references to item classes, but since
  204. Delphi automatically closes all editor forms before compiling/removing
  205. a package, we don't need to remove them. }
  206. end;
  207. function LoadItemImage(Instance: HINST; const ResName: String): Integer;
  208. var
  209. Bmp: TBitmap;
  210. begin
  211. Bmp := TBitmap.Create;
  212. try
  213. Bmp.Handle := LoadBitmap(Instance, PChar(ResName));
  214. if Bmp.Handle = 0 then
  215. Result := -1
  216. else
  217. Result := ItemImageList.AddMasked(Bmp, Bmp.Canvas.Pixels[0, Bmp.Height-1]);
  218. finally
  219. Bmp.Free;
  220. end;
  221. end;
  222. procedure TBRegisterItemClass(AClass: TTBCustomItemClass;
  223. const ACaption: String; ResInstance: HINST);
  224. var
  225. Info: PItemClassInfo;
  226. I: Integer;
  227. begin
  228. if ItemClasses <> nil then
  229. for I := ItemClasses.Count - 1 downto 0 do
  230. begin
  231. Info := ItemClasses[I];
  232. if Info.ItemClass = AClass then
  233. begin
  234. Dispose(Info);
  235. ItemClasses.Delete(I);
  236. end;
  237. end;
  238. New(Info);
  239. Info.ItemClass := AClass;
  240. Info.Caption := ACaption;
  241. Info.ImageIndex := LoadItemImage(ResInstance, Uppercase(AClass.ClassName));
  242. ItemClasses.Add(Info);
  243. end;
  244. function GetItemClassImage(AClass: TTBCustomItemClass): Integer;
  245. var
  246. I: Integer;
  247. Info: PItemClassInfo;
  248. begin
  249. for I := ItemClasses.Count-1 downto 0 do begin
  250. Info := ItemClasses[I];
  251. if AClass.InheritsFrom(Info.ItemClass) then begin
  252. Result := Info.ImageIndex;
  253. if Result >= 0 then
  254. Exit;
  255. end;
  256. end;
  257. if AClass.InheritsFrom(TTBSubmenuItem) then
  258. Result := 1
  259. else if AClass.InheritsFrom(TTBSeparatorItem) then
  260. Result := 2
  261. else
  262. Result := 0;
  263. end;
  264. procedure ShowEditForm(AParentComponent: TComponent; ARootItem: TTBCustomItem;
  265. const ADesigner: {$IFDEF JR_D6} IDesigner {$ELSE} IFormDesigner {$ENDIF});
  266. var
  267. I: Integer;
  268. Form: TCustomForm;
  269. EditForm: TTBItemEditForm;
  270. begin
  271. if Assigned(ARootItem.LinkSubitems) then begin
  272. case MessageDlg(Format('The LinkSubitems property is set to ''%s''. ' +
  273. 'Would you like to edit that item instead?',
  274. [ARootItem.LinkSubitems.Name]), mtConfirmation, [mbYes, mbNo, mbCancel], 0) of
  275. mrYes: begin
  276. AParentComponent := ARootItem.LinkSubitems;
  277. ARootItem := ARootItem.LinkSubitems;
  278. end;
  279. mrCancel: Exit;
  280. end;
  281. end;
  282. for I := 0 to Screen.FormCount-1 do begin
  283. Form := Screen.Forms[I];
  284. if Form is TTBItemEditForm then
  285. if TTBItemEditForm(Form).FRootItem = ARootItem then begin
  286. Form.Show;
  287. if Form.WindowState = wsMinimized then
  288. Form.WindowState := wsNormal;
  289. Exit;
  290. end;
  291. end;
  292. EditForm := TTBItemEditForm.Create(Application);
  293. try
  294. EditForm.Designer := ADesigner;
  295. EditForm.FParentComponent := AParentComponent;
  296. AParentComponent.FreeNotification(EditForm);
  297. EditForm.FRootItem := ARootItem;
  298. ARootItem.FreeNotification(EditForm);
  299. EditForm.FSelParentItem := ARootItem;
  300. EditForm.Caption := 'Editing ' + AParentComponent.Name;
  301. EditForm.RebuildTree;
  302. EditForm.RebuildList;
  303. {$IFDEF JR_D9}
  304. EditForm.PopupMode := pmExplicit;
  305. {$ENDIF}
  306. EditForm.Show;
  307. except
  308. EditForm.Free;
  309. raise;
  310. end;
  311. end;
  312. function IsSubmenuItem(Item: TTBCustomItem): Boolean;
  313. begin
  314. Result := tbisSubitemsEditable in TTBCustomItemAccess(Item).ItemStyle;
  315. end;
  316. procedure ShowVersion;
  317. const
  318. AboutText =
  319. '%s'#13#10 +
  320. 'Copyright (C) 1998-2005 by Jordan Russell'#13#10 +
  321. 'For conditions of distribution and use, see LICENSE.TXT.'#13#10 +
  322. #13#10 +
  323. 'Visit my web site for the latest versions of Toolbar2000:'#13#10 +
  324. 'http://www.jrsoftware.org/';
  325. begin
  326. MessageDlg(Format(AboutText, [Toolbar2000VersionPropText]), mtInformation,
  327. [mbOK], 0);
  328. end;
  329. { TTBItemEditForm }
  330. constructor TTBItemEditForm.Create(AOwner: TComponent);
  331. var
  332. I: Integer;
  333. Info: PItemClassInfo;
  334. Item: TTBItem;
  335. begin
  336. inherited;
  337. FNotifyItemList := TList.Create;
  338. ToolbarItems.SubMenuImages := ItemImageList;
  339. ListView.SmallImages := ItemImageList;
  340. { Populate the 'More' menu }
  341. for I := 0 to ItemClasses.Count-1 do begin
  342. Info := ItemClasses[I];
  343. Item := TTBItem.Create(Self);
  344. Item.Caption := Info.Caption;
  345. Item.ImageIndex := GetItemClassImage(Info.ItemClass);
  346. Item.Tag := Integer(Info.ItemClass);
  347. Item.OnClick := MoreItemClick;
  348. MoreMenu.Add(Item);
  349. end;
  350. { Run the hooks }
  351. if EditFormHooks <> nil then
  352. for I := 0 to EditFormHooks.Count - 1 do
  353. TTBDsgnEditorHook(EditFormHooks[I]^)(Self);
  354. end;
  355. destructor TTBItemEditForm.Destroy;
  356. begin
  357. inherited;
  358. if Assigned(FNotifyItemList) then begin
  359. UnregisterAllNotifications;
  360. FNotifyItemList.Free;
  361. FNotifyItemList := nil;
  362. end;
  363. end;
  364. procedure TTBItemEditForm.FormClose(Sender: TObject;
  365. var Action: TCloseAction);
  366. begin
  367. Action := caFree;
  368. end;
  369. procedure TTBItemEditForm.FormActivate(Sender: TObject);
  370. begin
  371. SetSelParentItem(FSelParentItem);
  372. end;
  373. procedure TTBItemEditForm.Notification(AComponent: TComponent;
  374. Operation: TOperation);
  375. begin
  376. inherited;
  377. if (Operation = opRemove) and
  378. ((AComponent = FParentComponent) or (AComponent = FRootItem)) then
  379. { Must use Free instead of Close, since Close causes the freeing of the
  380. form to be delayed until the next message. We have to destroy the form
  381. immediately, otherwise Delphi will crash when Compile is clicked on the
  382. TB2k package. }
  383. Free;
  384. {}{temp:}
  385. (*if (Operation = opRemove) and (FNotifyItemList.IndexOf(AComponent) <> -1) then begin
  386. outputdebugstring(pchar('Still in list: ' + AComponent.name));
  387. //beep;
  388. end;*)
  389. end;
  390. function TTBItemEditForm.UniqueName(Component: TComponent): String;
  391. begin
  392. Result := Designer.UniqueName(Component.ClassName);
  393. end;
  394. function TTBItemEditForm.GetEditState: TEditState;
  395. begin
  396. Result := [];
  397. if ActiveControl = ListView then begin
  398. if Assigned(ListView.Selected) then
  399. Result := [esCanDelete, esCanCut, esCanCopy];
  400. if ClipboardComponents then
  401. Include(Result, esCanPaste);
  402. end;
  403. end;
  404. {$IFDEF JR_D6}
  405. function TTBItemEditForm.EditAction(Action: TEditAction): Boolean;
  406. {$ELSE}
  407. procedure TTBItemEditForm.EditAction(Action: TEditAction);
  408. {$ENDIF}
  409. begin
  410. {$IFDEF JR_D6}
  411. Result := True;
  412. {$ENDIF}
  413. case Action of
  414. eaCut: Cut;
  415. eaCopy: Copy;
  416. eaPaste: Paste;
  417. eaDelete: Delete;
  418. {$IFDEF JR_D6}
  419. else
  420. Result := False;
  421. {$ENDIF}
  422. end;
  423. end;
  424. procedure TTBItemEditForm.UnregisterAllNotifications;
  425. var
  426. I: Integer;
  427. begin
  428. for I := FNotifyItemList.Count-1 downto 0 do begin
  429. //outputdebugstring(pchar('Unregall: ' + TTBCustomItem(FNotifyItemList[I]).name));
  430. TTBCustomItem(FNotifyItemList[I]).UnregisterNotification(ItemNotification);
  431. FNotifyItemList.Delete(I);
  432. end;
  433. end;
  434. procedure TTBItemEditForm.ItemNotification(Ancestor: TTBCustomItem;
  435. Relayed: Boolean; Action: TTBItemChangedAction; Index: Integer;
  436. Item: TTBCustomItem);
  437. var
  438. ListItem: TListItem;
  439. TreeNode: TTreeNode;
  440. I: Integer;
  441. C: String;
  442. begin
  443. { Manipulate the list view when items are inserted, deleted, or their Caption
  444. changes }
  445. case Action of
  446. tbicInserted:
  447. begin
  448. if (Ancestor = FSelParentItem) and not Relayed then
  449. AddListViewItem(Index, Item);
  450. if IsSubmenuItem(Item) then
  451. RebuildTree;
  452. end;
  453. tbicDeleting:
  454. if (Ancestor = FSelParentItem) and not Relayed then begin
  455. ListItem := ListView.FindData(0, Item, True, False);
  456. if Assigned(ListItem) then
  457. ListItem.Delete;
  458. end;
  459. tbicInvalidateAndResize:
  460. if (Ancestor = FSelParentItem) and not Relayed then begin
  461. ListItem := ListView.FindData(0, Item, True, False);
  462. if Assigned(ListItem) and (ListItem.Caption <> TTBCustomItem(Item).Caption) then
  463. ListItem.Caption := TTBCustomItem(Item).Caption;
  464. end;
  465. end;
  466. { Update tree view when an item is deleted, or a Caption changes }
  467. if Action = tbicDeleting then begin
  468. I := FNotifyItemList.IndexOf(Item);
  469. if I <> -1 then begin
  470. //outputdebugstring(pchar('Deleting, so unreging: ' + item.name));
  471. TTBCustomItem(Item).UnregisterNotification(ItemNotification);
  472. FNotifyItemList.Delete(I);
  473. end;
  474. end;
  475. if Action in [tbicDeleting, tbicInvalidateAndResize, tbicNameChanged] then begin
  476. TreeNode := TreeView.Items.GetFirstNode;
  477. while Assigned(TreeNode) do begin
  478. if TreeNode.Data = Item then begin
  479. if Action = tbicDeleting then begin
  480. TreeNode.Delete;
  481. if FSelParentItem = Item then
  482. SetSelParentItem(TTBCustomItem(Item).Parent);
  483. end
  484. else begin
  485. { tbicInvalidateAndResize, tbicNameChanged: }
  486. C := GetItemTreeCaption(Item);
  487. if TreeNode.Text <> C then
  488. TreeNode.Text := C;
  489. end;
  490. Break;
  491. end;
  492. TreeNode := TreeNode.GetNext;
  493. end;
  494. end;
  495. end;
  496. function TTBItemEditForm.GetItemTreeCaption(AItem: TTBCustomItem): String;
  497. begin
  498. if AItem <> FRootItem then begin
  499. Result := AItem.Caption;
  500. if Result = '' then
  501. Result := '[' + AItem.Name + ']';
  502. end
  503. else
  504. Result := '(Root)';
  505. end;
  506. procedure TTBItemEditForm.RebuildTree;
  507. procedure Recurse(const AParentItem: TTBCustomItem; const ATreeNode: TTreeNode;
  508. var FoundSelParentItem: TTreeNode);
  509. var
  510. I: Integer;
  511. NewNode: TTreeNode;
  512. ChildItem: TTBCustomItem;
  513. begin
  514. {}AParentItem.FreeNotification(Self);
  515. AParentItem.RegisterNotification(ItemNotification);
  516. FNotifyItemList.Add(AParentItem);
  517. NewNode := TreeView.Items.AddChild(ATreeNode, GetItemTreeCaption(AParentItem));
  518. NewNode.Data := AParentItem;
  519. if AParentItem = FSelParentItem then
  520. FoundSelParentItem := NewNode;
  521. for I := 0 to AParentItem.Count-1 do begin
  522. ChildItem := AParentItem[I];
  523. if IsSubmenuItem(ChildItem) then
  524. Recurse(ChildItem, NewNode, FoundSelParentItem);
  525. end;
  526. end;
  527. var
  528. FoundSelParentItem: TTreeNode;
  529. begin
  530. Inc(FRebuildingTree);
  531. try
  532. TreeView.Items.BeginUpdate;
  533. try
  534. TreeView.Items.Clear;
  535. UnregisterAllNotifications;
  536. FoundSelParentItem := nil;
  537. Recurse(FRootItem, nil, FoundSelParentItem);
  538. if FoundSelParentItem = nil then
  539. SetSelParentItem(FRootItem)
  540. else
  541. TreeView.Selected := FoundSelParentItem;
  542. TreeView.Items[0].Expand(True);
  543. finally
  544. TreeView.Items.EndUpdate;
  545. end;
  546. finally
  547. Dec(FRebuildingTree);
  548. end;
  549. end;
  550. function TTBItemEditForm.AddListViewItem(const Index: Integer;
  551. const Item: TTBCustomItem): TListItem;
  552. begin
  553. Result := ListView.Items.Insert(Index);
  554. Result.Data := Item;
  555. if not(Item is TTBControlItem) then begin
  556. Result.Caption := Item.Caption;
  557. Result.Subitems.Add(Item.ClassName);
  558. Result.ImageIndex := GetItemClassImage(TTBCustomItemClass(Item.ClassType));
  559. end
  560. else begin
  561. Result.Caption := '(Control)';
  562. Result.Subitems.Add(Item.ClassName);
  563. Result.ImageIndex := -1;
  564. end;
  565. end;
  566. procedure TTBItemEditForm.RebuildList;
  567. var
  568. ChildItem: TTBCustomItem;
  569. I: Integer;
  570. begin
  571. Inc(FRebuildingList);
  572. try
  573. ListView.Items.BeginUpdate;
  574. try
  575. ListView.Items.Clear;
  576. if Assigned(FSelParentItem) then begin
  577. for I := 0 to FSelParentItem.Count-1 do begin
  578. ChildItem := FSelParentItem[I];
  579. { Check for csDestroying because deleting an item in the tree view
  580. causes the parent item to be selected, and the parent item won't
  581. get a notification that the item is deleting since notifications
  582. were already sent }
  583. if not(csDestroying in ChildItem.ComponentState) then
  584. AddListViewItem(I, ChildItem);
  585. end;
  586. { Add an empty item to the end }
  587. ListView.Items.Add.ImageIndex := -1;
  588. end;
  589. finally
  590. ListView.Items.EndUpdate;
  591. end;
  592. { Work around a strange TListView bug(?). Without this, the column header
  593. isn't painted properly. }
  594. if HandleAllocated then
  595. SetWindowPos(ListView.Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or
  596. SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER);
  597. finally
  598. Dec(FRebuildingList);
  599. end;
  600. end;
  601. procedure TTBItemEditForm.SelectInObjectInspector(AList: TList);
  602. var
  603. CompList1, CompList2: TDesignerSelectionList;
  604. I: Integer;
  605. C: TComponent;
  606. begin
  607. { Designer.SetSelections will make components appear selected on the form.
  608. It will also select the component in Object Inspector, but only if the
  609. form has the focus. TDesignWindow.SetSelection will select the component
  610. in Object Inspector regardless of whether the form has the focus. }
  611. CompList1 := CreateSelectionList;
  612. CompList2 := CreateSelectionList;
  613. for I := 0 to AList.Count-1 do begin
  614. C := AList[I];
  615. { Must check for csDestroying. If SetSelection is passed a component that's
  616. destroying, Delphi will crash. }
  617. if not(csDestroying in C.ComponentState) then begin
  618. CompList1.Add(C);
  619. CompList2.Add(C);
  620. end;
  621. end;
  622. if CompList1.Count = 0 then begin
  623. {$IFNDEF JR_D6}
  624. CompList1.Free;
  625. CompList2.Free;
  626. {$ENDIF}
  627. end
  628. else begin
  629. Designer.SetSelections(CompList1);
  630. { Note: Never pass an empty list to SetSelection or Delphi will crash }
  631. { History here:
  632. - 1.34: SetSelection call remarked out because it fixed Delphi 6 issue
  633. with random AV's after the editor was closed.
  634. - 1.38: SetSelection call restored because without it, Ctrl+X/C/V didn't
  635. work.
  636. - 1.40: SetSelection call disabled on Delphi 6 only because AV problem
  637. still seems to exist despite another change which I thought fixed it.
  638. On D6 it isn't necessary to call SetSelection for Ctrl+X/C/V to work.
  639. Note: Using "ComponentDesigner.SetSelection(Designer, nil, CompList2);"
  640. instead seems to fix the AV problem, but for consistency with Delphi's
  641. TMainMenu editor (which only selects items when its parent form is
  642. focused), I decided not to call SetSelection at all on D6.
  643. }
  644. {$IFNDEF JR_D6}
  645. SetSelection(CompList2);
  646. {$ENDIF}
  647. end;
  648. end;
  649. procedure TTBItemEditForm.GetSelItemList(const AList: TList);
  650. var
  651. ListItem: TListItem;
  652. begin
  653. ListItem := nil;
  654. while True do begin
  655. ListItem := ListView.GetNextItem(ListItem, sdAll, [isSelected]);
  656. if ListItem = nil then
  657. Break;
  658. if Assigned(ListItem.Data) then
  659. AList.Add(ListItem.Data);
  660. end;
  661. end;
  662. procedure TTBItemEditForm.SetSelParentItem(ASelParentItem: TTBCustomItem);
  663. { - Rebuilds the list view to match a new selection (ASelParentItem) in the
  664. tree view
  665. - Updates toolbar
  666. - Selects selected item(s) into Object Inspector }
  667. var
  668. I: Integer;
  669. TreeNode: TTreeNode;
  670. ItemIsSelected: Boolean;
  671. List: TList;
  672. begin
  673. if FSettingSel > 0 then
  674. Exit;
  675. List := TList.Create;
  676. Inc(FSettingSel);
  677. try
  678. if FSelParentItem <> ASelParentItem then begin
  679. FSelParentItem := ASelParentItem;
  680. NewSubmenuButton.Enabled := Assigned(ASelParentItem);
  681. NewItemButton.Enabled := Assigned(ASelParentItem);
  682. NewSepButton.Enabled := Assigned(ASelParentItem);
  683. for I := 0 to MoreMenu.Count-1 do
  684. MoreMenu[I].Enabled := Assigned(ASelParentItem);
  685. if not Assigned(TreeView.Selected) or (TreeView.Selected.Data <> FSelParentItem) then begin
  686. if FSelParentItem = nil then
  687. TreeView.Selected := nil
  688. else begin
  689. TreeNode := TreeView.Items.GetFirstNode;
  690. while Assigned(TreeNode) do begin
  691. if TreeNode.Data = FSelParentItem then begin
  692. TreeView.Selected := TreeNode;
  693. Break;
  694. end;
  695. TreeNode := TreeNode.GetNext;
  696. end;
  697. end;
  698. end;
  699. RebuildList;
  700. end;
  701. ItemIsSelected := (ActiveControl = ListView) and Assigned(ListView.Selected) and
  702. Assigned(ListView.Selected.Data);
  703. if ItemIsSelected then
  704. GetSelItemList(List);
  705. CutButton.Enabled := ItemIsSelected;
  706. CopyButton.Enabled := ItemIsSelected;
  707. PasteButton.Enabled := (ActiveControl = ListView);
  708. DeleteButton.Enabled := ItemIsSelected or
  709. ((ActiveControl = TreeView) and (FSelParentItem <> FRootItem));
  710. MoveUpButton.Enabled := ItemIsSelected and
  711. (FSelParentItem.IndexOf(List.First) > 0);
  712. MoveDownButton.Enabled := ItemIsSelected and
  713. (FSelParentItem.IndexOf(List.Last) < FSelParentItem.Count-1);
  714. if ActiveControl = ListView then begin
  715. if List.Count = 0 then
  716. { No item was selected, or the blank item was selected.
  717. Select the root item so it looks like no item was selected in
  718. Object Inspector }
  719. List.Add(FRootItem);
  720. end
  721. else if not Assigned(ASelParentItem) or (ASelParentItem = FRootItem) then
  722. List.Add(FParentComponent)
  723. else
  724. List.Add(ASelParentItem);
  725. SelectInObjectInspector(List);
  726. finally
  727. Dec(FSettingSel);
  728. List.Free;
  729. end;
  730. end;
  731. procedure TTBItemEditForm.Cut;
  732. begin
  733. Copy;
  734. Delete;
  735. end;
  736. procedure TTBItemEditForm.Copy;
  737. var
  738. SelList: TList;
  739. CompList: TDesignerSelectionList;
  740. I: Integer;
  741. Item: TTBCustomItem;
  742. begin
  743. if ListView.Selected = nil then Exit;
  744. CompList := nil;
  745. SelList := TList.Create;
  746. try
  747. GetSelItemList(SelList);
  748. CompList := CreateSelectionList;
  749. for I := 0 to SelList.Count-1 do begin
  750. Item := SelList[I];
  751. if Item is TTBControlItem then
  752. raise EInvalidOperation.Create('Cannot cut or copy TTBControlItems');
  753. CompList.Add(Item);
  754. end;
  755. CopyComponents(FParentComponent.Owner, CompList);
  756. finally
  757. {$IFNDEF JR_D6}
  758. CompList.Free;
  759. {$ENDIF}
  760. SelList.Free;
  761. end;
  762. end;
  763. procedure TTBItemEditForm.Paste;
  764. var
  765. CompList: TDesignerSelectionList;
  766. begin
  767. if FSelParentItem = nil then Exit;
  768. CompList := CreateSelectionList;
  769. try
  770. PasteComponents(FParentComponent.Owner, FSelParentItem, CompList);
  771. if CompList.Count <> 0 then
  772. Designer.Modified;
  773. finally
  774. {$IFNDEF JR_D6}
  775. CompList.Free;
  776. {$ENDIF}
  777. end;
  778. end;
  779. procedure TTBItemEditForm.DeleteItem(const Item: TTBCustomItem);
  780. begin
  781. if csAncestor in Item.ComponentState then
  782. raise EInvalidOperation.Create('Items introduced in an ancestor form cannot be deleted');
  783. //Designer.ValidateRename(Item, Item.Name, '');
  784. Item.Free;
  785. Designer.Modified;
  786. end;
  787. procedure TTBItemEditForm.Delete;
  788. var
  789. List: TList;
  790. Item: TTBCustomItem;
  791. ListItem: TListItem;
  792. begin
  793. List := TList.Create;
  794. try
  795. List.Add(FSelParentItem);
  796. SelectInObjectInspector(List);
  797. finally
  798. List.Free;
  799. end;
  800. FSelParentItem.ViewBeginUpdate;
  801. try
  802. while Assigned(ListView.Selected) do begin
  803. Item := ListView.Selected.Data;
  804. if Item = nil then
  805. Break;
  806. DeleteItem(Item);
  807. end;
  808. finally
  809. FSelParentItem.ViewEndUpdate;
  810. end;
  811. { After deleting the items, select the item with the focus }
  812. ListItem := ListView.GetNextItem(nil, sdAll, [isFocused]);
  813. if Assigned(ListItem) then
  814. ListItem.Selected := True;
  815. end;
  816. procedure TTBItemEditForm.MoveItem(CurIndex, NewIndex: Integer);
  817. var
  818. WasFocused: Boolean;
  819. begin
  820. WasFocused := ListView.Items[CurIndex].Focused;
  821. FSelParentItem.Move(CurIndex, NewIndex);
  822. Designer.Modified;
  823. if WasFocused then
  824. ListView.Items[NewIndex].Focused := True;
  825. ListView.Items[NewIndex].Selected := True;
  826. end;
  827. procedure TTBItemEditForm.TreeViewChange(Sender: TObject; Node: TTreeNode);
  828. var
  829. NewSelectedParentItem: TTBCustomItem;
  830. begin
  831. if (FRebuildingTree > 0) or (FSettingSel > 0) then Exit;
  832. if Node = nil then
  833. NewSelectedParentItem := nil
  834. else
  835. NewSelectedParentItem := Node.Data;
  836. SetSelParentItem(NewSelectedParentItem);
  837. end;
  838. procedure TTBItemEditForm.TreeViewEnter(Sender: TObject);
  839. { When the tree view gets the focus, act as if the currently selected item
  840. was clicked. }
  841. begin
  842. ListView.Selected := nil;
  843. SetSelParentItem(FSelParentItem);
  844. end;
  845. procedure TTBItemEditForm.ListViewChange(Sender: TObject; Item: TListItem;
  846. Change: TItemChange);
  847. begin
  848. if (FRebuildingList > 0) or (FSettingSel > 0) or (Change <> ctState) or
  849. (csDestroying in ListView.ComponentState) then
  850. Exit;
  851. SetSelParentItem(FSelParentItem);
  852. end;
  853. procedure TTBItemEditForm.ListViewEnter(Sender: TObject);
  854. begin
  855. { When list view gets the focus, update the toolbar }
  856. SetSelParentItem(FSelParentItem);
  857. end;
  858. procedure TTBItemEditForm.ListViewDblClick(Sender: TObject);
  859. var
  860. SelItem: TTBCustomItem;
  861. PropCount, I: Integer;
  862. Props: PPropList;
  863. PropInfo: PPropInfo;
  864. MethodName: String;
  865. Method: TMethod;
  866. begin
  867. SelItem := nil;
  868. if Assigned(ListView.Selected) then
  869. SelItem := ListView.Selected.Data;
  870. if SelItem = nil then Exit;
  871. if IsSubmenuItem(SelItem) then begin
  872. SetSelParentItem(SelItem);
  873. Exit;
  874. end;
  875. PropCount := GetPropList(SelItem.ClassInfo, [tkMethod], nil);
  876. GetMem(Props, PropCount * SizeOf(PPropInfo));
  877. try
  878. GetPropList(SelItem.ClassInfo, [tkMethod], Props);
  879. for I := PropCount-1 downto 0 do begin
  880. PropInfo := Props[I];
  881. if CompareText({MP}string(PropInfo.Name), 'OnClick') = 0 then begin
  882. Method := GetMethodProp(SelItem, PropInfo);
  883. MethodName := Designer.GetMethodName(Method);
  884. if MethodName = '' then begin
  885. MethodName := SelItem.Name + 'Click';
  886. Method := Designer.CreateMethod(MethodName, GetTypeData(PropInfo.PropType^));
  887. SetMethodProp(SelItem,
  888. {$IFDEF JR_D5} {MP}string(PropInfo.Name) {$ELSE} PropInfo {$ENDIF},
  889. Method);
  890. Designer.Modified;
  891. end;
  892. if Designer.MethodExists(MethodName) then
  893. Designer.ShowMethod(MethodName);
  894. Break;
  895. end;
  896. end;
  897. finally
  898. FreeMem(Props);
  899. end;
  900. end;
  901. procedure TTBItemEditForm.ListViewKeyDown(Sender: TObject; var Key: Word;
  902. Shift: TShiftState);
  903. begin
  904. case Key of
  905. VK_RETURN: begin
  906. Key := 0;
  907. ActivateInspector(#0);
  908. end;
  909. VK_INSERT: begin
  910. Key := 0;
  911. if ssCtrl in Shift then
  912. NewSubmenuButtonClick(Sender)
  913. else
  914. NewItemButtonClick(Sender);
  915. end;
  916. VK_DELETE: begin
  917. Key := 0;
  918. Delete;
  919. end;
  920. end;
  921. end;
  922. procedure TTBItemEditForm.TreeViewKeyDown(Sender: TObject; var Key: Word;
  923. Shift: TShiftState);
  924. begin
  925. case Key of
  926. VK_RETURN: begin
  927. Key := 0;
  928. ActivateInspector(#0);
  929. end;
  930. VK_DELETE: begin
  931. Key := 0;
  932. DeleteButtonClick(Sender);
  933. end;
  934. end;
  935. end;
  936. procedure TTBItemEditForm.TreeViewKeyPress(Sender: TObject; var Key: Char);
  937. begin
  938. if {MP} CharInSet(Key, [#33..#126]) then begin
  939. ActivateInspector(Key);
  940. Key := #0;
  941. end
  942. else if Key = #13 then
  943. Key := #0; { suppress beep }
  944. end;
  945. procedure TTBItemEditForm.ListViewKeyPress(Sender: TObject; var Key: Char);
  946. begin
  947. if Key = '-' then begin
  948. NewSepButtonClick(Sender);
  949. Key := #0;
  950. end
  951. else if {MP} CharInSet(Key, [#33..#126]) then begin
  952. ActivateInspector(Key);
  953. Key := #0;
  954. end;
  955. end;
  956. procedure TTBItemEditForm.ListViewDragOver(Sender, Source: TObject; X,
  957. Y: Integer; State: TDragState; var Accept: Boolean);
  958. { List item dragged over the list view }
  959. var
  960. Item: TListItem;
  961. begin
  962. Accept := False;
  963. if (Sender = ListView) and (Source = ListView) and (ListView.SelCount = 1) then begin
  964. Item := ListView.GetItemAt(X, Y);
  965. if Assigned(Item) and (Item <> ListView.Selected) then
  966. Accept := True;
  967. end;
  968. end;
  969. procedure TTBItemEditForm.ListViewDragDrop(Sender, Source: TObject; X,
  970. Y: Integer);
  971. { List item dropped onto another list item }
  972. var
  973. ListItem: TListItem;
  974. Item: TTBCustomItem;
  975. NewIndex: Integer;
  976. begin
  977. if (Sender = ListView) and (Source = ListView) and (ListView.SelCount = 1) then begin
  978. ListItem := ListView.GetItemAt(X, Y);
  979. if Assigned(ListItem) and (ListItem <> ListView.Selected) and Assigned(FSelParentItem) then begin
  980. NewIndex := FSelParentItem.IndexOf(ListItem.Data);
  981. if NewIndex <> -1 then begin
  982. ListView.Items.BeginUpdate;
  983. { For good performance and to prevent Object Inspector flicker, increment
  984. FSettingSel to prevent calls to SetSelParentItem while moving items }
  985. Inc(FSettingSel);
  986. try
  987. Item := ListView.Selected.Data;
  988. MoveItem(FSelParentItem.IndexOf(Item), NewIndex);
  989. finally
  990. Dec(FSettingSel);
  991. ListView.Items.EndUpdate;
  992. end;
  993. { After decrementing FSettingSel, now call SetSelParentItem, to update
  994. the toolbar buttons }
  995. SetSelParentItem(FSelParentItem);
  996. end;
  997. end;
  998. end;
  999. end;
  1000. function TTBItemEditForm.TreeViewDragHandler(Sender, Source: TObject;
  1001. X, Y: Integer; Drop: Boolean): Boolean;
  1002. var
  1003. Node: TTreeNode;
  1004. ListItem: TListItem;
  1005. Item, NewParentItem: TTBCustomItem;
  1006. ItemList: TList;
  1007. I: Integer;
  1008. NeedRebuildTree: Boolean;
  1009. begin
  1010. Result := False;
  1011. if (Sender = TreeView) and (Source = ListView) then begin
  1012. Node := TreeView.GetNodeAt(X, Y);
  1013. if Assigned(Node) and (Node <> TreeView.Selected) then begin
  1014. NewParentItem := Node.Data;
  1015. ItemList := TList.Create;
  1016. try
  1017. ListItem := nil;
  1018. while True do begin
  1019. ListItem := ListView.GetNextItem(ListItem, sdAll, [isSelected]);
  1020. if ListItem = nil then
  1021. Break;
  1022. Item := ListItem.Data;
  1023. if Assigned(Item) and (Item <> NewParentItem) and
  1024. not Item.ContainsItem(NewParentItem) and
  1025. not(Item is TTBControlItem) then begin
  1026. Result := True;
  1027. ItemList.Add(Item);
  1028. end;
  1029. end;
  1030. if Drop then begin
  1031. NeedRebuildTree := False;
  1032. for I := 0 to ItemList.Count-1 do begin
  1033. Item := ItemList[I];
  1034. Item.Parent.Remove(Item);
  1035. NewParentItem.Add(Item);
  1036. Designer.Modified;
  1037. if IsSubmenuItem(Item) then
  1038. NeedRebuildTree := True;
  1039. end;
  1040. if NeedRebuildTree then
  1041. RebuildTree;
  1042. end;
  1043. finally
  1044. ItemList.Free;
  1045. end;
  1046. end;
  1047. end;
  1048. end;
  1049. procedure TTBItemEditForm.TreeViewDragOver(Sender, Source: TObject; X,
  1050. Y: Integer; State: TDragState; var Accept: Boolean);
  1051. { List item dragged over the tree view }
  1052. begin
  1053. Accept := TreeViewDragHandler(Sender, Source, X, Y, False);
  1054. end;
  1055. procedure TTBItemEditForm.TreeViewDragDrop(Sender, Source: TObject; X,
  1056. Y: Integer);
  1057. { List item dropped onto the tree view }
  1058. begin
  1059. TreeViewDragHandler(Sender, Source, X, Y, True);
  1060. end;
  1061. procedure TTBItemEditForm.CreateNewItem(const AClass: TTBCustomItemClass);
  1062. var
  1063. NewIndex: Integer;
  1064. NewItem: TTBCustomItem;
  1065. ListItem: TListItem;
  1066. begin
  1067. if FSelParentItem = nil then Exit;
  1068. NewIndex := -1;
  1069. if (GetKeyState(VK_SHIFT) >= 0) and Assigned(ListView.Selected) then
  1070. NewIndex := FSelParentItem.IndexOf(ListView.Selected.Data);
  1071. if NewIndex = -1 then
  1072. NewIndex := FSelParentItem.Count;
  1073. NewItem := AClass.Create(FParentComponent.Owner{Designer.Form});
  1074. try
  1075. NewItem.Name := Designer.UniqueName(NewItem.ClassName);
  1076. FSelParentItem.Insert(NewIndex, NewItem);
  1077. except
  1078. NewItem.Free;
  1079. raise;
  1080. end;
  1081. Designer.Modified;
  1082. ListView.Selected := nil;
  1083. ListItem := ListView.FindData(0, NewItem, True, False);
  1084. if Assigned(ListItem) then begin
  1085. ListItem.Selected := True;
  1086. ListItem.Focused := True;
  1087. ListItem.MakeVisible(False);
  1088. ListView.SetFocus;
  1089. end;
  1090. end;
  1091. procedure TTBItemEditForm.NewSubmenuButtonClick(Sender: TObject);
  1092. begin
  1093. CreateNewItem(TTBSubmenuItem);
  1094. end;
  1095. procedure TTBItemEditForm.NewItemButtonClick(Sender: TObject);
  1096. begin
  1097. CreateNewItem(TTBItem);
  1098. end;
  1099. procedure TTBItemEditForm.NewSepButtonClick(Sender: TObject);
  1100. begin
  1101. CreateNewItem(TTBSeparatorItem);
  1102. end;
  1103. procedure TTBItemEditForm.MoreItemClick(Sender: TObject);
  1104. begin
  1105. CreateNewItem(TTBCustomItemClass((Sender as TTBItem).Tag));
  1106. end;
  1107. procedure TTBItemEditForm.CutButtonClick(Sender: TObject);
  1108. begin
  1109. Cut;
  1110. end;
  1111. procedure TTBItemEditForm.CopyButtonClick(Sender: TObject);
  1112. begin
  1113. Copy;
  1114. end;
  1115. procedure TTBItemEditForm.PasteButtonClick(Sender: TObject);
  1116. begin
  1117. Paste;
  1118. end;
  1119. procedure TTBItemEditForm.DeleteButtonClick(Sender: TObject);
  1120. begin
  1121. if ActiveControl = ListView then
  1122. Delete
  1123. else if (ActiveControl = TreeView) and (FSelParentItem <> FRootItem) then
  1124. DeleteItem(FSelParentItem);
  1125. end;
  1126. procedure TTBItemEditForm.MoveUpButtonClick(Sender: TObject);
  1127. var
  1128. SelList: TList;
  1129. I, J: Integer;
  1130. Item: TTBCustomItem;
  1131. ListItem: TListItem;
  1132. begin
  1133. if FSelParentItem = nil then Exit;
  1134. SelList := TList.Create;
  1135. try
  1136. GetSelItemList(SelList);
  1137. if SelList.Count = 0 then Exit;
  1138. ListView.Items.BeginUpdate;
  1139. FSelParentItem.ViewBeginUpdate;
  1140. { For good performance and to prevent Object Inspector flicker, increment
  1141. FSettingSel to prevent calls to SetSelParentItem while moving items }
  1142. Inc(FSettingSel);
  1143. try
  1144. for I := 0 to SelList.Count-1 do begin
  1145. Item := SelList[I];
  1146. J := FSelParentItem.IndexOf(Item);
  1147. if J <> -1 then
  1148. MoveItem(J, J-1);
  1149. end;
  1150. ListItem := ListView.FindData(0, SelList[0], True, False);
  1151. if Assigned(ListItem) then
  1152. ListItem.MakeVisible(False);
  1153. finally
  1154. Dec(FSettingSel);
  1155. FSelParentItem.ViewEndUpdate;
  1156. ListView.Items.EndUpdate;
  1157. end;
  1158. { After decrementing FSettingSel, now call SetSelParentItem, to update
  1159. the toolbar buttons }
  1160. SetSelParentItem(FSelParentItem);
  1161. finally
  1162. SelList.Free;
  1163. end;
  1164. end;
  1165. procedure TTBItemEditForm.MoveDownButtonClick(Sender: TObject);
  1166. var
  1167. SelList: TList;
  1168. I, J: Integer;
  1169. Item: TTBCustomItem;
  1170. ListItem: TListItem;
  1171. begin
  1172. if FSelParentItem = nil then Exit;
  1173. SelList := TList.Create;
  1174. try
  1175. GetSelItemList(SelList);
  1176. if SelList.Count = 0 then Exit;
  1177. ListView.Items.BeginUpdate;
  1178. FSelParentItem.ViewBeginUpdate;
  1179. { For good performance and to prevent Object Inspector flicker, increment
  1180. FSettingSel to prevent calls to SetSelParentItem while moving items }
  1181. Inc(FSettingSel);
  1182. try
  1183. for I := SelList.Count-1 downto 0 do begin
  1184. Item := SelList[I];
  1185. J := FSelParentItem.IndexOf(Item);
  1186. if J <> -1 then
  1187. MoveItem(J, J+1);
  1188. end;
  1189. ListItem := ListView.FindData(0, SelList[SelList.Count-1], True, False);
  1190. if Assigned(ListItem) then
  1191. ListItem.MakeVisible(False);
  1192. finally
  1193. Dec(FSettingSel);
  1194. FSelParentItem.ViewEndUpdate;
  1195. ListView.Items.EndUpdate;
  1196. end;
  1197. { After decrementing FSettingSel, now call SetSelParentItem, to update
  1198. the toolbar buttons }
  1199. SetSelParentItem(FSelParentItem);
  1200. finally
  1201. SelList.Free;
  1202. end;
  1203. end;
  1204. procedure TTBItemEditForm.TConvertMenuClick(Sender: TObject);
  1205. begin
  1206. if FSelParentItem = nil then Exit;
  1207. DoConvert(FSelParentItem, FParentComponent.Owner);
  1208. end;
  1209. { TTBItemsEditor }
  1210. procedure TTBItemsEditor.Edit;
  1211. var
  1212. Intf: ITBItems;
  1213. begin
  1214. if Assigned(Component) and Component.GetInterface(ITBItems, Intf) then
  1215. ShowEditForm(Component, Intf.GetItems, Designer);
  1216. end;
  1217. procedure TTBItemsEditor.ExecuteVerb(Index: Integer);
  1218. begin
  1219. case Index of
  1220. 0: Edit;
  1221. 1: ShowVersion;
  1222. end;
  1223. end;
  1224. function TTBItemsEditor.GetVerbCount: Integer;
  1225. begin
  1226. Result := 2;
  1227. end;
  1228. function TTBItemsEditor.GetVerb(Index: Integer): String;
  1229. begin
  1230. case Index of
  1231. 0: Result := 'Edit...';
  1232. 1: Result := 'Version...';
  1233. else
  1234. Result := '';
  1235. end;
  1236. end;
  1237. { TTBItemsPropertyEditor }
  1238. procedure TTBItemsPropertyEditor.Edit;
  1239. var
  1240. Editor: {$IFDEF JR_D6} IComponentEditor {$ELSE} TComponentEditor {$ENDIF};
  1241. begin
  1242. if PropCount <> 1 then Exit;
  1243. Editor := GetComponentEditor(GetComponent(0) as TComponent, Designer);
  1244. try
  1245. Editor.Edit;
  1246. finally
  1247. {$IFNDEF JR_D6}
  1248. Editor.Free;
  1249. {$ENDIF}
  1250. end;
  1251. end;
  1252. function TTBItemsPropertyEditor.GetAttributes: TPropertyAttributes;
  1253. begin
  1254. Result := inherited GetAttributes + [paDialog, paReadOnly];
  1255. end;
  1256. function TTBItemsPropertyEditor.GetValue: String;
  1257. begin
  1258. Result := '(TB2000 Items)';
  1259. end;
  1260. procedure TBRegisterDsgnEditorHook(Hook: TTBDsgnEditorHook);
  1261. var
  1262. H: ^TTBDsgnEditorHook;
  1263. begin
  1264. New(H);
  1265. H^ := Hook;
  1266. EditFormHooks.Add(H);
  1267. end;
  1268. procedure TBUnregisterDsgnEditorHook(Hook: TTBDsgnEditorHook);
  1269. var
  1270. H: ^TTBDsgnEditorHook;
  1271. I: Integer;
  1272. begin
  1273. for I := EditFormHooks.Count - 1 downto 0 do
  1274. begin
  1275. H := EditFormHooks[I];
  1276. if (TMethod(H^).Code = TMethod(Hook).Code) and
  1277. (TMethod(H^).Data = TMethod(Hook).Data) then
  1278. begin
  1279. Dispose(H);
  1280. EditFormHooks.Delete(I);
  1281. // Break;
  1282. end;
  1283. end;
  1284. end;
  1285. initialization
  1286. ItemImageList := TImageList.Create(nil);
  1287. ItemImageList.Handle := ImageList_LoadImage(HInstance, 'TB2_DSGNEDITORIMAGES',
  1288. 16, 0, clFuchsia, IMAGE_BITMAP, 0);
  1289. ItemClasses := TList.Create;
  1290. EditFormHooks := TList.Create;
  1291. AddModuleUnloadProc(UnregisterModuleItemClasses);
  1292. finalization
  1293. RemoveModuleUnloadProc(UnregisterModuleItemClasses);
  1294. FreeItemClasses;
  1295. FreeAndNil(ItemImageList);
  1296. FreeAndNil(EditFormHooks);
  1297. end.