Support mouse click on lookup table. 1.1.0.20090612
authorPeng Huang <shawn.p.huang@gmail.com>
Fri, 12 Jun 2009 01:54:47 +0000 (09:54 +0800)
committerPeng Huang <shawn.p.huang@gmail.com>
Fri, 12 Jun 2009 01:54:47 +0000 (09:54 +0800)
15 files changed:
bus/engineproxy.c
bus/engineproxy.h
bus/inputcontext.c
bus/inputcontext.h
bus/panelproxy.c
bus/panelproxy.h
ibus/engine.py
ibus/interface/iengine.py
ibus/interface/ipanel.py
ibus/panel.py
src/ibusengine.c
src/ibusengine.h
src/ibusmarshalers.list
ui/gtk/candidatepanel.py
ui/gtk/panel.py

index e78fbcf..5a2f841 100644 (file)
@@ -687,7 +687,8 @@ void bus_engine_proxy_property_hide (BusEngineProxy *engine,
 }
 
 #define DEFINE_FUNCTION(Name, name)                         \
-    void bus_engine_proxy_##name (BusEngineProxy *engine)   \
+    void                                                    \
+    bus_engine_proxy_##name (BusEngineProxy *engine)        \
     {                                                       \
         g_assert (BUS_IS_ENGINE_PROXY (engine));            \
         ibus_proxy_call ((IBusProxy *) engine,              \
@@ -707,6 +708,21 @@ DEFINE_FUNCTION (Disable, disable)
 
 #undef DEFINE_FUNCTION
 
+void
+bus_engine_proxy_candidate_clicked (BusEngineProxy *engine,
+                                    guint           index,
+                                    guint           button,
+                                    guint           state)
+{
+    g_assert (BUS_IS_ENGINE_PROXY (engine));
+
+    ibus_proxy_call ((IBusProxy *) engine,
+                     "CandidateClicked",
+                     G_TYPE_UINT, &index,
+                     G_TYPE_UINT, &button,
+                     G_TYPE_UINT, &state,
+                     G_TYPE_INVALID);
+}
 
 IBusEngineDesc *
 bus_engine_proxy_get_desc (BusEngineProxy *engine)
index 2206c9a..8d1067c 100644 (file)
@@ -81,6 +81,10 @@ void             bus_engine_proxy_page_up           (BusEngineProxy *engine);
 void             bus_engine_proxy_page_down         (BusEngineProxy *engine);
 void             bus_engine_proxy_cursor_up         (BusEngineProxy *engine);
 void             bus_engine_proxy_cursor_down       (BusEngineProxy *engine);
+void             bus_engine_proxy_candidate_clicked (BusEngineProxy *engine,
+                                                     guint           index,
+                                                     guint           button,
+                                                     guint           state);
 void             bus_engine_proxy_enable            (BusEngineProxy *engine);
 void             bus_engine_proxy_disable           (BusEngineProxy *engine);
 void             bus_engine_proxy_property_activate (BusEngineProxy *engine,
index 511ebf5..0881581 100644 (file)
@@ -1208,47 +1208,32 @@ bus_input_context_focus_out (BusInputContext *context)
     }
 }
 
-void
-bus_input_context_page_up (BusInputContext *context)
-{
-    g_assert (BUS_IS_INPUT_CONTEXT (context));
-
-    BusInputContextPrivate *priv;
-    priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);
-
-    if (priv->engine) {
-        bus_engine_proxy_page_up (priv->engine);
-    }
-}
-
-void
-bus_input_context_page_down (BusInputContext *context)
-{
-    g_assert (BUS_IS_INPUT_CONTEXT (context));
-
-    BusInputContextPrivate *priv;
-    priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);
-
-    if (priv->engine) {
-        bus_engine_proxy_page_down (priv->engine);
-    }
-}
-
-void
-bus_input_context_cursor_up (BusInputContext *context)
-{
-    g_assert (BUS_IS_INPUT_CONTEXT (context));
-
-    BusInputContextPrivate *priv;
-    priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);
-
-    if (priv->engine) {
-        bus_engine_proxy_cursor_up (priv->engine);
-    }
-}
+#define DEFINE_FUNC(name)                                   \
+    void                                                    \
+    bus_input_context_##name (BusInputContext *context)     \
+    {                                                       \
+        g_assert (BUS_IS_INPUT_CONTEXT (context));          \
+                                                            \
+        BusInputContextPrivate *priv;                       \
+        priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);     \
+                                                            \
+        if (priv->engine) {                                 \
+            bus_engine_proxy_##name (priv->engine);         \
+        }                                                   \
+    }
+
+DEFINE_FUNC(page_up)
+DEFINE_FUNC(page_down)
+DEFINE_FUNC(cursor_up)
+DEFINE_FUNC(cursor_down)
+
+#undef DEFINE_FUNC
 
 void
-bus_input_context_cursor_down (BusInputContext *context)
+bus_input_context_candidate_clicked (BusInputContext *context,
+                                     guint            index,
+                                     guint            button,
+                                     guint            state)
 {
     g_assert (BUS_IS_INPUT_CONTEXT (context));
 
@@ -1256,7 +1241,10 @@ bus_input_context_cursor_down (BusInputContext *context)
     priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);
 
     if (priv->engine) {
-        bus_engine_proxy_cursor_down (priv->engine);
+        bus_engine_proxy_candidate_clicked (priv->engine,
+                                            index,
+                                            button,
+                                            state);
     }
 }
 
index 537cbef..f627b2d 100644 (file)
@@ -71,6 +71,10 @@ void                 bus_input_context_page_up          (BusInputContext    *con
 void                 bus_input_context_page_down        (BusInputContext    *context);
 void                 bus_input_context_cursor_up        (BusInputContext    *context);
 void                 bus_input_context_cursor_down      (BusInputContext    *context);
+void                 bus_input_context_candidate_clicked(BusInputContext    *context,
+                                                         guint               index,
+                                                         guint               button,
+                                                         guint               state);
 void                 bus_input_context_set_engine       (BusInputContext    *context,
                                                          BusEngineProxy     *factory);
 BusEngineProxy      *bus_input_context_get_engine       (BusInputContext    *context);
index 1d24b2f..d19c9be 100644 (file)
@@ -30,6 +30,7 @@ enum {
     PAGE_DOWN,
     CURSOR_UP,
     CURSOR_DOWN,
+    CANDIDATE_CLICKED,
     PROPERTY_ACTIVATE,
     PROPERTY_SHOW,
     PROPERTY_HIDE,
@@ -57,6 +58,11 @@ static void     bus_panel_proxy_page_up         (BusPanelProxy          *panel);
 static void     bus_panel_proxy_page_down       (BusPanelProxy          *panel);
 static void     bus_panel_proxy_cursor_up       (BusPanelProxy          *panel);
 static void     bus_panel_proxy_cursor_down     (BusPanelProxy          *panel);
+static void     bus_panel_proxy_candidate_clicked
+                                                (BusPanelProxy          *panel,
+                                                 guint                   index,
+                                                 guint                   button,
+                                                 guint                   state);
 static void     bus_panel_proxy_property_activate
                                                 (BusPanelProxy          *panel,
                                                  const gchar            *prop_name,
@@ -128,6 +134,7 @@ bus_panel_proxy_class_init (BusPanelProxyClass *klass)
     klass->cursor_up   = bus_panel_proxy_cursor_up;
     klass->cursor_down = bus_panel_proxy_cursor_down;
 
+    klass->candidate_clicked = bus_panel_proxy_candidate_clicked;
     klass->property_activate = bus_panel_proxy_property_activate;
 
     ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_panel_proxy_real_destroy;
@@ -171,6 +178,18 @@ bus_panel_proxy_class_init (BusPanelProxyClass *klass)
             ibus_marshal_VOID__VOID,
             G_TYPE_NONE, 0);
 
+    panel_signals[CANDIDATE_CLICKED] =
+        g_signal_new (I_("candidate-clicked"),
+            G_TYPE_FROM_CLASS (klass),
+            G_SIGNAL_RUN_LAST,
+            G_STRUCT_OFFSET(BusPanelProxyClass, candidate_clicked),
+            NULL, NULL,
+            ibus_marshal_VOID__UINT_UINT_UINT,
+            G_TYPE_NONE, 3,
+            G_TYPE_UINT,
+            G_TYPE_UINT,
+            G_TYPE_UINT);
+
     panel_signals[PROPERTY_ACTIVATE] =
         g_signal_new (I_("property-activate"),
             G_TYPE_FROM_CLASS (klass),
@@ -266,7 +285,22 @@ bus_panel_proxy_ibus_signal (IBusProxy      *proxy,
         }
     }
 
-    if (ibus_message_is_signal (message, IBUS_INTERFACE_PANEL, "PropertyActivate")) {
+    if (ibus_message_is_signal (message, IBUS_INTERFACE_PANEL, "CandidateClicked")) {
+        guint index, button, state;
+        gboolean retval;
+
+        retval = ibus_message_get_args (message,
+                                        &error,
+                                        G_TYPE_UINT, &index,
+                                        G_TYPE_UINT, &button,
+                                        G_TYPE_UINT, &state,
+                                        G_TYPE_INVALID);
+        if (!retval)
+            goto failed;
+
+        g_signal_emit (panel, panel_signals[CANDIDATE_CLICKED], 0, index, button, state);
+    }
+    else if (ibus_message_is_signal (message, IBUS_INTERFACE_PANEL, "PropertyActivate")) {
         gchar *prop_name;
         gint prop_state;
         gboolean retval;
@@ -476,46 +510,31 @@ bus_panel_proxy_update_property (BusPanelProxy  *panel,
                      G_TYPE_INVALID);
 }
 
-static void
-bus_panel_proxy_page_up (BusPanelProxy *panel)
-{
-    g_assert (BUS_IS_PANEL_PROXY (panel));
-
-    BusPanelProxyPrivate *priv;
-    priv = BUS_PANEL_PROXY_GET_PRIVATE (panel);
-
-    if (priv->focused_context) {
-        bus_input_context_page_up (priv->focused_context);
-    }
-}
-
-static void
-bus_panel_proxy_page_down (BusPanelProxy *panel)
-{
-    g_assert (BUS_IS_PANEL_PROXY (panel));
-
-    BusPanelProxyPrivate *priv;
-    priv = BUS_PANEL_PROXY_GET_PRIVATE (panel);
-
-    if (priv->focused_context) {
-        bus_input_context_page_down (priv->focused_context);
+#define DEFINE_FUNC(name)                                       \
+    static void                                                 \
+    bus_panel_proxy_##name (BusPanelProxy *panel)               \
+    {                                                           \
+        g_assert (BUS_IS_PANEL_PROXY (panel));                  \
+                                                                \
+        BusPanelProxyPrivate *priv;                             \
+        priv = BUS_PANEL_PROXY_GET_PRIVATE (panel);             \
+                                                                \
+        if (priv->focused_context) {                            \
+            bus_input_context_##name (priv->focused_context);   \
+        }                                                       \
     }
-}
-static void
-bus_panel_proxy_cursor_up (BusPanelProxy *panel)
-{
-    g_assert (BUS_IS_PANEL_PROXY (panel));
 
-    BusPanelProxyPrivate *priv;
-    priv = BUS_PANEL_PROXY_GET_PRIVATE (panel);
-
-    if (priv->focused_context) {
-        bus_input_context_cursor_up (priv->focused_context);
-    }
-}
+DEFINE_FUNC(page_up)
+DEFINE_FUNC(page_down)
+DEFINE_FUNC(cursor_up)
+DEFINE_FUNC(cursor_down)
+#undef DEFINE_FUNC
 
 static void
-bus_panel_proxy_cursor_down (BusPanelProxy *panel)
+bus_panel_proxy_candidate_clicked (BusPanelProxy *panel,
+                                   guint          index,
+                                   guint          button,
+                                   guint          state)
 {
     g_assert (BUS_IS_PANEL_PROXY (panel));
 
@@ -523,7 +542,10 @@ bus_panel_proxy_cursor_down (BusPanelProxy *panel)
     priv = BUS_PANEL_PROXY_GET_PRIVATE (panel);
 
     if (priv->focused_context) {
-        bus_input_context_cursor_down (priv->focused_context);
+        bus_input_context_candidate_clicked (priv->focused_context,
+                                             index,
+                                             button,
+                                             state);
     }
 }
 
index 0ecc4a7..039db78 100644 (file)
@@ -60,6 +60,10 @@ struct _BusPanelProxyClass {
     void (* page_down)          (BusPanelProxy   *panel);
     void (* cursor_up)          (BusPanelProxy   *panel);
     void (* cursor_down)        (BusPanelProxy   *panel);
+    void (* candidate_clicked)  (BusPanelProxy   *panel,
+                                 guint            index,
+                                 guint            button,
+                                 guint            state);
 
     void (* property_activate)  (BusPanelProxy   *panel,
                                  const gchar     *prop_name,
index f8c0447..15ffe8f 100644 (file)
@@ -179,6 +179,9 @@ class EngineProxy(interface.IEngine):
     def CursorDown(self):
         return self.__engine.cursor_down()
 
+    def CandidateClicked(self, index, button, state):
+        return self.__engine.candidate_clicked(index, button, state)
+
     def Enable(self):
         return self.__engine.enable()
 
index 63d6c0e..21b0305 100644 (file)
@@ -74,6 +74,10 @@ class IEngine(dbus.service.Object):
     @method()
     def CursorDown(self): pass
 
+    @method(in_signature="uuu")
+    def CandidateClicked(self, index, button, state):
+        pass
+
     @method()
     def Enable(self): pass
 
@@ -96,8 +100,8 @@ class IEngine(dbus.service.Object):
     @signal(signature="v")
     def CommitText(self, text): pass
 
-    @signal(signature="ubu")
-    def ForwardKeyEvent(self, keyval, is_press, state): pass
+    @signal(signature="uu")
+    def ForwardKeyEvent(self, keyval, state): pass
 
     @signal(signature="vub")
     def UpdatePreeditText(self, text, cursor_pos, visible): pass
index e5d174c..21f2647 100644 (file)
@@ -123,6 +123,9 @@ class IPanel(dbus.service.Object):
     @signal()
     def CursorUp(self): pass
 
+    @signal(signature="uuu")
+    def CandidateClicked(self, index, button, state): pass
+
     @signal()
     def CursorDown(self): pass
 
index 9a34109..8aa49d8 100644 (file)
@@ -142,6 +142,9 @@ class PanelBase(Object):
     def cursor_down(self):
         self.__proxy.CursorDown()
 
+    def candidate_clicked(self, index, button, state):
+        self.__proxy.CandidateClicked(index, button, state)
+
     def property_activate(self, prop_name, prop_state):
         prop_name = dbus.String(prop_name)
         prop_state = dbus.Int32(prop_state)
index d37cb3c..f71b515 100644 (file)
@@ -42,6 +42,7 @@ enum {
     PROPERTY_ACTIVATE,
     PROPERTY_SHOW,
     PROPERTY_HIDE,
+    CANDIDATE_CLICKED,
     LAST_SIGNAL,
 };
 
@@ -98,6 +99,11 @@ static void     ibus_engine_page_up         (IBusEngine         *engine);
 static void     ibus_engine_page_down       (IBusEngine         *engine);
 static void     ibus_engine_cursor_up       (IBusEngine         *engine);
 static void     ibus_engine_cursor_down     (IBusEngine         *engine);
+static void     ibus_engine_candidate_clicked
+                                            (IBusEngine         *engine,
+                                             guint               index,
+                                             guint               button,
+                                             guint               state);
 static void     ibus_engine_property_activate
                                             (IBusEngine         *engine,
                                              const gchar        *prop_name,
@@ -182,6 +188,7 @@ ibus_engine_class_init (IBusEngineClass *klass)
     klass->page_down    = ibus_engine_page_down;
     klass->cursor_up    = ibus_engine_cursor_up;
     klass->cursor_down  = ibus_engine_cursor_down;
+    klass->candidate_clicked    = ibus_engine_candidate_clicked;
     klass->property_activate    = ibus_engine_property_activate;
     klass->property_show        = ibus_engine_property_show;
     klass->property_hide        = ibus_engine_property_hide;
@@ -383,7 +390,7 @@ ibus_engine_class_init (IBusEngineClass *klass)
      * IBusEngine::page-up:
      * @engine: An IBusEngine.
      *
-     * Emitted when the page-up key is pressed.
+     * Emitted when the page-up button is pressed.
      * Implement the member function page_up() in extended class to receive this signal.
      *
      * <note><para>@user_data is not actually a valid parameter. It is displayed because of GtkDoc bug.</para></note>
@@ -402,7 +409,7 @@ ibus_engine_class_init (IBusEngineClass *klass)
      * IBusEngine::page-down:
      * @engine: An IBusEngine.
      *
-     * Emitted when the page-down key is pressed.
+     * Emitted when the page-down button is pressed.
      * Implement the member function page_down() in extended class to receive this signal.
      *
      * <note><para>@user_data is not actually a valid parameter. It is displayed because of GtkDoc bug.</para></note>
@@ -421,7 +428,7 @@ ibus_engine_class_init (IBusEngineClass *klass)
      * IBusEngine::cursor-up:
      * @engine: An IBusEngine.
      *
-     * Emitted when the up cursor key is pressed.
+     * Emitted when the up cursor button is pressed.
      * Implement the member function cursor_up() in extended class to receive this signal.
      *
      * <note><para>@user_data is not actually a valid parameter. It is displayed because of GtkDoc bug.</para></note>
@@ -440,7 +447,7 @@ ibus_engine_class_init (IBusEngineClass *klass)
      * IBusEngine::cursor-down:
      * @engine: An IBusEngine.
      *
-     * Emitted when the down cursor key is pressed.
+     * Emitted when the down cursor button is pressed.
      * Implement the member function cursor_down() in extended class to receive this signal.
      *
      * <note><para>@user_data is not actually a valid parameter. It is displayed because of GtkDoc bug.</para></note>
@@ -456,6 +463,28 @@ ibus_engine_class_init (IBusEngineClass *klass)
             0);
 
     /**
+     * IBusEngine::candidate-clicked:
+     * @engine: An IBusEngine.
+     *
+     * Emitted when candidate on lookup table is clicked.
+     * Implement the member function candidate_clicked() in extended class to receive this signal.
+     *
+     * <note><para>@user_data is not actually a valid parameter. It is displayed because of GtkDoc bug.</para></note>
+     */
+    engine_signals[CANDIDATE_CLICKED] =
+        g_signal_new (I_("candidate-clicked"),
+            G_TYPE_FROM_CLASS (gobject_class),
+            G_SIGNAL_RUN_LAST,
+            G_STRUCT_OFFSET (IBusEngineClass, candidate_clicked),
+            NULL, NULL,
+            ibus_marshal_VOID__UINT_UINT_UINT,
+            G_TYPE_NONE,
+            3,
+            G_TYPE_UINT,
+            G_TYPE_UINT,
+            G_TYPE_UINT);
+
+    /**
      * IBusEngine::property-activate:
      * @engine: An IBusEngine.
      *
@@ -648,7 +677,6 @@ ibus_engine_ibus_message (IBusEngine     *engine,
         return TRUE;
     }
 
-
     if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "ProcessKeyEvent")) {
         guint keyval, state;
         gboolean retval;
@@ -682,12 +710,50 @@ ibus_engine_ibus_message (IBusEngine     *engine,
     _keypress_fail:
         error_message = ibus_message_new_error_printf (message,
                         DBUS_ERROR_INVALID_ARGS,
-                        "%s.%s: Can not match signature (ubu) of method",
+                        "%s.%s: Can not match signature (uu) of method",
                         IBUS_INTERFACE_ENGINE, "ProcessKeyEvent");
         ibus_connection_send (connection, error_message);
         ibus_message_unref (error_message);
         return TRUE;
     }
+    else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "CandidateClicked")) {
+        guint index, button, state;
+        gboolean retval;
+        IBusError *error = NULL;
+
+        retval = ibus_message_get_args (message,
+                                        &error,
+                                        G_TYPE_UINT, &index,
+                                        G_TYPE_UINT, &button,
+                                        G_TYPE_UINT, &state,
+                                        G_TYPE_INVALID);
+
+        if (!retval)
+            goto _candidate_clicked_fail;
+
+        retval = FALSE;
+        g_signal_emit (engine,
+                       engine_signals[CANDIDATE_CLICKED],
+                       0,
+                       index,
+                       button,
+                       state,
+                       &retval);
+
+        return_message = ibus_message_new_method_return (message);
+        ibus_connection_send (connection, return_message);
+        ibus_message_unref (return_message);
+        return TRUE;
+
+    _candidate_clicked_fail:
+        error_message = ibus_message_new_error_printf (message,
+                        DBUS_ERROR_INVALID_ARGS,
+                        "%s.%s: Can not match signature (uuu) of method",
+                        IBUS_INTERFACE_ENGINE, "CandidateClicked");
+        ibus_connection_send (connection, error_message);
+        ibus_message_unref (error_message);
+        return TRUE;
+    }
     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyActivate")) {
         gchar *name;
         guint state;
@@ -950,6 +1016,15 @@ ibus_engine_cursor_down (IBusEngine *engine)
 }
 
 static void
+ibus_engine_candidate_clicked (IBusEngine *engine,
+                               guint       index,
+                               guint       button,
+                               guint       state)
+{
+    // g_debug ("candidate-clicked");
+}
+
+static void
 ibus_engine_property_activate (IBusEngine  *engine,
                                const gchar *prop_name,
                                guint        prop_state)
index 42937a7..43730af 100644 (file)
@@ -115,10 +115,17 @@ struct _IBusEngineClass {
                                      const gchar    *prop_name);
     void        (* property_hide)   (IBusEngine     *engine,
                                      const gchar    *prop_name);
+    void        (* candidate_clicked)
+                                    (IBusEngine     *engine,
+                                     guint           index,
+                                     guint           button,
+                                     guint           state);
+
+
 
     /*< private >*/
     /* padding */
-    gpointer pdummy[9];
+    gpointer pdummy[8];
 };
 
 GType        ibus_engine_get_type       (void);
index 37eedc2..ca7d07b 100644 (file)
@@ -10,6 +10,7 @@ BOOL:UINT,UINT
 BOOL:ULONG
 VOID:INT,INT,INT,INT
 VOID:UINT,UINT
+VOID:UINT,UINT,UINT
 VOID:OBJECT,UINT,BOOL
 VOID:OBJECT,BOOL
 VOID:BOXED,BOOL
index 5a71e1e..479dc7a 100644 (file)
@@ -19,6 +19,7 @@
 # Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 # Boston, MA  02111-1307  USA
 
+import operator
 import gtk
 import gtk.gdk as gdk
 import gobject
@@ -26,24 +27,43 @@ import pango
 import ibus
 from ibus._gtk import PangoAttrList
 
-class Label(gtk.Label): pass
+class EventBox(gtk.EventBox):
+    def __init__(self):
+        super(EventBox, self).__init__()
+        self.connect("realize", self.__realize_cb)
+
+    def __realize_cb(self, widget):
+        widget.window.set_cursor(gdk.Cursor(gdk.HAND2))
+
+gobject.type_register(EventBox, "IBusEventBox")
+
+class Label(gtk.Label):
+    pass
 gobject.type_register(Label, "IBusPanelLabel")
 
 class HSeparator(gtk.HBox):
-    def __init__ (self):
-        gtk.HBox.__init__ (self)
+    def __init__(self):
+        super(HSeparator, self).__init__()
         self.pack_start(gtk.HSeparator(), True, True, 4)
 
 class VSeparator(gtk.VBox):
-    def __init__ (self):
-        gtk.VBox.__init__ (self)
+    def __init__(self):
+        super(VSeparator, self).__init__()
         self.pack_start(gtk.VSeparator(), True, True, 4)
 
 class CandidateArea(gtk.HBox):
+    __gsignals__ = {
+        "candidate-clicked" : (
+            gobject.SIGNAL_RUN_FIRST,
+            gobject.TYPE_NONE,
+            (gobject.TYPE_UINT, gobject.TYPE_UINT, gobject.TYPE_UINT )),
+    }
+
     def __init__ (self, orientation):
         gtk.HBox.__init__ (self)
         self.__orientation = orientation
         self.__labels = []
+        self.__candidates = []
         self.__create_ui()
 
     def __create_ui(self):
@@ -56,41 +76,49 @@ class CandidateArea(gtk.HBox):
             self.pack_start(VSeparator(), False, False, 0)
             self.pack_start(self.__vbox2, True, True, 4)
 
-        for i in xrange(0, 16):
-            if i < 10:
-                label1 = Label("%d." % ((i + 1) % 10))
-            else:
-                label1 = Label("%c." % chr(97 + i - 10))
+        for i in range(0, 16):
+            label1 = Label("%c." % ("1234567890abcdef"[i]))
             label1.set_alignment(0.0, 0.5)
-            label1.set_no_show_all(True)
+            label1.show()
 
             label2 = Label()
             label2.set_alignment(0.0, 0.5)
-            label2.set_no_show_all(True)
+            label1.show()
 
             if self.__orientation == gtk.ORIENTATION_VERTICAL:
                 label1.set_property("xpad", 8)
                 label2.set_property("xpad", 8)
-                self.__vbox1.pack_start(label1, False, False, 2)
-                self.__vbox2.pack_start(label2, False, False, 2)
+                ebox1 = EventBox()
+                ebox1.set_no_show_all(True)
+                ebox1.add(label1)
+                ebox2 = EventBox()
+                ebox2.set_no_show_all(True)
+                ebox2.add(label2)
+                self.__vbox1.pack_start(ebox1, False, False, 2)
+                self.__vbox2.pack_start(ebox2, False, False, 2)
+                self.__candidates.append((ebox1, ebox2))
             else:
                 hbox = gtk.HBox()
+                hbox.show()
                 hbox.pack_start(label1, False, False, 1)
                 hbox.pack_start(label2, False, False, 1)
-                self.pack_start(hbox, False, False, 4)
+                ebox = EventBox()
+                ebox.set_no_show_all(True)
+                ebox.add(hbox)
+                self.pack_start(ebox, False, False, 4)
+                self.__candidates.append((ebox,))
 
             self.__labels.append((label1, label2))
 
-        self.__labels[0][0].show()
-        self.__labels[0][1].show()
+        cursor = gdk.Cursor(gdk.HAND1)
+        for i, ws in enumerate(self.__candidates):
+            for w in ws:
+                w.connect("button-press-event", lambda w, e, i:self.emit("candidate-clicked", i, e.button, e.state), i)
 
     def set_labels(self, labels):
         if not labels:
             for i in xrange(0, 16):
-                if i < 10:
-                    self.__labels[i][0].set_text("%d." % ((i + 1) % 10))
-                else:
-                    self.__labels[i][0].set_text("%c." % chr(97 + i - 10))
+                self.__labels[i][0].set_text("%c." % ("1234567890abcdef"[i]))
                 self.__labels[i][0].set_property("attributes", None)
             return
 
@@ -104,8 +132,7 @@ class CandidateArea(gtk.HBox):
 
     def set_candidates(self, candidates, focus_candidate = 0, show_cursor = True):
         assert len(candidates) <= len(self.__labels)
-        i = 0
-        for text, attrs in candidates:
+        for i, (text, attrs) in enumerate(candidates):
             if i == focus_candidate and show_cursor:
                 if attrs == None:
                     attrs = pango.AttrList()
@@ -118,21 +145,13 @@ class CandidateArea(gtk.HBox):
                 attrs.insert(attr)
 
             self.__labels[i][1].set_text(text)
-            self.__labels[i][1].set_property("attributes", attrs)
-            self.__labels[i][0].show()
             self.__labels[i][1].show()
+            self.__labels[i][1].set_property("attributes", attrs)
+            for w in self.__candidates[i]:
+                w.show()
 
-            i += 1
-
-        for label1, label2 in self.__labels[max(1, len(candidates)):]:
-            label1.hide()
-            label2.hide()
-
-        if len(candidates) == 0:
-            self.__labels[0][0].set_text("")
-            self.__labels[0][1].set_text("")
-        else:
-            self.__labels[0][0].set_text("1.")
+        for w in reduce(operator.add, self.__candidates[len(candidates):]):
+            w.hide()
 
 class CandidatePanel(gtk.VBox):
     __gproperties__ = {
@@ -160,6 +179,10 @@ class CandidatePanel(gtk.VBox):
             gobject.SIGNAL_RUN_FIRST,
             gobject.TYPE_NONE,
             ()),
+        "candidate-clicked" : (
+            gobject.SIGNAL_RUN_FIRST,
+            gobject.TYPE_NONE,
+            (gobject.TYPE_UINT, gobject.TYPE_UINT, gobject.TYPE_UINT)),
     }
 
     def __init__ (self):
@@ -222,6 +245,7 @@ class CandidatePanel(gtk.VBox):
         # create candidates area
         self.__candidate_area = CandidateArea(self.__orientation)
         self.__candidate_area.set_no_show_all(True)
+        self.__candidate_area.connect("candidate-clicked", lambda x, i, b, s: self.emit("candidate-clicked", i, b, s))
         self.update_lookup_table(self.__lookup_table, self.__lookup_table_visible)
 
         # create state label
index fde3299..037fca7 100644 (file)
@@ -96,6 +96,8 @@ class Panel(ibus.PanelBase):
                         lambda widget: self.page_up())
         self.__candidate_panel.connect("page-down",
                         lambda widget: self.page_down())
+        self.__candidate_panel.connect("candidate-clicked",
+                        lambda widget, index, button, state: self.candidate_clicked(index, button, state))
 
 
         self.__status_icon = gtk.StatusIcon()