Subversion Repositories Kolibri OS

Rev

Rev 8762 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. (*
  2.     Copyright 2021 Anton Krotov
  3.  
  4.     This file is part of CEdit.
  5.  
  6.     CEdit is free software: you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation, either version 3 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     CEdit is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with CEdit. If not, see <http://www.gnu.org/licenses/>.
  18. *)
  19.  
  20. MODULE Menu;
  21.  
  22. IMPORT
  23.     SYSTEM, G := Graph, List, K := KolibriOS;
  24.  
  25. CONST
  26.     fontHeight = 20;
  27.     fontWidth = 8;
  28.  
  29.     RIGHT = 16;
  30.     LEFT = 16;
  31.     TOP = 1;
  32.  
  33.     backColor = 0F0F0F0H;
  34.     foreColor = 0;
  35.     selBackColor = 091C9F7H;
  36.     selForeColor = 0;
  37.     disBackColor = backColor;
  38.     disForeColor = 808080H;
  39.     disSelBackColor = 0E4E4E4H;
  40.     disSelForeColor = disForeColor;
  41.  
  42.  
  43. TYPE
  44.     tItem* = POINTER TO RECORD (List.tItem)
  45.         id*, check: INTEGER;
  46.         text: ARRAY 32 OF WCHAR;
  47.         enabled, delim: BOOLEAN
  48.     END;
  49.  
  50.     tMenu* = POINTER TO RECORD
  51.         (*stack: POINTER TO RECORD stk: ARRAY 250000 OF INTEGER END;*)
  52.         tid*: INTEGER;
  53.         winX, winY, width*, height*: INTEGER;
  54.         selItem, cliItem: INTEGER;
  55.  
  56.         font: G.tFont;
  57.         canvas: G.tCanvas;
  58.  
  59.         items: List.tList;
  60.         click: PROCEDURE (menu: tMenu; id: INTEGER);
  61.         key: PROCEDURE (menu: tMenu; key: INTEGER): BOOLEAN
  62.     END;
  63.  
  64.     tClick = PROCEDURE (menu: tMenu; id: INTEGER);
  65.     tKey = PROCEDURE (menu: tMenu; key: INTEGER): BOOLEAN;
  66.  
  67. VAR
  68.     lastTID*: INTEGER;
  69.     stack: ARRAY 250000 OF INTEGER;
  70.  
  71.  
  72. PROCEDURE exit (m: tMenu);
  73. BEGIN
  74.     m.tid := 0;
  75.     K.Exit
  76. END exit;
  77.  
  78.  
  79. PROCEDURE repaint (m: tMenu);
  80. VAR
  81.     y, i: INTEGER;
  82.     item: tItem;
  83.     BkColor, TextColor: INTEGER;
  84.     canvas: G.tCanvas;
  85.  
  86. BEGIN
  87.     canvas := m.canvas;
  88.     G.SetColor(canvas, backColor);
  89.     G.clear(canvas);
  90.     G.SetColor(canvas, ORD((-BITS(backColor))*{0..23}) );
  91.     G.Rect(canvas, 0, 0, m.width, m.height);
  92.     y := TOP;
  93.     i := 0;
  94.     item := m.items.first(tItem);
  95.     WHILE item # NIL DO
  96.         IF item.enabled THEN
  97.             IF i # m.selItem THEN
  98.                 BkColor := backColor;
  99.                 TextColor := foreColor
  100.             ELSE
  101.                 BkColor := selBackColor;
  102.                 TextColor := selForeColor
  103.             END
  104.         ELSE
  105.             IF i # m.selItem THEN
  106.                 BkColor := disBackColor;
  107.                 TextColor := disForeColor
  108.             ELSE
  109.                 BkColor := disSelBackColor;
  110.                 TextColor := disSelForeColor
  111.             END
  112.         END;
  113.         G.SetColor(canvas, BkColor);
  114.         G.FillRect(canvas, 1, y, m.width - 1, y + fontHeight - 4);
  115.         G.SetTextColor(canvas, TextColor);
  116.         G.SetBkColor(canvas, BkColor);
  117.         G.TextOut2(canvas, LEFT, y + (fontHeight - 16) DIV 2 - 2, item.text, LENGTH(item.text));
  118.  
  119.         IF item.check = 1 THEN
  120.             G.SetColor(canvas, TextColor);
  121.             G.DLine(canvas, 4, 7, y + (fontHeight - 16) DIV 2 + 5, -1);
  122.             G.DLine(canvas, 4, 7, y + (fontHeight - 16) DIV 2 + 6, -1);
  123.             G.DLine(canvas, 7, 12, y + (fontHeight - 16) DIV 2 + 8, 1);
  124.             G.DLine(canvas, 7, 12, y + (fontHeight - 16) DIV 2 + 9, 1);
  125.         ELSIF item.check = 2 THEN
  126.             G.SetColor(canvas, TextColor);
  127.             G.FillRect(canvas, 6, y + fontHeight DIV 2 - 4, 10, y + fontHeight DIV 2)
  128.         END;
  129.  
  130.         INC(y, fontHeight);
  131.         IF item.delim THEN
  132.             G.SetColor(canvas, ORD((-BITS(backColor))*{0..23}));
  133.             G.HLine(canvas, y - 2, 1, m.width - 1)
  134.         END;
  135.         INC(i);
  136.         item := item.next(tItem)
  137.     END;
  138.     G.DrawCanvas(canvas, 0, 0)
  139. END repaint;
  140.  
  141.  
  142. PROCEDURE draw_window (m: tMenu);
  143. BEGIN
  144.     K.BeginDraw;
  145.     K.CreateWindow(m.winX, m.winY, m.width, m.height, 0, 61H, 0, 1, "");
  146.     repaint(m);
  147.     K.EndDraw
  148. END draw_window;
  149.  
  150.  
  151. PROCEDURE mouse (m: tMenu; VAR x, y: INTEGER);
  152. VAR
  153.     mouseX, mouseY: INTEGER;
  154. BEGIN
  155.     K.MousePos(mouseX, mouseY);
  156.     x := mouseX - m.winX;
  157.     y := mouseY - m.winY;
  158. END mouse;
  159.  
  160.  
  161. PROCEDURE click (m: tMenu; i: INTEGER);
  162. VAR
  163.     item: List.tItem;
  164. BEGIN
  165.     item := List.getItem(m.items, i);
  166.     IF item(tItem).enabled THEN
  167.         m.click(m, item(tItem).id);
  168.         exit(m)
  169.     END
  170. END click;
  171.  
  172.  
  173. PROCEDURE [stdcall] window (m: tMenu);
  174. VAR
  175.     x, y: INTEGER;
  176.     key: INTEGER;
  177.     msState: SET;
  178. BEGIN
  179.     m.selItem := -1;
  180.     m.cliItem := -1;
  181.     K.SetEventsMask({0, 1, 5});
  182.     WHILE TRUE DO
  183.         CASE K.WaitForEvent() OF
  184.         |1:
  185.             draw_window(m)
  186.         |2:
  187.             key := K.GetKey();
  188.             IF key DIV 65536 = 72 THEN
  189.                 DEC(m.selItem);
  190.                 IF m.selItem < 0 THEN
  191.                     m.selItem := 0
  192.                 END
  193.             ELSIF key DIV 65536 = 80 THEN
  194.                 INC(m.selItem);
  195.                 IF m.selItem >= m.items.count THEN
  196.                     m.selItem := m.items.count - 1
  197.                 END
  198.             ELSIF key DIV 65536 = 28 THEN
  199.                 IF m.selItem >= 0 THEN
  200.                     click(m, m.selItem)
  201.                 END;
  202.                 m.cliItem := -1
  203.             ELSE
  204.                 IF m.key(m, key) THEN
  205.                     exit(m)
  206.                 END
  207.             END;
  208.             repaint(m)
  209.         |6:
  210.             msState := K.MouseState();
  211.             mouse(m, x, y);
  212.             IF (0 <= x) & (x < m.width) & (0 <= y) & (y < m.height) THEN
  213.                 m.selItem := (y - TOP) DIV fontHeight;
  214.                 IF 8 IN msState THEN
  215.                     m.cliItem := (y - TOP) DIV fontHeight
  216.                 END;
  217.                 IF 16 IN msState THEN
  218.                     IF m.cliItem = m.selItem THEN
  219.                         click(m, m.cliItem)
  220.                     END;
  221.                     m.cliItem := -1
  222.                 END
  223.             ELSE
  224.                 m.cliItem := -1;
  225.                 IF {8, 9, 10} * msState # {} THEN
  226.                     exit(m)
  227.                 END
  228.             END;
  229.             repaint(m)
  230.         END
  231.     END
  232. END window;
  233.  
  234.  
  235. PROCEDURE AddMenuItem* (items: List.tList; id: INTEGER; s: ARRAY OF WCHAR);
  236. VAR
  237.     item: tItem;
  238. BEGIN
  239.     NEW(item);
  240.     item.id := id;
  241.     item.text := s;
  242.     item.enabled := TRUE;
  243.     item.delim := FALSE;
  244.     List.append(items, item);
  245. END AddMenuItem;
  246.  
  247.  
  248. PROCEDURE delimiter* (items: List.tList);
  249. BEGIN
  250.     items.last(tItem).delim := TRUE
  251. END delimiter;
  252.  
  253.  
  254. PROCEDURE getItem (m: tMenu; id: INTEGER): tItem;
  255. VAR
  256.     item: tItem;
  257. BEGIN
  258.     item := m.items.first(tItem);
  259.     WHILE (item # NIL) & (item.id # id) DO
  260.         item := item.next(tItem)
  261.     END
  262.     RETURN item
  263. END getItem;
  264.  
  265.  
  266. PROCEDURE setEnabled* (m: tMenu; id: INTEGER; value: BOOLEAN);
  267. VAR
  268.     item: tItem;
  269. BEGIN
  270.     item := getItem(m, id);
  271.     IF item # NIL THEN
  272.         item.enabled := value
  273.     END
  274. END setEnabled;
  275.  
  276.  
  277. PROCEDURE setCheck* (m: tMenu; id: INTEGER; value: INTEGER);
  278. VAR
  279.     item: tItem;
  280. BEGIN
  281.     item := getItem(m, id);
  282.     IF item # NIL THEN
  283.         item.check := value
  284.     END
  285. END setCheck;
  286.  
  287.  
  288. PROCEDURE isEnabled* (m: tMenu; id: INTEGER): BOOLEAN;
  289. VAR
  290.     item: tItem;
  291. BEGIN
  292.     item := getItem(m, id)
  293.     RETURN (item # NIL) & item.enabled
  294. END isEnabled;
  295.  
  296.  
  297. PROCEDURE opened* (m: tMenu): BOOLEAN;
  298.     RETURN m.tid # 0
  299. END opened;
  300.  
  301.  
  302. PROCEDURE open* (m: tMenu; x, y: INTEGER);
  303. BEGIN
  304.     IF m.tid = 0 THEN
  305.         m.winX := x;
  306.         m.winY := y;
  307. (*        DISPOSE(m.stack);
  308.         NEW(m.stack);
  309.         SYSTEM.PUT(SYSTEM.ADR(m.stack.stk[LEN(m.stack.stk) - 1]), m);
  310.         lastTID := K.CreateThread(SYSTEM.ADR(window), m.stack.stk);*)
  311.         SYSTEM.PUT(SYSTEM.ADR(stack[LEN(stack) - 1]), m);
  312.         lastTID := K.CreateThread(SYSTEM.ADR(window), stack);
  313.         m.tid := lastTID
  314.     END
  315. END open;
  316.  
  317.  
  318. PROCEDURE close* (m: tMenu);
  319. BEGIN
  320.     IF m.tid # 0 THEN
  321.         K.ExitID(m.tid);
  322.         (*DISPOSE(m.stack);*)
  323.         m.tid := 0
  324.     END
  325. END close;
  326.  
  327.  
  328. PROCEDURE create* (items: List.tList; click: tClick; key: tKey): tMenu;
  329. VAR
  330.     m: tMenu;
  331.     maxLength: INTEGER;
  332.     item: tItem;
  333. BEGIN
  334.     NEW(m);
  335.     m.tid := 0;
  336.     m.items  := items;
  337.     m.click := click;
  338.     m.key := key;
  339.     maxLength := 0;
  340.     item := items.first(tItem);
  341.     WHILE item # NIL DO
  342.         maxLength := MAX(maxLength, LENGTH(item.text));
  343.         item := item.next(tItem)
  344.     END;
  345.     m.width  := maxLength*fontWidth + LEFT + RIGHT;
  346.     m.height := items.count*fontHeight - 2;
  347.     m.font := G.CreateFont(1, "", {});
  348.     m.canvas := G.CreateCanvas(m.width + 1, m.height + 1);
  349.     (*m.stack := NIL;*)
  350.     G.SetFont(m.canvas, m.font);
  351.     RETURN m
  352. END create;
  353.  
  354.  
  355. BEGIN
  356.     lastTID := 0
  357. END Menu.