1 {
2 ***************************************************************************
3 * *
4 * This source is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This code is distributed in the hope that it will be useful, but *
10 * WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * General Public License for more details. *
13 * *
14 * A copy of the GNU General Public License is available on the World *
15 * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
16 * obtain it by writing to the Free Software Foundation, *
17 * Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. *
18 * *
19 ***************************************************************************
20
21 Author: Mattias Gaertner
22
23 Abstract:
24 A dialog showing the unused units of the current unit
25 (at cursor in source editor).
26 With the ability to remove them automatically.
27 }
28 unit UnusedUnitsDlg;
29
30 {$mode objfpc}{$H+}
31
32 interface
33
34 uses
35 Classes, SysUtils,
36 // LCL
37 Forms, Controls, ComCtrls, StdCtrls, ExtCtrls, Buttons, Dialogs,
38 // LazUtils
39 LazUTF8, LazLoggerBase,
40 // Codetools
41 CodeCache, CodeToolManager,
42 // IdeIntf
43 SrcEditorIntf, LazIDEIntf, IDEImagesIntf, IDEDialogs,
44 // IDE
45 LazarusIDEStrConsts;
46
47 type
48
49 { TUnusedUnitsDialog }
50
51 TUnusedUnitsDialog = class(TForm)
52 CancelBitBtn: TBitBtn;
53 ShowInitializationCheckBox: TCheckBox;
54 RemoveAllBitBtn: TBitBtn;
55 RemoveSelectedBitBtn: TBitBtn;
56 Panel1: TPanel;
57 UnitsTreeView: TTreeView;
58 procedure CancelBitBtnClick(Sender: TObject);
59 procedure FormCreate(Sender: TObject);
60 procedure RemoveAllBitBtnClick(Sender: TObject);
61 procedure RemoveSelectedBitBtnClick(Sender: TObject);
62 procedure ShowInitializationCheckBoxClick(Sender: TObject);
63 procedure UnitsTreeViewSelectionChanged(Sender: TObject);
64 private
65 FCode: TCodeBuffer;
66 FUnits: TStrings;
67 ImgIDInterface: LongInt;
68 ImgIDImplementation: LongInt;
69 ImgIDInitialization: LongInt;
70 ImgIDNone: LongInt;
71 procedure SetCode(AValue: TCodeBuffer);
72 procedure SetUnits(const AValue: TStrings);
73 procedure RebuildUnitsTreeView;
74 procedure UpdateButtons;
75 public
GetSelectedUnitsnull76 function GetSelectedUnits: TStrings;
GetAllUnitsnull77 function GetAllUnits: TStrings;
78 property Units: TStrings read FUnits write SetUnits;
79 property Code: TCodeBuffer read FCode write SetCode;
80 end;
81
82
ShowUnusedUnitsDialognull83 function ShowUnusedUnitsDialog: TModalResult;
ShowUnusedUnitsDialognull84 function ShowUnusedUnitsDialog(Code: TCodeBuffer): TModalResult;
85
86 implementation
87
88 {$R *.lfm}
89
ShowUnusedUnitsDialognull90 function ShowUnusedUnitsDialog: TModalResult;
91 var
92 SrcEdit: TSourceEditorInterface;
93 Code: TCodeBuffer;
94 begin
95 // get cursor position
96 Result:=mrAbort;
97 SrcEdit:=SourceEditorManagerIntf.ActiveEditor;
98 if SrcEdit=nil then exit;
99 Code:=TCodeBuffer(SrcEdit.CodeToolsBuffer);
100 if Code=nil then exit;
101 Result:=ShowUnusedUnitsDialog(Code);
102 end;
103
ShowUnusedUnitsDialognull104 function ShowUnusedUnitsDialog(Code: TCodeBuffer): TModalResult;
105 var
106 UnusedUnitsDialog: TUnusedUnitsDialog;
107 xUnits: TStringListUTF8Fast;
108 RemoveUnits: TStrings;
109 i: Integer;
110 DlgResult: TModalResult;
111 SrcEdit: TSourceEditorInterface;
112 begin
113 Result:=mrOk;
114 if Code=nil then exit;
115 if not LazarusIDE.BeginCodeTools then exit;
116
117 UnusedUnitsDialog:=nil;
118 RemoveUnits:=nil;
119 xUnits:=TStringListUTF8Fast.Create;
120 try
121 if not CodeToolBoss.FindUnusedUnits(Code,xUnits) then begin
122 DebugLn(['ShowUnusedUnitsDialog CodeToolBoss.FindUnusedUnits failed']);
123 LazarusIDE.DoJumpToCodeToolBossError;
124 exit(mrCancel);
125 end;
126 xUnits.Sort;
127
128 UnusedUnitsDialog:=TUnusedUnitsDialog.Create(nil);
129 UnusedUnitsDialog.Units:=xUnits;
130 UnusedUnitsDialog.Code:=Code;
131 DlgResult:=UnusedUnitsDialog.ShowModal;
132 if DlgResult=mrOk then
133 RemoveUnits:=UnusedUnitsDialog.GetSelectedUnits
134 else if DlgResult=mrAll then
135 RemoveUnits:=UnusedUnitsDialog.GetAllUnits
136 else
137 RemoveUnits:=nil;
138 if (RemoveUnits<>nil) and (RemoveUnits.Count>0) then begin
139 LazarusIDE.DoOpenEditorFile(Code.Filename,-1,-1,[]);
140 SrcEdit:=SourceEditorManagerIntf.SourceEditorIntfWithFilename(Code.Filename);
141 if SrcEdit=nil then begin
142 IDEMessageDialog(lisCCOErrorCaption,
143 Format(lisUnableToOpen, [Code.Filename]),
144 mtError,[mbCancel]);
145 exit(mrCancel);
146 end;
147
148 SrcEdit.BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('ShowUnusedUnitsDialog'){$ENDIF};
149 try
150 for i:=0 to RemoveUnits.Count-1 do begin
151 if not CodeToolBoss.RemoveUnitFromAllUsesSections(Code,RemoveUnits[i])
152 then begin
153 LazarusIDE.DoJumpToCodeToolBossError;
154 exit(mrCancel);
155 end;
156 end;
157 finally
158 SrcEdit.EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('ShowUnusedUnitsDialog'){$ENDIF};
159 end;
160 end;
161 finally
162 CodeToolBoss.SourceCache.ClearAllSourceLogEntries;
163 RemoveUnits.Free;
164 UnusedUnitsDialog.Free;
165 xUnits.Free;
166 end;
167 end;
168
169 { TUnusedUnitsDialog }
170
171 procedure TUnusedUnitsDialog.FormCreate(Sender: TObject);
172 begin
173 ShowInitializationCheckBox.Caption:=lisShowUnitsWithInitialization;
174 ShowInitializationCheckBox.Hint:=lisShowUnitsWithInitializationHint;
175 RemoveSelectedBitBtn.Caption:=lisRemoveSelectedUnits;
176 RemoveAllBitBtn.Caption:=lisRemoveAllUnits;
177 CancelBitBtn.Caption:=lisCancel;
178
179 UnitsTreeView.StateImages := IDEImages.Images_16;
180 ImgIDInterface := IDEImages.LoadImage('ce_interface');
181 ImgIDImplementation := IDEImages.LoadImage('ce_implementation');
182 ImgIDInitialization := IDEImages.LoadImage('ce_initialization');
183 ImgIDNone := IDEImages.LoadImage('ce_default');
184 end;
185
186 procedure TUnusedUnitsDialog.RemoveAllBitBtnClick(Sender: TObject);
187 begin
188 ModalResult:=mrAll;
189 end;
190
191 procedure TUnusedUnitsDialog.CancelBitBtnClick(Sender: TObject);
192 begin
193 ModalResult:=mrCancel;
194 end;
195
196 procedure TUnusedUnitsDialog.RemoveSelectedBitBtnClick(Sender: TObject);
197 begin
198 ModalResult:=mrOk;
199 end;
200
201 procedure TUnusedUnitsDialog.ShowInitializationCheckBoxClick(Sender: TObject);
202 begin
203 RebuildUnitsTreeView;
204 end;
205
206 procedure TUnusedUnitsDialog.UnitsTreeViewSelectionChanged(Sender: TObject);
207 begin
208 UpdateButtons;
209 end;
210
211 procedure TUnusedUnitsDialog.SetUnits(const AValue: TStrings);
212 begin
213 if FUnits=AValue then exit;
214 FUnits:=AValue;
215 RebuildUnitsTreeView;
216 end;
217
218 procedure TUnusedUnitsDialog.SetCode(AValue: TCodeBuffer);
219 begin
220 if FCode=AValue then Exit;
221 FCode:=AValue;
222 if FCode<>nil then
223 Caption:=Format(lisUnusedUnitsOf, [ExtractFilename(Code.Filename)]);
224 end;
225
226 procedure TUnusedUnitsDialog.RebuildUnitsTreeView;
227 var
228 i: Integer;
229 AUnitname: string;
230 Flags: string;
231 UseInterface: Boolean;
232 InImplUsesSection: Boolean;
233 UseCode, HideCode: Boolean;
234 IntfTreeNode: TTreeNode;
235 ImplTreeNode: TTreeNode;
236 ParentNode: TTreeNode;
237 TVNode: TTreeNode;
238 begin
239 UnitsTreeView.BeginUpdate;
240 UnitsTreeView.Items.Clear;
241 IntfTreeNode:=UnitsTreeView.Items.Add(nil,'Interface');
242 IntfTreeNode.StateIndex:=ImgIDInterface;
243 ImplTreeNode:=UnitsTreeView.Items.Add(nil,'Implementation');
244 ImplTreeNode.StateIndex:=ImgIDImplementation;
245 if Units<>nil then
246 begin
247 for i:=0 to Units.Count-1 do
248 begin
249 AUnitname:=Units.Names[i];
250 Flags:=Units.ValueFromIndex[i];
251 InImplUsesSection:=System.Pos(',implementation',Flags)>0;
252 UseInterface:=System.Pos(',used',Flags)>0;
253 UseCode:=System.Pos(',code',Flags)>0;
254 HideCode:=not ShowInitializationCheckBox.Checked;
255 if not (UseInterface or (HideCode and UseCode)) then
256 begin
257 if InImplUsesSection then
258 ParentNode:=ImplTreeNode
259 else
260 ParentNode:=IntfTreeNode;
261 TVNode:=UnitsTreeView.Items.AddChild(ParentNode,AUnitname);
262 if UseCode then
263 TVNode.StateIndex:=ImgIDInitialization
264 else
265 TVNode.StateIndex:=ImgIDInterface;
266 end;
267 end;
268 end;
269 IntfTreeNode.Expanded:=true;
270 ImplTreeNode.Expanded:=true;
271 UnitsTreeView.EndUpdate;
272 UpdateButtons;
273 end;
274
275 procedure TUnusedUnitsDialog.UpdateButtons;
276 var
277 RemoveUnits: TStrings;
278 begin
279 RemoveUnits:=GetSelectedUnits;
280 RemoveSelectedBitBtn.Enabled:=RemoveUnits.Count>0;
281 RemoveAllBitBtn.Enabled:=Units.Count>0;
282 RemoveUnits.Free;
283 end;
284
TUnusedUnitsDialog.GetSelectedUnitsnull285 function TUnusedUnitsDialog.GetSelectedUnits: TStrings;
286 var
287 TVNode: TTreeNode;
288 begin
289 Result:=TStringList.Create;
290 TVNode:=UnitsTreeView.Items.GetFirstNode;
291 while TVNode<>nil do begin
292 if TVNode.MultiSelected and (TVNode.Level=1) then
293 Result.Add(TVNode.Text);
294 TVNode:=TVNode.GetNext;
295 end;
296 end;
297
GetAllUnitsnull298 function TUnusedUnitsDialog.GetAllUnits: TStrings;
299 var
300 TVNode: TTreeNode;
301 begin
302 Result:=TStringList.Create;
303 TVNode:=UnitsTreeView.Items.GetFirstNode;
304 while TVNode<>nil do begin
305 if (TVNode.Level=1) then
306 Result.Add(TVNode.Text);
307 TVNode:=TVNode.GetNext;
308 end;
309 end;
310
311 end.
312
313