Jitterbug no more.
[fvwm.git] / modules / FvwmGtk / dialog.c
blobcbe294909fcbc0de9d9eb085340acceb37dc8513
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 #include "config.h"
19 #include <stdio.h>
20 #include <unistd.h>
22 #include <X11/Xlib.h>
23 #include <X11/keysym.h>
24 #include <X11/Xutil.h>
25 #include <X11/Xproto.h>
26 #include <X11/Xatom.h>
27 #include <X11/Intrinsic.h>
29 #include <glib.h>
30 #include <gtk/gtk.h>
31 #include <gdk/gdkprivate.h>
33 #include "libs/fvwmlib.h"
34 #include "libs/Module.h"
36 #include "menu.h"
37 #include "expand.h"
39 extern int fvwm_fd[2];
40 extern GHashTable *widgets;
41 extern GtkWidget *current;
42 extern unsigned long context;
44 GSList *radio_group = NULL;
45 char *group_name = NULL;
46 GtkWidget *menu = NULL;
47 int option_menu_items = 0;
48 int option_menu_active_item = 0;
49 char *notebook_label = NULL;
52 gpointer
53 widget_get_value (GtkWidget *w)
55 static char buf[100];
57 if (GTK_IS_OPTION_MENU (w))
59 GtkWidget *menu = GTK_OPTION_MENU (w)->menu;
60 GtkWidget *item;
62 if (menu == NULL)
63 return NULL;
64 item = gtk_menu_get_active (GTK_MENU (menu));
65 if (item)
67 return gtk_object_get_data (GTK_OBJECT (item), "value");
69 else
71 return NULL;
74 else if (GTK_IS_SCALE (w))
76 g_snprintf (buf, sizeof (buf), "%.*f",
77 GTK_RANGE (w)->digits,
78 gtk_range_get_adjustment (GTK_RANGE (w))->value);
79 return buf;
81 else if (GTK_IS_COLOR_SELECTION (w))
83 double rgb[3];
84 unsigned long red, green, blue;
86 gtk_color_selection_get_color (GTK_COLOR_SELECTION (w), rgb);
87 red = rgb[0] * 65536;
88 if (red >= 65536)
90 red = 65535;
92 green = rgb[1] * 65536;
93 if (green >= 65536)
95 green = 65535;
97 blue = rgb[2] * 65536;
98 if (blue >= 65536)
100 blue = 65535;
102 g_snprintf (buf, sizeof (buf), "rgb:%.4lx/%.4lx/%.4lx",
103 red, green, blue);
104 return buf;
106 else if (GTK_IS_ENTRY (w))
108 /* this also catches spin buttons */
109 return gtk_entry_get_text (GTK_ENTRY (w));
111 else if (GTK_IS_TOGGLE_BUTTON (w))
113 if (GTK_TOGGLE_BUTTON (w)->active)
115 return gtk_object_get_data (GTK_OBJECT (w), "on-value");
117 else
119 return gtk_object_get_data (GTK_OBJECT (w), "off-value");
123 return NULL;
127 /* generic callback added to all data widgets */
128 static void
129 update_value (GtkWidget *w)
131 char *val;
133 val = widget_get_value (w);
134 if (val)
136 gtk_object_set_data_full (GTK_OBJECT (gtk_widget_get_toplevel (w)),
137 gtk_widget_get_name (w), safestrdup (val), free);
142 static void
143 add_to_dialog (GtkWidget *w, int argc, char **argv)
145 int i;
146 gboolean expand = FALSE;
147 gboolean fill = FALSE;
148 gboolean focus = FALSE;
149 gboolean def = FALSE;
150 gboolean can_def = FALSE;
151 unsigned int padding = 0;
152 GtkWidget *dialog;
154 dialog = gtk_widget_get_toplevel (w);
155 for (i = argc - 1; i >= 0; i--)
157 if (strcmp (argv[i], "--") == 0)
159 for (i++; i < argc; i++)
161 if (strcasecmp (argv[i], "default") == 0)
163 can_def = TRUE;
164 def = TRUE;
166 else if (strcasecmp (argv[i], "can-default") == 0)
168 can_def = TRUE;
170 else if (strcasecmp (argv[i], "focus") == 0)
172 focus = TRUE;
174 else if (strcasecmp (argv[i], "expand") == 0)
176 expand = TRUE;
178 else if (strcasecmp (argv[i], "fill") == 0)
180 fill = TRUE;
182 else
184 padding = atoi (argv[i]);
187 break;
190 if (GTK_IS_NOTEBOOK (current))
192 gtk_notebook_append_page (GTK_NOTEBOOK (current), w,
193 gtk_label_new (notebook_label));
195 else if (GTK_IS_BOX (current))
197 gtk_box_pack_start (GTK_BOX (current), w, expand, fill, padding);
199 else
201 gtk_container_add (GTK_CONTAINER (current), w);
203 if (focus)
205 gtk_widget_grab_focus (w);
207 if (can_def)
209 GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
211 if (def)
213 gtk_widget_grab_default (w);
215 update_value (w);
219 void
220 send_values (GtkWidget *w)
222 GtkWidget *dialog;
223 char **vals;
225 dialog = gtk_widget_get_toplevel (w);
226 for (vals = (char **) gtk_object_get_data (GTK_OBJECT (w), "return_values");
227 *vals; vals++)
229 char *val = recursive_replace (dialog, *vals);
230 if (strcasecmp (val, "close") == 0)
232 gtk_widget_hide (dialog);
234 else
236 if (val[0] == '!')
238 system (val + 1);
240 else
242 SendText (fvwm_fd, val, context);
245 free (val);
249 void
250 open_dialog (int argc, char **argv)
252 GtkWidget *item;
253 char *name;
255 g_return_if_fail (argc >= 2);
257 item = g_hash_table_lookup (widgets, argv[0]);
258 if (item)
260 name = gtk_widget_get_name (item);
262 else
264 item = gtk_window_new (GTK_WINDOW_DIALOG);
265 gtk_widget_set_name (item, argv[0]);
266 name = gtk_widget_get_name (item);
267 g_hash_table_insert (widgets, name, item);
268 gtk_object_ref (GTK_OBJECT (item));
270 gtk_window_set_title (GTK_WINDOW (item), argv[1]);
271 gtk_window_set_wmclass (GTK_WINDOW (item), argv[1], "FvwmGtk");
272 gtk_object_set_data
273 (GTK_OBJECT (item), "values",
274 g_hash_table_new (g_str_hash, g_str_equal));
275 gtk_signal_connect
276 (GTK_OBJECT (item), "delete_event",
277 GTK_SIGNAL_FUNC (gtk_widget_hide), current);
278 if (argc >= 3 && strcasecmp ("center", argv[2]) == 0)
280 gtk_window_position (GTK_WINDOW (item), GTK_WIN_POS_CENTER);
282 else
284 gtk_window_position (GTK_WINDOW (item), GTK_WIN_POS_MOUSE);
286 if (argc >= 4)
288 int border_width;
290 border_width = atoi (argv[3]);
292 gtk_container_border_width (GTK_CONTAINER (item), border_width);
295 if (GTK_IS_MENU (item))
297 fprintf (stderr, "%s is a menu\n", name);
299 current = item;
303 /* this applies to rows, columns and frames */
304 void
305 dialog_end_something (int argc, char **argv)
307 g_return_if_fail (current != NULL);
308 current = GTK_WIDGET (current)->parent;
312 void
313 dialog_label (int argc, char **argv)
315 GtkWidget *item;
317 g_return_if_fail (argc >= 1);
319 item = gtk_label_new (argv[0]);
320 gtk_widget_show (item);
321 add_to_dialog (item, argc, argv);
325 void
326 dialog_notebook (int argc, char **argv)
328 g_return_if_fail (argc >= 1);
330 if (!GTK_IS_NOTEBOOK (current))
332 GtkWidget *nb = gtk_notebook_new ();
333 gtk_widget_show (nb);
334 add_to_dialog (nb, argc, argv);
335 current = nb;
337 if (notebook_label)
339 free (notebook_label);
340 notebook_label = NULL;
342 notebook_label = safestrdup (argv[0]);
346 void
347 dialog_end_notebook (int argc, char **argv)
349 g_return_if_fail (current != NULL);
351 if (notebook_label)
353 free (notebook_label);
354 notebook_label = NULL;
356 current = GTK_WIDGET (current)->parent;
360 void
361 dialog_start_frame (int argc, char **argv)
363 GtkWidget *item;
365 g_return_if_fail (argc >= 1);
367 item = gtk_frame_new (argv[0]);
368 if (argc >= 2)
370 int border_width;
372 border_width = atoi (argv[1]);
374 gtk_container_border_width (GTK_CONTAINER (item), border_width);
376 gtk_widget_show (item);
377 add_to_dialog (item, argc, argv);
378 current = item;
382 void
383 dialog_button (int argc, char **argv)
385 GtkWidget *item;
386 char **vals;
387 int i;
389 g_return_if_fail (argc >= 2);
391 item = gtk_button_new_with_label (argv[0]);
393 vals = (char **) safemalloc (argc * sizeof (char *));
394 for (i = 0; i < argc - 1; i++)
396 if (strcmp (argv[i+1], "--") == 0)
398 break;
400 vals[i] = safestrdup(argv[i + 1]);
402 vals[i] = NULL;
403 gtk_object_set_data (GTK_OBJECT (item), "return_values", vals);
404 gtk_signal_connect
405 (GTK_OBJECT (item), "clicked",
406 GTK_SIGNAL_FUNC (send_values), item);
407 gtk_widget_show (item);
408 add_to_dialog (item, argc, argv);
412 void
413 dialog_checkbutton (int argc, char **argv)
415 GtkWidget *item;
417 g_return_if_fail (argc >= 4);
419 item = gtk_check_button_new_with_label (argv[1]);
420 gtk_widget_set_name (item, argv[0]);
421 gtk_object_set_data (GTK_OBJECT (item), "on-value", safestrdup (argv[2]));
422 gtk_object_set_data (GTK_OBJECT (item), "off-value", safestrdup (argv[3]));
423 if (argc >= 5 && strcasecmp (argv[4], "on") == 0)
425 gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (item), TRUE);
427 else
429 gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (item), FALSE);
431 gtk_signal_connect
432 (GTK_OBJECT (item), "toggled",
433 GTK_SIGNAL_FUNC (update_value), item);
435 gtk_widget_show (item);
436 add_to_dialog (item, argc, argv);
440 void
441 dialog_entry (int argc, char **argv)
443 GtkWidget *item;
445 g_return_if_fail (argc >= 1);
446 item = gtk_entry_new ();
447 gtk_widget_set_name (item, argv[0]);
448 if (argc >= 2 && strcmp(argv[1], "--") != 0)
450 gtk_entry_set_text (GTK_ENTRY (item), argv[1]);
452 gtk_signal_connect
453 (GTK_OBJECT (item), "changed",
454 GTK_SIGNAL_FUNC (update_value), item);
455 gtk_widget_show (item);
456 add_to_dialog (item, argc, argv);
460 void
461 dialog_radiobutton (int argc, char **argv)
463 GtkWidget *item;
465 g_return_if_fail (argc >= 2);
467 item = gtk_radio_button_new_with_label (radio_group, argv[0]);
468 radio_group = gtk_radio_button_group (GTK_RADIO_BUTTON (item));
469 gtk_widget_set_name (item, group_name);
470 gtk_object_set_data (GTK_OBJECT (item), "on-value", safestrdup (argv[1]));
471 if (argc >= 3 && strcasecmp (argv[2], "on") == 0)
473 gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (item), TRUE);
475 else
477 gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (item), FALSE);
479 gtk_signal_connect
480 (GTK_OBJECT (item), "toggled",
481 GTK_SIGNAL_FUNC (update_value), item);
483 gtk_widget_show (item);
484 add_to_dialog (item, argc, argv);
488 void
489 dialog_start_radiogroup (int argc, char **argv)
491 g_return_if_fail (argc >= 1);
493 if (group_name)
495 free (group_name);
497 group_name = safestrdup (argv[0]);
498 radio_group = NULL;
502 void
503 dialog_end_radiogroup (int argc, char **argv)
505 if (group_name)
507 free (group_name);
508 group_name = NULL;
510 radio_group = NULL;
514 void
515 dialog_color (int argc, char **argv)
517 GtkWidget *item;
519 g_return_if_fail (argc >= 1);
521 item = gtk_color_selection_new ();
522 gtk_widget_set_name (item, argv[0]);
523 if (argc >= 2)
525 XColor color;
526 /* FIXME: get meaningful colormap */
527 if (XParseColor (gdk_display,
528 DefaultColormap (gdk_display, gdk_screen),
529 argv[1],
530 &color))
532 double rgb[3];
533 rgb[0] = (double) color.red / 65536.0;
534 rgb[1] = (double) color.green / 65536.0;
535 rgb[2] = (double) color.blue / 65536.0;
536 gtk_color_selection_set_color (GTK_COLOR_SELECTION (item), rgb);
539 gtk_signal_connect
540 (GTK_OBJECT (item), "color_changed",
541 GTK_SIGNAL_FUNC (update_value), item);
542 gtk_widget_show (item);
543 add_to_dialog (item, argc, argv);
547 void
548 dialog_start_box (int argc, char **argv)
550 GtkWidget *item;
551 int vertical = 0;
552 int homogeneous = 0;
553 int spacing = 0;
554 unsigned int border_width = 0;
555 int i;
556 gboolean read_spacing = TRUE;
558 for (i = 0; i < argc; i++)
560 if (strcmp (argv[i], "--") == 0)
562 break;
564 else if (strcasecmp (argv[i], "homogeneous") == 0)
566 homogeneous = 1;
568 else if (strcasecmp (argv[i], "vertical") == 0)
570 vertical = 1;
572 else if (read_spacing)
574 spacing = atoi (argv[i]);
575 read_spacing = FALSE;
577 else
579 border_width = atoi (argv[i]);
583 if (vertical)
585 item = gtk_vbox_new (homogeneous, spacing);
587 else
589 item = gtk_hbox_new (homogeneous, spacing);
591 gtk_container_border_width (GTK_CONTAINER (item), border_width);
592 gtk_widget_show (item);
593 add_to_dialog (item, argc, argv);
594 current = item;
598 void
599 dialog_separator (int argc, char **argv)
601 GtkWidget *item;
603 if (GTK_IS_HBOX (current))
605 item = gtk_vseparator_new ();
607 else
609 item = gtk_hseparator_new ();
611 gtk_widget_show (item);
612 add_to_dialog (item, argc, argv);
616 void
617 dialog_scale (int argc, char **argv)
619 unsigned int vertical = 0;
620 unsigned int digits = 0;
621 GtkWidget *item;
622 GtkObject *adj;
623 int i;
625 g_return_if_fail (argc >= 7);
627 i = 0;
628 if (argc >= 8)
630 if (strcasecmp (argv[1], "vertical") == 0)
632 vertical = 1;
633 i = 1;
635 else if (strcasecmp (argv[1], "horizontal") == 0)
637 vertical = 0;
638 i = 1;
642 if (argc >= 8 + i)
644 digits = atoi (argv[i + 7]);
647 adj = gtk_adjustment_new (atof (argv[i + 1]), atof (argv[i + 2]),
648 atof (argv[i + 3]), atof (argv[i + 4]),
649 atof (argv[i + 5]), atof (argv[i + 6]));
650 if (vertical)
652 item = gtk_vscale_new (GTK_ADJUSTMENT (adj));
654 else
656 item = gtk_hscale_new (GTK_ADJUSTMENT (adj));
658 gtk_signal_connect_object
659 (GTK_OBJECT (adj), "value_changed",
660 GTK_SIGNAL_FUNC (update_value), GTK_OBJECT (item));
661 gtk_widget_set_name (item, argv[0]);
662 gtk_scale_set_digits (GTK_SCALE (item), digits);
663 gtk_widget_show (item);
664 add_to_dialog (item, argc, argv);
668 void
669 dialog_spinbutton (int argc, char **argv)
671 GtkWidget *item;
672 GtkObject *adj;
673 unsigned int digits = 0;
675 g_return_if_fail (argc >= 8);
677 if (argc >= 9)
679 digits = atoi (argv[8]);
682 adj = gtk_adjustment_new (atof (argv[1]), atof (argv[2]),
683 atof (argv[3]), atof (argv[4]),
684 atof (argv[5]), atof (argv[6]));
686 item = gtk_spin_button_new (GTK_ADJUSTMENT (adj), atof (argv[7]), digits);
687 gtk_signal_connect_object
688 (GTK_OBJECT (adj), "value_changed",
689 GTK_SIGNAL_FUNC (update_value), GTK_OBJECT (item));
690 gtk_widget_set_name (item, argv[0]);
691 gtk_widget_show (item);
692 add_to_dialog (item, argc, argv);
696 void
697 dialog_start_option_menu (int argc, char **argv)
699 GtkWidget *item;
700 g_return_if_fail (argc >= 1);
702 option_menu_active_item = -1;
703 option_menu_items = 0;
704 item = gtk_option_menu_new ();
705 gtk_widget_set_name (item, argv[0]);
706 menu = gtk_menu_new ();
707 gtk_widget_show (menu);
708 add_to_dialog (item, argc, argv);
709 current = item;
713 void
714 dialog_end_option_menu (int argc, char **argv)
716 gtk_signal_connect_object
717 (GTK_OBJECT (menu), "deactivate",
718 GTK_SIGNAL_FUNC (update_value), GTK_OBJECT (current));
719 gtk_option_menu_set_menu (GTK_OPTION_MENU (current), menu);
720 menu = NULL;
721 if (option_menu_active_item > 0)
723 gtk_option_menu_set_history (GTK_OPTION_MENU (current),
724 option_menu_active_item);
726 update_value (current);
727 gtk_widget_show (current);
728 current = current->parent;
732 void
733 dialog_option_menu_item (int argc, char **argv)
735 GtkWidget *item;
737 g_return_if_fail (argc >= 2);
739 item = menu_item_new_with_pixmap_and_label ("", argv[0], NULL);
741 gtk_object_set_data (GTK_OBJECT (item), "value", safestrdup (argv[1]));
742 gtk_widget_show (item);
744 if (argc >= 3 && strcasecmp (argv[2], "on") == 0)
746 option_menu_active_item = option_menu_items;
749 gtk_menu_append (GTK_MENU (menu), item);
750 option_menu_items++;