ModuleTrees.Mod 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284
  1. MODULE ModuleTrees; (** AUTHOR "?"; PURPOSE "Visualize module structure as tree"; *)
  2. IMPORT
  3. Streams, Commands, Diagnostics, WMStandardComponents, WMGraphics, WMProperties, WMComponents,
  4. WMTextView, WMEditors, Strings, Texts, TextUtilities, KernelLog,
  5. WMTrees, WMEvents,
  6. FoxScanner, ModuleParser;
  7. CONST
  8. TreeLabelCaption = " Program Structure";
  9. TreeLabelCaptionError = " Program Structure (Errors)";
  10. ShowImages = TRUE;
  11. ImageActive = "ModuleTreesIcons.tar://activity.png";
  12. ImageCommandProc = "ModuleTreesIcons.tar://arrow-red.png";
  13. ImageContextProc = "ModuleTreesIcons.tar://arrow-green.png";
  14. (* Coloring for types *)
  15. ColorTypes = 000008FFFH;
  16. ColorObjects = WMGraphics.Blue;
  17. ColorActiveObjects = ColorObjects;
  18. (* Coloring for procedures *)
  19. ColorProcedure = WMGraphics.Black;
  20. ColorExclusive = WMGraphics.Red;
  21. ColorHasExclusiveBlock = WMGraphics.Magenta;
  22. SortIgnore = 1;
  23. SortProcedure = 2;
  24. SortNo = 90;
  25. SortBody = 99;
  26. (* TextInfo.flags *)
  27. NotPublic = 0;
  28. PosValid = 1;
  29. CanExecute = 2;
  30. (* Special procedure types *)
  31. Other = 0;
  32. CommandProc = 1; (* PROCEDURE(); *)
  33. ContextProc = 2; (* PROCEDURE(context : Commands.Context); *)
  34. TYPE
  35. TextInfo = OBJECT
  36. VAR
  37. flags : SET;
  38. pos : Texts.TextPosition;
  39. name : Strings.String;
  40. color : LONGINT;
  41. sortInfo : LONGINT;
  42. font : WMGraphics.Font;
  43. node : ModuleParser.Node;
  44. modulename : ARRAY 32 OF CHAR;
  45. external : BOOLEAN;
  46. position : LONGINT;
  47. END TextInfo;
  48. ExternalInfo* = OBJECT
  49. VAR
  50. modulename- : ARRAY 32 OF CHAR;
  51. position- : LONGINT;
  52. node- : ModuleParser.Node;
  53. PROCEDURE &Init(CONST modulename : ARRAY OF CHAR; position : LONGINT; node : ModuleParser.Node);
  54. BEGIN
  55. COPY(modulename, SELF.modulename);
  56. SELF.position := position;
  57. SELF.node := node;
  58. END Init;
  59. END ExternalInfo;
  60. ModuleTree* = OBJECT (WMStandardComponents.Panel)
  61. VAR
  62. toolbar: WMStandardComponents.Panel;
  63. label: WMStandardComponents.Label;
  64. refreshBtn, sortBtn, publicBtn: WMStandardComponents.Button;
  65. treeView: WMTrees.TreeView;
  66. tree: WMTrees.Tree;
  67. editor: WMEditors.Editor;
  68. highlight : WMTextView.Highlight;
  69. showPublicOnly : BOOLEAN;
  70. showTypeHierarchy- : WMProperties.BooleanProperty;
  71. onExpandNode-: WMEvents.EventSource;
  72. onGoToExternalModule- : WMEvents.EventSource;
  73. module : ModuleParser.Module;
  74. diagnostics : Diagnostics.StreamDiagnostics;
  75. writer : Streams.Writer;
  76. PROCEDURE & Init*;
  77. BEGIN
  78. Init^;
  79. showPublicOnly := FALSE;
  80. module := NIL;
  81. NEW(writer, KernelLog.Send, 256);
  82. NEW(diagnostics, writer);
  83. NEW(showTypeHierarchy, PrototypeShowTypeHierarchy, NIL, NIL); properties.Add(showTypeHierarchy);
  84. NEW(onGoToExternalModule, NIL, NIL, NIL, NIL); events.Add(onGoToExternalModule);
  85. NEW(label); label.alignment.Set(WMComponents.AlignTop);
  86. label.fillColor.Set(0CCCCCCFFH);
  87. label.SetCaption(TreeLabelCaption); label.bounds.SetHeight(20);
  88. SELF.AddContent(label);
  89. NEW(toolbar); toolbar.alignment.Set(WMComponents.AlignTop);
  90. toolbar.bounds.SetHeight(20);
  91. SELF.AddContent(toolbar);
  92. NEW(treeView); treeView.alignment.Set(WMComponents.AlignClient);
  93. treeView.clSelected.Set(0B0B0FFA0H);
  94. treeView.SetFont(treeFontPlain);
  95. SELF.AddContent(treeView);
  96. tree := treeView.GetTree();
  97. treeView.SetDrawNodeProc(DrawNode);
  98. treeView.onClickNode.Add(ClickNode);
  99. treeView.onMiddleClickNode.Add(MiddleClickNode);
  100. onExpandNode := treeView.onExpandNode;
  101. NEW(refreshBtn); refreshBtn.alignment.Set(WMComponents.AlignLeft);
  102. refreshBtn.caption.SetAOC("Refresh");
  103. refreshBtn.onClick.Add(RefreshHandler);
  104. toolbar.AddContent(refreshBtn);
  105. NEW(sortBtn); sortBtn.alignment.Set(WMComponents.AlignLeft);
  106. sortBtn.caption.SetAOC("Sort");
  107. sortBtn.onClick.Add(SortHandler);
  108. toolbar.AddContent(sortBtn);
  109. NEW(publicBtn); publicBtn.alignment.Set(WMComponents.AlignClient);
  110. publicBtn.caption.SetAOC("PublicOnly");
  111. publicBtn.isToggle.Set(TRUE);
  112. publicBtn.onClick.Add(ShowPublicHandler);
  113. toolbar.AddContent(publicBtn);
  114. END Init;
  115. PROCEDURE PropertyChanged*(sender, data : ANY);
  116. BEGIN
  117. IF (data = showTypeHierarchy) THEN
  118. RefreshHandler(NIL, NIL);
  119. ELSE
  120. PropertyChanged^(sender, data);
  121. END;
  122. END PropertyChanged;
  123. PROCEDURE SetEditor*(e: WMEditors.Editor);
  124. BEGIN
  125. IF e = editor THEN RETURN END;
  126. IF (highlight # NIL) & (editor # NIL) THEN
  127. editor.tv.RemoveHighlight(highlight);
  128. highlight := NIL
  129. END;
  130. editor := e;
  131. highlight := editor.tv.CreateHighlight();
  132. highlight.SetColor(LONGINT(0DDDD0060H));
  133. highlight.SetKind(WMTextView.HLOver)
  134. END SetEditor;
  135. PROCEDURE Erase*;
  136. BEGIN
  137. tree.Acquire;
  138. tree.SetRoot(NIL);
  139. tree.Release;
  140. treeView.SetFirstLine(0, TRUE);
  141. label.SetCaption(TreeLabelCaption);
  142. END Erase;
  143. PROCEDURE ShowPublicHandler(sender, data : ANY);
  144. BEGIN
  145. IF ~IsCallFromSequencer() THEN
  146. sequencer.ScheduleEvent(SELF.ShowPublicHandler, sender, data);
  147. RETURN
  148. END;
  149. showPublicOnly := ~showPublicOnly;
  150. publicBtn.SetPressed(showPublicOnly);
  151. tree.Acquire;
  152. SetNodeVisibilities(tree.GetRoot(), showPublicOnly);
  153. tree.Release;
  154. END ShowPublicHandler;
  155. PROCEDURE SetNodeVisibilities(parent : WMTrees.TreeNode; showPublicOnly : BOOLEAN);
  156. VAR n : WMTrees.TreeNode; state : SET; info : TextInfo; ptr : ANY;
  157. BEGIN
  158. n := tree.GetChildren(parent);
  159. WHILE n # NIL DO
  160. SetNodeVisibilities(n, showPublicOnly);
  161. state := tree.GetNodeState(n);
  162. ptr := tree.GetNodeData(n);
  163. IF (ptr # NIL) & (ptr IS TextInfo) THEN
  164. info := ptr (TextInfo);
  165. IF NotPublic IN info.flags THEN
  166. IF showPublicOnly THEN INCL(state, WMTrees.NodeHidden) ELSE EXCL(state, WMTrees.NodeHidden); END;
  167. END;
  168. END;
  169. tree.SetNodeState(n, state);
  170. n := tree.GetNextSibling(n);
  171. END;
  172. END SetNodeVisibilities;
  173. PROCEDURE GetNextNode(this : WMTrees.TreeNode; ignoreChildren : BOOLEAN) : WMTrees.TreeNode;
  174. VAR state : SET;
  175. BEGIN
  176. state := tree.GetNodeState(this);
  177. IF ~ignoreChildren & (tree.GetChildren(this) # NIL) THEN RETURN tree.GetChildren(this);
  178. ELSIF tree.GetNextSibling(this) # NIL THEN RETURN tree.GetNextSibling(this)
  179. ELSIF tree.GetParent(this) # NIL THEN RETURN GetNextNode(tree.GetParent(this), TRUE)
  180. ELSE RETURN NIL
  181. END
  182. END GetNextNode;
  183. PROCEDURE RefreshHandler*(sender, data: ANY);
  184. TYPE
  185. StringList = POINTER TO ARRAY OF Strings.String;
  186. VAR
  187. module: ModuleParser.Module;
  188. scanner: FoxScanner.Scanner;
  189. reader : TextUtilities.TextReader;
  190. rootNode: WMTrees.TreeNode;
  191. nofOpenNodes : LONGINT;
  192. openNodes : StringList;
  193. i : LONGINT;
  194. PROCEDURE Store;
  195. VAR node, tnode : WMTrees.TreeNode;
  196. stack : ARRAY 32 OF WMTrees.TreeNode;
  197. caption : Strings.String;
  198. tos : LONGINT;
  199. path : ARRAY 1024 OF CHAR;
  200. sl, tl : StringList;
  201. i : LONGINT;
  202. BEGIN
  203. nofOpenNodes := 0;
  204. node := tree.GetRoot();
  205. NEW(sl, 16);
  206. WHILE node # NIL DO
  207. IF WMTrees.NodeExpanded IN tree.GetNodeState(node) THEN
  208. tnode := node;
  209. tos := 0;
  210. REPEAT
  211. stack[tos] := tnode; INC(tos);
  212. tnode := tree.GetParent(tnode)
  213. UNTIL tnode = NIL;
  214. DEC(tos);
  215. path := "";
  216. WHILE tos >= 0 DO
  217. caption := tree.GetNodeCaption(stack[tos]);
  218. Strings.Append(path, caption^);
  219. DEC(tos);
  220. IF tos >= 0 THEN Strings.Append(path, "/") END
  221. END;
  222. IF nofOpenNodes >= LEN(sl) THEN
  223. NEW(tl, LEN(sl) * 2);
  224. FOR i := 0 TO LEN(sl) - 1 DO tl[i] := sl[i] END;
  225. sl := tl
  226. END;
  227. sl[nofOpenNodes] := Strings.NewString(path); INC(nofOpenNodes)
  228. END;
  229. node := GetNextNode(node, FALSE)
  230. END;
  231. openNodes := sl
  232. END Store;
  233. PROCEDURE Expand(path : ARRAY OF CHAR);
  234. VAR node, tnode : WMTrees.TreeNode;
  235. pos : LONGINT;
  236. found : BOOLEAN;
  237. ident : ARRAY 64 OF CHAR;
  238. string : Strings.String;
  239. BEGIN
  240. node := tree.GetRoot();
  241. pos := Strings.Pos("/", path);
  242. IF pos > 0 THEN
  243. Strings.Copy(path, 0, pos, ident);
  244. Strings.Delete(path, 0, pos + 1)
  245. END;
  246. WHILE (path # "") & (node # NIL) DO
  247. pos := Strings.Pos("/", path);
  248. IF pos > 0 THEN
  249. Strings.Copy(path, 0, pos, ident);
  250. Strings.Delete(path, 0, pos + 1)
  251. ELSE COPY(path, ident); path := ""
  252. END;
  253. tnode := tree.GetChildren(node);
  254. found := FALSE;
  255. WHILE (tnode # NIL) & ~ found DO
  256. string := tree.GetNodeCaption(tnode);
  257. IF (string # NIL) & (string^ = ident) THEN
  258. node := tnode;
  259. found := TRUE
  260. END;
  261. tnode := tree.GetNextSibling(tnode)
  262. END
  263. END;
  264. tree.InclNodeState(node, WMTrees.NodeExpanded);
  265. END Expand;
  266. BEGIN
  267. IF ~IsCallFromSequencer() THEN
  268. sequencer.ScheduleEvent(SELF.RefreshHandler, sender, data);
  269. ELSE
  270. NEW(reader, editor.text);
  271. scanner := FoxScanner.NewScanner("ModuleTrees", reader, 0, diagnostics);
  272. ModuleParser.Parse(scanner, module);
  273. SELF.module := module;
  274. IF module # NIL THEN
  275. IF showTypeHierarchy.Get() THEN
  276. ModuleParser.SetSuperTypes(module);
  277. END;
  278. tree.Acquire;
  279. Store;
  280. editor.text.AcquireRead;
  281. NEW(rootNode);
  282. tree.SetRoot(rootNode);
  283. tree.SetNodeData(rootNode, GetTextInfo(module, module.ident, TRUE, SortIgnore, treeView.clTextDefault.Get(), {}));
  284. tree.SetNodeCaption(rootNode, module.ident.name);
  285. IF module.context # NIL THEN
  286. AddPostfixToCaption(rootNode, Strings.NewString(" IN "));
  287. AddPostfixToCaption(rootNode, module.context.name);
  288. END;
  289. AddImportList(rootNode, module.importList);
  290. AddDefinitions(rootNode, module.definitions);
  291. AddDeclSeq(rootNode, module.declSeq);
  292. IF module.bodyPos # 0 THEN
  293. AddBody (rootNode, module, module.modifiers, module.bodyPos);
  294. END;
  295. tree.SetNodeState(rootNode, {WMTrees.NodeExpanded});
  296. SetNodeVisibilities(rootNode, showPublicOnly);
  297. editor.text.ReleaseRead;
  298. i := 0;
  299. WHILE i < nofOpenNodes DO
  300. Expand(openNodes[i]^); INC(i)
  301. END;
  302. tree.Release;
  303. treeView.SetFirstLine(0, TRUE);
  304. IF module.hasError THEN label.SetCaption(TreeLabelCaptionError);
  305. ELSE label.SetCaption(TreeLabelCaption);
  306. END;
  307. END;
  308. treeView.TreeChanged(NIL, NIL);
  309. END;
  310. END RefreshHandler;
  311. PROCEDURE SortHandler(sender, data: ANY);
  312. BEGIN
  313. tree.Acquire;
  314. SortTree(tree.GetRoot());
  315. tree.Release;
  316. END SortHandler;
  317. PROCEDURE SelectNodeByPos* (pos: LONGINT);
  318. VAR root, node: WMTrees.TreeNode; data : ANY;
  319. PROCEDURE FindNearestNode (node: WMTrees.TreeNode; pos: LONGINT): WMTrees.TreeNode;
  320. VAR nearestNode: WMTrees.TreeNode; distance, nearestDistance: LONGINT;
  321. PROCEDURE GetDistance (node: WMTrees.TreeNode; pos: LONGINT): LONGINT;
  322. VAR data: ANY;
  323. BEGIN
  324. data := tree.GetNodeData (node);
  325. WHILE (node # NIL) & ((data = NIL) OR ~(data IS TextInfo) OR (data(TextInfo).pos = NIL)) DO
  326. node := tree.GetChildren (node); data := tree.GetNodeData (node);
  327. END;
  328. IF (data # NIL) & (data IS TextInfo) & (data(TextInfo).pos # NIL) & (pos >= data(TextInfo).pos.GetPosition ()) THEN
  329. RETURN pos - data(TextInfo).pos.GetPosition ()
  330. ELSE
  331. RETURN MAX(LONGINT)
  332. END
  333. END GetDistance;
  334. BEGIN
  335. nearestNode := NIL; nearestDistance := MAX (LONGINT);
  336. WHILE node # NIL DO
  337. data := tree.GetNodeData(node);
  338. IF (data # NIL) & (data IS TextInfo) & (data(TextInfo).external = FALSE) THEN
  339. distance := GetDistance (node, pos);
  340. IF distance < nearestDistance THEN nearestNode := node; nearestDistance := distance END;
  341. END;
  342. node := tree.GetNextSibling (node);
  343. END;
  344. RETURN nearestNode;
  345. END FindNearestNode;
  346. BEGIN
  347. tree.Acquire;
  348. root := FindNearestNode (tree.GetRoot (), pos); node := NIL;
  349. WHILE (root # NIL) & (WMTrees.NodeExpanded IN tree.GetNodeState (root)) & (tree.GetChildren (root) # NIL) DO
  350. node := FindNearestNode (tree.GetChildren (root), pos); root := node;
  351. END;
  352. tree.Release;
  353. IF (node # NIL) THEN treeView.SelectNode (node); END;
  354. END SelectNodeByPos;
  355. PROCEDURE SortTree(parent: WMTrees.TreeNode);
  356. VAR
  357. n, left, right: WMTrees.TreeNode;
  358. nodeCount, i: LONGINT;
  359. BEGIN
  360. n := tree.GetChildren(parent);
  361. WHILE n # NIL DO
  362. SortTree(n);
  363. INC(nodeCount);
  364. n := tree.GetNextSibling(n);
  365. END;
  366. FOR i := 1 TO nodeCount-1 DO
  367. n := tree.GetChildren(parent);
  368. WHILE tree.GetNextSibling(n) # NIL DO
  369. left := n; right := tree.GetNextSibling(n);
  370. IF IsNodeGreater(left, right) THEN
  371. SwapSiblings(parent, left, right);
  372. n := left;
  373. ELSE
  374. n := right;
  375. END;
  376. END;
  377. END;
  378. END SortTree;
  379. PROCEDURE IsNodeGreater(left, right: WMTrees.TreeNode): BOOLEAN;
  380. VAR
  381. leftCaption, rightCaption, leftTmp, rightTmp: Strings.String;
  382. leftData, rightData: ANY;
  383. BEGIN
  384. leftData := tree.GetNodeData(left);
  385. rightData := tree.GetNodeData(right);
  386. IF (leftData # NIL) & (rightData # NIL) &
  387. (leftData IS TextInfo) & (rightData IS TextInfo) &
  388. (leftData(TextInfo).sortInfo >= rightData(TextInfo).sortInfo) &
  389. (leftData(TextInfo).font = rightData(TextInfo).font) &
  390. (leftData(TextInfo).sortInfo # SortNo) &
  391. (rightData(TextInfo).sortInfo # SortNo) THEN
  392. (* continue *)
  393. ELSE
  394. RETURN FALSE;
  395. END;
  396. leftCaption := tree.GetNodeCaption(left);
  397. rightCaption := tree.GetNodeCaption(right);
  398. IF (leftCaption^ = "VAR") OR (rightCaption^ = "VAR") OR
  399. (leftCaption^ = "CONST") OR (rightCaption^ = "CONST") OR
  400. (leftCaption^ = "IMPORT") OR (rightCaption^ = "IMPORT")
  401. THEN RETURN FALSE
  402. END;
  403. leftTmp := Strings.NewString(leftCaption^);
  404. rightTmp := Strings.NewString(rightCaption^);
  405. Strings.TrimLeft(leftTmp^, '-');
  406. Strings.TrimLeft(rightTmp^, '-');
  407. RETURN leftTmp^ > rightTmp^;
  408. END IsNodeGreater;
  409. PROCEDURE SwapSiblings(parent, left, right: WMTrees.TreeNode);
  410. BEGIN
  411. ASSERT(tree.GetNextSibling(left) = right);
  412. tree.RemoveNode(left);
  413. tree.AddChildNodeAfter(parent, right, left);
  414. END SwapSiblings;
  415. PROCEDURE DrawNode(canvas: WMGraphics.Canvas; w, h: LONGINT; node: WMTrees.TreeNode; state: SET);
  416. VAR dx, tdx, tdy : LONGINT; f : WMGraphics.Font; image : WMGraphics.Image;
  417. caption: Strings.String;
  418. ptr: ANY;
  419. BEGIN
  420. dx := 0;
  421. f := treeView.GetFont();
  422. image := tree.GetNodeImage(node);
  423. IF image # NIL THEN
  424. canvas.DrawImage(0, 0, image, WMGraphics.ModeSrcOverDst); dx := image.width + 5;
  425. END;
  426. ptr := tree.GetNodeData(node);
  427. IF (ptr # NIL) & (ptr IS TextInfo) THEN
  428. canvas.SetColor(ptr(TextInfo).color);
  429. f := ptr(TextInfo).font;
  430. canvas.SetFont(f);
  431. ELSE
  432. canvas.SetColor(treeView.clTextDefault.Get());
  433. canvas.SetFont(treeView.GetFont());
  434. END;
  435. caption := tree.GetNodeCaption(node);
  436. f.GetStringSize(caption^, tdx, tdy);
  437. IF WMTrees.StateSelected IN state THEN
  438. canvas.Fill(WMGraphics.MakeRectangle(0, 0, dx + tdx, h), treeView.clSelected.Get(), WMGraphics.ModeSrcOverDst)
  439. ELSIF WMTrees.StateHover IN state THEN
  440. canvas.Fill(WMGraphics.MakeRectangle(0, 0, dx + tdx, h), treeView.clHover.Get(), WMGraphics.ModeSrcOverDst)
  441. END;
  442. IF caption # NIL THEN canvas.DrawString(dx, h - f.descent - 1 , caption^) END;
  443. END DrawNode;
  444. PROCEDURE ClickNode(sender, data : ANY);
  445. VAR
  446. d: ANY;
  447. node : WMTrees.TreeNode;
  448. textInfo: TextInfo;
  449. a, b : LONGINT;
  450. text : Texts.Text;
  451. moduleNode : ModuleParser.Module;
  452. extInfo : ExternalInfo;
  453. BEGIN
  454. IF (data # NIL) & (data IS WMTrees.TreeNode) THEN
  455. tree.Acquire;
  456. d := tree.GetNodeData(data(WMTrees.TreeNode));
  457. IF (d = NIL) OR ((d # NIL) & (d IS TextInfo) & (d(TextInfo).flags * {PosValid} = {})) THEN
  458. (* Use pos of child (for VAR, CONST and IMPORT) *)
  459. node := tree.GetChildren(data(WMTrees.TreeNode));
  460. IF (node # NIL) THEN
  461. d := tree.GetNodeData(node);
  462. END;
  463. END;
  464. tree.Release;
  465. IF (d # NIL) & (d IS TextInfo) & (d(TextInfo).node # NIL) THEN
  466. textInfo := d(TextInfo);
  467. moduleNode := GetModuleNode(textInfo.node);
  468. IF (moduleNode = module) THEN
  469. IF (textInfo.pos # NIL) THEN
  470. text := editor.text;
  471. text.AcquireRead;
  472. editor.tv.cursor.SetPosition(textInfo.pos.GetPosition());
  473. editor.tv.cursor.SetVisible(TRUE);
  474. IF (node = NIL) THEN
  475. editor.tv.FindCommand(textInfo.pos.GetPosition(), a, b);
  476. highlight.SetFromTo(a, b);
  477. ELSE
  478. highlight.SetFromTo(0, 0); (* deactivate *)
  479. END;
  480. text.ReleaseRead;
  481. editor.SetFocus;
  482. ELSE
  483. KernelLog.String("ModuleTrees.ModuleTree.ClickNode: Expected TextInfo.pos # NIL"); KernelLog.Ln;
  484. END;
  485. ELSE
  486. NEW(extInfo, textInfo.modulename, textInfo.position, textInfo.node);
  487. onGoToExternalModule.Call(extInfo);
  488. END;
  489. END
  490. END
  491. END ClickNode;
  492. PROCEDURE MiddleClickNode(sender, data : ANY);
  493. VAR d : ANY; commandStr, ignoreMsg : ARRAY 128 OF CHAR; len: LONGINT; ignore : WORD;
  494. BEGIN
  495. IF (data # NIL) & (data IS WMTrees.TreeNode) THEN
  496. tree.Acquire;
  497. d := tree.GetNodeData(data(WMTrees.TreeNode));
  498. tree.Release;
  499. IF (d # NIL) & (d IS TextInfo) & (CanExecute IN d(TextInfo).flags) & (d(TextInfo).name # NIL) &
  500. (module # NIL) & (module.ident # NIL) & (module.ident.name # NIL)
  501. THEN
  502. COPY(module.ident.name^, commandStr);
  503. Strings.Append(commandStr, Commands.Delimiter);
  504. Strings.Append(commandStr, d(TextInfo).name^);
  505. len := Strings.Length(commandStr);
  506. IF (commandStr[len-1] = "*") THEN commandStr[len-1] := 0X; END;
  507. Commands.Activate(commandStr, NIL, {}, ignore, ignoreMsg);
  508. END;
  509. END;
  510. END MiddleClickNode;
  511. PROCEDURE GetTextInfo(node : ModuleParser.Node; infoItem: ModuleParser.InfoItem; isPublic : BOOLEAN; sortInfo, color: LONGINT; style: SET): TextInfo;
  512. VAR newInfo: TextInfo; moduleNode : ModuleParser.Module; font: WMGraphics.Font;
  513. BEGIN
  514. NEW(newInfo);
  515. newInfo.node := node;
  516. newInfo.flags := {};
  517. IF ~isPublic THEN INCL(newInfo.flags, NotPublic); END;
  518. newInfo.sortInfo := sortInfo;
  519. newInfo.color := color;
  520. IF style = {} THEN
  521. font := treeFontPlain;
  522. ELSIF style = {WMGraphics.FontBold} THEN
  523. font := treeFontBold;
  524. ELSIF style = {WMGraphics.FontItalic} THEN
  525. font := treeFontItalic;
  526. ELSE
  527. (* unknown style *)
  528. font := treeFontPlain;
  529. END;
  530. IF (node # NIL) THEN
  531. moduleNode := GetModuleNode(node);
  532. ELSE
  533. moduleNode := NIL;
  534. END;
  535. newInfo.font := font;
  536. IF (infoItem # NIL) THEN
  537. newInfo.name := infoItem.name;
  538. newInfo.position := infoItem.pos;
  539. INCL(newInfo.flags, PosValid);
  540. IF (moduleNode = NIL) OR (moduleNode = module) THEN
  541. newInfo.external := FALSE;
  542. newInfo.modulename := "";
  543. NEW(newInfo.pos, editor.text);
  544. newInfo.pos.SetPosition(infoItem.pos);
  545. ELSE
  546. newInfo.external := TRUE;
  547. newInfo.pos := NIL;
  548. COPY(moduleNode.ident.name^, newInfo.modulename);
  549. END;
  550. END;
  551. RETURN newInfo;
  552. END GetTextInfo;
  553. PROCEDURE IsPublic(identDef : ModuleParser.IdentDef) : BOOLEAN;
  554. BEGIN
  555. RETURN (identDef.vis = ModuleParser.Public) OR (identDef.vis = ModuleParser.PublicRO);
  556. END IsPublic;
  557. PROCEDURE HasPublicConsts(constDecl: ModuleParser.ConstDecl) : BOOLEAN;
  558. VAR n : ModuleParser.NodeList; c : ModuleParser.ConstDecl;
  559. BEGIN
  560. n := constDecl;
  561. WHILE (n # NIL) DO
  562. c := n (ModuleParser.ConstDecl);
  563. IF IsPublic(c.identDef) THEN RETURN TRUE; END;
  564. n := n.next;
  565. END;
  566. RETURN FALSE;
  567. END HasPublicConsts;
  568. PROCEDURE HasPublicVars(varDecl : ModuleParser.VarDecl) : BOOLEAN;
  569. VAR n, ni : ModuleParser.NodeList;
  570. BEGIN
  571. n := varDecl;
  572. WHILE (n # NIL) DO
  573. ni := n(ModuleParser.VarDecl).identList;
  574. WHILE (ni # NIL) DO
  575. IF IsPublic(ni(ModuleParser.IdentList).identDef) THEN RETURN TRUE; END;
  576. ni := ni.next;
  577. END;
  578. n := n.next;
  579. END;
  580. RETURN FALSE;
  581. END HasPublicVars;
  582. PROCEDURE GetModuleNode(node : ModuleParser.Node) : ModuleParser.Module;
  583. VAR n : ModuleParser.Node;
  584. BEGIN
  585. ASSERT(node # NIL);
  586. n := node;
  587. WHILE (n # n.parent) DO n := n.parent; END;
  588. IF (n # NIL) & (n IS ModuleParser.Module) THEN
  589. RETURN n (ModuleParser.Module);
  590. ELSE
  591. RETURN NIL;
  592. END;
  593. END GetModuleNode;
  594. PROCEDURE GetProcedureType(procHead : ModuleParser.ProcHead) : LONGINT;
  595. VAR type : LONGINT;
  596. PROCEDURE InModuleScope(procHead : ModuleParser.ProcHead) : BOOLEAN;
  597. BEGIN
  598. RETURN (procHead # NIL) & (procHead.parent.parent.parent = module);
  599. END InModuleScope;
  600. PROCEDURE IsCommandProc(procHead : ModuleParser.ProcHead) : BOOLEAN;
  601. BEGIN
  602. RETURN (procHead # NIL) & (procHead.formalPars = NIL);
  603. END IsCommandProc;
  604. PROCEDURE IsContextProc(procHead : ModuleParser.ProcHead) : BOOLEAN;
  605. BEGIN
  606. RETURN (procHead # NIL) & (procHead.formalPars # NIL) & (procHead.formalPars.fpSectionList # NIL) &
  607. (procHead.formalPars.fpSectionList.next = NIL) & (procHead.formalPars.fpSectionList.const = FALSE) &
  608. (procHead.formalPars.fpSectionList.var = FALSE) & (procHead.formalPars.fpSectionList.type.qualident # NIL) &
  609. (procHead.formalPars.fpSectionList.type.qualident.ident.name^ = "Commands.Context");
  610. END IsContextProc;
  611. BEGIN
  612. type := Other;
  613. IF InModuleScope(procHead) & (procHead.identDef.vis = ModuleParser.Public) & ~(procHead.operator) & ~(procHead.inline) THEN
  614. IF IsCommandProc(procHead) THEN
  615. type := CommandProc;
  616. ELSIF IsContextProc(procHead) THEN
  617. type := ContextProc;
  618. END;
  619. END;
  620. RETURN type;
  621. END GetProcedureType;
  622. PROCEDURE AddBody (root: WMTrees.TreeNode; pnode : ModuleParser.Node; modifiers: SET; pos: LONGINT);
  623. VAR node: WMTrees.TreeNode; info: TextInfo;
  624. BEGIN
  625. node := NewNode(root, Strings.NewString("BODY"));
  626. info := GetTextInfo(pnode, NIL, FALSE, SortBody, GetColor(modifiers, treeView.clTextDefault.Get()), {});
  627. NEW(info.pos, editor.text);
  628. info.pos.SetPosition(pos);
  629. INCL(info.flags, PosValid);
  630. tree.SetNodeData(node, info);
  631. END AddBody;
  632. PROCEDURE AddImportList(parent: WMTrees.TreeNode; importList: ModuleParser.Import);
  633. VAR
  634. n: ModuleParser.NodeList;
  635. newNode, importNode: WMTrees.TreeNode;
  636. info : TextInfo;
  637. import: ModuleParser.Import;
  638. nofImports : LONGINT;
  639. BEGIN
  640. n := importList;
  641. IF n # NIL THEN
  642. NEW(importNode);
  643. info := GetTextInfo(importList, NIL, FALSE, SortIgnore, treeView.clTextDefault.Get(), {});
  644. tree.SetNodeData(importNode, info);
  645. tree.SetNodeCaption(importNode, Strings.NewString("IMPORT"));
  646. tree.AddChildNode(parent, importNode);
  647. ELSE
  648. importNode := NIL;
  649. END;
  650. nofImports := 0;
  651. WHILE n # NIL DO
  652. import := n(ModuleParser.Import);
  653. newNode := AddInfoItem(importNode, import, import.ident, TRUE, SortIgnore, treeView.clTextDefault.Get(), {});
  654. IF import.alias # NIL THEN
  655. AddPostfixToCaption(newNode, Strings.NewString(" := "));
  656. AddPostfixToCaption(newNode, import.alias.name);
  657. END;
  658. IF import.context # NIL THEN
  659. AddPostfixToCaption(newNode, Strings.NewString(" IN "));
  660. AddPostfixToCaption(newNode, import.context.name);
  661. END;
  662. IF (newNode # NIL) THEN INC(nofImports); END;
  663. n := n.next;
  664. END;
  665. IF (importNode # NIL) THEN AddNumberPostfixToCaption(importNode, nofImports); END;
  666. END AddImportList;
  667. PROCEDURE AddDefinitions(parent: WMTrees.TreeNode; definitions: ModuleParser.Definition);
  668. VAR n, p: ModuleParser.NodeList; defNode, newNode: WMTrees.TreeNode;
  669. BEGIN
  670. n := definitions;
  671. WHILE n # NIL DO
  672. defNode := AddInfoItem(parent, n, n(ModuleParser.Definition).ident, TRUE, SortIgnore, WMGraphics.Green, {WMGraphics.FontItalic});
  673. p := n(ModuleParser.Definition).procs;
  674. WHILE p # NIL DO
  675. newNode := AddProcHead(defNode, p(ModuleParser.ProcHead));
  676. p := p.next;
  677. END;
  678. n := n.next;
  679. END;
  680. END AddDefinitions;
  681. PROCEDURE AddDeclSeq(parent: WMTrees.TreeNode; declSeq: ModuleParser.DeclSeq);
  682. VAR n: ModuleParser.NodeList; newNode: WMTrees.TreeNode; info : TextInfo;
  683. BEGIN
  684. n := declSeq;
  685. WHILE n # NIL DO
  686. declSeq := n(ModuleParser.DeclSeq);
  687. IF (declSeq.constDecl # NIL) THEN
  688. NEW(newNode);
  689. info := GetTextInfo(declSeq.constDecl, NIL, HasPublicConsts(declSeq.constDecl), SortIgnore, treeView.clTextDefault.Get(), {});
  690. tree.SetNodeData(newNode, info);
  691. tree.SetNodeCaption(newNode, Strings.NewString("CONST"));
  692. tree.AddChildNode(parent, newNode);
  693. AddConstDecl(newNode, declSeq.constDecl);
  694. END;
  695. IF declSeq.typeDecl # NIL THEN
  696. AddTypeDecl(parent, declSeq.typeDecl);
  697. END;
  698. IF (declSeq.varDecl # NIL) THEN
  699. NEW(newNode);
  700. info := GetTextInfo(declSeq.varDecl, NIL, HasPublicVars(declSeq.varDecl), SortIgnore, treeView.clTextDefault.Get(), {});
  701. tree.SetNodeData(newNode, info);
  702. tree.SetNodeCaption(newNode, Strings.NewString("VAR"));
  703. tree.AddChildNode(parent, newNode);
  704. AddVarDecl(newNode, declSeq.varDecl);
  705. END;
  706. IF declSeq.procDecl # NIL THEN
  707. AddProcDecl(parent, declSeq.procDecl);
  708. END;
  709. n := n.next;
  710. END;
  711. END AddDeclSeq;
  712. PROCEDURE AddProcDecl(treeNode: WMTrees.TreeNode; procDecl: ModuleParser.ProcDecl);
  713. VAR n: ModuleParser.NodeList; newNode: WMTrees.TreeNode;
  714. BEGIN
  715. n := procDecl;
  716. WHILE n # NIL DO
  717. procDecl := n(ModuleParser.ProcDecl);
  718. newNode := AddProcHead(treeNode, procDecl.head);
  719. IF (procDecl.declSeq # NIL) & (newNode # NIL) THEN
  720. AddDeclSeq(newNode, procDecl.declSeq);
  721. END;
  722. IF procDecl.bodyPos # 0 THEN
  723. AddBody (newNode, procDecl, {}, procDecl.bodyPos);
  724. END;
  725. n := n.next;
  726. END;
  727. END AddProcDecl;
  728. PROCEDURE AddProcHead(treeNode: WMTrees.TreeNode; procHead: ModuleParser.ProcHead): WMTrees.TreeNode;
  729. VAR
  730. newNode: WMTrees.TreeNode; caption: Strings.String;
  731. color : LONGINT; image : WMGraphics.Image; type : LONGINT; d : ANY;
  732. BEGIN
  733. IF (procHead # NIL) THEN
  734. color := GetColor(procHead.modifiers, ColorProcedure);
  735. newNode := AddIdentDef(treeNode, procHead, procHead.identDef, SortProcedure, color, {WMGraphics.FontBold});
  736. IF procHead.operator THEN
  737. IF procHead.identDef.vis = ModuleParser.Public THEN
  738. (* remove visibility sign (ugly) *)
  739. caption := tree.GetNodeCaption(newNode);
  740. Strings.TrimRight(caption^, '*');
  741. END;
  742. AddPrefixToCaption(newNode, Strings.NewString('"'));
  743. AddPostfixToCaption(newNode, Strings.NewString('"'));
  744. IF procHead.identDef.vis = ModuleParser.Public THEN
  745. (* add visibility sign (still ugly) *)
  746. AddPostfixToCaption(newNode, Strings.NewString("*"));
  747. END;
  748. END;
  749. IF procHead.constructor THEN
  750. AddPrefixToCaption(newNode, Strings.NewString("& "));
  751. END;
  752. IF procHead.inline THEN
  753. AddPrefixToCaption(newNode, Strings.NewString("-"));
  754. END;
  755. type := GetProcedureType(procHead);
  756. IF (type = CommandProc) OR (type = ContextProc) THEN
  757. tree.Acquire;
  758. d := tree.GetNodeData(newNode);
  759. IF (d # NIL) & (d IS TextInfo) THEN INCL(d(TextInfo).flags, CanExecute); END;
  760. tree.Release;
  761. END;
  762. IF ShowImages THEN
  763. CASE type OF
  764. |CommandProc: image := WMGraphics.LoadImage(ImageCommandProc, TRUE);
  765. |ContextProc: image := WMGraphics.LoadImage(ImageContextProc, TRUE);
  766. ELSE
  767. image := NIL;
  768. END;
  769. IF image # NIL THEN
  770. tree.Acquire; tree.SetNodeImage(newNode, image); tree.Release;
  771. END;
  772. END;
  773. IF (ModuleParser.Overwrite IN procHead.modifiers) THEN
  774. AddPostfixToCaption(newNode, Strings.NewString(" [overwrite]"));
  775. END;
  776. IF (ModuleParser.Overwritten IN procHead.modifiers) THEN
  777. AddPostfixToCaption(newNode, Strings.NewString(" [overwritten]"));
  778. END;
  779. AddFormalPars(newNode, procHead.formalPars);
  780. RETURN newNode;
  781. ELSE
  782. RETURN NIL;
  783. END
  784. END AddProcHead;
  785. PROCEDURE AddFormalPars(parent: WMTrees.TreeNode; formalPars: ModuleParser.FormalPars);
  786. VAR newNode: WMTrees.TreeNode;
  787. BEGIN
  788. IF formalPars # NIL THEN
  789. AddFPSection(parent, formalPars.fpSectionList);
  790. NEW(newNode);
  791. tree.SetNodeCaption(newNode, Strings.NewString("RETURN"));
  792. IF formalPars.returnType # NIL THEN
  793. AddType(newNode, formalPars.returnType, TRUE);
  794. tree.AddChildNode(parent, newNode);
  795. END;
  796. END;
  797. END AddFormalPars;
  798. PROCEDURE AddFPSection(parent: WMTrees.TreeNode; fpSection: ModuleParser.FPSection);
  799. VAR newNode: WMTrees.TreeNode; n, l: ModuleParser.NodeList; ptr : ANY;
  800. BEGIN
  801. n := fpSection;
  802. WHILE n # NIL DO
  803. l := n(ModuleParser.FPSection).identList;
  804. WHILE l # NIL DO
  805. newNode := AddIdentDef(parent, l, l(ModuleParser.IdentList).identDef, SortIgnore, treeView.clTextDefault.Get(), {});
  806. (* Make parameters always visible *)
  807. ptr := tree.GetNodeData(newNode);
  808. IF (ptr # NIL) & (ptr IS TextInfo) THEN
  809. EXCL(ptr(TextInfo).flags, NotPublic);
  810. END;
  811. IF n(ModuleParser.FPSection).var THEN
  812. AddPostfixToCaption(newNode, Strings.NewString(" (VAR)"));
  813. ELSIF n(ModuleParser.FPSection).const THEN
  814. AddPostfixToCaption(newNode, Strings.NewString(" (CONST)"));
  815. END;
  816. AddType(newNode, n(ModuleParser.FPSection).type, FALSE);
  817. l := l.next;
  818. END;
  819. n := n.next;
  820. END;
  821. END AddFPSection;
  822. PROCEDURE AddVarDecl(parent: WMTrees.TreeNode; varDecl: ModuleParser.VarDecl);
  823. VAR n: ModuleParser.NodeList; nofVariables, nofIdents : LONGINT;
  824. BEGIN
  825. n := varDecl; nofVariables := 0;
  826. WHILE n # NIL DO
  827. varDecl := n(ModuleParser.VarDecl);
  828. AddIdentList(parent, varDecl.identList, nofIdents);
  829. nofVariables := nofVariables + nofIdents;
  830. n := n.next;
  831. END;
  832. AddNumberPostfixToCaption(parent, nofVariables);
  833. END AddVarDecl;
  834. PROCEDURE AddTypeDecl(parent: WMTrees.TreeNode; typeDecl: ModuleParser.TypeDecl);
  835. VAR n: ModuleParser.NodeList; newNode: WMTrees.TreeNode;
  836. BEGIN
  837. n := typeDecl;
  838. WHILE n # NIL DO
  839. newNode := AddIdentDef(parent, n, n(ModuleParser.TypeDecl).identDef, SortIgnore, ColorTypes, {WMGraphics.FontItalic});
  840. AddType(newNode, n(ModuleParser.TypeDecl).type, FALSE);
  841. n := n.next;
  842. END;
  843. END AddTypeDecl;
  844. PROCEDURE AddType(parent: WMTrees.TreeNode; type: ModuleParser.Type; anonymous: BOOLEAN);
  845. VAR newNode: WMTrees.TreeNode;
  846. BEGIN
  847. IF type # NIL THEN
  848. IF type.qualident # NIL THEN
  849. newNode := AddQualident(parent, type.qualident, treeView.clTextDefault.Get(), {});
  850. ELSIF type.array # NIL THEN
  851. AddArray(parent, type.array);
  852. ELSIF type.record # NIL THEN
  853. AddRecord(parent, type.record, anonymous, TRUE);
  854. ELSIF type.pointer # NIL THEN
  855. AddPointer(parent, type.pointer);
  856. ELSIF type.object # NIL THEN
  857. AddObject(parent, type.object, anonymous, TRUE);
  858. ELSIF type.procedure # NIL THEN
  859. AddProcedure(parent, type.procedure);
  860. END;
  861. END;
  862. END AddType;
  863. PROCEDURE AddRecord(parent: WMTrees.TreeNode; record: ModuleParser.Record; anonymous, addSuperRecords: BOOLEAN);
  864. VAR p: WMTrees.TreeNode;
  865. BEGIN
  866. IF record # NIL THEN
  867. IF anonymous THEN p := NewNode(parent, Strings.NewString("RECORD"));
  868. ELSE p := parent;
  869. END;
  870. IF addSuperRecords THEN AddSuperRecords(parent, record); END;
  871. IF record.super # NIL THEN
  872. AddPostfixToCaption(p, Strings.NewString(" ("));
  873. AddPostfixToCaption(p, record.super.ident.name);
  874. AddPostfixToCaption(p, Strings.NewString(")"));
  875. END;
  876. AddFieldDecl(p, record.fieldList);
  877. END;
  878. END AddRecord;
  879. PROCEDURE AddFieldDecl(parent: WMTrees.TreeNode; fieldDecl: ModuleParser.FieldDecl);
  880. VAR newNode: WMTrees.TreeNode; n, l: ModuleParser.NodeList;
  881. BEGIN
  882. n := fieldDecl;
  883. WHILE n # NIL DO
  884. l := n(ModuleParser.FieldDecl).identList;
  885. WHILE l # NIL DO
  886. newNode := AddIdentDef(parent, l, l(ModuleParser.IdentList).identDef, SortIgnore, treeView.clTextDefault.Get(), {});
  887. AddType(newNode, n(ModuleParser.FieldDecl).type, FALSE);
  888. l := l.next;
  889. END;
  890. n := n.next;
  891. END;
  892. END AddFieldDecl;
  893. PROCEDURE AddPointer(parent: WMTrees.TreeNode; pointer: ModuleParser.Pointer);
  894. VAR newNode: WMTrees.TreeNode;
  895. BEGIN
  896. IF pointer # NIL THEN
  897. newNode := NewNode(parent, Strings.NewString("POINTER TO"));
  898. IF (pointer.type # NIL) & (pointer.type.record # NIL) & (pointer.type.record.super # NIL) THEN
  899. AddPostfixToCaption(parent, Strings.NewString(" ("));
  900. AddPostfixToCaption(parent, pointer.type.record.super.ident.name);
  901. AddPostfixToCaption(parent, Strings.NewString(")"));
  902. END;
  903. AddType(newNode, pointer.type, TRUE);
  904. END;
  905. END AddPointer;
  906. PROCEDURE AddArray(parent: WMTrees.TreeNode; array: ModuleParser.Array);
  907. VAR newNode: WMTrees.TreeNode;
  908. BEGIN
  909. IF array # NIL THEN
  910. newNode := NewNode(parent, Strings.NewString("ARRAY "));
  911. IF ~array.open THEN
  912. IF (array.len # NIL) & (array.len.name # NIL) THEN
  913. AddPostfixToCaption(newNode, array.len.name);
  914. AddPostfixToCaption(newNode, Strings.NewString(" "));
  915. END;
  916. END;
  917. AddPostfixToCaption(newNode, Strings.NewString("OF"));
  918. AddType(newNode, array.base, TRUE);
  919. END;
  920. END AddArray;
  921. PROCEDURE NewNode(parent: WMTrees.TreeNode; caption: Strings.String): WMTrees.TreeNode;
  922. VAR newNode: WMTrees.TreeNode;
  923. BEGIN
  924. IF parent # NIL THEN
  925. NEW(newNode);
  926. tree.SetNodeCaption(newNode, caption);
  927. tree.AddChildNode(parent, newNode);
  928. END;
  929. RETURN newNode;
  930. END NewNode;
  931. PROCEDURE AddQualident(parent: WMTrees.TreeNode; qualident: ModuleParser.Qualident; color: LONGINT; style: SET):
  932. WMTrees.TreeNode;
  933. VAR newNode: WMTrees.TreeNode;
  934. n: ModuleParser.NodeList;
  935. BEGIN
  936. IF qualident # NIL THEN
  937. newNode := AddInfoItem(parent, qualident, qualident.ident, TRUE, SortIgnore, color, style);
  938. n := qualident.next;
  939. WHILE n # NIL DO
  940. AddPostfixToCaption(newNode, Strings.NewString(", "));
  941. AddPostfixToCaption(newNode, n(ModuleParser.Qualident).ident.name);
  942. n := n.next;
  943. END;
  944. END;
  945. RETURN newNode;
  946. END AddQualident;
  947. PROCEDURE AddSuperRecords(parent : WMTrees.TreeNode; record : ModuleParser.Record);
  948. VAR
  949. newNode : WMTrees.TreeNode;
  950. superRecord : ModuleParser.Record;
  951. moduleNode : ModuleParser.Module;
  952. node : ModuleParser.Node;
  953. typeDecl : ModuleParser.TypeDecl;
  954. caption : ARRAY 256 OF CHAR;
  955. info : TextInfo;
  956. BEGIN
  957. ASSERT(record # NIL);
  958. superRecord := record.superPtr;
  959. WHILE (superRecord # NIL) DO
  960. NEW(newNode);
  961. info := GetTextInfo(superRecord, NIL, TRUE, SortNo, WMGraphics.Black, {WMGraphics.FontItalic});
  962. tree.SetNodeData(newNode, info);
  963. caption := "";
  964. moduleNode := GetModuleNode(superRecord);
  965. IF (moduleNode # module) THEN
  966. Strings.Append(caption, moduleNode.ident.name^); Strings.Append(caption, ".");
  967. END;
  968. node := superRecord.parent.parent;
  969. WHILE (node # NIL) & ~(node IS ModuleParser.TypeDecl) DO node := node.parent; END;
  970. IF (node # NIL) THEN
  971. typeDecl := node (ModuleParser.TypeDecl);
  972. Strings.Append(caption, typeDecl.identDef.ident.name^);
  973. ELSE
  974. caption := "ERROR!";
  975. END;
  976. tree.SetNodeCaption(newNode, Strings.NewString(caption));
  977. tree.AddChildNode(parent, newNode);
  978. AddRecord(newNode, superRecord, FALSE, FALSE);
  979. info.color := WMGraphics.Black;
  980. superRecord := superRecord.superPtr;
  981. END;
  982. END AddSuperRecords;
  983. PROCEDURE AddSuperClasses(parent : WMTrees.TreeNode; object : ModuleParser.Object);
  984. VAR
  985. newNode : WMTrees.TreeNode;
  986. superClass : ModuleParser.Object;
  987. moduleNode : ModuleParser.Module;
  988. typeDecl : ModuleParser.TypeDecl;
  989. caption : ARRAY 256 OF CHAR;
  990. info : TextInfo;
  991. BEGIN
  992. ASSERT(object # NIL);
  993. superClass := object.superPtr;
  994. WHILE (superClass # NIL) DO
  995. NEW(newNode);
  996. info := GetTextInfo(superClass, NIL, TRUE, SortNo, WMGraphics.Black, {WMGraphics.FontItalic});
  997. tree.SetNodeData(newNode, info);
  998. caption := "";
  999. moduleNode := GetModuleNode(superClass);
  1000. IF (moduleNode # module) THEN
  1001. Strings.Append(caption, moduleNode.ident.name^); Strings.Append(caption, ".");
  1002. END;
  1003. typeDecl := superClass.parent.parent (ModuleParser.TypeDecl);
  1004. Strings.Append(caption, typeDecl.identDef.ident.name^);
  1005. tree.SetNodeCaption(newNode, Strings.NewString(caption));
  1006. tree.AddChildNode(parent, newNode);
  1007. AddObject(newNode, superClass, FALSE, FALSE);
  1008. info.color := WMGraphics.Black;
  1009. superClass := superClass.superPtr;
  1010. END;
  1011. END AddSuperClasses;
  1012. PROCEDURE AddObject(parent: WMTrees.TreeNode; object: ModuleParser.Object; anonymous, addSuperClasses: BOOLEAN);
  1013. VAR newNode, p: WMTrees.TreeNode; ptr : ANY; ti : TextInfo; image : WMGraphics.Image;
  1014. BEGIN
  1015. IF object # NIL THEN
  1016. IF anonymous THEN p := NewNode(parent, Strings.NewString("OBJECT"));
  1017. ELSE p := parent;
  1018. END;
  1019. ptr := tree.GetNodeData(p);
  1020. IF (ptr # NIL) & (ptr IS TextInfo) THEN
  1021. ti := ptr (TextInfo);
  1022. ti.color := ColorObjects;
  1023. ELSE ti := NIL;
  1024. END;
  1025. IF ModuleParser.Active IN object.modifiers THEN
  1026. IF (ti # NIL) THEN
  1027. ti.color := ColorActiveObjects;
  1028. END;
  1029. IF ShowImages THEN
  1030. image := WMGraphics.LoadImage(ImageActive, TRUE);
  1031. IF image # NIL THEN
  1032. tree.Acquire; tree.SetNodeImage(p, image); tree.Release;
  1033. END;
  1034. END;
  1035. END;
  1036. IF (object.super # NIL) & addSuperClasses THEN
  1037. AddPostfixToCaption(p, Strings.NewString(" ("));
  1038. AddPostfixToCaption(p, object.super.ident.name);
  1039. AddPostfixToCaption(p, Strings.NewString(")"));
  1040. END;
  1041. IF object.implements # NIL THEN
  1042. newNode := AddQualident(p, object.implements, treeView.clTextDefault.Get(), {});
  1043. AddPrefixToCaption(newNode, Strings.NewString("Implements "));
  1044. END;
  1045. IF addSuperClasses THEN
  1046. AddSuperClasses(p, object);
  1047. END;
  1048. IF object.declSeq # NIL THEN
  1049. AddDeclSeq(p, object.declSeq);
  1050. END;
  1051. IF object.bodyPos # 0 THEN
  1052. AddBody (p, object, object.modifiers, object.bodyPos);
  1053. END;
  1054. END;
  1055. END AddObject;
  1056. PROCEDURE AddProcedure(parent: WMTrees.TreeNode; proc: ModuleParser.Procedure);
  1057. VAR newNode: WMTrees.TreeNode;
  1058. BEGIN
  1059. IF proc # NIL THEN
  1060. newNode := NewNode(parent, Strings.NewString("PROCEDURE"));
  1061. IF proc.delegate THEN AddPostfixToCaption(newNode, Strings.NewString(" {DELEGATE}")) END;
  1062. AddFormalPars(newNode, proc.formalPars);
  1063. END;
  1064. END AddProcedure;
  1065. PROCEDURE PrefixPostfixToCaption(node: WMTrees.TreeNode; prePost: Strings.String; prefix: BOOLEAN);
  1066. VAR
  1067. oldCaption, newCaption: Strings.String;
  1068. len: LONGINT;
  1069. BEGIN
  1070. oldCaption := tree.GetNodeCaption(node);
  1071. len := LEN(oldCaption^) + LEN(prePost^);
  1072. NEW(newCaption, len);
  1073. IF prefix THEN
  1074. Strings.Concat(prePost^, oldCaption^, newCaption^);
  1075. ELSE
  1076. Strings.Concat(oldCaption^, prePost^, newCaption^);
  1077. END;
  1078. tree.SetNodeCaption(node, newCaption);
  1079. END PrefixPostfixToCaption;
  1080. PROCEDURE AddPrefixToCaption(node: WMTrees.TreeNode; prefix: Strings.String);
  1081. BEGIN
  1082. PrefixPostfixToCaption(node, prefix, TRUE);
  1083. END AddPrefixToCaption;
  1084. PROCEDURE AddPostfixToCaption(node: WMTrees.TreeNode; postfix: Strings.String);
  1085. BEGIN
  1086. PrefixPostfixToCaption(node, postfix, FALSE);
  1087. END AddPostfixToCaption;
  1088. PROCEDURE AddNumberPostfixToCaption(node : WMTrees.TreeNode; number : LONGINT);
  1089. VAR postfix, nbr : ARRAY 16 OF CHAR;
  1090. BEGIN
  1091. Strings.IntToStr(number, nbr);
  1092. postfix := " ("; Strings.Append(postfix, nbr); Strings.Append(postfix, ")");
  1093. PrefixPostfixToCaption(node, Strings.NewString(postfix), FALSE);
  1094. END AddNumberPostfixToCaption;
  1095. PROCEDURE AddIdentList(parent: WMTrees.TreeNode; identList: ModuleParser.IdentList; VAR nofIdents : LONGINT);
  1096. VAR n: ModuleParser.NodeList; newNode: WMTrees.TreeNode;
  1097. BEGIN
  1098. nofIdents := 0;
  1099. n := identList;
  1100. WHILE n # NIL DO
  1101. newNode := AddIdentDef(parent, n, n(ModuleParser.IdentList).identDef, SortIgnore, treeView.clTextDefault.Get(), {});
  1102. INC(nofIdents);
  1103. n := n.next;
  1104. END;
  1105. END AddIdentList;
  1106. PROCEDURE AddConstDecl(parent: WMTrees.TreeNode; constDecl: ModuleParser.ConstDecl);
  1107. VAR
  1108. n: ModuleParser.NodeList;
  1109. newNode: WMTrees.TreeNode;
  1110. c : ModuleParser.ConstDecl;
  1111. nofConstants : LONGINT;
  1112. BEGIN
  1113. n := constDecl; nofConstants := 0;
  1114. WHILE n # NIL DO
  1115. c := n (ModuleParser.ConstDecl);
  1116. newNode := AddIdentDef(parent, c, c.identDef, SortIgnore, treeView.clTextDefault.Get(), {});
  1117. newNode := AddInfoItem(newNode, c, c.expr, IsPublic(c.identDef), SortIgnore, treeView.clTextDefault.Get(), {});
  1118. INC(nofConstants);
  1119. n := n.next;
  1120. END;
  1121. AddNumberPostfixToCaption(parent, nofConstants);
  1122. END AddConstDecl;
  1123. PROCEDURE AddIdentDef(parent: WMTrees.TreeNode; node : ModuleParser.Node; identDef: ModuleParser.IdentDef; sortInfo, color: LONGINT; style: SET):
  1124. WMTrees.TreeNode;
  1125. VAR newNode: WMTrees.TreeNode;
  1126. BEGIN
  1127. IF identDef # NIL THEN
  1128. newNode := AddInfoItem(parent, node, identDef.ident, IsPublic(identDef), sortInfo, color, style);
  1129. IF identDef.vis = ModuleParser.Public THEN
  1130. AddPostfixToCaption(newNode, Strings.NewString("*"));
  1131. ELSIF identDef.vis = ModuleParser.PublicRO THEN
  1132. AddPostfixToCaption(newNode, Strings.NewString("-"));
  1133. END;
  1134. RETURN newNode;
  1135. ELSE
  1136. RETURN NIL;
  1137. END
  1138. END AddIdentDef;
  1139. PROCEDURE AddInfoItem(parent: WMTrees.TreeNode; node : ModuleParser.Node; infoItem: ModuleParser.InfoItem; isPublic : BOOLEAN; sortInfo, color : LONGINT; style: SET):
  1140. WMTrees.TreeNode;
  1141. VAR newNode: WMTrees.TreeNode;
  1142. BEGIN
  1143. IF (infoItem # NIL) & (parent # NIL) THEN
  1144. NEW(newNode);
  1145. tree.SetNodeData(newNode, GetTextInfo(node, infoItem, isPublic, sortInfo, color, style));
  1146. tree.SetNodeCaption(newNode, infoItem.name);
  1147. tree.AddChildNode(parent, newNode);
  1148. END;
  1149. RETURN newNode;
  1150. END AddInfoItem;
  1151. END ModuleTree;
  1152. VAR
  1153. PrototypeShowTypeHierarchy : WMProperties.BooleanProperty;
  1154. treeFontPlain, treeFontBold, treeFontItalic: WMGraphics.Font;
  1155. PROCEDURE GetColor(modifiers : SET; defaultColor : LONGINT) : LONGINT;
  1156. VAR color : LONGINT;
  1157. BEGIN
  1158. IF (ModuleParser.Exclusive IN modifiers) THEN color := ColorExclusive;
  1159. ELSIF (ModuleParser.HasExclusiveBlock IN modifiers) THEN color := ColorHasExclusiveBlock;
  1160. ELSE
  1161. color := defaultColor;
  1162. END;
  1163. RETURN color;
  1164. END GetColor;
  1165. VAR font : WMGraphics.Font;
  1166. BEGIN
  1167. NEW(PrototypeShowTypeHierarchy, NIL, Strings.NewString("ShowTypeHierarchy"), Strings.NewString("Show type hierarchy?"));
  1168. PrototypeShowTypeHierarchy.Set(FALSE);
  1169. font := WMGraphics.GetDefaultFont();
  1170. treeFontPlain := WMGraphics.GetFont(font.name, font.size, font.style);
  1171. treeFontBold := WMGraphics.GetFont(font.name, font.size, {WMGraphics.FontBold});
  1172. treeFontItalic := WMGraphics.GetFont(font.name, font.size, {WMGraphics.FontItalic});
  1173. END ModuleTrees.
  1174. Tar.Create ModuleTreesIcons.tar
  1175. activity.png
  1176. arrow-red.png
  1177. arrow-yellow.png
  1178. arrow-green.png
  1179. arrow-blue.png
  1180. ~