165 lines
3.6 KiB
Python
165 lines
3.6 KiB
Python
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
|