Subversion Repositories Kolibri OS

Rev

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