diff options
Diffstat (limited to 'uitools/Menu.py')
-rw-r--r-- | uitools/Menu.py | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/uitools/Menu.py b/uitools/Menu.py new file mode 100644 index 0000000..8b64615 --- /dev/null +++ b/uitools/Menu.py @@ -0,0 +1,245 @@ +#!/usr/bin/env python +###################################################################### +# Provide classes to simplify creating menubars, pulldown menus, etc. +# +# Mitch Chapman +#--------------------------------------------------------------------- +# $Log: Menu.py,v $ +# Revision 1.1 1996/12/01 22:58:54 mchapman +# Initial revision +# +###################################################################### + +__version__ = "$Revision: 1.1 $" + +import Tkinter; Tk=Tkinter +import KWDict, string + +###################################################################### +# Convert a string of the form "&Something" to a tuple: +# ("Something", 0) +# indicating that the first letter of "Something" should be +# underlined. If no "&" occurs inside the string, the second tuple +# item will be None. +###################################################################### +def findUnderline(title): + ul = None + i = string.find(title, "&") + if i >= 0: + ul = i + title = title[:ul] + title[ul+1:] + return title, ul + + +###################################################################### +# This class represents a menubar, w. default relief, etc. +###################################################################### +class Menubar(Tk.Frame): + ################################################################## + # Create a new instance. + ################################################################## + def __init__(self, master=None, **kw): + opts = {'relief':'raised', 'bd':2} + for k,v in kw.items(): + opts[k] = v + apply(Tk.Frame.__init__, (self, master), opts) + Tk.Pack.config(self, side='top', fill='x') + + +###################################################################### +# This class represents a menu item in a Tk menu. +###################################################################### +class Item: + ################################################################## + # Create a new instance. + # master is the pane to which to append the new item. + # title is the text which will appear inside the menu item. It + # also determines what sort of menu item will be created. See + # below for details. + # cmd is the optional callback for this menu item. + # items specifies any items to be displayed in cascaded menus. + ################################################################## + def __init__(self, master, title, cmd=None, *items): + self.master = master + self.title = title + + if title[0] == "-": + master.add_separator() + self.index = master.index('last') + return + + submenu = None + createFn = master.add_command + prefix = title[0:2] + if prefix == "c_": + createFn = master.add_checkbutton + elif prefix == "r_": + createFn = master.add_radiobutton + elif prefix == "m_": + createFn = master.add_cascade + submenu = Pane(master) + apply(submenu.addItems, items) + else: + title = "x_" + title + + title, ul = findUnderline(title[2:]) + + # XXX no means is provided to associate a Tk variable with a + # radio button or a check button. + apply(createFn, (), KWDict.dict(label=title, command=cmd, + underline=ul, menu=submenu)) + self.index = master.index('last') + + ################################################################## + # Enable or disable an item. + ################################################################## + def enable(self, doEnable=1): + if doEnable: + newstate = 'normal' + else: + newstate = 'disabled' + + try: + # NOTE: This won't work for tear-off entries, or for separators. + self.master.tk.call(self.master._w, 'entryconfigure', self.index, + '-state', newstate) + except Tk.TclError: pass + +###################################################################### +# This class represents a pulldown menu. +###################################################################### +class Pulldown: + ################################################################## + # Create a new Pulldown menu. + # Each additional item should be a list consisting of menu + # item string and optional callback. Menu item strings are + # interpreted as indicated in parseMenuStr(). + # Returns the menu button which posts the new menu. + ################################################################## + def __init__(self, master, title, *items, **kw): + self.master = master + + packside='left' + if kw and 'side' in kw.keys(): + packside=kw['side'] + + # Create the menu button. + title, ul = findUnderline(title) + btnKeywords = KWDict.dict(text=title, underline=ul) + btn = apply(Tk.Menubutton, (master,), btnKeywords) + + # Create the menu pane and associate it with the button. + menu = btn.menu = Pane(btn) + btn['menu'] = menu + apply(menu.addItems, items) + + btn.pack(side=packside, padx='2m') + + +###################################################################### +# This class extends the Tkinter Menu class with convenience methods +# for enabling/disabling menu items and for support of popup menus. +###################################################################### +class Pane(Tk.Menu): + ################################################################## + # Init a new instance. + ################################################################## + def __init__(self, master=None, **kw): + apply(Tk.Menu.__init__, (self, master), kw) + self.items = [] + + ################################################################## + # Add items to a menu Pane. + ################################################################## + def addItems(self, *newItems): + # Create a menu item for each described item. + for item in newItems: + self.items.append(apply(Item, (self,) + tuple(item))) + + ################################################################## + # Enable or disable a menu item. + # If enable is non-zero, then the menu item is enabled; otherwise + # it is disabled. + ################################################################## + def enable(self, index, enable=1): + self.items[index].enable(enable) + + ################################################################## + # Pop up a menu pane -- + # useful when Pane is being used as a popup menu. + ################################################################## + def tk_popup(self, event=None): + x, y = 0, 0 + if event: + x, y = event.x_root, event.y_root + self.tk.call('tk_popup', self._w, x, y) + + +###################################################################### +# Mainline for testing +###################################################################### +def main(): + import TkDlgWrapper; TkDlg=TkDlgWrapper + + # To demonstrate, here's a simple file editor. + f = Tk.Frame() + m = Menubar(f) + t = Tk.Text(f) + + # Here are the file types which the open/save dialogs will recognize. + filetypes = (("Python", ".py"), ("Text", ".txt"), ("All Files", "*")) + openFile = TkDlg.OpenFile(f, defaultextension=".py", + filetypes=filetypes) + saveFile = TkDlg.SaveFile(f, defaultextension=".py", + filetypes=filetypes) + + # Here's an example of a popup menu. It should appear when + # you click mouse button 3 inside the text area. + textPopup = Pane(f, tearoff='0') + textPopup.addItems(["Cut"], ["Copy"], ["Paste"], ["Clear"]) + # Initially, disable all of the items. Enable them when a file + # is actually opened. + for item in textPopup.items: + item.enable(0) + t.bind("<3>", textPopup.tk_popup) + + def openAFile(openDlg = openFile, text=t, popup=textPopup): + filename = openDlg.show() + if filename: + text.delete('1.0', 'end') + inf = open(filename) + text.insert('end', inf.read()) + inf.close() + text.winfo_toplevel().title("Menu Example:%s" % filename) + # Enable the popup menu items. + for item in popup.items: + item.enable(1) + + def saveAFile(saveDlg = saveFile, text=t): + filename = saveDlg.show() + if filename: + outf = open(filename, "w") + outf.write(text.get('1.0', 'end')) + outf.close() + text.winfo_toplevel().title("Menu Example:%s" % filename) + + # Keyboard menu traversal appears to be broken under Tk 4.2 Try using + # keyboard traversal in the tk4.2 library's demo subdirectory... + fileMenu = Pulldown(m, "&File", + ["&Open...", openAFile], + ["Save &As...", saveAFile], + ["----"], + ["E&xit", m.quit]) + + helpMenu = Pulldown(m, "&Help", + ["&About"], + side='right') + + m.pack() + t.pack() + f.pack() + f.master.title("Menu Example") + f.mainloop() + +if __name__ == "__main__": + main() |