Menu

[r107]: / trunk / Src / UOverviewTreeBuilder.pas  Maximize  Restore  History

Download this file

341 lines (306 with data), 11.7 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
{
* UOverviewTreeBuilder.pas
*
* Implements a set of classes that populate the overview treeview with a list
* of snippets. Each class groups the snippets in different ways.
*
* v1.0 of 27 Jun 2009 - Original version.
*
*
* ***** 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 UOverviewTreeBuilder.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 UOverviewTreeBuilder;
interface
uses
// Delphu
ComCtrls,
// Project
USnippets, UView, UViewItemTreeNode;
type
{
TOverviewTreeBuilder:
Abstract base class for classes that populate the overview treeview with a
list of snippets. Each subclass groups the snippets in different ways.
}
TOverviewTreeBuilder = class abstract(TObject)
strict private
fTreeView: TTreeView; // Value of TreeView property
fSnippetList: TRoutineList; // Value of SnippetList property
strict protected
property TreeView: TTreeView read fTreeView;
{Reference to treeview populated by class}
property SnippetList: TRoutineList read fSnippetList;
{List of snippets to be displayed in treeview}
function AddViewItemNode(const ParentNode: TViewItemTreeNode;
const ViewItem: TViewItem): TViewItemTreeNode;
{Adds a new node to the tree view that represents a view item.
@param ParentNode [in] Node that is parent of new node.
@param ViewItem [in] View item for which we are adding node.
@return New tree node.
}
public
constructor Create(const TV: TTreeView; const SnippetList: TRoutineList);
{Class constructor. Sets up object to populate a treeview with a list of
snippets.
@param TV [in] Treeview control to be populated.
@param SnippetList [in] List of snippets to be added to TV.
}
procedure Build; virtual; abstract;
{Abstract method that descendants overrride to populate the treeview.
}
end;
{
TOverviewTreeBuilderClass:
Class reference for TOverviewTreeBuilder sub-classes.
}
TOverviewTreeBuilderClass = class of TOverviewTreeBuilder;
{
TOverviewCategorisedTreeBuilder:
Class that populates the overview treeview with a list of snippets grouped
by category.
}
TOverviewCategorisedTreeBuilder = class sealed(TOverviewTreeBuilder)
public
procedure Build; override;
{Populates treeview with snippets grouped by category.
}
end;
{
TOverviewAlphabeticTreeBuilder:
Class that populates the overview treeview with a list of snippets grouped
by initial letter of the snippet name.
}
TOverviewAlphabeticTreeBuilder = class sealed(TOverviewTreeBuilder)
public
procedure Build; override;
{Populates treeview with snippets grouped by initial letter of snippet
name.
}
end;
{
TOverviewSnipKindTreeBuilder:
Class that populates the overview treeview with a list of snippets grouped
by snippet kind.
}
TOverviewSnipKindTreeBuilder = class sealed(TOverviewTreeBuilder)
public
procedure Build; override;
{Populates treeview with snippets grouped by snippet kind.
}
end;
implementation
{
NOTE:
Early version of this code, that were contained in the FrOverview unit used
to add a section head tree node for every category and then delete empty ones.
However, attempts to delete the first node from a tree causes an endless loop,
freezing the program. This could be a bug in the Delphi treeview component.
Therefore the code in this unit now builds or uses a list of routines in for
each section and does not create a section header node for sections that
contain no routines.
}
uses
// Delphi
SysUtils, Classes,
// Project
UAlphabet, ULists, USnippetKindInfo;
{ TOverviewTreeBuilder }
function TOverviewTreeBuilder.AddViewItemNode(
const ParentNode: TViewItemTreeNode;
const ViewItem: TViewItem): TViewItemTreeNode;
{Adds a new node to the tree view that represents a view item.
@param ParentNode [in] Node that is parent of new node.
@param ViewItem [in] View item for which we are adding node.
@return New tree node.
}
begin
Result := TreeView.Items.AddChild(ParentNode, ViewItem.Description)
as TViewItemTreeNode;
Result.ViewItem := ViewItem;
end;
constructor TOverviewTreeBuilder.Create(const TV: TTreeView;
const SnippetList: TRoutineList);
{Class constructor. Sets up object to populate a treeview with a list of
snippets.
@param TV [in] Treeview control to be populated.
@param SnippetList [in] List of snippets to be added to TV.
}
begin
inherited Create;
fTreeView := TV;
fSnippetList := SnippetList;
end;
{ TOverviewCategorisedTreeBuilder }
procedure TOverviewCategorisedTreeBuilder.Build;
{Populates treeview with snippets grouped by category.
}
var
CatNode: TViewItemTreeNode; // reference to a category section node
Cat: TCategory; // each category in database
Snippet: TRoutine; // each snippet in a category
Sections: TStringList; // maps category to list of snippets in it
CatDescs: TStringList; // alphabetical list of category descriptions
CatDescIdx: Integer; // loops thru category description list
SectionIdx: Integer; // index of a category in Sections
begin
// Create string list that maps categories onto snippets
CatDescs := nil;
Sections := TStringList.Create;
try
Sections.Sorted := True;
CatDescs := TStringList.Create;
CatDescs.Sorted := True;
// Create required lists: 1) Sections maps categories to routine lists and
// 2) CatDescs maintains alphabetical list of section names
for Cat in Snippets.Categories do
begin
Sections.AddObject(Cat.Category, TRoutineList.Create);
CatDescs.AddObject(Cat.Description, Cat);
end;
// Add all snippets into correct category list
for Snippet in SnippetList do
begin
SectionIdx := Sections.IndexOf(Snippet.Category);
if SectionIdx >= 0 then
(Sections.Objects[SectionIdx] as TRoutineList).Add(Snippet);
end;
// Create tree
for CatDescIdx := 0 to Pred(CatDescs.Count) do
begin
Cat := CatDescs.Objects[CatDescIdx] as TCategory;
SectionIdx := Sections.IndexOf(Cat.Category);
Assert(SectionIdx >= 0,
ClassName + '.Build: Category not in section list');
if (Sections.Objects[SectionIdx] as TRoutineList).Count > 0 then
begin
CatNode := AddViewItemNode(nil, TViewItem.Create(vkCategory, Cat));
for Snippet in (Sections.Objects[SectionIdx] as TRoutineList) do
AddViewItemNode(CatNode, TViewItem.Create(Snippet));
end;
end;
finally
FreeAndNil(CatDescs);
// Free section list and contained snippet lists
for SectionIdx := Pred(Sections.Count) downto 0 do
Sections.Objects[SectionIdx].Free;
FreeAndNil(Sections);
end;
end;
{ TOverviewAlphabeticTreeBuilder }
procedure TOverviewAlphabeticTreeBuilder.Build;
{Populates treeview with snippets grouped by initial letter of snippet name.
}
function FirstCharOfName(const Name: string): Char;
{Gets the first character of a name.
@param Name [in] Name for which first character required.
@return Required character in upper case.
}
begin
Assert(Name <> '', ClassName + '.Build:FirstCharOfName: Name is empty');
Result := UpCase(Name[1]);
Assert(Result in ['_', 'A'..'Z'],
ClassName +
'.Build:FirstCharOfName: Name must begin with A..Z or underscore');
end;
var
Snippet: TRoutine; // each snippet in a list
Sections: TIntegerList; // alphabetic (+ underscore) sections
SectionSnippets: TRoutineList; // snippets in in section
LetterObj: TLetter; // references each letter object
Idx: Integer; // loops through all letters in Sections list
ParentNode: TViewItemTreeNode; // each section node in tree
begin
Sections := TIntegerList.Create;
try
// Create a snippet list for each letter
TAlphabet.Instance.InitEnum;
while TAlphabet.Instance.NextLetter(LetterObj) do
Sections.Add(Ord(LetterObj.Letter), TRoutineList.Create);
// populate section snippet list depending on snippet's initial letter
for Snippet in SnippetList do
begin
SectionSnippets := Sections.FindObject(
Ord(FirstCharOfName(Snippet.Name))
) as TRoutineList;
if Assigned(SectionSnippets) then
SectionSnippets.Add(Snippet);
end;
// Create tree nodes only section contains snippets
TAlphabet.Instance.InitEnum;
while TAlphabet.Instance.NextLetter(LetterObj) do
begin
SectionSnippets := Sections.FindObject(Ord(LetterObj.Letter))
as TRoutineList;
if Assigned(SectionSnippets) and (SectionSnippets.Count > 0) then
begin
ParentNode := AddViewItemNode(nil, TViewItem.Create(LetterObj));
for Snippet in SectionSnippets do
AddViewItemNode(ParentNode, TViewItem.Create(Snippet));
end;
end;
finally
// Free all sections and owned snippet lists
for Idx := 0 to Pred(Sections.Count) do
Sections.Objects[Idx].Free;
FreeAndNil(Sections);
end;
end;
{ TOverviewSnipKindTreeBuilder }
procedure TOverviewSnipKindTreeBuilder.Build;
{Populates treeview with snippets grouped by snippet kind.
}
var
Snippet: TRoutine; // each snippet in a snippets list
Kind: TSnippetKind; // each snippet kind
ParentNode: TViewItemTreeNode; // tree node for each snippet kind
Sections: array[TSnippetKind] // snippets associated with each kind
of TRoutineList;
begin
// Create snippet lists for each snippet kind
for Kind := Low(TSnippetKind) to High(TSnippetKind) do
Sections[Kind] := nil; // make safe in case exception occurs below
try
for Kind := Low(TSnippetKind) to High(TSnippetKind) do
Sections[Kind] := TRoutineList.Create;
// Allocate each snippet to appropriate snippet kind list
for Snippet in SnippetList do
Sections[Snippet.Kind].Add(Snippet);
// Create tree nodes only if section contains snippets
for Kind := Low(TSnippetKind) to High(TSnippetKind) do
begin
if Sections[Kind].Count > 0 then
begin
ParentNode := AddViewItemNode(
nil, TViewItem.Create(TSnippetKindInfoList.Instance[Kind])
);
for Snippet in Sections[Kind] do
AddViewItemNode(ParentNode, TViewItem.Create(Snippet));
end;
end;
finally
// Free each snippet list
for Kind := Low(TSnippetKind) to High(TSnippetKind) do
Sections[Kind].Free;
end;
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.