Gui.Mod 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. MODULE Gui;
  2. IMPORT G := Graph, Strings, Out;
  3. TYPE
  4. Caption* = POINTER TO CaptionDesc;
  5. CaptionDesc* = RECORD
  6. s*: ARRAY 100 OF CHAR
  7. END;
  8. DrawHandler* = PROCEDURE (W: Widget; x, y: INTEGER);
  9. MouseDownHandler* = PROCEDURE (W: Widget; x, y, btn: INTEGER);
  10. Widget* = POINTER TO WidgetDesc;
  11. WidgetDesc* = RECORD
  12. x*, y*, w*, h*: INTEGER;
  13. body*: Widget;
  14. text*: Caption;
  15. bmp*: G.Bitmap;
  16. parent*: Widget;
  17. prev*, next*: Widget;
  18. draw*: DrawHandler;
  19. (* Event Handlers *)
  20. onMouseDown*: MouseDownHandler
  21. END;
  22. Window* = POINTER TO WindowDesc;
  23. WindowDesc* = RECORD(WidgetDesc)
  24. win*: G.Window
  25. END;
  26. VAR
  27. Done*: BOOLEAN;
  28. exitRunLoop: BOOLEAN; (* See procedure Run *)
  29. font: G.Font;
  30. newWindowSettings: SET;
  31. ZZZ: INTEGER;
  32. globalWin: Window; (* !FIXME *)
  33. (* Widget *)
  34. PROCEDURE SetOnMouseDown*(W: Widget; handler: MouseDownHandler);
  35. BEGIN
  36. W.onMouseDown := handler
  37. END SetOnMouseDown;
  38. PROCEDURE InitWidget*(w: Widget);
  39. BEGIN
  40. w.x := 0; w.y := 0; w.w := 24; w.h := 24;
  41. w.draw := NIL;
  42. w.onMouseDown := NIL;
  43. (* Замок *)
  44. NEW(w.body); w.body.prev := w.body; w.body.next := w.body
  45. END InitWidget;
  46. PROCEDURE SetText*(w: Widget; s: ARRAY OF CHAR);
  47. BEGIN
  48. IF w.text = NIL THEN NEW(w.text) END;
  49. Strings.Copy(s, w.text.s)
  50. END SetText;
  51. PROCEDURE Place*(where, what: Widget; x, y: INTEGER);
  52. BEGIN
  53. what.x := x; what.y := y;
  54. (* Добавление в кольцо с замком *)
  55. what.prev := where.body.prev;
  56. what.next := where.body;
  57. where.body.prev.next := what;
  58. where.body.prev := what
  59. END Place;
  60. (* Window *)
  61. PROCEDURE NewWindowSettings*(settings: SET);
  62. BEGIN
  63. newWindowSettings := settings
  64. END NewWindowSettings;
  65. PROCEDURE DrawWidget(W: Widget; x, y: INTEGER);
  66. BEGIN
  67. W.draw(W, x + W.x, y + W.y)
  68. END DrawWidget;
  69. PROCEDURE DrawBody*(W: Widget; x, y: INTEGER);
  70. VAR p: Widget;
  71. BEGIN
  72. p := W.body.next;
  73. WHILE p # W.body DO
  74. DrawWidget(p, x, y);
  75. p := p.next
  76. END
  77. END DrawBody;
  78. PROCEDURE DrawWindow*(W: Widget; x, y: INTEGER);
  79. VAR c: G.Color;
  80. w, h: INTEGER;
  81. BEGIN
  82. G.MakeCol(c, ZZZ * 40 MOD 256, 120, 120);
  83. G.ClearToColor(c);
  84. G.MakeCol(c, 0, 0, ZZZ * 20 MOD 256);
  85. G.GetScreenSize(w, h);
  86. G.Rect(5, 5, w - 6, h - 6, c);
  87. DrawBody(W, x, y)
  88. END DrawWindow;
  89. PROCEDURE InitWindow*(win: Window; w, h: INTEGER);
  90. BEGIN
  91. InitWidget(win);
  92. win.win := G.NewWindow(-1, -1, w, h,
  93. 'Window', newWindowSettings);
  94. win.x := 0; win.y := 0;
  95. win.w := win.win.w; win.h := win.win.h;
  96. win.draw := DrawWindow
  97. END InitWindow;
  98. PROCEDURE NewWindow*(w, h: INTEGER): Window;
  99. VAR win: Window;
  100. BEGIN
  101. NEW(win);
  102. InitWindow(win, w, h);
  103. globalWin := win
  104. RETURN win END NewWindow;
  105. (* Draw *)
  106. PROCEDURE DrawAll;
  107. BEGIN
  108. globalWin.draw(globalWin, 0, 0);
  109. G.Flip
  110. END DrawAll;
  111. (* Fonts *)
  112. PROCEDURE GetFont*(W: Widget): G.Font;
  113. RETURN font END GetFont;
  114. (* General *)
  115. PROCEDURE TriggerOnMouseDown*(W: Widget; x, y, btn: INTEGER);
  116. BEGIN
  117. IF (W # NIL) & (W.onMouseDown # NIL) THEN
  118. W.onMouseDown(W, x, y, btn)
  119. END
  120. END TriggerOnMouseDown;
  121. PROCEDURE FindWidgetUnderMouse*(W: Widget; VAR x, y: INTEGER): Widget;
  122. VAR p: Widget;
  123. BEGIN
  124. IF W = NIL THEN p := W
  125. ELSIF W.body # NIL THEN
  126. p := W.body.prev;
  127. WHILE (p # W.body) &
  128. ~((p.x <= x) & (x < p.x + p.w) &
  129. (p.y <= y) & (y < p.y + p.h))
  130. DO p := p.prev
  131. END;
  132. IF p = W.body THEN p := W END
  133. ELSE p := NIL
  134. END
  135. RETURN p END FindWidgetUnderMouse;
  136. PROCEDURE HandleMouseDownEvent*(e: G.Event);
  137. VAR W: Widget;
  138. x, y: INTEGER;
  139. BEGIN
  140. x := e.x; y := e.y;
  141. W := FindWidgetUnderMouse(globalWin, x, y);
  142. TriggerOnMouseDown(W, x, y, e.button)
  143. END HandleMouseDownEvent;
  144. PROCEDURE HandleEvent(e: G.Event);
  145. BEGIN
  146. IF e.type = G.mouseDown THEN
  147. HandleMouseDownEvent(e)
  148. ELSIF e.type = G.keyDown THEN
  149. IF e.key = G.kEsc THEN exitRunLoop := TRUE END;
  150. INC(ZZZ)
  151. ELSIF e.type = G.quit THEN
  152. exitRunLoop := TRUE
  153. END
  154. END HandleEvent;
  155. PROCEDURE Run*;
  156. VAR e: G.Event;
  157. BEGIN
  158. exitRunLoop := FALSE;
  159. REPEAT
  160. WHILE G.HasEvents() DO
  161. G.WaitEvent(e);
  162. HandleEvent(e)
  163. END;
  164. DrawAll
  165. UNTIL exitRunLoop
  166. END Run;
  167. PROCEDURE Init*;
  168. BEGIN
  169. G.Settings(0, 0, {G.manual});
  170. G.Init;
  171. IF G.Done THEN
  172. font := G.LoadFont('../Data/Fonts/Main');
  173. IF font = NIL THEN
  174. Out.String('Gui: Could not load font.'); Out.Ln;
  175. Done := FALSE
  176. END
  177. ELSE Done := FALSE
  178. END
  179. END Init;
  180. PROCEDURE Close*;
  181. BEGIN
  182. G.Close
  183. END Close;
  184. BEGIN
  185. Done := TRUE;
  186. ZZZ := 0
  187. END Gui.