WIP implement register_properties and set_property
authorPeng Huang <shawn.p.huang@gmail.com>
Mon, 28 Nov 2011 23:08:27 +0000 (18:08 -0500)
committerPeng Huang <shawn.p.huang@gmail.com>
Tue, 21 Feb 2012 16:50:22 +0000 (11:50 -0500)
ui/gtk3/Makefile.am
ui/gtk3/panel.vala
ui/gtk3/property.vala [new file with mode: 0644]

index ac6c3ac..f94816a 100644 (file)
@@ -75,6 +75,7 @@ ibus_ui_gtk3_SOURCES = \
        keybindingmanager.vala \
        panel.vala \
        pango.vala \
+       property.vala \
        separator.vala \
        switcher.vala \
        grabkeycode.c \
index d87de2f..d53c5f4 100644 (file)
@@ -32,6 +32,7 @@ class Panel : IBus.PanelService {
     private IBus.EngineDesc[] m_engines;
     private CandidatePanel m_candidate_panel;
     private Switcher m_switcher;
+    private PropertyManager m_property_manager;
 
     public Panel(IBus.Bus bus) {
         assert(bus.is_connected());
@@ -68,6 +69,8 @@ class Panel : IBus.PanelService {
             handle_engine_switch(e, true);
         });
 
+        m_property_manager = new PropertyManager();
+
     }
 
     private void switch_engine(int i) {
@@ -120,7 +123,18 @@ class Panel : IBus.PanelService {
     private void status_icon_popup_menu(Gtk.StatusIcon status_icon,
                                         uint button,
                                         uint activate_time) {
-        debug("popup-menu %u %u", button, activate_time);
+        Gtk.Menu menu = m_property_manager.get_menu();
+        if (menu == null)
+            return;
+
+        menu.show_all();
+        menu.set_take_focus(false);
+
+        menu.popup(null,
+                   null,
+                   m_status_icon.position_menu,
+                   0,
+                   Gtk.get_current_event_time());
     }
 
     private void status_icon_activate(Gtk.StatusIcon status_icon) {
@@ -168,6 +182,14 @@ class Panel : IBus.PanelService {
         // debug("focus_out ic=%s", input_context_path);
     }
 
+    public override void register_properties(IBus.PropList props) {
+        m_property_manager.set_properties(props);
+    }
+
+    public override void update_property(IBus.Property prop) {
+        debug("update property");
+    }
+
     public override void update_preedit_text(IBus.Text text,
                                              uint cursor_pos,
                                              bool visible) {
diff --git a/ui/gtk3/property.vala b/ui/gtk3/property.vala
new file mode 100644 (file)
index 0000000..1192a64
--- /dev/null
@@ -0,0 +1,207 @@
+/* vim:set et sts=4 sw=4:
+ *
+ * ibus - The Input Bus
+ *
+ * Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or(at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+using IBus;
+using GLib;
+using Gtk;
+
+
+public class PropertyManager {
+    private IBus.PropList m_props;
+    private GLib.HashTable<string, IPropItem> m_prop_map =
+        new GLib.HashTable<string, IPropItem>(GLib.str_hash, null);
+    private Gtk.Menu m_menu;
+
+    public void ProperyManager() {
+    }
+
+    public void set_properties(IBus.PropList props) {
+        m_props = props;
+        m_prop_map.remove_all();
+        if (m_menu != null)
+            m_menu.destroy();
+        m_menu = create_menu(props);
+    }
+
+    public Gtk.Menu? get_menu() {
+        return m_menu;
+    }
+
+    public Gtk.Menu? create_menu(IBus.PropList props) {
+        Gtk.Menu menu = new Gtk.Menu();
+        int i = 0;
+        GLib.SList<PropRadioMenuItem> group = 
+            new GLib.SList<PropRadioMenuItem>();
+        while (true) {
+            IBus.Property prop = props.get(i);
+            if (prop == null)
+                break;
+            i++;
+            
+            IPropItem item = null;
+            switch(prop.get_prop_type()) {
+                case IBus.PropType.NORMAL:
+                    item = new PropImageMenuItem(prop);
+                    break;
+                case IBus.PropType.TOGGLE:
+                    item = new PropCheckMenuItem(prop);
+                    break;
+                case IBus.PropType.RADIO:
+                    {
+                        PropRadioMenuItem radio = new PropRadioMenuItem(prop, group);
+                        group.append(radio);
+                        item = radio;
+                    }
+                    break;
+                case IBus.PropType.MENU:
+                    {
+                        var menuitem = new PropImageMenuItem(prop);
+                        item = menuitem;
+                        Gtk.Menu submenu = create_menu(prop.get_sub_props());
+                        menuitem.set_submenu(submenu);
+                    }
+                    break;
+                case IBus.PropType.SEPARATOR:
+                    item = new PropSeparatorMenuItem(prop);
+                    break;
+                default:
+                    warning("unknown property type %d", (int)prop.get_prop_type());
+                    break;
+            }
+            if (item != null) {
+                m_prop_map.insert(prop.get_key(), item);
+                menu.append(item as Gtk.MenuItem);
+                // TODO
+                // item.property_activate.connect
+            }
+        }
+        if (i == 0)
+            return null;
+        return menu;
+    }
+
+    public void update_property(IBus.Property prop) {
+        assert(prop != null);
+        
+        IPropItem item = m_prop_map.lookup(prop.get_key());
+        return_if_fail(item != null);
+        item.update_property(prop);
+    }
+}
+
+public interface IPropItem : GLib.Object {
+    public abstract void update_property(IBus.Property prop);
+    public signal void property_activate(string key, int state);
+}
+
+public class PropImageMenuItem : Gtk.ImageMenuItem, IPropItem {
+    private IBus.Property m_property;
+    public PropImageMenuItem(IBus.Property property) {
+        assert(property != null);
+
+        m_property = property;
+        set_no_show_all(true);
+        sync();
+    }
+
+    public void update_property(IBus.Property property) {
+        m_property.set_label(property.get_label());
+        m_property.set_icon(property.get_icon());
+        m_property.set_visible(property.get_visible());
+        m_property.set_sensitive(property.get_sensitive());
+        m_property.set_tooltip(property.get_tooltip());
+        m_property.set_state(property.get_state());
+        sync();
+    }
+
+    private void sync() {
+        set_label(m_property.get_label().get_text());
+        set_icon(m_property.get_icon());
+        set_visible(m_property.get_visible());
+        set_sensitive(m_property.get_sensitive());
+    }
+
+    private void set_icon(string icon) {
+        int width, height;
+        Gtk.icon_size_lookup(Gtk.IconSize.MENU, out width, out height);
+        set_image(new IconWidget(icon, width));
+    }
+
+    public override void activate() {
+        property_activate(m_property.get_key(), m_property.get_state());
+    }
+}
+
+public class PropCheckMenuItem : Gtk.RadioMenuItem, IPropItem {
+    private IBus.Property m_property;
+    public PropCheckMenuItem(IBus.Property property) {
+        assert(property != null);
+
+        m_property = property;
+        set_no_show_all(true);
+        sync();
+    }
+
+    public void update_property(IBus.Property property) {
+        m_property.set_label(property.get_label());
+        m_property.set_icon(property.get_icon());
+        m_property.set_visible(property.get_visible());
+        m_property.set_sensitive(property.get_sensitive());
+        m_property.set_tooltip(property.get_tooltip());
+        m_property.set_state(property.get_state());
+        sync();
+    }
+
+    private void sync() {
+        set_label(m_property.get_label().get_text());
+        set_visible(m_property.get_visible());
+        set_sensitive(m_property.get_sensitive());
+        set_active(m_property.get_state() == IBus.PropState.CHECKED);
+    }
+
+    public override void toggled() {
+        IBus.PropState new_state = 
+            get_active() ? IBus.PropState.CHECKED : IBus.PropState.UNCHECKED;
+        if (m_property.get_state() != new_state) {
+            m_property.set_state(new_state);
+            property_activate(m_property.get_key(), m_property.get_state());
+        }
+    }
+}
+
+public class PropRadioMenuItem : PropCheckMenuItem {
+    public PropRadioMenuItem(IBus.Property property, GLib.SList<PropRadioMenuItem> group) {
+        base(property);
+        set_group(group);
+    }
+}
+
+public class PropSeparatorMenuItem : Gtk.SeparatorMenuItem, IPropItem {
+    private IBus.Property m_property;
+    public PropSeparatorMenuItem(IBus.Property property) {
+        assert(property != null);
+        m_property = property;
+    }
+
+    public void update_property(IBus.Property property) {
+    }
+}