1 // ---------------------------------------------------------------------------------
2 //
3 //  Copyright (C) 2003-2013 Fons Adriaensen <fons@linuxaudio.org>
4 //
5 //  This program is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU Lesser General Public License as published
7 //  by the Free Software Foundation; either version 2 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU Lesser General Public License for more details.
14 //
15 //  You should have received a copy of the GNU Lesser General Public
16 //  License along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //
19 // ---------------------------------------------------------------------------------
20 
21 
22 #include "clxclient.h"
23 
24 
X_button(X_window * parent,X_callback * callb,X_button_style * style,int xp,int yp,int cbid)25 X_button::X_button (X_window       *parent,
26                     X_callback     *callb,
27                     X_button_style *style,
28                     int xp, int yp,
29                     int  cbid) :
30     X_window (parent, xp, yp, style->size.x, style->size.y, style->color.shadow.bgnd),
31     _style (style),
32     _callb (callb),
33     _xs (style->size.x),
34     _ys (style->size.y),
35     _cbid (cbid),
36     _down (0),
37     _stat (0)
38 {
39     x_add_events (ExposureMask);
40     if (_callb) x_add_events (ButtonPressMask | ButtonReleaseMask | Button1MotionMask | LeaveWindowMask);
41 }
42 
43 
~X_button(void)44 X_button::~X_button (void)
45 {
46 }
47 
48 
handle_event(XEvent * E)49 void X_button::handle_event (XEvent *E)
50 {
51     switch (E->type)
52     {
53     case Expose:
54 	expose ((XExposeEvent *) E);
55 	break;
56 
57     case ButtonPress:
58 	bpress ((XButtonEvent *) E);
59 	break;
60 
61     case ButtonRelease:
62 	brelease ((XButtonEvent *) E);
63 	break;
64 
65     case MotionNotify:
66         _callb->handle_callb (X_callback::BUTTON | MOVE, this, E);
67 	break;
68 
69     case LeaveNotify:
70 	release ();
71 	break;
72     }
73 }
74 
75 
bpress(XButtonEvent * E)76 void X_button::bpress (XButtonEvent *E)
77 {
78     _down = 1;
79     redraw ();
80     _callb->handle_callb (X_callback::BUTTON | PRESS, this, (XEvent *) E);
81 }
82 
83 
brelease(XButtonEvent * E)84 void X_button::brelease (XButtonEvent *E)
85 {
86     _down = 0;
87     redraw ();
88     _callb->handle_callb (X_callback::BUTTON | RELSE, this, (XEvent *) E);
89 }
90 
91 
expose(XExposeEvent * E)92 void X_button::expose (XExposeEvent *E)
93 {
94     if (E->count == 0) redraw ();
95 }
96 
97 
release(void)98 void X_button::release (void)
99 {
100     if (_style->type & X_button_style::HOLDPTR) return;
101     XUngrabPointer (dpy (), CurrentTime);
102     _down = 0;
103     redraw ();
104 }
105 
106 
set_stat(int stat)107 void X_button::set_stat (int stat)
108 {
109     if (_stat != stat)
110     {
111 	_stat = stat;
112         redraw ();
113     }
114 }
115 
116 
redraw(void)117 void X_button::redraw (void)
118 {
119     GC gc = disp ()->dgc ();
120 
121     XSetFunction (dpy (), gc, GXcopy);
122     XSetLineAttributes (dpy (), gc, 0, LineSolid, CapButt, JoinBevel);
123     switch (_style->type & 3)
124     {
125     case X_button_style::RAISED:
126 	XSetForeground (dpy (), gc, _down ? _style->color.shadow.dark : _style->color.shadow.lite);
127 	XDrawLine (dpy (), win (), gc,  0, 0, 0, _ys - 2);
128 	XDrawLine (dpy (), win (), gc,  0, 0, _xs - 2, 0);
129 	XSetForeground (dpy (), gc, _down ? _style->color.shadow.lite : _style->color.shadow.dark);
130 	XDrawLine (dpy (), win (), gc, _xs - 1, 1, _xs - 1, _ys);
131 	XDrawLine (dpy (), win (), gc, 1, _ys - 1, _xs, _ys - 1);
132         XSetForeground (dpy (), gc, _style->color.shadow.bgnd);
133         XDrawPoint (dpy (), win (), gc, 0, _ys - 1);
134         XDrawPoint (dpy (), win (), gc, _xs - 1, 0);
135 	break;
136     }
137 }
138 
139 
140 
X_tbutton(X_window * parent,X_callback * callb,X_button_style * style,int xp,int yp,const char * text1,const char * text2,int cbid)141 X_tbutton::X_tbutton (X_window       *parent,
142                       X_callback     *callb,
143                       X_button_style *style,
144                       int             xp,
145                       int             yp,
146                       const char     *text1,
147                       const char     *text2,
148                       int             cbid) :
149     X_button (parent, callb, style, xp, yp, cbid),
150     _bg (0),
151     _fg (0),
152     _len1 (0),
153     _len2 (0)
154 {
155     set_text (text1, text2);
156 }
157 
158 
~X_tbutton(void)159 X_tbutton::~X_tbutton (void)
160 {
161 }
162 
163 
set_text(const char * text1,const char * text2)164 void X_tbutton::set_text (const char *text1, const char *text2)
165 {
166     _len1 = 0;
167     _len2 = 0;
168     if (text1) while (((*(unsigned char *) text1) >= ' ') && (_len1 < MAXLEN - 1)) _text1 [_len1++] = *text1++;
169     if (text2) while (((*(unsigned char *) text2) >= ' ') && (_len2 < MAXLEN - 1)) _text2 [_len2++] = *text2++;
170     _text1 [_len1] = 0;
171     _text2 [_len2] = 0;
172 }
173 
174 
redraw(void)175 void X_tbutton::redraw (void)
176 {
177     int            a, d, u, x, y;
178     GC             G = dgc ();
179     XftDraw       *D = xft ();
180     XftColor      *C;
181     XftFont       *F = _style->font;
182     XGlyphInfo     K;
183     unsigned long  b;
184 
185     XftDrawChange (D, win ());
186     XSetFunction (dpy (), G, GXcopy);
187     b = (_stat > 3) ? _bg : _style->color.bg [_stat];
188     XSetForeground (dpy (), G, b);
189     XFillRectangle (dpy (), win (), G, 0, 0, _xs, _ys);
190 
191     a = F->ascent;
192     d = F->descent;
193     u = a + d - _ys / 2;
194     if (u < 0) u = 0;
195 
196     C = (_stat > 3) ? _fg : _style->color.fg [_stat];
197     if (_len1)
198     {
199 	y = (_len2) ? _ys / 2 - d + u : (_ys + a - d) / 2;
200 	if (_style->type & X_button_style::ALEFT) x = 6;
201         else
202 	{
203             XftTextExtentsUtf8 (dpy (), F, (const FcChar8 *) _text1, _len1, &K);
204 	    if (_style->type & X_button_style::ARIGHT) x = _xs - K.width - 6;
205 	    else x = (_xs - K.width) / 2;
206 	}
207 	if (_down) { x += 1; y += 1; }
208         XftDrawStringUtf8 (D, C, F, x, y, (const FcChar8 *) _text1, _len1);
209     }
210     if (_len2)
211     {
212 	y = (_len1) ? _ys / 2 + a - u : (_ys + a - d) / 2;
213 	if (_style->type & X_button_style::ALEFT) x = 6;
214 	else
215 	{
216             XftTextExtentsUtf8 (dpy (), F, (const FcChar8 *) _text2, _len2, &K);
217             if (_style->type & X_button_style::ARIGHT) x = _xs - K.width - 6;
218 	    else x = (_xs - K.width) / 2;
219 	}
220 	if (_down) { x += 1; y += 1; }
221         XftDrawStringUtf8 (D, C, F, x, y, (const FcChar8 *) _text2, _len2);
222     }
223     if ((_style->type & 3) == X_button_style::BORDER)
224     {
225         XSetLineAttributes (dpy (), G, 1, LineSolid, CapButt, JoinBevel);
226 	XSetForeground (dpy (), G, C->pixel);
227 	XDrawRectangle (dpy (), win (), G, 0, 0, _xs - 1, _ys - 1);
228     }
229     else X_button::redraw ();
230 }
231 
232 
233 
X_ibutton(X_window * parent,X_callback * callb,X_button_style * style,int xp,int yp,XImage * image,int cbid)234 X_ibutton::X_ibutton (X_window       *parent,
235                       X_callback     *callb,
236                       X_button_style *style,
237                       int             xp,
238                       int             yp,
239                       XImage         *image,
240                       int             cbid) :
241     X_button (parent, callb, style, xp, yp, cbid),
242     _bg (0),
243     _fg (0),
244     _image (image)
245 {
246 }
247 
248 
~X_ibutton(void)249 X_ibutton::~X_ibutton (void)
250 {
251 }
252 
253 
redraw(void)254 void X_ibutton::redraw (void)
255 {
256     int           x, y;
257     unsigned long b, f;
258 
259     b = (_stat > 3) ? _bg : _style->color.bg [_stat];
260     f = (_stat > 3) ? _fg : _style->color.fg [_stat]->pixel;
261     XSetState (dpy (), dgc (), f, b, GXcopy, ~0);
262     XSetWindowBackground (dpy (), win (), b);
263     XClearWindow (dpy (), win ());
264     if (_image)
265     {
266 	x = (_xs - _image->width) / 2;
267         y = (_ys - _image->height) / 2;
268         XPutImage (dpy (), win (), dgc (), _image, 0, 0, x, y, _xs, _ys);
269     }
270     if ((_style->type & 3) == X_button_style::BORDER)
271     {
272         XSetLineAttributes (dpy (), dgc (), 1, LineSolid, CapButt, JoinBevel);
273 	XSetForeground (dpy (), dgc (), f);
274 	XDrawRectangle (dpy (), win (), dgc (), 0, 0, _xs - 1, _ys - 1);
275     }
276     else X_button::redraw ();
277 }
278 
279 
280 
X_pbutton(X_window * parent,X_callback * callb,X_button_style * style,int xp,int yp,Pixmap map0,Pixmap map1,int cbid)281 X_pbutton::X_pbutton (X_window       *parent,
282                       X_callback     *callb,
283                       X_button_style *style,
284                       int xp, int yp,
285                       Pixmap map0,
286                       Pixmap map1,
287                       int  cbid) :
288     X_button (parent, callb, style, xp, yp, cbid),
289     _map0 (map0),
290     _map1 (map1)
291 {
292     if (_map0) XSetWindowBackgroundPixmap (dpy (), win (), _map0);
293 }
294 
295 
~X_pbutton(void)296 X_pbutton::~X_pbutton (void)
297 {
298 }
299 
300 
set_stat(bool stat)301 void X_pbutton::set_stat (bool stat)
302 {
303     if (_stat != stat)
304     {
305         if (_map1) XSetWindowBackgroundPixmap (dpy (), win (), stat ? _map1 : _map0);
306         _stat = stat;
307         XClearWindow (dpy (), win ());
308         X_button::redraw ();
309     }
310 }
311 
312