From 59500bdeb5ecaa7324c8a910fe633e6a25dc7252 Mon Sep 17 00:00:00 2001 From: Peng Huang Date: Fri, 12 Jun 2009 09:54:47 +0800 Subject: [PATCH] Support mouse click on lookup table. --- bus/engineproxy.c | 18 ++++++++- bus/engineproxy.h | 4 ++ bus/inputcontext.c | 68 ++++++++++++++------------------ bus/inputcontext.h | 4 ++ bus/panelproxy.c | 98 +++++++++++++++++++++++++++++------------------ bus/panelproxy.h | 4 ++ ibus/engine.py | 3 ++ ibus/interface/iengine.py | 8 +++- ibus/interface/ipanel.py | 3 ++ ibus/panel.py | 3 ++ src/ibusengine.c | 87 ++++++++++++++++++++++++++++++++++++++--- src/ibusengine.h | 9 ++++- src/ibusmarshalers.list | 1 + ui/gtk/candidatepanel.py | 96 +++++++++++++++++++++++++++++----------------- ui/gtk/panel.py | 2 + 15 files changed, 284 insertions(+), 124 deletions(-) diff --git a/bus/engineproxy.c b/bus/engineproxy.c index e78fbcf..5a2f841 100644 --- a/bus/engineproxy.c +++ b/bus/engineproxy.c @@ -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) diff --git a/bus/engineproxy.h b/bus/engineproxy.h index 2206c9a..8d1067c 100644 --- a/bus/engineproxy.h +++ b/bus/engineproxy.h @@ -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, diff --git a/bus/inputcontext.c b/bus/inputcontext.c index 511ebf5..0881581 100644 --- a/bus/inputcontext.c +++ b/bus/inputcontext.c @@ -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); } } diff --git a/bus/inputcontext.h b/bus/inputcontext.h index 537cbef..f627b2d 100644 --- a/bus/inputcontext.h +++ b/bus/inputcontext.h @@ -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); diff --git a/bus/panelproxy.c b/bus/panelproxy.c index 1d24b2f..d19c9be 100644 --- a/bus/panelproxy.c +++ b/bus/panelproxy.c @@ -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); } } diff --git a/bus/panelproxy.h b/bus/panelproxy.h index 0ecc4a7..039db78 100644 --- a/bus/panelproxy.h +++ b/bus/panelproxy.h @@ -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, diff --git a/ibus/engine.py b/ibus/engine.py index f8c0447..15ffe8f 100644 --- a/ibus/engine.py +++ b/ibus/engine.py @@ -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() diff --git a/ibus/interface/iengine.py b/ibus/interface/iengine.py index 63d6c0e..21b0305 100644 --- a/ibus/interface/iengine.py +++ b/ibus/interface/iengine.py @@ -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 diff --git a/ibus/interface/ipanel.py b/ibus/interface/ipanel.py index e5d174c..21f2647 100644 --- a/ibus/interface/ipanel.py +++ b/ibus/interface/ipanel.py @@ -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 diff --git a/ibus/panel.py b/ibus/panel.py index 9a34109..8aa49d8 100644 --- a/ibus/panel.py +++ b/ibus/panel.py @@ -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) diff --git a/src/ibusengine.c b/src/ibusengine.c index d37cb3c..f71b515 100644 --- a/src/ibusengine.c +++ b/src/ibusengine.c @@ -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. * * @user_data is not actually a valid parameter. It is displayed because of GtkDoc bug. @@ -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. * * @user_data is not actually a valid parameter. It is displayed because of GtkDoc bug. @@ -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. * * @user_data is not actually a valid parameter. It is displayed because of GtkDoc bug. @@ -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. * * @user_data is not actually a valid parameter. It is displayed because of GtkDoc bug. @@ -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. + * + * @user_data is not actually a valid parameter. It is displayed because of GtkDoc bug. + */ + 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) diff --git a/src/ibusengine.h b/src/ibusengine.h index 42937a7..43730af 100644 --- a/src/ibusengine.h +++ b/src/ibusengine.h @@ -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); diff --git a/src/ibusmarshalers.list b/src/ibusmarshalers.list index 37eedc2..ca7d07b 100644 --- a/src/ibusmarshalers.list +++ b/src/ibusmarshalers.list @@ -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 diff --git a/ui/gtk/candidatepanel.py b/ui/gtk/candidatepanel.py index 5a71e1e..479dc7a 100644 --- a/ui/gtk/candidatepanel.py +++ b/ui/gtk/candidatepanel.py @@ -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 diff --git a/ui/gtk/panel.py b/ui/gtk/panel.py index fde3299..037fca7 100644 --- a/ui/gtk/panel.py +++ b/ui/gtk/panel.py @@ -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() -- 2.7.4