Revision: 6442
Author: deton.kih
Date: Sun Jun 13 00:30:03 2010
Log: * Add new table style candidate window for GTK+ immodule [uim-ja 234]
* gtk/uim-cand-win-tbl-gtk.c
  - New file. Add UIMCandWinTblGtk which inherits from UIMCandWinGtk
* gtk/uim-cand-win-tbl-gtk.h
  - New file
* gtk/gtk-im-uim.c
  - (im_uim_create_cand_win_gtk): New function
* gtk/uim-cand-win-gtk.h
  - (_UIMCandWinGtkClass): Add member functions
    to override in UIMCandWinTblGtkClass
* gtk/uim-cand-win-gtk.c
  - (set_candidates, set_page_candidates, set_index, set_page):
    Change to virtual member functions to override in UIMCandWinTblGtk
  - (uim_cand_win_gtk_update_label): Rename from update_label
    to use in uim-cand-win-tbl-gtk.c
* gtk/Makefile.am
  - (IM_UIM_SOURCES): Add uim-cand-win-tbl-gtk.c uim-cand-win-tbl-gtk.h

http://code.google.com/p/uim/source/detail?r=6442

Added:
 /trunk/gtk/uim-cand-win-tbl-gtk.c
 /trunk/gtk/uim-cand-win-tbl-gtk.h
Modified:
 /trunk/gtk/Makefile.am
 /trunk/gtk/gtk-im-uim.c
 /trunk/gtk/uim-cand-win-gtk.c
 /trunk/gtk/uim-cand-win-gtk.h

=======================================
--- /dev/null
+++ /trunk/gtk/uim-cand-win-tbl-gtk.c   Sun Jun 13 00:30:03 2010
@@ -0,0 +1,639 @@
+/*
+
+  copyright (c) 2003-2010 uim Project http://code.google.com/p/uim/
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+  3. Neither the name of authors nor the names of its contributors
+     may be used to endorse or promote products derived from this software
+     without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  SUCH DAMAGE.
+
+*/
+
+#include <config.h>
+
+#include "uim-cand-win-tbl-gtk.h"
+#include <string.h>
+#include <stdlib.h>
+#include <uim/uim.h>
+#include <uim/uim-scm.h>
+
+#define DEFAULT_MIN_WINDOW_WIDTH 80
+
+enum {
+  TERMINATOR = -1,
+  COLUMN_HEADING,
+  COLUMN_CANDIDATE1,
+  COLUMN_CANDIDATE2,
+  COLUMN_CANDIDATE3,
+  COLUMN_CANDIDATE4,
+  COLUMN_CANDIDATE5,
+  COLUMN_CANDIDATE6,
+  COLUMN_CANDIDATE7,
+  COLUMN_CANDIDATE8,
+  COLUMN_CANDIDATE9,
+  COLUMN_CANDIDATE10,
+  COLUMN_CANDIDATE11,
+  COLUMN_CANDIDATE12,
+  COLUMN_CANDIDATE13,
+  NR_COLUMNS
+};
+
+#define LABELCHAR_NR_COLUMNS 13
+#define LABELCHAR_NR_ROWS 8
+#define LABELCHAR_NR_CELLS (LABELCHAR_NR_COLUMNS * LABELCHAR_NR_ROWS)
+#define INDEX(row,col) ((row) * LABELCHAR_NR_COLUMNS + (col))
+/* 106 keyboard */
+static gchar default_labelchar_table[LABELCHAR_NR_CELLS] = {
+  '1','2','3','4','5', '6','7','8','9','0',   '-','^','\\',
+  'q','w','e','r','t', 'y','u','i','o','p',   '@','[','\0',
+  'a','s','d','f','g', 'h','j','k','l',';',   ':',']','\0',
+  'z','x','c','v','b', 'n','m',',','.','/',   '\0','\0',' ',
+  '!','"','#','$','%', '&','\'','(',')','\0', '=','~','|',
+  'Q','W','E','R','T', 'Y','U','I','O','P',   '`','{','\0',
+  'A','S','D','F','G', 'H','J','K','L','+',   '*','}','\0',
+  'Z','X','C','V','B', 'N','M','<','>','?',   '_','\0','\0',
+};
+/* labelchar_table consists of four blocks
+ *   blockLR  blockA
+ *   blockLRS blockAS
+ */
+#define BLOCK_A_ROW_START 0
+#define BLOCK_A_ROW_END 4
+#define BLOCK_A_COLUMN_START 10
+#define BLOCK_A_COLUMN_END LABELCHAR_NR_COLUMNS
+#define BLOCK_LRS_ROW_START BLOCK_A_ROW_END
+#define BLOCK_LRS_ROW_END LABELCHAR_NR_ROWS
+#define BLOCK_LRS_COLUMN_START 0
+#define BLOCK_LRS_COLUMN_END BLOCK_A_COLUMN_START
+#define BLOCK_AS_ROW_START BLOCK_LRS_ROW_START
+#define BLOCK_AS_ROW_END BLOCK_LRS_ROW_END
+#define BLOCK_AS_COLUMN_START BLOCK_LRS_COLUMN_END
+#define BLOCK_AS_COLUMN_END LABELCHAR_NR_COLUMNS
+
+#define BLOCK_SPACING 20
+#define HOMEPOSITION_SPACING 2
+#define SPACING_LEFT_BLOCK_COLUMN 4
+#define SPACING_RIGHT_BLOCK_COLUMN (BLOCK_A_COLUMN_START - 1)
+#define SPACING_UP_BLOCK_ROW (BLOCK_A_ROW_END - 1)
+#define SPACING_LEFTHAND_FAR_COLUMN 3
+#define SPACING_RIGHTHAND_FAR_COLUMN 5
+#define SPACING_UPPER_FAR_ROW 0
+#define SPACING_SHIFT_UPPER_FAR_ROW 4
+
+static void    uim_cand_win_tbl_gtk_init               (UIMCandWinTblGtk 
*cwin);
+static void    uim_cand_win_tbl_gtk_class_init (UIMCandWinGtkClass *klass);
+static void    uim_cand_win_tbl_gtk_dispose    (GObject *obj);
+static gchar   *init_labelchar_table(void);
+static void    show_table(GtkTable *view, GPtrArray *buttons);
+
+
+static GType cand_win_tbl_type = 0;
+static GTypeInfo const object_info = {
+  sizeof (UIMCandWinTblGtkClass),
+  (GBaseInitFunc) NULL,
+  (GBaseFinalizeFunc) NULL,
+  (GClassInitFunc) uim_cand_win_tbl_gtk_class_init,
+  (GClassFinalizeFunc) NULL,
+  NULL,                       /* class_data */
+  sizeof (UIMCandWinTblGtk),
+  0,                          /* n_preallocs */
+  (GInstanceInitFunc) uim_cand_win_tbl_gtk_init,
+};
+
+static GtkWindowClass *parent_class = NULL;
+
+GType
+uim_cand_win_tbl_gtk_get_type(void)
+{
+  if (!cand_win_tbl_type)
+ cand_win_tbl_type = g_type_register_static(UIM_TYPE_CAND_WIN_GTK, "UIMCandWinTblGtk",
+                                          &object_info, (GTypeFlags)0);
+  return cand_win_tbl_type;
+}
+
+GType
+uim_cand_win_tbl_gtk_register_type(GTypeModule *module)
+{
+  if (!cand_win_tbl_type)
+    cand_win_tbl_type = g_type_module_register_type(module,
+                                               UIM_TYPE_CAND_WIN_GTK,
+                                               "UIMCandWinTblGtk",
+                                               &object_info, 0);
+  return cand_win_tbl_type;
+}
+
+static void
+uim_cand_win_tbl_gtk_class_init (UIMCandWinGtkClass *klass)
+{
+  GObjectClass *object_class = (GObjectClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+  object_class->dispose = uim_cand_win_tbl_gtk_dispose;
+
+ klass->set_candidates = (void (*)(UIMCandWinGtk *, guint, GSList *))uim_cand_win_tbl_gtk_set_candidates; + klass->set_page_candidates = (void (*)(UIMCandWinGtk *, guint, GSList *))uim_cand_win_tbl_gtk_set_page_candidates; + klass->set_index = (void (*)(UIMCandWinGtk *, gint))uim_cand_win_tbl_gtk_set_index; + klass->set_page = (void (*)(UIMCandWinGtk *, gint))uim_cand_win_tbl_gtk_set_page;
+}
+
+static void
+uim_cand_win_tbl_gtk_init (UIMCandWinTblGtk *ctblwin)
+{
+  gint row, col;
+  GtkWidget *viewport;
+  UIMCandWinGtk *cwin;
+  cwin = UIM_CAND_WIN_GTK(ctblwin);
+
+  ctblwin->buttons = g_ptr_array_new();
+  ctblwin->labelchar_table = init_labelchar_table();
+
+  gtk_widget_destroy(cwin->view);
+ cwin->view = gtk_table_new(LABELCHAR_NR_ROWS, LABELCHAR_NR_COLUMNS, FALSE);
+  viewport = gtk_viewport_new(NULL, NULL);
+  gtk_container_add(GTK_CONTAINER(viewport), cwin->view);
+  gtk_container_add(GTK_CONTAINER(cwin->scrolled_window), viewport);
+ gtk_container_set_resize_mode(GTK_CONTAINER(viewport), GTK_RESIZE_PARENT);
+  for (row = 0; row < LABELCHAR_NR_ROWS; row++) {
+    for (col = 0; col < LABELCHAR_NR_COLUMNS; col++) {
+      GtkWidget *button;
+      button = gtk_button_new_with_label("  ");
+      gtk_table_attach_defaults(GTK_TABLE(cwin->view), button,
+                                col, col + 1, row, row + 1);
+      g_ptr_array_add(ctblwin->buttons, button);
+    }
+  }
+ gtk_table_set_col_spacing(GTK_TABLE(cwin->view), SPACING_LEFT_BLOCK_COLUMN,
+      BLOCK_SPACING);
+ gtk_table_set_col_spacing(GTK_TABLE(cwin->view), SPACING_RIGHT_BLOCK_COLUMN,
+      BLOCK_SPACING);
+  gtk_table_set_row_spacing(GTK_TABLE(cwin->view), SPACING_UP_BLOCK_ROW,
+      BLOCK_SPACING);
+ gtk_table_set_col_spacing(GTK_TABLE(cwin->view), SPACING_LEFTHAND_FAR_COLUMN,
+      HOMEPOSITION_SPACING);
+ gtk_table_set_col_spacing(GTK_TABLE(cwin->view), SPACING_RIGHTHAND_FAR_COLUMN,
+      HOMEPOSITION_SPACING);
+  gtk_table_set_row_spacing(GTK_TABLE(cwin->view), SPACING_UPPER_FAR_ROW,
+      HOMEPOSITION_SPACING);
+ gtk_table_set_row_spacing(GTK_TABLE(cwin->view), SPACING_SHIFT_UPPER_FAR_ROW,
+      HOMEPOSITION_SPACING);
+
+  gtk_widget_show_all(cwin->view);
+  gtk_widget_show(viewport);
+
+ gtk_widget_set_size_request(cwin->num_label, DEFAULT_MIN_WINDOW_WIDTH, -1); + gtk_window_set_default_size(GTK_WINDOW(cwin), DEFAULT_MIN_WINDOW_WIDTH, -1);
+  gtk_window_set_resizable(GTK_WINDOW(cwin), FALSE);
+}
+
+static gchar *
+init_labelchar_table(void)
+{
+  gchar *table;
+  uim_lisp list;
+  size_t len = 0;
+  uim_lisp *ary0, *ary;
+  guint i;
+
+  list = uim_scm_symbol_value("uim-candwin-prog-layout");
+  if (list == NULL || !uim_scm_listp(list)) {
+    return default_labelchar_table;
+  }
+  ary0 = ary = (uim_lisp *)uim_scm_list2array(list, &len, NULL);
+  if (ary == NULL || len <= 0) {
+    if (ary0) {
+      free(ary0);
+    }
+    return default_labelchar_table;
+  }
+  table = (gchar *)g_malloc(LABELCHAR_NR_CELLS);
+  if (table == NULL) {
+    free(ary0);
+    return default_labelchar_table;
+  }
+  for (i = 0; i < LABELCHAR_NR_CELLS; i++, ary++) {
+    table[i] = '\0';
+    if (i < len) {
+      char *str = uim_scm_c_str(*ary);
+      if (str) {
+        table[i] = *str;
+        free(str);
+      }
+    }
+  }
+  free(ary0);
+  return table;
+}
+
+static void
+uim_cand_win_tbl_gtk_dispose (GObject *obj)
+{
+  UIMCandWinTblGtk *ctblwin;
+
+  g_return_if_fail(UIM_IS_CAND_WIN_TBL_GTK(obj));
+
+  ctblwin = UIM_CAND_WIN_TBL_GTK(obj);
+
+  if (ctblwin->labelchar_table != default_labelchar_table) {
+    g_free(ctblwin->labelchar_table);
+    ctblwin->labelchar_table = NULL;
+  }
+  if (ctblwin->buttons) {
+    g_ptr_array_free(ctblwin->buttons, TRUE);
+    ctblwin->buttons = NULL;
+  }
+
+  if (G_OBJECT_CLASS (parent_class)->dispose)
+    G_OBJECT_CLASS (parent_class)->dispose(obj);
+}
+
+UIMCandWinTblGtk *
+uim_cand_win_tbl_gtk_new (void)
+{
+  GObject *obj = g_object_new(UIM_TYPE_CAND_WIN_TBL_GTK,
+                             "type", GTK_WINDOW_POPUP,
+                             NULL);
+  return UIM_CAND_WIN_TBL_GTK(obj);
+}
+
+static void
+get_row_column(gchar *labelchar_table, const gchar labelchar, gint *row, gint *col)
+{
+  gint i;
+  for (i = 0; i < LABELCHAR_NR_CELLS; i++) {
+    if (labelchar_table[i] == labelchar) {
+      *row = i / LABELCHAR_NR_COLUMNS;
+      *col = i % LABELCHAR_NR_COLUMNS;
+      return;
+    }
+  }
+  *row = 0;
+  *col = 0;
+}
+
+static void
+set_candidate(UIMCandWinTblGtk *ctblwin, GSList *node, GtkListStore *store)
+{
+  if (node) {
+    GtkTreeIter ti;
+    gint row = 0;
+    gint col = 0;
+    gint i;
+    const char *heading_label = NULL;
+    const char *cand_str = NULL;
+    uim_candidate cand = node->data;
+
+    heading_label = uim_candidate_get_heading_label(cand);
+    cand_str = uim_candidate_get_cand_str(cand);
+
+    get_row_column(ctblwin->labelchar_table, heading_label[0], &row, &col);
+    gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &ti);
+    for (i = 0; i < row; i++) {
+      gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &ti);
+    }
+    gtk_list_store_set(store, &ti, col, cand_str, TERMINATOR);
+  } else {
+    /* No need to set any data for empty row. */
+  }
+}
+
+void
+uim_cand_win_tbl_gtk_set_candidates(UIMCandWinTblGtk *ctblwin,
+                               guint display_limit,
+                               GSList *candidates)
+{
+  gint i, nr_stores = 1;
+  UIMCandWinGtk *cwin;
+
+  g_return_if_fail(UIM_IS_CAND_WIN_TBL_GTK(ctblwin));
+  cwin = UIM_CAND_WIN_GTK(ctblwin);
+
+  if (cwin->stores == NULL)
+    cwin->stores = g_ptr_array_new();
+
+  /* remove old data */
+ if (cwin->page_index >= 0 && cwin->page_index < (int) cwin->stores->len) {
+    /* Remove data from current page to shrink the window */
+    if (cwin->stores->pdata[cwin->page_index])
+      gtk_list_store_clear(cwin->stores->pdata[cwin->page_index]);
+  }
+  for (i = cwin->stores->len - 1; i >= 0; i--) {
+    GtkListStore *store = g_ptr_array_remove_index(cwin->stores, i);
+    if (store)
+      g_object_unref(G_OBJECT(store));
+  }
+
+  cwin->candidate_index = -1;
+  cwin->nr_candidates = g_slist_length(candidates);
+  cwin->display_limit = display_limit;
+
+  cwin->sub_window.active = FALSE;
+
+  if (candidates == NULL)
+    return;
+
+  /* calculate number of GtkListStores to create */
+  if (display_limit) {
+    nr_stores = cwin->nr_candidates / display_limit;
+    if (cwin->nr_candidates > display_limit * nr_stores)
+      nr_stores++;
+  }
+
+  /* create GtkListStores, and set candidates */
+  for (i = 0; i < nr_stores; i++) {
+    GtkListStore *store = gtk_list_store_new(LABELCHAR_NR_COLUMNS,
+        G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+        G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+        G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+       G_TYPE_STRING);
+    GSList *node;
+    guint j;
+
+    g_ptr_array_add(cwin->stores, store);
+
+    for (j = 0; j < LABELCHAR_NR_ROWS; j++) {
+      GtkTreeIter ti;
+      gtk_list_store_append(store, &ti);
+    }
+
+    /* set candidates */
+    for (j = i * display_limit, node = g_slist_nth(candidates, j);
+        display_limit ? j < display_limit * (i + 1) : j < cwin->nr_candidates;
+        j++, node = g_slist_next(node))
+    {
+      set_candidate(ctblwin, node, store);
+    }
+  }
+
+  uim_cand_win_gtk_set_page(cwin, 0);
+
+  uim_cand_win_gtk_update_label(cwin);
+}
+
+void
+uim_cand_win_tbl_gtk_set_page_candidates(UIMCandWinTblGtk *ctblwin,
+                                    guint page,
+                                    GSList *candidates)
+{
+  GtkListStore *store;
+  GSList *node;
+  gint j, len;
+  UIMCandWinGtk *cwin;
+
+  g_return_if_fail(UIM_IS_CAND_WIN_TBL_GTK(ctblwin));
+  cwin = UIM_CAND_WIN_GTK(ctblwin);
+
+  if (candidates == NULL)
+    return;
+
+  cwin->sub_window.active = FALSE;
+  len = g_slist_length(candidates);
+
+  /* create GtkListStores, and set candidates */
+  store = gtk_list_store_new(LABELCHAR_NR_COLUMNS, G_TYPE_STRING,
+      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+  cwin->stores->pdata[page] = store;
+
+  for (j = 0; j < LABELCHAR_NR_ROWS; j++) {
+    GtkTreeIter ti;
+    gtk_list_store_append(store, &ti);
+  }
+
+  /* set candidates */
+  for (j = 0, node = g_slist_nth(candidates, j);
+       j < len;
+       j++, node = g_slist_next(node))
+  {
+    set_candidate(ctblwin, node, store);
+  }
+}
+
+void
+uim_cand_win_tbl_gtk_set_index(UIMCandWinTblGtk *ctblwin, gint index)
+{
+  gint new_page;
+  UIMCandWinGtk *cwin;
+
+  g_return_if_fail(UIM_IS_CAND_WIN_TBL_GTK(ctblwin));
+  cwin = UIM_CAND_WIN_GTK(ctblwin);
+
+  if (index >= (gint) cwin->nr_candidates)
+    cwin->candidate_index = 0;
+  else
+    cwin->candidate_index = index;
+
+  if (cwin->candidate_index >= 0 && cwin->display_limit)
+    new_page = cwin->candidate_index / cwin->display_limit;
+  else
+    new_page = cwin->page_index;
+
+  if (cwin->page_index != new_page)
+    uim_cand_win_gtk_set_page(cwin, new_page);
+
+  uim_cand_win_gtk_update_label(cwin);
+}
+
+static void
+update_table_button(GtkTreeModel *model, GPtrArray *buttons, gchar *labelchar_table)
+{
+  GtkTreeIter ti;
+  gint row, col;
+  gboolean hasValue = TRUE;
+  gtk_tree_model_get_iter_first(model, &ti);
+  for (row = 0; row < LABELCHAR_NR_ROWS; row++) {
+    for (col = 0; col < LABELCHAR_NR_COLUMNS; col++) {
+      GValue value = {0};
+      const gchar *str = NULL;
+      GtkButton *button;
+      button = g_ptr_array_index(buttons, INDEX(row, col));
+      if (hasValue) {
+        gtk_tree_model_get_value(model, &ti, col, &value);
+        str = g_value_get_string(&value);
+      }
+      if (str == NULL) {
+        str = "  ";
+       if (labelchar_table[INDEX(row, col)] == '\0') {
+          gtk_button_set_relief(button, GTK_RELIEF_NONE);
+       } else {
+          gtk_button_set_relief(button, GTK_RELIEF_HALF);
+       }
+        gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
+      } else {
+        gtk_button_set_relief(button, GTK_RELIEF_NORMAL);
+        gtk_widget_set_sensitive(GTK_WIDGET(button), TRUE);
+      }
+      gtk_button_set_label(button, str);
+      if (hasValue) {
+        g_value_unset(&value);
+      }
+    }
+    if (hasValue) {
+      hasValue = gtk_tree_model_iter_next(model, &ti);
+    }
+  }
+}
+
+void
+uim_cand_win_tbl_gtk_set_page(UIMCandWinTblGtk *ctblwin, gint page)
+{
+  guint len, new_page;
+  gint new_index;
+  UIMCandWinGtk *cwin;
+
+  g_return_if_fail(UIM_IS_CAND_WIN_TBL_GTK(ctblwin));
+  cwin = UIM_CAND_WIN_GTK(ctblwin);
+  g_return_if_fail(cwin->stores);
+
+  len = cwin->stores->len;
+  g_return_if_fail(len);
+
+  if (page < 0)
+    new_page = len - 1;
+  else if (page >= (gint) len)
+    new_page = 0;
+  else
+    new_page = page;
+
+  update_table_button(GTK_TREE_MODEL(cwin->stores->pdata[new_page]),
+                      ctblwin->buttons, ctblwin->labelchar_table);
+  show_table(GTK_TABLE(cwin->view), ctblwin->buttons);
+
+  cwin->page_index = new_page;
+
+  if (cwin->display_limit) {
+    if (cwin->candidate_index >= 0)
+      new_index
+ = (new_page * cwin->display_limit) + (cwin->candidate_index % cwin->display_limit);
+    else
+      new_index = -1;
+  } else {
+    new_index = cwin->candidate_index;
+  }
+
+  if (new_index >= (gint) cwin->nr_candidates)
+    new_index = cwin->nr_candidates - 1;
+
+  uim_cand_win_gtk_set_index(cwin, new_index);
+}
+
+static gboolean
+is_empty_block(GPtrArray *buttons, gint rowstart, gint rowend, gint colstart, gint colend)
+{
+  gint row, col;
+  for (row = rowstart; row < rowend; row++) {
+    for (col = colstart; col < colend; col++) {
+      GtkButton *button;
+      GtkReliefStyle relief;
+      button = g_ptr_array_index(buttons, INDEX(row, col));
+      relief = gtk_button_get_relief(button);
+      if (relief == GTK_RELIEF_NORMAL) {
+        return FALSE;
+      }
+    }
+  }
+  return TRUE;
+}
+
+static void
+show_table(GtkTable *view, GPtrArray *buttons)
+{
+  /* hide empty blocks.
+   * pattern0(full table)
+   *   blockLR  blockA
+   *   blockLRS blockAS  (for shift key)
+   * pattern1(minimal blocks)
+   *   blockLR
+   * pattern2(without shift blocks)
+   *   blockLR  blockA
+   * pattern3(without symbol blocks)
+   *   blockLR
+   *   blockLRS
+   */
+  gint row, col;
+  gint hide_row, hide_col;
+  gint row_spacing, col_spacing;
+  gboolean blockA, blockAS, blockLRS;
+  blockA = !is_empty_block(buttons, BLOCK_A_ROW_START, BLOCK_A_ROW_END,
+      BLOCK_A_COLUMN_START, BLOCK_A_COLUMN_END);
+  blockAS = !is_empty_block(buttons, BLOCK_AS_ROW_START, BLOCK_AS_ROW_END,
+      BLOCK_AS_COLUMN_START, BLOCK_AS_COLUMN_END);
+ blockLRS = !is_empty_block(buttons, BLOCK_LRS_ROW_START, BLOCK_LRS_ROW_END,
+      BLOCK_LRS_COLUMN_START, BLOCK_LRS_COLUMN_END);
+
+  hide_row = LABELCHAR_NR_ROWS;
+  hide_col = LABELCHAR_NR_COLUMNS;
+  if (blockAS) { /* pattern0(full table) */
+    hide_row = LABELCHAR_NR_ROWS;
+    hide_col = LABELCHAR_NR_COLUMNS;
+  } else if (blockLRS) {
+    if (blockA) { /* pattern0(full table) */
+      hide_row = LABELCHAR_NR_ROWS;
+      hide_col = LABELCHAR_NR_COLUMNS;
+    } else { /* pattern3(without symbol blocks) */
+      hide_row = LABELCHAR_NR_ROWS;
+      hide_col = BLOCK_A_COLUMN_START;
+    }
+  } else if (blockA) { /* pattern2(without shift blocks) */
+    hide_row = BLOCK_A_ROW_END;
+    hide_col = LABELCHAR_NR_COLUMNS;
+  } else { /* pattern1(minimal blocks) */
+    hide_row = BLOCK_A_ROW_END;
+    hide_col = BLOCK_A_COLUMN_START;
+  }
+
+  for (row = 0; row < LABELCHAR_NR_ROWS; row++) {
+    for (col = 0; col < LABELCHAR_NR_COLUMNS; col++) {
+      GtkButton *button;
+      button = g_ptr_array_index(buttons, INDEX(row, col));
+      if (row >= hide_row || col >= hide_col) {
+        gtk_widget_hide(GTK_WIDGET(button));
+      } else {
+        gtk_widget_show(GTK_WIDGET(button));
+      }
+    }
+  }
+  if (hide_col <= BLOCK_A_COLUMN_START) {
+    col_spacing = 0;
+  } else {
+    col_spacing = BLOCK_SPACING;
+  }
+  if (hide_row <= BLOCK_LRS_ROW_START) {
+    row_spacing = 0;
+  } else {
+    row_spacing = BLOCK_SPACING;
+  }
+  gtk_table_set_col_spacing(view, SPACING_RIGHT_BLOCK_COLUMN, col_spacing);
+  gtk_table_set_row_spacing(view, SPACING_UP_BLOCK_ROW, row_spacing);
+  if (row_spacing) {
+    gtk_table_set_row_spacing(view, SPACING_SHIFT_UPPER_FAR_ROW,
+        HOMEPOSITION_SPACING);
+  } else {
+    gtk_table_set_row_spacing(view, SPACING_SHIFT_UPPER_FAR_ROW, 0);
+  }
+  /* gtk_table_resize(view, hide_row, hide_col); */
+  gtk_widget_show(GTK_WIDGET(view));
+}
=======================================
--- /dev/null
+++ /trunk/gtk/uim-cand-win-tbl-gtk.h   Sun Jun 13 00:30:03 2010
@@ -0,0 +1,75 @@
+/*
+
+  Copyright (c) 2003-2010 uim Project http://code.google.com/p/uim/
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+  3. Neither the name of authors nor the names of its contributors
+     may be used to endorse or promote products derived from this software
+     without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  SUCH DAMAGE.
+
+*/
+
+#ifndef UIM_GTK_UIM_CAND_WIN_TBL_GTK_H
+#define UIM_GTK_UIM_CAND_WIN_TBL_GTK_H
+
+#include "uim-cand-win-gtk.h"
+
+G_BEGIN_DECLS
+
+#define UIM_TYPE_CAND_WIN_TBL_GTK (uim_cand_win_tbl_gtk_get_type ())
+#define UIM_CAND_WIN_TBL_GTK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UIM_TYPE_CAND_WIN_TBL_GTK, UIMCandWinTblGtk)) +#define UIM_CAND_WIN_TBL_GTK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UIM_TYPE_CAND_WIN_TBL_GTK, UIMCandWinTblGtkClass)) +#define UIM_IS_CAND_WIN_TBL_GTK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UIM_TYPE_CAND_WIN_TBL_GTK)) +#define UIM_IS_CAND_WIN_TBL_GTK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UIM_TYPE_CAND_WIN_TBL_GTK)) +#define UIM_CAND_WIN_TBL_GTK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UIM_TYPE_CAND_WIN_TBL_GTK, UIMCandWinTblGtkClass))
+
+typedef struct _UIMCandWinTblGtk UIMCandWinTblGtk;
+typedef struct _UIMCandWinTblGtkClass UIMCandWinTblGtkClass;
+
+struct _UIMCandWinTblGtk {
+  UIMCandWinGtk parent;
+  GPtrArray *buttons;
+  gchar *labelchar_table;
+};
+
+struct _UIMCandWinTblGtkClass {
+  UIMCandWinGtkClass parent_class;
+};
+
+
+GType uim_cand_win_tbl_gtk_register_type(GTypeModule *module);
+GType uim_cand_win_tbl_gtk_get_type(void);
+UIMCandWinTblGtk *uim_cand_win_tbl_gtk_new(void);
+
+void uim_cand_win_tbl_gtk_set_candidates(UIMCandWinTblGtk *cwin,
+    guint disp_limit, GSList *candidates);
+void uim_cand_win_tbl_gtk_set_page_candidates(UIMCandWinTblGtk *cwin,
+    guint page, GSList *candidates);
+void uim_cand_win_tbl_gtk_set_index(UIMCandWinTblGtk *cwin, gint index);
+void uim_cand_win_tbl_gtk_set_page(UIMCandWinTblGtk *cwin, gint page);
+
+G_END_DECLS
+
+#endif /* UIM_GTK_UIM_CAND_WIN_TBL_GTK_H */
=======================================
--- /trunk/gtk/Makefile.am      Mon Apr 26 18:53:41 2010
+++ /trunk/gtk/Makefile.am      Sun Jun 13 00:30:03 2010
@@ -24,6 +24,7 @@
 IM_UIM_SOURCES = \
        gtk-im-uim.c gtk-im-uim.h key-util-gtk.c key-util-gtk.h \
        uim-cand-win-gtk.c uim-cand-win-gtk.h \
+       uim-cand-win-tbl-gtk.c uim-cand-win-tbl-gtk.h \
        caret-state-indicator.c caret-state-indicator.h \
        compose.c compose.h text-util.c text-util.h

=======================================
--- /trunk/gtk/gtk-im-uim.c     Sun Apr  4 20:35:54 2010
+++ /trunk/gtk/gtk-im-uim.c     Sun Jun 13 00:30:03 2010
@@ -59,6 +59,7 @@

 #include "gtk-im-uim.h"
 #include "uim-cand-win-gtk.h"
+#include "uim-cand-win-tbl-gtk.h"
 #include "caret-state-indicator.h"
 #include "key-util-gtk.h"
 #ifdef GDK_WINDOWING_X11
@@ -1379,6 +1380,22 @@
   }
   update_client_widget(uic);
 }
+
+static UIMCandWinGtk *
+im_uim_create_cand_win_gtk()
+{
+  UIMCandWinGtk *cwin;
+  char *candwinprog = uim_scm_symbol_value_str("uim-candwin-prog");
+  if (candwinprog && !strncmp(candwinprog, "uim-candwin-tbl", 15)) {
+    cwin = UIM_CAND_WIN_GTK(uim_cand_win_tbl_gtk_new());
+  } else {
+    cwin = uim_cand_win_gtk_new();
+  }
+  if (candwinprog) {
+    free(candwinprog);
+  }
+  return cwin;
+}

 static void
 im_uim_init(IMUIMContext *uic)
@@ -1393,7 +1410,7 @@
   uic->nr_psegs = 0;
   uic->prev_preedit_len = 0;

-  uic->cwin = uim_cand_win_gtk_new();
+  uic->cwin = im_uim_create_cand_win_gtk();
 #if IM_UIM_USE_TOPLEVEL
   cwin_list = g_list_append(cwin_list, uic->cwin);
 #endif
=======================================
--- /trunk/gtk/uim-cand-win-gtk.c       Wed May 19 01:40:38 2010
+++ /trunk/gtk/uim-cand-win-gtk.c       Sun Jun 13 00:30:03 2010
@@ -62,6 +62,16 @@
 static void    uim_cand_win_gtk_unmap          (GtkWidget *widget);
 static void    uim_cand_win_gtk_create_sub_window(UIMCandWinGtk *cwin);
 static void    uim_cand_win_gtk_layout_sub_window(UIMCandWinGtk *cwin);
+static void    uim_cand_win_gtk_real_set_candidates    (UIMCandWinGtk *cwin,
+                                                        guint disp_limit,
+                                                        GSList *candidates);
+static void    uim_cand_win_gtk_real_set_page_candidates(UIMCandWinGtk *cwin,
+                                                         guint page,
+                                                         GSList *candidates);
+static void    uim_cand_win_gtk_real_set_index         (UIMCandWinGtk *cwin,
+                                                        gint index);
+static void    uim_cand_win_gtk_real_set_page          (UIMCandWinGtk *cwin,
+                                                        gint page);

 static gboolean        tree_selection_change           (GtkTreeSelection 
*selection,
                                                 GtkTreeModel *model,
@@ -131,6 +141,11 @@

   widget_class->map   = uim_cand_win_gtk_map;
   widget_class->unmap = uim_cand_win_gtk_unmap;
+
+  klass->set_candidates = uim_cand_win_gtk_real_set_candidates;
+  klass->set_page_candidates = uim_cand_win_gtk_real_set_page_candidates;
+  klass->set_index = uim_cand_win_gtk_real_set_index;
+  klass->set_page = uim_cand_win_gtk_real_set_page;
 }

 void
@@ -309,8 +324,8 @@
   return UIM_CAND_WIN_GTK(obj);
 }

-static void
-update_label(UIMCandWinGtk *cwin)
+void
+uim_cand_win_gtk_update_label(UIMCandWinGtk *cwin)
 {
   char label_str[20];

@@ -349,14 +364,14 @@
                    cand_win_gtk_signals[INDEX_CHANGED_SIGNAL], 0);
     }

-    update_label(cwin);
+    uim_cand_win_gtk_update_label(cwin);

     if (cwin->candidate_index < 0)
       return FALSE;
     else
       return TRUE;
   } else {
-    update_label(cwin);
+    uim_cand_win_gtk_update_label(cwin);

     return TRUE;
   }
@@ -475,6 +490,14 @@
 uim_cand_win_gtk_set_candidates(UIMCandWinGtk *cwin,
                                guint display_limit,
                                GSList *candidates)
+{
+ UIM_CAND_WIN_GTK_GET_CLASS (cwin)->set_candidates(cwin, display_limit, candidates);
+}
+
+static void
+uim_cand_win_gtk_real_set_candidates(UIMCandWinGtk *cwin,
+                                    guint display_limit,
+                                    GSList *candidates)
 {
   gint i, nr_stores = 1;

@@ -559,13 +582,21 @@

   uim_cand_win_gtk_set_page(cwin, 0);

-  update_label(cwin);
+  uim_cand_win_gtk_update_label(cwin);
 }

 void
 uim_cand_win_gtk_set_page_candidates(UIMCandWinGtk *cwin,
                                     guint page,
                                     GSList *candidates)
+{
+ UIM_CAND_WIN_GTK_GET_CLASS (cwin)->set_page_candidates(cwin, page, candidates);
+}
+
+static void
+uim_cand_win_gtk_real_set_page_candidates(UIMCandWinGtk *cwin,
+                                         guint page,
+                                         GSList *candidates)
 {
   GtkListStore *store;
   GSList *node;
@@ -630,6 +661,12 @@

 void
 uim_cand_win_gtk_set_index(UIMCandWinGtk *cwin, gint index)
+{
+  UIM_CAND_WIN_GTK_GET_CLASS (cwin)->set_index(cwin, index);
+}
+
+static void
+uim_cand_win_gtk_real_set_index(UIMCandWinGtk *cwin, gint index)
 {
   gint new_page;

@@ -664,7 +701,7 @@
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cwin->view));

     gtk_tree_selection_unselect_all(selection);
-    update_label(cwin);
+    uim_cand_win_gtk_update_label(cwin);
   }
 }

@@ -687,6 +724,12 @@

 void
 uim_cand_win_gtk_set_page(UIMCandWinGtk *cwin, gint page)
+{
+  UIM_CAND_WIN_GTK_GET_CLASS (cwin)->set_page(cwin, page);
+}
+
+static void
+uim_cand_win_gtk_real_set_page(UIMCandWinGtk *cwin, gint page)
 {
   guint len, new_page;
   gint new_index;
=======================================
--- /trunk/gtk/uim-cand-win-gtk.h       Sun Apr  4 20:35:54 2010
+++ /trunk/gtk/uim-cand-win-gtk.h       Sun Jun 13 00:30:03 2010
@@ -86,6 +86,16 @@

   /* signals */
   void (*index_changed) (UIMCandWinGtkClass *cwin);
+
+  /* member functions */
+  void (*set_candidates)       (UIMCandWinGtk *cwin,
+                                guint disp_limit,
+                                GSList *candidates);
+  void (*set_page_candidates)  (UIMCandWinGtk *cwin,
+                                guint page,
+                                GSList *candidates);
+  void (*set_index)            (UIMCandWinGtk *cwin, gint index);
+  void (*set_page)             (UIMCandWinGtk *cwin, gint page);
 };


@@ -133,6 +143,8 @@
                                                         GdkRectangle *area);
 void           uim_cand_win_gtk_get_window_pos_type    (UIMCandWinGtk *cwin);

+void           uim_cand_win_gtk_update_label           (UIMCandWinGtk *cwin);
+
 G_END_DECLS

 #endif /*UIM_GTK_UIM_CAND_WIN_GTK_H */

Reply via email to