"""Pop-up menus.""" import logging import tkinter as tk import functools class menu(object): """Draws a hierarchical popup menu :param parent: If given, this menu is a leave of the "parent" menu :param leave: If set to True, close this menu when mouse leaves the area (defaults to True) """ def __init__(self, parent=None, leave=True): self.running = True self.parent = parent self._root = parent.root() if parent else tk.Tk() self._root.withdraw() self._menu = tk.Menu(self._root, tearoff=0) self._menu.bind("", self.__on_focus_out) if leave: self._menu.bind("", self.__on_focus_out) elif not parent: self.add_menuitem("close", self.__on_focus_out) self.add_separator() self._menu.bind("", self.release) """Returns the root node of this menu :return: root node """ def root(self): return self._root """Returns the menu :return: menu """ def menu(self): return self._menu def __on_focus_out(self, event=None): self.running = False self._root.destroy() def __on_click(self, callback): self._root.destroy() callback() def release(self, event=None): self.running=False if self.parent: self.parent.release(event) """Adds a cascading submenu to the current menu :param menuitem: label to display for the submenu :param submenu: submenu to show """ def add_cascade(self, menuitem, submenu): self._menu.add_cascade(label=menuitem, menu=submenu.menu()) """Adds an item to the current menu :param menuitem: label to display for the entry :param callback: method to invoke on click """ def add_menuitem(self, menuitem, callback): self._menu.add_command( label=menuitem, command=functools.partial(self.__on_click, callback) ) """Adds a separator to the menu in the current location""" def add_separator(self): self._menu.add_separator() """Shows this menu :param event: i3wm event that triggered the menu (dict that contains "x" and "y" fields) :param offset_x: x-axis offset from mouse position for the menu (defaults to 0) :param offset_y: y-axis offset from mouse position for the menu (defaults to 0) """ def show(self, event, offset_x=0, offset_y=0): try: self._menu.tk_popup(event["x"] + offset_x, event["y"] + offset_y) finally: self._menu.grab_release() while self.running == True: try: self._root.update_idletasks() self._root.update() except: self.running = False try: self._root.destroy() except: pass # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4