1 /* bitmapbutton.c - buttons with little pictures on them
2 Copyright (C) 1996-2017 Paul Sheer
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307, USA.
18 */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <my_string.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25
26 #include <X11/Intrinsic.h>
27 #include "lkeysym.h"
28
29 #include "stringtools.h"
30 #include "app_glob.c"
31
32 #include "coolwidget.h"
33
34 #include "mad.h"
35
36 extern struct look *look;
37
38 void render_rounded_bevel (Window win, int x1, int y1, int x2, int y2, int radius, int thick, int sunken);
39
CDrawBitmapButton(const char * identifier,Window parent,int x,int y,int width,int height,unsigned long fg,unsigned long bg,const unsigned char data[])40 CWidget *CDrawBitmapButton (const char *identifier, Window parent, int x, int y,
41 int width, int height, unsigned long fg, unsigned long bg, const unsigned char data[])
42 {
43 XSetWindowAttributes xswa;
44 CWidget *w = CSetupWidget (identifier, parent, x, y,
45 width + 8, height + 8, C_BITMAPBUTTON_WIDGET, INPUT_BUTTON, bg, 1);
46 w->render = render_button;
47 xswa.background_pixmap = w->pixmap = XCreateBitmapFromData (CDisplay, w->winid, (char *) data, width, height);
48 if (xswa.background_pixmap)
49 XChangeWindowAttributes (CDisplay, w->winid, CWBackPixmap, &xswa);
50 w->fg = fg;
51 w->bg = bg;
52 w->options |= WIDGET_TAKES_FOCUS_RING | WIDGET_HOTKEY_ACTIVATES;
53
54 set_hint_pos (x + width + 8 + WIDGET_SPACING, y + height + 8 + WIDGET_SPACING);
55
56 return w;
57 }
58
CDrawBitmap(const char * identifier,Window parent,int x,int y,int width,int height,unsigned long fg,unsigned long bg,const unsigned char data[])59 CWidget *CDrawBitmap (const char *identifier, Window parent, int x, int y,
60 int width, int height, unsigned long fg, unsigned long bg, const unsigned char data[])
61 {
62 CWidget *w = CSetupWidget (identifier, parent, x, y,
63 width + 8, height + 8, C_BITMAP_WIDGET, INPUT_EXPOSE, bg, 0);
64 Pixmap pixmap;
65
66 pixmap = XCreateBitmapFromData (CDisplay, w->winid, (char *) data, width, height);
67 w->pixmap = pixmap;
68
69 w->fg = fg;
70 w->bg = bg;
71
72 set_hint_pos (x + width + 8 + WIDGET_SPACING, height + 8 + WIDGET_SPACING);
73
74 return w;
75 }
76
CDrawPixmapButton(const char * identifier,Window parent,int x,int y,int width,int height,const char * data[],char start_char)77 CWidget *CDrawPixmapButton (const char *identifier, Window parent,
78 int x, int y, int width, int height, const char *data[], char start_char)
79 {
80 CWidget *w;
81 w = CDrawButton (identifier, parent, x, y, width, height, "");
82 CSetBackgroundPixmap (identifier, data, width, height, start_char);
83 w->pixmap_mask = CCreateClipMask (data, width, height, ' ');
84 return w;
85 }
86
87 #define PICTURE_SWITCH_SIZE 32
88
89 Pixmap Cswitchon = 0;
90 Pixmap Cswitchoff = 0;
91
92 /* here ->cursor holds the group (8 bits only)
93 and ->keypressed hold if the switch is on or off */
94
CDrawSwitch(const char * identifier,Window parent,int x,int y,int on,const char * label,int group)95 CWidget *CDrawSwitch (const char *identifier, Window parent, int x, int y, int on, const char *label, int group)
96 {
97 int y_button, y_label, h = 0, xt = 0, yt = 0, l;
98 CWidget *w;
99
100 if (group & SWITCH_PICTURE_TYPE) {
101 l = PICTURE_SWITCH_SIZE;
102 } else
103 l = (*look->get_switch_size) ();
104
105 if (label) {
106 CTextSize (0, &h, label);
107 h += TEXT_RELIEF * 2 + 2;
108 }
109
110 if (h > l ) {
111 y_button = y + (h - l) / 2;
112 y_label = y;
113 } else {
114 y_button = y;
115 y_label = y + (l - h) / 2;
116 }
117
118 w = CSetupWidget (identifier, parent, x, y_button,
119 l, l, C_SWITCH_WIDGET, INPUT_BUTTON, COLOR_FLAT, 1);
120
121 if (group & SWITCH_PICTURE_TYPE)
122 if (!Cswitchon) {
123 Cswitchon = XCreateBitmapFromData (CDisplay, w->winid, (char *) switchon_bits, PICTURE_SWITCH_SIZE, PICTURE_SWITCH_SIZE);
124 Cswitchoff = XCreateBitmapFromData (CDisplay, w->winid, (char *) switchoff_bits, PICTURE_SWITCH_SIZE, PICTURE_SWITCH_SIZE);
125 }
126 w->fg = COLOR_BLACK;
127 w->bg = COLOR_FLAT;
128 w->keypressed = on;
129 if (label)
130 w->label = (char *) strdup (label);
131 w->hotkey = find_hotkey (w);
132 w->cursor = group & 0x0FFUL;
133 w->render = render_switch;
134 w->options |= (group & 0xFFFFFF00UL) | WIDGET_TAKES_FOCUS_RING | WIDGET_HOTKEY_ACTIVATES;
135
136 if (label) {
137 CWidget *t;
138 #ifdef NEXT_LOOK
139 t = CDrawText (catstrs (identifier, ".label", NULL), parent, x + l, y_label, "%s", label);
140 #else
141 t = CDrawText (catstrs (identifier, ".label", NULL), parent, x + l + WIDGET_SPACING, y_label, "%s", label);
142 #endif
143 t->hotkey = w->hotkey; /* underlines the character */
144 CGetHintPos (&xt, &yt);
145 }
146
147 if (xt < x + l + WIDGET_SPACING)
148 xt = x + l + WIDGET_SPACING;
149 if (yt < y + l + WIDGET_SPACING)
150 yt = y + l + WIDGET_SPACING;
151 if (yt < y + h + WIDGET_SPACING)
152 yt = y + h + WIDGET_SPACING;
153
154 set_hint_pos (xt, yt);
155
156 return w;
157 }
158
159 /* sets and redraws in the group all except w */
set_switch_group(CWidget * w,int group,int on)160 void set_switch_group (CWidget * w, int group, int on)
161 {
162 CWidget *p = w;
163
164 if (!w->cursor) /* belongs to no group */
165 return;
166 for (;;) {
167 w = CNextFocus (w);
168 if (!w)
169 return;
170 if ((unsigned long) w == (unsigned long) p)
171 return;
172 if (w->cursor == group)
173 if (w->keypressed != on) {
174 w->keypressed = on;
175 CExpose (w->ident);
176 }
177 };
178 }
179
toggle_radio_button(CWidget * w)180 void toggle_radio_button (CWidget * w)
181 {
182 if (w->options & RADIO_INVERT_GROUP)
183 set_switch_group (w, w->cursor, w->keypressed);
184 else
185 set_switch_group (w, w->cursor, 0);
186 if (w->cursor && w->options & RADIO_ONE_ALWAYS_ON)
187 w->keypressed = 1;
188 else
189 w->keypressed = (w->keypressed == 0);
190
191 /* don't expose, 'cos called from eh_button which renders by itself */
192 }
193
render_switch(CWidget * wdt)194 void render_switch (CWidget * wdt)
195 {
196 (*look->render_switch) (wdt);
197 }
198
render_rounded_bevel(Window win,int xs1,int ys1,int xs2,int ys2,int radius,int thick,int sunken)199 void render_rounded_bevel (Window win, int xs1, int ys1, int xs2, int ys2, int radius, int thick, int sunken)
200 {
201 unsigned long cn, cs, cnw, cne, cse;
202 int i;
203 int x1, y1, x2, y2;
204
205 if (option_low_bandwidth)
206 return;
207
208 if ((sunken & 2)) {
209 CSetColor (COLOR_FLAT);
210 CRectangle (win, xs1, ys1, xs2 - xs1 + 1, ys2 - ys1 + 1);
211 }
212 sunken &= 1;
213
214 cn = sunken ? color_widget (4) : color_widget (11);
215 cs = sunken ? color_widget (11) : color_widget (4);
216 cnw = color_widget (14);
217 cse = color_widget (2);
218
219 if (sunken) {
220 cne = cnw;
221 cnw = cse;
222 cse = cne;
223 }
224 cne = color_widget (8);
225
226 #define Carc(win,x,y,w,h,a,b) XDrawArc(CDisplay,win,CGC,x,y,w,h,a,b)
227
228 for (x1 = xs1; x1 < xs1 + thick; x1++)
229 for (y1 = ys1; y1 < ys1 + thick; y1++) {
230 x2 = x1 + (xs2 - xs1 - thick + 1);
231 y2 = y1 + (ys2 - ys1 - thick + 1);
232 CSetColor (cnw);
233 Carc (win, x1, y1, (radius) * 2, (radius) * 2, 90 * 64, 90 * 64);
234 CSetColor (cse);
235 Carc (win, x2 - radius * 2, y2 - radius * 2, (radius) * 2, (radius) * 2, 270 * 64, 90 * 64);
236 CSetColor (cne);
237 Carc (win, x1, y2 - radius * 2, (radius) * 2, (radius) * 2, 180 * 64, 90 * 64);
238 Carc (win, x2 - radius * 2, y1, (radius) * 2, (radius) * 2, 0, 90 * 64);
239 }
240
241
242 if (radius)
243 radius--;
244 for (i = 0; i < thick; i++) {
245 CSetColor (cn);
246 CLine (win, xs1 + i, ys1 + radius, xs1 + i, ys2 - radius);
247 CLine (win, xs1 + radius, ys1 + i, xs2 - radius, ys1 + i);
248 CSetColor (cs);
249 CLine (win, xs2 - radius, ys2 - i, xs1 + radius, ys2 - i);
250 CLine (win, xs2 - i, ys1 + radius, xs2 - i, ys2 - radius);
251 CSetColor (color_widget (15));
252 if (sunken)
253 XDrawPoint (CDisplay, win, CGC, xs2 - i - (radius + 1) * 300 / 1024, ys2 - i - (radius + 1) * 300 / 1024);
254 else
255 XDrawPoint (CDisplay, win, CGC, xs1 + i + (radius + 1) * 300 / 1024, ys1 + i + (radius + 1) * 300 / 1024);
256 }
257
258
259 CSetColor (COLOR_BLACK);
260 }
261