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 Dialog used by the fpdoc editor to create a link.
25 }
26 unit FPDocSelectLink;
27
28 {$mode objfpc}{$H+}
29
30 interface
31
32 uses
33 Classes, SysUtils, Laz_AVL_Tree,
34 // LCL
35 LCLProc, LCLType, Forms, Controls, Graphics, ExtCtrls, StdCtrls, ButtonPanel,
36 // LazUtils
37 FileUtil, LazFileUtils, Laz2_DOM,
38 // IdeIntf
39 PackageIntf, ProjectIntf,
40 // IDE
41 CodeHelp, LazarusIDEStrConsts, PackageSystem, PackageDefs;
42
43 type
44
45 { TFPDocLinkCompletionItem }
46
47 TFPDocLinkCompletionItem = class
48 public
49 Text: string;
50 Description: string;
51 constructor Create(const AText, ADescription: string);
52 end;
53
54 { TFPDocLinkCompletionList }
55
56 TFPDocLinkCompletionList = class
57 private
58 FBGColor: TColor;
59 FItemHeight: integer;
60 FItems: TFPList; // list of TFPDocLinkCompletionItem
61 FPrefix: string;
62 FSelected: integer;
63 FSelectedBGColor: TColor;
64 FSelectedTextColor: TColor;
65 FSorted: Boolean;
66 FTextColor: TColor;
67 FTop: integer;
68 FVisibleItems: integer;
69 FTree: TAvlTree; // tree of TFPDocLinkCompletionItem
GetCountnull70 function GetCount: integer;
GetItemsnull71 function GetItems(Index: integer): TFPDocLinkCompletionItem;
72 procedure SetSorted(const AValue: Boolean);
73 procedure SetTop(const AValue: integer);
74 public
75 constructor Create;
76 destructor Destroy; override;
77 procedure Clear;
78 procedure Sort;
79 procedure AddPackage(Pkg: TLazPackage);
80 procedure Add(Identifier, Description: string);
81 procedure AddIdentifier(Identifier: string);
82 procedure Draw(Canvas: TCanvas; Width, Height: integer);
83 property Count: integer read GetCount;
84 property Sorted: Boolean read FSorted write SetSorted;
85 property Items[Index: integer]: TFPDocLinkCompletionItem read GetItems;
86 property ItemHeight: integer read FItemHeight write FItemHeight;// pixel per item
87 property VisibleItems: integer read FVisibleItems write FVisibleItems;// visible lines
88 property Top: integer read FTop write SetTop;
89 property Selected: integer read FSelected write FSelected;
90 property Prefix: string read FPrefix write FPrefix;
91 property BGColor: TColor read FBGColor write FBGColor;
92 property TextColor: TColor read FTextColor write FTextColor;
93 property SelectedBGColor: TColor read FSelectedBGColor write FSelectedBGColor;
94 property SelectedTextColor: TColor read FSelectedTextColor write FSelectedTextColor;
95 end;
96
97 { TFPDocLinkEditorDlg }
98
99 TFPDocLinkEditorDlg = class(TForm)
100 ButtonPanel1: TButtonPanel;
101 CompletionBox: TPaintBox;
102 TitleEdit: TEdit;
103 TitleLabel: TLabel;
104 LinkEdit: TEdit;
105 LinkLabel: TLabel;
106 procedure CompletionBoxMouseDown(Sender: TObject; {%H-}Button: TMouseButton;
107 {%H-}Shift: TShiftState; {%H-}X, Y: Integer);
108 procedure CompletionBoxPaint(Sender: TObject);
109 procedure FormCreate(Sender: TObject);
110 procedure FormDestroy(Sender: TObject);
111 procedure LinkEditChange(Sender: TObject);
112 procedure LinkEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
113 private
114 FStartFPDocFile: TLazFPDocFile;
115 fItems: TFPDocLinkCompletionList;
116 FSourceFilename: string;
117 FStartModuleOwner: TObject;
118 fUpdatingItems: boolean;
GetLinknull119 function GetLink: string;
GetLinkTitlenull120 function GetLinkTitle: string;
121 procedure SetStartFPDocFile(const AValue: TLazFPDocFile);
122 procedure SetLink(const AValue: string);
123 procedure SetLinkTitle(const AValue: string);
124 procedure SetSourceFilename(const AValue: string);
125 procedure SetStartModuleOwner(const AValue: TObject);
126 procedure UpdateCompletionBox;
127 procedure AddPackagesToCompletion(Prefix: string);
128 procedure AddModuleUnits(ModuleOwner: TObject; Prefix: string);
129 procedure AddProjectUnits(AProject: TLazProject; Prefix: string);
130 procedure AddPackageUnits(APackage: TLazPackage; Prefix: string);
131 procedure AddIdentifiers(ModuleOwner: TObject; FPDocFile: TLazFPDocFile;
132 Prefix: string);
133 procedure AddSubIdentifiers(Path: string);
134 public
135 procedure SetLinkAndContext(const ASrcFilename, ATitle, ALink: string;
136 ADocFile: TLazFPDocFile);
137 property SourceFilename: string read FSourceFilename write SetSourceFilename;
138 property LinkTitle: string read GetLinkTitle write SetLinkTitle;
139 property Link: string read GetLink write SetLink;
140 property StartFPDocFile: TLazFPDocFile read FStartFPDocFile write SetStartFPDocFile;
141 property StartModuleOwner: TObject read FStartModuleOwner write SetStartModuleOwner;
142 end;
143
ShowFPDocLinkEditorDialognull144 function ShowFPDocLinkEditorDialog(SrcFilename: string;
145 StartFPDocFile: TLazFPDocFile; out Link, LinkTitle: string): TModalResult;
146
CompareFPDocLinkCompletionItemnull147 function CompareFPDocLinkCompletionItem(Data1, Data2: Pointer): integer;
ComparePathWithFPDocLinkCompletionItemnull148 function ComparePathWithFPDocLinkCompletionItem(AnsiString1, Data2: Pointer): integer;
149
150 implementation
151
152 {$R *.lfm}
153
ShowFPDocLinkEditorDialognull154 function ShowFPDocLinkEditorDialog(SrcFilename: string;
155 StartFPDocFile: TLazFPDocFile; out Link, LinkTitle: string): TModalResult;
156 var
157 FPDocLinkEditorDlg: TFPDocLinkEditorDlg;
158 begin
159 Link:='';
160 LinkTitle:='';
161 FPDocLinkEditorDlg:=TFPDocLinkEditorDlg.Create(nil);
162 try
163 FPDocLinkEditorDlg.SetLinkAndContext(SrcFilename,LinkTitle,Link,StartFPDocFile);
164 Result:=FPDocLinkEditorDlg.ShowModal;
165 if Result=mrOk then begin
166 Link:=FPDocLinkEditorDlg.Link;
167 LinkTitle:=FPDocLinkEditorDlg.LinkTitle;
168 end;
169 finally
170 FPDocLinkEditorDlg.Release;
171 end;
172 end;
173
CompareFPDocLinkCompletionItemnull174 function CompareFPDocLinkCompletionItem(Data1, Data2: Pointer): integer;
175 var
176 Item1: TFPDocLinkCompletionItem absolute Data1;
177 Item2: TFPDocLinkCompletionItem absolute Data2;
178 begin
179 Result:=SysUtils.CompareText(Item1.Text,Item2.Text);
180 end;
181
ComparePathWithFPDocLinkCompletionItemnull182 function ComparePathWithFPDocLinkCompletionItem(AnsiString1, Data2: Pointer
183 ): integer;
184 var
185 s: String;
186 Item: TFPDocLinkCompletionItem absolute Data2;
187 begin
188 s:=AnsiString(AnsiString1);
189 Result:=SysUtils.CompareText(s,Item.Text);
190 end;
191
192 { TFPDocLinkEditorDlg }
193
194 procedure TFPDocLinkEditorDlg.FormCreate(Sender: TObject);
195 begin
196 Caption:=lisChooseAFPDocLink;
197 LinkLabel.Caption:=lisLinkTarget;
198 LinkLabel.Hint:=Format(lisExamplesIdentifierTMyEnumEnumUnitnameIdentifierPac,
199 [LineEnding, LineEnding, LineEnding, LineEnding]);
200 TitleLabel.Caption:=lisTitleLeaveEmptyForDefault;
201
202 LinkEdit.Text:='';
203 TitleEdit.Text:='';
204
205 // disable return key
206 ButtonPanel1.OKButton.Default:=false;
207
208 FItems:=TFPDocLinkCompletionList.Create;
209
210 ActiveControl:=LinkEdit;
211 end;
212
213 procedure TFPDocLinkEditorDlg.FormDestroy(Sender: TObject);
214 begin
215 FreeAndNil(fItems);
216 end;
217
218 procedure TFPDocLinkEditorDlg.CompletionBoxPaint(Sender: TObject);
219 begin
220 fItems.BGColor:=clWindow;
221 fItems.TextColor:=clWindowText;
222 fItems.SelectedBGColor:=clHighlight;
223 fItems.SelectedTextColor:=clHighlightText;
224 fItems.ItemHeight:=CompletionBox.Canvas.TextHeight('ABCTWSMgqp')+4;
225 fItems.VisibleItems:=CompletionBox.ClientHeight div fItems.ItemHeight;
226 fItems.Draw(CompletionBox.Canvas,
227 CompletionBox.ClientWidth,CompletionBox.ClientHeight);
228 end;
229
230 procedure TFPDocLinkEditorDlg.CompletionBoxMouseDown(Sender: TObject;
231 Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
232 var
233 Line: Integer;
234 begin
235 if fItems.ItemHeight<=0 then exit;
236 Line:=fItems.Top+(Y div fItems.ItemHeight);
237 if Line>=fItems.Count then exit;
238 Link:=FItems.Items[Line].Text;
239 LinkEdit.SelStart:=length(LinkEdit.Text);
240 end;
241
242 procedure TFPDocLinkEditorDlg.LinkEditChange(Sender: TObject);
243 begin
244 //DebugLn(['TFPDocLinkEditorDlg.LinkEditChange "',LinkEdit.Text,'"']);
245 Link:=LinkEdit.Text;
246 end;
247
248 procedure TFPDocLinkEditorDlg.LinkEditKeyDown(Sender: TObject; var Key: Word;
249 Shift: TShiftState);
250 var
251 Handled: Boolean;
252 begin
253 if Shift=[] then begin
254 Handled:=true;
255 case Key of
256 VK_UP:
257 if FItems.Selected>0 then begin
258 FItems.Selected:=FItems.Selected-1;
259 if FItems.Top>fItems.Selected then
260 FItems.Top:=fItems.Selected;
261 CompletionBox.Invalidate;
262 end;
263 VK_DOWN:
264 if FItems.Selected<fItems.Count-1 then begin
265 FItems.Selected:=FItems.Selected+1;
266 if FItems.Selected>=fItems.Top+fItems.VisibleItems then
267 FItems.Top:=FItems.Top+1;
268 CompletionBox.Invalidate;
269 end;
270 VK_RETURN:
271 if (FItems.Selected>=0) and (FItems.Selected<fItems.Count) then begin
272 Link:=FItems.Items[fItems.Selected].Text;
273 LinkEdit.SelStart:=length(LinkEdit.Text);
274 end;
275 else
276 Handled:=false;
277 end;
278 if Handled then Key:=VK_UNKNOWN;
279 end;
280 end;
281
282 procedure TFPDocLinkEditorDlg.SetSourceFilename(const AValue: string);
283 var
284 Owners: TFPList;
285 i: Integer;
286 begin
287 if FSourceFilename=AValue then exit;
288 FSourceFilename:=AValue;
289 FStartModuleOwner:=nil;
290 Owners:=PackageEditingInterface.GetPossibleOwnersOfUnit(FSourceFilename,
291 [piosfIncludeSourceDirectories]);
292 if Owners=nil then exit;
293 try
294 for i:=0 to Owners.Count-1 do begin
295 if TObject(Owners[i]) is TLazProject then begin
296 FStartModuleOwner:=TLazProject(Owners[i]);
297 end else if TObject(Owners[i]) is TLazPackage then begin
298 if FStartModuleOwner=nil then
299 FStartModuleOwner:=TLazPackage(Owners[i]);
300 end;
301 end;
302 finally
303 Owners.Free;
304 end;
305 end;
306
307 procedure TFPDocLinkEditorDlg.SetStartModuleOwner(const AValue: TObject);
308 begin
309 if FStartModuleOwner=AValue then exit;
310 FStartModuleOwner:=AValue;
311 end;
312
313 procedure TFPDocLinkEditorDlg.UpdateCompletionBox;
314 {
315 ToDo:
316 empty : show all packages, all units of current project/package and all identifiers of unit
317 #l : show all packages beginning with the letter l
318 #lcl. : show all units of package lcl
319 f : show all units and all identifiers beginning with the letter f
320 forms. : show all identifiers of unit forms and all sub identifiers of identifier forms
321
322 forms.tcontrol. : show all sub identifiers of identifier tcontrol
323 #lcl.forms. : same as above
324 #lcl.forms.tcontrol. : same as above
325 }
326 var
327 l: String;
328 begin
329 if FItems=nil then exit;
330 if fUpdatingItems then exit;
331 fUpdatingItems:=true;
332 try
333 fItems.Clear;
334 l:=FItems.Prefix;
335 //DebugLn(['TFPDocLinkEditorDlg.UpdateCompletionBox Prefix="',l,'"']);
336 AddSubIdentifiers(l);
337 CompletionBox.Invalidate;
338 finally
339 fUpdatingItems:=false;
340 end;
341 end;
342
343 procedure TFPDocLinkEditorDlg.AddPackagesToCompletion(Prefix: string);
344 var
345 i: Integer;
346 Pkg: TLazPackage;
347 begin
348 for i:=0 to PackageGraph.Count-1 do begin
349 Pkg:=PackageGraph.Packages[i];
350 if Pkg.FPDocPaths='' then continue;
351 if (SysUtils.CompareText(Prefix,copy(Pkg.Name,1,length(Prefix)))=0) then
352 fItems.AddPackage(Pkg);
353 end;
354 end;
355
356 procedure TFPDocLinkEditorDlg.AddModuleUnits(ModuleOwner: TObject;
357 Prefix: string);
358 var
359 AProject: TLazProject;
360 APackage: TLazPackage;
361 begin
362 DebugLn(['TFPDocLinkEditorDlg.AddModuleUnits ',DbgSName(ModuleOwner)]);
363 if ModuleOwner=nil then exit;
364 if ModuleOwner is TLazProject then begin
365 AProject:=TLazProject(ModuleOwner);
366 AddProjectUnits(AProject,Prefix);
367 end else if ModuleOwner is TLazPackage then begin
368 APackage:=TLazPackage(ModuleOwner);
369 AddPackageUnits(APackage,Prefix);
370 end;
371 end;
372
373 procedure TFPDocLinkEditorDlg.AddProjectUnits(AProject: TLazProject;
374 Prefix: string);
375 var
376 i: Integer;
377 Filename: String;
378 ProjFile: TLazProjectFile;
379 Identifier: String;
380 begin
381 DebugLn(['TFPDocLinkEditorDlg.AddProjectUnits ']);
382 for i:=0 to AProject.FileCount-1 do begin
383 ProjFile:=AProject.Files[i];
384 if ProjFile.IsPartOfProject then begin
385 Filename:=ProjFile.Filename;
386 if FilenameIsPascalUnit(Filename) then begin
387 Filename:=ExtractFileNameOnly(Filename);
388 DebugLn(['TFPDocLinkEditorDlg.AddProjectUnits ',Prefix,' ',Filename]);
389 if (CompareFilenames(Prefix,copy(Filename,1,length(Prefix)))=0) then
390 begin
391 Identifier:=ExtractFileNameOnly(ProjFile.Filename);
392 if AProject<>StartModuleOwner then
393 Identifier:='#'+ExtractFileNameOnly(AProject.ProjectInfoFile)+'.'+Identifier;
394 fItems.Add(Identifier, lisProjectUnit);
395 end;
396 end;
397 end;
398 end;
399 end;
400
401 procedure TFPDocLinkEditorDlg.AddPackageUnits(APackage: TLazPackage;
402 Prefix: string);
403 var
404 i: Integer;
405 PkgFile: TPkgFile;
406 Filename: String;
407 Identifier: String;
408 begin
409 for i:=0 to APackage.FileCount-1 do begin
410 PkgFile:=APackage.Files[i];
411 Filename:=PkgFile.GetFullFilename;
412 if FilenameIsPascalUnit(Filename) then begin
413 Filename:=ExtractFileNameOnly(Filename);
414 if (CompareFilenames(Prefix,copy(Filename,1,length(Prefix)))=0) then
415 begin
416 Identifier:=ExtractFileNameOnly(Filename);
417 if APackage<>StartModuleOwner then
418 Identifier:='#'+APackage.Name+'.'+Identifier;
419 fItems.Add(Identifier, lisPackageUnit);
420 end;
421 end;
422 end;
423 end;
424
425 procedure TFPDocLinkEditorDlg.AddIdentifiers(ModuleOwner: TObject;
426 FPDocFile: TLazFPDocFile; Prefix: string);
427 var
428 DOMNode: TDOMNode;
429 ElementName: String;
430 ModuleName: String;
431 begin
432 if FPDocFile=nil then exit;
433 //DebugLn(['TFPDocLinkEditorDlg.AddIdentifiers ',FPDocFile.Filename,' Prefix=',Prefix]);
434 DOMNode:=FPDocFile.GetFirstElement;
435 while DOMNode<>nil do begin
436 if (DOMNode is TDomElement) then begin
437 //DebugLn(['TFPDocLinkEditorDlg.AddIdentifiers ',DbgSName(DOMNode)]);
438 ElementName:=TDomElement(DOMNode).GetAttribute('name');
439 if (SysUtils.CompareText(Prefix,copy(ElementName,1,length(Prefix)))=0)
440 then begin
441 // same prefix
442 if (FPDocFile<>nil) and (FPDocFile<>StartFPDocFile) then begin
443 // different unit
444 ElementName:=ExtractFileNameOnly(FPDocFile.Filename)+'.'+ElementName;
445 end;
446 if (ModuleOwner<>nil) and (ModuleOwner<>StartModuleOwner) then begin
447 // different module
448 if ModuleOwner is TLazProject then
449 ModuleName:=lowercase(ExtractFileNameOnly(TLazProject(ModuleOwner).ProjectInfoFile))
450 else if ModuleOwner is TLazPackage then
451 ModuleName:=TLazPackage(ModuleOwner).Name
452 else
453 ModuleName:='';
454 if ModuleName<>'' then
455 ElementName:='#'+ModuleName+'.'+ElementName
456 else
457 ElementName:='';
458 end;
459 if ElementName<>'' then
460 FItems.AddIdentifier(ElementName);
461 end;
462 end;
463 DOMNode:=DOMNode.NextSibling;
464 end;
465 end;
466
467 procedure TFPDocLinkEditorDlg.AddSubIdentifiers(Path: string);
468 var
469 p: LongInt;
470 Prefix: String;
471 ModuleOwner: TObject;
472 FPDocFile: TLazFPDocFile;
473 DOMNode: TDOMNode;
474 InvalidPath: integer;
475 CacheWasUsed: boolean;
476 DOMElement: TDOMElement;
477 begin
478 p:=length(Path);
479 while (p>0) and (Path[p]<>'.') do dec(p);
480 if p<1 then begin
481 // empty : show all packages, all units of current project/package and all identifiers of unit
482 // #l : show all packages beginning with the letter l
483 // f : show all units and all identifiers beginning with the letter f
484 if (Path='') or (Path[1]='#') then
485 AddPackagesToCompletion(copy(Path,2,length(Path)));
486 if (Path='') or (Path[1]<>'#') then begin
487 AddModuleUnits(StartModuleOwner,Path);
488 AddIdentifiers(StartModuleOwner,StartFPDocFile,Path);
489 end;
490 end else begin
491 // sub identifier
492 //DebugLn(['TFPDocLinkEditorDlg.AddSubIdentifiers searching context ..']);
493 CodeHelpBoss.GetLinkedFPDocNode(StartFPDocFile,nil,Path,
494 [chofUpdateFromDisk,chofQuiet],ModuleOwner,FPDocFile,DOMNode,InvalidPath,
495 CacheWasUsed);
496 // get rest path as filter
497 Prefix:=copy(Path,InvalidPath,length(Path));
498 if (Prefix<>'') and (Prefix[1]='.') then System.Delete(Prefix,1,1);
499 //DebugLn(['TFPDocLinkEditorDlg.AddSubIdentifiers context found: ModuleOwner=',DbgSName(ModuleOwner),' FPDocFile=',FPDocFile<>nil,' DOMNode=',DOMNode<>nil,' invalid path="',Prefix,'"']);
500 if DOMNode is TDomElement then begin
501 // show elements of unit, beginning with prefix
502 DOMElement:=TDomElement(DOMNode);
503 Prefix:=DOMElement.GetAttribute('name')+'.'+Prefix;
504 AddIdentifiers(ModuleOwner,FPDocFile,Prefix);
505 end else if FPDocFile<>nil then begin
506 // show elements of unit, beginning with prefix
507 AddIdentifiers(ModuleOwner,FPDocFile,Prefix);
508 end else if ModuleOwner<>nil then begin
509 // show units of module, beginning with first part of prefix
510 p:=1;
511 while (p<=length(Prefix)) and (Prefix[p]<>'.') do inc(p);
512 Prefix:=copy(Prefix,1,p-1);
513 if ModuleOwner is TLazPackage then
514 AddPackageUnits(TLazPackage(ModuleOwner),Prefix)
515 else if ModuleOwner is TLazProject then
516 AddProjectUnits(TLazProject(ModuleOwner),Prefix);
517 end;
518 end;
519 end;
520
521 procedure TFPDocLinkEditorDlg.SetLinkAndContext(const ASrcFilename, ATitle,
522 ALink: string; ADocFile: TLazFPDocFile);
523 begin
524 StartFPDocFile:=ADocFile;
525 fSourceFilename:=ASrcFilename;
526 LinkTitle:=ATitle;
527 Link:=ALink;
528 UpdateCompletionBox;
529 end;
530
GetLinkTitlenull531 function TFPDocLinkEditorDlg.GetLinkTitle: string;
532 begin
533 Result:=TitleEdit.Text;
534 end;
535
536 procedure TFPDocLinkEditorDlg.SetStartFPDocFile(const AValue: TLazFPDocFile);
537 begin
538 if FStartFPDocFile=AValue then exit;
539 FStartFPDocFile:=AValue;
540 FStartModuleOwner:=CodeHelpBoss.FindModuleOwner(FStartFPDocFile);
541 end;
542
GetLinknull543 function TFPDocLinkEditorDlg.GetLink: string;
544 begin
545 Result:=LinkEdit.Text;
546 end;
547
548 procedure TFPDocLinkEditorDlg.SetLink(const AValue: string);
549 begin
550 if FItems=nil then exit;
551 if AValue=fItems.Prefix then exit;
552 fItems.Prefix:=AValue;
553 LinkEdit.Text:=AValue;
554 UpdateCompletionBox;
555 end;
556
557 procedure TFPDocLinkEditorDlg.SetLinkTitle(const AValue: string);
558 begin
559 TitleEdit.Text:=AValue;
560 end;
561
562 { TFPDocLinkCompletionList }
563
GetCountnull564 function TFPDocLinkCompletionList.GetCount: integer;
565 begin
566 Result:=FItems.Count;
567 end;
568
TFPDocLinkCompletionList.GetItemsnull569 function TFPDocLinkCompletionList.GetItems(Index: integer
570 ): TFPDocLinkCompletionItem;
571 begin
572 Result:=TFPDocLinkCompletionItem(FItems[Index]);
573 end;
574
575 procedure TFPDocLinkCompletionList.SetSorted(const AValue: Boolean);
576 begin
577 if FSorted=AValue then exit;
578 if AValue then
579 Sort
580 else
581 FSorted:=false;
582 end;
583
584 procedure TFPDocLinkCompletionList.SetTop(const AValue: integer);
585 begin
586 if FTop=AValue then exit;
587 FTop:=AValue;
588 end;
589
590 constructor TFPDocLinkCompletionList.Create;
591 begin
592 FItems:=TFPList.Create;
593 FTree:=TAvlTree.Create(@CompareFPDocLinkCompletionItem);
594 end;
595
596 destructor TFPDocLinkCompletionList.Destroy;
597 begin
598 Clear;
599 FreeAndNil(FItems);
600 FreeAndNil(FTree);
601 inherited Destroy;
602 end;
603
604 procedure TFPDocLinkCompletionList.Clear;
605 var
606 i: Integer;
607 begin
608 FTree.Clear;
609 for i:=0 to FItems.Count-1 do TObject(FItems[i]).Free;
610 FItems.Clear;
611 FSelected:=0;
612 FTop:=0;
613 FSorted:=true;
614 end;
615
616 procedure TFPDocLinkCompletionList.Sort;
617 var
618 Node: TAvlTreeNode;
619 i: Integer;
620 begin
621 if FSorted then exit;
622 Node:=FTree.FindLowest;
623 i:=0;
624 while Node<>nil do begin
625 FItems[i]:=Node.Data;
626 inc(i);
627 Node:=FTree.FindSuccessor(Node);
628 end;
629 FSorted:=true;
630 end;
631
632 procedure TFPDocLinkCompletionList.AddPackage(Pkg: TLazPackage);
633 begin
634 Add('#'+Pkg.Name, Format(lisPackage2, [Pkg.IDAsString]));
635 end;
636
637 procedure TFPDocLinkCompletionList.Add(Identifier, Description: string);
638 var
639 Item: TFPDocLinkCompletionItem;
640 begin
641 if FTree.FindKey(Pointer(Identifier),
642 @ComparePathWithFPDocLinkCompletionItem)<>nil
643 then exit;
644 Item:=TFPDocLinkCompletionItem.Create(Identifier,Description);
645 FItems.Add(Item);
646 FTree.Add(Item);
647 FSorted:=false;
648 end;
649
650 procedure TFPDocLinkCompletionList.AddIdentifier(Identifier: string);
651 begin
652 Add(Identifier, lisIdentifier);
653 end;
654
655 procedure TFPDocLinkCompletionList.Draw(Canvas: TCanvas; Width, Height: integer);
656 var
657 i: LongInt;
658 y: Integer;
659 dy: LongInt;
660 Item: TFPDocLinkCompletionItem;
661 s: String;
662 begin
663 //DebugLn(['TFPDocLinkCompletionList.Draw ',Width,' ',Height,' Count=',Count]);
664 Sorted:=true;
665 i:=Top;
666 y:=0;
667 dy:=ItemHeight;
668 while (y<Height) and (i<Count) do begin
669 Item:=Items[i];
670 Canvas.Brush.Style:=bsSolid;
671 Canvas.Font.Style:=[];
672 if i=Selected then begin
673 Canvas.Brush.Color:=SelectedBGColor;
674 Canvas.Font.Color:=SelectedTextColor;
675 end else begin
676 Canvas.Brush.Color:=BGColor;
677 Canvas.Font.Color:=TextColor;
678 end;
679 Canvas.FillRect(0,y,Width,y+dy);
680 s:=Item.Text;
681 Canvas.TextOut(2,y+2,s);
682 inc(y,dy);
683 inc(i);
684 end;
685 if y<Height then begin
686 Canvas.Brush.Color:=BGColor;
687 Canvas.FillRect(0,y,Width,Height);
688 end;
689 end;
690
691 { TFPDocLinkCompletionItem }
692
693 constructor TFPDocLinkCompletionItem.Create(const AText, ADescription: string);
694 begin
695 Text:=AText;
696 Description:=ADescription;
697 end;
698
699 end.
700
701