]> Pileus Git - ~andy/gtk/blob - gtk/gtkinputdialog.c
More composite children.
[~andy/gtk] / gtk / gtkinputdialog.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library 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 GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * gtkinputdialog.c
22  *
23  * Copyright 1997 Owen Taylor <owt1@cornell.edu>
24  *
25  */
26
27 /*
28  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
29  * file for a list of people on the GTK+ Team.  See the ChangeLog
30  * files for a list of changes.  These files are distributed with
31  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
32  */
33
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <ctype.h>
38 #include "gdk/gdkkeysyms.h"
39 #include "gtkbutton.h"
40 #include "gtkentry.h"
41 #include "gtkhbox.h"
42 #include "gtkhseparator.h"
43 #include "gtkinputdialog.h"
44 #include "gtklabel.h"
45 #include "gtklistitem.h"
46 #include "gtkmain.h"
47 #include "gtkmarshalers.h"
48 #include "gtkmenu.h"
49 #include "gtkmenuitem.h"
50 #include "gtknotebook.h"
51 #include "gtkoptionmenu.h"
52 #include "gtkscrolledwindow.h"
53 #include "gtksignal.h"
54 #include "gtktable.h"
55 #include "gtkvbox.h"
56
57 #include "gtkintl.h"
58
59 typedef struct {
60   gint       index;
61   GtkWidget *entry;
62   GtkInputDialog *inputd;
63 } GtkInputKeyInfo;
64
65 enum
66 {
67   ENABLE_DEVICE,
68   DISABLE_DEVICE,
69   LAST_SIGNAL
70 };
71
72
73 #define AXIS_LIST_WIDTH 160
74 #define AXIS_LIST_HEIGHT 175
75
76 #define KEYS_LIST_WIDTH 200
77 #define KEYS_LIST_HEIGHT 175
78
79 /* Forward declarations */
80
81 static void gtk_input_dialog_class_init       (GtkInputDialogClass *klass);
82 static void gtk_input_dialog_init             (GtkInputDialog      *inputd);
83 static void gtk_input_dialog_set_device       (GtkWidget           *widget,
84                                                gpointer             data);
85 static void gtk_input_dialog_set_mapping_mode (GtkWidget           *w,
86                                                gpointer             data);
87 static void gtk_input_dialog_set_axis         (GtkWidget           *widget,
88                                                gpointer             data);
89 static void gtk_input_dialog_fill_axes        (GtkInputDialog      *inputd,
90                                                GdkDevice           *info);
91 static void gtk_input_dialog_set_key          (GtkInputKeyInfo     *key,
92                                                guint                keyval,
93                                                GdkModifierType      modifiers);
94 static gint gtk_input_dialog_key_press        (GtkWidget           *widget,
95                                                GdkEventKey         *event,
96                                                GtkInputKeyInfo     *key);
97 static void gtk_input_dialog_clear_key        (GtkWidget           *widget,
98                                                GtkInputKeyInfo     *key);
99 static void gtk_input_dialog_destroy_key      (GtkWidget           *widget,
100                                                GtkInputKeyInfo     *key);
101 static void gtk_input_dialog_fill_keys        (GtkInputDialog      *inputd,
102                                                GdkDevice           *info);
103
104 static GtkObjectClass *parent_class = NULL;
105 static guint input_dialog_signals[LAST_SIGNAL] = { 0 };
106
107 GtkType
108 gtk_input_dialog_get_type (void)
109 {
110   static GtkType input_dialog_type = 0;
111
112   if (!input_dialog_type)
113     {
114       static const GtkTypeInfo input_dialog_info =
115       {
116         "GtkInputDialog",
117         sizeof (GtkInputDialog),
118         sizeof (GtkInputDialogClass),
119         (GtkClassInitFunc) gtk_input_dialog_class_init,
120         (GtkObjectInitFunc) gtk_input_dialog_init,
121         /* reserved_1 */ NULL,
122         /* reserved_2 */ NULL,
123         (GtkClassInitFunc) NULL,
124       };
125
126       input_dialog_type = gtk_type_unique (GTK_TYPE_DIALOG,
127                                            &input_dialog_info);
128     }
129
130   return input_dialog_type;
131 }
132
133 static void
134 gtk_input_dialog_class_init (GtkInputDialogClass *klass)
135 {
136   GtkObjectClass *object_class;
137
138   object_class = (GtkObjectClass*) klass;
139
140   parent_class = gtk_type_class (GTK_TYPE_DIALOG);
141
142   klass->enable_device = NULL;
143   klass->disable_device = NULL;
144
145   input_dialog_signals[ENABLE_DEVICE] =
146     gtk_signal_new ("enable_device",
147                     GTK_RUN_LAST,
148                     GTK_CLASS_TYPE (object_class),
149                     GTK_SIGNAL_OFFSET (GtkInputDialogClass, enable_device),
150                     _gtk_marshal_VOID__OBJECT,
151                     GTK_TYPE_NONE, 1, GDK_TYPE_DEVICE);
152
153   input_dialog_signals[DISABLE_DEVICE] =
154     gtk_signal_new ("disable_device",
155                     GTK_RUN_LAST,
156                     GTK_CLASS_TYPE (object_class),
157                     GTK_SIGNAL_OFFSET (GtkInputDialogClass, disable_device),
158                     _gtk_marshal_VOID__OBJECT,
159                     GTK_TYPE_NONE, 1, GDK_TYPE_DEVICE);
160 }
161
162 static void
163 gtk_input_dialog_init (GtkInputDialog *inputd)
164 {
165   GtkWidget *vbox;
166   GtkWidget *util_box;
167   GtkWidget *label;
168   GtkWidget *device_menu;
169   GtkWidget *mapping_menu;
170   GtkWidget *menuitem;
171   GtkWidget *optionmenu;
172   GtkWidget *separator;
173   GtkWidget *notebook;
174
175   GList *tmp_list;
176   GList *device_info;
177
178   gtk_widget_push_composite_child ();
179
180   device_info = gdk_devices_list ();
181
182   /* shell and main vbox */
183
184   gtk_window_set_title (GTK_WINDOW (inputd), _("Input"));
185
186   vbox = gtk_vbox_new (FALSE, 4);
187   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
188   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (inputd)->vbox), vbox, TRUE, TRUE, 0);
189
190   if (g_list_length(device_info) <= 1) /* only core device */
191     {
192       label = gtk_label_new (_("No input devices"));
193       gtk_container_add (GTK_CONTAINER (vbox), label);
194
195       gtk_widget_show (label);
196     }
197   else
198     {
199       /* menu for selecting device */
200
201       device_menu = gtk_menu_new ();
202
203       for (tmp_list = device_info; tmp_list; tmp_list = tmp_list->next) {
204         GdkDevice *info = (GdkDevice *)(tmp_list->data);
205         if (info != gdk_device_get_core_pointer ())
206           {
207             menuitem = gtk_menu_item_new_with_label(info->name);
208
209             gtk_menu_shell_append (GTK_MENU_SHELL (device_menu), menuitem);
210             gtk_widget_show (menuitem);
211             gtk_object_set_user_data (GTK_OBJECT (menuitem), inputd);
212             gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
213                                 (GtkSignalFunc) gtk_input_dialog_set_device,
214                                 info);
215           }
216       }
217
218       util_box = gtk_hbox_new (FALSE, 2);
219       gtk_box_pack_start (GTK_BOX (vbox), util_box, FALSE, FALSE, 0);
220
221       label = gtk_label_new(_("_Device:"));
222       gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2);
223
224       optionmenu = gtk_option_menu_new ();
225       gtk_label_set_mnemonic_widget (GTK_LABEL (label), optionmenu);
226       gtk_box_pack_start (GTK_BOX (util_box), optionmenu, TRUE, TRUE, 2);
227       gtk_widget_show (optionmenu);
228       gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), device_menu);
229
230       gtk_widget_show (label);
231
232       /* Device options */
233
234       /* mapping mode option menu */
235
236       mapping_menu = gtk_menu_new ();
237
238       menuitem = gtk_menu_item_new_with_label(_("Disabled"));
239       gtk_menu_shell_append (GTK_MENU_SHELL (mapping_menu), menuitem);
240       gtk_object_set_user_data (GTK_OBJECT (menuitem), inputd);
241       gtk_widget_show (menuitem);
242       gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
243                           (GtkSignalFunc) gtk_input_dialog_set_mapping_mode,
244                           GINT_TO_POINTER (GDK_MODE_DISABLED));
245
246       menuitem = gtk_menu_item_new_with_label(_("Screen"));
247       gtk_menu_shell_append (GTK_MENU_SHELL (mapping_menu), menuitem);
248       gtk_object_set_user_data (GTK_OBJECT (menuitem), inputd);
249       gtk_widget_show (menuitem);
250       gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
251                           (GtkSignalFunc) gtk_input_dialog_set_mapping_mode,
252                           GINT_TO_POINTER (GDK_MODE_SCREEN));
253
254       menuitem = gtk_menu_item_new_with_label(_("Window"));
255       gtk_menu_shell_append (GTK_MENU_SHELL (mapping_menu), menuitem);
256       gtk_object_set_user_data (GTK_OBJECT (menuitem), inputd);
257       gtk_widget_show (menuitem);
258       gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
259                           (GtkSignalFunc) gtk_input_dialog_set_mapping_mode,
260                           GINT_TO_POINTER (GDK_MODE_WINDOW));
261
262       label = gtk_label_new(_("_Mode: "));
263       gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2);
264
265       inputd->mode_optionmenu = gtk_option_menu_new ();
266       gtk_label_set_mnemonic_widget (GTK_LABEL (label), inputd->mode_optionmenu);
267       gtk_box_pack_start (GTK_BOX (util_box), inputd->mode_optionmenu, FALSE, FALSE, 2);
268       gtk_widget_show (inputd->mode_optionmenu);
269       gtk_option_menu_set_menu (GTK_OPTION_MENU (inputd->mode_optionmenu), mapping_menu);
270
271       gtk_widget_show(label);
272
273       gtk_widget_show (util_box);
274
275       util_box = gtk_hbox_new (FALSE, 2);
276       gtk_box_pack_start (GTK_BOX(vbox), util_box, FALSE, FALSE, 0);
277
278       gtk_widget_show (label);
279       gtk_widget_show (util_box);
280
281       separator = gtk_hseparator_new();
282       gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
283       gtk_widget_show (separator);
284
285       /* Notebook */
286
287       notebook = gtk_notebook_new ();
288       gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
289       gtk_widget_show (notebook);
290       
291       /*  The axis listbox  */
292
293       label = gtk_label_new (_("_Axes"));
294
295       inputd->axis_listbox = gtk_scrolled_window_new (NULL, NULL);
296       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(inputd->axis_listbox),
297                                       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
298       
299       gtk_widget_set_usize (inputd->axis_listbox, AXIS_LIST_WIDTH, AXIS_LIST_HEIGHT);
300       gtk_notebook_append_page (GTK_NOTEBOOK(notebook), 
301                                 inputd->axis_listbox, label);
302
303       gtk_widget_show (inputd->axis_listbox);
304
305       inputd->axis_list = 0;
306
307       /* Keys listbox */
308
309       label = gtk_label_new (_("_Keys"));
310
311       inputd->keys_listbox = gtk_scrolled_window_new (NULL, NULL);
312       gtk_widget_set_usize (inputd->keys_listbox, KEYS_LIST_WIDTH, KEYS_LIST_HEIGHT);
313       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(inputd->keys_listbox),
314                                       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
315       gtk_notebook_append_page (GTK_NOTEBOOK(notebook), 
316                                 inputd->keys_listbox, label);
317
318       gtk_widget_show (inputd->keys_listbox);
319
320       inputd->keys_list = 0;
321
322       /* ...set_device expects to get input dialog from widget user data */
323       gtk_object_set_user_data (GTK_OBJECT (inputd), inputd);
324       gtk_input_dialog_set_device (GTK_WIDGET(inputd), device_info->data);
325
326     }
327
328   /* We create the save button in any case, so that clients can 
329      connect to it, without paying attention to whether it exits */
330   inputd->save_button = gtk_button_new_with_label (_("Save"));
331   GTK_WIDGET_SET_FLAGS (inputd->save_button, GTK_CAN_DEFAULT);
332   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(inputd)->action_area),
333                       inputd->save_button, TRUE, TRUE, 0);
334   gtk_widget_show (inputd->save_button);
335
336   if (g_list_length(device_info) <= 1) /* only core device */
337     gtk_widget_set_sensitive(inputd->save_button, FALSE);
338
339   inputd->close_button = gtk_button_new_with_label (_("Close"));
340   GTK_WIDGET_SET_FLAGS (inputd->close_button, GTK_CAN_DEFAULT);
341   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(inputd)->action_area),
342                       inputd->close_button, TRUE, TRUE, 0);
343
344   gtk_widget_show (inputd->close_button);
345   gtk_widget_grab_default (inputd->close_button);
346
347   gtk_widget_show (vbox);
348
349   gtk_widget_pop_composite_child ();
350 }
351
352
353 GtkWidget*
354 gtk_input_dialog_new (void)
355 {
356   GtkInputDialog *inputd;
357
358   inputd = gtk_type_new (GTK_TYPE_INPUT_DIALOG);
359
360   return GTK_WIDGET (inputd);
361 }
362
363 static void
364 gtk_input_dialog_set_device(GtkWidget *widget, gpointer data)
365 {
366   GdkDevice *device = data;
367
368   GtkInputDialog *inputd = GTK_INPUT_DIALOG(
369                 gtk_object_get_user_data(GTK_OBJECT(widget)));
370
371   inputd->current_device = device;
372
373   gtk_input_dialog_fill_axes(inputd, device);
374   gtk_input_dialog_fill_keys(inputd, device);
375
376   gtk_option_menu_set_history(GTK_OPTION_MENU(inputd->mode_optionmenu),
377                               device->mode);
378 }
379
380 static void
381 gtk_input_dialog_set_mapping_mode (GtkWidget *w,
382                                    gpointer   data)
383 {
384   GtkInputDialog *inputd = GTK_INPUT_DIALOG(
385                 gtk_object_get_user_data(GTK_OBJECT(w)));
386   GdkDevice *info = inputd->current_device;
387   GdkInputMode old_mode = info->mode;
388   GdkInputMode mode = GPOINTER_TO_INT (data);
389
390   if (mode != old_mode)
391     {
392       if (gdk_device_set_mode (inputd->current_device, mode))
393         {
394           if (mode == GDK_MODE_DISABLED)
395             gtk_signal_emit (GTK_OBJECT (inputd),
396                              input_dialog_signals[DISABLE_DEVICE],
397                              info);
398           else
399             gtk_signal_emit (GTK_OBJECT (inputd),
400                              input_dialog_signals[ENABLE_DEVICE],
401                              info);
402         }
403       else
404         gtk_option_menu_set_history (GTK_OPTION_MENU (inputd->mode_optionmenu),
405                                      old_mode);
406
407       /* FIXME: error dialog ? */
408     }
409 }
410
411 static void
412 gtk_input_dialog_set_axis(GtkWidget *widget, gpointer data)
413 {
414   GdkAxisUse use = GPOINTER_TO_INT(data) & 0xFFFF;
415   GdkAxisUse old_use;
416   GdkAxisUse *new_axes;
417   GtkInputDialog *inputd = GTK_INPUT_DIALOG (gtk_object_get_user_data (GTK_OBJECT (widget)));
418   GdkDevice *info = inputd->current_device;
419
420   gint axis = (GPOINTER_TO_INT(data) >> 16) - 1;
421   gint old_axis;
422   int i;
423
424   new_axes = g_new (GdkAxisUse, info->num_axes);
425   old_axis = -1;
426   for (i=0;i<info->num_axes;i++)
427     {
428       new_axes[i] = info->axes[i].use;
429       if (info->axes[i].use == use)
430         old_axis = i;
431     }
432
433   if (axis != -1)
434     old_use = info->axes[axis].use;
435   else
436     old_use = GDK_AXIS_IGNORE;
437
438   if (axis == old_axis)
439     return;
440
441   /* we must always have an x and a y axis */
442   if ((axis == -1 && (use == GDK_AXIS_X || use == GDK_AXIS_Y)) ||
443       (old_axis == -1 && (old_use == GDK_AXIS_X || old_use == GDK_AXIS_Y)))
444     {
445       gtk_option_menu_set_history (
446                 GTK_OPTION_MENU (inputd->axis_items[use]),
447                 old_axis + 1);
448     }
449   else
450     {
451       if (axis != -1)
452         gdk_device_set_axis_use (info, axis, use);
453
454       if (old_axis != -1)
455         gdk_device_set_axis_use (info, old_axis, old_use);
456
457       if (old_use != GDK_AXIS_IGNORE)
458         {
459           gtk_option_menu_set_history (
460                 GTK_OPTION_MENU (inputd->axis_items[old_use]),
461                 old_axis + 1);
462         }
463     }
464
465   g_free (new_axes);
466 }
467
468 static void
469 gtk_input_dialog_fill_axes(GtkInputDialog *inputd, GdkDevice *info)
470 {
471   static const char *axis_use_strings[GDK_AXIS_LAST] =
472   {
473     "",
474     N_("X"),
475     N_("Y"),
476     N_("Pressure"),
477     N_("X Tilt"),
478     N_("Y Tilt"),
479     N_("Wheel")
480   };
481
482   int i,j;
483   GtkWidget *menu;
484   GtkWidget *option_menu;
485   GtkWidget *label;
486
487   /* remove all the old items */
488   if (inputd->axis_list)
489     {
490       gtk_widget_hide (inputd->axis_list);      /* suppress resizes (or get warnings) */
491       gtk_widget_destroy (inputd->axis_list);
492     }
493   inputd->axis_list = gtk_table_new (GDK_AXIS_LAST, 2, 0);
494   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (inputd->axis_listbox), 
495                                          inputd->axis_list);
496   gtk_widget_show (inputd->axis_list);
497
498   gtk_widget_realize (inputd->axis_list);
499   gdk_window_set_background (inputd->axis_list->window,
500                              &inputd->axis_list->style->base[GTK_STATE_NORMAL]);
501
502   for (i=GDK_AXIS_X;i<GDK_AXIS_LAST;i++)
503     {
504       /* create the label */
505
506       label = gtk_label_new (_(axis_use_strings[i]));
507       gtk_table_attach (GTK_TABLE (inputd->axis_list), label, 0, 1, i, i+1, 
508                         0, 0, 2, 2);
509
510       /* and the use option menu */
511       menu = gtk_menu_new();
512
513       for (j = -1; j < info->num_axes; j++)
514         {
515           char buffer[16];
516           GtkWidget *menu_item;
517
518           if (j == -1)
519             menu_item = gtk_menu_item_new_with_label (_("none"));
520           else
521             {
522               sprintf (buffer,"%d",j+1);
523               menu_item = gtk_menu_item_new_with_label (buffer);
524             }
525           gtk_object_set_user_data (GTK_OBJECT (menu_item), inputd);
526           gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
527                               (GtkSignalFunc) gtk_input_dialog_set_axis,
528                               GINT_TO_POINTER (0x10000 * (j + 1) + i));
529           gtk_widget_show (menu_item);
530           gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
531         }
532
533       inputd->axis_items[i] = option_menu = gtk_option_menu_new ();
534       gtk_table_attach (GTK_TABLE (inputd->axis_list), option_menu, 
535                         1, 2, i, i+1, 0, 0, 2, 2);
536
537       gtk_widget_show (option_menu);
538       gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
539       for (j = 0; j < info->num_axes; j++)
540         if (info->axes[j].use == (GdkAxisUse) i)
541           {
542             gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), j+1);
543             break;
544           }
545
546       gtk_widget_show (label);
547     }
548 }
549
550 static void 
551 gtk_input_dialog_clear_key (GtkWidget *widget, GtkInputKeyInfo *key)
552 {
553   gtk_entry_set_text (GTK_ENTRY(key->entry), _("(disabled)"));
554   gdk_device_set_key (key->inputd->current_device, key->index, 0, 0);
555 }
556
557 static void 
558 gtk_input_dialog_set_key (GtkInputKeyInfo *key,
559                           guint keyval, GdkModifierType modifiers)
560 {
561   GString *str;
562   gchar chars[2];
563
564   if (keyval)
565     {
566       str = g_string_new("");
567       
568       if (modifiers & GDK_SHIFT_MASK)
569         g_string_append (str, "Shift+");
570       if (modifiers & GDK_CONTROL_MASK)
571         g_string_append (str, "Ctrl+");
572       if (modifiers & GDK_MOD1_MASK)
573         g_string_append (str, "Alt+");
574       
575       if ((keyval >= 0x20) && (keyval <= 0xFF))
576         {
577           chars[0] = keyval;
578           chars[1] = 0;
579           g_string_append (str, chars);
580         }
581       else
582         g_string_append (str, _("(unknown)"));
583       gtk_entry_set_text (GTK_ENTRY(key->entry), str->str);
584
585       g_string_free (str, TRUE);
586     }
587   else
588     {
589       gtk_entry_set_text (GTK_ENTRY(key->entry), _("(disabled)"));
590     }
591 }
592
593 static gint
594 gtk_input_dialog_key_press (GtkWidget *widget, 
595                             GdkEventKey *event,
596                             GtkInputKeyInfo *key)
597 {
598   gtk_input_dialog_set_key (key, event->keyval, event->state & 0xFF);
599   gdk_device_set_key (key->inputd->current_device, key->index, 
600                       event->keyval, event->state & 0xFF);
601
602   gtk_signal_emit_stop_by_name (GTK_OBJECT(widget), "key_press_event");
603   
604   return TRUE;
605 }
606
607 static void 
608 gtk_input_dialog_destroy_key (GtkWidget *widget, GtkInputKeyInfo *key)
609 {
610   g_free (key);
611 }
612
613 static void
614 gtk_input_dialog_fill_keys(GtkInputDialog *inputd, GdkDevice *info)
615 {
616   int i;
617   GtkWidget *label;
618   GtkWidget *button;
619
620   char buffer[32];
621   
622   /* remove all the old items */
623   if (inputd->keys_list)
624     {
625       gtk_widget_hide (inputd->keys_list);      /* suppress resizes (or get warnings) */
626       gtk_widget_destroy (inputd->keys_list);
627     }
628
629   inputd->keys_list = gtk_table_new (info->num_keys, 3, FALSE);
630   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (inputd->keys_listbox), 
631                                          inputd->keys_list);
632   gtk_widget_show (inputd->keys_list);
633
634   gtk_widget_realize (inputd->keys_list);
635   gdk_window_set_background (inputd->keys_list->window,
636                              &inputd->keys_list->style->base[GTK_STATE_NORMAL]);
637
638   for (i=0;i<info->num_keys;i++)
639     {
640       GtkInputKeyInfo *key = g_new (GtkInputKeyInfo, 1);
641       key->index = i;
642       key->inputd = inputd;
643
644       /* create the label */
645
646       sprintf(buffer, "%d", i+1);
647       label = gtk_label_new(buffer);
648       gtk_table_attach (GTK_TABLE (inputd->keys_list), label, 0, 1, i, i+1, 
649                         0, 0, 2, 2);
650       gtk_widget_show (label);
651
652       /* the entry */
653
654       key->entry = gtk_entry_new ();
655       gtk_table_attach (GTK_TABLE (inputd->keys_list), key->entry, 1, 2, i, i+1, 
656                         GTK_EXPAND | GTK_FILL , 0, 2, 2);
657       gtk_widget_show (key->entry);
658
659       gtk_signal_connect (GTK_OBJECT(key->entry), "key_press_event",
660                           GTK_SIGNAL_FUNC (gtk_input_dialog_key_press), key);
661       gtk_signal_connect (GTK_OBJECT(key->entry), "destroy",
662                           GTK_SIGNAL_FUNC (gtk_input_dialog_destroy_key), 
663                           key);
664       
665       /* and clear button */
666
667       button = gtk_button_new_with_label (_("clear"));
668       gtk_table_attach (GTK_TABLE (inputd->keys_list), button, 2, 3, i, i+1, 
669                         0, 0, 2, 2);
670       gtk_widget_show (button);
671
672       gtk_signal_connect (GTK_OBJECT(button), "clicked",
673                           GTK_SIGNAL_FUNC (gtk_input_dialog_clear_key), key);
674
675       gtk_input_dialog_set_key (key, info->keys[i].keyval,
676                                 info->keys[i].modifiers);
677     }
678 }