MenuViewers.Mod.txt 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. MODULE MenuViewers; (*JG 26.8.90 / 16.9.93 / NW 10.3.2013*)
  2. IMPORT Input, Display, Viewers, Oberon;
  3. CONST extend* = 0; reduce* = 1; FrameColor = Display.white;
  4. TYPE Viewer* = POINTER TO ViewerDesc;
  5. ViewerDesc* = RECORD (Viewers.ViewerDesc)
  6. menuH*: INTEGER
  7. END;
  8. ModifyMsg* = RECORD (Display.FrameMsg)
  9. id*: INTEGER;
  10. dY*, Y*, H*: INTEGER
  11. END;
  12. PROCEDURE Copy (V: Viewer; VAR V1: Viewer);
  13. VAR Menu, Main: Display.Frame; M: Oberon.CopyMsg;
  14. BEGIN Menu := V.dsc; Main := V.dsc.next;
  15. NEW(V1); V1^ := V^; V1.state := 0;
  16. M.F := NIL; Menu.handle(Menu, M); V1.dsc := M.F;
  17. M.F := NIL; Main.handle(Main, M); V1.dsc.next := M.F
  18. END Copy;
  19. PROCEDURE Draw (V: Viewers.Viewer);
  20. BEGIN
  21. Display.ReplConst(FrameColor, V.X, V.Y, 1, V.H, Display.replace);
  22. Display.ReplConst(FrameColor, V.X + V.W - 1, V.Y, 1, V.H, Display.replace);
  23. Display.ReplConst(FrameColor, V.X + 1, V.Y, V.W - 2, 1, Display.replace);
  24. Display.ReplConst(FrameColor, V.X + 1, V.Y + V.H - 1, V.W - 2, 1, Display.replace)
  25. END Draw;
  26. PROCEDURE Extend (V: Viewer; newY: INTEGER);
  27. VAR dH: INTEGER;
  28. BEGIN dH := V.Y - newY;
  29. IF dH > 0 THEN
  30. Display.ReplConst(Display.black, V.X + 1, newY + 1, V.W - 2, dH, Display.replace);
  31. Display.ReplConst(FrameColor, V.X, newY, 1, dH, Display.replace);
  32. Display.ReplConst(FrameColor, V.X + V.W - 1, newY, 1, dH, Display.replace);
  33. Display.ReplConst(FrameColor, V.X + 1, newY, V.W - 2, 1, Display.replace)
  34. END
  35. END Extend;
  36. PROCEDURE Reduce (V: Viewer; newY: INTEGER);
  37. BEGIN Display.ReplConst(FrameColor, V.X + 1, newY, V.W - 2, 1, Display.replace)
  38. END Reduce;
  39. PROCEDURE Grow (V: Viewer; oldH: INTEGER);
  40. VAR dH: INTEGER;
  41. BEGIN dH := V.H - oldH;
  42. IF dH > 0 THEN
  43. Display.ReplConst(FrameColor, V.X, V.Y + oldH, 1, dH, Display.replace);
  44. Display.ReplConst(FrameColor, V.X + V.W - 1, V.Y + oldH, 1, dH, Display.replace);
  45. Display.ReplConst(FrameColor, V.X + 1, V.Y + V.H - 1, V.W - 2, 1, Display.replace)
  46. END
  47. END Grow;
  48. PROCEDURE Shrink (V: Viewer; newH: INTEGER);
  49. BEGIN Display.ReplConst(FrameColor, V.X + 1, V.Y + newH - 1, V.W - 2, 1, Display.replace)
  50. END Shrink;
  51. PROCEDURE Adjust (F: Display.Frame; id, dY, Y, H: INTEGER);
  52. VAR M: ModifyMsg;
  53. BEGIN M.id := id; M.dY := dY; M.Y := Y; M.H := H; F.handle(F, M); F.Y := Y; F.H := H
  54. END Adjust;
  55. PROCEDURE Restore (V: Viewer);
  56. VAR Menu, Main: Display.Frame;
  57. BEGIN Menu := V.dsc; Main := V.dsc.next;
  58. Oberon.RemoveMarks(V.X, V.Y, V.W, V.H);
  59. Draw(V);
  60. Menu.X := V.X + 1; Menu.Y := V.Y + V.H - 1; Menu.W := V.W - 2; Menu.H := 0;
  61. Main.X := V.X + 1; Main.Y := V.Y + V.H - V.menuH; Main.W := V.W - 2; Main.H := 0;
  62. IF V.H > V.menuH + 1 THEN
  63. Adjust(Menu, extend, 0, V.Y + V.H - V.menuH, V.menuH - 1);
  64. Adjust(Main, extend, 0, V.Y + 1, V.H - V.menuH - 1)
  65. ELSE Adjust(Menu, extend, 0, V.Y + 1, V.H - 2)
  66. END
  67. END Restore;
  68. PROCEDURE Modify (V: Viewer; Y, H: INTEGER);
  69. VAR Menu, Main: Display.Frame;
  70. BEGIN Menu := V.dsc; Main := V.dsc.next;
  71. IF Y < V.Y THEN (*extend*)
  72. Oberon.RemoveMarks(V.X, Y, V.W, V.Y - Y);
  73. Extend(V, Y);
  74. IF H > V.menuH + 1 THEN
  75. Adjust(Menu, extend, 0, Y + H - V.menuH, V.menuH - 1);
  76. Adjust(Main, extend, 0, Y + 1, H - V.menuH - 1)
  77. ELSE Adjust(Menu, extend, 0, Y + 1, H - 2)
  78. END
  79. ELSIF Y > V.Y THEN (*reduce*)
  80. Oberon.RemoveMarks(V.X, V.Y, V.W, V.H);
  81. IF H > V.menuH + 1 THEN
  82. Adjust(Main, reduce, 0, Y + 1, H - V.menuH - 1);
  83. Adjust(Menu, reduce, 0, Y + H - V.menuH, V.menuH - 1)
  84. ELSE
  85. Adjust(Main, reduce, 0, Y + H - V.menuH, 0);
  86. Adjust(Menu, reduce, 0, Y + 1, H - 2)
  87. END;
  88. Reduce(V, Y)
  89. END
  90. END Modify;
  91. PROCEDURE Change (V: Viewer; X, Y: INTEGER; Keys: SET);
  92. VAR Menu, Main: Display.Frame;
  93. V1: Viewers.Viewer;
  94. keysum: SET; Y0, dY, H: INTEGER;
  95. BEGIN (*Keys # {}*)
  96. Menu := V.dsc; Main := V.dsc.next;
  97. Oberon.DrawMouseArrow(X, Y);
  98. Display.ReplConst(Display.white, V.X + 1, V.Y + V.H - 1 - V.dsc.H, V.W - 2, V.dsc.H, Display.invert);
  99. Y0 := Y; keysum := Keys; Input.Mouse(Keys, X, Y);
  100. WHILE Keys # {} DO
  101. keysum := keysum + Keys;
  102. Oberon.DrawMouseArrow(X, Y); Input.Mouse(Keys, X, Y)
  103. END;
  104. Display.ReplConst(Display.white, V.X + 1, V.Y + V.H - 1 - V.dsc.H, V.W - 2, V.dsc.H, Display.invert);
  105. IF ~(0 IN keysum) THEN
  106. IF 1 IN keysum THEN V1 := Viewers.This(X, Y);
  107. IF (V1 IS Viewer) & (Y > V1.Y + V1.H - V1(Viewer).menuH - 2) THEN Y := V1.Y + V1.H END;
  108. IF Y < V1.Y + V.menuH + 2 THEN Y := V1.Y + V.menuH + 2 END;
  109. Viewers.Close(V); Viewers.Open(V, X, Y); Restore(V)
  110. ELSE
  111. IF Y > Y0 THEN (*extend*) dY := Y - Y0;
  112. V1 := Viewers.Next(V);
  113. IF V1.state > 1 THEN
  114. CASE V1 OF
  115. Viewer:
  116. IF V1.H < V1.menuH + 2 THEN dY := 0
  117. ELSIF V1.H < V1.menuH + 2 + dY THEN dY := V1.H - V1.menuH - 2
  118. END |
  119. Viewers.Viewer: IF V1.H < 1 + dY THEN dY := V1.H - 1 END
  120. END
  121. ELSIF V1.H < dY THEN dY := V1.H
  122. END;
  123. Viewers.Change(V, V.Y + V.H + dY);
  124. Oberon.RemoveMarks(V.X, V.Y, V.W, V.H);
  125. Grow(V, V.H - dY);
  126. IF V.H > V.menuH + 1 THEN
  127. Adjust(Menu, extend, dY, V.Y + V.H - V.menuH, V.menuH - 1);
  128. Adjust(Main, extend, dY, V.Y + 1, V.H - V.menuH - 1)
  129. ELSE (*V.H > 1*)
  130. Adjust(Menu, extend, dY, V.Y + 1, V.H - 2);
  131. Adjust(Main, extend, dY, V.Y + V.H - V.menuH, 0)
  132. END
  133. ELSIF Y < Y0 THEN (*reduce*) dY := Y0 - Y;
  134. IF V.H >= V.menuH + 2 THEN
  135. IF V.H < V.menuH + 2 + dY THEN dY := V.H - V.menuH - 2 END;
  136. Oberon.RemoveMarks(V.X, V.Y, V.W, V.H);
  137. H := V.H - dY;
  138. Adjust(Main, reduce, dY, V.Y + 1, H - V.menuH - 1);
  139. Adjust(Menu, reduce, dY, V.Y + H - V.menuH, V.menuH - 1);
  140. Shrink(V, H); Viewers.Change(V, V.Y + H)
  141. END
  142. END
  143. END
  144. END
  145. END Change;
  146. PROCEDURE Suspend (V: Viewer);
  147. VAR Menu, Main: Display.Frame;
  148. BEGIN Menu := V.dsc; Main := V.dsc.next;
  149. Adjust(Main, reduce, 0, V.Y + V.H - V.menuH, 0);
  150. Adjust(Menu, reduce, 0, V.Y + V.H - 1, 0)
  151. END Suspend;
  152. PROCEDURE Handle* (V: Display.Frame; VAR M: Display.FrameMsg);
  153. VAR X, Y: INTEGER;
  154. Menu, Main: Display.Frame; V1: Viewer;
  155. BEGIN Menu := V.dsc; Main := V.dsc.next;
  156. CASE M OF
  157. Oberon.InputMsg:
  158. IF M.id = Oberon.track THEN
  159. X := M.X; Y := M.Y;
  160. IF Y < V.Y + 1 THEN Oberon.DrawMouseArrow(X, Y)
  161. ELSIF Y < V.Y + V.H - V(Viewer).menuH THEN Main.handle(Main, M)
  162. ELSIF Y < V.Y + V.H - V(Viewer).menuH + 2 THEN Menu.handle(Menu, M)
  163. ELSIF Y < V.Y + V.H - 1 THEN
  164. IF 2 IN M.keys THEN Change(V(Viewer), X, Y, M.keys) ELSE Menu.handle(Menu, M) END
  165. ELSE Oberon.DrawMouseArrow(X, Y)
  166. END
  167. ELSE Menu.handle(Menu, M); Main.handle(Main, M)
  168. END |
  169. Oberon.ControlMsg:
  170. IF M.id = Oberon.mark THEN
  171. X := M.X; Y := M.Y; Oberon.DrawMouseArrow(X, Y); Oberon.DrawPointer(X, Y)
  172. ELSE Menu.handle(Menu, M); Main.handle(Main, M)
  173. END |
  174. Oberon.CopyMsg:
  175. Copy(V(Viewer), V1); M.F := V1 |
  176. Viewers.ViewerMsg:
  177. IF M.id = Viewers.restore THEN Restore(V(Viewer))
  178. ELSIF M.id = Viewers.modify THEN Modify(V(Viewer), M.Y, M.H)
  179. ELSIF M.id = Viewers.suspend THEN Suspend(V(Viewer))
  180. END |
  181. Display.FrameMsg: Menu.handle(Menu, M); Main.handle(Main, M)
  182. END
  183. END Handle;
  184. PROCEDURE New* (Menu, Main: Display.Frame; menuH, X, Y: INTEGER): Viewer;
  185. VAR V: Viewer;
  186. BEGIN NEW(V);
  187. V.handle := Handle; V.dsc := Menu; V.dsc.next := Main; V.menuH := menuH;
  188. Viewers.Open(V, X, Y); Restore(V); RETURN V
  189. END New;
  190. END MenuViewers.