mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-10 03:48:27 +02:00
IDE: lazdoc editor: implemented creating new elements
git-svn-id: trunk@13336 -
This commit is contained in:
parent
2611c3b386
commit
3545742d9e
@ -134,7 +134,7 @@
|
||||
<Unit14>
|
||||
<Filename Value="lazdemsg.pp"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="lazdemsg"/>
|
||||
<UnitName Value="LazDEMsg"/>
|
||||
</Unit14>
|
||||
<Unit15>
|
||||
<Filename Value="lazdeopts.pp"/>
|
||||
|
512
ide/lazdoc.pas
512
ide/lazdoc.pas
@ -28,6 +28,8 @@ unit LazDoc;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
{ $define VerboseLazDoc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
@ -37,7 +39,7 @@ uses
|
||||
CodeCache, CacheCodeTools, FileProcs,
|
||||
Laz_DOM, Laz_XMLRead, Laz_XMLWrite,
|
||||
// IDEIntf
|
||||
MacroIntf, PackageIntf, LazHelpIntf, ProjectIntf, LazIDEIntf,
|
||||
MacroIntf, PackageIntf, LazHelpIntf, ProjectIntf, IDEDialogs, LazIDEIntf,
|
||||
// IDE
|
||||
CompilerOptions, IDEProcs, PackageDefs, EnvironmentOpts, DialogProcs;
|
||||
|
||||
@ -84,7 +86,8 @@ type
|
||||
destructor Destroy; override;
|
||||
function GetModuleNode: TDOMNode;
|
||||
function GetFirstElement: TDOMNode;
|
||||
function GetElementWithName(const ElementName: string): TDOMNode;
|
||||
function GetElementWithName(const ElementName: string;
|
||||
CreateIfNotExists: boolean = false): TDOMNode;
|
||||
function GetChildValuesAsString(Node: TDOMNode): String;
|
||||
function GetValuesFromNode(Node: TDOMNode): TFPDocElementValues;
|
||||
function GetValueFromNode(Node: TDOMNode; Item: TFPDocItem): string;
|
||||
@ -102,6 +105,7 @@ type
|
||||
SourceFilename: string;
|
||||
FPDocFilename: string;
|
||||
FPDocFilenameTimeStamp: integer;
|
||||
FilesTimeStamp: integer;
|
||||
end;
|
||||
|
||||
{ TLazDocElement }
|
||||
@ -166,6 +170,9 @@ type
|
||||
const AMethod: TMethod);
|
||||
procedure CallDocChangeEvents(HandlerType: TLazDocManagerHandler;
|
||||
Doc: TLazFPDocFile);
|
||||
function DoCreateFPDocFileForSource(const SrcFilename: string): string;
|
||||
function CreateFPDocFile(const ExpandedFilename, PackageName,
|
||||
ModuleName: string): TCodeBuffer;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
@ -183,7 +190,8 @@ type
|
||||
out CacheWasUsed: boolean): string;
|
||||
function GetFPDocFilenameForSource(SrcFilename: string;
|
||||
ResolveIncludeFiles: Boolean;
|
||||
out CacheWasUsed: boolean): string;
|
||||
out CacheWasUsed: boolean;
|
||||
CreateIfNotExists: boolean = false): string;
|
||||
function CodeNodeToElementName(Tool: TFindDeclarationTool;
|
||||
CodeNode: TCodeTreeNode): string;
|
||||
function GetFPDocNode(Tool: TCodeTool; CodeNode: TCodeTreeNode; Complete: boolean;
|
||||
@ -192,12 +200,18 @@ type
|
||||
function GetDeclarationChain(Code: TCodeBuffer; X, Y: integer;
|
||||
out ListOfPCodeXYPosition: TFPList;
|
||||
out CacheWasUsed: boolean): TLazDocParseResult;
|
||||
function GetCodeContext(CodePos: PCodeXYPosition;
|
||||
out FindContext: TFindContext;
|
||||
Complete: boolean;
|
||||
out CacheWasUsed: boolean): TLazDocParseResult;
|
||||
function GetElementChain(Code: TCodeBuffer; X, Y: integer; Complete: boolean;
|
||||
out Chain: TLazDocElementChain;
|
||||
out CacheWasUsed: boolean): TLazDocParseResult;
|
||||
function GetHint(Code: TCodeBuffer; X, Y: integer; Complete: boolean;
|
||||
out Hint: string;
|
||||
out CacheWasUsed: boolean): TLazDocParseResult;
|
||||
function CreateElement(Code: TCodeBuffer; X, Y: integer;
|
||||
out Element: TLazDocElement): Boolean;
|
||||
public
|
||||
// Event lists
|
||||
procedure RemoveAllHandlersOfObject(AnObject: TObject);
|
||||
@ -308,11 +322,14 @@ begin
|
||||
|
||||
//proceed to element
|
||||
Result := Result.FirstChild;
|
||||
while Result.NodeName <> 'element' do
|
||||
while (Result<>nil) and (Result.NodeName <> 'element') do
|
||||
Result := Result.NextSibling;
|
||||
end;
|
||||
|
||||
function TLazFPDocFile.GetElementWithName(const ElementName: string): TDOMNode;
|
||||
function TLazFPDocFile.GetElementWithName(const ElementName: string;
|
||||
CreateIfNotExists: boolean): TDOMNode;
|
||||
var
|
||||
ModuleNode: TDOMNode;
|
||||
begin
|
||||
Result:=GetFirstElement;
|
||||
//DebugLn(['TLazFPDocFile.GetElementWithName ',ElementName,' GetFirstElement=',GetFirstElement<>nil]);
|
||||
@ -325,6 +342,19 @@ begin
|
||||
exit;
|
||||
Result:=Result.NextSibling;
|
||||
end;
|
||||
if (Result=nil) and CreateIfNotExists then begin
|
||||
DebugLn(['TLazFPDocFile.GetElementWithName creating ',ElementName]);
|
||||
ModuleNode:=GetModuleNode;
|
||||
if ModuleNode=nil then begin
|
||||
DebugLn(['TLazFPDocFile.GetElementWithName create failed: missing module name. ElementName=',ElementName]);
|
||||
exit;
|
||||
end;
|
||||
Result:=Doc.CreateElement('element');
|
||||
DocChanging;
|
||||
TDOMElement(Result).SetAttribute('name',ElementName);
|
||||
ModuleNode.AppendChild(Result);
|
||||
DocChanged;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TLazFPDocFile.GetChildValuesAsString(Node: TDOMNode): String;
|
||||
@ -335,8 +365,10 @@ begin
|
||||
Child:=Node.FirstChild;
|
||||
while Child<>nil do begin
|
||||
//DebugLn(['TLazFPDocFile.GetChildValuesAsString ',dbgsName(Child)]);
|
||||
if Child is TDOMText then
|
||||
if Child is TDOMText then begin
|
||||
//DebugLn(['TLazFPDocFile.GetChildValuesAsString Data="',TDOMText(Child).Data,'" Length=',TDOMText(Child).Length]);
|
||||
Result:=Result+TDOMText(Child).Data;
|
||||
end;
|
||||
Child:=Child.NextSibling;
|
||||
end;
|
||||
end;
|
||||
@ -379,6 +411,7 @@ var
|
||||
begin
|
||||
Result:='';
|
||||
Child:=Node.FindNode(FPDocItemNames[Item]);
|
||||
//DebugLn(['TLazFPDocFile.GetValueFromNode ',FPDocItemNames[Item],' Found=',Child<>nil]);
|
||||
if Child<>nil then begin
|
||||
if Item=fpdiExample then
|
||||
Result := Child.Attributes.GetNamedItem('file').NodeValue
|
||||
@ -391,6 +424,7 @@ procedure TLazFPDocFile.SetChildValue(Node: TDOMNode; const ChildName: string;
|
||||
NewValue: string);
|
||||
var
|
||||
Child: TDOMNode;
|
||||
TextNode: TDOMText;
|
||||
begin
|
||||
Child:=Node.FindNode(ChildName);
|
||||
NewValue:=ToUnixLineEnding(NewValue);
|
||||
@ -416,22 +450,21 @@ begin
|
||||
if NewValue<>'' then begin
|
||||
DebugLn(['TLazFPDocFile.SetChildValue Adding Name=',ChildName,' NewValue="',NewValue,'"']);
|
||||
DocChanging;
|
||||
Child := Doc.CreateTextNode(NewValue);
|
||||
Child := Doc.CreateElement(ChildName);
|
||||
Node.AppendChild(Child);
|
||||
TextNode := Doc.CreateTextNode(NewValue);
|
||||
Child.AppendChild(TextNode);
|
||||
DocChanged;
|
||||
end;
|
||||
end else begin
|
||||
end else if GetChildValuesAsString(Child)<>NewValue then begin
|
||||
// change node
|
||||
if Child.FirstChild=nil then begin
|
||||
DebugLn(['TLazFPDocFile.SetChildValue FAILED ',Node.NodeName,' ChildName=',Child.NodeName,' Child.FirstChild=nil']);
|
||||
exit;
|
||||
end;
|
||||
if Child.FirstChild.NodeValue <> NewValue then begin
|
||||
DebugLn(['TLazDocForm.CheckAndWriteNode Changing ',Node.NodeName,' ChildName=',Child.NodeName,' OldValue=',Child.FirstChild.NodeValue,' NewValue="',NewValue,'"']);
|
||||
DocChanging;
|
||||
Child.FirstChild.NodeValue := NewValue;
|
||||
DocChanged;
|
||||
end;
|
||||
DocChanging;
|
||||
while Child.FirstChild<>nil do
|
||||
Child.FirstChild.Free;
|
||||
DebugLn(['TLazDocForm.CheckAndWriteNode Changing ',Node.NodeName,' ChildName=',Child.NodeName,' OldValue=',Child.FirstChild.NodeValue,' NewValue="',NewValue,'"']);
|
||||
TextNode := Doc.CreateTextNode(NewValue);
|
||||
Child.AppendChild(TextNode);
|
||||
DocChanged;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -495,6 +528,194 @@ begin
|
||||
TLazDocChangeEvent(FHandlers[HandlerType].Items[i])(Self,Doc);
|
||||
end;
|
||||
|
||||
function TLazDocManager.DoCreateFPDocFileForSource(const SrcFilename: string
|
||||
): string;
|
||||
|
||||
procedure CleanUpPkgList(var PkgList: TFPList);
|
||||
var
|
||||
i: Integer;
|
||||
AProject: TLazProject;
|
||||
BaseDir: String;
|
||||
APackage: TLazPackage;
|
||||
begin
|
||||
if (PkgList=nil) then exit;
|
||||
for i:=PkgList.Count-1 downto 0 do begin
|
||||
if TObject(PkgList[i]) is TLazProject then begin
|
||||
AProject:=TLazProject(PkgList[i]);
|
||||
BaseDir:=ExtractFilePath(AProject.ProjectInfoFile);
|
||||
if BaseDir<>'' then continue;
|
||||
end else if TObject(PkgList[i]) is TLazPackage then begin
|
||||
APackage:=TLazPackage(PkgList[i]);
|
||||
BaseDir:=APackage.Directory;
|
||||
if BaseDir<>'' then continue;
|
||||
end;
|
||||
// this owner can not be used
|
||||
PkgList.Delete(i);
|
||||
end;
|
||||
if PkgList.Count=0 then
|
||||
FreeAndNil(PkgList);
|
||||
|
||||
if PkgList.Count>1 then begin
|
||||
// there are more than one possible owners
|
||||
DebugLn(['TLazDocManager.DoCreateFPDocFileForSource.CleanUpPkgList Warning: overlapping projects/packages']);
|
||||
end;
|
||||
end;
|
||||
|
||||
function SelectNewLazDocPaths(const Title, BaseDir: string): string;
|
||||
begin
|
||||
Result:=LazSelectDirectory('Choose LazDoc directory for '+Title,BaseDir);
|
||||
end;
|
||||
|
||||
var
|
||||
PkgList: TFPList;
|
||||
NewOwner: TObject;
|
||||
AProject: TLazProject;
|
||||
APackage: TLazPackage;
|
||||
p: Integer;
|
||||
LazDocPaths: String;
|
||||
LazDocPackageName: String;
|
||||
NewPath: String;
|
||||
BaseDir: String;
|
||||
Code: TCodeBuffer;
|
||||
CurUnitName: String;
|
||||
AVLNode: TAvgLvlTreeNode;
|
||||
begin
|
||||
Result:='';
|
||||
DebugLn(['TLazDocManager.DoCreateFPDocFileForSource ',SrcFilename]);
|
||||
if not FilenameIsAbsolute(SrcFilename) then begin
|
||||
DebugLn(['TLazDocManager.DoCreateFPDocFileForSource failed, because file no absolute: ',SrcFilename]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
PkgList:=nil;
|
||||
try
|
||||
// get all packages owning the file
|
||||
PkgList:=PackageEditingInterface.GetOwnersOfUnit(SrcFilename);
|
||||
CleanUpPkgList(PkgList);
|
||||
if (PkgList=nil) then begin
|
||||
PkgList:=PackageEditingInterface.GetOwnersOfUnit(SrcFilename);
|
||||
CleanUpPkgList(PkgList);
|
||||
end;
|
||||
if PkgList=nil then begin
|
||||
// no package/project found
|
||||
MessageDlg('Package not found',
|
||||
'The unit '+SrcFilename+' is not owned be any package or project.'#13
|
||||
+'Please add the unit to a package or project.'#13
|
||||
+'Unable to create the fpdoc file.',mtError,[mbCancel],0);
|
||||
exit;
|
||||
end;
|
||||
|
||||
NewOwner:=TObject(PkgList[0]);
|
||||
if NewOwner is TLazProject then begin
|
||||
AProject:=TLazProject(NewOwner);
|
||||
BaseDir:=ExtractFilePath(AProject.ProjectInfoFile);
|
||||
if AProject.LazDocPaths='' then
|
||||
AProject.LazDocPaths:=SelectNewLazDocPaths(AProject.ShortDescription,BaseDir);
|
||||
LazDocPaths:=AProject.LazDocPaths;
|
||||
LazDocPackageName:=ExtractFileNameOnly(AProject.ProjectInfoFile);
|
||||
end else if NewOwner is TLazPackage then begin
|
||||
APackage:=TLazPackage(NewOwner);
|
||||
BaseDir:=APackage.Directory;
|
||||
if APackage.LazDocPaths='' then
|
||||
APackage.LazDocPaths:=SelectNewLazDocPaths(APackage.Name,BaseDir);
|
||||
LazDocPaths:=APackage.LazDocPaths;
|
||||
LazDocPackageName:=APackage.Name;
|
||||
end else begin
|
||||
DebugLn(['TLazDocManager.DoCreateFPDocFileForSource unknown owner type ',dbgsName(NewOwner)]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
p:=1;
|
||||
repeat
|
||||
NewPath:=GetNextDirectoryInSearchPath(LazDocPaths,p);
|
||||
if not FilenameIsAbsolute(NewPath) then
|
||||
NewPath:=AppendPathDelim(BaseDir)+NewPath;
|
||||
if DirPathExistsCached(NewPath) then begin
|
||||
// fpdoc directory found
|
||||
Result:=AppendPathDelim(NewPath)+lowercase(ExtractFileNameOnly(SrcFilename))+'.xml';
|
||||
Code:=CodeToolBoss.LoadFile(SrcFilename,true,false);
|
||||
// get unitname
|
||||
CurUnitName:=ExtractFileNameOnly(SrcFilename);
|
||||
if Code<>nil then
|
||||
CurUnitName:=CodeToolBoss.GetSourceName(Code,false);
|
||||
// remove cache (source to fpdoc filename)
|
||||
AVLNode:=FSrcToDocMap.FindKey(Pointer(SrcFilename),
|
||||
@CompareAnsistringWithLDSrc2DocSrcFile);
|
||||
if AVLNode<>nil then
|
||||
FSrcToDocMap.FreeAndDelete(AVLNode);
|
||||
// create fpdoc file
|
||||
if CreateFPDocFile(Result,LazDocPackageName,CurUnitName)=nil then
|
||||
Result:='';
|
||||
exit;
|
||||
end;
|
||||
until false;
|
||||
|
||||
// no valid directory found
|
||||
DebugLn(['TLazDocManager.DoCreateFPDocFileForSource LazDocModul="',LazDocPackageName,'" LazDocPaths="',LazDocPaths,'" ']);
|
||||
MessageDlg('No valid lazdoc path',
|
||||
LazDocPackageName+' does not have any valid lazdoc path.'#13
|
||||
+'Unable to create the fpdoc file for '+SrcFilename,mtError,[mbCancel],0);
|
||||
finally
|
||||
PkgList.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TLazDocManager.CreateFPDocFile(const ExpandedFilename,
|
||||
PackageName, ModuleName: string): TCodeBuffer;
|
||||
var
|
||||
Doc: TXMLDocument;
|
||||
DescrNode: TDOMElement;
|
||||
ms: TMemoryStream;
|
||||
s: string;
|
||||
ModuleNode: TDOMElement;
|
||||
PackageNode: TDOMElement;
|
||||
begin
|
||||
Result:=nil;
|
||||
if FileExistsCached(ExpandedFilename) then begin
|
||||
Result:=CodeToolBoss.LoadFile(ExpandedFilename,true,false);
|
||||
exit;
|
||||
end;
|
||||
Result:=CodeToolBoss.CreateFile(ExpandedFilename);
|
||||
if Result=nil then begin
|
||||
MessageDlg('Unable to create file',
|
||||
'Unable to create file '+ExpandedFilename,mtError,[mbCancel],0);
|
||||
exit;
|
||||
end;
|
||||
|
||||
Doc:=nil;
|
||||
ms:=nil;
|
||||
try
|
||||
Doc:=TXMLDocument.Create;
|
||||
// <fpdoc-descriptions>
|
||||
DescrNode:=Doc.CreateElement('fpdoc-descriptions');
|
||||
Doc.AppendChild(DescrNode);
|
||||
// <package name="packagename">
|
||||
PackageNode:=Doc.CreateElement('package');
|
||||
PackageNode.SetAttribute('name',PackageName);
|
||||
DescrNode.AppendChild(PackageNode);
|
||||
// <module name="unitname">
|
||||
ModuleNode:=Doc.CreateElement('module');
|
||||
ModuleNode.SetAttribute('name',ModuleName);
|
||||
PackageNode.AppendChild(ModuleNode);
|
||||
// write the XML to a string
|
||||
ms:=TMemoryStream.Create;
|
||||
WriteXMLFile(Doc,ms);
|
||||
ms.Position:=0;
|
||||
SetLength(s,ms.Size);
|
||||
if s<>'' then
|
||||
ms.Read(s[1],length(s));
|
||||
// copy to codebuffer
|
||||
//DebugLn(['TLazDocManager.CreateFPDocFile ',s]);
|
||||
Result.Source:=s;
|
||||
// save file
|
||||
if SaveCodeBuffer(Result)<>mrOk then
|
||||
Result:=nil;
|
||||
finally
|
||||
ms.Free;
|
||||
Doc.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TLazDocManager.Create;
|
||||
begin
|
||||
FDocs:=TAvgLvlTree.Create(@CompareLazFPDocFilenames);
|
||||
@ -647,7 +868,8 @@ begin
|
||||
end;
|
||||
|
||||
function TLazDocManager.GetFPDocFilenameForSource(SrcFilename: string;
|
||||
ResolveIncludeFiles: Boolean; out CacheWasUsed: boolean): string;
|
||||
ResolveIncludeFiles: Boolean; out CacheWasUsed: boolean;
|
||||
CreateIfNotExists: boolean): string;
|
||||
var
|
||||
FPDocName: String;
|
||||
SearchPath: String;
|
||||
@ -671,9 +893,9 @@ var
|
||||
if not FilenameIsAbsolute(SrcFilename) then exit;
|
||||
|
||||
if CheckSourceDirectories then begin
|
||||
PkgList:=PackageEditingInterface.GetOwnersOfUnit(SrcFilename);
|
||||
end else begin
|
||||
PkgList:=PackageEditingInterface.GetPossibleOwnersOfUnit(SrcFilename,[]);
|
||||
end else begin
|
||||
PkgList:=PackageEditingInterface.GetOwnersOfUnit(SrcFilename);
|
||||
end;
|
||||
// get all packages owning the file
|
||||
if PkgList=nil then exit;
|
||||
@ -730,46 +952,61 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
if not FilenameIsPascalSource(SrcFilename) then exit;
|
||||
if not FilenameIsPascalSource(SrcFilename) then begin
|
||||
DebugLn(['TLazDocManager.GetFPDocFilenameForSource error: not a source file: "',SrcFilename,'"']);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// first try cache
|
||||
MapEntry:=nil;
|
||||
AVLNode:=FSrcToDocMap.FindKey(Pointer(SrcFilename),@CompareAnsistringWithLDSrc2DocSrcFile);
|
||||
if AVLNode<>nil then begin
|
||||
MapEntry:=TLDSourceToFPDocFile(AVLNode.Data);
|
||||
if MapEntry.FPDocFilenameTimeStamp=CompilerParseStamp then begin
|
||||
Result:=MapEntry.FPDocFilename;
|
||||
exit;
|
||||
try
|
||||
// first try cache
|
||||
MapEntry:=nil;
|
||||
AVLNode:=FSrcToDocMap.FindKey(Pointer(SrcFilename),
|
||||
@CompareAnsistringWithLDSrc2DocSrcFile);
|
||||
if AVLNode<>nil then begin
|
||||
MapEntry:=TLDSourceToFPDocFile(AVLNode.Data);
|
||||
if (MapEntry.FPDocFilenameTimeStamp=CompilerParseStamp)
|
||||
and (MapEntry.FilesTimeStamp=FileStateCache.TimeStamp) then begin
|
||||
Result:=MapEntry.FPDocFilename;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
CacheWasUsed:=false;
|
||||
|
||||
{$IFDEF VerboseLazDoc}
|
||||
DebugLn(['TLazDocManager.GetFPDocFilenameForSource searching SrcFilename=',SrcFilename]);
|
||||
{$ENDIF}
|
||||
CacheWasUsed:=false;
|
||||
|
||||
// first check if the file is owned by any project/package
|
||||
SearchPath:='';
|
||||
CheckUnitOwners(false);
|
||||
CheckUnitOwners(true);
|
||||
CheckIfInLazarus;
|
||||
{$IFDEF VerboseLazDoc}
|
||||
DebugLn(['TLazDocManager.GetFPDocFilenameForSource searching SrcFilename=',SrcFilename]);
|
||||
{$ENDIF}
|
||||
|
||||
// finally add the default paths
|
||||
AddSearchPath(EnvironmentOptions.LazDocPaths,'');
|
||||
FPDocName:=lowercase(ExtractFileNameOnly(SrcFilename))+'.xml';
|
||||
{$IFDEF VerboseLazDoc}
|
||||
DebugLn(['TLazDocManager.GetFPDocFilenameForSource Search ',FPDocName,' in "',SearchPath,'"']);
|
||||
{$ENDIF}
|
||||
Result:=SearchFileInPath(FPDocName,'',SearchPath,';',ctsfcAllCase);
|
||||
|
||||
// save to cache
|
||||
if MapEntry=nil then begin
|
||||
MapEntry:=TLDSourceToFPDocFile.Create;
|
||||
MapEntry.SourceFilename:=SrcFilename;
|
||||
FSrcToDocMap.Add(MapEntry);
|
||||
// first check if the file is owned by any project/package
|
||||
SearchPath:='';
|
||||
CheckUnitOwners(false);// first check if file is owned by a package/project
|
||||
CheckUnitOwners(true);// then check if the file is in a source directory of a package/project
|
||||
CheckIfInLazarus;
|
||||
|
||||
// finally add the default paths
|
||||
AddSearchPath(EnvironmentOptions.LazDocPaths,'');
|
||||
FPDocName:=lowercase(ExtractFileNameOnly(SrcFilename))+'.xml';
|
||||
{$IFDEF VerboseLazDoc}
|
||||
DebugLn(['TLazDocManager.GetFPDocFilenameForSource Search ',FPDocName,' in "',SearchPath,'"']);
|
||||
{$ENDIF}
|
||||
Result:=SearchFileInPath(FPDocName,'',SearchPath,';',ctsfcAllCase);
|
||||
|
||||
// save to cache
|
||||
if MapEntry=nil then begin
|
||||
MapEntry:=TLDSourceToFPDocFile.Create;
|
||||
MapEntry.SourceFilename:=SrcFilename;
|
||||
FSrcToDocMap.Add(MapEntry);
|
||||
end;
|
||||
MapEntry.FPDocFilename:=Result;
|
||||
MapEntry.FPDocFilenameTimeStamp:=CompilerParseStamp;
|
||||
MapEntry.FilesTimeStamp:=FileStateCache.TimeStamp;
|
||||
finally
|
||||
if (Result='') and CreateIfNotExists then begin
|
||||
Result:=DoCreateFPDocFileForSource(SrcFilename);
|
||||
end;
|
||||
{$IFDEF VerboseLazDoc}
|
||||
DebugLn(['TLazDocManager.GetFPDocFilenameForSource SrcFilename="',SrcFilename,'" Result="',Result,'"']);
|
||||
{$ENDIF}
|
||||
end;
|
||||
MapEntry.FPDocFilename:=Result;
|
||||
MapEntry.FPDocFilenameTimeStamp:=CompilerParseStamp;
|
||||
end;
|
||||
|
||||
function TLazDocManager.CodeNodeToElementName(Tool: TFindDeclarationTool;
|
||||
@ -841,6 +1078,65 @@ begin
|
||||
Result:=ldprFailed;
|
||||
end;
|
||||
|
||||
function TLazDocManager.GetCodeContext(CodePos: PCodeXYPosition; out
|
||||
FindContext: TFindContext; Complete: boolean; out CacheWasUsed: boolean
|
||||
): TLazDocParseResult;
|
||||
var
|
||||
CurTool: TCodeTool;
|
||||
CleanPos: integer;
|
||||
Node: TCodeTreeNode;
|
||||
begin
|
||||
Result:=ldprFailed;
|
||||
FindContext:=CleanFindContext;
|
||||
CacheWasUsed:=true;
|
||||
|
||||
//DebugLn(['TLazDocManager.GetElementChain i=',i,' X=',CodePos^.X,' Y=',CodePos^.Y]);
|
||||
if (CodePos=nil) or (CodePos^.Code=nil) or (CodePos^.X<1) or (CodePos^.Y<1)
|
||||
then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain invalid CodePos']);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// build CodeTree and find node
|
||||
if not CodeToolBoss.Explore(CodePos^.Code,CurTool,false,true) then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain note: there was a parser error']);
|
||||
end;
|
||||
if CurTool=nil then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain explore failed']);
|
||||
exit;
|
||||
end;
|
||||
if CurTool.CaretToCleanPos(CodePos^,CleanPos)<>0 then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain invalid CodePos']);
|
||||
exit;
|
||||
end;
|
||||
|
||||
Node:=CurTool.FindDeepestNodeAtPos(CleanPos,false);
|
||||
if Node=nil then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain node not found']);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// use only definition nodes
|
||||
if (Node.Desc=ctnProcedureHead)
|
||||
and (Node.Parent<>nil) and (Node.Parent.Desc=ctnProcedure) then
|
||||
Node:=Node.Parent;
|
||||
if not (Node.Desc in
|
||||
(AllIdentifierDefinitions+[ctnProperty,ctnProcedure,ctnEnumIdentifier]))
|
||||
then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain ignoring node ',Node.DescAsString]);
|
||||
exit;
|
||||
end;
|
||||
if (CurTool.NodeIsForwardDeclaration(Node)) then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain ignoring forward']);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// success
|
||||
FindContext.Tool:=CurTool;
|
||||
FindContext.Node:=Node;
|
||||
Result:=ldprSuccess;
|
||||
end;
|
||||
|
||||
function TLazDocManager.GetElementChain(Code: TCodeBuffer; X, Y: integer;
|
||||
Complete: boolean; out Chain: TLazDocElementChain; out CacheWasUsed: boolean
|
||||
): TLazDocParseResult;
|
||||
@ -848,12 +1144,10 @@ var
|
||||
ListOfPCodeXYPosition: TFPList;
|
||||
i: Integer;
|
||||
CodePos: PCodeXYPosition;
|
||||
CurTool: TCodeTool;
|
||||
CleanPos: integer;
|
||||
LDElement: TLazDocElement;
|
||||
SrcFilename: String;
|
||||
FPDocFilename: String;
|
||||
Node: TCodeTreeNode;
|
||||
FindContext: TFindContext;
|
||||
begin
|
||||
Chain:=nil;
|
||||
ListOfPCodeXYPosition:=nil;
|
||||
@ -877,49 +1171,15 @@ begin
|
||||
for i:=0 to ListOfPCodeXYPosition.Count-1 do begin
|
||||
// get source position of declaration
|
||||
CodePos:=PCodeXYPosition(ListOfPCodeXYPosition[i]);
|
||||
//DebugLn(['TLazDocManager.GetElementChain i=',i,' X=',CodePos^.X,' Y=',CodePos^.Y]);
|
||||
if (CodePos=nil) or (CodePos^.Code=nil) or (CodePos^.X<1) or (CodePos^.Y<1)
|
||||
then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain i=',i,' invalid CodePos']);
|
||||
continue;
|
||||
end;
|
||||
|
||||
// build CodeTree and find node
|
||||
if not CodeToolBoss.Explore(CodePos^.Code,CurTool,false,true) then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain i=',i,' explore failed']);
|
||||
continue;
|
||||
end;
|
||||
if CurTool.CaretToCleanPos(CodePos^,CleanPos)<>0 then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain i=',i,' invalid CodePos']);
|
||||
continue;
|
||||
end;
|
||||
|
||||
Node:=CurTool.FindDeepestNodeAtPos(CleanPos,false);
|
||||
if Node=nil then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain i=',i,' node not found']);
|
||||
continue;
|
||||
end;
|
||||
|
||||
// use only definition nodes
|
||||
if (Node.Desc=ctnProcedureHead)
|
||||
and (Node.Parent<>nil) and (Node.Parent.Desc=ctnProcedure) then
|
||||
Node:=Node.Parent;
|
||||
if not (Node.Desc in
|
||||
(AllIdentifierDefinitions+[ctnProperty,ctnProcedure,ctnEnumIdentifier]))
|
||||
then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain i=',i,' ignoring node ',Node.DescAsString]);
|
||||
continue;
|
||||
end;
|
||||
if (CurTool.NodeIsForwardDeclaration(Node)) then begin
|
||||
DebugLn(['TLazDocManager.GetElementChain i=',i,' ignoring forward']);
|
||||
continue;
|
||||
end;
|
||||
Result:=GetCodeContext(CodePos,FindContext,Complete,CacheWasUsed);
|
||||
if Result=ldprFailed then continue; // skip invalid contexts
|
||||
if Result<>ldprSuccess then continue;
|
||||
if (not CacheWasUsed) and (not Complete) then exit(ldprParsing);
|
||||
|
||||
// add element
|
||||
LDElement:=Chain.Add;
|
||||
LDElement.CodeXYPos:=CodePos^;
|
||||
LDElement.CodeContext.Tool:=CurTool;
|
||||
LDElement.CodeContext.Node:=Node;
|
||||
LDElement.CodeContext:=FindContext;
|
||||
//DebugLn(['TLazDocManager.GetElementChain i=',i,' CodeContext=',FindContextToString(LDElement.CodeContext)]);
|
||||
|
||||
// find corresponding FPDoc file
|
||||
@ -1063,6 +1323,62 @@ begin
|
||||
DebugLn(['TLazDocManager.GetHint END Hint="',Hint,'"']);
|
||||
end;
|
||||
|
||||
function TLazDocManager.CreateElement(Code: TCodeBuffer; X, Y: integer;
|
||||
out Element: TLazDocElement): Boolean;
|
||||
var
|
||||
CacheWasUsed: boolean;
|
||||
SrcFilename: String;
|
||||
FPDocFilename: String;
|
||||
begin
|
||||
Result:=false;
|
||||
Element:=nil;
|
||||
if Code=nil then begin
|
||||
DebugLn(['TLazDocManager.CreateElement failed Code=nil']);
|
||||
exit;
|
||||
end;
|
||||
DebugLn(['TLazDocManager.CreateElement START ',Code.Filename,' ',X,',',Y]);
|
||||
|
||||
Element:=TLazDocElement.Create;
|
||||
try
|
||||
// check if code context can have a fpdoc element
|
||||
Element.CodeXYPos.Code:=Code;
|
||||
Element.CodeXYPos.X:=X;
|
||||
Element.CodeXYPos.Y:=Y;
|
||||
if GetCodeContext(@Element.CodeXYPos,Element.CodeContext,true,
|
||||
CacheWasUsed)<>ldprSuccess then
|
||||
begin
|
||||
DebugLn(['TLazDocManager.CreateElement GetCodeContext failed for ',Code.Filename,' ',X,',',Y]);
|
||||
exit;
|
||||
end;
|
||||
Element.ElementName:=CodeNodeToElementName(Element.CodeContext.Tool,
|
||||
Element.CodeContext.Node);
|
||||
DebugLn(['TLazDocManager.CreateElement Element.ElementName=',Element.ElementName]);
|
||||
|
||||
// find / create fpdoc file
|
||||
SrcFilename:=Element.CodeContext.Tool.MainFilename;
|
||||
FPDocFilename:=GetFPDocFilenameForSource(SrcFilename,false,CacheWasUsed,true);
|
||||
if FPDocFilename='' then begin
|
||||
// no fpdoc file
|
||||
DebugLn(['TLazDocManager.CreateElement unable to create fpdoc file for ',FPDocFilename]);
|
||||
end;
|
||||
DebugLn(['TLazDocManager.CreateElement FPDocFilename=',FPDocFilename]);
|
||||
|
||||
// parse fpdoc file
|
||||
if not LoadFPDocFile(FPDocFilename,true,false,Element.FPDocFile,CacheWasUsed)
|
||||
then begin
|
||||
DebugLn(['TLazDocManager.CreateElement unable to load fpdoc file ',FPDocFilename]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
Element.ElementNode:=Element.FPDocFile.GetElementWithName(
|
||||
Element.ElementName,true);
|
||||
Result:=Element.ElementNode<>nil;
|
||||
finally
|
||||
if not Result then
|
||||
FreeAndNil(Element);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TLazDocManager.FreeDocs;
|
||||
var
|
||||
AVLNode: TAvgLvlTreeNode;
|
||||
|
@ -1,11 +1,11 @@
|
||||
object LazDocEditForm: TLazDocEditForm
|
||||
Left = 205
|
||||
Left = 303
|
||||
Height = 117
|
||||
Top = 511
|
||||
Top = 548
|
||||
Width = 753
|
||||
HorzScrollBar.Page = 752
|
||||
VertScrollBar.Page = 116
|
||||
ActiveControl = InheritedShortEdit
|
||||
ActiveControl = ShortEdit
|
||||
Caption = 'LazDoc editor'
|
||||
ClientHeight = 117
|
||||
ClientWidth = 753
|
||||
@ -16,9 +16,9 @@ object LazDocEditForm: TLazDocEditForm
|
||||
Left = 17
|
||||
Height = 117
|
||||
Width = 736
|
||||
ActivePage = InheritedTabSheet
|
||||
ActivePage = ShortTabSheet
|
||||
Align = alClient
|
||||
TabIndex = 5
|
||||
TabIndex = 0
|
||||
TabOrder = 0
|
||||
TabPosition = tpBottom
|
||||
object ShortTabSheet: TTabSheet
|
||||
@ -34,6 +34,33 @@ object LazDocEditForm: TLazDocEditForm
|
||||
TabOrder = 0
|
||||
Text = 'ShortEdit'
|
||||
end
|
||||
object CreateButton: TButton
|
||||
AnchorSideTop.Control = ShortEdit
|
||||
AnchorSideTop.Side = asrBottom
|
||||
Left = 6
|
||||
Height = 29
|
||||
Top = 29
|
||||
Width = 98
|
||||
AutoSize = True
|
||||
BorderSpacing.Around = 6
|
||||
Caption = 'CreateButton'
|
||||
OnClick = CreateButtonClick
|
||||
TabOrder = 1
|
||||
end
|
||||
object SaveButton: TButton
|
||||
AnchorSideLeft.Control = CreateButton
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = CreateButton
|
||||
Left = 110
|
||||
Height = 29
|
||||
Top = 29
|
||||
Width = 87
|
||||
AutoSize = True
|
||||
BorderSpacing.Left = 6
|
||||
Caption = 'SaveButton'
|
||||
OnClick = SaveButtonClick
|
||||
TabOrder = 2
|
||||
end
|
||||
end
|
||||
object DescrTabSheet: TTabSheet
|
||||
Caption = 'DescrTabSheet'
|
||||
|
@ -1,21 +1,28 @@
|
||||
{ This is an automatically generated lazarus resource file }
|
||||
|
||||
|
||||
LazarusResources.Add('TLazDocEditForm','FORMDATA',[
|
||||
'TPF0'#15'TLazDocEditForm'#14'LazDocEditForm'#4'Left'#3#205#0#6'Height'#2'u'#3
|
||||
+'Top'#3#255#1#5'Width'#3#241#2#18'HorzScrollBar.Page'#3#240#2#18'VertScrollB'
|
||||
+'ar.Page'#2't'#13'ActiveControl'#7#18'InheritedShortEdit'#7'Caption'#6#13'La'
|
||||
+'zDoc editor'#12'ClientHeight'#2'u'#11'ClientWidth'#3#241#2#8'OnCreate'#7#10
|
||||
+'FormCreate'#9'OnDestroy'#7#11'FormDestroy'#8'OnResize'#7#10'FormResize'#0#12
|
||||
+'TPageControl'#11'PageControl'#4'Left'#2#17#6'Height'#2'u'#5'Width'#3#224#2
|
||||
+#10'ActivePage'#7#17'InheritedTabSheet'#5'Align'#7#8'alClient'#8'TabIndex'#2
|
||||
+#5#8'TabOrder'#2#0#11'TabPosition'#7#8'tpBottom'#0#9'TTabSheet'#13'ShortTabS'
|
||||
+'heet'#7'Caption'#6#13'ShortTabSheet'#12'ClientHeight'#2'V'#11'ClientWidth'#3
|
||||
+#220#2#0#5'TEdit'#9'ShortEdit'#6'Height'#2#23#5'Width'#3#218#2#5'Align'#7#5
|
||||
+'alTop'#19'BorderSpacing.Right'#2#2#13'OnEditingDone'#7#22'DocumentationTagC'
|
||||
+'hange'#8'TabOrder'#2#0#4'Text'#6#9'ShortEdit'#0#0#0#9'TTabSheet'#13'DescrTa'
|
||||
+'bSheet'#7'Caption'#6#13'DescrTabSheet'#12'ClientHeight'#2'V'#11'ClientWidth'
|
||||
+#3#220#2#0#5'TMemo'#9'DescrMemo'#6'Height'#2'R'#5'Width'#3#218#2#5'Align'#7#8
|
||||
'TPF0'#15'TLazDocEditForm'#14'LazDocEditForm'#4'Left'#3'/'#1#6'Height'#2'u'#3
|
||||
+'Top'#3'$'#2#5'Width'#3#241#2#18'HorzScrollBar.Page'#3#240#2#18'VertScrollBa'
|
||||
+'r.Page'#2't'#13'ActiveControl'#7#9'ShortEdit'#7'Caption'#6#13'LazDoc editor'
|
||||
+#12'ClientHeight'#2'u'#11'ClientWidth'#3#241#2#8'OnCreate'#7#10'FormCreate'#9
|
||||
+'OnDestroy'#7#11'FormDestroy'#8'OnResize'#7#10'FormResize'#0#12'TPageControl'
|
||||
+#11'PageControl'#4'Left'#2#17#6'Height'#2'u'#5'Width'#3#224#2#10'ActivePage'
|
||||
+#7#13'ShortTabSheet'#5'Align'#7#8'alClient'#8'TabIndex'#2#0#8'TabOrder'#2#0
|
||||
+#11'TabPosition'#7#8'tpBottom'#0#9'TTabSheet'#13'ShortTabSheet'#7'Caption'#6
|
||||
+#13'ShortTabSheet'#12'ClientHeight'#2'V'#11'ClientWidth'#3#220#2#0#5'TEdit'#9
|
||||
+'ShortEdit'#6'Height'#2#23#5'Width'#3#218#2#5'Align'#7#5'alTop'#19'BorderSpa'
|
||||
+'cing.Right'#2#2#13'OnEditingDone'#7#22'DocumentationTagChange'#8'TabOrder'#2
|
||||
+#0#4'Text'#6#9'ShortEdit'#0#0#7'TButton'#12'CreateButton'#21'AnchorSideTop.C'
|
||||
+'ontrol'#7#9'ShortEdit'#18'AnchorSideTop.Side'#7#9'asrBottom'#4'Left'#2#6#6
|
||||
+'Height'#2#29#3'Top'#2#29#5'Width'#2'b'#8'AutoSize'#9#20'BorderSpacing.Aroun'
|
||||
+'d'#2#6#7'Caption'#6#12'CreateButton'#7'OnClick'#7#17'CreateButtonClick'#8'T'
|
||||
+'abOrder'#2#1#0#0#7'TButton'#10'SaveButton'#22'AnchorSideLeft.Control'#7#12
|
||||
+'CreateButton'#19'AnchorSideLeft.Side'#7#9'asrBottom'#21'AnchorSideTop.Contr'
|
||||
+'ol'#7#12'CreateButton'#4'Left'#2'n'#6'Height'#2#29#3'Top'#2#29#5'Width'#2'W'
|
||||
+#8'AutoSize'#9#18'BorderSpacing.Left'#2#6#7'Caption'#6#10'SaveButton'#7'OnCl'
|
||||
+'ick'#7#15'SaveButtonClick'#8'TabOrder'#2#2#0#0#0#9'TTabSheet'#13'DescrTabSh'
|
||||
+'eet'#7'Caption'#6#13'DescrTabSheet'#12'ClientHeight'#2'V'#11'ClientWidth'#3
|
||||
+#220#2#0#5'TMemo'#9'DescrMemo'#6'Height'#2'R'#5'Width'#3#218#2#5'Align'#7#8
|
||||
+'alClient'#19'BorderSpacing.Right'#2#2#20'BorderSpacing.Bottom'#2#4#13'Lines'
|
||||
+'.Strings'#1#6#9'DescrMemo'#0#8'OnChange'#7#22'DocumentationTagChange'#8'Tab'
|
||||
+'Order'#2#0#0#0#0#9'TTabSheet'#14'ErrorsTabSheet'#7'Caption'#6#14'ErrorsTabS'
|
||||
@ -58,7 +65,7 @@ LazarusResources.Add('TLazDocEditForm','FORMDATA',[
|
||||
+'bOrder'#2#1#0#0#0#9'TTabSheet'#17'InheritedTabSheet'#7'Caption'#6#17'Inheri'
|
||||
+'tedTabSheet'#12'ClientHeight'#2'V'#11'ClientWidth'#3#220#2#0#6'TLabel'#19'I'
|
||||
+'nheritedShortLabel'#6'Height'#2#20#3'Top'#2#2#5'Width'#3#220#2#5'Align'#7#5
|
||||
+'alTop'#17'BorderSpacing.Top'#2#2#7'Caption'#6#19'InheritedShortLabel'#11'Pa'
|
||||
,'alTop'#17'BorderSpacing.Top'#2#2#7'Caption'#6#19'InheritedShortLabel'#11'Pa'
|
||||
+'rentColor'#8#0#0#5'TEdit'#18'InheritedShortEdit'#22'AnchorSideLeft.Control'
|
||||
+#7#17'InheritedTabSheet'#21'AnchorSideTop.Control'#7#19'InheritedShortLabel'
|
||||
+#18'AnchorSideTop.Side'#7#9'asrBottom'#23'AnchorSideRight.Control'#7#17'Inhe'
|
||||
@ -66,7 +73,7 @@ LazarusResources.Add('TLazDocEditForm','FORMDATA',[
|
||||
+#2#24#5'Width'#3#220#2#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#17'Bord'
|
||||
+'erSpacing.Top'#2#2#8'ReadOnly'#9#8'TabOrder'#2#0#4'Text'#6#18'InheritedShor'
|
||||
+'tEdit'#0#0#7'TButton'#21'MoveToInheritedButton'#6'Height'#2#29#3'Top'#2'6'#5
|
||||
,'Width'#3#158#0#8'AutoSize'#9#7'Caption'#6#21'MoveToInheritedButton'#7'OnCli'
|
||||
+'Width'#3#158#0#8'AutoSize'#9#7'Caption'#6#21'MoveToInheritedButton'#7'OnCli'
|
||||
+'ck'#7#26'MoveToInheritedButtonClick'#8'TabOrder'#2#1#0#0#7'TButton'#23'Copy'
|
||||
+'FromInheritedButton'#22'AnchorSideLeft.Control'#7#21'MoveToInheritedButton'
|
||||
+#19'AnchorSideLeft.Side'#7#9'asrBottom'#21'AnchorSideTop.Control'#7#21'MoveT'
|
||||
@ -122,7 +129,7 @@ LazarusResources.Add('TLazDocEditForm','FORMDATA',[
|
||||
+#9'c #A37A4E",'#13#10'"} '#9'c #F0E1CF",'#13#10'"| '#9'c #BD964F",'#13#10'"1'
|
||||
+' '#9'c #977740",'#13#10'"2 '#9'c #7C6038",'#13#10'"3 '#9'c #9C7749",'#13#10
|
||||
+'"4 '#9'c #866340",'#13#10'"5 '#9'c #BA8D59",'#13#10'"6 '#9'c #634430",'#13
|
||||
+#10'"7 '#9'c #8A6542",'#13#10'"8 '#9'c #C99761",'#13#10'"9 '#9'c #CC9B62",'
|
||||
,#10'"7 '#9'c #8A6542",'#13#10'"8 '#9'c #C99761",'#13#10'"9 '#9'c #CC9B62",'
|
||||
+#13#10'"0 '#9'c #6C5842",'#13#10'"a '#9'c #82705A",'#13#10'"b '#9'c #A47C4F"'
|
||||
+','#13#10'"c '#9'c #614A2F",'#13#10'"d '#9'c #906C45",'#13#10'"e '#9'c #7C51'
|
||||
+'3C",'#13#10'"f '#9'c #AD7F54",'#13#10'"g '#9'c #B78858",'#13#10'"h '#9'c #A'
|
||||
@ -130,7 +137,7 @@ LazarusResources.Add('TLazDocEditForm','FORMDATA',[
|
||||
+' #93705B",'#13#10'"l '#9'c #3F3636",'#13#10'"m '#9'c #D3D3D3",'#13#10'"n '#9
|
||||
+'c #CE9E60",'#13#10'"o '#9'c #755738",'#13#10'"p '#9'c #A77951",'#13#10'"q '
|
||||
+#9'c #CE9C63",'#13#10'"r '#9'c #3B271D",'#13#10'"s '#9'c #825F4B",'#13#10'"t'
|
||||
,' '#9'c #D6D5D3",'#13#10'"u '#9'c #EEEAE0",'#13#10'"v '#9'c #AB7A53",'#13#10
|
||||
+' '#9'c #D6D5D3",'#13#10'"u '#9'c #EEEAE0",'#13#10'"v '#9'c #AB7A53",'#13#10
|
||||
+'"w '#9'c #745438",'#13#10'"x '#9'c #A77B50",'#13#10'"y '#9'c #948B83",'#13
|
||||
+#10'"z '#9'c #261313",'#13#10'"A '#9'c #8B6843",'#13#10'"B '#9'c #634730",'
|
||||
+#13#10'"C '#9'c #4B3924",'#13#10'"D '#9'c #B58757",'#13#10'"E '#9'c #816347"'
|
||||
@ -186,7 +193,7 @@ LazarusResources.Add('TLazDocEditForm','FORMDATA',[
|
||||
+' ",'#13#10'" ",'#13#10'" ",'
|
||||
+#13#10'" ",'#13#10'" ",'#13#10'" '
|
||||
+' "};'#13#10#9'NumGlyphs'#2#0#7'OnClick'#7#17'FormatButtonClick'#0#0#0#11
|
||||
+'TOpenDialog'#10'OpenDialog'#5'Title'#6#17'Open example file'#6'Filter'#6#28
|
||||
,'TOpenDialog'#10'OpenDialog'#5'Title'#6#17'Open example file'#6'Filter'#6#28
|
||||
+'pascal file|*.pas; *.pp; *.p'#11'FilterIndex'#2#0#4'left'#2'@'#3'top'#2#24#0
|
||||
+#0#0
|
||||
]);
|
||||
|
@ -31,7 +31,7 @@ unit LazDocFrm;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
{ $define dbgLazDoc}
|
||||
{ $define VerboseLazDoc}
|
||||
|
||||
interface
|
||||
|
||||
@ -68,6 +68,8 @@ type
|
||||
TLazDocEditForm = class(TForm)
|
||||
AddLinkButton: TButton;
|
||||
BrowseExampleButton: TButton;
|
||||
SaveButton: TButton;
|
||||
CreateButton: TButton;
|
||||
CopyFromInheritedButton: TButton;
|
||||
MoveToInheritedButton: TButton;
|
||||
InheritedShortEdit: TEdit;
|
||||
@ -98,6 +100,7 @@ type
|
||||
procedure AddLinkButtonClick(Sender: TObject);
|
||||
procedure BrowseExampleButtonClick(Sender: TObject);
|
||||
procedure CopyFromInheritedButtonClick(Sender: TObject);
|
||||
procedure CreateButtonClick(Sender: TObject);
|
||||
procedure DeleteLinkButtonClick(Sender: TObject);
|
||||
procedure DocumentationTagChange(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
@ -108,6 +111,7 @@ type
|
||||
procedure LinkListBoxClick(Sender: TObject);
|
||||
procedure ApplicationIdle(Sender: TObject; var Done: Boolean);
|
||||
procedure MoveToInheritedButtonClick(Sender: TObject);
|
||||
procedure SaveButtonClick(Sender: TObject);
|
||||
private
|
||||
FCaretXY: TPoint;
|
||||
FModified: Boolean;
|
||||
@ -126,6 +130,7 @@ type
|
||||
function FindInheritedIndex: integer;
|
||||
procedure Save;
|
||||
function GetValues: TFPDocElementValues;
|
||||
procedure SetModified(const AValue: boolean);
|
||||
function WriteNode(Element: TLazDocElement; Values: TFPDocElementValues;
|
||||
Interactive: Boolean): Boolean;
|
||||
procedure UpdateChain;
|
||||
@ -137,6 +142,7 @@ type
|
||||
procedure OnLazDocChanged(Sender: TObject; LazDocFPFile: TLazFPDocFile);
|
||||
procedure LoadGUIValues(Element: TLazDocElement);
|
||||
procedure MoveToInherited(Element: TLazDocElement);
|
||||
function CreateElement(Element: TLazDocElement): Boolean;
|
||||
public
|
||||
procedure Reset;
|
||||
procedure InvalidateChain;
|
||||
@ -148,6 +154,7 @@ type
|
||||
property Doc: TXMLdocument read GetDoc;
|
||||
property SourceFilename: string read GetSourceFilename;
|
||||
property CaretXY: TPoint read FCaretXY;
|
||||
property Modified: boolean read FModified write SetModified;
|
||||
end;
|
||||
|
||||
var
|
||||
@ -232,6 +239,11 @@ begin
|
||||
InsertRemarkButton.Hint := lisLazDocHintRemarkTag;
|
||||
InsertVarTagButton.Hint := lisLazDocHintVarTag;
|
||||
|
||||
CreateButton.Caption := 'Create help item';
|
||||
CreateButton.Enabled:=false;
|
||||
SaveButton.Caption := 'Save';
|
||||
SaveButton.Enabled:=false;
|
||||
|
||||
AddLinkButton.Caption := lisLazDocAddLinkButton;
|
||||
DeleteLinkButton.Caption := lisLazDocDeleteLinkButton;
|
||||
|
||||
@ -413,6 +425,11 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TLazDocEditForm.SaveButtonClick(Sender: TObject);
|
||||
begin
|
||||
Save;
|
||||
end;
|
||||
|
||||
function TLazDocEditForm.GetContextTitle(Element: TLazDocElement): string;
|
||||
// get codetools path. for example: TButton.Align
|
||||
begin
|
||||
@ -487,6 +504,7 @@ begin
|
||||
if (fChain<>nil) and (fChain.Count>0) then
|
||||
Element:=fChain[0];
|
||||
LoadGUIValues(Element);
|
||||
SaveButton.Enabled:=FModified;
|
||||
end;
|
||||
|
||||
procedure TLazDocEditForm.UpdateInheritedControls;
|
||||
@ -597,7 +615,11 @@ var
|
||||
OldModified: Boolean;
|
||||
begin
|
||||
OldModified:=FModified;
|
||||
|
||||
EnabledState := (Element<>nil) and (Element.ElementNode<>nil);
|
||||
|
||||
CreateButton.Enabled := (Element<>nil) and (Element.ElementNode=nil)
|
||||
and (Element.ElementName<>'');
|
||||
|
||||
if EnabledState then
|
||||
begin
|
||||
@ -643,6 +665,25 @@ begin
|
||||
WriteNode(Element,Values,true);
|
||||
end;
|
||||
|
||||
function TLazDocEditForm.CreateElement(Element: TLazDocElement): Boolean;
|
||||
var
|
||||
NewElement: TLazDocElement;
|
||||
begin
|
||||
DebugLn(['TLazDocEditForm.CreateElement ']);
|
||||
if (Element=nil) or (Element.ElementName='') then exit(false);
|
||||
NewElement:=nil;
|
||||
Include(FFlags,ldffWriting);
|
||||
try
|
||||
Result:=LazDocBoss.CreateElement(Element.CodeXYPos.Code,
|
||||
Element.CodeXYPos.X,Element.CodeXYPos.Y,NewElement);
|
||||
finally
|
||||
Exclude(FFlags,ldffWriting);
|
||||
NewElement.Free;
|
||||
end;
|
||||
Reset;
|
||||
InvalidateChain;
|
||||
end;
|
||||
|
||||
procedure TLazDocEditForm.Reset;
|
||||
begin
|
||||
FreeAndNil(fChain);
|
||||
@ -656,7 +697,8 @@ begin
|
||||
LinkListBox.Clear;
|
||||
ExampleEdit.Clear;
|
||||
|
||||
FModified := False;
|
||||
Modified := False;
|
||||
CreateButton.Enabled:=false;
|
||||
end;
|
||||
|
||||
procedure TLazDocEditForm.InvalidateChain;
|
||||
@ -705,7 +747,7 @@ end;
|
||||
|
||||
procedure TLazDocEditForm.ClearEntry(DoSave: Boolean);
|
||||
begin
|
||||
FModified:=true;
|
||||
Modified:=true;
|
||||
ShortEdit.Text:='';
|
||||
DescrMemo.Text:='';
|
||||
ErrorsMemo.Text:='';
|
||||
@ -729,6 +771,7 @@ begin
|
||||
end else begin
|
||||
FModified := False;
|
||||
end;
|
||||
SaveButton.Enabled:=false;
|
||||
end;
|
||||
|
||||
function TLazDocEditForm.GetValues: TFPDocElementValues;
|
||||
@ -740,6 +783,13 @@ begin
|
||||
Result[fpdiExample]:=ExampleEdit.Text;
|
||||
end;
|
||||
|
||||
procedure TLazDocEditForm.SetModified(const AValue: boolean);
|
||||
begin
|
||||
if FModified=AValue then exit;
|
||||
FModified:=AValue;
|
||||
SaveButton.Enabled:=FModified;
|
||||
end;
|
||||
|
||||
function TLazDocEditForm.WriteNode(Element: TLazDocElement;
|
||||
Values: TFPDocElementValues; Interactive: Boolean): Boolean;
|
||||
var
|
||||
@ -888,7 +938,7 @@ end;
|
||||
|
||||
procedure TLazDocEditForm.DocumentationTagChange(Sender: TObject);
|
||||
begin
|
||||
FModified := True;
|
||||
Modified := True;
|
||||
end;
|
||||
|
||||
function TLazDocEditForm.MakeLink: String;
|
||||
@ -925,7 +975,7 @@ begin
|
||||
if Trim(LinkIdComboBox.Text) <> '' then
|
||||
begin
|
||||
LinkListBox.Items.Add(MakeLink);
|
||||
FModified := True;
|
||||
Modified := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -951,7 +1001,13 @@ begin
|
||||
mtConfirmation,[mrYes,'Replace',mrCancel],0)<>mrYes then exit;
|
||||
end;
|
||||
LoadGUIValues(fChain[i]);
|
||||
FModified:=true;
|
||||
Modified:=true;
|
||||
end;
|
||||
|
||||
procedure TLazDocEditForm.CreateButtonClick(Sender: TObject);
|
||||
begin
|
||||
if (fChain=nil) or (fChain.Count=0) then exit;
|
||||
CreateElement(fChain[0]);
|
||||
end;
|
||||
|
||||
procedure TLazDocEditForm.DeleteLinkButtonClick(Sender: TObject);
|
||||
@ -959,7 +1015,7 @@ begin
|
||||
if LinkListBox.ItemIndex >= 0 then begin
|
||||
LinkListBox.Items.Delete(LinkListBox.ItemIndex);
|
||||
DebugLn(['TLazDocEditForm.DeleteLinkButtonClick ']);
|
||||
FModified := True;
|
||||
Modified := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user