pgeditor.pp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900
  1. {$mode objfpc}
  2. {$h+}
  3. unit pgEditor;
  4. interface
  5. uses SysUtils,Classes,gdk,fpgtk,gtk,fpgtkext,dom,xmlread,xmlwrite;
  6. Type
  7. TTagType = (ttBold,ttItalic,ttUnderline,ttParagraph,ttVariable,ttRemark,
  8. ttNumberedList,ttUnnumberedList,ttListItem,ttTable,ttRow,
  9. ttCell,TTHeader,ttPre,ttCode,ttLink,ttFile);
  10. TNodeTreeItem = Class(TFPGtkTreeItem)
  11. Private
  12. FNode : TDomElement;
  13. Public
  14. Constructor Create (ANode : TDomElement); virtual;
  15. Property Node : TDomElement Read Fnode;
  16. Procedure CheckSubTree;
  17. end;
  18. TModuleTreeItem = Class(TNodeTreeItem);
  19. TTopicTreeItem = Class(TNodeTreeItem);
  20. TPackageTreeItem = Class(TNodeTreeItem);
  21. TNodeSelectEvent = Procedure (Sender : TObject; Node : TDomElement) Of Object;
  22. TPackageEditor = Class(TFPGtkVPaned)
  23. Private
  24. FCurrentPackage,
  25. FCurrentElement,
  26. FCurrentModule,
  27. FCurrentTopic : TDomElement;
  28. FOnSelectElement,
  29. FOnSelectPackage,
  30. FOnSelectTopic,
  31. FOnSelectionChanged,
  32. // FOnDeSelectElement,
  33. FOnSelectModule : TNodeSelectEvent;
  34. FDescriptionNode : TDomNode;
  35. FModuleTree : TFPGtkScrollTree;
  36. FElementTree : TFPGtkScrollTree;
  37. FModuleNode : TNodeTreeItem;
  38. FModified : Boolean;
  39. PTMenu,
  40. PMMenu : TFPgtkMenu;
  41. PMNode : TNodeTreeItem;
  42. FTRenameMenu,
  43. FTDeleteMenu,
  44. FRenameMenu,
  45. FDeleteMenu : TFPgtkMenuItem;
  46. Procedure MenuRenameClick(Sender : TFPGtkObject; Data : Pointer);
  47. Procedure MenuDeleteClick(Sender : TFPGtkObject; Data : Pointer);
  48. Function PopupModuleMenu(Sender:TFPgtkWidget; Event:PGdkEventButton; data:pointer): boolean;
  49. Function PopupTopicMenu(Sender:TFPgtkWidget; Event:PGdkEventButton; data:pointer): boolean;
  50. Procedure SelectTopic(Sender : TFPGtkObject; Data : Pointer);
  51. Procedure SelectModule(Sender : TFPGtkObject; Data : Pointer);
  52. Procedure SelectPackage(Sender : TFPGtkObject; Data : Pointer);
  53. Procedure SelectElement(Sender : TFPGtkObject; Data : Pointer);
  54. // Procedure DeSelectElement(Sender : TFPGtkWidget; Data : Pointer);
  55. // Procedure DoSelectionChanged(Sender : TFPGtkWidget; Data : Pointer);
  56. Procedure ShowModuleElements(Module : TDomElement);
  57. Procedure SetCurrentModule(Value : TDomElement);
  58. Procedure SetCurrentPackage(Value : TDomElement);
  59. Function FindPackageNode(P : TDomElement) : TNodeTreeItem;
  60. Function FindModuleNodeInNode(M : TDomElement; N : TNodeTreeItem) : TNodeTreeItem;
  61. Function FindTopicNodeInNode(M : TDomElement; N : TNodeTreeItem) : TNodeTreeItem;
  62. Function FindElementNode(E : TDomElement; N : TNodeTreeItem) : TNodeTreeItem;
  63. Procedure SetCurrentElement(E : TDomElement);
  64. Procedure SetCurrentTopic(T : TDomElement);
  65. Function CreateElementNode(E : TDomelement) : TNodeTreeItem;
  66. Procedure DeletePackage(N : TNodeTreeItem);
  67. Procedure DeleteModule(N : TNodeTreeItem);
  68. Procedure DeleteTopic(N : TNodeTreeItem);
  69. Procedure DeleteElement(N : TNodeTreeItem);
  70. Procedure RenamePackage(N : TNodeTreeItem);
  71. Procedure RenameModule(N : TNodeTreeItem);
  72. Procedure RenameTopic(N : TNodeTreeItem);
  73. Procedure RenameElement(N : TNodeTreeItem);
  74. Function GetSelectedNode : TNodeTreeItem;
  75. Procedure GetNameData(Sender : TFPGtkWindow;Data : Pointer; Action : Integer;Initiator : TFPGtkObject);
  76. Function NewName(ATitle : String;Var AName : String) : Boolean;
  77. Procedure ClearElements;
  78. Public
  79. Constructor Create;
  80. Procedure SetDescriptionNode (Value : TDomNode);
  81. Procedure Refresh;
  82. Procedure AddElement(E : TDomElement);
  83. Procedure DeletePackage(P : TDomElement);
  84. Procedure DeleteModule(M : TDomElement);
  85. Procedure DeleteElement(E : TDomElement);
  86. Procedure DeleteTopic(T : TDomElement);
  87. Procedure RenamePackage(P : TDomElement);
  88. Procedure RenameModule(M : TDomElement);
  89. Procedure RenameElement(E : TDomElement);
  90. Procedure RenameTopic(T : TDomElement);
  91. Property ModuleTree : TFPGtkScrollTree Read FModuleTree;
  92. Property ElementTree : TFPGtkScrollTree Read FElementTree;
  93. Property DescriptionNode : TDomNode Read FDescriptionNode Write SetDescriptionNode;
  94. Property OnSelectModule : TNodeSelectEvent Read FOnSelectModule Write FOnSelectmodule;
  95. Property OnSelectTopic : TNodeSelectEvent Read FOnSelectTopic Write FOnSelectTopic;
  96. Property OnSelectPackage : TNodeSelectEvent Read FOnSelectPackage Write FOnSelectPackage;
  97. // Property OnDeSelectElement : TNodeSelectEvent Read FOnDeSelectElement Write FOnDeSelectElement;
  98. Property OnSelectElement : TNodeSelectEvent Read FOnSelectElement Write FOnSelectElement;
  99. // Property OnSelectionChanged : TNodeSelectEvent Read FOnSelectionChanged Write FOnSelectionChanged;
  100. Property CurrentPackage : TDomElement Read FCurrentPackage Write SetCurrentPackage;
  101. Property CurrentModule : TDomElement Read FCurrentModule Write SetCurrentModule;
  102. Property CurrentTopic : TDomElement Read FCurrentTopic Write SetCurrentTopic;
  103. Property CurrentElement: TDomElement Read FCurrentElement Write SetCurrentElement;
  104. Property Modified : Boolean Read FModified Write FModified;
  105. end;
  106. TElementEditor = Class(TFPGtkVBox)
  107. Private
  108. FExampleNode,
  109. FShortNode,
  110. FDescrNode,
  111. FErrorsNode,
  112. FSeeAlsoNode,
  113. Felement : TDomElement;
  114. FLabel : TFPGtkLabel;
  115. FShortEntry : TFPGtkEntry;
  116. FDescrMemo,
  117. FErrorsMemo,
  118. FSeeAlsoMemo : TFPGtkScrollText;
  119. FExample : TFPGtkEntry;
  120. FCurrentEditable : TFPGtkEditable;
  121. FModified : Boolean;
  122. Procedure GetNodes;
  123. Procedure SetElement (Value : TDomElement);
  124. Function CurrentEditable : TFPGtkEditable;
  125. Function OnEditableFocusIn(Sender : TFPGtkWidget; Event : PGDKEventFocus;Data : Pointer) : Boolean;
  126. Function GetCurrentSelection : String;
  127. Procedure OnTextModified(Sender : TFPGtkObject; Data : Pointer);
  128. Public
  129. Procedure Refresh;
  130. Constructor Create;
  131. Function TestSave(S : String) : Boolean;
  132. Function CurrentXML : String;
  133. Function Save : Boolean;
  134. Procedure DeleteElement;
  135. Procedure InsertTag (tagName : String);
  136. Procedure InsertTag (TagType : TTagType);
  137. Procedure InsertLink(LinkTarget,LinkText : String);
  138. Procedure InsertTable(Cols,Rows : Integer; UseHeader : Boolean);
  139. Property Element : TDomElement Read FElement Write SetElement;
  140. Property CurrentSelection : String Read GetCurrentSelection;
  141. Property Modified : Boolean Read FModified Write FModified;
  142. end;
  143. TEditorPage = Class(TFPGtkHPaned)
  144. Private
  145. FChangingSelection : Boolean;
  146. FFileNameLabel : TFpGtkLabel;
  147. FDocument : TXMLDocument;
  148. FPackages : TPackageEditor;
  149. FElement : TElementEditor;
  150. FFileNAme : String;
  151. Procedure ElementSelected(Sender : TObject; Node : TDomElement) ;
  152. Procedure TopicSelected(Sender : TObject; Node : TDomElement) ;
  153. Procedure ModuleSelected(Sender : TObject; Node : TDomElement) ;
  154. Procedure PackageSelected(Sender : TObject; Node : TDomElement) ;
  155. // Procedure SelectionChanged(Sender : TFPgtkWidget; Node : TDomElement) ;
  156. // Procedure ElementDeSelected(Sender : TObject; Node : TDomElement) ;
  157. Function GetCurrentSelection : String;
  158. Function GetCurrentPackage : TDomElement;
  159. Function GetCurrentModule : TDomElement;
  160. Function GetCurrentTopic : TDomElement;
  161. Function GetCurrentElement : TDomElement;
  162. Procedure SetCurrentModule(Value : TDomElement);
  163. Procedure SetCurrentTopic(Value : TDomElement);
  164. Procedure SetCurrentPackage(Value : TDomElement);
  165. Procedure SetCurrentElement(Value : TDomElement);
  166. Procedure SetModified(Value : Boolean);
  167. Function GetModified : Boolean;
  168. Function MakeBackup(FN : String) : Boolean;
  169. Public
  170. Constructor Create;
  171. Function FirstPackage : TDomElement;
  172. Function FirstModule(APackage : TDomElement) : TDomElement;
  173. Procedure DisplayDocument;
  174. Procedure ClearDocument;
  175. Procedure LoadFromFile(FN : String);
  176. Procedure LoadFromStream(S : TStream);
  177. Procedure SaveToFile(FN : String);
  178. Procedure SetFileName(FN : String);
  179. Procedure InsertTag(TagType : TTagType);
  180. Procedure InsertLink(LinkTarget,LinkText : String);
  181. Procedure InsertTable(Cols,Rows : Integer; UseHeader : Boolean);
  182. Procedure NewPackage(APackageName : String);
  183. Procedure NewModule(AModuleName : String);
  184. Procedure NewTopic(ATopicName : String);
  185. Procedure NewElement(AElementName : String);
  186. Procedure GetElementList(List : TStrings);
  187. Property FileName : String Read FFileName;
  188. Property CurrentSelection : String Read GetCurrentSelection;
  189. Property CurrentPackage : TDomElement Read GetCurrentPackage Write SetCurrentPackage;
  190. Property CurrentModule : TDomElement Read GetCurrentModule Write SetCurrentModule;
  191. Property CurrentTopic : TDomElement Read GetCurrentTopic Write SetCurrentTopic;
  192. Property CurrentElement : TDomElement Read GetCurrentElement Write SetCurrentElement;
  193. Property FileNameLabel : TFPgtkLabel Read FFileNameLabel Write FFileNameLabel;
  194. Property Modified : Boolean Read GetModified Write SetModified;
  195. end;
  196. Const
  197. TagNames : Array[TTagType] of string = ('b','i','u','p','var','remark',
  198. 'ol','ul','li','table','tr',
  199. 'td','th','pre','code','link','file'
  200. );
  201. implementation
  202. uses fpdemsg,frmnewnode,fpdeopts;
  203. { ---------------------------------------------------------------------
  204. TElementEditor
  205. ---------------------------------------------------------------------}
  206. Constructor TElementEditor.Create;
  207. Var
  208. F1,F2 : TFPGtkVPaned;
  209. V : TFPgtkVBox;
  210. L : TFpGtkLabel;
  211. begin
  212. Inherited Create;
  213. FLabel:=TFPgtkLabel.Create(SNoElement);
  214. PackStart(FLabel,False,False,0);
  215. L:=TFPGtkLabel.Create(SShortDescription);
  216. // Short
  217. V:=TFPGtkVBox.Create;
  218. FShortEntry:=TFPGtkEntry.Create;
  219. FShortEntry.ConnectFocusInEvent(@OnEditableFocusIn,Nil);
  220. FShortEntry.ConnectChanged(@OnTextModified,Nil);
  221. V.PackStart(L,False,False,0);
  222. V.PackStart(FShortEntry,True,true,0);
  223. PackStart(V,false,false,0);
  224. // Errors
  225. L:=TFPGtkLabel.Create(SErrors);
  226. V:=TFPGtkVBox.Create;
  227. FErrorsMemo:=TFPGtkScrollText.Create;
  228. FErrorsMemo.TheText.ConnectFocusInEvent(@OnEditableFocusIn,Nil);
  229. FErrorsMemo.TheText.ConnectChanged(@OnTextModified,Nil);
  230. FErrorsMemo.setusize(400,50);
  231. V.PackStart(L,False,False,0);
  232. V.PackStart(FErrorsMemo,True,true,0);
  233. F2:=TFPGtkVPaned.Create;
  234. F2.Pack1(V,True,True);
  235. // See Also
  236. V:=TFPGtkVBox.Create;
  237. L:=TFPGtkLabel.Create(SSeeAlso);
  238. FSeeAlsoMemo:=TFPGtkScrollText.Create;
  239. // FSeeAlsoMemo.TheText.ConnectEnterNotify(@OnEnterEditable,Nil);
  240. FSeeAlsoMemo.TheText.ConnectFocusInEvent(@OnEditableFocusIn,Nil);
  241. FSeeAlsoMemo.TheText.ConnectChanged(@OnTextModified,Nil);
  242. FSeeAlsoMemo.setusize(400,50);
  243. V.PackStart(L,False,False,0);
  244. V.PackStart(FSeeAlsoMemo,True,true,0);
  245. F2.Pack2(V,False,True);
  246. // Descr
  247. L:=TFPGtkLabel.Create(SDescription);
  248. V:=TFPGtkVBox.Create;
  249. FDescrMemo:=TFPGtkScrollText.Create;
  250. // FDescrMemo.TheText.ConnectEnterNotify(@OnEnterEditable,Nil);
  251. FDescrMemo.TheText.ConnectFocusInEvent(@OnEditableFocusIn,Nil);
  252. FDescrMemo.TheText.ConnectChanged(@OnTextModified,Nil);
  253. FDescrMemo.setusize(400,150);
  254. V.PackStart(L,False,False,0);
  255. V.PackStart(FDescrMemo,True,true,0);
  256. F1:=TFPGtkVPaned.Create;
  257. F1.Pack1(V,True,True);
  258. F1.Pack2(F2,False,True);
  259. PackStart(F1,true,true,0);
  260. // Example
  261. V:=TFPGtkVBox.Create;
  262. L:=TFPGtkLabel.Create(SCodeExample);
  263. FExample:=TFPGtkEntry.Create;
  264. FExample.ConnectFocusInEvent(@OnEditableFocusIn,Nil);
  265. FExample.ConnectChanged(@OnTextModified,Nil);
  266. V.PackStart(L,False,False,0);
  267. V.PackStart(FExample,True,true,0);
  268. PackStart(V,false,false,0);
  269. end;
  270. Procedure TElementEditor.SetElement (Value : TDomElement);
  271. begin
  272. // Writeln('Setelement');
  273. If (Value<>FElement) then
  274. If not Modified or Save then
  275. begin
  276. {
  277. If (Value=Nil) then
  278. Writeln('Setelement called with Nil')
  279. else
  280. Writeln('Setelement : ',Value['name']);}
  281. FElement:=Value;
  282. // Writeln('Setelement : Refreshing');
  283. Refresh;
  284. // Writeln('SetElement : Refreshed');
  285. end;
  286. end;
  287. Procedure TElementEditor.DeleteElement;
  288. begin
  289. FElement:=Nil;
  290. Refresh;
  291. end;
  292. Procedure TElementEditor.Refresh;
  293. Var
  294. S : TSTringStream;
  295. Function NodeToString(E : TDomElement) : String;
  296. Var
  297. N : TDomNode;
  298. begin
  299. If (E=Nil) then
  300. Result:=''
  301. else
  302. begin
  303. S.Seek(0,soFromBeginning);
  304. S.Size:=0;
  305. N:=E.FirstChild;
  306. While Assigned(N) do
  307. begin
  308. WriteXml(N,S);
  309. N:=N.NextSibling;
  310. end;
  311. Result:=S.Datastring;
  312. end;
  313. end;
  314. Function RemoveLineFeeds(S : String) : String;
  315. Var
  316. I : Integer;
  317. begin
  318. Result:=S;
  319. For I:=1 to Length(Result) do
  320. If Result[i] in [#10,#13] then
  321. Result[i]:=' ';
  322. end;
  323. begin
  324. GetNodes;
  325. If Assigned(Felement) then
  326. FLabel.Text:=Format(SDataForElement,[FElement['name']])
  327. else
  328. FLabel.Text:=SNoElement;
  329. S:=TStringStream.Create('');
  330. Try
  331. FShortEntry.Text:=RemoveLineFeeds(NodeToString(FShortNode));
  332. FDescrMemo.Text:=NodeToString(FDescrNode);
  333. FErrorsMemo.Text:=NodeToString(FErrorsNode);
  334. FSeeAlsoMemo.Text:=NodeToString(FSeeAlsoNode);
  335. If FExampleNode=Nil then
  336. FExample.Text:=''
  337. else
  338. FExample.Text:=FExampleNode['file'];
  339. FModified:=False;
  340. Finally
  341. S.Free;
  342. end;
  343. end;
  344. Function TElementeditor.TestSave(S : String) : Boolean;
  345. Const
  346. Head = '<?xml version="1.0" encoding="ISO-8859-1"?><fpdoc-descriptions>';
  347. Tail = '</fpdoc-descriptions>';
  348. SErrorSaving = 'There is an error in the documentation nodes:'+LineEnding+
  349. '%s'+LineEnding+
  350. 'Please correct it first and try saving again.';
  351. Var
  352. D : TXMLDocument;
  353. SS : TStringStream;
  354. begin
  355. // Writeln('In testsave');
  356. Result:=Length(S)=0;
  357. If Not Result then
  358. begin
  359. SS:=TStringStream.Create(Head+S+Tail);
  360. Try
  361. Try
  362. ReadXmlFile(D,SS);
  363. Result:=True;
  364. except
  365. On E : Exception do
  366. MessageDlg(SErrorSaving,[E.Message],mtError,[mbOK],0)
  367. end;
  368. finally
  369. D.Free;
  370. SS.Free;
  371. end;
  372. end;
  373. end;
  374. Function TElementEditor.CurrentXML : String;
  375. Function GetNodeString(NodeName,Value : String) : String;
  376. begin
  377. Result:='';
  378. If (Value<>'') Then
  379. Result:=Format('<%s>%s</%s>',[NodeName,Value,NodeName])
  380. else If Not SkipEmptyNodes then
  381. result:='<'+NodeName+'/>';
  382. end;
  383. Var
  384. S : String;
  385. begin
  386. // Writeln('In currentxml');
  387. Result:='';
  388. If Not Assigned(FElement) then
  389. Exit;
  390. Result:=GetNodeString('short',Trim(FShortEntry.Text));
  391. Result:=Result+GetNodeString('descr',trim(FDescrMemo.Text));
  392. Result:=Result+GetNodeString('errors',trim(FErrorsMemo.Text));
  393. Result:=Result+GetNodeString('seealso',trim(FSeeAlsoMemo.Text));
  394. S:=Trim(FExample.Text);
  395. If (S<>'') then
  396. Result:=Result+'<example file="'+S+'"/>';
  397. // Writeln('Currentxml : ',Result);
  398. end;
  399. Function TElementEditor.Save : Boolean;
  400. Var
  401. SS : TStringStream;
  402. S : String;
  403. N,NN : TDomNode;
  404. begin
  405. Result:=False;
  406. S:=CurrentXML;
  407. If TestSave(S) then
  408. begin
  409. // Writeln('Saving data');
  410. SS:=TStringStream.Create(S);
  411. Try
  412. // Free child nodes.
  413. N:=FElement.FirstChild;
  414. While N<>Nil do
  415. begin
  416. NN:=N.NextSibling;
  417. If not ((N is TDomElement) and (N.NodeName='element')) then
  418. FElement.RemoveChild(N);
  419. N:=NN;
  420. end;
  421. // Read them again from stream.
  422. SS.Seek(0,soFromBeginning);
  423. ReadXMLFragment(FElement,SS);
  424. FModified:=False;
  425. Result:=True;
  426. // Writeln('Data saved');
  427. Finally
  428. SS.Free;
  429. end;
  430. end;
  431. end;
  432. Procedure TElementEditor.InsertTag (tagName : String);
  433. Var
  434. PB,PE : Integer;
  435. begin
  436. If Assigned(CurrentEditable) then
  437. With CurrentEditable do
  438. begin
  439. PB:=SelectionStart;
  440. PE:=SelectionEnd;
  441. InsertText('</'+TagName+'>',PE);
  442. InsertText('<'+TagName+'>',PB);
  443. SelectionStart:=PB+Length(TagName)+2;
  444. FModified:=True;
  445. end;
  446. end;
  447. Procedure TElementEditor.InsertTag(TagType : TTagType);
  448. begin
  449. InsertTag(TagNames[TagTYpe]);
  450. end;
  451. Procedure TElementEditor.InsertLink(LinkTarget,LinkText : String);
  452. begin
  453. If CurrentEditable<>Nil then
  454. With CurrentEditable do
  455. begin
  456. If (LinkText<>'') then
  457. Selection:='<link id="'+LinkTarget+'">'+LinkText+'</link>'
  458. else
  459. Selection:='<link id="'+LinkTarget+'"/>';
  460. end;
  461. end;
  462. Procedure TElementEditor.InsertTable(Cols,Rows : Integer; UseHeader : Boolean);
  463. Var
  464. I,J : Integer;
  465. R,T : String;
  466. begin
  467. If (CurrentEditable=FDescrMemo.TheText) or
  468. (CurrentEditable=FErrorsMemo.TheText) then
  469. begin
  470. R:='<tr>';
  471. For I:=1 to Cols do
  472. R:=R+'<td></td>';
  473. R:=R+'</tr>'+lineEnding;
  474. T:='';
  475. If UseHeader then
  476. begin
  477. Dec(Rows);
  478. T:='<th>';
  479. For I:=1 to Cols do
  480. T:=T+'<td></td>';
  481. T:=T+'</th>'+lineEnding;
  482. end;
  483. For I:=1 to rows do
  484. T:=T+R;
  485. T:=LineEnding+'<table>'+LineEnding+T+'</table>'+LineEnding;
  486. With CurrentEditable do
  487. Selection:=t;
  488. end;
  489. end;
  490. Procedure TElementEditor.GetNodes;
  491. Var
  492. Node : TDomNode;
  493. S : String;
  494. begin
  495. FShortNode:=Nil;
  496. FDescrNode:=Nil;
  497. FErrorsNode:=Nil;
  498. FSeeAlsoNode:=Nil;
  499. FExampleNode:=Nil;
  500. If Assigned(FElement) then
  501. begin
  502. Node:=FElement.FirstChild;
  503. While Assigned(Node) do
  504. begin
  505. If (Node.NodeType=ELEMENT_NODE) then
  506. begin
  507. S:=Node.NodeName;
  508. If S='short' then
  509. FShortNode:=TDomElement(Node)
  510. else if S='descr' then
  511. FDescrNode:=TDomElement(Node)
  512. else if S='errors' then
  513. FErrorsNode:=TDomElement(Node)
  514. else if S='seealso' then
  515. FSeeAlsoNode:=TDomElement(Node)
  516. else if S='example' then
  517. FExampleNode:=TDomElement(Node);
  518. end;
  519. Node:=Node.NextSibling;
  520. end;
  521. end;
  522. end;
  523. Function TElementEditor.CurrentEditable : TFPGtkEditable;
  524. begin
  525. Result:=FCurrentEditable;
  526. end;
  527. Function TElementEditor.OnEditableFocusIn(Sender : TFPGtkWidget; Event : PGDKEventFocus;Data : Pointer) : Boolean;
  528. begin
  529. FCurrentEditable:=Sender as TFPGtkEditable;
  530. Result:=False;
  531. end;
  532. Procedure TElementEditor.OnTextModified(Sender : TFPGtkObject; Data : Pointer);
  533. begin
  534. FModified:=True;
  535. end;
  536. Function TElementEditor.GetCurrentSelection : String;
  537. begin
  538. If CurrentEditable=Nil then
  539. begin
  540. // Writeln('No current editable');
  541. Result:=''
  542. end
  543. else
  544. Result:=CurrentEditable.Selection;
  545. end;
  546. { ---------------------------------------------------------------------
  547. TNodeTreeItem
  548. ---------------------------------------------------------------------}
  549. Constructor TNodeTreeItem.Create (ANode : TDomElement);
  550. begin
  551. Inherited Create;
  552. FNode:=Anode;
  553. Text:=ANode['name'];
  554. end;
  555. Procedure TNodeTreeItem.CheckSubTree;
  556. begin
  557. If (SubTree=Nil) then
  558. SubTree:=TFPgtkTree.Create;
  559. end;
  560. { ---------------------------------------------------------------------
  561. TPackageEditor
  562. ---------------------------------------------------------------------}
  563. Constructor TPackageEditor.Create;
  564. begin
  565. Inherited;
  566. FModuleTree:=TFPGtkScrollTree.Create;
  567. FElementTree:=TFPGtkScrollTree.Create;
  568. // FelementTree.Tree.ConnectSelectionChanged(@DoSelectionChanged,Nil);
  569. PMMenu:=TFPgtkMenu.Create;
  570. FRenameMenu:=NewMenuItem(SMenuRename,'','',@MenuRenameClick,Nil);
  571. FDeleteMenu:=NewMenuItem(SMenuDelete,'','',@MenuDeleteClick,Nil);
  572. PMMenu.Append(FRenameMenu);
  573. PMMenu.Append(FDeleteMenu);
  574. Add1(FModuleTree);
  575. Add2(FElementTree);
  576. PTMenu:=TFPgtkMenu.Create;
  577. FTRenameMenu:=NewMenuItem(SMenuRename,'','',@MenuRenameClick,Nil);
  578. FTDeleteMenu:=NewMenuItem(SMenuDelete,'','',@MenuDeleteClick,Nil);
  579. PTMenu.Append(FTRenameMenu);
  580. PTMenu.Append(FTDeleteMenu);
  581. end;
  582. function TPackageEditor.PopupModuleMenu(Sender:TFPgtkWidget; Event:PGdkEventButton; data:pointer): boolean;
  583. begin
  584. PMNode:=Sender as TNodeTreeItem;
  585. Result:=(event^.thetype=GDK_BUTTON_PRESS) and (event^.button=3);
  586. If Result then
  587. PMMenu.Popup(3);
  588. end;
  589. function TPackageEditor.PopupTopicMenu(Sender:TFPgtkWidget; Event:PGdkEventButton; data:pointer): boolean;
  590. begin
  591. PMNode:=Sender as TNodeTreeItem;
  592. Result:=(event^.thetype=GDK_BUTTON_PRESS) and (event^.button=3);
  593. If Result then
  594. PTMenu.Popup(3);
  595. end;
  596. Procedure TPackageEditor.SetDescriptionNode (Value : TDomNode);
  597. begin
  598. FDescriptionNode:=Value;
  599. Refresh;
  600. end;
  601. {Procedure TPackageEditor.DoSelectionChanged(Sender : TFPGtkWidget; Data : Pointer);
  602. Var
  603. N : TNodeTreeItem;
  604. E : TDomElement;
  605. begin
  606. // Writeln('In doselectionchanged');
  607. If Assigned(FOnSelectionChanged) Then
  608. begin
  609. // Writeln('Getting selected node');
  610. N:=GetSelectedNode;
  611. If N<>Nil then
  612. E:=N.Node
  613. else
  614. E:=Nil;
  615. FOnSelectionChanged(Sender,E);
  616. end;
  617. end;
  618. }
  619. Procedure TPackageEditor.SelectModule(Sender : TFPGtkObject; Data : Pointer);
  620. Var
  621. W : TFPGtkWidget;
  622. begin
  623. FCurrentElement:=Nil;
  624. FCurrentTopic:=Nil;
  625. FCurrentModule:=TDomElement(Data);
  626. FCurrentPackage:=FCurrentModule.ParentNode as TDomElement;
  627. ShowModuleElements(FCurrentModule);
  628. If Assigned(FOnSelectModule) then
  629. FOnSelectModule(Self,FCurrentModule);
  630. end;
  631. Procedure TPackageEditor.SelectPackage(Sender : TFPGtkObject; Data : Pointer);
  632. begin
  633. FCurrentElement:=Nil;
  634. FCurrentModule:=Nil;
  635. FCurrentTopic:=Nil;
  636. FCurrentPackage:=TDomElement(Data);
  637. If Assigned(FOnSelectPackage) then
  638. FOnSelectPackage(Self,FCurrentPackage);
  639. end;
  640. Procedure TPackageEditor.SelectTopic(Sender : TFPGtkObject; Data : Pointer);
  641. Var
  642. P : TDomElement;
  643. begin
  644. FCurrentTopic:=TDomElement(Data);
  645. P:=FCurrentTopic.ParentNode as TDomElement;
  646. if P.NodeName='module' then
  647. CurrentModule:=P
  648. else if P.NodeName='topic' then
  649. CurrentPackage:=P.ParentNode as TDomElement
  650. else if P.NodeName='package' then
  651. CurrentPackage:=p
  652. else
  653. Raise Exception.CreateFmt(SErrUnknownDomElement,[P.NodeName]);
  654. If Assigned(FOnSelectTopic) then
  655. FOnSelectPackage(Self,FCurrentTopic);
  656. end;
  657. Function TPackageEditor.GetSelectedNode : TNodeTreeItem;
  658. Var
  659. G : TFPgtkGroup;
  660. begin
  661. G:=TFPgtkGroup.Create;
  662. try
  663. FModuleTree.Tree.GetSelection(G);
  664. If G.Count>0 then
  665. try
  666. Result:=TObject(G[0]) as TNodeTreeItem;
  667. except
  668. Result:=Nil;
  669. end
  670. else
  671. Result:=Nil;
  672. finally
  673. G.Free;
  674. end;
  675. // Writeln('Getselectednode done');
  676. end;
  677. Procedure TPackageEditor.MenuRenameClick(Sender : TFPGtkObject; Data : Pointer);
  678. Var
  679. N : TNodeTreeItem;
  680. E : TDomElement;
  681. begin
  682. N:=PMNode;
  683. If (N<>Nil) then
  684. If N.Node.NodeName='package' then
  685. RenamePackage(N)
  686. Else if N.Node.NodeName='module' then
  687. RenameModule(N)
  688. Else if N.Node.NodeName='topic' then
  689. RenameTopic(N)
  690. else if N.Node.NodeName='element' then
  691. RenameElement(N)
  692. end;
  693. Procedure TPackageEditor.MenuDeleteClick(Sender : TFPGtkObject; Data : Pointer);
  694. Var
  695. N : TNodeTreeItem;
  696. E : TDomElement;
  697. begin
  698. N:=PMNode;
  699. If (N<>Nil) then
  700. If N.Node.NodeName='package' then
  701. DeletePackage(N)
  702. Else if N.Node.NodeName='module' then
  703. DeleteModule(N)
  704. Else if N.Node.NodeName='topic' then
  705. DeleteTopic(N)
  706. else if N.Node.NodeName='element' then
  707. DeleteElement(N);
  708. end;
  709. Procedure TPackageEditor.DeletePackage(N : TNodeTreeItem);
  710. begin
  711. If (Not ConfirmDelete) or
  712. (MessageDlg(SDeletePackage,[N.Node['name']],mtConfirmation,mbYesNo,0)=mrYes) then
  713. begin
  714. N.Node.ParentNode.RemoveChild(N.Node);
  715. Refresh;
  716. FModified:=True;
  717. end;
  718. end;
  719. Procedure TPackageEditor.DeleteModule(N : TNodeTreeItem);
  720. begin
  721. If (Not ConfirmDelete) or
  722. (MessageDlg(SDeleteModule,[N.Node['name']],mtConfirmation,mbYesNo,0)=mrYes) then
  723. begin
  724. N.Node.ParentNode.RemoveChild(N.Node);
  725. Refresh;
  726. FModified:=True;
  727. end;
  728. end;
  729. Procedure TPackageEditor.DeleteTopic(N : TNodeTreeItem);
  730. begin
  731. If (Not ConfirmDelete) or
  732. (MessageDlg(SDeleteTopic,[N.Node['name']],mtConfirmation,mbYesNo,0)=mrYes) then
  733. begin
  734. N.Node.ParentNode.RemoveChild(N.Node);
  735. Refresh;
  736. FModified:=True;
  737. end;
  738. end;
  739. Procedure TPackageEditor.GetNameData(Sender : TFPGtkWindow;Data : Pointer; Action : Integer;Initiator : TFPGtkObject);
  740. type
  741. PString = ^AnsiString;
  742. begin
  743. With (Sender as TNewNodeForm) do
  744. PString(Data)^:=FENodeName.Text;
  745. end;
  746. Function TPackageEditor.NewName(ATitle : String;Var AName : String) : Boolean;
  747. Var
  748. S : String;
  749. begin
  750. With TNewNodeForm.Create do
  751. begin
  752. Title:=ATitle;
  753. FENodeName.Text:=AName;
  754. Result:=Execute(Nil,@S,@GetNameData)=drOK;
  755. If Result Then
  756. AName:=S;
  757. end;
  758. end;
  759. Procedure TPackageEditor.RenamePackage(N : TNodeTreeItem);
  760. Var
  761. S : String;
  762. begin
  763. S:=N.Node['name'];
  764. If NewName(SRenamePackage,S) then
  765. begin
  766. N.Node['name']:=S;
  767. N.Text:=S;
  768. FModified:=True;
  769. end;
  770. end;
  771. Procedure TPackageEditor.RenameModule(N : TNodeTreeItem);
  772. Var
  773. S : String;
  774. begin
  775. S:=N.Node['name'];
  776. If NewName(SRenameModule,S) then
  777. begin
  778. N.Node['name']:=S;
  779. N.Text:=S;
  780. FModified:=True;
  781. end;
  782. end;
  783. Procedure TPackageEditor.RenameTopic(N : TNodeTreeItem);
  784. Var
  785. S : String;
  786. begin
  787. S:=N.Node['name'];
  788. If NewName(SRenameTopic,S) then
  789. begin
  790. N.Node['name']:=S;
  791. N.Text:=S;
  792. FModified:=True;
  793. end;
  794. end;
  795. Procedure TPackageEditor.RenameElement(N : TNodeTreeItem);
  796. Var
  797. S : String;
  798. begin
  799. S:=N.Node['name'];
  800. If NewName(SRenameElement,S) then
  801. begin
  802. N.Node['name']:=S;
  803. N.Text:=S;
  804. FModified:=True;
  805. end;
  806. end;
  807. Procedure TPackageEditor.SelectElement (Sender : TFPGtkObject; Data : Pointer);
  808. begin
  809. FCurrentElement:=TDomElement(Data);
  810. If Assigned(FOnSelectElement) then
  811. FOnSelectElement(Self,FCurrentElement);
  812. end;
  813. {
  814. Procedure TPackageEditor.DeSelectElement(Sender : TFPGtkWidget; Data : Pointer);
  815. Var
  816. M : TDomElement;
  817. begin
  818. // Writeln('In Deselectelement');
  819. M:=TDomElement(Data);
  820. If Assigned(FOnDeSelectElement) then
  821. FOnDeSelectElement(Self,M);
  822. end;
  823. }
  824. Function TPackageEditor.CreateElementNode(E : TDomelement) : TNodeTreeItem;
  825. begin
  826. Result:=TNodeTreeItem.Create(E);
  827. Result.ConnectSelect(@SelectElement,E);
  828. if (E.NodeName='element') then
  829. Result.ConnectButtonPressEvent(@PopupModuleMenu,Nil);
  830. // Result.ConnectDeselect(@DeselectElement,E);
  831. end;
  832. Procedure TPackageEditor.DeleteElement(N : TNodeTreeItem);
  833. Var
  834. Reposition : Boolean;
  835. Index : Integer;
  836. begin
  837. Reposition:=(N.Node=CurrentElement);
  838. With (FModuleNode.Subtree as TFPgtkTree) do
  839. begin
  840. Index:=ChildPosition(N);
  841. Remove(N);
  842. FModified:=True;
  843. If Reposition then
  844. SelectItem(Index);
  845. end;
  846. end;
  847. Procedure TPackageEditor.DeleteElement(E : TDomElement);
  848. Var
  849. N : TNodeTreeItem;
  850. begin
  851. N:=FindElementNode(E,Nil);
  852. If (N<>Nil) then
  853. DeleteElement(N);
  854. end;
  855. Procedure TPackageEditor.DeletePackage(P : TDomElement);
  856. Var
  857. N : TNodeTreeItem;
  858. begin
  859. N:=FindPackageNode(P);
  860. If N<>NIl then
  861. DeletePackage(N);
  862. end;
  863. Procedure TPackageEditor.DeleteModule(M : TDomElement);
  864. Var
  865. N : TNodeTreeItem;
  866. begin
  867. N:=FindModuleNodeInNode(M,Nil);
  868. If N<>NIl then
  869. DeleteModule(N);
  870. end;
  871. Procedure TPackageEditor.DeleteTopic(T : TDomElement);
  872. Var
  873. N : TNodeTreeItem;
  874. begin
  875. N:=FindTopicNodeInNode(T,Nil);
  876. If N<>NIl then
  877. DeleteTopic(N);
  878. end;
  879. Procedure TPackageEditor.RenamePackage(P : TDomElement);
  880. Var
  881. N : TNodeTreeItem;
  882. begin
  883. N:=FindPackageNode(P);
  884. If N<>NIl then
  885. RenamePackage(N);
  886. end;
  887. Procedure TPackageEditor.RenameModule(M : TDomElement);
  888. Var
  889. N : TNodeTreeItem;
  890. begin
  891. N:=FindModuleNodeInNode(M,Nil);
  892. If N<>NIl then
  893. RenameModule(N);
  894. end;
  895. Procedure TPackageEditor.RenameTopic(T : TDomElement);
  896. Var
  897. N : TNodeTreeItem;
  898. begin
  899. N:=FindTopicNodeInNode(T,Nil);
  900. If N<>NIl then
  901. RenameTopic(N);
  902. end;
  903. Procedure TPackageEditor.RenameElement(E : TDomElement);
  904. Var
  905. N : TNodeTreeItem;
  906. begin
  907. N:=FindElementNode(E,Nil);
  908. If N<>NIl then
  909. RenameElement(N);
  910. end;
  911. Procedure TPackageEditor.ClearElements;
  912. begin
  913. FElementTree.Tree.ClearItems(0,-1);
  914. end;
  915. Procedure TPackageEditor.ShowModuleElements(Module : TDomElement);
  916. Var
  917. Node : TDomNode;
  918. ETreeNode : TNodeTreeItem;
  919. S : TStringList;
  920. I : Integer;
  921. begin
  922. ClearElements;
  923. If Assigned(Module) then
  924. begin
  925. FModuleNode:=CreateElementNode(Module);
  926. FElementTree.Tree.Append(FModuleNode);
  927. FModuleNode.Show;
  928. FModuleNode.SubTree:=TFPGtkTree.Create;
  929. S:=TStringList.Create;
  930. Try
  931. S.Sorted:=True;
  932. Node:=Module.FirstChild;
  933. While Assigned(Node) do
  934. begin
  935. If (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='element') then
  936. begin
  937. ETreeNode:=CreateElementNode(TDomElement(Node));
  938. S.AddObject(TDomElement(Node)['name'],ETreeNode);
  939. end;
  940. Node:=Node.NextSibling;
  941. end;
  942. For I:=0 to S.Count-1 do
  943. begin
  944. ETreeNode:=TNodeTreeItem(S.Objects[i]);
  945. (FModuleNode.SubTree as TFPgtKTree).Append(ETreeNode);
  946. //ETreeNode.Show;
  947. end;
  948. Finally
  949. S.Free;
  950. end;
  951. FModuleNode.Expand;
  952. // NOT (!!) FModuleNode.Select; this cannot be undone...
  953. FElementTree.Tree.SelectChild(FModuleNode);
  954. end;
  955. FelementTree.Tree.SelectionMode:=GTK_SELECTION_BROWSE;
  956. end;
  957. Procedure TPackageEditor.Refresh;
  958. Procedure DoTopicNode(Node : TDomElement;Parent : TNodeTreeItem);
  959. Var
  960. TTreeNode : TTopicTreeItem;
  961. SubNode : TDomNode;
  962. begin
  963. TTreeNode:=TTopicTreeItem.Create(TDomElement(Node));
  964. TTreeNode.ConnectSelect(@SelectTopic,Node);
  965. TTreeNode.ConnectButtonPressEvent(@PopupTopicMenu,Nil);
  966. Parent.CheckSubtree;
  967. TFPGtkTree(Parent.SubTree).Append(TTreeNode);
  968. TTreeNode.Show;
  969. SubNode:=Node.FirstChild;
  970. While (SubNode<>Nil) do
  971. begin
  972. If (SubNode.NodeType=ELEMENT_NODE) and (SubNode.NodeName='topic') then
  973. DoTopicNode(SubNode as TDomElement,TtreeNode);
  974. SubNode:=SubNode.NextSibling;
  975. end;
  976. end;
  977. var
  978. Node,SubNode,SSnode : TDomNode;
  979. FTreeNode : TPackageTreeItem;
  980. MTreeNode: TModuleTreeItem;
  981. begin
  982. FModuleTree.Tree.ClearItems(0,-1);
  983. If Assigned(FDescriptionNode) then
  984. begin
  985. Node:=FDescriptionNode.FirstChild;
  986. While Assigned(Node) do
  987. begin
  988. If (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='package') then
  989. begin
  990. FTreeNode:=TPackageTreeItem.Create(TDomElement(Node));
  991. FTreeNode.ConnectSelect(@Selectpackage,Node);
  992. FTreeNode.ConnectButtonPressEvent(@PopupModuleMenu,Nil);
  993. FModuleTree.Tree.Append(FTreeNode);
  994. FTreeNode.Show;
  995. SubNode:=Node.FirstChild;
  996. While Assigned(SubNode) do
  997. begin
  998. If (SubNode.NodeType=ELEMENT_NODE) and (SubNode.NodeName='module') then
  999. begin
  1000. MTreeNode:=TModuleTreeItem.Create(TDomElement(SubNode));
  1001. MtreeNode.ConnectSelect(@SelectModule,SubNode);
  1002. MTreeNode.ConnectButtonPressEvent(@PopupModuleMenu,Nil);
  1003. FTreeNode.CheckSubtree;
  1004. TFPGtkTree(FTreeNode.SubTree).Append(MTreeNode);
  1005. //MTreeNode.Show;
  1006. SSNode:=SubNode.FirstChild;
  1007. While (SSNode<>Nil) do
  1008. begin
  1009. if (SSNode.NodeType=ELEMENT_NODE) and (SSNode.NodeName='topic') then
  1010. DoTopicNode(SSNode as TDomElement,MTreeNode);
  1011. SSNode:=SSNode.NextSibling;
  1012. end;
  1013. end
  1014. else if (SubNode.NodeType=ELEMENT_NODE) and (SubNode.NodeName='topic') then
  1015. begin
  1016. DoTopicNode(SubNode as TDomElement,FTreeNode);
  1017. end;
  1018. SubNode:=SubNode.NextSibling;
  1019. end;
  1020. end;
  1021. Node:=Node.NextSibling;
  1022. end;
  1023. end;
  1024. CurrentModule:=Nil;
  1025. FModified:=False;
  1026. end;
  1027. Function TPackageEditor.FindPackageNode(P : TDomElement) : TNodeTreeItem;
  1028. Var
  1029. N : TNodeTreeItem;
  1030. G : TFPgtkWidgetGroup;
  1031. I : Integer;
  1032. begin
  1033. Result:=Nil;
  1034. G:=FModuleTree.Tree.Children;
  1035. I:=0;
  1036. While (Result=Nil) and (I<G.Count) do
  1037. begin
  1038. If G.Items[i] is TNodeTreeItem then
  1039. begin
  1040. If TNodeTreeItem(G.items[i]).Node=P then
  1041. Result:=TNodeTreeItem(G.items[i]);
  1042. end
  1043. else
  1044. Writeln('Child ',i,' of tree is not a node :',G.Items[i].ClassName);
  1045. Inc(I);
  1046. end;
  1047. If (Result=Nil) then
  1048. Raise Exception.CreateFmt(SErrNoNodeForPackage,[P['name']]);
  1049. end;
  1050. Function TPackageEditor.FindModuleNodeInNode(M : TDomElement; N : TNodeTreeItem) : TNodeTreeItem;
  1051. Var
  1052. SN : TNodeTreeItem;
  1053. G : TFPgtkWidgetGroup;
  1054. I : Integer;
  1055. begin
  1056. Result:=Nil;
  1057. If (N<>Nil) then
  1058. SN:=N
  1059. else
  1060. SN:=FindPackageNode(M.ParentNode as TDomElement);
  1061. If Assigned(SN) and Assigned(SN.SubTree) Then
  1062. begin
  1063. G:=(SN.SubTree as TFpGtkTree).Children;
  1064. I:=0;
  1065. While (Result=Nil) and (I<G.Count) do
  1066. begin
  1067. If G.Items[i] is TNodeTreeItem then
  1068. begin
  1069. If TNodeTreeItem(G.items[i]).Node=M then
  1070. Result:=TNodeTreeItem(G.items[i]);
  1071. end
  1072. else
  1073. Writeln('Child ',i,' of tree is not a node :',G.Items[i].ClassName);
  1074. Inc(I);
  1075. end;
  1076. end;
  1077. If (Result=Nil) then
  1078. Raise Exception.CreateFmt(SErrNoNodeForModule,[M['name']]);
  1079. end;
  1080. Function TPackageEditor.FindTopicNodeInNode(M : TDomElement; N : TNodeTreeItem) : TNodeTreeItem;
  1081. Var
  1082. SN : TNodeTreeItem;
  1083. G : TFPgtkWidgetGroup;
  1084. I : Integer;
  1085. E : TDomElement;
  1086. PN : String;
  1087. begin
  1088. Result:=Nil;
  1089. If (N<>Nil) then
  1090. SN:=N
  1091. else
  1092. begin
  1093. E:=M.ParentNode as TDomElement;
  1094. PN:=(E.NodeName);
  1095. if PN='module' then
  1096. SN:=FindModuleNodeInNode(E,FindPackageNode(E.ParentNode as TDomElement))
  1097. else if PN='topic' then
  1098. // Assumes that we can only nest 2 deep inside package node.
  1099. SN:=FindTopicNodeInNode(E,FindPackageNode(E.ParentNode as TDomElement))
  1100. else if (PN='package') then
  1101. SN:=FindPackageNode(E);
  1102. end;
  1103. If Assigned(SN) and Assigned(SN.SubTree) Then
  1104. begin
  1105. G:=(SN.SubTree as TFpGtkTree).Children;
  1106. I:=0;
  1107. While (Result=Nil) and (I<G.Count) do
  1108. begin
  1109. If G.Items[i] is TNodeTreeItem then
  1110. begin
  1111. If TNodeTreeItem(G.items[i]).Node=M then
  1112. Result:=TNodeTreeItem(G.items[i]);
  1113. end
  1114. else
  1115. Writeln('Child ',i,' of tree is not a node :',G.Items[i].ClassName);
  1116. Inc(I);
  1117. end;
  1118. end;
  1119. If (Result=Nil) then
  1120. Raise Exception.CreateFmt(SErrNoNodeForModule,[M['name']]);
  1121. end;
  1122. Function TPackageEditor.FindElementNode(E : TDomElement; N : TNodeTreeItem) : TNodeTreeItem;
  1123. Var
  1124. SN : TNodeTreeItem;
  1125. G : TFPgtkWidgetGroup;
  1126. I : Integer;
  1127. begin
  1128. Result:=Nil;
  1129. If (N<>Nil) then
  1130. SN:=N
  1131. else
  1132. SN:=FModuleNode; // FindModuleNodeInNode(E.ParentNode as TDomElement,Nil);
  1133. If E.NodeName='module' then
  1134. Result:=FModuleNode
  1135. else If Assigned(SN) and Assigned(SN.SubTree) Then
  1136. begin
  1137. G:=(SN.SubTree as TFpGtkTree).Children;
  1138. I:=0;
  1139. While (Result=Nil) and (I<G.Count) do
  1140. begin
  1141. If G.Items[i] is TNodeTreeItem then
  1142. begin
  1143. If TNodeTreeItem(G.items[i]).Node=E then
  1144. Result:=TNodeTreeItem(G.items[i]);
  1145. end
  1146. else
  1147. Writeln('Child ',i,' of tree is not a node :',G.Items[i].ClassName);
  1148. Inc(I);
  1149. end;
  1150. end;
  1151. If (Result=Nil) then
  1152. Raise Exception.CreateFmt(SErrNoNodeForElement,[E['name']]);
  1153. end;
  1154. Procedure TPackageEditor.AddElement(E : TDomElement);
  1155. Var
  1156. N : TNodeTreeItem;
  1157. begin
  1158. // Writeln('Adding element ',E['name']);
  1159. N:=CreateElementNode(E);
  1160. // Writeln('Appending node element ',N.Node['name']);
  1161. (FModuleNode.Subtree as TFpGtKTree).Append(N);
  1162. // Writeln('Setting current node');
  1163. CurrentElement:=E;
  1164. FModified:=True;
  1165. end;
  1166. Procedure TPackageEditor.SetCurrentElement(E : TDomElement);
  1167. Var
  1168. N : TNodeTreeItem;
  1169. begin
  1170. // Writeln('In setcurrentelement');
  1171. If (E<>FCurrentElement) then
  1172. begin
  1173. If Assigned(FCurrentElement) then
  1174. begin
  1175. N:=FindElementNode(FCurrentElement,Nil);
  1176. If Assigned(N) then
  1177. N.Deselect;
  1178. end;
  1179. CurrentModule:=E.ParentNode as TDomElement;
  1180. N:=FindElementNode(E,Nil);
  1181. if Assigned(N) then
  1182. With (FModuleNode.Subtree as TFPgtkTree) do
  1183. SelectChild(N);
  1184. end;
  1185. end;
  1186. Procedure TPackageEditor.SetCurrentModule(Value : TDomElement);
  1187. Var
  1188. N1,N2 : TNodeTreeItem;
  1189. begin
  1190. If (FCurrentModule<>Value) then
  1191. begin
  1192. FCurrentModule:=Value;
  1193. If Assigned(Value) then
  1194. begin
  1195. FCurrentPackage:=Value.ParentNode as TDomElement;
  1196. N1:=FindPackageNode(FCurrentPackage);
  1197. N1.Expand;
  1198. N2:=FindModuleNodeInNode(FCurrentModule,N1);
  1199. (N1.SubTree as TFPgtkTree).SelectChild(N2);
  1200. end
  1201. Else
  1202. ClearElements;
  1203. end;
  1204. end;
  1205. Procedure TPackageEditor.SetCurrentTopic(T : TDomElement);
  1206. Var
  1207. N : TDomElement;
  1208. PI,NI : TNodeTreeItem;
  1209. begin
  1210. If (FCurrentTopic<>T) then
  1211. begin
  1212. FCurrentElement:=Nil;
  1213. FCurrentTopic:=T;
  1214. If Assigned(T) then
  1215. begin
  1216. // Writeln('clearing current element');
  1217. If (CurrentElement<>Nil) then
  1218. CurrentElement:=Nil;
  1219. // Writeln('checking parent node');
  1220. N:=T.ParentNode as TDomElement;
  1221. If N.NodeName='topic' then
  1222. begin
  1223. // Writeln('Parent is topic');
  1224. N:=N.ParentNode as TDomElement;
  1225. PI:=FindTopicNodeInNode(N,Nil);
  1226. end;
  1227. if N.NodeName='module' then
  1228. begin
  1229. // Writeln('Parent is module');
  1230. CurrentModule:=N;
  1231. N:=N.ParentNode as TDomElement;
  1232. PI:=FindModuleNodeInNode(N,Nil);
  1233. end
  1234. else if N.NodeName='package' then
  1235. begin
  1236. // Writeln('Parent is package ?');
  1237. CurrentModule:=Nil;
  1238. CurrentPackage:=N;
  1239. PI:=FindPackageNode(N)
  1240. end
  1241. { else
  1242. Writeln('Unknown parent node')}
  1243. ;
  1244. NI:=FindTopicNodeInNode(T,PI);
  1245. If Assigned(PI) then
  1246. begin
  1247. // Writeln('Expanding parent node');
  1248. PI.Expand;
  1249. If Assigned(PI.Subtree) and Assigned(NI) then
  1250. begin
  1251. // Writeln('Selecting subnode');
  1252. (PI.SubTree as TFPgtkTree).SelectChild(NI);
  1253. end;
  1254. end;
  1255. end;
  1256. end;
  1257. end;
  1258. Procedure TPackageEditor.SetCurrentPackage(Value : TDomElement);
  1259. Var
  1260. N : TNodeTreeItem;
  1261. begin
  1262. FCurrentPackage:=Value;
  1263. N:=FindPackageNode(Value);
  1264. N.Expand;
  1265. N.Select;
  1266. end;
  1267. { ---------------------------------------------------------------------
  1268. TPageEditor
  1269. ---------------------------------------------------------------------}
  1270. Constructor TEditorPage.Create;
  1271. begin
  1272. Inherited Create;
  1273. FPackages:=TPackageEditor.Create;
  1274. FElement:=TElementEditor.Create;
  1275. // Fpackages.OnSelectionChanged:=@SelectionChanged;
  1276. FPackages.OnSelectElement:=@ElementSelected;
  1277. FPackages.OnSelectModule:=@ModuleSelected;
  1278. FPackages.OnSelectPackage:=@PackageSelected;
  1279. FPackages.OnSelectTopic:=@TopicSelected;
  1280. // FPackages.OnDeselectElement:=@ElementDeSelected;
  1281. Add1(FPackages);
  1282. Add2(FElement);
  1283. end;
  1284. Procedure TEditorPage.ClearDocument;
  1285. begin
  1286. if (FDocument<>nil) then
  1287. begin
  1288. FDocument.Free;
  1289. FDocument:=Nil;
  1290. end;
  1291. end;
  1292. Procedure TEditorPage.LoadFromFile(FN : String);
  1293. Var
  1294. F : TFileStream;
  1295. begin
  1296. ClearDocument;
  1297. F:=TFileStream.Create(FN,fmOpenRead);
  1298. Try
  1299. SetFileName(FN);
  1300. ReadXMLFile(FDocument,F);
  1301. DisplayDocument;
  1302. finally
  1303. F.Free;
  1304. end;
  1305. end;
  1306. Procedure TEditorPage.LoadFromStream(S : TStream);
  1307. begin
  1308. ClearDocument;
  1309. ReadXMLFile(FDocument,S);
  1310. SetFileName(SNewDocument);
  1311. DisplayDocument;
  1312. end;
  1313. Procedure TEditorPage.SetFileName(FN : String);
  1314. begin
  1315. FFileName:=FN;
  1316. FFileNameLabel.Text:=ChangeFileExt(ExtractFileName(FN),'');
  1317. end;
  1318. Function TEditorPage.MakeBackup(FN : String) : Boolean;
  1319. Var
  1320. BN : String;
  1321. begin
  1322. Result:=Not CreateBackup;
  1323. If not Result then
  1324. begin
  1325. BN:=ChangeFileExt(FN,BackupExtension);
  1326. Result:=RenameFile(FN,BN);
  1327. end;
  1328. end;
  1329. Procedure TEditorPage.SaveToFile(FN : String);
  1330. begin
  1331. If FElement.Modified then
  1332. FElement.Save;
  1333. If (not FileExists(FN)) or MakeBackup(FN) then
  1334. begin
  1335. WriteXMLFile(FDocument,FN);
  1336. if (FN<>FFileName) then
  1337. SetFileName(FN);
  1338. end;
  1339. end;
  1340. Procedure TEditorPage.DisplayDocument;
  1341. begin
  1342. FPackages.DescriptionNode:=FDocument.DocumentElement;
  1343. end;
  1344. {
  1345. Procedure TEditorPage.SelectionChanged(Sender : TFPgtkWidget; Node : TDomElement) ;
  1346. //Procedure TEditorPage.SelectionChanged(Sender : TObject; Node : TDomElement) ;
  1347. Var
  1348. OldNode : TDomElement;
  1349. begin
  1350. If Not FChangingSelection then
  1351. begin
  1352. FChangingSelection:=True;
  1353. Try
  1354. OldNode:=FElement.Element;
  1355. If (OldNode<>Node) then
  1356. begin
  1357. FElement.Element:=Node;
  1358. {
  1359. if the switch didn't succeed, it means that something went wrong
  1360. when saving the old node, so we reselect the old node.
  1361. }
  1362. If FElement.Element<>Node then
  1363. begin
  1364. FPackages.CurrentElement:=OldNode;
  1365. end;
  1366. end;
  1367. Finally
  1368. FChangingSelection:=False;
  1369. end;
  1370. end;
  1371. end;
  1372. }
  1373. Procedure TEditorPage.ElementSelected(Sender : TObject; Node : TDomElement) ;
  1374. Var
  1375. OldNode : TDomElement;
  1376. begin
  1377. // Writeln('In ElementSelected');
  1378. OldNode:=FElement.Element;
  1379. If OldNode<>Node then
  1380. begin
  1381. FElement.Element:=Node;
  1382. {
  1383. if the switch didn't succeed, it means that something went wrong
  1384. when saving the old node, so we reselect the old node.
  1385. }
  1386. { If FElement.Element<>Node then
  1387. FPackages.CurrentElement:=OldNode;
  1388. } end;
  1389. end;
  1390. Procedure TEditorPage.PackageSelected(Sender : TObject; Node : TDomElement) ;
  1391. begin
  1392. ElementSelected(Sender,Node);
  1393. end;
  1394. Procedure TEditorPage.ModuleSelected(Sender : TObject; Node : TDomElement) ;
  1395. begin
  1396. ElementSelected(Sender,Node);
  1397. end;
  1398. Procedure TEditorPage.TopicSelected(Sender : TObject; Node : TDomElement) ;
  1399. begin
  1400. ElementSelected(Sender,Node);
  1401. end;
  1402. {
  1403. Procedure TEditorPage.ElementDeselected(Sender : TObject; Node : TDomElement) ;
  1404. begin
  1405. With FElement do
  1406. If Modified then
  1407. Save;
  1408. end;
  1409. }
  1410. Procedure TEditorPage.InsertTag(TagType : TTagType);
  1411. begin
  1412. FElement.InsertTag(TagType)
  1413. end;
  1414. Procedure TEditorPage.InsertLink(LinkTarget,LinkText : String);
  1415. begin
  1416. FElement.InsertLink(LinkTarget,LinkText);
  1417. end;
  1418. Procedure TEditorPage.InsertTable(Cols,Rows : Integer; UseHeader : Boolean);
  1419. begin
  1420. Felement.InsertTable(Cols,Rows,UseHeader);
  1421. end;
  1422. Function TEditorPage.GetCurrentSelection : String;
  1423. begin
  1424. Result:=FElement.CurrentSelection;
  1425. end;
  1426. Procedure TEditorPage.NewPackage(APackageName : String);
  1427. Var
  1428. P : TDomElement;
  1429. begin
  1430. P:=FDocument.CreateElement('package');
  1431. P['name']:=APAckageName;
  1432. FDocument.DocumentElement.AppendChild(P);
  1433. FPackages.Refresh;
  1434. FPackages.FModified:=True;
  1435. CurrentPackage:=P;
  1436. end;
  1437. Function TEditorPage.FirstPackage : TDomElement;
  1438. Var
  1439. N : TDomNode;
  1440. begin
  1441. N:=FDocument.DocumentElement.FirstChild;
  1442. While (N<>Nil) and
  1443. Not ((N.NodeType=ELEMENT_NODE) and
  1444. (N.NodeName='package')) do
  1445. N:=N.NextSibling;
  1446. Result:=TDomElement(N);
  1447. end;
  1448. Function TEditorPage.FirstModule(APackage : TDomElement) : TDomElement;
  1449. Var
  1450. N : TDomNode;
  1451. begin
  1452. N:=APAckage.FirstChild;
  1453. While (N<>Nil) and
  1454. Not ((N.NodeType=ELEMENT_NODE) and
  1455. (N.NodeName='module')) do
  1456. N:=N.NextSibling;
  1457. Result:=TDomElement(N);
  1458. end;
  1459. Procedure TEditorPage.NewModule(AModuleName : String);
  1460. Var
  1461. M,P : TDomElement;
  1462. begin
  1463. If CurrentPackage<>Nil then
  1464. P:=CurrentPackage
  1465. else
  1466. P:=FirstPackage;
  1467. If (P=Nil) then
  1468. Raise Exception.CreateFmt(SErrNoPackageForModule,[AModuleName]);
  1469. M:=FDocument.CreateElement('module');
  1470. M['name']:=AModuleName;
  1471. P.AppendChild(M);
  1472. FPackages.Refresh;
  1473. FPackages.FModified:=True;
  1474. CurrentModule:=M;
  1475. end;
  1476. Procedure TEditorPage.NewTopic(ATopicName : String);
  1477. Var
  1478. T,M,P : TDomElement;
  1479. begin
  1480. {
  1481. If currently a topic is selected, make a subtopic, or a sibling topic.
  1482. If no topic is selected, then make a topic under the current module or
  1483. package. A menu to move topics up/down is needed...
  1484. }
  1485. if (CurrentTopic<>Nil) then
  1486. begin
  1487. M:=CurrentTopic.ParentNode as TDomElement;
  1488. If M.NodeName='module' then
  1489. P:=M
  1490. else if M.NodeName='topic' then
  1491. P:=M
  1492. else
  1493. P:=CurrentTopic;
  1494. // Writeln('Parent topic is ',P.NodeName)
  1495. end
  1496. else if (CurrentModule<>Nil) then
  1497. P:=CurrentModule
  1498. else if (CurrentPackage<>Nil) then
  1499. P:=CurrentPackage
  1500. else
  1501. P:=FirstPackage;
  1502. If (P=Nil) then
  1503. Raise Exception.CreateFmt(SErrNoNodeForTopic,[ATopicName]);
  1504. // Writeln('Parent node : ',P.NodeName);
  1505. T:=FDocument.CreateElement('topic');
  1506. T['name']:=ATopicName;
  1507. P.AppendChild(T);
  1508. // Writeln('Refreshing tree');
  1509. FPackages.Refresh;
  1510. FPackages.FModified:=True;
  1511. // Writeln('Setting current topic');
  1512. CurrentTopic:=T;
  1513. end;
  1514. Procedure TEditorPage.NewElement(AElementName : String);
  1515. Var
  1516. P,E,M : TDomElement;
  1517. N : TDomNode;
  1518. begin
  1519. If CurrentModule<>Nil then
  1520. M:=CurrentModule
  1521. else
  1522. begin
  1523. P:=FirstPackage;
  1524. If P<>Nil then
  1525. M:=FirstModule(P)
  1526. else
  1527. M:=Nil;
  1528. If M<>Nil then
  1529. CurrentModule:=M;
  1530. end;
  1531. If (M=Nil) then
  1532. Raise Exception.CreateFmt(SErrNoModuleForElement,[AElementName]);
  1533. E:=FDocument.CreateElement('element');
  1534. E['name']:=AElementName;
  1535. M.AppendChild(E);
  1536. FPackages.AddElement(E);
  1537. end;
  1538. Function TEditorPage.GetCurrentPackage : TDomElement;
  1539. begin
  1540. Result:=FPackages.CurrentPackage;
  1541. end;
  1542. Function TEditorPage.GetCurrentModule : TDomElement;
  1543. begin
  1544. Result:=FPackages.CurrentModule;
  1545. end;
  1546. Function TEditorPage.GetCurrentTopic : TDomElement;
  1547. begin
  1548. Result:=FPackages.CurrentTopic;
  1549. end;
  1550. Function TEditorPage.GetCurrentElement : TDomElement;
  1551. begin
  1552. Result:=FElement.Element;
  1553. end;
  1554. Procedure TEditorPage.SetCurrentElement(Value : TDomElement);
  1555. begin
  1556. FPackages.CurrentElement:=Value;
  1557. end;
  1558. Procedure TEditorPage.SetCurrentModule(Value : TDomElement);
  1559. begin
  1560. FPackages.CurrentModule:=Value;
  1561. end;
  1562. Procedure TEditorPage.SetCurrentTopic(Value : TDomElement);
  1563. begin
  1564. FPackages.CurrentTopic:=Value;
  1565. end;
  1566. Procedure TEditorPage.SetCurrentPackage(Value : TDomElement);
  1567. begin
  1568. FPackages.CurrentPackage:=Value;
  1569. end;
  1570. Procedure TEditorPage.SetModified(Value : Boolean);
  1571. begin
  1572. end;
  1573. Function TEditorPage.GetModified : Boolean;
  1574. begin
  1575. Result:=FPackages.Modified or FElement.Modified;
  1576. end;
  1577. Procedure TEditorPage.GetElementList(List : TStrings);
  1578. Var
  1579. N : TDOmNode;
  1580. begin
  1581. With List do
  1582. begin
  1583. Clear;
  1584. If Assigned(CurrentModule) then
  1585. begin
  1586. N:=Currentmodule.FirstChild;
  1587. While (N<>Nil) do
  1588. begin
  1589. If (N is TDomElement) and (N.NodeName='element') then
  1590. Add(TDomElement(N)['name']);
  1591. N:=N.NextSibling;
  1592. end;
  1593. end;
  1594. end;
  1595. end;
  1596. end.