Subversion Repositories Kolibri OS

Rev

Rev 9174 | Rev 9181 | 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 Scroll;
21
 
8762 leency 22
IMPORT G := Graph, K := KolibriOS;
8728 leency 23
 
9174 akron1 24
CONST
25
 
26
	ScrollIPC* = 0;
27
 
8728 leency 28
TYPE
29
 
9174 akron1 30
	tScroll* = RECORD
31
		vertical, Inc*, Dec*, mouse*: BOOLEAN;
32
		top*, left*,
33
		width*, height*: INTEGER; (* read only *)
34
		btnSize, sliderSize: INTEGER;
35
		pos, Slider, pos0, maxVal*, value*: INTEGER;
36
		canvas*: G.tCanvas
37
	END;
8728 leency 38
 
39
 
9174 akron1 40
PROCEDURE create* (vertical: BOOLEAN; width, height: INTEGER; btnSize, sliderSize: INTEGER; VAR scroll: tScroll);
8728 leency 41
BEGIN
9174 akron1 42
	scroll.vertical := vertical;
43
	scroll.Inc := FALSE;
44
	scroll.Dec := FALSE;
45
	scroll.Slider := -1;
46
	scroll.mouse := FALSE;
47
	scroll.left := 0;
48
	scroll.top := 0;
49
	scroll.width := width;
50
	scroll.height := height;
51
	scroll.btnSize := btnSize;
52
	scroll.sliderSize := sliderSize;
53
	scroll.pos := 0;
54
	scroll.maxVal := 0;
55
	scroll.canvas := G.CreateCanvas(width, height)
56
END create;
8728 leency 57
 
58
 
9174 akron1 59
PROCEDURE Rect (canvas: G.tCanvas; left, top, right, bottom: INTEGER);
60
BEGIN
61
	G.FillRect(canvas, left, top, right, bottom);
62
	G.SetColor(canvas, K.borderColor);
63
	G.Rect(canvas, left, top, right, bottom);
64
END Rect;
65
 
66
 
67
PROCEDURE _paint (scroll: tScroll);
8728 leency 68
VAR
9174 akron1 69
	canvas: G.tCanvas;
70
	x, y, d, x1, x2, y1, y2,
71
	width, height, btn: INTEGER;
72
 
73
 
74
	PROCEDURE SetColor (canvas: G.tCanvas; c: BOOLEAN);
75
	VAR
76
		color: INTEGER;
77
	BEGIN
78
		IF c THEN
79
			color := K.btnColor
80
		ELSE
81
			color := K.btnTextColor
82
		END;
83
		G.SetColor(canvas, color)
84
	END SetColor;
85
 
86
 
8728 leency 87
BEGIN
9174 akron1 88
	btn := scroll.btnSize;
89
	width := scroll.width;
90
	height := scroll.height;
91
	canvas := scroll.canvas;
92
	G.SetColor(canvas, K.winColor);
9180 akron1 93
	G.clear(canvas);
9174 akron1 94
	G.SetColor(canvas, K.borderColor);
95
	G.Rect(canvas, 0, 0, width - 1, height - 1);
96
	IF scroll.vertical THEN
97
		SetColor(canvas, ~scroll.Dec);
98
		Rect(canvas, 0, 0, width - 1, btn - 1);
99
		SetColor(canvas, ~scroll.Inc);
100
		Rect(canvas, 0, height - btn, width - 1, height - 1);
101
		G.SetColor(canvas, K.btnColor);
102
		Rect(canvas, 0, btn + scroll.pos - 1, width - 1, btn + scroll.pos + scroll.sliderSize - 1);
8728 leency 103
 
9174 akron1 104
		G.SetColor(canvas, K.btnTextColor);
8728 leency 105
 
9174 akron1 106
		y := btn + scroll.pos + scroll.sliderSize DIV 2 - 1;
107
		G.HLine(canvas, y, width DIV 4, 3*width DIV 4);
108
		G.HLine(canvas, y - 3, width DIV 3, 2*width DIV 3);
109
		G.HLine(canvas, y + 3, width DIV 3, 2*width DIV 3);
110
 
111
		d := 4*width DIV 10;
112
		x1 := (width - d) DIV 2;
113
		x2 := x1 + d;
114
 
115
		SetColor(canvas, scroll.Dec);
116
		y := (btn - d DIV 2) DIV 2 + d DIV 2 - 1;
117
		G.Triangle(canvas, x1 - 1, y, x2, y, G.triUp);
118
 
119
		SetColor(canvas, scroll.Inc);
120
		y := y + height - btn - d DIV 2 + 1;
121
		G.Triangle(canvas, x1 - 1, y, x2, y, G.triDown);
122
	ELSE
123
		SetColor(canvas, ~scroll.Dec);
124
		Rect(canvas, 0, 0, btn - 1, height - 1);
125
		SetColor(canvas, ~scroll.Inc);
126
		Rect(canvas, width - btn, 0, width - 1, height - 1);
127
		G.SetColor(canvas, K.btnColor);
128
		Rect(canvas, btn + scroll.pos - 1, 0, btn + scroll.pos + scroll.sliderSize - 1, height - 1);
129
 
130
		G.SetColor(canvas, K.btnTextColor);
131
 
132
		x := btn + scroll.pos + scroll.sliderSize DIV 2 - 1;
133
		G.VLine(canvas, x, height DIV 4, 3*height DIV 4);
134
		G.VLine(canvas, x - 3, height DIV 3, 2*height DIV 3);
135
		G.VLine(canvas, x + 3, height DIV 3, 2*height DIV 3);
136
 
137
		d := 4*height DIV 10;
138
		y1 := (height - d) DIV 2;
139
		y2 := y1 + d;
140
 
141
		SetColor(canvas, scroll.Dec);
142
		x := (btn - d DIV 2) DIV 2 + d DIV 2 - 1;
143
		G.Triangle(canvas, x, y1 - 1, x, y2, G.triLeft);
144
 
145
		SetColor(canvas, scroll.Inc);
146
		x := x + width - btn - d DIV 2 + 1;
147
		G.Triangle(canvas, x, y1 - 1, x, y2, G.triRight);
148
	END;
149
	G.DrawCanvas(scroll.canvas, scroll.left, scroll.top)
150
END _paint;
151
 
152
 
153
PROCEDURE paint* (scroll: tScroll);
8728 leency 154
BEGIN
9174 akron1 155
	IF scroll.canvas # NIL THEN
156
		_paint(scroll)
157
	END
158
END paint;
159
 
160
 
161
PROCEDURE resize* (VAR scroll: tScroll; width, height: INTEGER);
162
BEGIN
163
	G.destroy(scroll.canvas);
164
	scroll.canvas := G.CreateCanvas(width, height);
165
	scroll.width := width;
166
	scroll.height := height;
167
	paint(scroll)
8728 leency 168
END resize;
169
 
170
 
9174 akron1 171
PROCEDURE setValue* (VAR scroll: tScroll; value: INTEGER);
8728 leency 172
VAR
9174 akron1 173
	pos, maxPos, n, m: INTEGER;
8728 leency 174
BEGIN
9174 akron1 175
	IF scroll.vertical THEN
176
		maxPos := scroll.height
177
	ELSE
178
		maxPos := scroll.width
179
	END;
180
	maxPos := maxPos - scroll.btnSize*2 - scroll.sliderSize + 1;
181
	IF (value < 0) OR (scroll.maxVal <= 0) THEN
182
		value := 0;
183
		pos := 0
184
	ELSIF value > scroll.maxVal THEN
185
		value := scroll.maxVal;
186
		pos := maxPos
187
	ELSE
188
		IF (maxPos + 1) >= scroll.maxVal THEN
189
			n := (maxPos + 1) DIV scroll.maxVal;
190
			m := (maxPos + 1) MOD scroll.maxVal;
191
			pos := value*n + MIN(value, m)
192
		ELSE
193
			pos := value*(maxPos + 1) DIV scroll.maxVal
194
		END;
195
		IF pos > maxPos THEN
196
			pos := maxPos;
197
			value := scroll.maxVal
198
		END
199
	END;
200
	scroll.pos := pos;
201
	scroll.value := value
202
END setValue;
8728 leency 203
 
204
 
9174 akron1 205
PROCEDURE change* (VAR scroll: tScroll);
8728 leency 206
BEGIN
9174 akron1 207
	IF scroll.Inc THEN
208
		setValue(scroll, scroll.value + 1)
209
	ELSIF scroll.Dec THEN
210
		setValue(scroll, scroll.value - 1)
211
	END;
212
	paint(scroll)
213
END change;
214
 
215
 
216
PROCEDURE ceil (p, q: INTEGER): INTEGER;
217
	RETURN p DIV q + ORD(p MOD q # 0)
218
END ceil;
219
 
220
 
221
PROCEDURE setPos (VAR scroll: tScroll; pos: INTEGER);
222
VAR
223
	maxPos, value, n, m, x, x0, q: INTEGER;
224
BEGIN
225
	IF scroll.maxVal > 0 THEN
226
		IF scroll.vertical THEN
227
			maxPos := scroll.height
228
		ELSE
229
			maxPos := scroll.width
230
		END;
231
		maxPos := maxPos - scroll.btnSize*2 - scroll.sliderSize + 1;
232
		IF pos <= 0 THEN
233
			pos := 0;
234
			value := 0
235
		ELSIF pos >= maxPos THEN
236
			pos := maxPos;
237
			value := scroll.maxVal
238
		ELSE
239
			IF scroll.maxVal <= maxPos + 1 THEN
240
				n := (maxPos + 1) DIV scroll.maxVal;
241
				m := (maxPos + 1) MOD scroll.maxVal;
242
 
243
				q := m*(n + 1);
244
				IF q < pos THEN
245
					value := ceil(pos - m, n)
246
				ELSIF q > pos THEN
247
					value := ceil(pos, n + 1)
248
				ELSE
249
					value := m
250
				END;
251
 
252
				x := value*n + MIN(value, m);
253
				x0 := (value - 1)*n + MIN(value - 1, m);
254
 
255
				IF x - pos > pos - x0 THEN
256
					pos := x0;
257
					DEC(value)
258
				ELSE
259
					pos := x;
260
					IF pos > maxPos THEN
261
						pos := maxPos;
262
						value := scroll.maxVal
263
					END
264
				END
265
			ELSE
266
				value := scroll.maxVal*pos DIV (maxPos + 1)
267
			END
268
		END
269
	ELSE
270
		pos := 0;
271
		scroll.value := 0
272
	END;
273
	scroll.pos := pos;
274
	scroll.value := value
275
END setPos;
276
 
277
 
278
PROCEDURE isActive* (scroll: tScroll): BOOLEAN;
279
	RETURN scroll.Inc OR scroll.Dec OR (scroll.Slider # -1)
280
END isActive;
281
 
282
 
283
PROCEDURE MouseMove* (VAR scroll: tScroll; x, y: INTEGER);
284
VAR
285
	c: INTEGER;
286
BEGIN
287
	IF scroll.Slider # -1 THEN
288
		IF scroll.vertical THEN
289
			c := y - scroll.top
290
		ELSE
291
			c := x - scroll.left
292
		END;
293
		setPos(scroll, scroll.pos0 + c - scroll.Slider);
294
		paint(scroll)
295
	END
296
END MouseMove;
297
 
298
 
299
PROCEDURE between (a, b, c: INTEGER): BOOLEAN;
300
	RETURN (a <= b) & (b <= c)
301
END between;
302
 
303
 
304
PROCEDURE SendIPC*;
305
BEGIN
306
	K.SendIPC(K.ThreadID(), ScrollIPC)
307
END SendIPC;
308
 
309
 
310
PROCEDURE MouseDown* (VAR scroll: tScroll; x, y: INTEGER);
311
VAR
312
	c, size: INTEGER;
313
BEGIN
314
	x := x - scroll.left;
315
	y := y - scroll.top;
316
	scroll.mouse := TRUE;
317
	IF between(0, x, scroll.width - 1) & between(0, y, scroll.height - 1) THEN
318
		IF scroll.vertical THEN
319
			c := y;
320
			size := scroll.height
321
		ELSE
322
			c := x;
323
			size := scroll.width
324
		END;
325
		IF between(scroll.btnSize + scroll.pos - 1, c, scroll.btnSize + scroll.pos + scroll.sliderSize - 1) THEN
326
			scroll.pos0 := scroll.pos;
327
			scroll.Slider := c
328
		ELSE
329
			IF between(0, c, scroll.btnSize - 1) THEN
330
				scroll.Dec := TRUE;
331
				SendIPC
332
			ELSE
333
				IF between(size - scroll.btnSize, c, size - 1) THEN
334
					scroll.Inc := TRUE;
335
					SendIPC
336
				ELSE
337
					setPos(scroll, c - scroll.btnSize - scroll.sliderSize DIV 2);
338
					scroll.pos0 := scroll.pos;
339
					scroll.Slider := c;
340
					paint(scroll)
341
				END
342
			END
343
		END
344
	END
345
END MouseDown;
346
 
347
 
348
PROCEDURE MouseUp* (VAR scroll: tScroll);
349
BEGIN
350
	IF scroll.mouse THEN
351
		scroll.Slider := -1;
352
		scroll.Inc := FALSE;
353
		scroll.Dec := FALSE;
354
		scroll.mouse := FALSE;
355
		paint(scroll)
356
	END
8728 leency 357
END MouseUp;
358
 
359
 
360
END Scroll.