Subversion Repositories Kolibri OS

Rev

Rev 8728 | Rev 9174 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8728 leency 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 .
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
        tid*: INTEGER;
52
        winX, winY, width*, height*: INTEGER;
53
        selItem, cliItem: INTEGER;
54
 
55
        font: G.tFont;
56
        canvas: G.tCanvas;
57
 
58
        items: List.tList;
59
        click: PROCEDURE (menu: tMenu; id: INTEGER);
60
        key: PROCEDURE (menu: tMenu; key: INTEGER): BOOLEAN
61
    END;
62
 
63
    tClick = PROCEDURE (menu: tMenu; id: INTEGER);
64
    tKey = PROCEDURE (menu: tMenu; key: INTEGER): BOOLEAN;
65
 
66
VAR
67
    lastTID*: INTEGER;
68
    stack: ARRAY 250000 OF INTEGER;
69
 
70
 
71
PROCEDURE exit (m: tMenu);
72
BEGIN
73
    m.tid := 0;
74
    K.Exit
75
END exit;
76
 
77
 
78
PROCEDURE repaint (m: tMenu);
79
VAR
80
    y, i: INTEGER;
81
    item: tItem;
82
    BkColor, TextColor: INTEGER;
83
    canvas: G.tCanvas;
84
 
85
BEGIN
86
    canvas := m.canvas;
87
    G.SetColor(canvas, backColor);
88
    G.clear(canvas);
89
    G.SetColor(canvas, ORD((-BITS(backColor))*{0..23}) );
90
    G.Rect(canvas, 0, 0, m.width, m.height);
91
    y := TOP;
92
    i := 0;
93
    item := m.items.first(tItem);
94
    WHILE item # NIL DO
95
        IF item.enabled THEN
96
            IF i # m.selItem THEN
97
                BkColor := backColor;
98
                TextColor := foreColor
99
            ELSE
100
                BkColor := selBackColor;
101
                TextColor := selForeColor
102
            END
103
        ELSE
104
            IF i # m.selItem THEN
105
                BkColor := disBackColor;
106
                TextColor := disForeColor
107
            ELSE
108
                BkColor := disSelBackColor;
109
                TextColor := disSelForeColor
110
            END
111
        END;
112
        G.SetColor(canvas, BkColor);
113
        G.FillRect(canvas, 1, y, m.width - 1, y + fontHeight - 4);
114
        G.SetTextColor(canvas, TextColor);
115
        G.SetBkColor(canvas, BkColor);
116
        G.TextOut2(canvas, LEFT, y + (fontHeight - 16) DIV 2 - 2, item.text, LENGTH(item.text));
117
 
118
        IF item.check = 1 THEN
119
            G.SetColor(canvas, TextColor);
120
            G.DLine(canvas, 4, 7, y + (fontHeight - 16) DIV 2 + 5, -1);
121
            G.DLine(canvas, 4, 7, y + (fontHeight - 16) DIV 2 + 6, -1);
122
            G.DLine(canvas, 7, 12, y + (fontHeight - 16) DIV 2 + 8, 1);
123
            G.DLine(canvas, 7, 12, y + (fontHeight - 16) DIV 2 + 9, 1);
124
        ELSIF item.check = 2 THEN
125
            G.SetColor(canvas, TextColor);
126
            G.FillRect(canvas, 6, y + fontHeight DIV 2 - 4, 10, y + fontHeight DIV 2)
127
        END;
128
 
129
        INC(y, fontHeight);
130
        IF item.delim THEN
131
            G.SetColor(canvas, ORD((-BITS(backColor))*{0..23}));
132
            G.HLine(canvas, y - 2, 1, m.width - 1)
133
        END;
134
        INC(i);
135
        item := item.next(tItem)
136
    END;
137
    G.DrawCanvas(canvas, 0, 0)
138
END repaint;
139
 
140
 
141
PROCEDURE draw_window (m: tMenu);
142
BEGIN
143
    K.BeginDraw;
144
    K.CreateWindow(m.winX, m.winY, m.width, m.height, 0, 61H, 0, 1, "");
145
    repaint(m);
146
    K.EndDraw
147
END draw_window;
148
 
149
 
150
PROCEDURE mouse (m: tMenu; VAR x, y: INTEGER);
151
VAR
152
    mouseX, mouseY: INTEGER;
153
BEGIN
154
    K.MousePos(mouseX, mouseY);
155
    x := mouseX - m.winX;
156
    y := mouseY - m.winY;
157
END mouse;
158
 
159
 
160
PROCEDURE click (m: tMenu; i: INTEGER);
161
VAR
162
    item: List.tItem;
163
BEGIN
164
    item := List.getItem(m.items, i);
8762 leency 165
    IF (item # NIL) & item(tItem).enabled THEN
8728 leency 166
        m.click(m, item(tItem).id);
167
        exit(m)
168
    END
169
END click;
170
 
171
 
172
PROCEDURE [stdcall] window (m: tMenu);
173
VAR
174
    x, y: INTEGER;
175
    key: INTEGER;
176
    msState: SET;
177
BEGIN
178
    m.selItem := -1;
179
    m.cliItem := -1;
180
    K.SetEventsMask({0, 1, 5});
181
    WHILE TRUE DO
182
        CASE K.WaitForEvent() OF
183
        |1:
184
            draw_window(m)
185
        |2:
186
            key := K.GetKey();
187
            IF key DIV 65536 = 72 THEN
188
                DEC(m.selItem);
189
                IF m.selItem < 0 THEN
190
                    m.selItem := 0
191
                END
192
            ELSIF key DIV 65536 = 80 THEN
193
                INC(m.selItem);
194
                IF m.selItem >= m.items.count THEN
195
                    m.selItem := m.items.count - 1
196
                END
197
            ELSIF key DIV 65536 = 28 THEN
198
                IF m.selItem >= 0 THEN
199
                    click(m, m.selItem)
200
                END;
201
                m.cliItem := -1
202
            ELSE
203
                IF m.key(m, key) THEN
204
                    exit(m)
205
                END
206
            END;
207
            repaint(m)
208
        |6:
209
            msState := K.MouseState();
210
            mouse(m, x, y);
211
            IF (0 <= x) & (x < m.width) & (0 <= y) & (y < m.height) THEN
212
                m.selItem := (y - TOP) DIV fontHeight;
213
                IF 8 IN msState THEN
214
                    m.cliItem := (y - TOP) DIV fontHeight
215
                END;
216
                IF 16 IN msState THEN
217
                    IF m.cliItem = m.selItem THEN
218
                        click(m, m.cliItem)
219
                    END;
220
                    m.cliItem := -1
221
                END
222
            ELSE
223
                m.cliItem := -1;
224
                IF {8, 9, 10} * msState # {} THEN
225
                    exit(m)
226
                END
227
            END;
228
            repaint(m)
229
        END
230
    END
231
END window;
232
 
233
 
234
PROCEDURE AddMenuItem* (items: List.tList; id: INTEGER; s: ARRAY OF WCHAR);
235
VAR
236
    item: tItem;
237
BEGIN
238
    NEW(item);
239
    item.id := id;
240
    item.text := s;
241
    item.enabled := TRUE;
242
    item.delim := FALSE;
243
    List.append(items, item);
244
END AddMenuItem;
245
 
246
 
247
PROCEDURE delimiter* (items: List.tList);
248
BEGIN
249
    items.last(tItem).delim := TRUE
250
END delimiter;
251
 
252
 
253
PROCEDURE getItem (m: tMenu; id: INTEGER): tItem;
254
VAR
255
    item: tItem;
256
BEGIN
257
    item := m.items.first(tItem);
258
    WHILE (item # NIL) & (item.id # id) DO
259
        item := item.next(tItem)
260
    END
261
    RETURN item
262
END getItem;
263
 
264
 
265
PROCEDURE setEnabled* (m: tMenu; id: INTEGER; value: BOOLEAN);
266
VAR
267
    item: tItem;
268
BEGIN
269
    item := getItem(m, id);
270
    IF item # NIL THEN
271
        item.enabled := value
272
    END
273
END setEnabled;
274
 
275
 
276
PROCEDURE setCheck* (m: tMenu; id: INTEGER; value: INTEGER);
277
VAR
278
    item: tItem;
279
BEGIN
280
    item := getItem(m, id);
281
    IF item # NIL THEN
282
        item.check := value
283
    END
284
END setCheck;
285
 
286
 
287
PROCEDURE isEnabled* (m: tMenu; id: INTEGER): BOOLEAN;
288
VAR
289
    item: tItem;
290
BEGIN
291
    item := getItem(m, id)
292
    RETURN (item # NIL) & item.enabled
293
END isEnabled;
294
 
295
 
296
PROCEDURE opened* (m: tMenu): BOOLEAN;
297
    RETURN m.tid # 0
298
END opened;
299
 
300
 
301
PROCEDURE open* (m: tMenu; x, y: INTEGER);
302
BEGIN
303
    IF m.tid = 0 THEN
304
        m.winX := x;
305
        m.winY := y;
306
        SYSTEM.PUT(SYSTEM.ADR(stack[LEN(stack) - 1]), m);
307
        lastTID := K.CreateThread(SYSTEM.ADR(window), stack);
308
        m.tid := lastTID
309
    END
310
END open;
311
 
312
 
313
PROCEDURE close* (m: tMenu);
314
BEGIN
315
    IF m.tid # 0 THEN
316
        K.ExitID(m.tid);
317
        m.tid := 0
318
    END
319
END close;
320
 
321
 
322
PROCEDURE create* (items: List.tList; click: tClick; key: tKey): tMenu;
323
VAR
324
    m: tMenu;
325
    maxLength: INTEGER;
326
    item: tItem;
327
BEGIN
328
    NEW(m);
329
    m.tid := 0;
330
    m.items  := items;
331
    m.click := click;
332
    m.key := key;
333
    maxLength := 0;
334
    item := items.first(tItem);
335
    WHILE item # NIL DO
336
        maxLength := MAX(maxLength, LENGTH(item.text));
337
        item := item.next(tItem)
338
    END;
339
    m.width  := maxLength*fontWidth + LEFT + RIGHT;
340
    m.height := items.count*fontHeight - 2;
341
    m.font := G.CreateFont(1, "", {});
342
    m.canvas := G.CreateCanvas(m.width + 1, m.height + 1);
343
    G.SetFont(m.canvas, m.font);
344
    RETURN m
345
END create;
346
 
347
 
348
BEGIN
349
    lastTID := 0
350
END Menu.