def show_menu(self, event):
     self.menu = Menu(gtk_menu=True)
     # Since some application menus doesn't seem to be
     # update, let's try to fetch just in case.
     self.dbusmenu.fetch_layout()
     
     self.menu.add_quicklist(self.dbusmenu.layout)
     self.sids = {}
     self.sids[0] = self.menu.connect("item-activated",
                                      self.on_menuitem_activated)
     #~ self.sids[1] = self.menu.connect("item-hovered",
                                      #~ self.__on_menuitem_hovered)
     #~ self.sids[2] = self.menu.connect("menu-resized",
                                      #~ self.__on_menu_resized)
     gtkmenu = self.menu.get_menu()
     self.sd_sid = gtkmenu.connect("selection-done", self.menu_closed)
     gtkmenu.popup(None, None, self.position_menu,
                   event.button, event.time)
class AppIndicator(gtk.EventBox):
    def __init__(self, applet, icon_name, position, address, obj,
                  icon_path, label, labelguide,
                  accessibledesc, hint=None, title=None):
        self.applet_r = weakref.ref(applet)
        self.menu = None
        gtk.EventBox.__init__(self)
        self.set_visible_window(False)
        self.box = None
        self.icon = gtk.Image()
        self.icon_name = None
        self.icon_pixbufs = {}
        self.label = gtk.Label()
        self.repack()
        self.icon_themepath = icon_path
        self.on_icon_changed(icon_name, None)
        self.on_label_changed(label, labelguide)
        
        # Older versions of application-indicator-service doesn't give a title.
        self.title = title
        
        self.dbusmenu = DBusMenu(self, address, obj)
        
        self.show_all()
        self.connect("button-press-event", self.on_button_press_event)

    def repack(self):
        if self.box is not None:
            self.box.remove(self.icon)
            self.box.remove(self.label)
            self.remove(self.box)
            self.box.destroy()
        if self.applet_r().get_position() in ("left", "right"):
            self.box = gtk.VBox()
            self.label.set_angle(270)
        else:
            self.box = gtk.HBox()
            self.label.set_angle(0)
        self.box.pack_start(self.icon)
        self.box.pack_start(self.label)
        self.add(self.box)

    def on_button_press_event(self, widget, event):
        self.show_menu(event)

    def show_menu(self, event):
        self.menu = Menu(gtk_menu=True)
        # Since some application menus doesn't seem to be
        # update, let's try to fetch just in case.
        self.dbusmenu.fetch_layout()
        
        self.menu.add_quicklist(self.dbusmenu.layout)
        self.sids = {}
        self.sids[0] = self.menu.connect("item-activated",
                                         self.on_menuitem_activated)
        #~ self.sids[1] = self.menu.connect("item-hovered",
                                         #~ self.__on_menuitem_hovered)
        #~ self.sids[2] = self.menu.connect("menu-resized",
                                         #~ self.__on_menu_resized)
        gtkmenu = self.menu.get_menu()
        self.sd_sid = gtkmenu.connect("selection-done", self.menu_closed)
        gtkmenu.popup(None, None, self.position_menu,
                      event.button, event.time)

    def menu_closed(self, *args):
        if self.menu is not None:
            for key in self.sids.keys():
                sid = self.sids.pop(key)
                self.menu.disconnect(sid)
            self.sd_sid = self.menu.get_menu().disconnect(self.sd_sid)
            self.menu.delete_menu()
            self.menu = None

    def on_menuitem_activated(self, menu_item, identifier):
        if identifier.startswith("unity_"):
            identifier = int(identifier.rsplit("_", 1)[-1])
            data = dbus.String("", variant_level=1)
            t = dbus.UInt32(0)
            self.dbusmenu.send_event(identifier, "clicked", data, t)

    def on_icon_changed(self, icon_name=None, icon_desc=None):
        if self.icon_name == icon_name:
            return
        if icon_name is not None:
            self.icon_name = icon_name
        self.update_icon()
        
    def update_icon(self):
        if self.icon_name in self.icon_pixbufs:
            pixbuf = self.icon_pixbufs[self.icon_name]
        else:
            pixbuf = self.get_icon(self.icon_name)
            self.icon_pixbufs[self.icon_name] = pixbuf
        self.icon.set_from_pixbuf(pixbuf)
        
    def get_icon(self, icon_name):
        if icon_name.startswith("/") and os.path.exists(icon_name):
            pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(icon_name,
                                                          ICONSIZE, 
                                                          ICONSIZE)
        else:
            icon_theme = gtk.icon_theme_get_default()
            if self.icon_themepath != "" and \
               os.path.exists(self.icon_themepath):
                icon_theme.prepend_search_path(self.icon_themepath)
            pixbuf = icon_theme.load_icon(self.icon_name, ICONSIZE, 0)
        return pixbuf

    def on_icon_themepath_changed(self, path):
        if self.icon_themepath == path:
            return
        self.icon_themepath = path
        #reset icon_pixbufs so that the icons will be reloaded.
        self.icon_pixbufs = {}
        # Update the icon
        if self.icon_name is not None:
            self.update_icon()

    def on_label_changed(self, label, guide):
        self.label.set_text(label)

    def on_title_changed(self, title):
        self.title = title

    def position_menu(self, menu):
        x, y = self.get_window().get_origin()
        a = self.get_allocation()
        w, h = menu.size_request()
        size = self.applet_r().get_size()
        if self.applet_r().get_position() == "left":
            x += size
            y += a.y
        if self.applet_r().get_position() == "right":
            x -= w
            y += a.y
        if self.applet_r().get_position() == "top":
            x += a.x
            y += size
        if self.applet_r().get_position() == "bottom":
            x += a.x
            y -= h
        screen = self.get_window().get_screen()
        if y + h > screen.get_height():
                y = screen.get_height() - h
        if x + w >= screen.get_width():
                x = screen.get_width() - w
        return (x, y, False)