Newer
Older
scim-wnn / scim-wnn / src / scim_wnn_imengine_setup.cpp
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 *  Copyright (C) 2004 TAM (Teppei Tamra)
 *  Copyright (C) 2004 Hiroyuki Ikezoe
 *  Copyright (C) 2004 Takuro Ashie
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
 * Based on scim-hangul.
 * Copyright (c) 2004 James Su <suzhe@turbolinux.com.cn>
 */

#define Uses_SCIM_CONFIG_BASE

#include <gtk/gtk.h>

#ifdef HAVE_CONFIG_H
  #include <config.h>
#endif

#include <scim.h>
#include <gtk/scimkeyselection.h>
#include "scim_wnn_def.h"

#ifdef HAVE_GETTEXT
  #include <libintl.h>
  #define _(String) dgettext(GETTEXT_PACKAGE,String)
  #define N_(String) (String)
#else
  #define _(String) (String)
  #define N_(String) (String)
  #define bindtextdomain(Package,Directory)
  #define textdomain(domain)
  #define bind_textdomain_codeset(domain,codeset)
#endif

using namespace scim;

#define scim_module_init wnn_imengine_setup_LTX_scim_module_init
#define scim_module_exit wnn_imengine_setup_LTX_scim_module_exit

#define scim_setup_module_create_ui       wnn_imengine_setup_LTX_scim_setup_module_create_ui
#define scim_setup_module_get_category    wnn_imengine_setup_LTX_scim_setup_module_get_category
#define scim_setup_module_get_name        wnn_imengine_setup_LTX_scim_setup_module_get_name
#define scim_setup_module_get_description wnn_imengine_setup_LTX_scim_setup_module_get_description
#define scim_setup_module_load_config     wnn_imengine_setup_LTX_scim_setup_module_load_config
#define scim_setup_module_save_config     wnn_imengine_setup_LTX_scim_setup_module_save_config
#define scim_setup_module_query_changed   wnn_imengine_setup_LTX_scim_setup_module_query_changed



static GtkWidget * create_setup_window ();
static void        load_config (const ConfigPointer &config);
static void        save_config (const ConfigPointer &config);
static bool        query_changed ();

// Module Interface.
/*
    ****今回のリリースでは設定モジュールは搭載させません****

    !!!リリース後コメントアウトを外してデバグ!!!

extern "C" {
    void scim_module_init (void)
    {
        bindtextdomain (GETTEXT_PACKAGE, SCIM_WNN_LOCALEDIR);
        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
    }

    void scim_module_exit (void)
    {
    }

    GtkWidget * scim_setup_module_create_ui (void)
    {
        return create_setup_window ();
    }

    String scim_setup_module_get_category (void)
    {
        return String ("IMEngine");
    }

    String scim_setup_module_get_name (void)
    {
        return String (_("Wnn"));
    }

    String scim_setup_module_get_description (void)
    {
        return String (_("An Wnn IMEngine Module."));
    }

    void scim_setup_module_load_config (const ConfigPointer &config)
    {
        load_config (config);
    }

    void scim_setup_module_save_config (const ConfigPointer &config)
    {
        save_config (config);
    }

    bool scim_setup_module_query_changed ()
    {
        return query_changed ();
    }
} // extern "C"

*/

// Internal data structure
struct KeyboardConfigData
{
    const char *key;
    String      data;
    const char *label;
    const char *title;
    const char *tooltip;
    GtkWidget  *entry;
    GtkWidget  *button;
};

// Internal data declaration.
static bool __config_use_kana = false;

static bool __have_changed    = true;

static GtkWidget    * __widget_use_kana = 0;
static GtkTooltips  * __widget_tooltips = 0;

static KeyboardConfigData __config_keyboards [] =
{
    /* edit */
    {
        SCIM_CONFIG_WNN_KEY_COMMIT,
        SCIM_DEFAULT_WNN_KEY_COMMIT,
        N_("Commit keys:"),
        N_("Select commit keys"),
        N_("The key events to commit the preedit string. "),
        NULL,
        NULL,
    },
    {
        SCIM_CONFIG_WNN_KEY_CONVERSION_START,
        SCIM_DEFAULT_WNN_KEY_CONVERSION_START,
        N_("Convert keys:"),
        N_("Select convert keys"),
        N_("The key events to convert the preedit string to kanji. "),
        NULL,
        NULL,
    },
    {
        SCIM_CONFIG_WNN_KEY_CANCEL,
        SCIM_DEFAULT_WNN_KEY_CANCEL,
        N_("Cancel keys:"),
        N_("Select cancel keys"),
        N_("The key events to cancel preediting or converting. "),
        NULL,
        NULL,
    },
    {
        SCIM_CONFIG_WNN_KEY_BACKSPACE,
        SCIM_DEFAULT_WNN_KEY_BACKSPACE,
        N_("Backspace keys:"),
        N_("Select backspace keys"),
        N_("The key events to delete a character before caret. "),
        NULL,
        NULL,
    },
    {
        SCIM_CONFIG_WNN_KEY_DELETE,
        SCIM_DEFAULT_WNN_KEY_DELETE,
        N_("Delete keys:"),
        N_("Select delete keys"),
        N_("The key events to delete a character after caret. "),
        NULL,
        NULL,
    },

    /* caret */
    {
        SCIM_CONFIG_WNN_KEY_FORWARD,
        SCIM_DEFAULT_WNN_KEY_FORWARD,
        N_("Move forward keys:"),
        N_("Select move caret forward keys"),
        N_("The key events to move the caret to forward. "),
        NULL,
        NULL,
    },
    {
        SCIM_CONFIG_WNN_KEY_BACKWARD,
        SCIM_DEFAULT_WNN_KEY_BACKWARD,
        N_("Move backward keys:"),
        N_("Select move caret backward keys"),
        N_("The key events to move the caret to backward. "),
        NULL,
        NULL,
    },

    /* segment */
    {
        SCIM_CONFIG_WNN_KEY_CONVERSION_FORWARD,
        SCIM_DEFAULT_WNN_KEY_CONVERSION_FORWARD,
        N_("Next segment keys:"),
        N_("Select next segment keys"),
        N_("The key events to select next segment. "),
        NULL,
        NULL,
    },
    {
        SCIM_CONFIG_WNN_KEY_CONVERSION_BACKWARD,
        SCIM_DEFAULT_WNN_KEY_CONVERSION_BACKWARD,
        N_("Previous segment keys:"),
        N_("Select previous segment keys"),
        N_("The key events to select previous segment. "),
        NULL,
        NULL,
    },
    {
        SCIM_CONFIG_WNN_KEY_CONVERSION_SHRINK,
        SCIM_DEFAULT_WNN_KEY_CONVERSION_SHRINK,
        N_("Shrink segment keys:"),
        N_("Select shrink segment keys"),
        N_("The key events to shrink the selected segment. "),
        NULL,
        NULL,
    },
    {
        SCIM_CONFIG_WNN_KEY_CONVERSION_EXPAND,
        SCIM_DEFAULT_WNN_KEY_CONVERSION_EXPAND,
        N_("Expand segment keys:"),
        N_("Select expand segment keys"),
        N_("The key events to expand the selected segment. "),
        NULL,
        NULL,
    },

    /* candidates */
    {
        SCIM_CONFIG_WNN_KEY_CONVERSION_NEXT,
        SCIM_DEFAULT_WNN_KEY_CONVERSION_NEXT,
        N_("Next keys:"),
        N_("Select next candidate keys"),
        N_("The key events to select next candidate. "),
        NULL,
        NULL,
    },
    {
        SCIM_CONFIG_WNN_KEY_CONVERSION_PREV,
        SCIM_DEFAULT_WNN_KEY_CONVERSION_PREV,
        N_("Previous keys:"),
        N_("Select previous candidate keys"),
        N_("The key events to select previous candidate. "),
        NULL,
        NULL,
    },
    {
        SCIM_CONFIG_WNN_KEY_LOOKUPPAGEUP,
        SCIM_DEFAULT_WNN_KEY_LOOKUPPAGEUP,
        N_("Page up keys:"),
        N_("Select page up candidates keys"),
        N_("The key events to select page up candidates. "),
        NULL,
        NULL,
    },
    {
        SCIM_CONFIG_WNN_KEY_LOOKUPPAGEDOWN,
        SCIM_DEFAULT_WNN_KEY_LOOKUPPAGEDOWN,
        N_("Page down keys:"),
        N_("Select page down candidates keys"),
        N_("The key events to select page down candidates. "),
        NULL,
        NULL,
    },

    /* convert */
    /* mode */
    {
        NULL,
        "",
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
    },
};
/* FIXME! */
#if 1
static unsigned int key_nums[] =
{
    3,4,8,
};
static char *key_conf_page_labels[] =
{
    "Common keys","preedit keys","convert keys",
};
static unsigned int key_conf_pages = sizeof (key_nums) / sizeof (unsigned int);
#endif

static void on_default_editable_changed      (GtkEditable *editable,
                                              gpointer     user_data);
static void on_default_toggle_button_toggled (GtkToggleButton *togglebutton,
                                              gpointer         user_data);
static void on_default_key_selection_clicked (GtkButton *button,
                                              gpointer   user_data);
void setup_widget_value ();


static GtkWidget *
create_options_page ()
{
    GtkWidget *vbox;

    vbox = gtk_vbox_new (FALSE, 0);
    gtk_widget_show (vbox);

    //__widget_use_kana = gtk_check_button_new_with_mnemonic (_("Use _Kana Table"));
    //gtk_widget_show (__widget_use_kana);
    //gtk_box_pack_start (GTK_BOX (vbox), __widget_use_kana, FALSE, FALSE, 4);
    //gtk_container_set_border_width (GTK_CONTAINER (__widget_use_kana), 4);

    // Connect all signals.
    //g_signal_connect ((gpointer) __widget_use_kana, "toggled",
    //                  G_CALLBACK (on_default_toggle_button_toggled),
    //                  &__config_use_kana);

    return vbox;
}

static GtkWidget *
create_keyboard_page (unsigned int page)
{
    GtkWidget *table;
    GtkWidget *label;
    unsigned int i, start = 0, end = 0;

    if (page >= key_conf_pages)
        return NULL;

    for (i = 0; i < page; i++)
        start += key_nums[i];
    end = start + key_nums[page];

    table = gtk_table_new (3, 3, FALSE);
    gtk_widget_show (table);

    // Create keyboard setting.
    for (i = start; i < end /*__config_keyboards [i].key*/; ++ i) {
        label = gtk_label_new (NULL);
        gtk_label_set_text_with_mnemonic (GTK_LABEL (label), _(__config_keyboards[i].label));
        gtk_widget_show (label);
        gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
        gtk_misc_set_padding (GTK_MISC (label), 4, 0);
        gtk_table_attach (GTK_TABLE (table), label, 0, 1, i, i+1,
                          (GtkAttachOptions) (GTK_FILL),
                          (GtkAttachOptions) (GTK_FILL), 4, 4);

        __config_keyboards [i].entry = gtk_entry_new ();
        gtk_widget_show (__config_keyboards [i].entry);
        gtk_table_attach (GTK_TABLE (table), __config_keyboards [i].entry, 1, 2, i, i+1,
                          (GtkAttachOptions) (GTK_FILL|GTK_EXPAND),
                          (GtkAttachOptions) (GTK_FILL), 4, 4);
        gtk_entry_set_editable (GTK_ENTRY (__config_keyboards[i].entry), FALSE);

        __config_keyboards[i].button = gtk_button_new_with_label ("...");
        gtk_widget_show (__config_keyboards[i].button);
        gtk_table_attach (GTK_TABLE (table), __config_keyboards[i].button, 2, 3, i, i+1,
                          (GtkAttachOptions) (GTK_FILL),
                          (GtkAttachOptions) (GTK_FILL), 4, 4);
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), __config_keyboards[i].button);
    }

    for (i = start; i < end /*__config_keyboards [i].key*/; ++ i) {
        g_signal_connect ((gpointer) __config_keyboards [i].button, "clicked",
                          G_CALLBACK (on_default_key_selection_clicked),
                          &(__config_keyboards [i]));
        g_signal_connect ((gpointer) __config_keyboards [i].entry, "changed",
                          G_CALLBACK (on_default_editable_changed),
                          &(__config_keyboards [i].data));
    }

    for (i = start; i < end /*__config_keyboards [i].key*/; ++ i) {
        gtk_tooltips_set_tip (__widget_tooltips, __config_keyboards [i].entry,
                              _(__config_keyboards [i].tooltip), NULL);
    }

    return table;
}

static GtkWidget *
create_setup_window ()
{
    static GtkWidget *window = NULL;

    if (!window) {
        GtkWidget *notebook = gtk_notebook_new();
        gtk_widget_show (notebook);
        window = notebook;
        gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);

        // Create the first page.
        GtkWidget *page = create_options_page ();
        GtkWidget *label = gtk_label_new (_("Options"));
        gtk_widget_show (label);
        gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, label);

        //setup_widget_value ();

        // Create the second page.
        for (unsigned int i = 0; i < key_conf_pages; i++) {
            page = create_keyboard_page (i);
            label = gtk_label_new (_(key_conf_page_labels[i]));
            gtk_widget_show (label);
            gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, label);
        }

        setup_widget_value ();
    }

    return window;
}

void
setup_widget_value ()
{
//    if (__widget_use_kana) {
//        gtk_toggle_button_set_active (
//            GTK_TOGGLE_BUTTON (__widget_use_kana),
//            __config_use_kana);
//    }

    for (int i = 0; __config_keyboards [i].key; ++ i) {
        if (__config_keyboards [i].entry) {
            gtk_entry_set_text (
                GTK_ENTRY (__config_keyboards [i].entry),
                __config_keyboards [i].data.c_str ());
        }
    }
}

void
load_config (const ConfigPointer &config)
{
    if (!config.null ()) {
    //    __config_use_kana =
    //        config->read (String (SCIM_CONFIG_IMENGINE_ANTHY_USE_KANA),
    //                      __config_use_kana);

        for (int i = 0; __config_keyboards [i].key; ++ i) {
            __config_keyboards [i].data =
                config->read (String (__config_keyboards [i].key),
                              __config_keyboards [i].data);
        }

        setup_widget_value ();

        __have_changed = false;
    }
}

void
save_config (const ConfigPointer &config)
{
    if (!config.null ()) {
    //    config->write (String (SCIM_CONFIG_IMENGINE_ANTHY_USE_KANA),
    //                    __config_use_kana);

        for (int i = 0; __config_keyboards [i].key; ++ i) {
            config->write (String (__config_keyboards [i].key),
                          __config_keyboards [i].data);
        }

        __have_changed = false;
    }
}

bool
query_changed ()
{
    return __have_changed;
}


static void
on_default_toggle_button_toggled (GtkToggleButton *togglebutton,
                                  gpointer         user_data)
{
    bool *toggle = static_cast<bool*> (user_data);

    if (toggle) {
        *toggle = gtk_toggle_button_get_active (togglebutton);
        __have_changed = true;
    }
}

static void
on_default_editable_changed (GtkEditable *editable,
                             gpointer     user_data)
{
    String *str = static_cast <String *> (user_data);

    if (str) {
        *str = String (gtk_entry_get_text (GTK_ENTRY (editable)));
        __have_changed = true;
    }
}

static void
on_default_key_selection_clicked (GtkButton *button,
                                  gpointer   user_data)
{
    KeyboardConfigData *data = static_cast <KeyboardConfigData *> (user_data);

    if (data) {
        GtkWidget *dialog = scim_key_selection_dialog_new (_(data->title));
        gint result;

        scim_key_selection_dialog_set_keys (
            SCIM_KEY_SELECTION_DIALOG (dialog),
            gtk_entry_get_text (GTK_ENTRY (data->entry)));

        result = gtk_dialog_run (GTK_DIALOG (dialog));

        if (result == GTK_RESPONSE_OK) {
            const gchar *keys = scim_key_selection_dialog_get_keys (
                            SCIM_KEY_SELECTION_DIALOG (dialog));

            if (!keys) keys = "";

            if (strcmp (keys, gtk_entry_get_text (GTK_ENTRY (data->entry))) != 0)
                gtk_entry_set_text (GTK_ENTRY (data->entry), keys);
        }

        gtk_widget_destroy (dialog);
    }
}