Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
#include <thread.h>
5
#include <mouse.h>
6
#include <keyboard.h>
7
#include <control.h>
8
 
9
typedef struct Slider Slider;
10
 
11
struct Slider
12
{
13
	Control;
14
	int		border;
15
	CImage	*image;
16
	CImage	*textcolor;
17
	CImage	*bordercolor;
18
	CImage	*indicatorcolor;
19
	int		absolute;
20
	int		max;
21
	int		vis;
22
	int		value;
23
	int		clamphigh;
24
	int		clamplow;
25
	int		horizontal;
26
	int		lastbut;
27
};
28
 
29
enum{
30
	EAbsolute,
31
	EBorder,
32
	EBordercolor,
33
	EClamp,
34
	EFocus,
35
	EFormat,
36
	EHide,
37
	EImage,
38
	EIndicatorcolor,
39
	EMax,
40
	EOrient,
41
	ERect,
42
	EReveal,
43
	EShow,
44
	ESize,
45
	EValue,
46
	EVis,
47
};
48
 
49
static char *cmds[] = {
50
	[EAbsolute] =		"absolute",
51
	[EBorder] =		"border",
52
	[EBordercolor] =	"bordercolor",
53
	[EClamp] =		"clamp",
54
	[EFocus] = 		"focus",
55
	[EFormat] = 		"format",
56
	[EHide] =			"hide",
57
	[EImage] =		"image",
58
	[EIndicatorcolor] =	"indicatorcolor",
59
	[EMax] =			"max",
60
	[EOrient] =		"orient",
61
	[ERect] =			"rect",
62
	[EReveal] =		"reveal",
63
	[EShow] =			"show",
64
	[ESize] =			"size",
65
	[EValue] =			"value",
66
	[EVis] =			"vis",
67
};
68
 
69
static void
70
sliderfree(Control *c)
71
{
72
	Slider *s;
73
 
74
	s = (Slider*)c;
75
	_putctlimage(s->image);
76
	_putctlimage(s->textcolor);
77
	_putctlimage(s->bordercolor);
78
	_putctlimage(s->indicatorcolor);
79
}
80
 
81
static void
82
slidershow(Slider *s)
83
{
84
	Rectangle r, t;
85
	int l, h, d;
86
 
87
	if (s->hidden)
88
		return;
89
	r = s->rect;
90
	draw(s->screen, r, s->image->image, nil, s->image->image->r.min);
91
	if(s->border > 0){
92
		border(s->screen, r, s->border, s->bordercolor->image, s->bordercolor->image->r.min);
93
		r = insetrect(r, s->border);
94
	}
95
	if(s->max <= 0)
96
		return;
97
	if(s->horizontal)
98
		d = Dx(r);
99
	else
100
		d = Dy(r);
101
	l = muldiv(s->value, d, s->max);
102
	h = muldiv(s->value+s->vis, d, s->max);
103
	if(s->clamplow && s->clamphigh){
104
		l = 0;
105
		h = d;
106
	}else if(s->clamplow){
107
		h = l;
108
		l = 0;
109
	}else if(s->clamphigh)
110
		h = d;
111
	t = r;
112
	if(s->horizontal){
113
		r.max.x = r.min.x+h;
114
		r.min.x += l;
115
	}else{
116
		r.max.y = r.min.y+h;
117
		r.min.y += l;
118
	}
119
	if(rectclip(&r, t))
120
		draw(s->screen, r, s->indicatorcolor->image, nil, s->indicatorcolor->image->r.min);
121
	flushimage(display, 1);
122
}
123
 
124
static void
125
sliderctl(Control *c, CParse *cp)
126
{
127
	int cmd, prev;
128
	Rectangle r;
129
	Slider *s;
130
 
131
	s = (Slider*)c;
132
	cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
133
	switch(cmd){
134
	default:
135
		ctlerror("%q: unrecognized message '%s'", s->name, cp->str);
136
		break;
137
	case EAbsolute:
138
		_ctlargcount(s, cp, 2);
139
		s->absolute = cp->iargs[1];
140
		break;
141
	case EBorder:
142
		_ctlargcount(s, cp, 2);
143
		if(cp->iargs[1] < 0)
144
			ctlerror("%q: bad border: %c", s->name, cp->str);
145
		s->border = cp->iargs[1];
146
		break;
147
	case EBordercolor:
148
		_ctlargcount(s, cp, 2);
149
		_setctlimage(s, &s->bordercolor, cp->args[1]);
150
		break;
151
	case EClamp:
152
		_ctlargcount(s, cp, 3);
153
		if(strcmp(cp->args[1], "high") == 0)
154
			s->clamphigh = cp->iargs[2];
155
		else if(strcmp(cp->args[1], "low") == 0)
156
			s->clamplow = cp->iargs[2];
157
		else
158
			ctlerror("%q: unrecognized clamp: %s", s->name, cp->str);
159
		break;
160
	case EFocus:
161
		/* ignore focus change */
162
		break;
163
	case EFormat:
164
		_ctlargcount(s, cp, 2);
165
		s->format = ctlstrdup(cp->args[1]);
166
		break;
167
	case EHide:
168
		_ctlargcount(s, cp, 1);
169
		s->hidden = 1;
170
		break;
171
	case EImage:
172
		_ctlargcount(s, cp, 2);
173
		_setctlimage(s, &s->image, cp->args[1]);
174
		break;
175
	case EIndicatorcolor:
176
		_ctlargcount(s, cp, 2);
177
		_setctlimage(s, &s->indicatorcolor, cp->args[1]);
178
		break;
179
	case EMax:
180
		_ctlargcount(s, cp, 2);
181
		if(cp->iargs[1] < 0)
182
			ctlerror("%q: negative max value: %s", s->name, cp->str);
183
		if(s->max != cp->iargs[1]){
184
			s->max = cp->iargs[1];
185
			slidershow(s);
186
		}
187
		break;
188
	case EOrient:
189
		_ctlargcount(s, cp, 2);
190
		prev = s->horizontal;
191
		if(strncmp(cp->args[1], "hor", 3) == 0)
192
			s->horizontal = 1;
193
		else if(strncmp(cp->args[1], "ver", 3) == 0)
194
			s->horizontal = 0;
195
		else
196
			ctlerror("%q: unrecognized orientation: %s", s->name, cp->str);
197
		if(s->horizontal != prev)
198
			slidershow(s);
199
		break;
200
	case ERect:
201
		_ctlargcount(s, cp, 5);
202
		r.min.x = cp->iargs[1];
203
		r.min.y = cp->iargs[2];
204
		r.max.x = cp->iargs[3];
205
		r.max.y = cp->iargs[4];
206
		if(Dx(r)<=0 || Dy(r)<=0)
207
			ctlerror("%q: bad rectangle: %s", s->name, cp->str);
208
		s->rect = r;
209
		break;
210
	case EReveal:
211
		_ctlargcount(s, cp, 1);
212
		s->hidden = 0;
213
		slidershow(s);
214
		break;
215
	case EShow:
216
		_ctlargcount(s, cp, 1);
217
		slidershow(s);
218
		break;
219
	case ESize:
220
		if (cp->nargs == 3)
221
			r.max = Pt(0x7fffffff, 0x7fffffff);
222
		else{
223
			_ctlargcount(s, cp, 5);
224
			r.max.x = cp->iargs[3];
225
			r.max.y = cp->iargs[4];
226
		}
227
		r.min.x = cp->iargs[1];
228
		r.min.y = cp->iargs[2];
229
		if(r.min.x<=0 || r.min.y<=0 || r.max.x<=0 || r.max.y<=0 || r.max.x < r.min.x || r.max.y < r.min.y)
230
			ctlerror("%q: bad sizes: %s", s->name, cp->str);
231
		s->size.min = r.min;
232
		s->size.max = r.max;
233
		break;
234
	case EValue:
235
		_ctlargcount(s, cp, 2);
236
		if(s->value != cp->iargs[1]){
237
			s->value = cp->iargs[1];
238
			slidershow(s);
239
		}
240
		break;
241
	case EVis:
242
		_ctlargcount(s, cp, 2);
243
		if(s->vis != cp->iargs[1]){
244
			s->vis = cp->iargs[1];
245
			slidershow(s);
246
		}
247
		break;
248
	}
249
}
250
 
251
static void
252
slidermouse(Control *c, Mouse *m)
253
{
254
	Rectangle r;
255
	int v, l, d, b;
256
	Slider *s;
257
 
258
	s =(Slider*)c;
259
	if(m->buttons == 0){
260
		/* buttons now up */
261
		s->lastbut = 0;
262
		return;
263
	}
264
	if(!s->absolute && s->lastbut==m->buttons && s->lastbut!=2){
265
		/* clicks only on buttons 1 & 3; continuous motion on 2 (or when absolute) */
266
		return;
267
	}
268
	if(s->lastbut!=0 && m->buttons!=s->lastbut){
269
		/* buttons down have changed; wait for button up */
270
		return;
271
	}
272
	s->lastbut = m->buttons;
273
 
274
	r = insetrect(s->rect, s->border);
275
	if(s->horizontal){
276
		v = m->xy.x - r.min.x;
277
		d = Dx(r);
278
	}else{
279
		v = m->xy.y - r.min.y;
280
		d = Dy(r);
281
	}
282
	if(s->absolute)
283
		b = 2;
284
	else
285
		b = m->buttons;
286
	switch(b){
287
	default:
288
		return;
289
	case 1:
290
		l = s->value - muldiv(v, s->vis, d);
291
		break;
292
	case 2:
293
		l = muldiv(v, s->max, d);
294
		break;
295
	case 4:
296
		l = s->value + muldiv(v, s->vis, d);
297
		break;
298
	}
299
	if(l < 0)
300
		l = 0;
301
	if(l > s->max)
302
		l = s->max;
303
	if(l != s->value){
304
		s->value = l;
305
		chanprint(s->event, s->format, s->name, s->value);
306
		slidershow(s);
307
	}
308
}
309
 
310
Control*
311
createslider(Controlset *cs, char *name)
312
{
313
	Slider *s;
314
 
315
	s = (Slider*)_createctl(cs, "slider", sizeof(Slider), name);
316
	s->image = _getctlimage("white");
317
	s->textcolor = _getctlimage("black");
318
	s->bordercolor = _getctlimage("black");
319
	s->indicatorcolor = _getctlimage("black");
320
	s->format = ctlstrdup("%q: value %d");
321
	s->border = 0;
322
	s->mouse = slidermouse;
323
	s->ctl = sliderctl;
324
	s->exit = sliderfree;
325
	return (Control*)s;
326
}