Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ########################################################################################################################
- # File: menus.py
- # Author: Dan Huckson, https://github.com/unodan
- # Date: 2018-06-25
- ########################################################################################################################
- from os import path, getcwd
- from platform import system, release
- from tkinter import Menu, PhotoImage
- from tkinter.font import Font
- class MenuItem:
- def __init__(self, parent, json, **kwargs):
- self.parent = parent
- self.has_children = False
- self.font = json.get('font')
- self.label = json.get('label')
- self.state = json.get('state')
- self.value = json.get('value')
- self.index = kwargs.get('index')
- self.command = json.get('command')
- self.onvalue = json.get('onvalue', True)
- self.offvalue = json.get('offvalue', False)
- self.variable = json.get('variable')
- self.compound = json.get('compound', 'left')
- self.underline = json.get('underline', 0)
- self.foreground = json.get('foreground')
- self.background = json.get('background')
- self.accelerator = json.get('accelerator')
- self.activeforeground = json.get('activeforeground')
- self.activebackground = json.get('activebackground')
- if isinstance(self.font, dict):
- self.font = Font(
- family=self.font.get('family'),
- size=self.font.get('size'),
- weight=self.font.get('weight', 'normal'),
- slant=self.font.get('slant', 'roman'),
- underline=self.font.get('underline', False),
- overstrike=self.font.get('overstrike', False)
- )
- self.image = PhotoImage(file=path.join(getcwd(), 'tkmenus', 'images', json.get('image', 'blank-21x16.png')))
- kwargs = {
- 'font': self.font,
- 'label': self.label,
- 'state': self.state,
- 'index': self.index,
- 'command': self.command,
- 'variable': self.variable,
- 'compound': self.compound,
- 'underline': self.underline,
- 'foreground': self.foreground,
- 'background': self.background,
- 'accelerator': self.accelerator,
- 'activeforeground': self.activeforeground,
- 'activebackground': self.activebackground,
- }
- index = self.index
- widget_type = json.get('type')
- if widget_type == 'separator':
- func = parent.insert_separator if index else parent.add_separator
- func(index=index, background=self.background)
- elif widget_type == 'checkbutton':
- func = parent.insert_checkbutton if index else parent.add_checkbutton
- func(**{**kwargs, **{'onvalue': self.onvalue, 'offvalue': self.offvalue}})
- elif widget_type == 'radiobutton':
- func = parent.insert_radiobutton if index else parent.add_radiobutton
- func(**{**kwargs, **{'value': self.value}})
- else:
- func = parent.insert_command if index else parent.add_command
- func(**{**kwargs, **{'image': self.image}})
- def cget(self, attribute):
- return getattr(self, attribute, None)
- def config(self, **kwargs):
- for attribute, value in kwargs.items():
- setattr(self, attribute, value)
- index = self.index
- if not self.parent.tearoff:
- index -= 1
- self.parent.entryconfig(index, **kwargs)
- class Menus(Menu):
- def __init__(self, parent, **kwargs):
- self.items = {}
- self.parent = parent
- self.index = kwargs.pop('index', None)
- super().__init__(parent, **kwargs)
- def menu(self, uri):
- return self.get_child(uri)
- def populate(self, children):
- for key, child in children.items():
- self.add_child(key, child)
- return self
- def add_child(self, key, json, **kwargs):
- font = json.get('font', kwargs.get('font', self.cget('font')))
- if isinstance(font, dict):
- font = Font(
- family=font.get('family'),
- size=font.get('size'),
- weight=font.get('weight', 'normal'),
- slant=font.get('slant', 'roman'),
- underline=font.get('underline', False),
- overstrike=font.get('overstrike', False)
- )
- kwargs = {
- 'bd': json.get('bd', kwargs.get('bd', self.cget('bd'))),
- 'font': font,
- 'index': json.get('index', kwargs.get('index')),
- 'tearoff': json.get('tearoff', kwargs.get('tearoff', self.cget('tearoff'))),
- 'foreground': json.get('foreground', kwargs.get('foreground', self.cget('foreground'))),
- 'background': json.get('background', kwargs.get('background', self.cget('background'))),
- 'activeforeground': json.get(
- 'activeforeground', kwargs.get('activeforeground', self.cget('activeforeground'))),
- 'activebackground': json.get(
- 'activebackground', kwargs.get('activebackground', self.cget('activebackground'))),
- }
- func = SubMenu if 'children' in json else MenuItem
- self.items[key] = func(self, json, **kwargs)
- def get_child(self, uri):
- uri = uri.replace('\\', '/')
- if '/' in uri:
- def parse(parent, uri_part):
- parts = uri_part.split('/', 1)
- child = parent.get_child(parts[0])
- if len(parts) > 1:
- child = parse(child, parts[1])
- return child
- return parse(self, uri)
- return self.items.get(uri, None)
- def get_children(self):
- return self.items
- @property
- def has_children(self):
- return len(self.items)
- def config_children(self, **kwargs):
- def process(children):
- for index, child in children.items():
- if isinstance(child, MenuItem) and child.cget('widget_type') == 'separator':
- continue
- child.config(**kwargs)
- if child.has_children:
- process(child.get_children())
- process(self.get_children())
- class SubMenu(Menus):
- def __init__(self, parent, json, **kwargs):
- super().__init__(parent, **kwargs)
- self.__index = 0
- self.bd = json.get('bd', kwargs.get('bd'))
- self.font = json.get('font', kwargs.get('font'))
- self.label = json.get('label', kwargs.get('label'))
- self.image = json.get('image', kwargs.get('image'))
- self.index = json.get('index', kwargs.get('index'))
- self.state = json.get('state', kwargs.get('state'))
- self.tearoff = json.get('tearoff', kwargs.get('tearoff'))
- self.compound = json.get('compound', kwargs.get('compound', 'left'))
- self.underline = json.get('underline', kwargs.get('underline'))
- self.foreground = json.get('foreground', kwargs.get('foreground'))
- self.background = json.get('background', kwargs.get('background'))
- self.activeforeground = json.get('activeforeground', kwargs.get('activeforeground'))
- self.activebackground = json.get('activebackground', kwargs.get('activebackground'))
- if not isinstance(parent, MenuBar):
- self.image = PhotoImage(file=path.join(getcwd(), 'tkmenus', 'images', 'blank-21x16.png'))
- kwargs = {
- 'menu': self,
- 'label': self.label,
- 'image': self.image,
- 'compound': self.compound,
- 'underline': self.underline
- }
- if not self.index:
- parent.add_cascade(**kwargs)
- else:
- parent.insert_cascade(self.index, **kwargs)
- kwargs = {
- 'font': self.font,
- 'state': self.state,
- 'foreground': self.foreground,
- 'background': self.background,
- 'activeforeground': self.activeforeground,
- 'activebackground': self.activebackground,
- }
- for key, child in json.get('children').items():
- kwargs = {**kwargs, **{'index': self.next_index()}}
- if 'children' in child:
- self.items[key] = SubMenu(self, child, **{**kwargs, **{
- 'bd': child.get('bd', None),
- 'tearoff': child.get('tearoff', 0)
- }})
- else:
- self.items[key] = MenuItem(self, child, **kwargs)
- def next_index(self):
- self.__index += 1
- return self.__index
- class MenuBar(Menus):
- def __init__(self, parent, **kwargs):
- super().__init__(parent, **kwargs)
- self.items = {}
- self.platform = system()
- print(system(), release())
- class PopupMenu(Menus):
- def __init__(self, parent, **kwargs):
- super().__init__(parent, **kwargs)
- tearoff = kwargs.get('tearoff', 0)
- self.items = {}
- self.__leave = False
- self.__delay_destroy = 1000
- self.bind("<Enter>", self.on_enter)
- self.bind("<Leave>", self.on_leave)
- self.bind("<Escape>", self.on_escape)
- self.config(tearoff=tearoff)
- def on_enter(self, event):
- if event:
- self.__leave = False
- def on_leave(self, event):
- self.__leave = True
- def leave():
- if self.__leave:
- self.on_escape(event)
- self.after(self.__delay_destroy, leave)
- def on_escape(self, event):
- if event:
- self.unpost()
- self.__leave = False
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement