Title: Signature
Hi

I hope someone can help me with the following problem:

I have attached a menu class which is part of a project I have written.

As my main menu names can be multiple lines I am using the image facility, without text, of Menu. However I cannot get an accelerate key to work.

Can anyone please assist me?
--

Regards


Paul Malherbe

Tartan Systems


Phone:

+27 (0)21-671-1866

Mobile:

+27 (0)82-900-5260

Fax:

+27 (0)86-262-1838



"""
SYNOPSIS
    These is the Menu class used in TARTAN.

    This file is part of Tartan Systems (TARTAN).

AUTHOR
    Written by Paul Malherbe, <p...@tartan.co.za>

COPYING
    Copyright (C) 2004-2013 Paul Malherbe. Free use of this software is
    granted under the terms of the GNU General Public License (GPL) as
    published by the Free Software Foundation, either version 2 of the
    License, or (at your option) any later version.

    TARTAN is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY, without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License along
    with TARTAN, if not, write to the Free Software Foundation, Inc.,
    59 Temple Place, Suite 330, Boston, MA  02111-1307  USA or view/download
    it at http://www.gnu.org/licenses/gpl.txt
"""

from Tkinter import *
from PIL import Image, ImageDraw, ImageFont, ImageTk

def getUnderline(dic, txt, sav=False):
    """
    dic  = dictionary name to use
    txt  = text to find underline for
    sav  = keep existing underlined character
    """
    if not txt:
        return dic, 0
    if sav and txt.count("_"):
        return dic, txt.index("_")
    pos = 0
    for c in txt:
        # If the label is Exit, try and make x the hot key
        if txt == "Exit" and c == "E":
            continue
        if (ord(c) in range(65, 91) or ord(c) in range(97, 123)) and \
                                (dic.count(c.lower()) == 0 and \
                                dic.count(c.upper()) == 0):
            dic.append(c)
            pos = txt.index(c)
            break
    return pos

class TartanMenu:
    """
    Use this to class to draw menus as follows:

    Create a list of lists of MenuBar Items for example:

        men = [["MM","Control", "Control Routines and exit"],
               ["MM","General", "General Ledger Menu"],
               ["MM","Creditors", "Creditor's Ledger Menu"],
               ["MM","Debtors", "Debtor's Ledger Menu"],
               ["MM","Stores", "Stores Ledger Menu"],
               ["MM","Help", "User's Manual and About","right"]]

        Where the fields are as follows:

        MM = Main Menu:
             Menu Name
             Detail
        CM = Cascade Menu:
             Parent Name
             Menu Name
             Detail
        
    Create a list of lists of Menu Items for example:

        mod = [["F","Control","tarCfg","Configure Tartan"],
               ["PNN","Control","co1010","Company Records"],
               ["F","Control","sysEnd","Exit Program"],
               ["CY","Control","l -l","Directory"]]

        Where the fields are as follows:

            Type        F =  Function
                        P123 where  1 = Requiring Company Number (Y/N)
                                    2 = Requiring Period Selection (Y/N)
                                    3 = Pass the User Name to the Module
            Parent Menu Name
            Program, Function or Command
            Security Level
            Prompt
            Routine number if required for type P above

    Draw the menus as follows:

        menu = TartanMenu(usr, men, mod, ign, lvl, cmd)

        mf  = Tartan MainFrame
        usr = User Name
        men = Menues
        mod = Modules
        lvl = Security Level
        cmd = Command to Execute on Selection
        img = Background Image to Display
    """
    def __init__(self, **args):
        for arg in args:
            exec "self.%s = args[arg]" % arg
        self.setVariables()

    def setVariables(self):
        # Create a list of menues and a dictionary of modules
        menues = []
        self.moddic = {}
        for m in self.mod:
            if not self.lvl == None and m[3] > self.lvl:
                continue
            if m[1] not in menues:
                menues.append(m[1])
            if m[0][0] == "P":
                mm = "mm_%s" % m[2][:2]
                if mm not in menues:
                    menues.append(mm)
                if len(m) == 6:
                    mod = "%s%s" % (m[2][:-1], m[5])
                    self.moddic[mod] = [m[0], m[4], m[5]]
                else:
                    mod = "%s%s" % (m[2][:-1], 0)
                    self.moddic[mod] = [m[0], m[4], None]
            else:
                mod = m[2]
                self.moddic[mod] = [m[0], m[4], None]
        self.menues = []
        for men in self.men:
            if men[0] == "MM" and men[1] in menues:
                self.menues.append(men)
            elif men[2] in menues:
                self.menues.append(men)

    def drawMenu(self):
        self.menubar = Menu(fg="black", bg="white", activebackground="black")
        self.mf["menu"] = self.menubar
        labs = {}
        mwth = 0
        for m in self.menues:
            if m[0] == "MM":
                if "mbar" in labs:
                    pass
                else:
                    labs["mbar"] = []
                exec "%s = Menu(self.menubar, tearoff=False)" % m[1]
                pos = getUnderline(labs["mbar"], m[2])
                img = self.createLabel(m[2], pos)
                nam = m[2].split()[0].split("'")[0]
                exec "image_%s = img" % nam
                exec "self.menubar.add_cascade(image=img, menu=%s)" % m[1]
                exec "cm1 = lambda event, self=self, menu=%s: "\
                    "self.postMenu(event, menu)" % m[1]
                self.menubar.bind_all("<Alt_L><%s>" %  m[2][pos].upper(), cm1)
                self.menubar.bind_all("<Alt_L><%s>" %  m[2][pos].lower(), cm1)
                self.menubar.bind_all("<Escape>", self.unpostMenu)
                mwth += img.width()
            elif m[0] == "CM":
                if m[1] in labs:
                    pass
                else:
                    labs[m[1]] = []
                exec "%s = Menu(%s, tearoff=False)" % (m[2], m[1])
                pos = getUnderline(labs[m[1]], m[3])
                exec '%s.add_cascade(label="%s", menu=%s, '\
                    'underline=pos)' % (m[1], m[3], m[2])
        for m in self.mod:
            if m[3] > self.lvl:
                continue
            if m[1] in labs:
                pass
            else:
                labs[m[1]] = []
            if m[0][0] == "P" and len(m) == 6:
                rtn = int(m[5])
            else:
                rtn = None
            if m[4] == "Quit":
                exec "%s.add_separator()" % m[1]
            pos = getUnderline(labs[m[1]], m[4])
            cmd = (self.menubar.register(self.cmd), m[0], m[2], rtn)
            #stk = m[2].lower()
            #if stk in images:
            #    image = Image.open(images[stk])
            #elif stk in aliases and os.path.isfile(aliases[stk]):
            #    image = Image.open(aliases[stk])
            #else:
            #    image = None
            image = None
            if image:
                image = image.resize((20, 20), 0)
                exec "self.image%s = ImageTk.PhotoImage(image)" % stk
                exec '%s.add_command(label="%s", command=cmd, underline=pos, '\
                    'image=self.image%s, compound="left")' % (m[1], m[4], stk)
            else:
                exec '%s.add_command(label="%s", command=cmd, underline=pos)' \
                    % (m[1], m[4])
        self.mf.geometry("%sx%s" % (mwth, 200))
        self.mf.mainloop()

    def postMenu(self, event, menu):
        menu.event_generate("<Enter>")
        menu.event_generate("<Button-1>")
        menu.event_generate("<Leave>")
        #menu.post(event.x_root, event.y_root)
        #self.posted = menu
        #menu.focus_force()

    def unpostMenu(self, event):
        try:
            self.posted.unpost()
        except:
            pass

    def createLabel(self, text, pos):
        unl = text[pos]
        text = text.split()
        if len(text) == 1:
            text.insert(0, "")
        elif len(text) == 3:
            text[1] = "%s %s" % (text[1], text[2])
            del text[2]
        self.font = ImageFont.truetype("DejaVuSans-Bold.ttf", 12)
        img = Image.new("RGBA", (70,30), (255,255,255))
        self.draw = ImageDraw.Draw(img)
        self.draw.text((0, 0),text[0],(0,0,0), font=self.font)
        done = self.drawUnderline(text[0], unl, 14)
        self.draw.text((0, 15),text[1],(0,0,0), font=self.font)
        if not done:
            self.drawUnderline(text[1], unl, 28)
        return ImageTk.PhotoImage(img)

    def drawUnderline(self, text, unl, y):
        done = False
        x = 0
        for c in text:
            if c == unl:
                w = self.font.getsize(c)[0]
                self.draw.line((x, y, x+w, y), fill=(0,0,0), width=1)
                done = True
                break
        return done

    def closeMenu(self, children=True):
        self.menubar.destroy()
        self.mf.quit()

if __name__ == "__main__":
    def doNothing(m0, m2, rtn):
        print m0, m2, rtn
        if m2 == "sysEnd":
            menu.closeMenu()

    tk = Tk()
    args = {
        "mf": tk,
        "men": [
            ["MM","mm_sy","System"],
            ["MM","mm_uy","General Utilities"],
            ["MM","mm_hp","Help","right"]],
        "mod": [
            ["F","mm_sy","chgUsr",0,"Change User"],
            ["F","mm_sy","chgPwd",0,"Change Password"],
            ["F","mm_sy","tarUsr",7,"User's Maintenance"],
            ["F","mm_sy","sysUpd",0,"Upgrade System"],
            ["F","mm_sy","tarUpd",5,"Update File Formats"],
            ["PNNN","mm_sy","tb1040",9,"Copy Tables"],
            ["F","mm_sy","tarBck",0,"Backup Database"],
            ["F","mm_sy","tarRes",5,"Restore Database"],
            ["F","mm_sy","tarCfg",0,"Preferences"],
            ["F","mm_sy","sysEnd",0,"Quit"],
            ["PYNN","mm_uy","bm1010",0,"Bulk Mail/SMS Utility"],
            ["PNNN","mm_uy","fc1010",0,"Loan/Lease Calculator"],
            ["PNNY","mm_uy","pm1010",0,"Personal Password Manager"],
            ["PNNY","mm_uy","rp1010",2,"Report Generator"],
            ["PNNN","mm_uy","pw1010",0,"Server User Maintenance"],
            ["PNNY","mm_uy","td1010",0,"Telephone Directory"],
            ["PNNN","mm_uy","tp1010",5,"Template Manager"],
            ["F","mm_uy","showCal",0,"Calendar"],
            ["F","mm_hp","doAbout",0,"About"],
            ["F","mm_hp","doManual",0,"Manual"]],
        "lvl": 9,
        "cmd": doNothing}
    menu = TartanMenu(**args)
    menu.drawMenu()
_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss@python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss

Reply via email to