/ide/patheditordlg.pas

http://github.com/graemeg/lazarus · Pascal · 635 lines · 532 code · 62 blank · 41 comment · 49 complexity · d479e513d6eebf054b120ede5addf109 MD5 · raw file

  1. {
  2. /***************************************************************************
  3. patheditordlg.pp
  4. ----------------
  5. ***************************************************************************/
  6. *****************************************************************************
  7. See the file COPYING.modifiedLGPL.txt, included in this distribution,
  8. for details about the license.
  9. *****************************************************************************
  10. Abstract:
  11. Defines the TPathEditorDialog, which is a form to edit search paths
  12. }
  13. unit PathEditorDlg;
  14. {$mode objfpc}{$H+}
  15. interface
  16. uses
  17. Classes, SysUtils, types, Forms, Controls, Buttons, StdCtrls, Dialogs, Graphics,
  18. Menus, ButtonPanel, ExtCtrls, FileUtil, LazFileUtils, MacroIntf, IDEImagesIntf,
  19. LCLType, TransferMacros, LazarusIDEStrConsts, ShortPathEdit, Clipbrd, LCLProc;
  20. type
  21. { TPathEditorDialog }
  22. TPathEditorDialog = class(TForm)
  23. AddTemplateButton: TBitBtn;
  24. ButtonPanel1: TButtonPanel;
  25. CopyMenuItem: TMenuItem;
  26. OpenDialog1: TOpenDialog;
  27. SaveDialog1: TSaveDialog;
  28. ExportMenuItem: TMenuItem;
  29. ImportMenuItem: TMenuItem;
  30. SeparMenuItem: TMenuItem;
  31. PasteMenuItem: TMenuItem;
  32. PopupMenu1: TPopupMenu;
  33. ReplaceButton: TBitBtn;
  34. AddButton: TBitBtn;
  35. DeleteInvalidPathsButton: TBitBtn;
  36. DirectoryEdit: TShortPathEdit;
  37. Splitter1: TSplitter;
  38. DeleteButton: TBitBtn;
  39. PathListBox: TListBox;
  40. MoveDownButton: TBitBtn;
  41. MoveUpButton: TBitBtn;
  42. TemplatesListBox: TListBox;
  43. TemplateGroupBox: TGroupBox;
  44. PathGroupBox: TGroupBox;
  45. BrowseDialog: TSelectDirectoryDialog;
  46. procedure AddButtonClick(Sender: TObject);
  47. procedure AddTemplateButtonClick(Sender: TObject);
  48. procedure CopyMenuItemClick(Sender: TObject);
  49. procedure ExportMenuItemClick(Sender: TObject);
  50. procedure PasteMenuItemClick(Sender: TObject);
  51. procedure DeleteInvalidPathsButtonClick(Sender: TObject);
  52. procedure DeleteButtonClick(Sender: TObject);
  53. procedure DirectoryEditAcceptDirectory(Sender: TObject; var Value: String);
  54. procedure DirectoryEditChange(Sender: TObject);
  55. procedure FormCreate(Sender: TObject);
  56. procedure FormResize(Sender: TObject);
  57. procedure FormShow(Sender: TObject);
  58. procedure MoveDownButtonClick(Sender: TObject);
  59. procedure MoveUpButtonClick(Sender: TObject);
  60. procedure PathListBoxDrawItem({%H-}Control: TWinControl; Index: Integer;
  61. ARect: TRect; {%H-}State: TOwnerDrawState);
  62. procedure PathListBoxKeyDown(Sender: TObject; var Key: Word;
  63. Shift: TShiftState);
  64. procedure PathListBoxSelectionChange(Sender: TObject; {%H-}User: boolean);
  65. procedure ReplaceButtonClick(Sender: TObject);
  66. procedure ImportMenuItemClick(Sender: TObject);
  67. procedure TemplatesListBoxDblClick(Sender: TObject);
  68. procedure TemplatesListBoxSelectionChange(Sender: TObject; {%H-}User: boolean);
  69. private
  70. FBaseDirectory: string;
  71. FEffectiveBaseDirectory: string;
  72. function GetPath: string;
  73. function GetTemplates: string;
  74. function BaseRelative(const APath: string): String;
  75. function PathAsAbsolute(const APath: string): String;
  76. function PathMayExist(APath: string): TObject;
  77. procedure ReadHelper(Paths: TStringList);
  78. procedure SetBaseDirectory(const AValue: string);
  79. procedure SetPath(const AValue: string);
  80. procedure SetTemplates(const AValue: string);
  81. procedure UpdateButtons;
  82. procedure WriteHelper(Paths: TStringList);
  83. public
  84. property BaseDirectory: string read FBaseDirectory write SetBaseDirectory;
  85. property EffectiveBaseDirectory: string read FEffectiveBaseDirectory;
  86. property Path: string read GetPath write SetPath;
  87. property Templates: string read GetTemplates write SetTemplates;
  88. end;
  89. TOnPathEditorExecuted = function (Context: String; var NewPath: String): Boolean of object;
  90. { TPathEditorButton }
  91. TPathEditorButton = class(TButton)
  92. private
  93. FCurrentPathEditor: TPathEditorDialog;
  94. FAssociatedEdit: TCustomEdit;
  95. FContextCaption: String;
  96. FTemplates: String;
  97. FOnExecuted: TOnPathEditorExecuted;
  98. protected
  99. procedure DoOnPathEditorExecuted;
  100. public
  101. procedure Click; override;
  102. property CurrentPathEditor: TPathEditorDialog read FCurrentPathEditor;
  103. property AssociatedEdit: TCustomEdit read FAssociatedEdit write FAssociatedEdit;
  104. property ContextCaption: String read FContextCaption write FContextCaption;
  105. property Templates: String read FTemplates write FTemplates;
  106. property OnExecuted: TOnPathEditorExecuted read FOnExecuted write FOnExecuted;
  107. end;
  108. function PathEditorDialog: TPathEditorDialog;
  109. procedure SetPathTextAndHint(aPath: String; aEdit: TCustomEdit);
  110. implementation
  111. {$R *.lfm}
  112. var PathEditor: TPathEditorDialog;
  113. function PathEditorDialog: TPathEditorDialog;
  114. begin
  115. if PathEditor=nil then
  116. PathEditor:=TPathEditorDialog.Create(Application);
  117. Result:=PathEditor;
  118. end;
  119. function TextToPath(const AText: string): string;
  120. var
  121. i, j: integer;
  122. begin
  123. Result:=AText;
  124. // convert all line ends to semicolons, remove empty paths and trailing spaces
  125. i:=1;
  126. j:=1;
  127. while i<=length(AText) do begin
  128. if AText[i] in [#10,#13] then begin
  129. // new line -> new path
  130. inc(i);
  131. if (i<=length(AText)) and (AText[i] in [#10,#13])
  132. and (AText[i]<>AText[i-1]) then
  133. inc(i);
  134. // skip spaces at end of path
  135. while (j>1) and (Result[j-1]=' ') do
  136. dec(j);
  137. // skip empty paths
  138. if (j=1) or (Result[j-1]<>';') then begin
  139. Result[j]:=';';
  140. inc(j);
  141. end;
  142. end else if ord(AText[i])<32 then begin
  143. // skip trailing spaces
  144. inc(i)
  145. end else if AText[i]=' ' then begin
  146. // space -> skip spaces at beginning of path
  147. if (j>1) and (Result[j-1]<>';') then begin
  148. Result[j]:=AText[i];
  149. inc(j);
  150. end;
  151. inc(i);
  152. end else begin
  153. // path char -> just copy
  154. Result[j]:=AText[i];
  155. inc(j);
  156. inc(i);
  157. end;
  158. end;
  159. if (j>1) and (Result[j-1]=';') then dec(j);
  160. SetLength(Result,j-1);
  161. end;
  162. function PathToText(const APath: string): string;
  163. var
  164. i: integer;
  165. begin
  166. Result:='';
  167. for i:=1 to length(APath) do
  168. if APath[i]=';' then
  169. Result:=Result+LineEnding
  170. else
  171. Result:=Result+APath[i];
  172. end;
  173. procedure SetPathTextAndHint(aPath: String; aEdit: TCustomEdit);
  174. begin
  175. aEdit.Text := aPath;
  176. if Pos(';', aPath) > 0 then // Zero or one separate paths.
  177. aEdit.Hint := PathToText(aPath)
  178. else
  179. aEdit.Hint := lisDelimiterIsSemicolon;
  180. end;
  181. { TPathEditorDialog }
  182. function TPathEditorDialog.BaseRelative(const APath: string): String;
  183. begin
  184. Result:=Trim(APath);
  185. if (FEffectiveBaseDirectory<>'') and FilenameIsAbsolute(FEffectiveBaseDirectory) then
  186. Result:=CreateRelativePath(Result, FEffectiveBaseDirectory);
  187. end;
  188. function TPathEditorDialog.PathAsAbsolute(const APath: string): String;
  189. begin
  190. Result:=APath;
  191. if not TTransferMacroList.StrHasMacros(Result) // not a template
  192. and (FEffectiveBaseDirectory<>'') and FilenameIsAbsolute(FEffectiveBaseDirectory) then
  193. Result:=CreateAbsolutePath(Result, FEffectiveBaseDirectory);
  194. end;
  195. function TPathEditorDialog.PathMayExist(APath: string): TObject;
  196. // Returns 1 if path exists or contains a macro, 0 otherwise.
  197. // Result is casted to TObject to be used for Strings.Objects.
  198. begin
  199. if TTransferMacroList.StrHasMacros(APath) then
  200. Exit(TObject(1));
  201. Result:=TObject(0);
  202. if (FEffectiveBaseDirectory<>'') and FilenameIsAbsolute(FEffectiveBaseDirectory) then
  203. APath:=CreateAbsolutePath(APath, FEffectiveBaseDirectory);
  204. if DirectoryExists(APath) then
  205. Result:=TObject(1);
  206. end;
  207. procedure TPathEditorDialog.AddButtonClick(Sender: TObject);
  208. var
  209. y: integer;
  210. RelPath: String;
  211. begin
  212. with PathListBox do begin
  213. y:=ItemIndex+1;
  214. if y=0 then
  215. y:=Count;
  216. RelPath:=BaseRelative(DirectoryEdit.Text);
  217. Items.InsertObject(y, RelPath, PathMayExist(DirectoryEdit.Text));
  218. ItemIndex:=y;
  219. UpdateButtons;
  220. end;
  221. end;
  222. procedure TPathEditorDialog.ReplaceButtonClick(Sender: TObject);
  223. var
  224. RelPath: String;
  225. begin
  226. with PathListBox do begin
  227. RelPath:=BaseRelative(DirectoryEdit.Text);
  228. Items[ItemIndex]:=RelPath;
  229. Items.Objects[ItemIndex]:=PathMayExist(DirectoryEdit.Text);
  230. UpdateButtons;
  231. end;
  232. end;
  233. procedure TPathEditorDialog.DeleteButtonClick(Sender: TObject);
  234. begin
  235. PathListBox.Items.Delete(PathListBox.ItemIndex);
  236. UpdateButtons;
  237. end;
  238. procedure TPathEditorDialog.DirectoryEditAcceptDirectory(Sender: TObject; var Value: String);
  239. begin
  240. DirectoryEdit.Text := BaseRelative(Value);
  241. {$IFDEF LCLCarbon}
  242. // Not auto-called on Mac. ToDo: fix it in the component instead of here.
  243. DirectoryEdit.OnChange(nil);
  244. {$ENDIF}
  245. end;
  246. procedure TPathEditorDialog.DeleteInvalidPathsButtonClick(Sender: TObject);
  247. var
  248. i: Integer;
  249. begin
  250. with PathListBox do
  251. for i:=Items.Count-1 downto 0 do
  252. if PtrInt(Items.Objects[i])=0 then
  253. Items.Delete(i);
  254. end;
  255. procedure TPathEditorDialog.AddTemplateButtonClick(Sender: TObject);
  256. var
  257. i, y: integer;
  258. begin
  259. y:=-1;
  260. for i:=0 to TemplatesListBox.Items.Count-1 do begin
  261. if TemplatesListBox.Selected[i]
  262. and (PathListBox.Items.IndexOf(TemplatesListBox.Items[i])=-1) then begin
  263. PathListBox.Items.AddObject(TemplatesListBox.Items[i], TObject(1));
  264. y:=PathListBox.Count-1;
  265. end;
  266. end;
  267. if y>=1 then begin
  268. PathListBox.ItemIndex:=y;
  269. UpdateButtons;
  270. end;
  271. end;
  272. procedure TPathEditorDialog.WriteHelper(Paths: TStringList);
  273. // Helper method for writing paths. Collect paths to a StringList.
  274. var
  275. i: integer;
  276. begin
  277. for i := 0 to PathListBox.Count-1 do
  278. Paths.Add(PathAsAbsolute(PathListBox.Items[i]));
  279. end;
  280. procedure TPathEditorDialog.CopyMenuItemClick(Sender: TObject);
  281. var
  282. Paths: TStringList;
  283. begin
  284. Paths := TStringList.Create;
  285. try
  286. WriteHelper(Paths);
  287. Clipboard.AsText := Paths.Text;
  288. finally
  289. Paths.Free;
  290. end;
  291. end;
  292. procedure TPathEditorDialog.ExportMenuItemClick(Sender: TObject);
  293. var
  294. Paths: TStringList;
  295. begin
  296. if not SaveDialog1.Execute then Exit;
  297. Paths := TStringList.Create;
  298. try
  299. WriteHelper(Paths);
  300. Paths.SaveToFile(SaveDialog1.FileName);
  301. finally
  302. Paths.Free;
  303. end;
  304. end;
  305. procedure TPathEditorDialog.ReadHelper(Paths: TStringList);
  306. // Helper method for reading paths. Insert paths from a StringList to the ListBox.
  307. var
  308. s: string;
  309. y, i: integer;
  310. begin
  311. y := PathListBox.ItemIndex;
  312. if y = -1 then
  313. y := PathListBox.Count-1;
  314. for i := 0 to Paths.Count-1 do
  315. begin
  316. s := Trim(Paths[i]);
  317. if s <> '' then
  318. begin
  319. Inc(y);
  320. PathListBox.Items.InsertObject(y, BaseRelative(s), PathMayExist(s));
  321. end;
  322. end;
  323. //PathListBox.ItemIndex := y;
  324. UpdateButtons;
  325. end;
  326. procedure TPathEditorDialog.PasteMenuItemClick(Sender: TObject);
  327. var
  328. Paths: TStringList;
  329. begin
  330. Paths := TStringList.Create;
  331. try
  332. Paths.Text := Clipboard.AsText;
  333. ReadHelper(Paths);
  334. finally
  335. Paths.Free;
  336. end;
  337. end;
  338. procedure TPathEditorDialog.ImportMenuItemClick(Sender: TObject);
  339. var
  340. Paths: TStringList;
  341. begin
  342. if not OpenDialog1.Execute then Exit;
  343. Paths := TStringList.Create;
  344. try
  345. Paths.LoadFromFile(OpenDialog1.FileName);
  346. ReadHelper(Paths);
  347. finally
  348. Paths.Free;
  349. end;
  350. end;
  351. procedure TPathEditorDialog.DirectoryEditChange(Sender: TObject);
  352. begin
  353. UpdateButtons;
  354. end;
  355. procedure TPathEditorDialog.PathListBoxSelectionChange(Sender: TObject; User: boolean);
  356. Var
  357. FullPath : String;
  358. begin
  359. with PathListBox do
  360. if ItemIndex>-1 then begin
  361. DirectoryEdit.Text:=BaseRelative(Items[ItemIndex]);
  362. FullPath := Items[ItemIndex];
  363. IDEMacros.SubstituteMacros(FullPath);
  364. DirectoryEdit.Directory:=PathAsAbsolute(FullPath);
  365. end;
  366. UpdateButtons;
  367. end;
  368. procedure TPathEditorDialog.TemplatesListBoxSelectionChange(Sender: TObject; User: boolean);
  369. begin
  370. UpdateButtons;
  371. end;
  372. procedure TPathEditorDialog.TemplatesListBoxDblClick(Sender: TObject);
  373. begin
  374. AddTemplateButtonClick(Nil);
  375. end;
  376. procedure TPathEditorDialog.FormCreate(Sender: TObject);
  377. const
  378. Filt = 'Text file (*.txt)|*.txt|All files (*)|*';
  379. begin
  380. Caption:=dlgDebugOptionsPathEditorDlgCaption;
  381. PathGroupBox.Caption:=lisPathEditSearchPaths;
  382. MoveUpButton.Hint:=lisPathEditMovePathUp;
  383. MoveDownButton.Hint:=lisPathEditMovePathDown;
  384. ReplaceButton.Caption:=lisReplace;
  385. ReplaceButton.Hint:=lisPathEditorReplaceHint;
  386. AddButton.Caption:=lisAdd;
  387. AddButton.Hint:=lisPathEditorAddHint;
  388. DeleteButton.Caption:=lisDelete;
  389. DeleteButton.Hint:=lisPathEditorDeleteHint;
  390. DeleteInvalidPathsButton.Caption:=lisPathEditDeleteInvalidPaths;
  391. DeleteInvalidPathsButton.Hint:=lisPathEditorDeleteInvalidHint;
  392. TemplateGroupBox.Caption:=lisPathEditPathTemplates;
  393. AddTemplateButton.Caption:=lisCodeTemplAdd;
  394. AddTemplateButton.Hint:=lisPathEditorTemplAddHint;
  395. PopupMenu1.Images:=IDEImages.Images_16;
  396. CopyMenuItem.Caption:=lisCopyAllItemsToClipboard;
  397. CopyMenuItem.ImageIndex:=IDEImages.LoadImage(16, 'laz_copy');
  398. PasteMenuItem.Caption:=lisPasteFromClipboard;
  399. PasteMenuItem.ImageIndex:=IDEImages.LoadImage(16, 'laz_paste');
  400. ExportMenuItem.Caption:=lisExportAllItemsToFile;
  401. ExportMenuItem.ImageIndex:=IDEImages.LoadImage(16, 'laz_save');
  402. ImportMenuItem.Caption:=lisImportFromFile;
  403. ImportMenuItem.ImageIndex:=IDEImages.LoadImage(16, 'laz_open');
  404. OpenDialog1.Filter:=Filt;
  405. SaveDialog1.Filter:=Filt;
  406. MoveUpButton.LoadGlyphFromResourceName(HInstance, 'arrow_up');
  407. MoveDownButton.LoadGlyphFromResourceName(HInstance, 'arrow_down');
  408. ReplaceButton.LoadGlyphFromResourceName(HInstance, 'menu_reportingbug');
  409. AddButton.LoadGlyphFromResourceName(HInstance, 'laz_add');
  410. DeleteButton.LoadGlyphFromResourceName(HInstance, 'laz_delete');
  411. DeleteInvalidPathsButton.LoadGlyphFromResourceName(HInstance, 'menu_clean');
  412. AddTemplateButton.LoadGlyphFromResourceName(HInstance, 'laz_add');
  413. end;
  414. procedure TPathEditorDialog.FormResize(Sender: TObject);
  415. var
  416. PathGroupBoxHeight: integer;
  417. begin
  418. PathGroupBoxHeight:=((ClientHeight-70)*2) div 3;
  419. if PathGroupBoxHeight<10 then
  420. PathGroupBoxHeight:=10;
  421. PathGroupBox.Height:=PathGroupBoxHeight;
  422. end;
  423. procedure TPathEditorDialog.FormShow(Sender: TObject);
  424. begin
  425. PathListBox.ItemIndex:=-1;
  426. TemplatesListBox.ItemIndex:=-1;
  427. UpdateButtons;
  428. end;
  429. procedure TPathEditorDialog.MoveDownButtonClick(Sender: TObject);
  430. var
  431. y: integer;
  432. begin
  433. y:=PathListBox.ItemIndex;
  434. if (y>-1) and (y<PathListBox.Count-1) then begin
  435. PathListBox.Items.Move(y,y+1);
  436. PathListBox.ItemIndex:=y+1;
  437. UpdateButtons;
  438. end;
  439. end;
  440. procedure TPathEditorDialog.MoveUpButtonClick(Sender: TObject);
  441. var
  442. y: integer;
  443. begin
  444. y:=PathListBox.ItemIndex;
  445. if (y>0) and (y<PathListBox.Count) then begin
  446. PathListBox.Items.Move(y,y-1);
  447. PathListBox.ItemIndex:=y-1;
  448. UpdateButtons;
  449. end;
  450. end;
  451. procedure TPathEditorDialog.PathListBoxDrawItem(Control: TWinControl;
  452. Index: Integer; ARect: TRect; State: TOwnerDrawState);
  453. begin
  454. if Index < 0 then Exit;
  455. with PathListBox do begin
  456. Canvas.FillRect(ARect);
  457. if PtrInt(Items.Objects[Index]) = 0 then
  458. Canvas.Font.Color := clGray;
  459. Canvas.TextRect(ARect, ARect.Left, ARect.Top, Items[Index]);
  460. end;
  461. end;
  462. procedure TPathEditorDialog.PathListBoxKeyDown(Sender: TObject; var Key: Word;
  463. Shift: TShiftState);
  464. begin
  465. if (ssCtrl in shift) and ((Key = VK_UP) or (Key = VK_DOWN)) then begin
  466. if Key = VK_UP then
  467. MoveUpButtonClick(Nil)
  468. else
  469. MoveDownButtonClick(Nil);
  470. Key:=VK_UNKNOWN;
  471. end;
  472. end;
  473. function TPathEditorDialog.GetPath: string;
  474. begin
  475. Result:=TextToPath(PathListBox.Items.Text);
  476. end;
  477. function TPathEditorDialog.GetTemplates: string;
  478. begin
  479. Result:=TextToPath(TemplatesListBox.Items.Text);
  480. end;
  481. procedure TPathEditorDialog.SetPath(const AValue: string);
  482. var
  483. sl: TStringList;
  484. i: Integer;
  485. begin
  486. DirectoryEdit.Text:='';
  487. PathListBox.Items.Clear;
  488. sl:=TstringList.Create();
  489. try
  490. sl.Text:=PathToText(AValue);
  491. for i:=0 to sl.Count-1 do
  492. PathListBox.Items.AddObject(sl[i], PathMayExist(sl[i]));
  493. PathListBox.ItemIndex:=-1;
  494. finally
  495. sl.Free;
  496. end;
  497. end;
  498. procedure TPathEditorDialog.SetTemplates(const AValue: string);
  499. var
  500. NewVis: Boolean;
  501. begin
  502. TemplatesListBox.Items.Text := PathToText(AValue);
  503. NewVis := TemplatesListBox.Count > 0;
  504. if NewVis = TemplateGroupBox.Visible then Exit;
  505. TemplateGroupBox.Visible := NewVis;
  506. if NewVis then
  507. TemplateGroupBox.Top:=0;
  508. end;
  509. procedure TPathEditorDialog.UpdateButtons;
  510. var
  511. i: integer;
  512. InValidPathsExist: Boolean;
  513. begin
  514. // Replace / add / delete / Delete Invalid Paths
  515. AddButton.Enabled:=(DirectoryEdit.Text<>'') and (DirectoryEdit.Text<>FEffectiveBaseDirectory)
  516. and (PathListBox.Items.IndexOf(BaseRelative(DirectoryEdit.Text))=-1);
  517. ReplaceButton.Enabled:=AddButton.Enabled and (PathListBox.ItemIndex>-1) ;
  518. DeleteButton.Enabled:=PathListBox.SelCount=1; // or ItemIndex>-1; ?
  519. AddTemplateButton.Enabled:=(TemplatesListBox.SelCount>1) or ((TemplatesListBox.ItemIndex>-1)
  520. and (PathListBox.Items.IndexOf(TemplatesListBox.Items[TemplatesListBox.ItemIndex])=-1));
  521. // Delete non-existent paths button. Check if there are any.
  522. InValidPathsExist:=False;
  523. for i:=0 to PathListBox.Items.Count-1 do
  524. if PtrInt(PathListBox.Items.Objects[i])=0 then begin
  525. InValidPathsExist:=True;
  526. Break;
  527. end;
  528. DeleteInvalidPathsButton.Enabled:=InValidPathsExist;
  529. // Move up / down buttons
  530. i := PathListBox.ItemIndex;
  531. MoveUpButton.Enabled := i > 0;
  532. MoveDownButton.Enabled := (i > -1) and (i < PathListBox.Count-1);
  533. end;
  534. procedure TPathEditorDialog.SetBaseDirectory(const AValue: string);
  535. begin
  536. if FBaseDirectory=AValue then exit;
  537. FBaseDirectory:=AValue;
  538. FEffectiveBaseDirectory:=FBaseDirectory;
  539. IDEMacros.SubstituteMacros(FEffectiveBaseDirectory);
  540. DirectoryEdit.Directory:=FEffectiveBaseDirectory;
  541. end;
  542. { TPathEditorButton }
  543. procedure TPathEditorButton.Click;
  544. begin
  545. FCurrentPathEditor:=PathEditorDialog;
  546. try
  547. inherited Click;
  548. FCurrentPathEditor.Templates := SetDirSeparators(FTemplates);
  549. FCurrentPathEditor.Path := AssociatedEdit.Text;
  550. FCurrentPathEditor.ShowModal;
  551. DoOnPathEditorExecuted;
  552. finally
  553. FCurrentPathEditor:=nil;
  554. end;
  555. end;
  556. procedure TPathEditorButton.DoOnPathEditorExecuted;
  557. var
  558. Ok: Boolean;
  559. NewPath: String;
  560. begin
  561. NewPath := FCurrentPathEditor.Path;
  562. Ok := (FCurrentPathEditor.ModalResult = mrOk) and (AssociatedEdit.Text <> NewPath);
  563. if Ok and Assigned(OnExecuted) then
  564. Ok := OnExecuted(ContextCaption, NewPath);
  565. // Assign value only if old <> new and OnExecuted allows it.
  566. if Ok then
  567. SetPathTextAndHint(NewPath, AssociatedEdit);
  568. end;
  569. end.