diff options
author | graemeg <graemeg@ae50a9b5-8222-0410-bf8d-8a13f76226bf> | 2008-03-25 20:25:13 +0000 |
---|---|---|
committer | graemeg <graemeg@ae50a9b5-8222-0410-bf8d-8a13f76226bf> | 2008-03-25 20:25:13 +0000 |
commit | e85577cc7d0688a02cf4cc8098405583966add70 (patch) | |
tree | 87d4b6e28b506634ed67c6976090754a56573216 | |
parent | d6c76fb72a83a593a74a62b8d40b2b51546ec13c (diff) | |
download | fpGUI-e85577cc7d0688a02cf4cc8098405583966add70.tar.xz |
* more work on the DocEditor, but still far from having a working product.
-rw-r--r-- | examples/apps/docedit/docedit.lpi | 27 | ||||
-rw-r--r-- | examples/apps/docedit/docedit.lpr | 2 | ||||
-rw-r--r-- | examples/apps/docedit/doceditmsg.pas | 181 | ||||
-rw-r--r-- | examples/apps/docedit/doceditopts.pas | 154 | ||||
-rw-r--r-- | examples/apps/docedit/fpdeutil.pas | 90 | ||||
-rw-r--r-- | examples/apps/docedit/frm_main.pas | 115 | ||||
-rw-r--r-- | examples/apps/docedit/images/node_edit.xpm | 30 | ||||
-rw-r--r-- | examples/apps/docedit/images/node_finished.xpm | 30 | ||||
-rw-r--r-- | examples/apps/docedit/images/node_modified.xpm | 30 | ||||
-rw-r--r-- | examples/apps/docedit/images/node_new.xpm | 29 | ||||
-rw-r--r-- | examples/apps/docedit/model.pas | 198 | ||||
-rw-r--r-- | examples/apps/docedit/pkeditor.pas | 1136 |
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. + + |