Line data Source code
1 : /* Copyright (C) 2000-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include <stdlib.h>
28 : #include "gdraw.h"
29 : #include "ggadgetP.h"
30 : #include "ustring.h"
31 : #include "gkeysym.h"
32 : #include "gresource.h"
33 : #include "gwidget.h"
34 :
35 : static void GListButtonDoPopup(GListButton *);
36 :
37 : GBox _GGadget_button_box = GBOX_EMPTY; /* Don't initialize here */
38 : GBox _GGadget_defaultbutton_box = GBOX_EMPTY; /* Don't initialize here */
39 : static GBox _GGadget_cancelbutton_box = GBOX_EMPTY; /* Don't initialize here */
40 : static GBox _GGadget_colorbutton_box = GBOX_EMPTY; /* Don't initialize here */
41 : static GBox _GGadget_droplist_box = GBOX_EMPTY; /* Don't initialize here */
42 : static GBox label_box = GBOX_EMPTY; /* Don't initialize here */
43 : static int shift_on_press = 0;
44 : static FontInstance *label_font = NULL, *button_font = NULL;
45 : static int gbutton_inited = false;
46 : #define COLOR_BUTTON_BOX_LEN 10
47 :
48 : static GResInfo gcancel_ri, gdefault_ri, gbutton_ri, gdroplist_ri, gcolor_ri;
49 : static GResInfo glabel_ri = {
50 : &gbutton_ri, &ggadget_ri,NULL, NULL,
51 : &label_box,
52 : &label_font,
53 : NULL,
54 : NULL,
55 : N_("Label"),
56 : N_("Text Labels"),
57 : "GLabel",
58 : "Gdraw",
59 : false,
60 : omf_border_type|omf_border_width|omf_padding,
61 : NULL,
62 : GBOX_EMPTY,
63 : NULL,
64 : NULL,
65 : NULL
66 : };
67 :
68 : static GTextInfo button_lab[] = {
69 : { (unichar_t *) "Disabled Button", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
70 : { (unichar_t *) "Enabled Button" , NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' }
71 : };
72 : static GGadgetCreateData button_gcd[] = {
73 : { GButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, &button_lab[0], { NULL }, gg_visible, NULL, NULL }, NULL, NULL },
74 : { GButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, &button_lab[1], { NULL }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL }
75 : };
76 : static GGadgetCreateData *barray[] = { GCD_Glue, &button_gcd[0], GCD_Glue, &button_gcd[1], GCD_Glue, NULL, NULL };
77 : static GGadgetCreateData buttonbox =
78 : {GHVGroupCreate, { { 2, 2, 0, 0 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) barray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
79 : static struct resed gbutton_re[] = {
80 : { N_("Shift On Press"), "ShiftOnPress", rt_bool, &shift_on_press, N_("Background color of column headers at the top of a matrix edit"), NULL, { 0 }, 0, 0 },
81 : RESED_EMPTY
82 : };
83 : static GResInfo gbutton_ri = {
84 : &gdefault_ri, &ggadget_ri,&gdefault_ri, &gcancel_ri,
85 : &_GGadget_button_box,
86 : &button_font,
87 : &buttonbox,
88 : gbutton_re,
89 : N_("Button"),
90 : N_("Buttons"),
91 : "GButton",
92 : "Gdraw",
93 : true,
94 : #ifdef __Mac
95 : box_do_depressed_background|omf_border_type|omf_border_width|
96 : omf_border_shape|omf_padding,
97 : #else
98 : box_foreground_border_inner|box_foreground_border_outer|
99 : /*box_active_border_inner|*/box_do_depressed_background|box_draw_default,
100 : #endif
101 : /* Will be initialized later */
102 : NULL,
103 : GBOX_EMPTY,
104 : NULL,
105 : NULL,
106 : NULL
107 : };
108 : static GGadgetCreateData def_gcd[] = {
109 : { GButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, &button_lab[0], { NULL }, gg_visible|gg_but_default, NULL, NULL }, NULL, NULL },
110 : { GButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, &button_lab[1], { NULL }, gg_visible|gg_enabled|gg_but_default, NULL, NULL }, NULL, NULL }
111 : };
112 : static GGadgetCreateData *darray[] = { GCD_Glue, &def_gcd[0], GCD_Glue, &def_gcd[1], GCD_Glue, NULL, NULL };
113 : static GGadgetCreateData defbox =
114 : { GHVGroupCreate, { { 2, 2, 0, 0 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) darray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
115 : static GResInfo gdefault_ri = {
116 : &gcancel_ri, &gbutton_ri,&gcancel_ri,NULL,
117 : &_GGadget_defaultbutton_box,
118 : NULL,
119 : &defbox,
120 : NULL,
121 : N_("Default Button"),
122 : N_("Default Buttons"),
123 : "GDefaultButton",
124 : "Gdraw",
125 : true,
126 : #ifdef __Mac
127 : box_gradient_bg|omf_main_background|omf_gradient_bg_end,
128 : #else
129 : 0,
130 : #endif
131 : NULL,
132 : GBOX_EMPTY,
133 : NULL,
134 : NULL,
135 : NULL
136 : };
137 : static GGadgetCreateData cancel_gcd[] = {
138 : { GButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, &button_lab[0], { NULL }, gg_visible|gg_but_cancel, NULL, NULL }, NULL, NULL },
139 : { GButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, &button_lab[1], { NULL }, gg_visible|gg_enabled|gg_but_cancel, NULL, NULL }, NULL, NULL }
140 : };
141 : static GGadgetCreateData *carray[] = { GCD_Glue, &cancel_gcd[0], GCD_Glue, &cancel_gcd[1], GCD_Glue, NULL, NULL };
142 : static GGadgetCreateData cancelbox =
143 : {GHVGroupCreate, { {2, 2, 0, 0}, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) carray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
144 : static GResInfo gcancel_ri = {
145 : &gcolor_ri, &gbutton_ri,&gdefault_ri,NULL,
146 : &_GGadget_cancelbutton_box,
147 : NULL,
148 : &cancelbox,
149 : NULL,
150 : N_("Cancel Button"),
151 : N_("Cancel Buttons"),
152 : "GCancelButton",
153 : "Gdraw",
154 : true,
155 : #ifdef __Mac
156 : box_gradient_bg|omf_main_background|omf_gradient_bg_end,
157 : #else
158 : 0,
159 : #endif
160 : NULL,
161 : GBOX_EMPTY,
162 : NULL,
163 : NULL,
164 : NULL
165 : };
166 : static GGadgetCreateData color_gcd[] = {
167 : { GColorButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) (intpt) (0x000000) }, gg_visible, NULL, NULL }, NULL, NULL },
168 : { GColorButtonCreate, { GRECT_EMPTY, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) (intpt) (0x000000) }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL }
169 : };
170 : static GGadgetCreateData *colarray[] = { GCD_Glue, &color_gcd[0], GCD_Glue, &color_gcd[1], GCD_Glue, NULL, NULL };
171 : static GGadgetCreateData colorbox =
172 : { GHVGroupCreate, { { 2, 2, 0, 0 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) colarray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
173 : static GResInfo gcolor_ri = {
174 : &gdroplist_ri, &gbutton_ri,NULL,NULL,
175 : &_GGadget_colorbutton_box,
176 : NULL,
177 : &colorbox,
178 : NULL,
179 : N_("Color Button"),
180 : N_("Color Button"),
181 : "GColorButton",
182 : "Gdraw",
183 : true,
184 : 0,
185 : NULL,
186 : GBOX_EMPTY,
187 : NULL,
188 : NULL,
189 : NULL
190 : };
191 : static GTextInfo list_choices[] = {
192 : { (unichar_t *) "1", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
193 : { (unichar_t *) "2", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
194 : { (unichar_t *) "3", NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0' },
195 : GTEXTINFO_EMPTY
196 : };
197 :
198 : static GGadgetCreateData droplist_gcd[] = {
199 : { GListButtonCreate, { { 0, 0, 80, 0 }, NULL, 0, 0, 0, 0, 0, &list_choices[0], { list_choices }, gg_visible, NULL, NULL }, NULL, NULL },
200 : { GListButtonCreate, { { 0, 0, 80, 0 }, NULL, 0, 0, 0, 0, 0, &list_choices[1], { list_choices }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL }
201 : };
202 : static GGadgetCreateData *dlarray[] = { GCD_Glue, &droplist_gcd[0], GCD_Glue, &droplist_gcd[1], GCD_Glue, NULL, NULL };
203 : static GGadgetCreateData droplistbox =
204 : { GHVGroupCreate, { { 2, 2, 0, 0 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) dlarray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
205 : static GResInfo gdroplist_ri = {
206 : NULL, &gbutton_ri,&listmark_ri,NULL,
207 : &_GGadget_droplist_box,
208 : NULL,
209 : &droplistbox,
210 : NULL,
211 : N_("Drop List Button"),
212 : N_("Drop List Button"),
213 : "GDropList",
214 : "Gdraw",
215 : true,
216 : #ifdef __Mac
217 : omf_border_type|omf_border_width|omf_border_shape,
218 : #else
219 : 0,
220 : #endif
221 : NULL,
222 : GBOX_EMPTY,
223 : NULL,
224 : NULL,
225 : NULL
226 : };
227 :
228 0 : static void GButtonInvoked(GButton *b,GEvent *ev) {
229 : GEvent e;
230 :
231 0 : if ( b->labeltype==3 ) {
232 : struct hslrgba hsl;
233 0 : gColor2Hslrgba(&hsl,((GColorButton *) b)->col);
234 0 : hsl = GWidgetColorA(_("Pick a color"),&hsl,NULL);
235 0 : if ( hsl.rgb ) {
236 0 : ((GColorButton *) b)->col = gHslrgba2Color(&hsl);
237 0 : GGadgetRedraw(&b->g);
238 : } else
239 0 : return;
240 : }
241 0 : e.type = et_controlevent;
242 0 : e.w = b->g.base;
243 0 : e.u.control.subtype = et_buttonactivate;
244 0 : e.u.control.g = &b->g;
245 0 : if ( ev!=NULL && ev->type==et_mouseup ) {
246 0 : e.u.control.u.button.clicks = ev->u.mouse.clicks;
247 0 : e.u.control.u.button.button = ev->u.mouse.button;
248 0 : e.u.control.u.button.state = ev->u.mouse.state;
249 : } else {
250 0 : e.u.control.u.button.clicks = 0;
251 0 : e.u.control.u.button.button = 0;
252 0 : e.u.control.u.button.state = 0;
253 : }
254 0 : if ( b->g.handle_controlevent != NULL )
255 0 : (b->g.handle_controlevent)(&b->g,&e);
256 : else
257 0 : GDrawPostEvent(&e);
258 : }
259 :
260 0 : static void GButtonPressed(GButton *b) {
261 : GEvent e;
262 :
263 0 : if ( b->labeltype==2 && ((GListButton *) b)->ltot>0 )
264 0 : GListButtonDoPopup((GListButton *) b);
265 : else {
266 0 : e.type = et_controlevent;
267 0 : e.w = b->g.base;
268 0 : e.u.control.subtype = et_buttonpress;
269 0 : e.u.control.g = &b->g;
270 0 : if ( b->g.handle_controlevent != NULL )
271 0 : (b->g.handle_controlevent)(&b->g,&e);
272 : else
273 0 : GDrawPostEvent(&e);
274 : }
275 0 : }
276 :
277 0 : static int gbutton_stringsize( GButton *gb,unichar_t *label,int *lcnt ) {
278 0 : int maxtextwidth = 0;
279 : unichar_t *pt, *start;
280 :
281 0 : for ( pt = label; ; ) {
282 0 : for ( start=pt; *pt!='\0' && *pt!='\n'; ++pt );
283 0 : if ( pt!=start ) {
284 0 : int w = GDrawGetTextWidth(gb->g.base,start,pt-start);
285 0 : if ( w>maxtextwidth ) maxtextwidth=w;
286 : }
287 0 : ++(*lcnt);
288 0 : if ( *pt=='\0' )
289 0 : break;
290 0 : ++pt;
291 0 : }
292 0 : return maxtextwidth;
293 : }
294 :
295 0 : static unichar_t *gbutton_textsize( GButton *gb, int *_maxlcnt, int *_maxw ) {
296 : int i, lcnt, maxlcnt, maxtextwidth;
297 : unichar_t *ltxt;
298 : GFont *old;
299 :
300 0 : old = GDrawSetFont(gb->g.base,gb->font);
301 :
302 0 : maxtextwidth = maxlcnt = 0;
303 0 : if ( gb->label!=NULL ) {
304 0 : maxtextwidth = gbutton_stringsize( gb,gb->label,&maxlcnt );
305 0 : ltxt = gb->label;
306 : }
307 : /* If there is a list of alternate labels, iterate through all */
308 : /* and get the maximum width and height */
309 0 : if ( gb->labeltype == 0 && gb->ti!=NULL ) {
310 0 : for ( i=0; i<gb->ltot; i++ ) {
311 0 : lcnt = 0;
312 0 : int w = gbutton_stringsize( gb,gb->ti[i]->text,&lcnt );
313 0 : if ( w>maxtextwidth ) {
314 0 : maxtextwidth=w;
315 0 : ltxt = gb->ti[i]->text;
316 : }
317 0 : if ( lcnt>maxlcnt ) maxlcnt=lcnt;
318 : }
319 : }
320 0 : (void) GDrawSetFont(gb->g.base,old);
321 0 : *_maxlcnt = maxlcnt;
322 0 : *_maxw = maxtextwidth;
323 0 : return( ltxt );
324 : }
325 :
326 0 : static int gbutton_expose(GWindow pixmap, GGadget *g, GEvent *event) {
327 0 : GImageButton *gb = (GImageButton *) g;
328 0 : int off = gb->within && gb->shiftonpress ? gb->pressed : 0;
329 0 : int x = g->inner.x + off;
330 0 : GImage *img = gb->image;
331 : GRect old1, old2;
332 : int width;
333 0 : int marklen = GDrawPointsToPixels(pixmap,_GListMarkSize),
334 0 : spacing = GDrawPointsToPixels(pixmap,_GGadget_TextImageSkip);
335 : int yoff;
336 : GRect unpadded_inner;
337 : int pad, lcnt, maxtextwidth;
338 : unichar_t *pt, *start;
339 0 : int cbbl=0;
340 :
341 0 : if ( g->state == gs_invisible )
342 0 : return( false );
343 0 : else if ( gb->labeltype!=1 /* Not image buttons */ )
344 : /* Do Nothing */;
345 0 : else if ( g->state == gs_disabled ) {
346 0 : if ( gb->disabled != NULL ) img = gb->disabled;
347 0 : } else if ( gb->pressed && gb->within && gb->active!=NULL )
348 0 : img = gb->active;
349 0 : else if ( gb->within )
350 0 : img = gb->img_within;
351 :
352 0 : GDrawPushClip(pixmap,&g->r,&old1);
353 :
354 0 : GBoxDrawBackground(pixmap,&g->r,g->box,
355 0 : gb->within && gb->pressed? gs_pressedactive: g->state,gb->is_default);
356 0 : if ( g->box->border_type!=bt_none ||
357 0 : (g->box->flags&(box_foreground_border_inner|box_foreground_border_outer|box_active_border_inner))!=0 ) {
358 0 : GBoxDrawBorder(pixmap,&g->r,g->box,g->state,gb->is_default);
359 :
360 0 : unpadded_inner = g->inner;
361 0 : pad = GDrawPointsToPixels(g->base,g->box->padding);
362 0 : unpadded_inner.x -= pad; unpadded_inner.y -= pad;
363 0 : unpadded_inner.width += 2*pad; unpadded_inner.height += 2*pad;
364 0 : GDrawPushClip(pixmap,&unpadded_inner,&old2);
365 : }
366 0 : if ( gb->font!=NULL )
367 0 : GDrawSetFont(pixmap,gb->font);
368 :
369 0 : gbutton_textsize((GButton *) gb,&lcnt,&maxtextwidth);
370 0 : yoff = (g->inner.height-lcnt*gb->fh)/2;
371 0 : if ( lcnt>1 && yoff<0 )
372 0 : yoff = 0;
373 :
374 0 : if ( gb->g.takes_input ) {
375 0 : width = 0;
376 0 : if ( img!=NULL ) {
377 0 : width = GImageGetScaledWidth(pixmap,img);
378 0 : if ( gb->label!=NULL )
379 0 : width += spacing;
380 : }
381 0 : if ( gb->label!=NULL )
382 0 : width += maxtextwidth;
383 0 : if ( gb->labeltype==3 ) {
384 0 : cbbl = GDrawPointsToPixels(NULL,COLOR_BUTTON_BOX_LEN);
385 0 : width += cbbl + spacing;
386 : }
387 0 : if ( width<=g->inner.width )
388 0 : x += ( g->inner.width-width )/2;
389 : else
390 0 : x += (g->inner.y-g->r.y);
391 : }
392 0 : if ( gb->labeltype==3 ) {
393 : GRect r;
394 0 : Color fg = g->state==gs_disabled?g->box->disabled_foreground:
395 0 : g->box->main_foreground==COLOR_DEFAULT?GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap)):
396 0 : g->box->main_foreground;
397 0 : r.x = x+1; r.y = g->inner.y+1;
398 0 : r.width = cbbl-2;
399 0 : if ( img!=NULL )
400 0 : r.height = GImageGetScaledHeight(pixmap,img)-2;
401 : else
402 0 : r.height = gb->fh-2;
403 0 : if ( ((GColorButton *) gb)->col!=COLOR_TRANSPARENT )
404 0 : GDrawFillRect(pixmap,&r,((GColorButton *) gb)->col);
405 0 : GDrawDrawRect(pixmap,&r,fg);
406 0 : x += cbbl + spacing;
407 : }
408 0 : if ( gb->image_precedes && img!=NULL ) {
409 0 : GDrawDrawScaledImage(pixmap,img,x,g->inner.y + off);
410 0 : x += GImageGetScaledWidth(pixmap,img) + spacing;
411 : }
412 0 : if ( gb->label!=NULL ) {
413 0 : Color fg = g->state==gs_disabled?g->box->disabled_foreground:
414 0 : g->box->main_foreground==COLOR_DEFAULT?GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap)):
415 0 : g->box->main_foreground;
416 0 : if ( lcnt==1 ) {
417 0 : _ggadget_underlineMnemonic(pixmap,x,g->inner.y + gb->as + yoff + off,gb->label,
418 0 : g->mnemonic,fg,g->inner.y+g->inner.height);
419 0 : x += GDrawDrawText(pixmap,x,g->inner.y + gb->as + yoff + off,gb->label,-1,fg);
420 : } else {
421 0 : int y = g->inner.y + gb->as + yoff + off;
422 0 : for ( pt = gb->label; ; ) {
423 0 : for ( start=pt; *pt!='\0' && *pt!='\n'; ++pt );
424 0 : if ( pt!=start )
425 0 : GDrawDrawText(pixmap,x,y,start,pt-start,fg);
426 0 : if ( *pt=='\0' )
427 0 : break;
428 0 : ++pt;
429 0 : y+=gb->fh;
430 0 : }
431 0 : x += maxtextwidth;
432 : }
433 0 : x += spacing;
434 : }
435 0 : if ( !gb->image_precedes && img!=NULL )
436 0 : GDrawDrawScaledImage(pixmap,img,x,g->inner.y + off);
437 :
438 0 : if ( g->box->border_type!=bt_none ||
439 0 : (g->box->flags&(box_foreground_border_inner|box_foreground_border_outer|box_active_border_inner))!=0 )
440 0 : GDrawPopClip(pixmap,&old2);
441 :
442 0 : if ( gb->labeltype==2 ) {
443 0 : int bp = GBoxBorderWidth(g->base,g->box);
444 0 : GListMarkDraw(pixmap,
445 0 : g->r.x + g->r.width - marklen - spacing/2 - bp,
446 : g->inner.y,
447 : g->inner.height,
448 : g->state);
449 : }
450 :
451 0 : GDrawPopClip(pixmap,&old1);
452 0 : return( true );
453 : }
454 :
455 0 : static int gbutton_mouse(GGadget *g, GEvent *event) {
456 0 : GLabel *gb = (GLabel *) g;
457 0 : int within = gb->within, pressed = gb->pressed;
458 : int was_state;
459 :
460 0 : if ( !g->takes_input || (g->state!=gs_enabled && g->state!=gs_active && g->state!=gs_focused )) {
461 0 : if ( !g->takes_input && event->type == et_mousemove && !gb->pressed &&
462 0 : g->popup_msg )
463 0 : GGadgetPreparePopup(g->base,g->popup_msg);
464 0 : return( false );
465 : }
466 :
467 0 : if ( gb->labeltype==2 && event->type==et_mousedown &&
468 0 : ((GListButton *) gb)->popup!=NULL ) {
469 0 : GDrawDestroyWindow(((GListButton *) gb)->popup);
470 0 : ((GListButton *) gb)->popup = NULL;
471 0 : return( true );
472 : }
473 0 : was_state = g->state;
474 0 : if ( event->type == et_crossing ) {
475 0 : if ( gb->within && !event->u.crossing.entered )
476 0 : gb->within = false;
477 0 : if ( gb->pressed && (event->u.crossing.state&ksm_buttons)==0 )
478 0 : gb->pressed = false;
479 0 : } else if ( gb->pressed && event->type==et_mouseup ) {
480 0 : if ( GGadgetWithin(g,event->u.mouse.x,event->u.mouse.y)) {
481 0 : if ( event->type == et_mouseup ) {
482 0 : gb->pressed = false;
483 0 : GButtonInvoked(gb,event);
484 : } else
485 0 : gb->within = false;
486 : } else
487 0 : gb->pressed = false;
488 0 : } else if ( event->type == et_mousedown &&
489 0 : GGadgetWithin(g,event->u.mouse.x,event->u.mouse.y)) {
490 0 : gb->pressed = true;
491 0 : gb->within = true;
492 0 : GButtonPressed(gb);
493 0 : } else if ( event->type == et_mousemove &&
494 0 : GGadgetWithin(g,event->u.mouse.x,event->u.mouse.y)) {
495 0 : gb->within = true;
496 0 : if ( !gb->pressed && g->popup_msg )
497 0 : GGadgetPreparePopup(g->base,g->popup_msg);
498 0 : } else if ( event->type == et_mousemove && gb->within ) {
499 0 : gb->within = false;
500 : } else {
501 0 : return( false );
502 : }
503 0 : if ( within != gb->within && was_state==g->state )
504 0 : g->state = gb->within? gs_active : gs_enabled;
505 0 : if ( within != gb->within || pressed != gb->pressed )
506 0 : _ggadget_redraw(g);
507 0 : return( event->type==et_mousedown || event->type==et_mouseup || gb->within );
508 : }
509 :
510 0 : static int gbutton_key(GGadget *g, GEvent *event) {
511 0 : GLabel *gb = (GLabel *) g;
512 :
513 0 : if ( !g->takes_input || (g->state!=gs_enabled && g->state!=gs_active ))
514 0 : return(false);
515 0 : if ( gb->labeltype==2 && ((GListButton *) gb)->popup!=NULL ) {
516 0 : GWindow popup = ((GListButton *) gb)->popup;
517 0 : (GDrawGetEH(popup))(popup,event);
518 0 : return( true );
519 : }
520 :
521 0 : if ( event->u.chr.chars[0]==' ' ) {
522 0 : GButtonInvoked(gb,NULL);
523 0 : return( true );
524 : }
525 0 : return(false);
526 : }
527 :
528 0 : static int gbutton_focus(GGadget *g, GEvent *event) {
529 0 : GLabel *gb = (GLabel *) g;
530 :
531 0 : if ( !g->takes_input || (g->state!=gs_enabled && g->state!=gs_active ))
532 0 : return(false);
533 :
534 0 : if ( event->u.focus.mnemonic_focus==mf_shortcut ||
535 0 : event->u.focus.mnemonic_focus==mf_mnemonic ) {
536 0 : GButtonInvoked(gb,NULL);
537 0 : return( true );
538 : }
539 0 : return( true );
540 : }
541 :
542 0 : static void gbutton_destroy(GGadget *g) {
543 0 : GButton *b = (GButton *) g;
544 :
545 0 : if ( b==NULL )
546 0 : return;
547 0 : if ( b->labeltype==2 ) {
548 0 : GListButton *glb = (GListButton *) g;
549 0 : if ( glb->popup ) {
550 0 : GDrawDestroyWindow(glb->popup);
551 0 : GDrawSync(NULL);
552 0 : GDrawProcessWindowEvents(glb->popup); /* popup's destroy routine must execute before we die */
553 : }
554 0 : GTextInfoArrayFree(glb->ti);
555 : }
556 0 : free(b->label);
557 0 : _ggadget_destroy(g);
558 : }
559 :
560 : static int GButtonGetDesiredWidth(GLabel *gl);
561 0 : static void GButtonSetInner(GButton *b) {
562 0 : int width, mark = 0;
563 0 : int bp = GBoxBorderWidth(b->g.base,b->g.box);
564 :
565 0 : if ( b->labeltype==2 )
566 0 : mark = GDrawPointsToPixels(b->g.base,_GListMarkSize) +
567 0 : GDrawPointsToPixels(b->g.base,_GGadget_TextImageSkip);
568 0 : width = GButtonGetDesiredWidth(b);
569 0 : if ( width<=b->g.r.width-2*bp-mark )
570 0 : b->g.inner.width = width;
571 : else
572 0 : b->g.inner.width = b->g.r.width-2*bp;
573 0 : if ( !b->g.takes_input )
574 0 : b->g.inner.x = b->g.r.x + bp;
575 : else
576 0 : b->g.inner.x = b->g.r.x + (b->g.r.width-b->g.inner.width-mark)/2;
577 0 : }
578 :
579 0 : static void GButtonSetTitle(GGadget *g,const unichar_t *tit) {
580 0 : GButton *b = (GButton *) g;
581 :
582 0 : if ( b->g.free_box )
583 0 : free( b->g.box );
584 0 : free(b->label);
585 0 : b->label = u_copy(tit);
586 0 : GButtonSetInner(b);
587 0 : _ggadget_redraw(g);
588 0 : }
589 :
590 0 : static void GButtonSetImageTitle(GGadget *g,GImage *img,const unichar_t *tit, int before) {
591 0 : GButton *b = (GButton *) g;
592 :
593 0 : if ( b->g.free_box )
594 0 : free( b->g.box );
595 0 : free(b->label);
596 0 : b->label = u_copy(tit);
597 0 : b->image = img;
598 0 : b->image_precedes = before;
599 :
600 0 : GButtonSetInner(b);
601 :
602 0 : _ggadget_redraw(g);
603 0 : }
604 :
605 0 : static const unichar_t *_GButtonGetTitle(GGadget *g) {
606 0 : GButton *b = (GButton *) g;
607 0 : return( b->label );
608 : }
609 :
610 0 : static GImage *GButtonGetImage(GGadget *g) {
611 0 : GButton *b = (GButton *) g;
612 0 : return( b->image );
613 : }
614 :
615 0 : static void GButtonSetFont(GGadget *g,FontInstance *new) {
616 0 : GButton *b = (GButton *) g;
617 0 : b->font = new;
618 0 : }
619 :
620 0 : static FontInstance *GButtonGetFont(GGadget *g) {
621 0 : GButton *b = (GButton *) g;
622 0 : return( b->font );
623 : }
624 :
625 0 : static void GListBSelectOne(GGadget *g, int32 pos) {
626 0 : GListButton *gl = (GListButton *) g;
627 : int i;
628 :
629 0 : for ( i=0; i<gl->ltot; ++i )
630 0 : gl->ti[i]->selected = false;
631 0 : if ( pos>=gl->ltot ) pos = gl->ltot-1;
632 0 : if ( pos<0 ) pos = 0;
633 0 : if ( gl->ltot>0 ) {
634 0 : gl->ti[pos]->selected = true;
635 0 : GButtonSetImageTitle(g,gl->ti[pos]->image,gl->ti[pos]->text,gl->ti[pos]->image_precedes);
636 : }
637 0 : }
638 :
639 0 : static int32 GListBIsSelected(GGadget *g, int32 pos) {
640 0 : GListButton *gl = (GListButton *) g;
641 :
642 0 : if ( pos>=gl->ltot )
643 0 : return( false );
644 0 : if ( pos<0 )
645 0 : return( false );
646 0 : if ( gl->ltot>0 )
647 0 : return( gl->ti[pos]->selected );
648 :
649 0 : return( false );
650 : }
651 :
652 0 : static int32 GListBGetFirst(GGadget *g) {
653 : int i;
654 0 : GListButton *gl = (GListButton *) g;
655 :
656 0 : for ( i=0; i<gl->ltot; ++i )
657 0 : if ( gl->ti[i]->selected )
658 0 : return( i );
659 :
660 0 : return( -1 );
661 : }
662 :
663 0 : static GTextInfo **GListBGet(GGadget *g,int32 *len) {
664 0 : GListButton *gl = (GListButton *) g;
665 0 : if ( len!=NULL ) *len = gl->ltot;
666 0 : return( gl->ti );
667 : }
668 :
669 0 : static GTextInfo *GListBGetItem(GGadget *g,int32 pos) {
670 0 : GListButton *gl = (GListButton *) g;
671 0 : if ( pos<0 || pos>=gl->ltot )
672 0 : return( NULL );
673 :
674 0 : return(gl->ti[pos]);
675 : }
676 :
677 0 : static void GListButSet(GGadget *g,GTextInfo **ti,int32 docopy) {
678 0 : GListButton *gl = (GListButton *) g;
679 : int i;
680 :
681 0 : GTextInfoArrayFree(gl->ti);
682 0 : if ( docopy || ti==NULL )
683 0 : ti = GTextInfoArrayCopy(ti);
684 0 : gl->ti = ti;
685 0 : gl->ltot = GTextInfoArrayCount(ti);
686 0 : for ( i=0; ti[i]->text!=NULL || ti[i]->line; ++i ) {
687 0 : if ( ti[i]->selected && ti[i]->text!=NULL ) {
688 0 : GGadgetSetTitle(g,ti[i]->text);
689 0 : break;
690 : }
691 : }
692 0 : }
693 :
694 0 : static void GListButClear(GGadget *g) {
695 0 : GListButSet(g,NULL,true);
696 0 : }
697 :
698 0 : static int GButtonIsDefault(GGadget *g) {
699 0 : GLabel *gl = (GLabel *) g;
700 0 : return( gl->is_default );
701 : }
702 :
703 0 : static int GButtonGetDesiredWidth(GLabel *gl) {
704 0 : int iwidth=0, width=0;
705 0 : if ( gl->image!=NULL ) {
706 0 : iwidth = GImageGetScaledWidth(gl->g.base,gl->image);
707 : }
708 0 : if ( gl->label!=NULL ) {
709 : int lcnt;
710 0 : gbutton_textsize(gl,&lcnt,&width);
711 : }
712 :
713 0 : if ( width!=0 && iwidth!=0 )
714 0 : width += GDrawPointsToPixels(gl->g.base,_GGadget_TextImageSkip);
715 0 : width += iwidth;
716 :
717 0 : if ( gl->labeltype==3 )
718 0 : width += GDrawPointsToPixels(gl->g.base,_GGadget_TextImageSkip) +
719 0 : GDrawPointsToPixels(gl->g.base,COLOR_BUTTON_BOX_LEN);
720 0 : return( width );
721 : }
722 :
723 0 : static void GButtonGetDesiredSize(GGadget *g, GRect *outer, GRect *inner) {
724 0 : GLabel *gl = (GLabel *) g;
725 0 : int iwidth=0, iheight=0;
726 : GTextBounds bounds;
727 0 : int as=0, ds, ld, fh=0, width=0;
728 : GRect needed;
729 : int i;
730 0 : int bp = GBoxBorderWidth(g->base,g->box);
731 :
732 0 : if ( gl->image!=NULL ) {
733 0 : iwidth = GImageGetScaledWidth(gl->g.base,gl->image);
734 0 : iheight = GImageGetScaledHeight(gl->g.base,gl->image);
735 : }
736 0 : GDrawWindowFontMetrics(g->base,gl->font,&as, &ds, &ld);
737 0 : if ( gl->label!=NULL ) {
738 : int lcnt;
739 0 : unichar_t *ltxt = NULL;
740 0 : ltxt = gbutton_textsize(gl,&lcnt,&width);
741 0 : if ( lcnt==1 ) {
742 0 : FontInstance *old = GDrawSetFont(gl->g.base,gl->font);
743 0 : width = GDrawGetTextBounds(gl->g.base,ltxt, -1, &bounds);
744 0 : GDrawSetFont(gl->g.base,old);
745 0 : if ( as<bounds.as ) as = bounds.as;
746 0 : if ( ds<bounds.ds ) ds = bounds.ds;
747 0 : fh = as+ds;
748 : } else
749 0 : fh = gl->fh*lcnt;
750 : } else
751 0 : fh = as+ds;
752 :
753 0 : if ( gl->labeltype==3 ) {
754 0 : if ( width!=0 )
755 0 : width += GDrawPointsToPixels(NULL,COLOR_BUTTON_BOX_LEN) +
756 0 : GDrawPointsToPixels(gl->g.base,_GGadget_TextImageSkip);
757 : else
758 0 : width = GDrawPointsToPixels(NULL,COLOR_BUTTON_BOX_LEN);
759 : }
760 :
761 0 : if ( width!=0 && iwidth!=0 )
762 0 : width += GDrawPointsToPixels(gl->g.base,_GGadget_TextImageSkip);
763 0 : width += iwidth;
764 0 : if ( iheight<fh )
765 0 : iheight = fh;
766 :
767 0 : if ( gl->labeltype==2 ) {
768 0 : GListButton *glb = (GListButton *) gl;
769 : int temp;
770 0 : int extra = GDrawPointsToPixels(gl->g.base,_GListMarkSize) +
771 0 : 2*GDrawPointsToPixels(gl->g.base,_GGadget_TextImageSkip) +
772 0 : GBoxBorderWidth(gl->g.base,&_GListMark_Box);
773 0 : for ( i=0; i<glb->ltot; ++i ) {
774 0 : temp = GTextInfoGetWidth(gl->g.base,glb->ti[i],gl->font) + extra;
775 0 : if ( temp>width ) width = temp;
776 0 : temp = GTextInfoGetHeight(gl->g.base,glb->ti[i],gl->font);
777 0 : if ( temp>iheight )
778 0 : iheight = temp;
779 : }
780 0 : width += GDrawPointsToPixels(gl->g.base,_GGadget_TextImageSkip) +
781 0 : GDrawPointsToPixels(gl->g.base,_GListMarkSize);
782 : }
783 :
784 0 : if ( gl->shiftonpress ) {
785 0 : ++width; ++iheight; /* one pixel for movement when button is pushed */
786 : }
787 :
788 0 : width += gl->g.takes_input?2*GDrawPointsToPixels(gl->g.base,2):0;
789 0 : needed.x = needed.y = 0;
790 0 : needed.width = width;
791 0 : needed.height = iheight;
792 0 : if ( g->desired_width>2*bp )
793 0 : needed.width = g->desired_width-2*bp;
794 0 : if ( g->desired_height>2*bp )
795 0 : needed.height = g->desired_height-2*bp;
796 0 : if ( inner!=NULL ) {
797 0 : inner->x = inner->y = 0;
798 0 : inner->width = width;
799 0 : inner->height = iheight;
800 : }
801 :
802 0 : _ggadgetFigureSize(gl->g.base,gl->g.box,&needed,gl->is_default);
803 :
804 0 : if ( outer!=NULL ) {
805 0 : outer->x = outer->y = 0;
806 0 : outer->width = needed.width;
807 0 : outer->height = needed.height;
808 : }
809 0 : }
810 :
811 0 : static void _gbutton_resize(GGadget *g, int32 width, int32 height ) {
812 : GRect inner;
813 0 : int bp = GBoxBorderWidth(g->base,g->box);
814 :
815 0 : GButtonGetDesiredSize(g,NULL,&inner);
816 0 : if ( inner.height<height-2*bp ) inner.height = height-2*bp;
817 :
818 0 : g->inner.height = inner.height;
819 0 : g->inner.y = g->r.y + (height-inner.height)/2;
820 0 : g->r.width = width;
821 0 : g->r.height = height;
822 0 : GButtonSetInner((GButton *) g);
823 0 : }
824 :
825 : struct gfuncs gbutton_funcs = {
826 : 0,
827 : sizeof(struct gfuncs),
828 :
829 : gbutton_expose,
830 : gbutton_mouse,
831 : gbutton_key,
832 : NULL,
833 : gbutton_focus,
834 : NULL,
835 : NULL,
836 :
837 : _ggadget_redraw,
838 : _ggadget_move,
839 : _gbutton_resize,
840 : _ggadget_setvisible,
841 : _ggadget_setenabled,
842 : _ggadget_getsize,
843 : _ggadget_getinnersize,
844 :
845 : gbutton_destroy,
846 :
847 : GButtonSetTitle,
848 : _GButtonGetTitle,
849 : NULL,
850 : GButtonSetImageTitle,
851 : GButtonGetImage,
852 :
853 : GButtonSetFont,
854 : GButtonGetFont,
855 :
856 : NULL,
857 : NULL,
858 : NULL,
859 : NULL,
860 : NULL,
861 : NULL,
862 : NULL,
863 : NULL,
864 : NULL,
865 : NULL,
866 : NULL,
867 :
868 : GButtonGetDesiredSize,
869 : _ggadget_setDesiredSize,
870 : NULL,
871 : GButtonIsDefault
872 : };
873 :
874 : struct gfuncs glistbutton_funcs = {
875 : 0,
876 : sizeof(struct gfuncs),
877 :
878 : gbutton_expose,
879 : gbutton_mouse,
880 : gbutton_key,
881 : NULL,
882 : gbutton_focus,
883 : NULL,
884 : NULL,
885 :
886 : _ggadget_redraw,
887 : _ggadget_move,
888 : _gbutton_resize,
889 : _ggadget_setvisible,
890 : _ggadget_setenabled,
891 : _ggadget_getsize,
892 : _ggadget_getinnersize,
893 :
894 : gbutton_destroy,
895 :
896 : GButtonSetTitle,
897 : _GButtonGetTitle,
898 : NULL,
899 : GButtonSetImageTitle,
900 : GButtonGetImage,
901 :
902 : GButtonSetFont,
903 : GButtonGetFont,
904 :
905 : GListButClear,
906 : GListButSet,
907 : GListBGet,
908 : GListBGetItem,
909 : NULL,
910 : GListBSelectOne,
911 : GListBIsSelected,
912 : GListBGetFirst,
913 : NULL,
914 : NULL,
915 : NULL,
916 :
917 : GButtonGetDesiredSize,
918 : _ggadget_setDesiredSize, /* GTextField does this right. but this is good enough for now */
919 : NULL,
920 : NULL
921 : };
922 :
923 0 : void _GButton_SetDefault(GGadget *g,int32 is_default) {
924 0 : GButton *gb = (GButton *) g;
925 : GRect maxr;
926 0 : int scale = GDrawPointsToPixels(g->base,1);
927 0 : int def_size = (g->box->flags & box_draw_default)?scale+GDrawPointsToPixels(g->base,2):0;
928 :
929 0 : if ( gb->is_default == is_default )
930 0 : return;
931 0 : gb->is_default = is_default;
932 0 : if ( def_size==0 )
933 0 : return;
934 0 : if ( is_default ) {
935 0 : g->r.x -= def_size;
936 0 : g->r.y -= def_size;
937 0 : g->r.width += 2*def_size;
938 0 : g->r.height += 2*def_size;
939 0 : maxr = g->r;
940 : } else {
941 0 : maxr = g->r;
942 0 : g->r.x += def_size;
943 0 : g->r.y += def_size;
944 0 : g->r.width -= 2*def_size;
945 0 : g->r.height -= 2*def_size;
946 : }
947 0 : ++maxr.width; ++maxr.height;
948 0 : GDrawRequestExpose(g->base, &maxr, false);
949 : }
950 :
951 0 : void _GButtonInit(void) {
952 : #ifdef __Mac
953 : extern GBox _ggadget_Default_Box;
954 : #endif
955 :
956 0 : if ( gbutton_inited )
957 0 : return;
958 :
959 0 : GGadgetInit();
960 0 : _GGadgetCopyDefaultBox(&label_box);
961 0 : _GGadgetCopyDefaultBox(&_GGadget_button_box);
962 : #ifdef __Mac
963 : _GGadget_button_box.border_type = bt_box;
964 : _GGadget_button_box.border_width = 1;
965 : _GGadget_button_box.border_shape = bs_roundrect;
966 : _GGadget_button_box.flags |= box_do_depressed_background;
967 : _GGadget_button_box.padding = 1;
968 : #else
969 0 : _GGadget_button_box.flags |= box_foreground_border_inner|box_foreground_border_outer|
970 : /*box_active_border_inner|*/box_do_depressed_background|box_draw_default;
971 : #endif
972 0 : label_box.border_type = bt_none;
973 0 : label_box.border_width = label_box.padding = /*label_box.flags =*/ 0;
974 0 : button_font = _GGadgetInitDefaultBox("GButton.",&_GGadget_button_box,NULL);
975 0 : label_font = _GGadgetInitDefaultBox("GLabel.",&label_box,button_font);
976 0 : shift_on_press = GResourceFindBool("GButton.ShiftOnPress",false);
977 0 : _GGadget_droplist_box = _GGadget_button_box;
978 0 : _GGadget_defaultbutton_box = _GGadget_button_box;
979 0 : _GGadget_cancelbutton_box = _GGadget_button_box;
980 : #ifdef __Mac
981 : _GGadget_defaultbutton_box.flags |= box_gradient_bg;
982 : _GGadget_defaultbutton_box.main_background = 0x64a4f2;
983 : _GGadget_defaultbutton_box.gradient_bg_end = 0xb7ceeb;
984 : _GGadget_cancelbutton_box.flags |= box_gradient_bg;
985 : _GGadget_cancelbutton_box.main_background = 0xf27458;
986 : _GGadget_cancelbutton_box.gradient_bg_end = 0xebb4a0;
987 : _GGadget_droplist_box.border_type = _ggadget_Default_Box.border_type;
988 : _GGadget_droplist_box.border_width = _ggadget_Default_Box.border_width;
989 : _GGadget_droplist_box.border_shape = _ggadget_Default_Box.border_shape;
990 : #endif
991 0 : _GGadget_colorbutton_box = _GGadget_button_box;
992 0 : _GGadgetInitDefaultBox("GDefaultButton.",&_GGadget_defaultbutton_box,NULL);
993 0 : _GGadgetInitDefaultBox("GCancelButton.",&_GGadget_cancelbutton_box,NULL);
994 0 : _GGadgetInitDefaultBox("GDropList.",&_GGadget_droplist_box,NULL);
995 0 : _GGadgetInitDefaultBox("GColorButton.",&_GGadget_colorbutton_box,NULL);
996 0 : gbutton_inited = true;
997 : }
998 :
999 0 : static void GLabelFit(GLabel *gl) {
1000 0 : int as=0, ds, ld;
1001 : GRect outer,inner;
1002 :
1003 0 : if ( gl->g.r.width == -1 ) {
1004 0 : gl->g.r.width = GDrawPointsToPixels(gl->g.base,GIntGetResource(_NUM_Buttonsize));
1005 0 : if ( gl->is_default )
1006 0 : gl->g.r.width += 6;
1007 : }
1008 :
1009 0 : GDrawWindowFontMetrics(gl->g.base,gl->font,&as, &ds, &ld);
1010 0 : gl->as = as;
1011 0 : gl->fh = as+ds;
1012 :
1013 0 : GButtonGetDesiredSize(&gl->g,&outer, &inner);
1014 0 : _ggadgetSetRects(&gl->g,&outer, &inner, 0, 0);
1015 0 : if ( gl->g.takes_input )
1016 0 : GButtonSetInner((GButton *) gl);
1017 0 : }
1018 :
1019 0 : static GLabel *_GLabelCreate(GLabel *gl, struct gwindow *base, GGadgetData *gd,void *data, GBox *def) {
1020 0 : if ( !gbutton_inited )
1021 0 : _GButtonInit();
1022 0 : gl->g.funcs = &gbutton_funcs;
1023 0 : _GGadget_Create(&gl->g,base,gd,data,def);
1024 :
1025 0 : if (( gl->is_default = gd->flags&gg_but_default?1:0 ) )
1026 0 : _GWidget_SetDefaultButton(&gl->g);
1027 0 : if (( gl->is_cancel = gd->flags&gg_but_cancel?1:0 ))
1028 0 : _GWidget_SetCancelButton(&gl->g);
1029 0 : gl->font = def==&label_box ? label_font : button_font;
1030 0 : if ( gd->label!=NULL ) {
1031 0 : gl->image_precedes = gd->label->image_precedes;
1032 0 : if ( gd->label->font!=NULL )
1033 0 : gl->font = gd->label->font;
1034 0 : if ( gd->label->text_in_resource && gd->label->text_is_1byte )
1035 0 : gl->label = utf82u_mncopy((char *) gd->label->text,&gl->g.mnemonic);
1036 0 : else if ( gd->label->text_in_resource )
1037 0 : gl->label = u_copy((unichar_t *) GStringGetResource((intpt) gd->label->text,&gl->g.mnemonic));
1038 0 : else if ( gd->label->text_is_1byte )
1039 0 : gl->label = /* def2u_*/ utf82u_copy((char *) gd->label->text);
1040 : else
1041 0 : gl->label = u_copy(gd->label->text);
1042 0 : gl->image = gd->label->image;
1043 : }
1044 0 : gl->shiftonpress = shift_on_press;
1045 0 : GLabelFit(gl);
1046 0 : _GGadget_FinalPosition(&gl->g,base,gd);
1047 :
1048 0 : if ( gd->flags & gg_group_end )
1049 0 : _GGadgetCloseGroup(&gl->g);
1050 0 : return( gl );
1051 : }
1052 :
1053 0 : GGadget *GLabelCreate(struct gwindow *base, GGadgetData *gd,void *data) {
1054 0 : GLabel *gl = calloc(1,sizeof(GListButton));;
1055 : int i;
1056 :
1057 0 : if ( gd->u.list!=NULL ) {
1058 0 : gl->ti = GTextInfoArrayFromList(gd->u.list,&gl->ltot);
1059 : }
1060 0 : if ( gd->label==NULL && gd->u.list!=NULL ) {
1061 0 : for ( i=0; gd->u.list[i].text == NULL; ++i );
1062 0 : if ( gd->u.list[i].text!=NULL )
1063 0 : gd->label = &gd->u.list[i];
1064 : }
1065 0 : gl = _GLabelCreate(gl,base,gd,data,&label_box);
1066 0 : return( &gl->g );
1067 : }
1068 :
1069 0 : GGadget *GButtonCreate(struct gwindow *base, GGadgetData *gd,void *data) {
1070 0 : GLabel *gl = _GLabelCreate(calloc(1,sizeof(GLabel)),base,gd,data,
1071 0 : gd->flags & gg_but_default ? &_GGadget_defaultbutton_box :
1072 0 : gd->flags & gg_but_cancel ? &_GGadget_cancelbutton_box :
1073 : &_GGadget_button_box);
1074 :
1075 0 : gl->g.takes_input = true; gl->g.takes_keyboard = true; gl->g.focusable = true;
1076 0 : return( &gl->g );
1077 : }
1078 :
1079 0 : GGadget *GImageButtonCreate(struct gwindow *base, GGadgetData *gd,void *data) {
1080 0 : GImageButton *gl =
1081 0 : (GImageButton *) _GLabelCreate(calloc(1,sizeof(GImageButton)),base,gd,data,&_GGadget_button_box);
1082 :
1083 0 : gl->g.takes_input = true;
1084 0 : gl->labeltype = 1;
1085 0 : if ( gd->label!=NULL ) {
1086 0 : gl->img_within = gd->label[1].image;
1087 0 : gl->active = gd->label[2].image;
1088 0 : gl->disabled = gd->label[3].image;
1089 : }
1090 0 : return( &gl->g );
1091 : }
1092 :
1093 0 : GGadget *GColorButtonCreate(struct gwindow *base, GGadgetData *gd,void *data) {
1094 : GColorButton *gl;
1095 : static GTextInfo ti;
1096 0 : Color col = gd->u.col;
1097 :
1098 0 : if ( ti.image==NULL && ti.text==NULL ) {
1099 0 : ti.image = GGadgetImageCache("colorwheel.png");
1100 0 : if ( ti.image==NULL ) {
1101 0 : ti.text = (unichar_t *) _("Color");
1102 0 : ti.text_is_1byte = true;
1103 : }
1104 : }
1105 0 : gd->label = &ti;
1106 0 : gl = calloc(1,sizeof(GColorButton));
1107 0 : gl->labeltype = 3;
1108 0 : gl = (GColorButton *) _GLabelCreate((GLabel *) gl,base,gd,data,&_GGadget_colorbutton_box);
1109 0 : gl->g.takes_input = true;
1110 0 : gl->col = col;
1111 0 : return( &gl->g );
1112 : }
1113 :
1114 0 : void GColorButtonSetColor(GGadget *g, Color col) {
1115 0 : GColorButton *gb = (GColorButton *) g;
1116 0 : gb->col = col;
1117 0 : GGadgetRedraw(g);
1118 0 : }
1119 :
1120 0 : Color GColorButtonGetColor(GGadget *g) {
1121 0 : return( ((GColorButton *) g)->col );
1122 : }
1123 :
1124 0 : static void GListButtonSelected(GGadget *g, int i) {
1125 0 : GListButton *gl = (GListButton *) g;
1126 : GEvent e;
1127 :
1128 0 : gl->popup = NULL;
1129 0 : _GWidget_ClearGrabGadget(&gl->g);
1130 0 : if ( i<0 || i>=gl->ltot )
1131 0 : return;
1132 0 : free(gl->label); gl->label = u_copy(gl->ti[i]->text);
1133 0 : gl->image = gl->ti[i]->image;
1134 0 : gl->image_precedes = gl->ti[i]->image_precedes;
1135 0 : GButtonSetInner((GButton *) gl);
1136 0 : _ggadget_redraw(g);
1137 :
1138 0 : e.type = et_controlevent;
1139 0 : e.w = g->base;
1140 0 : e.u.control.subtype = et_listselected;
1141 0 : e.u.control.g = g;
1142 0 : e.u.control.u.list.from_mouse = true;
1143 0 : if ( gl->g.handle_controlevent != NULL )
1144 0 : (gl->g.handle_controlevent)(&gl->g,&e);
1145 : else
1146 0 : GDrawPostEvent(&e);
1147 : }
1148 :
1149 0 : static void GListButtonDoPopup(GListButton *gl) {
1150 0 : gl->within = false; gl->pressed = false;
1151 0 : gl->popup = GListPopupCreate(&gl->g,GListButtonSelected,gl->ti);
1152 0 : }
1153 :
1154 0 : static int _GListAlphaCompare(const void *v1, const void *v2) {
1155 0 : GTextInfo * const *pt1 = v1, * const *pt2 = v2;
1156 0 : return( GTextInfoCompare(*pt1,*pt2));
1157 : }
1158 :
1159 0 : GGadget *GListButtonCreate(struct gwindow *base, GGadgetData *gd,void *data) {
1160 0 : GListButton *gl = calloc(1,sizeof(GListButton));
1161 : int i;
1162 :
1163 0 : gl->labeltype = 2;
1164 0 : gl->g.takes_input = true;
1165 0 : if ( gd->u.list!=NULL ) {
1166 0 : gl->ti = GTextInfoArrayFromList(gd->u.list,&gl->ltot);
1167 0 : if ( gd->flags & gg_list_alphabetic )
1168 0 : qsort(gl->ti,gl->ltot,sizeof(GTextInfo *),_GListAlphaCompare);
1169 : }
1170 0 : if ( gd->label==NULL && gd->u.list!=NULL ) {
1171 : /* find first selected item if there is one */
1172 0 : for ( i=0; gd->u.list[i].text!=NULL || gd->u.list[i].line; ++i )
1173 0 : if ( gd->u.list[i].selected )
1174 0 : break;
1175 : /* else first item with text */
1176 0 : if ( gd->u.list[i].text==NULL && !gd->u.list[i].line ) {
1177 0 : for ( i=0; gd->u.list[i].line; ++i );
1178 0 : if ( gd->u.list[i].text==NULL && !gd->u.list[i].line )
1179 0 : i = 0;
1180 : }
1181 0 : gd->label = &gd->u.list[i];
1182 : }
1183 0 : _GLabelCreate((GLabel *) gl,base,gd,data,&_GGadget_droplist_box);
1184 0 : gl->g.funcs = &glistbutton_funcs;
1185 0 : return( &gl->g );
1186 : }
1187 :
1188 0 : GResInfo *_GButtonRIHead(void) {
1189 0 : _GButtonInit();
1190 0 : return( &glabel_ri );
1191 : }
|