# vim:set et sts=4 sw=4: # # ibus - The Input Bus # # Copyright (c) 2007-2008 Huang Peng # # 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 import gtk import gobject import ibus import icon from propitem import PropItem class Menu (gtk.Menu, PropItem): __gsignals__ = { "property-activate" : ( gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_INT)), } def __init__ (self, prop): gtk.Menu.__init__ (self) PropItem.__init__ (self, prop) self.set_take_focus (False) self.__create_items (self._prop.sub_props) self.show_all () self.set_sensitive (prop.sensitive) def __create_items (self, props): radio_group = None for prop in props: if prop.type == ibus.PROP_TYPE_NORMAL: item = gtk.ImageMenuItem (prop) elif prop.type == ibus.PROP_TYPE_TOGGLE: item = CheckMenuItem (prop) elif prop.type == ibus.PROP_TYPE_RADIO: item = RadioMenuItem (radio_group, prop) radio_group = item elif prop.type == ibus.PROP_TYPE_SEPARATOR: item = SeparatorMenuItem () radio_group = None elif prop.type == ibus.PROP_TYPE_MENU: item = gtk.ImageMenuItem (prop) item.set_submenu (Menu (prop)) else: assert Fasle item.set_sensitive (prop.sensitive) if prop.visible: item.set_no_show_all (False) item.show () else: item.set_no_show_all (True) item.hide () item.connect ("property-activate", lambda w,n,s: self.emit ("property-activate", n, s)) self.append (item) self._sub_items.append (item) def popup (self, button, active_time, widget): gtk.Menu.popup (self, None, None, menu_position, button, active_time, widget) def _property_clicked (self, item, prop): pass class ImageMenuItem (gtk.ImageMenuItem, PropItem): __gsignals__ = { "property-activate" : ( gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_INT)), } def __init__ (self, prop): gtk.ImageMenuItem.__init__ (self, label = prop.label.text) PropItem.__init__ (self, prop) if self._prop.icon: size = gtk.icon_size_lookup(gtk.ICON_SIZE_MENU) self.set_image (icon.IconWidget(prop.icon, size[0])) if self._prop.visible: self.set_no_show_all (False) self.show_all () else: self.set_no_show_all (True) self.hide_all () def do_activate (self): self.emit ("property-activate", self._prop.key, self._prop.state) def property_changed (self): self.set_sensitive (self._prop.sensitive) if self._prop.visible: self.set_no_show_all (False) self.show_all () else: self.set_no_show_all (True) self.hide_all () class CheckMenuItem (gtk.CheckMenuItem, PropItem): __gsignals__ = { "property-activate" : ( gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_INT)), } def __init__ (self, prop): gtk.CheckMenuItem.__init__ (self, label = prop.label.text) PropItem.__init__ (self, prop) self.set_active (self._prop._state == ibus.PROP_STATE_CHECKED) if prop.visible: self.set_no_show_all (False) self.show_all () else: self.set_no_show_all (True) self.hide_all () def do_toggled (self): if self.get_active (): self._prop.state = ibus.PROP_STATE_CHECKED else: self._prop.state = ibus.PROP_STATE_UNCHECKED self.emit ("property-activate", self._prop.key, self._prop.state) def property_changed (self): self.set_active (self._prop.state == ibus.PROP_STATE_CHECKED) self.set_sensitive (self._prop.sensitive) if self._prop.visible: self.set_no_show_all (False) self.show_all () else: self.set_no_show_all (True) self.hide_all () class RadioMenuItem (gtk.RadioMenuItem, PropItem): __gsignals__ = { "property-activate" : ( gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_INT)), } def __init__ (self, group, prop): gtk.RadioMenuItem.__init__ (self, group, label = prop.label.text) PropItem.__init__ (self, prop) self.set_active (self._prop.state == ibus.PROP_STATE_CHECKED) if prop.visible: self.set_no_show_all (False) self.show_all () else: self.set_no_show_all (True) self.hide_all () def property_changed (self): self.set_active (self._prop.state == ibus.PROP_STATE_CHECKED) self.set_sensitive (self._prop.sensitive) if self._prop.visible: self.set_no_show_all (False) self.show_all () else: self.set_no_show_all (True) self.hide_all () def do_toggled (self): if self.get_active (): self._prop.state = ibus.PROP_STATE_CHECKED else: self._prop.state = ibus.PROP_STATE_UNCHECKED self.emit ("property-activate", self._prop.key, self._prop.state) class SeparatorMenuItem (gtk.SeparatorMenuItem, PropItem): __gsignals__ = { "property-activate" : ( gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_INT)), } gobject.type_register (Menu, "IBusMenu") gobject.type_register (ImageMenuItem, "IBusImageMenuItem") gobject.type_register (CheckMenuItem, "IBusCheckMenuItem") gobject.type_register (RadioMenuItem, "IBusRadioMenuItem") gobject.type_register (SeparatorMenuItem, "IBusSeparatorMenuItem") def menu_position (menu, button): screen = button.get_screen () monitor = screen.get_monitor_at_window (button.window) monitor_allocation = screen.get_monitor_geometry (monitor) x, y = button.window.get_origin () x += button.allocation.x y += button.allocation.y menu_width, menu_height = menu.size_request () if x + menu_width >= monitor_allocation.width: x -= menu_width - button.allocation.width elif x - menu_width <= 0: pass else: if x <= monitor_allocation.width * 3 / 4: pass else: x -= menu_width - button.allocation.width if y + button.allocation.height + menu_height >= monitor_allocation.height: y -= menu_height elif y - menu_height <= 0: y += button.allocation.height else: if y <= monitor_allocation.height * 3 / 4: y += button.allocation.height else: y -= menu_height return (x, y, False)