summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/apps/docedit/docedit.lpi27
-rw-r--r--examples/apps/docedit/docedit.lpr2
-rw-r--r--examples/apps/docedit/doceditmsg.pas181
-rw-r--r--examples/apps/docedit/doceditopts.pas154
-rw-r--r--examples/apps/docedit/fpdeutil.pas90
-rw-r--r--examples/apps/docedit/frm_main.pas115
-rw-r--r--examples/apps/docedit/images/node_edit.xpm30
-rw-r--r--examples/apps/docedit/images/node_finished.xpm30
-rw-r--r--examples/apps/docedit/images/node_modified.xpm30
-rw-r--r--examples/apps/docedit/images/node_new.xpm29
-rw-r--r--examples/apps/docedit/model.pas198
-rw-r--r--examples/apps/docedit/pkeditor.pas1136
12 files changed, 1909 insertions, 113 deletions
diff --git a/examples/apps/docedit/docedit.lpi b/examples/apps/docedit/docedit.lpi
index ac254e0a..1f29664b 100644
--- a/examples/apps/docedit/docedit.lpi
+++ b/examples/apps/docedit/docedit.lpi
@@ -35,7 +35,7 @@
<MinVersion Minor="5" Valid="True"/>
</Item2>
</RequiredPackages>
- <Units Count="3">
+ <Units Count="8">
<Unit0>
<Filename Value="docedit.lpr"/>
<IsPartOfProject Value="True"/>
@@ -51,6 +51,31 @@
<IsPartOfProject Value="True"/>
<UnitName Value="frm_options"/>
</Unit2>
+ <Unit3>
+ <Filename Value="model.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="model"/>
+ </Unit3>
+ <Unit4>
+ <Filename Value="fpdeutil.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="FPDEUtil"/>
+ </Unit4>
+ <Unit5>
+ <Filename Value="pkeditor.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="PkEditor"/>
+ </Unit5>
+ <Unit6>
+ <Filename Value="doceditmsg.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="doceditmsg"/>
+ </Unit6>
+ <Unit7>
+ <Filename Value="doceditopts.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="doceditopts"/>
+ </Unit7>
</Units>
</ProjectOptions>
<CompilerOptions>
diff --git a/examples/apps/docedit/docedit.lpr b/examples/apps/docedit/docedit.lpr
index 6cc96293..493efcb1 100644
--- a/examples/apps/docedit/docedit.lpr
+++ b/examples/apps/docedit/docedit.lpr
@@ -8,7 +8,7 @@ uses
{$ENDIF}{$ENDIF}
Classes,
fpgfx,
- frm_main, frm_options;
+ frm_main, frm_options, model, FPDEUtil, PkEditor, doceditmsg, doceditopts;
procedure MainProc;
diff --git a/examples/apps/docedit/doceditmsg.pas b/examples/apps/docedit/doceditmsg.pas
new file mode 100644
index 00000000..5b69e165
--- /dev/null
+++ b/examples/apps/docedit/doceditmsg.pas
@@ -0,0 +1,181 @@
+{
+ ***************************************************************************
+ * *
+ * This source is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This code is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * General Public License for more details. *
+ * *
+ * A copy of the GNU General Public License is available on the World *
+ * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
+ * obtain it by writing to the Free Software Foundation, *
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * *
+ ***************************************************************************
+
+ Author: Michael Van Canneyt
+}
+unit doceditmsg;
+
+{$mode objfpc}{$h+}
+
+interface
+
+ResourceString
+
+{ ---------------------------------------------------------------------
+ Strings which appear in the program
+ ---------------------------------------------------------------------}
+
+ SFileTemplate = 'template.xml';
+ SFPDE = 'Free Pascal documentation editor';
+ SName = 'Name';
+ SOK = ' OK ';
+ SCancel = ' Cancel ';
+ SNewDocument = 'New document';
+ SNew = 'New';
+ SInsertLink = 'Insert link';
+ SInsertTable = 'Insert table';
+ SInsertPrintShortLink = 'Insert short description link';
+ SForFile = ' in file ';
+ SForPackage = ' in package ';
+ SForModule = ' in module ';
+ SForTopic = ' in topic';
+ SLinkTarget = 'Link target';
+ SLinkText = 'Link text';
+ STableRows = 'Rows';
+ STableCols = 'Columns';
+ STableHeader = 'Use header row';
+ SPackages = 'Packages';
+ SFileModified = 'Document "%s" was modified, would you like to save it?';
+ SDeletePackage = 'Are you sure you want to delete package "%s" ?';
+ SDeleteModule = 'Are you sure you want to delete module "%s" ?';
+ SDeleteTopic = 'Are you sure you want to delete topic "%s" ?';
+ SDeleteElement = 'Are you sure you want to delete element "%s" ?';
+ SRenamePackage = 'Rename package';
+ SRenameModule = 'Rename module';
+ SRenameTopic = 'Rename topic';
+ SRenameElement = 'Rename element';
+ SNoElement = 'No element selected';
+ SDataForElement = 'Documentation for element "%s":';
+ SShortDescription = 'Short';
+ SDescription = 'Description';
+ SErrors = 'Errors';
+ SSeeAlso = 'See Also';
+ SCodeExample = 'Example code File';
+ SMakeSkelFromSource = 'Make new document from source file';
+ SSkelErrorWithFile = 'makeskel reported an error (%d). Try to load produced file anyway ?';
+ SSkelErrorWithoutFile = 'makeskel reported an error (%d) and produced no file.';
+ SOptConfirmDelete = 'Confirm node deletion';
+ SOptCreateBackup = 'Backup existing files';
+ SOptSkipEmptyNodes = 'Do not create empty nodes';
+ SOptBackupExtension = 'Backup file extension';
+ SOptDefaultExtension = 'Default extension for new files';
+ SOptMaxRecentUsed = 'Items in MRU list';
+ SAboutText = 'fpdoc editor 1.0'#10'(c) 2002 Michael Van Canneyt'#10+
+ 'See http://www.freepascal.org/';
+ SFileStructure = 'Documentation structure';
+ SModuleElements = 'Elements for selected node';
+{ ---------------------------------------------------------------------
+ Menu strings
+ ---------------------------------------------------------------------}
+
+ SMenuOpen = '_Open';
+ SMenuNew = '_New';
+ SMenuNewFromSource = 'New from so_urce';
+ SMenuSave = '_Save';
+ SMenuSaveAs = 'Save _as';
+ SMenuRecent = '_Recent';
+ SMenuClose = '_Close';
+ SMenuExit = 'E_xit';
+ SMenuFile = 'File';
+
+ SMenuInsert = 'Insert';
+ SMenuInsertPackage = '_Package';
+ SMenuInsertModule = '_Module';
+ SMenuInsertTopic = 'T_opic';
+ SMenuInsertElement = '_Element';
+ SMenuInsertLink = '_Link';
+ SMenuInsertTable = '_Table';
+
+ SMenuFormat = 'Format';
+ SMenuFormatBold = '_Bold';
+ SMenuFormatUnderLine = '_Underline';
+ SMenuFormatItalics = '_Italic';
+ SMenuformatVariable = '_Variable';
+ SMenuFormatRemark = '_Remark';
+ SMenuFormatParaGraph = '_Paragraph';
+ SMenuFormatCode = '_Code';
+ SMenuFormatFile = '_File';
+
+ SMenuRename = 'Rename';
+ SMenuDelete = 'Delete';
+ SMenuExpandAll = 'Expand All';
+ SMenuCollapseAll = 'Collapse All';
+
+ SMenuExtra = 'Extra';
+ SMenuExtraoptions = 'Options';
+
+ SMenuHelp = 'Help';
+ SMenuHelpAbout = 'About';
+
+{ ---------------------------------------------------------------------
+ Hint strings
+ ---------------------------------------------------------------------}
+ SHintFileNew = 'New file';
+ SHintFileOpen = 'Open file';
+ SHintFileSave = 'Save file';
+ SHintFileSaveAs = 'Save file as';
+
+ SHintInsertPackage = 'New package';
+ SHintInsertModule = 'New module';
+ SHintInsertTopic = 'New topic';
+ SHintInsertElement = 'New element';
+ SHintInsertLink = 'Insert link';
+ ShintInsertTable = 'Insert table';
+ SHintInsertPrintShortLink = 'Insert a short description link';
+
+ SMarkSelection = 'Mark selection %s';
+
+ SHMenuExtraOptions = 'Show options dialog';
+ SHMenuHelpAbout = 'About this program';
+
+ SHintToolbarAdd = 'Add';
+ SHintToolbarEdit = 'Edit';
+ SHintToolbarDelete = 'Delete';
+
+{ ---------------------------------------------------------------------
+ Error messages.
+ ---------------------------------------------------------------------}
+
+
+ SErrNoPackageForModule = 'No package found to insert module "%s"';
+ SErrNoNodeForTopic = 'No parent node found to insert topic "%s"';
+ SErrNoNodeForPackage = 'No node found for package "%s"';
+ SErrNoNodeForModule = 'No node found for module "%s"';
+ SErrNoModuleForElement = 'No module found to insert element "%s"';
+ SErrNoNodeForElement = 'No node found for element "%s"';
+ SErrUnknownDomElement = 'Unknwon DOM element as parent for selected element: "%s"';
+
+
+ SSaveFileTitle = 'Enter filename to save to';
+ SOpenFileTitle = 'Select file to open';
+
+Function FormatHint(S : String) : String;
+
+implementation
+
+uses sysutils;
+
+Function FormatHint(S : String) : String;
+
+begin
+ Result:=Format(SMarkSelection,[S]);
+end;
+
+end.
diff --git a/examples/apps/docedit/doceditopts.pas b/examples/apps/docedit/doceditopts.pas
new file mode 100644
index 00000000..8f97fddf
--- /dev/null
+++ b/examples/apps/docedit/doceditopts.pas
@@ -0,0 +1,154 @@
+{
+ ***************************************************************************
+ * *
+ * This source is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This code is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * General Public License for more details. *
+ * *
+ * A copy of the GNU General Public License is available on the World *
+ * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
+ * obtain it by writing to the Free Software Foundation, *
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * *
+ ***************************************************************************
+
+ Author: Michael Van Canneyt
+}
+unit doceditopts;
+
+{$mode objfpc}{$H+}
+
+Interface
+
+uses SysUtils,IniFiles;
+
+Var
+ SkipEmptyNodes : Boolean;
+ ConfirmDelete : Boolean;
+ CreateBackup : Boolean;
+ ShowHelpHints : Boolean;
+ StartMaximized : Boolean;
+ ReopenLast : Boolean;
+ MaxRecentUsed : Integer;
+ BackupExtension : String;
+ DefaultExtension : String;
+ CmdMakeSkel : String;
+ cmdFPDoc : String;
+
+Const
+ ImgIndxNew = 0;
+ ImgIndxEdited = 1;
+ ImgIndxModified = 2;
+ imgIndxFinished = 3;
+
+Procedure LoadOptions;
+Procedure SaveOptions;
+Function GetOptionFileName : String;
+
+Implementation
+
+Const
+ DefFilename = 'doceditor.ini';
+ SecPrefs = 'Preferences';
+ KeySkipEmptyNodes = 'SkipEmptyNodes';
+ KeyConfirmDelete = 'ConfirmDelete';
+ KeyCreateBackup = 'CreateBackup';
+ KeyBackupExtension = 'BackupExtension';
+ KeyDefaultExtension = 'DefaultExtension';
+ //KeyMaxRecentUsed = 'MaxMRUitems';
+ KeyCmdMakeSkel = 'makeskel';
+ KeyCmdFpdoc = 'fpdoc';
+ KeyShowHints = 'ShowHints';
+
+{$ifndef MSWindows}
+Function GetOptionFileName : String;
+
+Const
+ fpdedir = '.fpde';
+
+Var
+ HomeDir : String;
+
+begin
+ HomeDir:=GetEnvironmentVariable('HOME');
+ If (HomeDir<>'') then
+ begin
+ HomeDir:=IncludeTrailingPathDelimiter(HomeDir)+fpdedir;
+ If not DirectoryExists(HomeDir) then
+ If Not CreateDir(HomeDir) then
+ HomeDir:=''
+ else
+ HomeDir:=HomeDir;
+ end;
+ Result:=IncludeTrailingPathDelimiter(HomeDir)+DefFileName;
+end;
+
+{$else}
+
+Function GetOptionFileName : String;
+
+begin
+ Result:=ExtractFilePath(Paramstr(0))+DefFileName;
+end;
+{$endif}
+
+Procedure LoadOptions;
+
+begin
+ With TInifile.Create(GetOptionFileName) do
+ Try
+ SkipEmptyNodes:=ReadBool(SecPrefs,KeySkipEmptyNodes,SkipEmptyNodes);
+ ConfirmDelete:=ReadBool(SecPrefs,KeyConfirmDelete,ConfirmDelete);
+ CreateBackup:=ReadBool(SecPrefs,KeyCreateBackup,CreateBackup);
+ ShowHelpHints:=ReadBool(SecPrefs,KeyShowHints,ShowHelpHints);
+ StartMaximized := ReadBool(SecPrefs, 'StartMaximized', StartMaximized);
+ ReopenLast := ReadBool(SecPrefs, 'ReopenLast', ReopenLast);
+ BackupExtension:=ReadString(SecPrefs,KeyBackupExtension,BackupExtension);
+ DefaultExtension:=ReadString(SecPrefs,KeyDefaultExtension,DefaultExtension);
+ CmdMakeSkel:=ReadString(SecPrefs,KeyCmdMakeSkel,cmdMakeSkel);
+ Cmdfpdoc:=ReadString(SecPrefs,KeyCmdfpdoc,cmdfpdoc);
+ finally
+ Free;
+ end;
+end;
+
+Procedure SaveOptions;
+
+begin
+ With TInifile.Create(GetOptionFileName) do
+ Try
+ WriteBool(SecPrefs,KeySkipEmptyNodes,SkipEmptyNodes);
+ WriteBool(SecPrefs,KeyConfirmDelete,ConfirmDelete);
+ WriteBool(SecPrefs,KeyCreateBackup,CreateBackup);
+ WriteBool(SecPrefs,KeyShowHints,ShowHelpHints);
+ WriteBool(SecPrefs, 'StartMaximized', StartMaximized);
+ WriteBool(SecPrefs, 'ReopenLast', ReopenLast);
+ WriteString(SecPrefs,KeyBackupExtension,BackupExtension);
+ WriteString(SecPrefs,KeyDefaultExtension,DefaultExtension);
+ WriteString(SecPrefs,KeyCmdMakeSkel,cmdMakeSkel);
+ WriteString(SecPrefs,KeyCmdfpdoc,cmdfpdoc);
+ UpdateFile;
+ finally
+ Free;
+ end;
+end;
+
+Initialization
+ SkipEmptyNodes := True;
+ ConfirmDelete := True;
+ CreateBackup := True;
+ StartMaximized := true;
+ ReopenLast := true;
+ BackupExtension := '.~xml';
+ DefaultExtension := '.xml';
+ MaxRecentUSed := 10;
+ CmdMakeSkel := 'makeskel';
+ cmdfpdoc := 'fpdoc';
+ ShowHelpHints := true;
+end.
diff --git a/examples/apps/docedit/fpdeutil.pas b/examples/apps/docedit/fpdeutil.pas
new file mode 100644
index 00000000..e5f22299
--- /dev/null
+++ b/examples/apps/docedit/fpdeutil.pas
@@ -0,0 +1,90 @@
+{
+ ***************************************************************************
+ * *
+ * This source is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This code is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * General Public License for more details. *
+ * *
+ * A copy of the GNU General Public License is available on the World *
+ * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
+ * obtain it by writing to the Free Software Foundation, *
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * *
+ ***************************************************************************
+
+ Author: Michael Van Canneyt
+}
+unit FPDEUtil;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, DOM;
+
+Type
+ TTagType = (ttBold,ttItalic,ttUnderline,ttParagraph,ttVariable,ttRemark,
+ ttNumberedList,ttUnnumberedList,ttListItem,ttTable,ttRow,
+ ttCell,TTHeader,ttPre,ttCode,ttLink,ttFile,ttPrintShort);
+
+ TElementEvent = Procedure (Node : TDomElement) of Object;
+
+Const
+ TagNames : Array[TTagType] of string = ('b','i','u','p','var','remark',
+ 'ol','ul','li','table','tr',
+ 'td','th','pre','code','link','file', 'printshort');
+
+Function IsPackageNode (Node : TDomNode) : Boolean;
+Function IsModuleNode (Node : TDomNode) : Boolean;
+Function IsTopicNode (Node : TDomNode) : Boolean;
+Function IsElementNode (Node : TDomNode) : Boolean;
+Function IsLinkNode (Node : TDomNode) : Boolean;
+
+
+implementation
+{ ---------------------------------------------------------------------
+ Auxiliary functions
+ ---------------------------------------------------------------------}
+
+Function IsPackageNode (Node : TDomNode) : Boolean;
+
+begin
+ Result:=Assigned(Node) and (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='package')
+end;
+
+Function IsModuleNode (Node : TDomNode) : Boolean;
+
+begin
+ Result:=Assigned(Node) and (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='module')
+end;
+
+Function IsTopicNode (Node : TDomNode) : Boolean;
+
+begin
+ Result:=Assigned(Node) and (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='topic')
+end;
+
+Function IsElementNode (Node : TDomNode) : Boolean;
+
+begin
+ Result:=Assigned(Node) and (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='element')
+end;
+
+Function IsLinkNode (Node : TDomNode) : Boolean;
+
+begin
+ Result:=Assigned(Node) and (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='link')
+end;
+
+
+
+
+end.
+
diff --git a/examples/apps/docedit/frm_main.pas b/examples/apps/docedit/frm_main.pas
index 5467752e..e2ddca95 100644
--- a/examples/apps/docedit/frm_main.pas
+++ b/examples/apps/docedit/frm_main.pas
@@ -21,11 +21,12 @@ uses
gui_memo,
gui_tree,
gui_bevel,
- dom, XMLWrite, XMLRead, contnrs;
+ dom, XMLWrite, XMLRead, contnrs, model;
type
TMainForm = class(TfpgForm)
private
+ FFile: TDescDocument;
FDescriptionNode: TDomNode;
FDoc: TXMLDocument;
FModified: Boolean;
@@ -33,14 +34,11 @@ type
FModuleTree: TObjectList;
FElementTree: TObjectList;
procedure btnQuitClicked(Sender: TObject);
- procedure btnOpenClicked(Sender: TObject);
procedure miFileQuitClicked(Sender: TObject);
procedure miFileOpenClicked(Sender: TObject);
procedure miFileSaveAsClicked(Sender: TObject);
procedure miHelpAboutClicked(Sender: TObject);
procedure miExtraOptionsClicked(Sender: TObject);
- procedure ProcessXMLFile(pFilename: string);
- procedure Refresh;
procedure GetElementList(List: TStrings);
public
{@VFD_HEAD_BEGIN: MainForm}
@@ -109,11 +107,6 @@ begin
Close;
end;
-procedure TMainForm.btnOpenClicked(Sender: TObject);
-begin
- // open xml file
-end;
-
procedure TMainForm.miFileQuitClicked(Sender: TObject);
begin
Close;
@@ -129,7 +122,8 @@ begin
if dlg.RunOpenFile then
begin
lblFilename.Text := dlg.FileName;
- ProcessXMLFile(dlg.FileName);
+ FFile := TDescDocument.Create(dlg.Filename);
+// ProcessXMLFile(dlg.FileName);
end
finally
dlg.Free;
@@ -172,107 +166,6 @@ begin
end;
end;
-procedure TMainForm.ProcessXMLFile(pFilename: string);
-var
- dn: TDOMNode;
- ls: TStringList;
-begin
- ReadXMLFile(FDoc, pFilename);
- FDescriptionNode := FDoc.DocumentElement;
- Refresh;
- ls := TStringList.Create;
- GetElementList(ls);
- writeln('.......');
- writeln(ls.Text);
- ls.Free;
-end;
-
-procedure TMainForm.Refresh;
-
- procedure DoTopicNode(Node: TDomElement; Parent: TNodeTreeItem);
- var
- TTreeNode: TTopicTreeItem;
- SubNode: TDomNode;
- begin
- TTreeNode := TTopicTreeItem.Create(TDomElement(Node));
-// TTreeNode.ConnectSelect(@SelectTopic,Node);
-// TTreeNode.ConnectButtonPressEvent(@PopupTopicMenu,Nil);
-// Parent.CheckSubItems;
- Parent.Add(TTreeNode);
-// TFPGtkTree(Parent.SubTree).Append(TTreeNode);
-// TTreeNode.Show;
- SubNode := Node.FirstChild;
- while (SubNode <> nil) do
- begin
- if (SubNode.NodeType = ELEMENT_NODE) and (SubNode.NodeName = 'topic') then
- DoTopicNode(SubNode as TDomElement, TTreeNode);
- SubNode := SubNode.NextSibling;
- end;
- end;
-
-var
- Node, SubNode, SSnode: TDomNode;
- FTreeNode: TPackageTreeItem;
- MTreeNode: TModuleTreeItem;
-
-begin
- CurrentModule := nil;
-
-// FModuleTree.Tree.ClearItems(0,-1);
- if Assigned(FDescriptionNode) then
- begin
- Node := FDescriptionNode.FirstChild;
- while Assigned(Node) do
- begin
- if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'package') then
- begin
- writeln('package: ', Node.Attributes.GetNamedItem('name').TextContent);
- FTreeNode := TPackageTreeItem.Create(TDomElement(Node));
-// FTreeNode.ConnectSelect(@Selectpackage,Node);
-// FTreeNode.ConnectButtonPressEvent(@PopupModuleMenu,Nil);
- FModuleTree.Add(FTreeNode);
-// FTreeNode.Show;
- SubNode := Node.FirstChild;
- while Assigned(SubNode) do
- begin
- if (SubNode.NodeType = ELEMENT_NODE) and (SubNode.NodeName = 'module') then
- begin
- writeln(' module: ', SubNode.Attributes.GetNamedItem('name').TextContent);
- if not Assigned(CurrentModule) then
- CurrentModule := TDomElement(SubNode);
- MTreeNode := TModuleTreeItem.Create(TDomElement(SubNode));
-// MtreeNode.ConnectSelect(@SelectModule,SubNode);
-// MTreeNode.ConnectButtonPressEvent(@PopupModuleMenu,Nil);
-// FTreeNode.CheckSubtree;
- FTreeNode.Add(MTreeNode);
-// TFPGtkTree(FTreeNode.SubTree).Append(MTreeNode);
- //MTreeNode.Show;
- SSNode := SubNode.FirstChild;
- while (SSNode <> nil) do
- begin
- if (SSNode.NodeType = ELEMENT_NODE) and (SSNode.NodeName = 'topic') then
- begin
- writeln(' topic: ', SSNode.Attributes.GetNamedItem('name').TextContent);
- DoTopicNode(SSNode as TDomElement, MTreeNode);
- end;
- SSNode := SSNode.NextSibling;
- end;
- end
- else if (SubNode.NodeType = ELEMENT_NODE) and (SubNode.NodeName = 'topic') then
- begin
- writeln(' topic: ', SubNode.Attributes.GetNamedItem('name').TextContent);
- DoTopicNode(SubNode as TDomElement,FTreeNode);
- end;
- SubNode := SubNode.NextSibling;
- end;
- end;
- Node := Node.NextSibling;
- end;
- end;
-// CurrentModule := Nil;
- FModified := False;
-end;
-
procedure TMainForm.GetElementList(List: TStrings);
var
N: TDOMNode;
diff --git a/examples/apps/docedit/images/node_edit.xpm b/examples/apps/docedit/images/node_edit.xpm
new file mode 100644
index 00000000..c32c290a
--- /dev/null
+++ b/examples/apps/docedit/images/node_edit.xpm
@@ -0,0 +1,30 @@
+/* XPM */
+static char * node_edit_xpm[] = {
+"13 14 13 1",
+" c None",
+". c #FFFFFF",
+"+ c #909290",
+"@ c #848684",
+"# c #FFFF00",
+"$ c #C6C7C6",
+"% c #EE0808",
+"& c #000000",
+"* c #888B88",
+"= c #FDFEFD",
+"- c #8B8E8B",
+"; c #FDFDFD",
+"> c #FEFEFE",
+".............",
+".+@@@@@@@....",
+".+#.#.#.$@...",
+".+.#.#.#$.@..",
+".+#.%.#.&&&&.",
+".*.#%%.%%#$&.",
+"=-#.%%%%%.$&.",
+";+.#%#%#%#$&.",
+";+#.%.%.%.$&.",
+";+.#%#.#%#$&.",
+">+#.#.#.#.$&.",
+";+$$$$$$$$$&.",
+">&&&&&&&&&&&.",
+">............"};
diff --git a/examples/apps/docedit/images/node_finished.xpm b/examples/apps/docedit/images/node_finished.xpm
new file mode 100644
index 00000000..1dbc674e
--- /dev/null
+++ b/examples/apps/docedit/images/node_finished.xpm
@@ -0,0 +1,30 @@
+/* XPM */
+static char * node_finished_xpm[] = {
+"13 14 13 1",
+" c None",
+". c #FFFFFF",
+"+ c #909290",
+"@ c #848684",
+"# c #FFFF00",
+"$ c #C6C7C6",
+"% c #000000",
+"& c #888B88",
+"* c #086F1E",
+"= c #FDFEFD",
+"- c #8B8E8B",
+"; c #FDFDFD",
+"> c #FEFEFE",
+".............",
+".+@@@@@@@....",
+".+#.#.#.$@...",
+".+.#.#.#$.@..",
+".+#.#.#.%%%%.",
+".&.#.#.**#$%.",
+"=-#*#.#**.$%.",
+";+.**#**.#$%.",
+";+#**.**#.$%.",
+";+.#***#.#$%.",
+">+#.#**.#.$%.",
+";+$$$$$$$$$%.",
+">%%%%%%%%%%%.",
+">............"};
diff --git a/examples/apps/docedit/images/node_modified.xpm b/examples/apps/docedit/images/node_modified.xpm
new file mode 100644
index 00000000..61c34903
--- /dev/null
+++ b/examples/apps/docedit/images/node_modified.xpm
@@ -0,0 +1,30 @@
+/* XPM */
+static char * node_modified_xpm[] = {
+"13 14 13 1",
+" c None",
+". c #FFFFFF",
+"+ c #909290",
+"@ c #848684",
+"# c #FFFF00",
+"$ c #C6C7C6",
+"% c #000000",
+"& c #888B88",
+"* c #2A00FD",
+"= c #FDFEFD",
+"- c #8B8E8B",
+"; c #FDFDFD",
+"> c #FEFEFE",
+".............",
+".+@@@@@@@....",
+".+#.#.#.$@...",
+".+.#.#.#$.@..",
+".+#.#.#.%%%%.",
+".&.******#$%.",
+"=-#******.$%.",
+";+.*.**#*#$%.",
+";+#.#**.#.$%.",
+";+.#.**#.#$%.",
+">+#.****#.$%.",
+";+$$$$$$$$$%.",
+">%%%%%%%%%%%.",
+">............"};
diff --git a/examples/apps/docedit/images/node_new.xpm b/examples/apps/docedit/images/node_new.xpm
new file mode 100644
index 00000000..5ac7ce87
--- /dev/null
+++ b/examples/apps/docedit/images/node_new.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static char * node_new_xpm[] = {
+"13 14 12 1",
+" c None",
+". c #FFFFFF",
+"+ c #909290",
+"@ c #848684",
+"# c #FFFF00",
+"$ c #C6C7C6",
+"% c #000000",
+"& c #888B88",
+"* c #FDFEFD",
+"= c #8B8E8B",
+"- c #FDFDFD",
+"; c #FEFEFE",
+".............",
+".+@@@@@@@....",
+".+#.#.#.$@...",
+".+.#.#.#$.@..",
+".+#.#.#.%%%%.",
+".&.#.#.#.#$%.",
+"*=#.#.#.#.$%.",
+"-+.#.#.#.#$%.",
+"-+#.#.#.#.$%.",
+"-+.#.#.#.#$%.",
+";+#.#.#.#.$%.",
+"-+$$$$$$$$$%.",
+";%%%%%%%%%%%.",
+";............"};
diff --git a/examples/apps/docedit/model.pas b/examples/apps/docedit/model.pas
new file mode 100644
index 00000000..c3e7e4bf
--- /dev/null
+++ b/examples/apps/docedit/model.pas
@@ -0,0 +1,198 @@
+unit model;
+
+{$mode objfpc}{$H+}
+
+{$Define DEBUG}
+
+interface
+
+uses
+ Classes, SysUtils, dom, contnrs;
+
+type
+
+ // forward declaration
+ TPackage = class;
+
+
+ TDescDocument = class(TObject)
+ private
+ FFilename: string;
+ FModified: Boolean;
+ FPackage: TPackage;
+ FDoc: TXMLDocument;
+ procedure BuildNodeTree;
+ protected
+ procedure ProcessXMLFile;
+ public
+ constructor Create(const pFilename: string);
+ destructor Destroy; override;
+ property Item: TPackage read FPackage write FPackage;
+ property Filename: string read FFilename;
+ property Modified: Boolean read FModified write FModified;
+ end;
+
+
+ TDocNode = class(TObject)
+ private
+ FDesc: string;
+ FDomElement: TDomElement;
+ FItems: TObjectList;
+ FName: string;
+ FShortDesc: string;
+ procedure SetDesc(const AValue: string);
+ procedure SetName(const AValue: string);
+ procedure SetShortDesc(const AValue: string);
+ public
+ constructor Create(const aName: string);
+ procedure AddItem(aNode: TDocNode);
+ property ShortDesc: string read FShortDesc write SetShortDesc;
+ property Desc: string read FDesc write SetDesc;
+ property Name: string read FName write SetName;
+ property Items: TObjectList read FItems;
+ property DomElement: TDomElement read FDomElement write FDomElement;
+ end;
+
+
+ TPackage = class(TDocNode) // eg: CoreLib
+ end;
+
+
+ TModule = class(TDocNode) // eg: fpgfx
+ end;
+
+
+ TTopic = class(TDocNode) // eg: ????
+ end;
+
+
+ TElement = class(TDocNode) // eg: TfpgWindow or TfpgWindow.Create
+ end;
+
+
+implementation
+
+uses
+ xmlread, xmlwrite, fpdeutil;
+
+procedure DebugLn(const AText: string);
+begin
+ {$IFDEF DEBUG}
+ writeln(AText);
+ {$ENDIF}
+end;
+
+{ TDocNode }
+
+procedure TDocNode.SetShortDesc(const AValue: string);
+begin
+ if FShortDesc=AValue then exit;
+ FShortDesc:=AValue;
+end;
+
+constructor TDocNode.Create(const aName: string);
+begin
+ inherited Create;
+ FName := aName;
+end;
+
+procedure TDocNode.AddItem(aNode: TDocNode);
+begin
+ if not Assigned(FItems) then
+ FItems := TObjectList.create(True);
+ FItems.Add(aNode);
+end;
+
+procedure TDocNode.SetDesc(const AValue: string);
+begin
+ if FDesc=AValue then exit;
+ FDesc:=AValue;
+end;
+
+procedure TDocNode.SetName(const AValue: string);
+begin
+ if FName=AValue then exit;
+ FName:=AValue;
+end;
+
+{ TDescDocument }
+
+procedure TDescDocument.BuildNodeTree;
+var
+ root: TDomNode; // <fpdoc-description> node
+ node, snode, ssnode: TDomNode;
+ oModule: TModule;
+ oTopic: TTopic;
+begin
+ root := FDoc.DocumentElement;
+ if Assigned(root) then
+ begin
+ node := root.FirstChild;
+ while Assigned(node) do
+ begin
+ if IsPackageNode(node) then
+ begin
+ FPackage := TPackage.Create(Node.Attributes.GetNamedItem('name').TextContent);
+ FPackage.DomElement := TDomElement(Node);
+ DebugLn('found package: ' + FPackage.Name);
+
+ snode := node.FirstChild;
+ while Assigned(snode) do
+ begin
+ // we can have 'module' or 'topic' at this level
+ if IsModuleNode(snode) then
+ begin
+ oModule := TModule.Create(snode.attributes.getnameditem('name').textcontent);
+ oModule.DomElement := TDomElement(snode);
+ DebugLn('found module: ' + oModule.Name);
+ FPackage.AddItem(oModule);
+
+ ssnode := snode.FirstChild;
+ while Assigned(ssnode) do
+ begin
+ if IsTopicNode(ssnode) then
+ begin
+ oTopic := TTopic.Create(ssnode.attributes.getnameditem('name').textcontent);
+ oTopic.DomElement := TDomElement(ssnode);
+ DebugLn('found topic: ' + oTopic.Name);
+ oModule.AddItem(oTopic);
+ end;
+ ssnode := ssnode.NextSibling;
+ end; { while }
+ end
+ else if (snode.NodeType = ELEMENT_NODE) and (snode.NodeName = 'topic') then
+ begin
+ DebugLn('TODO: package/topic level for node: ' + snode.attributes.getnameditem('name').textcontent);
+ end;
+ snode := snode.NextSibling;
+ end; { while }
+ end;
+ node := node.NextSibling;
+ end; { while }
+ end; { if }
+end;
+
+procedure TDescDocument.ProcessXMLFile;
+begin
+ ReadXMLFile(FDoc, FFilename);
+ BuildNodeTree;
+end;
+
+constructor TDescDocument.Create(const pFilename: string);
+begin
+ inherited Create;
+ FModified := False;
+ FFilename := pFilename;
+ FDoc := TXMLDocument.Create;
+ ProcessXMLFile;
+end;
+
+destructor TDescDocument.Destroy;
+begin
+ FDoc.Free;
+ inherited Destroy;
+end;
+
+
+end.
+
diff --git a/examples/apps/docedit/pkeditor.pas b/examples/apps/docedit/pkeditor.pas
new file mode 100644
index 00000000..0dcde7f1
--- /dev/null
+++ b/examples/apps/docedit/pkeditor.pas
@@ -0,0 +1,1136 @@
+{
+ ***************************************************************************
+ * *
+ * This source is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This code is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * General Public License for more details. *
+ * *
+ * A copy of the GNU General Public License is available on the World *
+ * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
+ * obtain it by writing to the Free Software Foundation, *
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * *
+ ***************************************************************************
+
+ Author: Michael Van Canneyt
+}
+unit PkEditor;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ SysUtils, Classes, DOM, gui_bevel, gui_label, gui_tree, gui_menu,
+ gfx_imagelist, FPDEUtil, doceditmsg, doceditopts;
+
+Type
+ { TPackageEditor }
+ TCustomPackageEditor = Class(TfpgBevel)
+ Private
+ FModified : Boolean;
+ FDescriptionNode : TDomNode;
+ FCurrentPackage,
+ FCurrentElement,
+ FCurrentModule,
+ FCurrentTopic : TDomElement;
+ FOnSelectElement,
+ FOnSelectPackage,
+ FOnSelectTopic,
+ FOnSelectModule : TElementEvent;
+ protected
+ Procedure SetCurrentModule(Value : TDomElement); virtual;
+ Procedure SetCurrentPackage(Value : TDomElement); virtual;
+ Procedure SetCurrentElement(E : TDomElement); virtual;
+ Procedure SetCurrentTopic(T : TDomElement); virtual;
+ Procedure SetDescriptionNode (Value : TDomNode); virtual;
+ Public
+ Procedure Refresh; virtual; abstract;
+ Procedure AddElement(E : TDomElement); virtual; abstract;
+ Procedure DeletePackage(P : TDomElement); virtual; abstract;
+ Procedure DeleteModule(M : TDomElement); virtual; abstract;
+ Procedure DeleteElement(E : TDomElement); virtual; abstract;
+ Procedure DeleteTopic(T : TDomElement); virtual; abstract;
+ Procedure RenamePackage(P : TDomElement); virtual; abstract;
+ Procedure RenameModule(M : TDomElement); virtual; abstract;
+ Procedure RenameElement(E : TDomElement); virtual; abstract;
+ Procedure RenameTopic(T : TDomElement); virtual; abstract;
+ Property DescriptionNode : TDomNode Read FDescriptionNode Write SetDescriptionNode;
+ Property OnSelectModule : TElementEvent Read FOnSelectModule Write FOnSelectmodule;
+ Property OnSelectTopic : TElementEvent Read FOnSelectTopic Write FOnSelectTopic;
+ Property OnSelectPackage : TElementEvent Read FOnSelectPackage Write FOnSelectPackage;
+ Property OnSelectElement : TElementEvent Read FOnSelectElement Write FOnSelectElement;
+ Property CurrentPackage : TDomElement Read FCurrentPackage Write SetCurrentPackage;
+ Property CurrentModule : TDomElement Read FCurrentModule Write SetCurrentModule;
+ Property CurrentTopic : TDomElement Read FCurrentTopic Write SetCurrentTopic;
+ Property CurrentElement : TDomElement Read FCurrentElement Write SetCurrentElement;
+ Property Modified : Boolean Read FModified Write FModified;
+ end;
+
+
+ // faking a Splitter control
+ TSplitter = class(TfpgBevel);
+
+
+ TPackageEditor = Class(TCustomPackageEditor)
+ Private
+ FLModules,
+ FLElements : TfpgLabel;
+ FPElements : TfpgBevel;
+ FModuleTree : TfpgTreeView;
+ FElementTree : TfpgTreeView;
+ FModuleNode : TfpgTreeNode;
+ FSplitter : TSplitter;
+ PEMenu,
+ PMMenu : TfpgPopupMenu;
+ FMRenameMenu,
+ FMDeleteMenu,
+ FERenameMenu,
+ FECollapseAllMenu,
+ FEExpandAllMenu,
+ FEDeleteMenu : TfpgMenuItem;
+ FImagelist : TfpgImageList;
+ // Callbacks for visual controls.
+ Procedure ModuleChange(Sender: TObject; Node: TfpgTreeNode);
+ Procedure ModuleChanging(Sender: TObject; Node: TfpgTreeNode;
+ Var AllowChange : Boolean);
+ Procedure ElementChange(Sender: TObject; Node: TfpgTreeNode);
+ Procedure ElementChanging(Sender: TObject; Node: TfpgTreeNode;
+ Var AllowChange : Boolean);
+ Procedure MenuRenameClick(Sender : TObject);
+ Procedure MenuDeleteClick(Sender : TObject);
+ Procedure MenuCollapseAllClick(Sender: TObject);
+ procedure MenuExpandAllClick(Sender: TObject);
+ // Internal node methods.
+ Procedure DeleteNode(Msg : String; N : TfpgTreeNode; E : TDomElement);
+ Procedure DeleteElementNode(N : TfpgTreeNode);
+ Procedure RenameNode(Msg : String; N : TfpgTreeNode);
+ Function GetSelectedNode : TfpgTreeNode;
+ Function NewName(ATitle : String;Var AName : String) : Boolean;
+ Function AddDomNode(E : TDomElement;Nodes: TfpgTreeNode;
+ AParent : TfpgTreeNode) : TfpgTreeNode;
+ Procedure DoTopicNode(Node : TDomElement;Nodes: TfpgTreeNode;
+ AParent : TfpgTreeNode);
+ Procedure ClearElements;
+ Procedure SetModuleNode(N : TfpgTreeNode);
+ Function CreateElementNode(E : TDomelement) : TfpgTreeNode;
+ // Correspondence TreeNode<->TDomElement
+ Function FindPackageNode(P : TDomElement) : TfpgTreeNode;
+ Function FindModuleNodeInNode(M : TDomElement; N : TfpgTreeNode) : TfpgTreeNode;
+ Function FindTopicNodeInNode(M : TDomElement; N : TfpgTreeNode) : TfpgTreeNode;
+ Function FindElementNode(E : TDomElement; N : TfpgTreeNode) : TfpgTreeNode;
+ // Element node methods.
+ Procedure SelectTopic(Sender : TDomElement);
+ Procedure SelectModule(Sender : TDomElement);
+ Procedure SelectPackage(Sender : TDomElement);
+ Procedure SelectElement(Sender : TDomElement);
+ Procedure ShowModuleElements(Module : TDomElement);
+ Procedure SetCurrentElementNode(N : TfpgTreeNode);
+ Procedure SetCurrentModuleNode(N : TfpgTreeNode);
+ Procedure SetCurrentPackageNode(N : TfpgTreeNode);
+ Procedure SetCurrentTopicNode(T : TfpgTreeNode);
+ // Other methods
+ procedure UpdateNodeImage(N: TfpgTreeNode);
+ procedure SetNodeImage(N: TfpgTreeNode; Index: Integer);
+ Protected
+ Procedure SetCurrentModule(Value : TDomElement); override;
+ Procedure SetCurrentPackage(Value : TDomElement); override;
+ Procedure SetCurrentElement(E : TDomElement); override;
+ Procedure SetCurrentTopic(T : TDomElement); override;
+ Procedure SetDescriptionNode (Value : TDomNode); override;
+ Public
+ Constructor Create(AOwner : TComponent);override;
+ Procedure Refresh; override;
+ Procedure AddElement(E : TDomElement); override;
+ Procedure DeletePackage(P : TDomElement); override;
+ Procedure DeleteModule(M : TDomElement); override;
+ Procedure DeleteElement(E : TDomElement); override;
+ Procedure DeleteTopic(T : TDomElement); override;
+ Procedure RenamePackage(P : TDomElement); override;
+ Procedure RenameModule(M : TDomElement); override;
+ Procedure RenameElement(E : TDomElement); override;
+ Procedure RenameTopic(T : TDomElement); override;
+ procedure UpdateSelectedNodeStatus;
+ Property ModuleTree : TfpgTreeView Read FModuleTree;
+ Property ElementTree : TfpgTreeView Read FElementTree;
+ end;
+
+
+implementation
+
+uses frmNewNode, graphics;
+
+{ ---------------------------------------------------------------------
+ Auxiliary routines
+ ---------------------------------------------------------------------}
+
+Function GetNextNode(N : TTreeNode) : TTreeNode;
+
+begin
+ Result:=N.GetNextSibling;
+ If (Result=Nil) and (N.Parent<>Nil) then
+ begin
+ Result:=N.Parent.Items[0]; // Count is always >=0, N !!
+ While (Result<>Nil) and (Result.GetNextSibling<>N) do
+ Result:=Result.GetNextSibling;
+ If (Result=Nil) then
+ Result:=N.Parent;
+ end;
+end;
+
+Function SubNodeWithElement(P : TTreeNode; E : TDomElement) : TTreeNode;
+
+Var
+ N : TTreeNode;
+
+begin
+ Result:=Nil;
+ If (E<>Nil) and (P<>Nil) and (P.Count>0) then
+ begin
+ N:=P.Items[0];
+ While (Result=Nil) and (N<>Nil) do
+ If (N.Data=Pointer(E)) then
+ Result:=N
+ else
+ begin
+ //recurse
+ if N.HasChildren then
+ Result:=SubNodeWithElement(N, E);
+ N:=N.GetNextSibling;
+ end;
+ end;
+end;
+
+{ ---------------------------------------------------------------------
+ TCustomPackageEditor
+ ---------------------------------------------------------------------}
+
+procedure TCustomPackageEditor.SetCurrentModule(Value: TDomElement);
+begin
+ if (Value <> nil) then begin
+ if (Value.ParentNode <> nil) then begin
+ CurrentPackage:=Value.ParentNode as TDomElement;
+ FCurrentModule:=Value;
+ end;
+ end;
+end;
+
+procedure TCustomPackageEditor.SetCurrentPackage(Value: TDomElement);
+begin
+ FCurrentPackage:=Value;
+end;
+
+procedure TCustomPackageEditor.SetCurrentElement(E: TDomElement);
+begin
+ FCurrentElement:=E;
+end;
+
+procedure TCustomPackageEditor.SetCurrentTopic(T: TDomElement);
+
+Var
+ N : TDomElement;
+
+begin
+ If (FCurrentTopic<>T) then
+ begin
+ N:=T.ParentNode as TDomElement;
+ if IsModuleNode(N) then
+ CurrentModule:=N
+ else if IsPackageNode(N) then
+ begin
+ CurrentModule:=Nil;
+ CurrentPackage:=N;
+ end
+ else
+ Raise Exception.Create('Unknown parent node for topic node '+TDomElement(T)['name']);
+ FCurrentTopic:=T;
+ end;
+end;
+
+procedure TCustomPackageEditor.SetDescriptionNode(Value: TDomNode);
+begin
+ FDescriptionNode:=Value;
+end;
+
+
+{ ---------------------------------------------------------------------
+ TPackageEditor
+ ---------------------------------------------------------------------}
+
+Constructor TPackageEditor.Create(AOwner : TComponent);
+
+ Function NewMenuItem(ACaption : String; AOnClick : TNotifyEvent) : TfpgMenuItem;
+
+ begin
+ Result:=TfpgMenuItem.Create(Self);
+ Result.Caption:=ACaption;
+ Result.OnClick:=AOnClick;
+ end;
+
+begin
+ Inherited;
+ FImageList := TImageList.Create(Self);
+ Fimagelist.AddLazarusResource('node_new'); // ImgIndxNew
+ Fimagelist.AddLazarusResource('node_edit'); // ImgIndxEdited
+ Fimagelist.AddLazarusResource('node_modified'); // ImgIndxModified
+ Fimagelist.AddLazarusResource('node_finished'); // ImgIndxFinished
+
+ FLModules:=Tfpglabel.Create(Self);
+ With FLModules do
+ begin
+ Parent:=Self;
+ Align:=alTop;
+ Height:=20;
+ Caption:=SFileStructure;
+ end;
+ FModuleTree:=TfpgTreeView.Create(Self);
+ With FModuleTree do
+ begin
+ Parent:=Self;
+ Top := 25;
+ Align:=AlTop;
+ Height:=150;
+ Images:=FImageList;
+ OnChange:=@ModuleChange;
+ OnChanging:=@ModuleChanging;
+ end;
+ FSplitter:=TSplitter.Create(Self);
+ With FSplitter do
+ begin
+ Parent:=Self;
+ Top := 180;
+ align:=alTop;
+ end;
+ FPElements:=TfpgBevel.Create(Self);
+ With FPElements do
+ begin
+ Parent:=Self;
+ Top := 185;
+ align:=AlClient;
+ end;
+ FLElements:=Tfpglabel.Create(Self);
+ With FLElements do
+ begin
+ Parent:=FpElements;
+ Align:=alTop;
+ Height:=20;
+ Caption:=SModuleElements;
+ end;
+ FElementTree:=TfpgTreeView.Create(Self);
+ With FElementTree do
+ begin
+ Parent:=FpElements;
+ Top := 25;
+ Align:=AlClient;
+ Images:=FImageList;
+ OnChange:=@ElementChange;
+ OnChanging:=@ElementChanging;
+ end;
+ PEMenu:=TfpgPopupMenu.Create(Self);
+ FERenameMenu:=NewMenuItem(SMenuRename,@MenuRenameClick);
+ FEDeleteMenu:=NewMenuItem(SMenuDelete,@MenuDeleteClick);
+ FEExpandAllMenu:=NewMenuItem(SMenuExpandAll,@MenuExpandAllClick);
+ FECollapseAllMenu:=NewMenuItem(SMenuCollapseAll,@MenuCollapseAllClick);
+ PEMenu.Items.Add(FERenameMenu);
+ PEMenu.Items.Add(FEDeleteMenu);
+ PEMenu.Items.Add(NewMenuItem('-',nil));
+ PEMEnu.Items.Add(FEExpandAllMenu);
+ PEMenu.Items.Add(FECollapseAllMenu);
+ FElementTree.PopupMenu:=PEMenu;
+ PMMenu:=TPopupMenu.Create(Self);
+ FMRenameMenu:=NewMenuItem(SMenuRename,@MenuRenameClick);
+ FMDeleteMenu:=NewMenuItem(SMenuDelete,@MenuDeleteClick);
+ PMMenu.Items.Add(FMRenameMenu);
+ PMMenu.Items.Add(FMDeleteMenu);
+ FModuleTree.PopupMenu:=PMMenu;
+end;
+
+Procedure TPackageEditor.SetDescriptionNode (Value : TDomNode);
+
+begin
+ Inherited;
+ Refresh;
+end;
+
+
+procedure TPackageEditor.ModuleChanging(Sender: TObject; Node: TfpgTreeNode;
+ var AllowChange: Boolean);
+begin
+ if Sender=nil then ;
+ if Node=nil then ;
+ AllowChange:=True;
+end;
+
+Procedure TPackageEditor.ModuleChange(Sender: TObject; Node: TfpgTreeNode);
+
+Var
+ o : TDomElement;
+
+begin
+ if Sender=nil then ;
+ If (Node<>Nil) then
+ begin
+ O:=TDomElement(Node.Data);
+ If (O<>Nil) then
+ If IsPackageNode(O) then
+ SelectPackage(O)
+ else if IsModuleNode(O) then
+ SelectModule(O)
+ else if IsTopicNode(O) then
+ SelectTopic(O)
+ end;
+end;
+
+procedure TPackageEditor.ElementChanging(Sender: TObject; Node: TfpgTreeNode;
+ var AllowChange: Boolean);
+begin
+ if Sender=nil then ;
+ if Node=nil then ;
+ AllowChange:=True;
+end;
+
+Procedure TPackageEditor.SelectElement(Sender : TDomElement);
+
+begin
+ If IsElementNode(Sender) then
+ CurrentElement:=Sender
+ else // FModuleNode selected.
+ CurrentElement:=Nil;
+ If Assigned(FOnSelectElement) then
+ OnSelectElement(Sender);
+end;
+
+Procedure TPackageEditor.ElementChange(Sender: TObject; Node: TfpgTreeNode);
+
+Var
+ o : TDomElement;
+
+begin
+ if Sender=nil then ;
+ If (Node<>Nil) then
+ begin
+ O:=TDomElement(Node.Data);
+ SelectElement(O)
+ end;
+end;
+
+
+Procedure TPackageEditor.SelectModule(Sender : TDomElement);
+begin
+ Inherited CurrentElement:=Nil;
+ Inherited CurrentTopic:=Nil;
+ Inherited CurrentModule:=Sender;
+ Inherited CurrentPackage:=FCurrentModule.ParentNode as TDomElement;
+ ShowModuleElements(FCurrentModule);
+ If Assigned(FOnSelectModule) then
+ FOnSelectModule(Sender);
+end;
+
+Procedure TPackageEditor.SelectPackage(Sender : TDomElement);
+
+begin
+ Inherited CurrentElement:=Nil;
+ Inherited CurrentModule:=Nil;
+ Inherited CurrentTopic:=Nil;
+ Inherited CurrentPackage:=Sender;
+ ShowModuleElements(Nil);
+ If Assigned(FOnSelectPackage) then
+ FOnSelectPackage(Sender);
+end;
+
+Procedure TPackageEditor.SelectTopic(Sender : TDomElement);
+
+Var
+ P : TDomElement;
+
+begin
+ Inherited CurrentTopic:=Sender;
+ P:=FCurrentTopic.ParentNode as TDomElement;
+ if IsModuleNode(P) then
+ Inherited CurrentModule:=P
+ else if IsTopicNode(P) then
+ Inherited CurrentPackage:=P.ParentNode as TDomElement
+ else if IsPackageNode(P) then
+ Inherited CurrentPackage:=p
+ else
+ Raise Exception.CreateFmt(SErrUnknownDomElement,[P.NodeName]);
+ If Assigned(FOnSelectTopic) then
+ FOnSelectTopic(Sender);
+end;
+
+Function TPackageEditor.GetSelectedNode : TTreeNode;
+
+begin
+ Result:=FModuleTree.Selected;
+end;
+
+Procedure TPackageEditor.MenuRenameClick(Sender : TObject);
+
+Var
+ E : TDomElement;
+
+begin
+ if Sender=nil then ;
+ E:=TDomElement(FModuleTree.Selected.Data);
+ If Assigned(E) then
+ If IsPackageNode(E)then
+ RenamePackage(E)
+ else if IsModuleNode(E) then
+ RenameModule(E)
+ Else if IsTopicNode(E) then
+ RenameTopic(E)
+ else if IsElementNode(E) then
+ RenameElement(E)
+end;
+
+
+Procedure TPackageEditor.MenuDeleteClick(Sender : TObject);
+
+Var
+ E : TDomElement;
+
+begin
+ If (Sender=FEDeleteMenu) then
+ begin
+ E:=TDomElement(FElementTree.Selected.Data);
+ If IsElementNode(E) then
+ DeleteElement(E);
+ end
+ else
+ begin
+ E:=TDomElement(FModuleTree.Selected.Data);
+ If IsPackageNode(E) then
+ DeleteNode(SDeletePackage,FModuleTree.Selected,E)
+ else if IsModuleNode(E) then
+ DeleteNode(SDeleteModule,FModuleTree.Selected,E)
+ else if IsTopicNode(E) then
+ DeleteNode(SDeleteTopic,FModuleTree.Selected,E)
+ end;
+end;
+
+procedure TPackageEditor.MenuCollapseAllClick(Sender: TObject);
+var
+ Node: TTreeNode;
+begin
+ if Sender=nil then ;
+ ElementTree.FullCollapse;
+ Node := ElementTree.Items.GetFirstNode;
+ if Node<>nil then
+ Node.Expand(False);
+end;
+
+procedure TPackageEditor.MenuExpandAllClick(Sender: TObject);
+begin
+ if Sender=nil then ;
+ ElementTree.FullExpand;
+end;
+
+
+Procedure TPackageEditor.SetModuleNode(N : TfpgTreeNode);
+
+begin
+ If N<>Nil then
+ begin
+ FModuleTree.Selected:=N;
+ ModuleChange(FModuleTree,N);
+ end
+ else
+ Refresh;
+end;
+
+Procedure TPackageEditor.DeleteNode(Msg : String; N : TfpgTreeNode; E : TDomElement);
+
+Var
+ P : TTreeNode;
+
+begin
+ If (Not ConfirmDelete) or
+ (MessageDlg(Format(Msg,[E['name']]),mtConfirmation,[mbYes,mbNo],0)=mrYes) then
+ begin
+ P:=GetNextNode(N);
+ FModuleTree.Items.Delete(N);
+ FModified:=True;
+ SetModuleNode(P);
+ end;
+end;
+
+Function TPackageEditor.NewName(ATitle : String;Var AName : String) : Boolean;
+begin
+ Result:=false;
+ With TNewNodeForm.Create(Self) do
+ Try
+ Caption:=ATitle;
+ ENodeName.Text:=AName;
+ If (ShowModal=mrOK) Then begin
+ AName:=ENodeName.Text;
+ Result:=AName<>'';
+ end;
+ Finally
+ Free;
+ end;
+end;
+
+Procedure TPackageEditor.RenameNode(Msg : String; N : TfpgTreeNode);
+
+Var
+ E : TDomElement;
+ S : String;
+
+begin
+ E:=TDomElement(N.Data);
+ S:=E['name'];
+ If NewName(Msg,S) then
+ begin
+ E['name']:=S;
+ N.Text:=S;
+ FModified:=True;
+ end;
+end;
+
+Function TPackageEditor.CreateElementNode(E : TDomelement) : TfpgTreeNode;
+
+begin
+ Result:=FELementTree.Items.AddChild(FModuleNode,E['name']);
+ Result.Data:=E;
+end;
+
+Procedure TPackageEditor.DeleteElementNode(N : TfpgTreeNode);
+
+Var
+ Reposition : Boolean;
+ P : TTreeNode;
+
+begin
+ Reposition:=(TDomElement(N.Data)=CurrentElement) and (CurrentElement<>Nil) ;
+ P:=GetNextNode(N);
+ FElementTree.Items.Delete(N);
+ FModified:=True;
+ If Reposition then
+ begin
+ FElementTree.Selected:=P;
+ ElementChange(FElementTree,P);
+ end;
+end;
+
+Procedure TPackageEditor.DeleteElement(E : TDomElement);
+
+Var
+ N : TTreeNode;
+
+begin
+ N:=FindElementNode(E,Nil);
+ If (N<>Nil) then
+ DeleteElementNode(N);
+end;
+
+Procedure TPackageEditor.DeletePackage(P : TDomElement);
+
+Var
+ N : TTreeNode;
+
+begin
+ N:=FindPackageNode(P);
+ If N<>NIl then
+ DeleteNode(SDeletePackage,N,P);
+end;
+
+
+Procedure TPackageEditor.DeleteModule(M : TDomElement);
+
+Var
+ N : TTreeNode;
+
+begin
+ N:=FindModuleNodeInNode(M,Nil);
+ If N<>NIl then
+ DeleteNode(SDeleteModule,N,M);
+end;
+
+
+Procedure TPackageEditor.DeleteTopic(T : TDomElement);
+
+Var
+ N : TTreeNode;
+
+begin
+ N:=FindTopicNodeInNode(T,Nil);
+ If N<>NIl then
+ DeleteNode(SDeleteTopic,N,T);
+end;
+
+
+Procedure TPackageEditor.RenamePackage(P : TDomElement);
+
+Var
+ N : TTreeNode;
+
+begin
+ N:=FindPackageNode(P);
+ If N<>NIl then
+ RenameNode(SRenamePackage,N);
+end;
+
+
+Procedure TPackageEditor.RenameModule(M : TDomElement);
+
+Var
+ N : TTreeNode;
+
+begin
+ N:=FindModuleNodeInNode(M,Nil);
+ If N<>NIl then
+ RenameNode(SRenameModule,N);
+end;
+
+
+Procedure TPackageEditor.RenameTopic(T : TDomElement);
+
+Var
+ N : TTreeNode;
+
+begin
+ N:=FindTopicNodeInNode(T,Nil);
+ If N<>NIl then
+ RenameNode(SRenameTopic,N);
+end;
+
+procedure DebugElement(Element: TDomElement);
+var
+ Level: integer;
+const
+ NType:Array[0..12] of String[30] =
+ (
+ '0:UNKNOWN',
+ '1:ELEMENT_NODE',
+ '2:ATTRIBUTE_NODE',
+ '3:TEXT_NODE',
+ '4:CDATA_SECTION_NODE',
+ '5:ENTITY_REFERENCE_NODE',
+ '6:ENTITY_NODE',
+ '7:PROCESSING_INSTRUCTION_NODE',
+ '8:COMMENT_NODE',
+ '9:DOCUMENT_NODE',
+ '10:DOCUMENT_TYPE_NODE',
+ '11:DOCUMENT_FRAGMENT_NODE',
+ '12:NOTATION_NODE'
+ );
+ function GetLevelSpc: String;
+ begin
+ SetLength(Result, Level*2);
+ FillChar(Result[1], Level*2, ' ');
+ end;
+ procedure DebugNodes(Node: TDomNode);
+ begin
+ Node := Node.FirstChild;
+ while node<>nil do begin
+ WriteLn(GetLevelSpc, 'Node=',Node.NodeName,' Type=',NType[Node.NodeType],' Value=',Node.NodeValue);
+ if (node.NodeType = ELEMENT_NODE) then begin
+ Inc(Level);
+ DebugNodes(Node);
+ Dec(Level);
+ end;
+ Node := Node.NextSibling;
+ end;
+ end;
+begin
+ if assigned(Element) then begin
+ WriteLn('Element: ', Element['name'],': ');
+ level := 1;
+ DebugNodes(Element);
+ end else
+ WriteLn('Element <nil>');
+end;
+
+
+procedure TPackageEditor.UpdateSelectedNodeStatus;
+begin
+ if ElementTree.Selected<>nil then
+ SetNodeImage(ElementTree.Selected, ImgIndxModified);
+end;
+
+Procedure TPackageEditor.RenameElement(E : TDomElement);
+
+Var
+ N : TTreeNode;
+
+begin
+ N:=FindElementNode(E,Nil);
+ If N<>NIl then
+ RenameNode(SRenameElement,N);
+end;
+
+Procedure TPackageEditor.ClearElements;
+
+begin
+ FElementTree.Items.Clear;
+ FModuleNode:=Nil;
+end;
+
+Procedure TPackageEditor.ShowModuleElements(Module : TDomElement);
+
+Var
+ Node : TDomNode;
+ SNode,PNode,TNode : TTreeNode;
+ S : TStringList;
+ I,L : Integer;
+ N,PN : String;
+
+begin
+ ClearElements;
+ If Assigned(Module) then
+ begin
+ FModuleNode:=FElementTree.Items.Add(Nil,Module['name']);
+ S:=TStringList.Create;
+ Try
+ // get sorted list of elements
+ Node:=Module.FirstChild;
+ While Assigned(Node) do
+ begin
+ If IsElementNode(Node) then
+ S.AddObject(TDomElement(Node)['name'],Node);
+ Node:=Node.NextSibling;
+ end;
+ S.Sorted:=True;
+ // root node
+ TNode:=FModuleNode;
+ // process list of elements, create levels
+ For I:=0 to S.Count-1 do
+ begin
+ PNode:=Nil;
+ SNode:=TNode;
+ N:=S[i];
+ // look for a tentative new parents
+ While (SNode<>FModuleNode) and (PNode=Nil) do
+ begin
+ PN:=TDomElement(SNode.Data)['name']+'.';
+ L:=Length(PN);
+ If CompareText(Copy(N,1,L),PN)=0 then
+ PNode:=SNode;
+ SNode:=SNode.Parent;
+ end;
+ If (PNode=Nil) then
+ PNode:=FModuleNode
+ else
+ System.Delete(N,1,L);
+ TNode:=FElementTree.Items.AddChild(PNode,N);
+ TNode.Data:=S.Objects[i];
+ UpdateNodeImage(TNode);
+ end;
+ Finally
+ S.Free;
+ end;
+ FModuleNode.Expand(False);
+ FElementTree.Selected:=FModuleNode;
+ ElementChange(FElementTree,FModuleNode);
+ end;
+end;
+
+Function TPackageEditor.AddDomNode(E : TDomElement;Nodes: TfpgTreeNodes;AParent : TfpgTreeNode) : TfpgTreeNode;
+
+begin
+ Result:=Nodes.AddChild(AParent,E['name']);
+ Result.Data:=E;
+end;
+
+Procedure TPackageEditor.DoTopicNode(Node : TDomElement;Nodes: TfpgTreeNode;AParent : TfpgTreeNode);
+
+Var
+ N : TTreeNode;
+ SubNode : TDomNode;
+
+begin
+ N:=Nodes.AddChild(AParent,Node['name']);
+ N.Data:=Node;
+ SubNode:=Node.FirstChild;
+ While (SubNode<>Nil) do
+ begin
+ If IsTopicNode(SubNode) then
+ DoTopicNode(SubNode as TDomElement,Nodes,N);
+ SubNode:=SubNode.NextSibling;
+ end;
+end;
+
+
+Procedure TPackageEditor.Refresh;
+
+var
+ Node,SubNode,SSnode : TDomNode;
+ R,P,M : TTreeNode;
+
+begin
+ FModuleTree.Items.Clear;
+ R:=FModuleTree.Items.add(Nil,SPackages);
+ If Assigned(FDescriptionNode) then
+ begin
+ Node:=FDescriptionNode.FirstChild;
+ While Assigned(Node) do
+ begin
+ If IsPackageNode(Node) then
+ begin
+ P:=AddDomNode(Node as TDomElement,FModuleTree.Items,R);
+ SubNode:=Node.FirstChild;
+ While Assigned(SubNode) do
+ begin
+ If IsModuleNode(SubNode) then
+ begin
+ M:=AddDomNode(SubNode as TDomElement,FModuleTree.Items,P);
+ SSNode:=SubNode.FirstChild;
+ While (SSNode<>Nil) do
+ begin
+ if IsTopicNode(SSNode) then
+ DoTopicNode(SSNode as TDomElement,FModuleTree.Items,M);
+ SSNode:=SSNode.NextSibling;
+ end;
+ end
+ else if IsTopicNode(SubNode) then
+ DoTopicNode(SubNode as TDomElement,FModuleTree.Items,P);
+ SubNode:=SubNode.NextSibling;
+ end;
+ end;
+ Node:=Node.NextSibling;
+ end;
+ end;
+ CurrentModule:=Nil;
+ FModified:=False;
+end;
+
+
+Function TPackageEditor.FindPackageNode(P : TDomElement) : TfpgTreeNode;
+begin
+ Result:=Nil;
+ Result:=SubNodeWithElement(FModuleTree.Items[0],P);
+ If (Result=Nil) then
+ Raise Exception.CreateFmt(SErrNoNodeForPackage,[P['name']]);
+end;
+
+Function TPackageEditor.FindModuleNodeInNode(M : TDomElement; N : TfpgTreeNode) : TfpgTreeNode;
+
+Var
+ P : TTreeNode;
+
+begin
+ Result:=Nil;
+ If (N<>Nil) then
+ P:=N
+ else
+ P:=FindPackageNode(M.ParentNode as TDomElement);
+ Result:=SubNodeWithElement(P,M);
+ If (Result=Nil) then
+ Raise Exception.CreateFmt(SErrNoNodeForModule,[M['name']]);
+end;
+
+Function TPackageEditor.FindTopicNodeInNode(M : TDomElement; N : TfpgTreeNode) : TfpgTreeNode;
+
+Var
+ P : TTreeNode;
+ E : TDomElement;
+
+begin
+ Result:=Nil;
+ If (N<>Nil) then
+ P:=N
+ else
+ begin
+ E:=M.ParentNode as TDomElement;
+ If IsModuleNode(E) then
+ P:=FindModuleNodeInNode(E,FindPackageNode(E.ParentNode as TDomElement))
+ else if IsTopicNode(E) then
+ // Assumes that we can only nest 2 deep inside package node !!
+ P:=FindTopicNodeInNode(E,FindPackageNode(E.ParentNode as TDomElement))
+ else if IsPackageNode(E) then
+ P:=FindPackageNode(E);
+ end;
+ Result:=SubNodeWithElement(P,M);
+ If (Result=Nil) then
+ Raise Exception.CreateFmt(SErrNoNodeForTopic,[M['name']]);
+end;
+
+Function TPackageEditor.FindElementNode(E: TDomElement; N: TfpgTreeNode): TfpgTreeNode;
+
+Var
+ P : TTreeNode;
+
+begin
+ If IsModuleNode(E) then
+ Result:=FModuleNode
+ else
+ begin
+ Result:=Nil;
+ If (N<>Nil) then
+ P:=N
+ else
+ P:=FModuleNode;
+ Result:=SubNodeWithElement(P,E);
+ end;
+end;
+
+Procedure TPackageEditor.AddElement(E : TDomElement);
+
+Var
+ N : TTreeNode;
+
+begin
+ N:=CreateElementNode(E);
+ SetCurrentElementNode(N);
+ FModified:=True;
+end;
+
+
+Procedure TPackageEditor.SetCurrentPackage(Value : TDomElement);
+
+begin
+ if (Value<>CurrentPackage) then
+ begin
+ Inherited;
+ If (Value<>Nil) then
+ SetCurrentPackageNode(FindPackageNode(Value));
+ end;
+end;
+
+Procedure TPackageEditor.SetCurrentPackageNode(N : TfpgTreeNode);
+
+begin
+ FModuleTree.Selected:=N;
+end;
+
+Procedure TPackageEditor.SetCurrentModule(Value : TDomElement);
+begin
+ If (Value<>CurrentModule) then
+ begin
+ Inherited;
+ If Assigned(Value) then
+ SetCurrentModuleNode(FindModuleNodeInNode(Value,Nil))
+ else
+ ClearElements;
+ end;
+end;
+
+Procedure TPackageEditor.SetCurrentModuleNode(N : TfpgTreeNode);
+
+Var
+ P : TTreeNode;
+
+begin
+ P:=FindPackageNode(CurrentPackage);
+ If Assigned(P) then
+ P.Expand(False);
+ FModuleTree.Selected:=N;
+end;
+
+Procedure TPackageEditor.SetCurrentTopic(T : TDomElement);
+
+Var
+ N : TDomElement;
+ PN : TTreeNode;
+
+begin
+ If (CurrentTopic<>T) then
+ begin
+ N:=T.ParentNode as TDomElement;
+ if IsModuleNode(N) then
+ begin
+ CurrentModule:=N;
+ PN:=FindModuleNodeInNode(N,Nil);
+ end
+ else if IsPackageNode(N) then
+ begin
+ CurrentModule:=Nil;
+ CurrentPackage:=N;
+ PN:=FindPackageNode(n);
+ end;
+ SetCurrentTopicNode(FindTopicNodeInNode(T,PN));
+ end;
+ Inherited;
+end;
+
+Procedure TPackageEditor.SetCurrentTopicNode(T : TfpgTreeNode);
+
+begin
+ T.Parent.Expand(False);
+ FModuleTree.Selected:=T;
+ If (CurrentElement<>Nil) then
+ CurrentElement:=Nil;
+end;
+
+procedure TPackageEditor.UpdateNodeImage(N: TfpgTreeNode);
+var
+ ImgIndex: Integer;
+ Node: TDomNode;
+ Element: TDomElement;
+begin
+ if assigned(N) then begin
+
+ Element := TDomElement(N.Data);
+ //DebugElement(Element);
+ if not Assigned(Element) then
+ exit;
+
+ // get image index accoding of element edit state
+ ImgIndex := ImgIndxNew;
+ node := Element.FirstChild;
+ while Assigned(node) do begin
+ if (node.NodeType=ELEMENT_NODE) and node.HasChildNodes then begin
+ if
+ (
+ (node.NodeName = 'short') or
+ (node.NodeName = 'descr') or
+ (node.NodeName = 'sealso') or
+ (node.NodeName = 'example') or
+ (node.NodeName = 'errors')
+ ) then begin
+ ImgIndex := ImgIndxModified;
+ break;
+ end;
+ end;
+ Node := Node.NextSibling;
+ end;
+
+ // assign index to node and propagate status to parent
+ SetNodeImage(N, ImgIndex);
+ end;
+end;
+
+procedure TPackageEditor.SetNodeImage(N: TfpgTreeNode; Index: Integer);
+begin
+ N.ImageIndex := Index;
+ N.SelectedIndex := Index;
+ if Index>ImgIndxEdited then
+ while assigned(N.Parent) do begin
+ N := N.Parent;
+ if N.ImageIndex < ImgIndxEdited then begin
+ N.ImageIndex := ImgIndxEdited;
+ N.SelectedIndex := ImgIndxEdited;
+ end;
+ end;
+end;
+
+Procedure TPackageEditor.SetCurrentElement(E : TDomElement);
+var
+ SelNode:TTreeNode;
+begin
+ If (E<>FCurrentElement) and (E <> nil) then
+ begin
+ Inherited;
+ CurrentModule:=E.ParentNode as TDomElement;
+ SelNode:=FElementTree.Selected;
+ //avoid selecting an already selected node (occurs in OnChange event)
+ if (SelNode = nil) or (SelNode.Data <> Pointer(E)) then
+ SetCurrentElementNode(FindElementNode(E,Nil));
+ end;
+end;
+
+Procedure TPackageEditor.SetCurrentElementNode(N : TfpgTreeNode);
+
+begin
+ FElementTree.Selected:=N;
+end;
+
+end.
+
+