1 unit EditorFileManager;
2
3 {$mode objfpc}{$H+}
4
5 interface
6
7 uses
8 Classes, sysutils, Forms, Controls, CheckLst, ButtonPanel, StdCtrls, Buttons,
9 ExtCtrls, Menus, LCLProc, LCLType, IDEImagesIntf, LazIDEIntf, IDEHelpIntf,
10 SrcEditorIntf, IDEWindowIntf, SourceEditor, LazarusIDEStrConsts,
11 ListFilterEdit, IDEOptionDefs;
12
13 type
14
15 { TEditorFileManagerForm }
16
17 TEditorFileManagerForm = class(TForm)
18 ActivateMenuItem: TMenuItem;
19 FileCountLabel: TLabel;
20 MoveDownBtn: TSpeedButton;
21 MoveUpBtn: TSpeedButton;
22 FilterPanel: TPanel;
23 OpenButton: TSpeedButton;
24 SaveCheckedButton: TBitBtn;
25 ButtonPanel1: TButtonPanel;
26 CloseCheckedButton: TBitBtn;
27 CloseMenuItem: TMenuItem;
28 Panel1: TPanel;
29 PopupMenu1: TPopupMenu;
30 CheckAllCheckBox: TCheckBox;
31 CheckListBox1: TCheckListBox;
32 FilterEdit: TListFilterEdit;
33 SortAlphabeticallyButton: TSpeedButton;
34 procedure ActivateMenuItemClick(Sender: TObject);
35 procedure CheckListBox1DblClick(Sender: TObject);
36 procedure CheckListBox1KeyDown(Sender: TObject; var Key: Word;
37 Shift: TShiftState);
38 procedure CheckListBox1KeyPress(Sender: TObject; var Key: char);
39 procedure CloseButtonClick(Sender: TObject);
40 procedure DoEditorsChanged(Sender: TObject);
41 procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
42 procedure HelpButtonClick(Sender: TObject);
43 procedure MoveDownBtnClick(Sender: TObject);
44 procedure MoveUpBtnClick(Sender: TObject);
45 procedure CheckListBox1Click(Sender: TObject);
46 procedure CheckListBox1ItemClick(Sender: TObject; Index: integer);
47 procedure CloseCheckedButtonClick(Sender: TObject);
48 procedure PopupMenu1Popup(Sender: TObject);
49 procedure SaveCheckedButtonClick(Sender: TObject);
50 procedure CloseMenuItemClick(Sender: TObject);
51 procedure FormCreate(Sender: TObject);
52 procedure ActivateButtonClick(Sender: TObject);
53 procedure CheckAllCheckBoxClick(Sender: TObject);
54 procedure SortAlphabeticallyButtonClick(Sender: TObject);
55 private
56 FSortAlphabetically: boolean;
57 procedure CloseListItem(ListIndex: integer);
58 procedure PopulateList;
SrcEditorByListItemnull59 function SrcEditorByListItem(ListIndex: integer): TSourceEditor;
60 procedure SetSortAlphabetically(AValue: boolean);
61 procedure UpdateCheckAllCaption;
62 procedure UpdateButtons;
63 procedure UpdateMoveButtons(ListIndex: integer);
64 public
65 destructor Destroy; override;
66 property SortAlphabetically: boolean read FSortAlphabetically write SetSortAlphabetically;
67 end;
68
69 var
70 EditorFileManagerForm: TEditorFileManagerForm;
71
72 procedure ShowEditorFileManagerForm(State: TIWGetFormState = iwgfShowOnTop);
73
74 implementation
75
76 {$R *.lfm}
77
78 procedure ShowEditorFileManagerForm(State: TIWGetFormState);
79 begin
80 if EditorFileManagerForm = Nil then
81 IDEWindowCreators.CreateForm(EditorFileManagerForm,TEditorFileManagerForm,
82 State=iwgfDisabled,LazarusIDE.OwningComponent)
83 else if State=iwgfDisabled then
84 EditorFileManagerForm.DisableAlign;
85 if State>=iwgfShow then
86 IDEWindowCreators.ShowForm(EditorFileManagerForm,State=iwgfShowOnTop);
87 end;
88
89 { TEditorFileManagerForm }
90
91 procedure TEditorFileManagerForm.FormCreate(Sender: TObject);
92 begin
93 Name := NonModalIDEWindowNames[nmiwEditorFileManager];
94
95 SourceEditorManager.RegisterChangeEvent(semEditorCreate, @DoEditorsChanged);
96 SourceEditorManager.RegisterChangeEvent(semEditorDestroy, @DoEditorsChanged);
97
98 PopulateList; // Populate the list with all open editor file names
99 // Captions
100 Caption:=lisSourceEditorWindowManager;
101 ActivateMenuItem.Caption:=lisActivate;
102 CloseMenuItem.Caption:=lisClose;
103 CheckAllCheckBox.Caption:=lisCheckAll;
104 SaveCheckedButton.Caption:=lisSaveAllChecked;
105 CloseCheckedButton.Caption:=lisCloseAllChecked;
106 MoveUpBtn.Hint:=lisMoveSelectedUp;
107 MoveDownBtn.Hint:=lisMoveSelectedDown;
108 // Icons
109 PopupMenu1.Images:=IDEImages.Images_16;
110 ActivateMenuItem.ImageIndex:=IDEImages.LoadImage('laz_open');
111 CloseMenuItem.ImageIndex:=IDEImages.LoadImage('menu_close');
112 IDEImages.AssignImage(CloseCheckedButton, 'menu_close_all');
113 IDEImages.AssignImage(SaveCheckedButton, 'menu_save_all');
114 IDEImages.AssignImage(MoveUpBtn, 'arrow_up');
115 IDEImages.AssignImage(MoveDownBtn, 'arrow_down');
116 // Buttons on FilterPanel
117 IDEImages.AssignImage(OpenButton, 'laz_open');
118 OpenButton.Hint:=lisActivateSelected;
119 SortAlphabeticallyButton.Hint:=lisPESortFilesAlphabetically;
120 IDEImages.AssignImage(SortAlphabeticallyButton, 'pkg_sortalphabetically');
121 end;
122
123 procedure TEditorFileManagerForm.CheckListBox1Click(Sender: TObject);
124 var
125 clb: TCheckListBox;
126 begin
127 clb:=Sender as TCheckListBox;
128 // Enable Activate when there is a selected item.
129 OpenButton.Enabled:=clb.SelCount>0;
130 UpdateMoveButtons(clb.ItemIndex);
131 end;
132
133 procedure TEditorFileManagerForm.CheckListBox1ItemClick(Sender: TObject; Index: integer);
134 var
135 clb: TCheckListBox;
136 i: Integer;
137 HasChecked: Boolean;
138 begin
139 clb:=Sender as TCheckListBox;
140 // Notify the filter edit that item's checked state has changed.
141 if Index>-1 then
142 FilterEdit.ItemWasClicked(clb.Items[Index], clb.Checked[Index]);
143 // Enable save and close buttons when there are checked items.
144 HasChecked:=False;
145 for i:=clb.Count-1 downto 0 do
146 if clb.Checked[i] then begin
147 HasChecked:=True;
148 Break;
149 end;
150 SaveCheckedButton.Enabled:=HasChecked;
151 CloseCheckedButton.Enabled:=HasChecked;
152 CloseMenuItem.Enabled:=HasChecked;
153 CheckAllCheckBox.Enabled:=clb.Count>0;
154 // If all items were unchecked, change CheckAllCheckBox state.
155 if CheckAllCheckBox.Checked and not HasChecked then begin
156 CheckAllCheckBox.Checked:=HasChecked;
157 UpdateCheckAllCaption;
158 end;
159 CheckListBox1Click(CheckListBox1); // Call also OnClick handler for other controls.
160 end;
161
162 procedure TEditorFileManagerForm.CheckAllCheckBoxClick(Sender: TObject);
163 var
164 cb: TCheckBox;
165 i: Integer;
166 begin
167 cb:=Sender as TCheckBox;
168 UpdateCheckAllCaption;
169 // Set / reset all CheckListBox1 items.
170 for i:=0 to CheckListBox1.Count-1 do begin
171 if CheckListBox1.Checked[i]<>cb.Checked then begin
172 CheckListBox1.Checked[i]:=cb.Checked;
173 FilterEdit.ItemWasClicked(CheckListBox1.Items[i], cb.Checked); // Notify the filter
174 end;
175 end;
176 CheckListBox1ItemClick(CheckListBox1, CheckListBox1.Count-1);
177 end;
178
179 procedure TEditorFileManagerForm.SortAlphabeticallyButtonClick(Sender: TObject);
180 begin
181 SortAlphabetically:=SortAlphabeticallyButton.Down;
182 end;
183
184 procedure TEditorFileManagerForm.SaveCheckedButtonClick(Sender: TObject);
185 var
186 i: Integer;
187 SrcEdit: TSourceEditor;
188 begin
189 for i:=CheckListBox1.Count-1 downto 0 do
190 if CheckListBox1.Checked[i] then begin
191 SrcEdit:=SrcEditorByListItem(i);
192 Assert(Assigned(SrcEdit), 'TEditorFileManagerForm.SaveCheckedButtonClick: SrcEdit is not assigned.');
193 if (not SrcEdit.CodeBuffer.IsVirtual) and (LazarusIDE.DoSaveEditorFile(SrcEdit, []) <> mrOk) then
194 DebugLn(['TSourceNotebook.EncodingClicked LazarusIDE.DoSaveEditorFile failed']);
195 end;
196 end;
197
198 procedure TEditorFileManagerForm.CloseCheckedButtonClick(Sender: TObject);
199 var
200 i: Integer;
201 begin
202 for i:=CheckListBox1.Count-1 downto 0 do
203 if CheckListBox1.Checked[i] then
204 CloseListItem(i);
205 PopulateList;
206 UpdateButtons;
207 end;
208
209 procedure TEditorFileManagerForm.PopupMenu1Popup(Sender: TObject);
210 var
211 HasSelected: Boolean;
212 begin
213 HasSelected:=CheckListBox1.SelCount>0;
214 ActivateMenuItem.Enabled:=HasSelected;
215 CloseMenuItem.Enabled:=HasSelected;
216 end;
217
218 procedure TEditorFileManagerForm.CloseMenuItemClick(Sender: TObject);
219 begin
220 CloseListItem(CheckListBox1.ItemIndex);
221 PopulateList;
222 UpdateButtons;
223 end;
224
225 procedure TEditorFileManagerForm.ActivateMenuItemClick(Sender: TObject);
226 begin
227 ActivateButtonClick(nil);
228 end;
229
230 procedure TEditorFileManagerForm.CheckListBox1DblClick(Sender: TObject);
231 begin
232 ActivateButtonClick(nil);
233 end;
234
235 procedure TEditorFileManagerForm.CheckListBox1KeyDown(Sender: TObject;
236 var Key: Word; Shift: TShiftState);
237 begin
238 if (ssCtrl in Shift ) and ((Key = VK_UP) or (Key = VK_DOWN)) then begin
239 if Key = VK_UP then
240 MoveUpBtnClick(nil)
241 else
242 MoveDownBtnClick(nil);
243 Key:=VK_UNKNOWN;
244 end;
245 end;
246
247 procedure TEditorFileManagerForm.CheckListBox1KeyPress(Sender: TObject; var Key: char);
248 begin
249 if Key = char(VK_RETURN) then
250 ActivateButtonClick(nil);
251 end;
252
253 procedure TEditorFileManagerForm.CloseButtonClick(Sender: TObject);
254 begin
255 Close;
256 end;
257
258 procedure TEditorFileManagerForm.DoEditorsChanged(Sender: TObject);
259 begin
260 PopulateList;
261 end;
262
263 procedure TEditorFileManagerForm.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
264 begin
265 if (Key = VK_ESCAPE) and (Shift = []) then
266 Close;
267 end;
268
269 procedure TEditorFileManagerForm.HelpButtonClick(Sender: TObject);
270 begin
271 LazarusHelp.ShowHelpForIDEControl(Self);
272 end;
273
274 procedure TEditorFileManagerForm.MoveDownBtnClick(Sender: TObject);
275 var
276 SrcEdit: TSourceEditor;
277 i: Integer;
278 begin
279 i:=CheckListBox1.ItemIndex;
280 if (i>-1) and (i<CheckListBox1.Items.Count-1)
281 and (FilterEdit.Filter='') and not SortAlphabetically then begin
282 SrcEdit:=SrcEditorByListItem(i);
283 Assert(Assigned(SrcEdit), 'TEditorFileManagerForm.MoveDownBtnClick: SrcEdit is not assigned.');
284 if SrcEdit.PageIndex < SrcEdit.SourceNotebook.PageCount-1 then begin
285 // First move the source editor tab
286 SrcEdit.SourceNotebook.MoveEditor(SrcEdit.PageIndex, SrcEdit.PageIndex+1);
287 // Then switch the list items
288 FilterEdit.Items.Exchange(i, i+1);
289 FilterEdit.InvalidateFilter;
290 UpdateMoveButtons(i+1);
291 end;
292 end;
293 end;
294
295 procedure TEditorFileManagerForm.MoveUpBtnClick(Sender: TObject);
296 var
297 SrcEdit: TSourceEditor;
298 i: Integer;
299 begin
300 i := CheckListBox1.ItemIndex;
301 if (i > 0) and (FilterEdit.Filter='') and not SortAlphabetically then begin
302 SrcEdit:=SrcEditorByListItem(i);
303 Assert(Assigned(SrcEdit), 'TEditorFileManagerForm.MoveUpBtnClick: SrcEdit is not assigned.');
304 if SrcEdit.PageIndex > 0 then begin
305 // First move the source editor tab
306 SrcEdit.SourceNotebook.MoveEditor(SrcEdit.PageIndex, SrcEdit.PageIndex-1);
307 // Then switch the list items
308 FilterEdit.Items.Exchange(i, i-1);
309 FilterEdit.InvalidateFilter;
310 UpdateMoveButtons(i-1);
311 end;
312 end;
313 end;
314
315 procedure TEditorFileManagerForm.ActivateButtonClick(Sender: TObject);
316 var
317 i: Integer;
318 SrcEdit: TSourceEditor;
319 begin
320 for i:=0 to CheckListBox1.Count-1 do
321 if CheckListBox1.Selected[i] then begin // Find first selected.
322 SrcEdit:=SrcEditorByListItem(CheckListBox1.ItemIndex);
323 Assert(Assigned(SrcEdit), 'TEditorFileManagerForm.ActivateButtonClick: SrcEdit is not assigned.');
324 SrcEdit.Activate;
325 Break;
326 end;
327 end;
328
329 // Private methods
330
331 procedure TEditorFileManagerForm.CloseListItem(ListIndex: integer);
332 var
333 SrcEdit: TSourceEditor;
334 begin
335 SrcEdit:=SrcEditorByListItem(ListIndex);
336 Assert(Assigned(SrcEdit), 'TEditorFileManagerForm.CloseListItem: SrcEdit is not assigned.');
337 LazarusIDE.DoCloseEditorFile(SrcEdit, [cfSaveFirst]);
338 end;
339
340 procedure TEditorFileManagerForm.PopulateList;
341 // Populate the list with all open editor file names
342 var
343 SrcEdit: TSourceEditor;
344 i, j: Integer;
345 sw: TSourceNotebook;
346 Modi: String;
347 begin
348 FilterEdit.Items.Clear;
349 with SourceEditorManager do
350 for i:=0 to SourceWindowCount-1 do begin
351 sw:=SourceWindows[i];
352 Assert(sw.PageCount=sw.EditorCount, 'sw.PageCount<>sw.EditorCount');
353 for j:=0 to sw.EditorCount-1 do begin
354 SrcEdit:=sw.FindSourceEditorWithPageIndex(j);
355 if SrcEdit.Modified then
356 Modi:='* '
357 else
358 Modi:='';
359 FilterEdit.Items.Add(Modi+SrcEdit.FileName);
360 end;
361 end;
362 FilterEdit.InvalidateFilter;
363 FileCountLabel.Caption:=Format(dlgFiles,[IntToStr(SourceEditorManager.SourceEditorCount)]);
364 end;
365
SrcEditorByListItemnull366 function TEditorFileManagerForm.SrcEditorByListItem(ListIndex: integer): TSourceEditor;
367 var
368 s: String;
369 begin
370 s:=CheckListBox1.Items[ListIndex];
371 if (s<>'') and (s[1]='*') then // Modified indicator
372 delete(s, 1, 2);
373 Result:=SourceEditorManager.SourceEditorIntfWithFilename(s);
374 end;
375
376 procedure TEditorFileManagerForm.SetSortAlphabetically(AValue: boolean);
377 begin
378 if FSortAlphabetically=AValue then exit;
379 FSortAlphabetically:=AValue;
380 SortAlphabeticallyButton.Down:=FSortAlphabetically;
381 FilterEdit.SortData:=FSortAlphabetically;
382 FilterEdit.InvalidateFilter;
383 end;
384
385 procedure TEditorFileManagerForm.UpdateCheckAllCaption;
386 // Caption text: check all / uncheck all
387 begin
388 if CheckAllCheckBox.Checked then
389 CheckAllCheckBox.Caption:=lisUncheckAll
390 else
391 CheckAllCheckBox.Caption:=lisCheckAll;
392 end;
393
394 procedure TEditorFileManagerForm.UpdateButtons;
395 // Update the filter and buttons. Reuse event handlers for it.
396 begin
397 FilterEdit.InvalidateFilter;
398 CheckListBox1ItemClick(CheckListBox1, CheckListBox1.Count-1);
399 end;
400
401 procedure TEditorFileManagerForm.UpdateMoveButtons(ListIndex: integer);
402 var
403 SrcEdit: TSourceEditor;
404 UpEnabled, DownEnabled: Boolean;
405 begin
406 UpEnabled:=False;
407 DownEnabled:=False;
408 if (ListIndex>-1) and (ListIndex<CheckListBox1.Items.Count)
409 and (FilterEdit.Filter='') and not SortAlphabetically then begin
410 //DebugLn(['TEditorFileManagerForm.UpdateMoveButtons: Filename', CheckListBox1.Items[ListIndex], ', ListIndex:', ListIndex]);
411 SrcEdit:=SrcEditorByListItem(ListIndex);
412 if Assigned(SrcEdit) then begin
413 DownEnabled:=(ListIndex<CheckListBox1.Items.Count-1)
414 and (SrcEdit.PageIndex<SrcEdit.SourceNotebook.PageCount-1);
415 UpEnabled:=(ListIndex>0) and (SrcEdit.PageIndex>0);
416 end;
417 end;
418 MoveUpBtn.Enabled:=UpEnabled;
419 MoveDownBtn.Enabled:=DownEnabled;
420 end;
421
422 destructor TEditorFileManagerForm.Destroy;
423 begin
424 if SourceEditorManager <> nil then begin
425 SourceEditorManager.UnRegisterChangeEvent(semEditorCreate, @DoEditorsChanged);
426 SourceEditorManager.UnRegisterChangeEvent(semEditorDestroy, @DoEditorsChanged);
427 end;
428 inherited Destroy;
429 end;
430
431 end.
432
433