Demo/tkinter/matt/menu-all-types-of-entries.py
from Tkinter import *

# some vocabulary to keep from getting confused. This terminology
# is something I cooked up for this file, but follows the man pages
# pretty closely
#
#
#
#       This is a MENUBUTTON
#       V
# +-------------+
# |             |
#
# +------------++------------++------------+
# |            ||            ||            |
# |  File      ||  Edit      || Options    |   <-------- the MENUBAR
# |            ||            ||            |
# +------------++------------++------------+
# | New...         |
# | Open...        |
# | Print          |
# |                |  <-------- This is a MENU. The lines of text in the menu are
# |                |                            MENU ENTRIES
# |                +---------------+
# | Open Files >   | file1         |
# |                | file2         |
# |                | another file  | <------ this cascading part is also a MENU
# +----------------|               |
#                  |               |
#                  |               |
#                  |               |
#                  +---------------+



# some miscellaneous callbacks
def new_file():
    print "opening new file"

def open_file():
    print "opening OLD file"

def print_something():
    print "picked a menu item"



anchovies = 0

def print_anchovies():
    global anchovies
    anchovies = not anchovies
    print "anchovies?", anchovies

def makeCommandMenu():
    # make menu button
    Command_button = Menubutton(mBar, text='Simple Button Commands',
                                underline=0)
    Command_button.pack(side=LEFT, padx="2m")

    # make the pulldown part of the File menu. The parameter passed is the master.
    # we attach it to the button as a python attribute called "menu" by convention.
    # hopefully this isn't too confusing...
    Command_button.menu = Menu(Command_button)

    # just to be cute, let's disable the undo option:
    Command_button.menu.add_command(label="Undo")
    # undo is the 0th entry...
    Command_button.menu.entryconfig(0, state=DISABLED)

    Command_button.menu.add_command(label='New...', underline=0,
                                    command=new_file)
    Command_button.menu.add_command(label='Open...', underline=0,
                                    command=open_file)
    Command_button.menu.add_command(label='Different Font', underline=0,
                                    font='-*-helvetica-*-r-*-*-*-180-*-*-*-*-*-*',
                                    command=print_something)

    # we can make bitmaps be menu entries too. File format is X11 bitmap.
    # if you use XV, save it under X11 bitmap format. duh-uh.,..
    Command_button.menu.add_command(
        bitmap="info")
        #bitmap='@/home/mjc4y/dilbert/project.status.is.doomed.last.panel.bm')

    # this is just a line
    Command_button.menu.add('separator')

    # change the color
    Command_button.menu.add_command(label='Quit', underline=0,
                                    background='red',
                                    activebackground='green',
                                    command=Command_button.quit)

    # set up a pointer from the file menubutton back to the file menu
    Command_button['menu'] = Command_button.menu

    return Command_button



def makeCascadeMenu():
    # make menu button
    Cascade_button = Menubutton(mBar, text='Cascading Menus', underline=0)
    Cascade_button.pack(side=LEFT, padx="2m")

    # the primary pulldown
    Cascade_button.menu = Menu(Cascade_button)

    # this is the menu that cascades from the primary pulldown....
    Cascade_button.menu.choices = Menu(Cascade_button.menu)

    # ...and this is a menu that cascades from that.
    Cascade_button.menu.choices.weirdones = Menu(Cascade_button.menu.choices)

    # then you define the menus from the deepest level on up.
    Cascade_button.menu.choices.weirdones.add_command(label='avacado')
    Cascade_button.menu.choices.weirdones.add_command(label='belgian endive')
    Cascade_button.menu.choices.weirdones.add_command(label='beefaroni')

    # definition of the menu one level up...
    Cascade_button.menu.choices.add_command(label='Chocolate')
    Cascade_button.menu.choices.add_command(label='Vanilla')
    Cascade_button.menu.choices.add_command(label='TuttiFruiti')
    Cascade_button.menu.choices.add_command(label='WopBopaLoopBapABopBamBoom')
    Cascade_button.menu.choices.add_command(label='Rocky Road')
    Cascade_button.menu.choices.add_command(label='BubbleGum')
    Cascade_button.menu.choices.add_cascade(
        label='Weird Flavors',
        menu=Cascade_button.menu.choices.weirdones)

    # and finally, the definition for the top level
    Cascade_button.menu.add_cascade(label='more choices',
                                    menu=Cascade_button.menu.choices)

    Cascade_button['menu'] = Cascade_button.menu

    return Cascade_button

def makeCheckbuttonMenu():
    global fred
    # make menu button
    Checkbutton_button = Menubutton(mBar, text='Checkbutton Menus',
                                    underline=0)
    Checkbutton_button.pack(side=LEFT, padx='2m')

    # the primary pulldown
    Checkbutton_button.menu = Menu(Checkbutton_button)

    # and all the check buttons. Note that the "variable" "onvalue" and "offvalue" options
    # are not supported correctly at present. You have to do all your application
    # work through the calback.
    Checkbutton_button.menu.add_checkbutton(label='Pepperoni')
    Checkbutton_button.menu.add_checkbutton(label='Sausage')
    Checkbutton_button.menu.add_checkbutton(label='Extra Cheese')

    # so here's a callback
    Checkbutton_button.menu.add_checkbutton(label='Anchovy',
                                            command=print_anchovies)

    # and start with anchovies selected to be on. Do this by
    # calling invoke on this menu option. To refer to the "anchovy" menu
    # entry we need to know it's index. To do this, we use the index method
    # which takes arguments of several forms:
    #
    # argument        what it does
    # -----------------------------------
    # a number        -- this is useless.
    # "last"          -- last option in the menu
    # "none"          -- used with the activate command. see the man page on menus
    # "active"        -- the currently active menu option. A menu option is made active
    #                         with the 'activate' method
    # "@number"       -- where 'number' is an integer and is treated like a y coordinate in pixels
    # string pattern  -- this is the option used below, and attempts to match "labels" using the
    #                    rules of Tcl_StringMatch
    Checkbutton_button.menu.invoke(Checkbutton_button.menu.index('Anchovy'))

    # set up a pointer from the file menubutton back to the file menu
    Checkbutton_button['menu'] = Checkbutton_button.menu

    return Checkbutton_button


def makeRadiobuttonMenu():
    # make menu button
    Radiobutton_button = Menubutton(mBar, text='Radiobutton Menus',
                                    underline=0)
    Radiobutton_button.pack(side=LEFT, padx='2m')

    # the primary pulldown
    Radiobutton_button.menu = Menu(Radiobutton_button)

    # and all the Radio buttons. Note that the "variable" "onvalue" and "offvalue" options
    # are not supported correctly at present. You have to do all your application
    # work through the calback.
    Radiobutton_button.menu.add_radiobutton(label='Republican')
    Radiobutton_button.menu.add_radiobutton(label='Democrat')
    Radiobutton_button.menu.add_radiobutton(label='Libertarian')
    Radiobutton_button.menu.add_radiobutton(label='Commie')
    Radiobutton_button.menu.add_radiobutton(label='Facist')
    Radiobutton_button.menu.add_radiobutton(label='Labor Party')
    Radiobutton_button.menu.add_radiobutton(label='Torie')
    Radiobutton_button.menu.add_radiobutton(label='Independent')
    Radiobutton_button.menu.add_radiobutton(label='Anarchist')
    Radiobutton_button.menu.add_radiobutton(label='No Opinion')

    # set up a pointer from the file menubutton back to the file menu
    Radiobutton_button['menu'] = Radiobutton_button.menu

    return Radiobutton_button


def makeDisabledMenu():
    Dummy_button = Menubutton(mBar, text='Dead Menu', underline=0)
    Dummy_button.pack(side=LEFT, padx='2m')

    # this is the standard way of turning off a whole menu
    Dummy_button["state"] = DISABLED
    return Dummy_button


#################################################
#### Main starts here ...
root = Tk()


# make a menu bar
mBar = Frame(root, relief=RAISED, borderwidth=2)
mBar.pack(fill=X)

Command_button     = makeCommandMenu()
Cascade_button     = makeCascadeMenu()
Checkbutton_button = makeCheckbuttonMenu()
Radiobutton_button = makeRadiobuttonMenu()
NoMenu             = makeDisabledMenu()

# finally, install the buttons in the menu bar.
# This allows for scanning from one menubutton to the next.
mBar.tk_menuBar(Command_button, Cascade_button, Checkbutton_button, Radiobutton_button, NoMenu)


root.title('menu demo')
root.iconname('menu demo')

root.mainloop()