1 /** @file scim_aaa_frontend_setup.cpp
2  * implementation of Setup Module for FrontEnd Hotkeys configuration.
3  */
4 
5 /*
6  * Smart Common Input Method
7  *
8  * Copyright (c) 2005 James Su <suzhe@tsinghua.org.cn>
9  *
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this program; if not, write to the
23  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24  * Boston, MA  02111-1307  USA
25  *
26  * $Id: scim_frontend_setup.cpp,v 1.6 2005/06/29 08:19:17 suzhe Exp $
27  *
28  */
29 
30 #define Uses_SCIM_CONFIG_PATH
31 #define Uses_SCIM_CONFIG_BASE
32 #define Uses_SCIM_EVENT
33 
34 #include <iostream>
35 
36 #include <gtk/gtk.h>
37 
38 #include "scim_private.h"
39 #include "scim.h"
40 #include "scimkeyselection.h"
41 
42 using namespace scim;
43 
44 #define scim_module_init aaa_frontend_setup_LTX_scim_module_init
45 #define scim_module_exit aaa_frontend_setup_LTX_scim_module_exit
46 
47 #define scim_setup_module_create_ui       aaa_frontend_setup_LTX_scim_setup_module_create_ui
48 #define scim_setup_module_get_category    aaa_frontend_setup_LTX_scim_setup_module_get_category
49 #define scim_setup_module_get_name        aaa_frontend_setup_LTX_scim_setup_module_get_name
50 #define scim_setup_module_get_description aaa_frontend_setup_LTX_scim_setup_module_get_description
51 #define scim_setup_module_load_config     aaa_frontend_setup_LTX_scim_setup_module_load_config
52 #define scim_setup_module_save_config     aaa_frontend_setup_LTX_scim_setup_module_save_config
53 #define scim_setup_module_query_changed   aaa_frontend_setup_LTX_scim_setup_module_query_changed
54 
55 static GtkWidget * create_setup_window ();
56 static void        load_config (const ConfigPointer &config);
57 static void        save_config (const ConfigPointer &config);
58 static bool        query_changed ();
59 
60 // Module Interface.
61 extern "C" {
scim_module_init(void)62     void scim_module_init (void)
63     {
64     }
65 
scim_module_exit(void)66     void scim_module_exit (void)
67     {
68     }
69 
scim_setup_module_create_ui(void)70     GtkWidget * scim_setup_module_create_ui (void)
71     {
72         return create_setup_window ();
73     }
74 
scim_setup_module_get_category(void)75     String scim_setup_module_get_category (void)
76     {
77         return String ("FrontEnd");
78     }
79 
scim_setup_module_get_name(void)80     String scim_setup_module_get_name (void)
81     {
82         return String (_("Global Setup"));
83     }
84 
scim_setup_module_get_description(void)85     String scim_setup_module_get_description (void)
86     {
87         return String (_("Setup the global options used by All FrontEnd modules, including X11 FrontEnd, GTK IMModule, QT IMModule etc."));
88     }
89 
scim_setup_module_load_config(const ConfigPointer & config)90     void scim_setup_module_load_config (const ConfigPointer &config)
91     {
92         load_config (config);
93     }
94 
scim_setup_module_save_config(const ConfigPointer & config)95     void scim_setup_module_save_config (const ConfigPointer &config)
96     {
97         save_config (config);
98     }
99 
scim_setup_module_query_changed()100     bool scim_setup_module_query_changed ()
101     {
102         return query_changed ();
103     }
104 } // extern "C"
105 
106 // Internal data structure
107 struct KeyboardConfigData
108 {
109     const char *key;
110     const char *label;
111     const char *title;
112     const char *tooltip;
113     GtkWidget  *entry;
114     GtkWidget  *button;
115     String      data;
116 };
117 
118 // Internal data declaration.
119 
120 static bool           __config_on_the_spot       = true;
121 
122 static bool           __config_shared_input_method = false;
123 
124 static KeyboardLayout __config_keyboard_layout   = SCIM_KEYBOARD_Unknown;
125 
126 static bool           __have_changed             = false;
127 
128 
129 static GtkWidget     * __widget_on_the_spot      = 0;
130 
131 static GtkTooltips   * __widget_tooltips         = 0;
132 
133 static GtkWidget     * __widget_keyboard_layout  = NULL;
134 
135 static GtkWidget     * __widget_shared_input_method = NULL;
136 
137 static KeyboardConfigData __config_keyboards [] =
138 {
139     {
140         // key
141         SCIM_CONFIG_HOTKEYS_FRONTEND_TRIGGER,
142         // label
143         N_("_Trigger:"),
144         // title
145         N_("Select the trigger keys"),
146         // tooltip
147         N_("The key events to turn on/off SCIM input method. "
148            "Click on the button on the right to edit it."),
149         // entry
150         NULL,
151         // button
152         NULL,
153         // data
154         "Control+space"
155     },
156     {
157         // key
158         SCIM_CONFIG_HOTKEYS_FRONTEND_ON,
159         // label
160         N_("Turn _On:"),
161         // title
162         N_("Select the Turn On keys"),
163         // tooltip
164         N_("The key events to turn on SCIM input method. "
165            "Click on the button on the right to edit it."),
166         // entry
167         NULL,
168         // button
169         NULL,
170         // data
171         ""
172     },
173     {
174         // key
175         SCIM_CONFIG_HOTKEYS_FRONTEND_OFF,
176         // label
177         N_("Turn O_ff:"),
178         // title
179         N_("Select the Turn Off keys"),
180         // tooltip
181         N_("The key events to turn off SCIM input method. "
182            "Click on the button on the right to edit it."),
183         // entry
184         NULL,
185         // button
186         NULL,
187         // data
188         ""
189     },
190     {
191         // key
192         SCIM_CONFIG_HOTKEYS_FRONTEND_NEXT_FACTORY,
193         // label
194         N_("_Next input method:"),
195         // title
196         N_("Select the next input method keys"),
197         // tooltip
198         N_("The key events to switch to the next input method. "
199            "Click on the button on the right to edit it."),
200         // entry
201         NULL,
202         // button
203         NULL,
204         // data
205         "Control+Alt+Down,"
206         "Control+Shift_R,"
207         "Control+Shift_L"
208     },
209     {
210         // key
211         SCIM_CONFIG_HOTKEYS_FRONTEND_PREVIOUS_FACTORY,
212         // label
213         N_("_Previous input method:"),
214         // title
215         N_("Select the previous input method keys"),
216         // tooltip
217         N_("The key events to switch to the previous input method. "
218            "Click on the button on the right to edit it."),
219         // entry
220         NULL,
221         // button
222         NULL,
223         // data
224         "Control+Alt+Up,"
225         "Shift+Control_R,"
226         "Shift+Control_L"
227     },
228     {
229         // key
230         SCIM_CONFIG_HOTKEYS_FRONTEND_SHOW_FACTORY_MENU,
231         // label
232         N_("Show input method _menu:"),
233         // title
234         N_("Select the show input method menu keys"),
235         // tooltip
236         N_("The key events to show the input method menu. "
237            "Click on the button on the right to edit it."),
238         // entry
239         NULL,
240         // button
241         NULL,
242         // data
243         "Control+Alt+l,"
244         "Control+Alt+m,"
245         "Control+Alt+s,"
246         "Control+Alt+Right,"
247     },
248     {
249         // key
250         NULL,
251         // label
252         NULL,
253         // title
254         NULL,
255         // tooltip
256         NULL,
257         // entry
258         NULL,
259         // button
260         NULL,
261         // data
262         ""
263     },
264 };
265 
266 // Declaration of internal functions.
267 static void
268 on_default_editable_changed          (GtkEditable     *editable,
269                                       gpointer         user_data);
270 
271 static void
272 on_default_key_selection_clicked     (GtkButton       *button,
273                                       gpointer         user_data);
274 
275 static void
276 on_keyboard_layout_changed           (GtkComboBox     *combobox,
277                                       gpointer         user_data);
278 
279 static void
280 on_default_toggle_button_toggled     (GtkToggleButton *togglebutton,
281                                       gpointer         user_data);
282 
283 static void
284 setup_widget_value ();
285 
286 // Function implementations.
287 static GtkWidget *
create_setup_window()288 create_setup_window ()
289 {
290     static GtkWidget *window = 0;
291 
292     if (!window) {
293         GtkWidget *table;
294         GtkWidget *frame;
295         GtkWidget *hbox;
296         GtkWidget *vbox;
297         GtkWidget *label;
298         int i;
299 
300         __widget_tooltips = gtk_tooltips_new ();
301 
302         // Create the toplevel box.
303         window = gtk_vbox_new (FALSE, 0);
304         gtk_widget_show (window);
305 
306         frame = gtk_frame_new (_("Options"));
307         gtk_widget_show (frame);
308         gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
309         gtk_box_pack_start (GTK_BOX (window), frame, FALSE, FALSE, 0);
310 
311         vbox = gtk_vbox_new (FALSE, 4);
312         gtk_widget_show (vbox);
313         gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
314         gtk_container_add (GTK_CONTAINER (frame), vbox);
315 
316         // Keyboard Layout.
317         hbox = gtk_hbox_new (FALSE, 4);
318         gtk_widget_show (hbox);
319         gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
320 
321         label = gtk_label_new_with_mnemonic (_("_Keyboard Layout:"));
322         gtk_widget_show (label);
323         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
324 
325         __widget_keyboard_layout = gtk_combo_box_new_text ();
326         gtk_widget_show (__widget_keyboard_layout);
327 
328         gtk_label_set_mnemonic_widget (GTK_LABEL (label), __widget_keyboard_layout);
329 
330         for (size_t i = 0; i < SCIM_KEYBOARD_NUM_LAYOUTS; ++i) {
331             gtk_combo_box_append_text (GTK_COMBO_BOX (__widget_keyboard_layout),
332                 scim_keyboard_layout_get_display_name (static_cast<KeyboardLayout> (i)).c_str ());
333         }
334 
335         g_signal_connect (G_OBJECT (__widget_keyboard_layout), "changed",
336                           G_CALLBACK (on_keyboard_layout_changed),
337                           NULL);
338 
339         gtk_box_pack_start (GTK_BOX (hbox), __widget_keyboard_layout, TRUE, TRUE, 0);
340 
341         gtk_tooltips_set_tip (__widget_tooltips, __widget_keyboard_layout,
342                               _("You should choose your currently used keyboard layout here "
343                                 "so that input methods, who care about keyboard layout, could work correctly."), NULL);
344 
345         // On The Spot.
346         __widget_on_the_spot = gtk_check_button_new_with_mnemonic (_("_Embed Preedit String into client window"));
347         gtk_widget_show (__widget_on_the_spot);
348         gtk_box_pack_start (GTK_BOX (vbox), __widget_on_the_spot, FALSE, FALSE, 0);
349 
350         gtk_tooltips_set_tip (__widget_tooltips, __widget_on_the_spot,
351                               _("If this option is checked, "
352                                 "the preedit string will be displayed directly in the client input window, "
353                                 "rather than in a independent float window."), NULL);
354 
355         g_signal_connect ((gpointer) __widget_on_the_spot, "toggled",
356                           G_CALLBACK (on_default_toggle_button_toggled),
357                           &__config_on_the_spot);
358 
359         // Shared input method.
360         __widget_shared_input_method = gtk_check_button_new_with_mnemonic (_("_Share the same input method among all applications"));
361         gtk_widget_show (__widget_shared_input_method);
362         gtk_box_pack_start (GTK_BOX (vbox), __widget_shared_input_method, FALSE, FALSE, 0);
363 
364         gtk_tooltips_set_tip (__widget_tooltips, __widget_shared_input_method,
365                               _("If this option is checked, "
366                                 "then only one input method could be used by all applications at the same time."
367                                 "Otherwise different input method could be used by each application."), NULL);
368 
369         g_signal_connect ((gpointer) __widget_shared_input_method, "toggled",
370                           G_CALLBACK (on_default_toggle_button_toggled),
371                           &__config_shared_input_method);
372 
373         frame = gtk_frame_new (_("Hotkeys"));
374         gtk_widget_show (frame);
375         gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
376         gtk_box_pack_start (GTK_BOX (window), frame, TRUE, TRUE, 0);
377 
378         table = gtk_table_new (3, 3, FALSE);
379         gtk_widget_show (table);
380         gtk_container_add (GTK_CONTAINER (frame), table);
381         gtk_table_set_row_spacings (GTK_TABLE (table), 0);
382         gtk_table_set_col_spacings (GTK_TABLE (table), 8);
383 
384         for (i = 0; __config_keyboards [i].key; ++ i) {
385             label = gtk_label_new (NULL);
386             gtk_label_set_text_with_mnemonic (GTK_LABEL (label), _(__config_keyboards[i].label));
387             gtk_widget_show (label);
388             gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
389             gtk_misc_set_padding (GTK_MISC (label), 4, 0);
390             gtk_table_attach (GTK_TABLE (table), label, 0, 1, i, i+1,
391                               (GtkAttachOptions) (GTK_FILL),
392                               (GtkAttachOptions) (GTK_FILL), 4, 2);
393 
394             __config_keyboards [i].entry = gtk_entry_new ();
395             gtk_widget_show (__config_keyboards [i].entry);
396             gtk_table_attach (GTK_TABLE (table), __config_keyboards [i].entry, 1, 2, i, i+1,
397                               (GtkAttachOptions) (GTK_FILL|GTK_EXPAND),
398                               (GtkAttachOptions) (GTK_FILL), 4, 2);
399             gtk_entry_set_editable (GTK_ENTRY (__config_keyboards[i].entry), FALSE);
400 
401             __config_keyboards[i].button = gtk_button_new_with_label ("...");
402             gtk_widget_show (__config_keyboards[i].button);
403             gtk_table_attach (GTK_TABLE (table), __config_keyboards[i].button, 2, 3, i, i+1,
404                               (GtkAttachOptions) (GTK_FILL),
405                               (GtkAttachOptions) (GTK_FILL), 4, 2);
406             gtk_label_set_mnemonic_widget (GTK_LABEL (label), __config_keyboards[i].button);
407         }
408 
409         for (i = 0; __config_keyboards [i].key; ++ i) {
410             g_signal_connect ((gpointer) __config_keyboards [i].button, "clicked",
411                               G_CALLBACK (on_default_key_selection_clicked),
412                               &(__config_keyboards [i]));
413             g_signal_connect ((gpointer) __config_keyboards [i].entry, "changed",
414                               G_CALLBACK (on_default_editable_changed),
415                               &(__config_keyboards [i].data));
416         }
417 
418         for (i = 0; __config_keyboards [i].key; ++ i) {
419             gtk_tooltips_set_tip (__widget_tooltips, __config_keyboards [i].entry,
420                                   _(__config_keyboards [i].tooltip), NULL);
421         }
422 
423         setup_widget_value ();
424     }
425 
426     return window;
427 }
428 
429 static void
setup_widget_value()430 setup_widget_value ()
431 {
432     for (int i = 0; __config_keyboards [i].key; ++ i) {
433         if (__config_keyboards [i].entry) {
434             gtk_entry_set_text (
435                 GTK_ENTRY (__config_keyboards [i].entry),
436                 __config_keyboards [i].data.c_str ());
437         }
438     }
439 
440     if (__widget_on_the_spot) {
441         gtk_toggle_button_set_active (
442             GTK_TOGGLE_BUTTON (__widget_on_the_spot),
443             __config_on_the_spot);
444     }
445 
446     if (__widget_shared_input_method) {
447         gtk_toggle_button_set_active (
448             GTK_TOGGLE_BUTTON (__widget_shared_input_method),
449             __config_shared_input_method);
450     }
451 
452     gtk_combo_box_set_active (GTK_COMBO_BOX (__widget_keyboard_layout), (gint) __config_keyboard_layout);
453 }
454 
455 static void
load_config(const ConfigPointer & config)456 load_config (const ConfigPointer &config)
457 {
458     if (!config.null ()) {
459         for (int i = 0; __config_keyboards [i].key; ++ i) {
460             __config_keyboards [i].data =
461                 config->read (String (__config_keyboards [i].key),
462                               __config_keyboards [i].data);
463         }
464 
465         __config_on_the_spot =
466             config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT),
467                           __config_on_the_spot);
468 
469         __config_shared_input_method =
470             config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD),
471                           __config_shared_input_method);
472 
473         __config_keyboard_layout = scim_get_default_keyboard_layout ();
474 
475         setup_widget_value ();
476 
477         __have_changed = false;
478     }
479 }
480 
481 static void
save_config(const ConfigPointer & config)482 save_config (const ConfigPointer &config)
483 {
484     if (!config.null ()) {
485         for (int i = 0; __config_keyboards [i].key; ++ i) {
486             config->write (String (__config_keyboards [i].key),
487                           __config_keyboards [i].data);
488         }
489 
490         gint act = gtk_combo_box_get_active (GTK_COMBO_BOX (__widget_keyboard_layout));
491 
492         if (act >= 0 && act < SCIM_KEYBOARD_NUM_LAYOUTS)
493             __config_keyboard_layout = static_cast<KeyboardLayout> (act);
494         else
495             __config_keyboard_layout = SCIM_KEYBOARD_Unknown;
496 
497         if (__config_keyboard_layout != scim_get_default_keyboard_layout ())
498             scim_set_default_keyboard_layout (__config_keyboard_layout);
499 
500         config->write (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT),
501                        __config_on_the_spot);
502 
503         config->write (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD),
504                        __config_shared_input_method);
505 
506         __have_changed = false;
507     }
508 }
509 
510 static bool
query_changed()511 query_changed ()
512 {
513     return __have_changed;
514 }
515 
516 static void
on_default_editable_changed(GtkEditable * editable,gpointer user_data)517 on_default_editable_changed (GtkEditable *editable,
518                              gpointer     user_data)
519 {
520     String *str = static_cast <String *> (user_data);
521 
522     if (str) {
523         *str = String (gtk_entry_get_text (GTK_ENTRY (editable)));
524         __have_changed = true;
525     }
526 }
527 
528 static void
on_default_key_selection_clicked(GtkButton * button,gpointer user_data)529 on_default_key_selection_clicked (GtkButton *button,
530                                   gpointer   user_data)
531 {
532     KeyboardConfigData *data = static_cast <KeyboardConfigData *> (user_data);
533 
534     if (data) {
535         GtkWidget *dialog = scim_key_selection_dialog_new (_(data->title));
536         gint result;
537 
538         scim_key_selection_dialog_set_keys (
539             SCIM_KEY_SELECTION_DIALOG (dialog),
540             data->data.c_str ());
541 
542         result = gtk_dialog_run (GTK_DIALOG (dialog));
543 
544         if (result == GTK_RESPONSE_OK) {
545             const gchar *keys = scim_key_selection_dialog_get_keys (
546                             SCIM_KEY_SELECTION_DIALOG (dialog));
547 
548             if (!keys) keys = "";
549 
550             if (String (keys) != data->data)
551                 gtk_entry_set_text (GTK_ENTRY (data->entry), keys);
552         }
553 
554         gtk_widget_destroy (dialog);
555     }
556 }
557 
558 static void
on_default_toggle_button_toggled(GtkToggleButton * togglebutton,gpointer user_data)559 on_default_toggle_button_toggled (GtkToggleButton *togglebutton,
560                                   gpointer         user_data)
561 {
562     bool *toggle = static_cast<bool*> (user_data);
563 
564     if (toggle) {
565         *toggle = gtk_toggle_button_get_active (togglebutton);
566         __have_changed = true;
567     }
568 }
569 
570 static void
on_keyboard_layout_changed(GtkComboBox * combobox,gpointer user_data)571 on_keyboard_layout_changed (GtkComboBox *combobox,
572                             gpointer     user_data)
573 {
574     __have_changed = true;
575 }
576 
577 
578 /*
579 vi:ts=4:nowrap:expandtab
580 */
581 
582