Menu

[r172]: / trunk / Src / FmDependenciesDlg.pas  Maximize  Restore  History

Download this file

365 lines (332 with data), 12.0 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
{
* FmDependenciesDlg.pas
*
* Implements a dialog box that recursively displays all the dependencies of a
* snippet.
*
* v1.0 of 06 Jun 2009 - Original version.
* v1.1 of 10 Jul 2009 - Changed so that "no snippets" and "circular reference"
* message labels recognise default OS font.
* - Revised control alignment code to allow for height of
* text in "circular reference" label.
*
*
* ***** BEGIN LICENSE BLOCK *****
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is FmDependenciesDlg.pas
*
* The Initial Developer of the Original Code is Peter Johnson
* (http://www.delphidabbler.com/).
*
* Portions created by the Initial Developer are Copyright (C) 2009 Peter
* Johnson. All Rights Reserved.
*
* ***** END LICENSE BLOCK *****
}
unit FmDependenciesDlg;
{$WARN UNSAFE_CAST OFF}
interface
uses
// Delphi
ComCtrls, StdCtrls, Controls, ExtCtrls, Classes,
// Project
FmGenericViewDlg, USnippetIDs, USnippets, USnippetsTVDraw;
type
{
TDependenciesDlg:
Dialog box that displays all the dependencies of a snippet in a tree view.
}
TDependenciesDlg = class(TGenericViewDlg)
tvDependencies: TTreeView;
lblCircularRef: TLabel;
lblNoDependencies: TLabel;
procedure FormDestroy(Sender: TObject);
procedure tvDependenciesCollapsing(Sender: TObject; Node: TTreeNode;
var AllowCollapse: Boolean);
strict private
type
{
TTVDraw:
Object used to draw snippets tree view nodes.
}
TTVDraw = class(TSnippetsTVDraw)
strict private
fRootID: TSnippetID; // ID of snippet whose dependency nodes displayed
strict protected
function IsUserDefinedNode(const Node: TTreeNode): Boolean;
override;
{Checks if a node represents a user defined snippets object.
@param Node [in] Node to be checked.
@return True if node represents user defined object, False if not.
}
function IsErrorNode(const Node: TTreeNode): Boolean;
override;
{Checks if a node represents an error condition.
@param Node [in] Node to be checked.
@return True if node represents error condition, False if not.
}
public
constructor Create(const RootID: TSnippetID);
{Class constructor. Sets up object.
@param ID [in] ID snippet for which dependencies are displayed.
}
end;
var
fSnippetID: TSnippetID; // Snippet whose dependencies are displayed
fDependsList: TRoutineList; // List of dependencies to be displayed
fTVDraw: TTVDraw; // Customises appearance of tree view}
procedure PopulateTreeView;
{Populates treeview with nodes for each snippet in dependency list.
}
procedure AddDependencies(const Parent: TTreeNode;
const DependsList: TRoutineList);
{Adds tree nodes for snippets in a dependency list.
@param Parent [in] Parent node for nodes from dependency list.
@param DependsList [in] Dependency list containing snippets to be added
to treeview.
}
procedure DisplayCircularRefWarning;
{Displays circular reference warning label.
}
function GetDisplayName: string;
{Gets display name for snippet for which dependencies are being displayed.
@return Required display name: snippet's name if available, otherwise an
untitled string.
}
strict protected
procedure ConfigForm; override;
{Configure controls on form.
}
procedure ArrangeForm; override;
{Arranges controls on form.
}
procedure InitForm; override;
{Initialises form by placing focus on close button rather than treeview.
}
public
class procedure Execute(const AOwner: TComponent;
const SnippetID: TSnippetID; const DependsList: TRoutineList); overload;
{Displays dialog box containing details of a snippet's dependencies.
@param AOwner [in] Component that owns the dialog box.
@param SnippetID [in] ID of snippet for which dependencies are to be
displayed.
}
class procedure Execute(const AOwner: TComponent; const Snippet: TRoutine);
overload;
{Displays dialog box containing details of a snippet's dependencies.
@param AOwner [in] Component that owns the dialog box.
@param Snippet [in] Snippet for which dependencies are to be displayed.
}
end;
implementation
uses
// Delphi
SysUtils, Graphics,
// Project
UColours, UFontHelper, USnippetKindInfo, FmGenericDlg;
{$R *.dfm}
{ TDependenciesDlg }
procedure TDependenciesDlg.AddDependencies(const Parent: TTreeNode;
const DependsList: TRoutineList);
{Adds tree nodes for snippets in a dependency list.
@param Parent [in] Parent node for nodes from dependency list.
@param DependsList [in] Dependency list containing snippets to be added to
treeview.
}
var
RequiredSnippet: TRoutine; // iterates through snippets in DependsList
ChildNode: TTreeNode; // a node added to treeview
begin
for RequiredSnippet in DependsList do
begin
// Add node for snippet from dependency list
ChildNode := tvDependencies.Items.AddChild(
Parent,
RequiredSnippet.Name
+ ' ('
+ TSnippetKindInfoList.Instance[RequiredSnippet.Kind].Description
+ ')'
);
ChildNode.Data := RequiredSnippet; // reference to associated snippet
// Check for circular reference. If detetected display warning otherwise
// recursively add child nodes for snippet's dependency list
if (RequiredSnippet.ID <> fSnippetID) then
AddDependencies(ChildNode, RequiredSnippet.Depends)
else
DisplayCircularRefWarning;
end;
end;
procedure TDependenciesDlg.ArrangeForm;
{Arranges controls on form.
}
begin
inherited;
// Position "no dependencies" message label in form
lblNoDependencies.Left :=
(pnlBody.ClientWidth - lblNoDependencies.Width) div 2;
lblNoDependencies.Top :=
(pnlBody.ClientHeight - lblNoDependencies.Height) div 2;
// Adjust size of treeview
if lblCircularRef.Visible then
begin
// move label
lblCircularRef.Top := pnlBody.Top + pnlBody.ClientHeight
- lblCircularRef.Height - 8;
// circular reference: make room to see circular reference label
tvDependencies.Align := alTop;
tvDependencies.Height := lblCircularRef.Top - 6;
end
else
// no circular reference: use all space for treeview
tvDependencies.Align := alClient;
end;
procedure TDependenciesDlg.ConfigForm;
{Configure controls on form.
}
resourcestring
sNoDepends = '%s has no dependencies'; // message when no dependencies
sTitle = 'Dependencies for %s'; // form caption template
begin
inherited;
// Set form caption
Caption := Format(sTitle, [GetDisplayName]);
// Set "no dependencies" label in case needed and make bold
lblNoDependencies.Caption := Format(sNoDepends, [GetDisplayName]);
lblNoDependencies.Font.Style := [fsBold];
// Set "circular reference" label's colour and visibility
lblCircularRef.Font.Color := clWarningText;
lblCircularRef.Visible := False;
// Provide custom draw support for treeview
fTVDraw := TTVDraw.Create(fSnippetID);
tvDependencies.OnCustomDrawItem := fTVDraw.CustomDrawItem;
// Populate treeview with dependency information
PopulateTreeView;
// Hide treeview, revealing "no dependencies" label if no dependencies
if tvDependencies.Items.Count = 0 then
tvDependencies.Visible := False;
end;
procedure TDependenciesDlg.DisplayCircularRefWarning;
{Displays circular reference warning label.
}
begin
lblCircularRef.Visible := True;
end;
class procedure TDependenciesDlg.Execute(const AOwner: TComponent;
const Snippet: TRoutine);
{Displays dialog box containing details of a snippet's dependencies.
@param AOwner [in] Component that owns the dialog box.
@param Snippet [in] Snippet for which dependencies are to be displayed.
}
begin
Execute(AOwner, Snippet.ID, Snippet.Depends);
end;
class procedure TDependenciesDlg.Execute(const AOwner: TComponent;
const SnippetID: TSnippetID; const DependsList: TRoutineList);
{Displays dialog box containing details of a snippet's dependencies.
@param AOwner [in] Component that owns the dialog box.
@param SnippetIS [in] ID of snippet for which dependencies are to be
displayed.
}
begin
with Create(AOwner) do
try
fSnippetID := SnippetID;
fDependsList := DependsList;
ShowModal;
finally
Free;
end;
end;
procedure TDependenciesDlg.FormDestroy(Sender: TObject);
{Form destruction event handler. Frees owned object.
@param Sender [in] Not used.
}
begin
inherited;
FreeAndNil(fTVDraw);
end;
function TDependenciesDlg.GetDisplayName: string;
{Gets display name for snippet for which dependencies are being displayed.
@return Required display name: snippet's name if available, otherwise an
untitled string.
}
resourcestring
sUntitled = '<Untitled Snippet>'; // display name when snippet has no name
begin
Result := fSnippetID.Name;
if Result = '' then
Result := sUntitled;
end;
procedure TDependenciesDlg.InitForm;
{Initialises form by placing focus on close button rather than treeview.
}
begin
inherited;
btnClose.SetFocus;
end;
procedure TDependenciesDlg.PopulateTreeView;
{Populates treeview with nodes for each snippet in dependency list.
}
begin
tvDependencies.Items.BeginUpdate;
try
tvDependencies.Items.Clear;
AddDependencies(nil, fDependsList);
tvDependencies.FullExpand;
finally
tvDependencies.Items.EndUpdate;
end;
end;
procedure TDependenciesDlg.tvDependenciesCollapsing(Sender: TObject;
Node: TTreeNode; var AllowCollapse: Boolean);
{Handles event triggered when tree view wants to collapse. We don't allow
this.
@param Sender [in] Not used.
@param Node [in] Not used.
@param AllowChange [in/out] Set false to prevent tree view collapsing.
}
begin
AllowCollapse := False;
end;
{ TDependenciesDlg.TTVDraw }
constructor TDependenciesDlg.TTVDraw.Create(
const RootID: TSnippetID);
{Class constructor. Sets up object.
@param ID [in] ID snippet for which dependencies are displayed.
}
begin
inherited Create;
fRootID := RootID;
end;
function TDependenciesDlg.TTVDraw.IsErrorNode(
const Node: TTreeNode): Boolean;
{Checks if a node represents an error condition.
@param Node [in] Node to be checked.
@return True if node represents error condition, False if not.
}
begin
Result := Assigned(Node.Data) and (TRoutine(Node.Data).ID = fRootID);
end;
function TDependenciesDlg.TTVDraw.IsUserDefinedNode(
const Node: TTreeNode): Boolean;
{Checks if a node represents a user defined snippets object.
@param Node [in] Node to be checked.
@return True if node represents user defined object, False if not.
}
begin
if not Assigned(Node.Data) then
Result := True
else
Result := TRoutine(Node.Data).UserDefined;
end;
end.
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.