import abc from typing import Any, Optional, Union, List, Dict from biopro.util.json import JsonSerialize class MenuEntry(JsonSerialize, metaclass=abc.ABCMeta): """menu entry **json format** :: MenuEntry = { "name" :str "text" :str "description" :str? } """ __slots__ = ('name', 'text', 'desp') def __init__(self, name: str, text: str, desp: Optional[str] = None): self.name = name self.text = text self.desp = desp def as_json(self) -> Dict[str, Any]: return { 'name': self.name, 'text': self.text, 'description': self.desp } class MenuItem(MenuEntry): """menu item **json format** :: MenuItem (MenuEntry) = { "command" :str? "active" :bool } """ __slots__ = ('command', 'active') def __init__(self, name: str, text: str, desp: Optional[str] = None, command: Union[None, str, List[str]] = None, active: bool = False): super().__init__(name, text, desp) if isinstance(command, list): self.command: Optional[str] = ';'.join(command) else: self.command: Optional[str] = command self.active = active def as_json(self): ret = super().as_json() ret.update({ 'command': self.command, 'active': self.active }) return ret class Menu(MenuEntry): """menu **json format** :: Menu (MenuEntry) = { "menu" :[MenuEntry] } """ __slots__ = ('_menu',) # XXX condition menu? def __init__(self, name: str, text: str, menu: List[MenuEntry] = None, desp: Optional[str] = None): super().__init__(name, text, desp) self._menu: List[MenuEntry] = menu if menu is not None else [] def __len__(self): return len(self._menu) def __getitem__(self, index: int) -> MenuEntry: return self._menu[index] def __setitem__(self, index: int, value: MenuEntry): self._menu[index] = value def __delitem__(self, index: Union[int, slice]): del self._menu[index] def __iter__(self): return iter(self._menu) def append(self, menu: MenuEntry): self._menu.append(menu) def append_item(self, name: str, text: str, desp: Optional[str] = None, command: Union[None, str, List[str]] = None, active: bool = False) -> MenuItem: e = MenuItem(name, text, desp=desp, command=command, active=active) self._menu.append(e) return e def append_menu(self, name: str, text: str, menu: List[MenuEntry] = None, desp: Optional[str] = None) -> 'Menu': e = Menu(name, text, desp=desp, menu=menu) self._menu.append(e) return e def extend(self, menu: Union[List[MenuEntry], 'Menu']): if isinstance(menu, Menu): self._menu.extend(menu._menu) elif isinstance(menu, list): self._menu.extend(menu) else: raise TypeError(menu.__class__.__name__) def as_json(self): ret = super().as_json() ret.update({ 'menu': [v.as_json() for v in self._menu] }) return ret