IDE: fpdoc link editor: completion with prefix

git-svn-id: trunk@21067 -
This commit is contained in:
mattias 2009-08-02 13:02:48 +00:00
parent ada6f9b0a0
commit 6eac16dcaf
5 changed files with 90 additions and 55 deletions

View File

@ -268,6 +268,7 @@ type
Flags: TCodeHelpOpenFileFlags;
out ModuleOwner: TObject;
out FPDocFile: TLazFPDocFile; out DOMNode: TDOMNode;
out InvalidPath: integer;
out CacheWasUsed: boolean): TCodeHelpParseResult;
function GetDeclarationChain(Code: TCodeBuffer; X, Y: integer;
out ListOfPCodeXYPosition: TFPList;
@ -1688,7 +1689,7 @@ end;
function TCodeHelpManager.GetLinkedFPDocNode(StartFPDocFile: TLazFPDocFile;
StartDOMNode: TDOMNode; const Path: string; Flags: TCodeHelpOpenFileFlags;
out ModuleOwner: TObject; out FPDocFile: TLazFPDocFile; out DOMNode: TDOMNode;
out CacheWasUsed: boolean): TCodeHelpParseResult;
out InvalidPath: integer; out CacheWasUsed: boolean): TCodeHelpParseResult;
function FindFPDocFilename(BaseDir, SearchPath, UnitName: string): string;
begin
@ -1711,6 +1712,7 @@ begin
ModuleOwner:=nil;
FPDocFile:=nil;
DOMNode:=nil;
InvalidPath:=0;
CacheWasUsed:=false;
Result:=chprFailed;
@ -1728,6 +1730,7 @@ begin
if PkgName='' then exit;
Pkg:=PackageGraph.FindAPackageWithName(PkgName,nil);
if Pkg=nil then exit;
InvalidPath:=p;
ModuleOwner:=Pkg;
if p>length(Path) then begin
// link to the module, no unit
@ -1775,6 +1778,7 @@ begin
// load FPDocFile
Result:=LoadFPDocFile(FPDocFilename,Flags,FPDocFile,CacheWasUsed);
if Result<>chprSuccess then exit;
InvalidPath:=p;
if p>length(Path) then begin
// link to a unit, no element
Result:=chprSuccess;
@ -1784,14 +1788,23 @@ begin
p:=StartPos;
// find element
while (p<=length(Path)) and (Path[p]<>'.') do inc(p);
ElementName:=copy(Path,p+1,length(Path));
//DebugLn(['TCodeHelpManager.GetLinkedFPDocNode ElementName=',ElementName]);
DOMNode:=FPDocFile.GetElementWithName(ElementName);
if DOMNode<>nil then
Result:=chprSuccess
else
Result:=chprFailed;
p:=length(Path)+1;
while p>StartPos do begin
ElementName:=copy(Path,StartPos,p-StartPos);
//DebugLn(['TCodeHelpManager.GetLinkedFPDocNode ElementName=',ElementName]);
DOMNode:=FPDocFile.GetElementWithName(ElementName);
if DOMNode<>nil then begin
InvalidPath:=p;
if p>length(Path) then
Result:=chprSuccess
else
Result:=chprFailed;
exit;
end;
dec(p);
while (p>StartPos) and (Path[p]<>'.') do dec(p);
end;
Result:=chprFailed;
end;
function TCodeHelpManager.GetDeclarationChain(Code: TCodeBuffer; X, Y: integer;

View File

@ -54,6 +54,7 @@ object FPDocLinkEditorDlg: TFPDocLinkEditorDlg
BorderSpacing.Left = 6
BorderSpacing.Right = 6
BorderSpacing.Bottom = 6
OnMouseDown = CompletionBoxMouseDown
OnPaint = CompletionBoxPaint
end
object ButtonPanel1: TButtonPanel

View File

@ -20,20 +20,21 @@ LazarusResources.Add('TFPDocLinkEditorDlg','FORMDATA',[
+'AnchorSideTop.Side'#7#9'asrBottom'#4'Left'#2#6#6'Height'#2'j'#3'Top'#2'x'#5
+'Width'#3#140#1#5'Align'#7#8'alBottom'#7'Anchors'#11#5'akTop'#6'akLeft'#7'ak'
+'Right'#8'akBottom'#0#18'BorderSpacing.Left'#2#6#19'BorderSpacing.Right'#2#6
+#20'BorderSpacing.Bottom'#2#6#7'OnPaint'#7#18'CompletionBoxPaint'#0#0#12'TBu'
+'ttonPanel'#12'ButtonPanel1'#4'Left'#2#6#6'Height'#2','#3'Top'#3#232#0#5'Wid'
+'th'#3#140#1#8'TabOrder'#2#0#11'ShowButtons'#11#4'pbOK'#8'pbCancel'#0#0#0#5
+'TEdit'#8'LinkEdit'#22'AnchorSideLeft.Control'#7#5'Owner'#21'AnchorSideTop.C'
+'ontrol'#7#9'LinkLabel'#18'AnchorSideTop.Side'#7#9'asrBottom'#23'AnchorSideR'
+#20'BorderSpacing.Bottom'#2#6#11'OnMouseDown'#7#22'CompletionBoxMouseDown'#7
+'OnPaint'#7#18'CompletionBoxPaint'#0#0#12'TButtonPanel'#12'ButtonPanel1'#4'L'
+'eft'#2#6#6'Height'#2','#3'Top'#3#232#0#5'Width'#3#140#1#8'TabOrder'#2#0#11
+'ShowButtons'#11#4'pbOK'#8'pbCancel'#0#0#0#5'TEdit'#8'LinkEdit'#22'AnchorSid'
+'eLeft.Control'#7#5'Owner'#21'AnchorSideTop.Control'#7#9'LinkLabel'#18'Ancho'
+'rSideTop.Side'#7#9'asrBottom'#23'AnchorSideRight.Control'#7#5'Owner'#20'Anc'
+'horSideRight.Side'#7#9'asrBottom'#4'Left'#2#6#6'Height'#2#27#3'Top'#2']'#5
+'Width'#3#140#1#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#18'BorderSpaci'
+'ng.Left'#2#6#17'BorderSpacing.Top'#2#6#19'BorderSpacing.Right'#2#6#8'OnChan'
+'ge'#7#14'LinkEditChange'#9'OnKeyDown'#7#15'LinkEditKeyDown'#14'OnUTF8KeyPre'
+'ss'#7#20'LinkEditUTF8KeyPress'#14'ParentShowHint'#8#8'ShowHint'#9#8'TabOrde'
+'r'#2#1#4'Text'#6#8'LinkEdit'#0#0#5'TEdit'#9'TitleEdit'#21'AnchorSideTop.Con'
+'trol'#7#10'TitleLabel'#18'AnchorSideTop.Side'#7#9'asrBottom'#23'AnchorSideR'
+'ight.Control'#7#5'Owner'#20'AnchorSideRight.Side'#7#9'asrBottom'#4'Left'#2#6
+#6'Height'#2#27#3'Top'#2']'#5'Width'#3#140#1#7'Anchors'#11#5'akTop'#6'akLeft'
+#7'akRight'#0#18'BorderSpacing.Left'#2#6#17'BorderSpacing.Top'#2#6#19'Border'
+'Spacing.Right'#2#6#8'OnChange'#7#14'LinkEditChange'#9'OnKeyDown'#7#15'LinkE'
+'ditKeyDown'#14'OnUTF8KeyPress'#7#20'LinkEditUTF8KeyPress'#14'ParentShowHint'
+#8#8'ShowHint'#9#8'TabOrder'#2#1#4'Text'#6#8'LinkEdit'#0#0#5'TEdit'#9'TitleE'
+'dit'#21'AnchorSideTop.Control'#7#10'TitleLabel'#18'AnchorSideTop.Side'#7#9
+'asrBottom'#23'AnchorSideRight.Control'#7#5'Owner'#20'AnchorSideRight.Side'#7
+#9'asrBottom'#4'Left'#2#6#6'Height'#2#27#3'Top'#2#30#5'Width'#3#140#1#7'Anch'
+'ors'#11#5'akTop'#6'akLeft'#7'akRight'#0#17'BorderSpacing.Top'#2#6#19'Border'
+'Spacing.Right'#2#6#8'TabOrder'#2#2#4'Text'#6#9'TitleEdit'#0#0#0
+#6'Height'#2#27#3'Top'#2#30#5'Width'#3#140#1#7'Anchors'#11#5'akTop'#6'akLeft'
+#7'akRight'#0#17'BorderSpacing.Top'#2#6#19'BorderSpacing.Right'#2#6#8'TabOrd'
+'er'#2#2#4'Text'#6#9'TitleEdit'#0#0#0
]);

View File

@ -99,6 +99,8 @@ type
TitleLabel: TLabel;
LinkEdit: TEdit;
LinkLabel: TLabel;
procedure CompletionBoxMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure CompletionBoxPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
@ -220,9 +222,21 @@ begin
CompletionBox.ClientWidth,CompletionBox.ClientHeight);
end;
procedure TFPDocLinkEditorDlg.CompletionBoxMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
Line: Integer;
begin
if fItems.ItemHeight<=0 then exit;
Line:=fItems.Top+(Y div fItems.ItemHeight);
if Line>=fItems.Count then exit;
Link:=FItems.Items[Line].Text;
LinkEdit.SelStart:=length(LinkEdit.Text);
end;
procedure TFPDocLinkEditorDlg.LinkEditChange(Sender: TObject);
begin
DebugLn(['TFPDocLinkEditorDlg.LinkEditChange "',LinkEdit.Text,'"']);
//DebugLn(['TFPDocLinkEditorDlg.LinkEditChange "',LinkEdit.Text,'"']);
Link:=LinkEdit.Text;
end;
@ -263,13 +277,6 @@ end;
procedure TFPDocLinkEditorDlg.LinkEditUTF8KeyPress(Sender: TObject;
var UTF8Key: TUTF8Char);
begin
if UTF8Key='.' then begin
if (FItems.Selected>=0) and (FItems.Selected<fItems.Count) then begin
Link:=FItems.Items[fItems.Selected].Text+'.';
LinkEdit.SelStart:=length(LinkEdit.Text);
end;
UTF8Key:='';
end;
end;
procedure TFPDocLinkEditorDlg.SetSourceFilename(const AValue: string);
@ -323,7 +330,7 @@ begin
fItems.Clear;
l:=LinkEdit.Text;
FItems.Prefix:=l;
DebugLn(['TFPDocLinkEditorDlg.UpdateCompletionBox Prefix="',l,'"']);
//DebugLn(['TFPDocLinkEditorDlg.UpdateCompletionBox Prefix="',l,'"']);
AddSubIdentifiers(l);
CompletionBox.Invalidate;
end;
@ -376,7 +383,7 @@ begin
Identifier:=ExtractFileNameOnly(ProjFile.Filename);
if AProject<>StartModuleOwner then
Identifier:='#'+ExtractFileNameOnly(AProject.ProjectInfoFile)+'.'+Identifier;
fItems.Add(Identifier,'project unit');
fItems.Add(Identifier, lisProjectUnit);
end;
end;
end;
@ -402,7 +409,7 @@ begin
Identifier:=ExtractFileNameOnly(Filename);
if APackage<>StartModuleOwner then
Identifier:='#'+APackage.Name+'.'+Identifier;
fItems.Add(Identifier,'package unit');
fItems.Add(Identifier, lisPackageUnit);
end;
end;
end;
@ -452,44 +459,51 @@ procedure TFPDocLinkEditorDlg.AddSubIdentifiers(Path: string);
var
p: LongInt;
Prefix: String;
HelpResult: TCodeHelpParseResult;
ModuleOwner: TObject;
FPDocFile: TLazFPDocFile;
DOMNode: TDOMNode;
InvalidPath: integer;
CacheWasUsed: boolean;
DOMElement: TDOMElement;
begin
p:=length(Path);
while (p>0) and (Path[p]<>'.') do dec(p);
Prefix:=copy(Path,p+1,length(Path));
Path:=copy(Path,1,p-1);
if p<1 then begin
// empty : show all packages, all units of current project/package and all identifiers of unit
// #l : show all packages beginning with the letter l
// f : show all units and all identifiers beginning with the letter f
if (Prefix='') or (Prefix[1]='#') then
AddPackagesToCompletion(copy(Prefix,2,length(Prefix)));
if (Prefix='') or (Prefix[1]<>'#') then begin
AddModuleUnits(StartModuleOwner,Prefix);
AddIdentifiers(StartModuleOwner,StartFPDocFile,Prefix);
if (Path='') or (Path[1]='#') then
AddPackagesToCompletion(copy(Path,2,length(Path)));
if (Path='') or (Path[1]<>'#') then begin
AddModuleUnits(StartModuleOwner,Path);
AddIdentifiers(StartModuleOwner,StartFPDocFile,Path);
end;
end else begin
// sub identifier
DebugLn(['TFPDocLinkEditorDlg.AddSubIdentifiers searching context ..']);
HelpResult:=CodeHelpBoss.GetLinkedFPDocNode(StartFPDocFile,nil,Path,
[chofUpdateFromDisk,chofQuiet],ModuleOwner,FPDocFile,DOMNode,CacheWasUsed);
if HelpResult<>chprSuccess then exit;
DebugLn(['TFPDocLinkEditorDlg.AddSubIdentifiers context found: ModuleOwner=',DbgSName(ModuleOwner),' FPDocFile=',FPDocFile<>nil,' DOMNode=',DOMNode<>nil]);
//DebugLn(['TFPDocLinkEditorDlg.AddSubIdentifiers searching context ..']);
CodeHelpBoss.GetLinkedFPDocNode(StartFPDocFile,nil,Path,
[chofUpdateFromDisk,chofQuiet],ModuleOwner,FPDocFile,DOMNode,InvalidPath,
CacheWasUsed);
// get rest path as filter
Prefix:=copy(Path,InvalidPath,length(Path));
if (Prefix<>'') and (Prefix[1]='.') then System.Delete(Prefix,1,1);
//DebugLn(['TFPDocLinkEditorDlg.AddSubIdentifiers context found: ModuleOwner=',DbgSName(ModuleOwner),' FPDocFile=',FPDocFile<>nil,' DOMNode=',DOMNode<>nil,' invalid path="',Prefix,'"']);
if DOMNode is TDomElement then begin
DOMElement:=TDomElement(DOMNode);
AddIdentifiers(ModuleOwner,FPDocFile,DOMElement.GetAttribute('name')+'.'+Prefix);
Prefix:=DOMElement.GetAttribute('name')+'.'+Prefix;
AddIdentifiers(ModuleOwner,FPDocFile,Prefix);
end else if FPDocFile<>nil then begin
// show elements of unit, beginning with prefix
AddIdentifiers(ModuleOwner,FPDocFile,Prefix);
end else if ModuleOwner<>nil then begin
// show units of module, beginning with first part of prefix
p:=1;
while (p<=length(Prefix)) and (Prefix[p]<>'.') do inc(p);
Prefix:=copy(Prefix,1,p-1);
if ModuleOwner is TLazPackage then
AddPackageUnits(TLazPackage(ModuleOwner),Prefix)
else if ModuleOwner is TLazProject then
AddProjectUnits(TLazProject(ModuleOwner),Prefix)
AddProjectUnits(TLazProject(ModuleOwner),Prefix);
end;
end;
end;
@ -556,8 +570,10 @@ end;
procedure TFPDocLinkCompletionList.SetSorted(const AValue: Boolean);
begin
if FSorted=AValue then exit;
FSorted:=AValue;
if FSorted then Sort;
if AValue then
Sort
else
FSorted:=false;
end;
procedure TFPDocLinkCompletionList.SetTop(const AValue: integer);
@ -610,7 +626,7 @@ end;
procedure TFPDocLinkCompletionList.AddPackage(Pkg: TLazPackage);
begin
Add('#'+Pkg.Name,'package '+Pkg.IDAsString);
Add('#'+Pkg.Name, Format(lisPackage2, [Pkg.IDAsString]));
end;
procedure TFPDocLinkCompletionList.Add(Identifier, Description: string);
@ -628,7 +644,7 @@ end;
procedure TFPDocLinkCompletionList.AddIdentifier(Identifier: string);
begin
Add(Identifier,'identifier');
Add(Identifier, lisIdentifier);
end;
procedure TFPDocLinkCompletionList.Draw(Canvas: TCanvas; Width, Height: integer);
@ -639,7 +655,7 @@ var
Item: TFPDocLinkCompletionItem;
s: String;
begin
DebugLn(['TFPDocLinkCompletionList.Draw ',Width,' ',Height,' Count=',Count]);
//DebugLn(['TFPDocLinkCompletionList.Draw ',Width,' ',Height,' Count=',Count]);
Sorted:=true;
i:=Top;
y:=0;

View File

@ -4215,6 +4215,10 @@ resourcestring
+'sIdentifier%sTMyEnum.Enum%sUnitname.Identifier%s#PackageName.UnitName.'
+'Identifier';
lisTitleLeaveEmptyForDefault = 'Title (leave empty for default)';
lisPackageUnit = 'package unit';
lisPackage2 = 'package %s';
lisIdentifier = 'identifier';
lisProjectUnit = 'project unit';
lisSyntaxMode = 'Syntax mode';
lisObjectPascalDefault = 'Object Pascal - default';
lisDelphi = 'Delphi';