summaryrefslogtreecommitdiff
path: root/uitools/Menu.py
diff options
context:
space:
mode:
Diffstat (limited to 'uitools/Menu.py')
-rw-r--r--uitools/Menu.py245
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()