""" Houses all the supporting rewx components for the main application window. """ import wx # type: ignore from typing_extensions import TypedDict from gooey.gui.components.config import ConfigPage, TabbedConfigPage from gooey.gui.components.console import Console from gooey.gui.components.mouse import notifyMouseEvent from gooey.gui.components.sidebar import Sidebar from gooey.gui.components.tabbar import Tabbar from gooey.gui.lang.i18n import _ from gooey.gui.pubsub import pub from gooey.gui.state import present_time from gooey.gui.three_to_four import Constants from gooey.python_bindings import constants from rewx import components as c # type: ignore from rewx import wsx, mount, update # type: ignore from rewx.core import Component, Ref # type: ignore from rewx.widgets import set_basic_props # type: ignore def attach_notifier(parent): """ Recursively attaches the mouseEvent notifier to all elements in the tree """ parent.Bind(wx.EVT_LEFT_DOWN, notifyMouseEvent) for child in parent.Children: attach_notifier(child) class HeaderProps(TypedDict): background_color: str title: str show_title: bool subtitle: str show_subtitle: bool class RHeader(Component): def __init__(self, props): super().__init__(props) self.parentRef = Ref() def component_did_mount(self): attach_notifier(self.parentRef.instance) def render(self): if 'running' not in self.props['image_uri']: imageProps = { 'uri': self.props['image_uri'], 'size': self.props['image_size'], 'flag': wx.RIGHT, 'border': 10} else: imageProps = { 'size': self.props['image_size'], 'flag': wx.RIGHT, 'border': 10} return wsx( [c.Block, {'orient': wx.HORIZONTAL, 'ref': self.parentRef, 'min_size': (120, self.props['height']), 'background_color': self.props['background_color']}, [c.Block, {'orient': wx.VERTICAL, 'flag': wx.ALIGN_CENTER_VERTICAL | wx.ALL, 'proportion': 1, 'border': 10}, [TitleText, {'label': self.props['title'], 'show': self.props['show_title'], 'wx_name': 'header_title'}], [c.StaticText, {'label': self.props['subtitle'], 'show': self.props['show_subtitle'], 'wx_name': 'header_subtitle'}]], [c.StaticBitmap, imageProps]] ) class RFooter(Component): def __init__(self, props): super().__init__(props) self.ref = Ref() def component_did_mount(self): """ We have to manually wire up LEFT_DOWN handlers for every component due to wx limitations. See: mouse.py docs for background. """ block: wx.BoxSizer = self.ref.instance attach_notifier(block) def handle(self, btn): def inner(*args, **kwargs): pub.send_message(btn['id']) return inner def render(self): return wsx( [c.Block, {'orient': wx.VERTICAL, 'min_size': (30, 53), 'background_color': self.props['bg_color']}, [c.Block, {'orient': wx.VERTICAL, 'proportion': 1}], [c.Block, {'orient': wx.HORIZONTAL, 'border': 20, 'flag': wx.EXPAND | wx.LEFT | wx.RIGHT, 'ref': self.ref}, [c.Gauge, {'range': 100, 'proportion': 1, 'value': self.props['progress']['value'], 'show': self.props['progress']['show']}], [c.StaticText, {'label': present_time(self.props['timing']), 'flag': wx.LEFT, 'wx_name': 'timing', 'show': self.props['timing']['show'], 'border': 20}], [c.Block, {'orient': wx.HORIZONTAL, 'proportion': 1}], *[[c.Button, {**btn, 'label': _(btn['label_id']), 'min_size': (90, 23), 'flag': wx.LEFT, 'border': 10, 'on_click': self.handle(btn) }] for btn in self.props['buttons']]], [c.Block, {'orient': wx.VERTICAL, 'proportion': 1}]] ) class RNavbar(Component): def __init__(self, props): super().__init__(props) # if self.buildSpec['navigation'] == constants.TABBED: # navigation = Tabbar(self, self.buildSpec, self.configs) # else: # navigation = Sidebar(self, self.buildSpec, self.configs) # if self.buildSpec['navigation'] == constants.HIDDEN: # navigation.Hide() def render(self): return wsx( ) def VerticalSpacer(props): return wsx([c.Block, {'orient': wx.VERTICAL, 'min_size': (-1, props['height'])}]) def SidebarControls(props): return wsx( [c.Block, {'orient': wx.VERTICAL, 'min_size': (180, 0), 'size': (180, 0), 'show': props.get('show', True), 'flag': wx.EXPAND, 'proportion': 0, 'background_color': props['bg_color']}, [c.Block, {'orient': wx.VERTICAL, 'min_size': (180, 0), 'size': (180, 0), 'flag': wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, 'border': 10, 'proportion': 1, 'background_color': props['bg_color']}, [VerticalSpacer, {'height': 15}], [TitleText, {'label': props['label']}], [VerticalSpacer, {'height': 5}], [c.ListBox, {'choices': props['options'], 'value': props['activeSelection'], 'proportion': 1, 'on_change': props['on_change'], 'flag': wx.EXPAND}], [VerticalSpacer, {'height': 10}]]] ) def ProgressSpinner(props): return wsx( [c.Block, {'flag': wx.EXPAND, 'show': props['show']}, [c.Gauge, {'flag': wx.EXPAND, 'value': -1, 'size': (-1, 4)}], [c.StaticLine, {'style': wx.LI_HORIZONTAL, 'flag': wx.EXPAND}]] ) def ErrorWarning(props): return wsx( [c.Block, {'orient': wx.HORIZONTAL, 'background_color': '#fdeded', 'style': wx.SIMPLE_BORDER, 'flag': wx.EXPAND | wx.ALL, 'proportion': 0, 'border': 5, 'min_size': (-1, 45), 'show': props.get('show', True)}, [c.StaticBitmap, {'size': (24, 24), 'flag': wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 'border': 6, 'uri': props['uri']}], [c.StaticText, {'label': 'Whoops! You have some errors which must be corrected', 'flag': wx.ALIGN_CENTER_VERTICAL}]] ) def RSidebar(props): return wsx( [c.Block, {'orient': wx.HORIZONTAL, 'show': props.get('show', True), 'flag': props['flag'], 'proportion': props['proportion'], 'ref': props['ref']}, [SidebarControls, {**props, 'show': props['show_sidebar']}], [c.StaticLine, {'style': wx.LI_VERTICAL, 'flag': wx.EXPAND, 'min_size': (1, -1)}], *[[TabbedConfigPage if props['tabbed_groups'] else ConfigPage, {'flag': wx.EXPAND, 'proportion': 3, 'config': config, 'show': i == props['activeSelection']}] for i, config in enumerate(props['config'].values())] ] ) def RTabbedLayout(props): return wsx( [c.Notebook, {'flag': wx.EXPAND | wx.ALL, 'show': props.get('show', True), 'proportion': 1, 'on_change': props['on_change'], 'ref': props['ref']}, *[[c.NotebookItem, {'title': props['options'][i], 'selected': props['activeSelection'] == i}, [TabbedConfigPage if props['tabbed_groups'] else ConfigPage, {'flag': wx.EXPAND, 'proportion': 3, 'config': config, 'show': i == props['activeSelection']}]] for i, config in enumerate(props['config'].values())]] ) def layout_choose(): def buildNavigation(self): """ Chooses the appropriate layout navigation component based on user prefs """ if self.buildSpec['navigation'] == constants.TABBED: navigation = Tabbar(self, self.buildSpec, self.configs) else: navigation = Sidebar(self, self.buildSpec, self.configs) if self.buildSpec['navigation'] == constants.HIDDEN: navigation.Hide() return navigation def buildConfigPanels(self, parent): page_class = TabbedConfigPage if self.buildSpec['tabbed_groups'] else ConfigPage return [page_class(parent, widgets, self.buildSpec) for widgets in self.buildSpec['widgets'].values()] class TitleText(Component): def __init__(self, props): super().__init__(props) self.ref = Ref() def component_did_mount(self): text: wx.StaticText = self.ref.instance font_size = text.GetFont().GetPointSize() text.SetFont(wx.Font( int(font_size * 1.2), wx.FONTFAMILY_DEFAULT, Constants.WX_FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False )) def render(self): return wsx([c.StaticText, {**self.props, 'label': self.props['label'], 'ref': self.ref}]) ## ## REWX definitions: ## @mount.register(ConfigPage) # type: ignore def config(element, parent): return update(element, ConfigPage(parent, element['props']['config'], {'contents': []})) @update.register(ConfigPage) # type: ignore def config(element, instance: ConfigPage): set_basic_props(instance, element['props']) return instance @mount.register(TabbedConfigPage) # type: ignore def tabbedconfig(element, parent): return update(element, TabbedConfigPage(parent, element['props']['config'], {'contents': []})) @update.register(TabbedConfigPage) # type: ignore def tabbedconfig(element, instance: TabbedConfigPage): set_basic_props(instance, element['props']) return instance @mount.register(Console) # type: ignore def console(element, parent): return update(element, Console(parent, element['props'])) @update.register(Console) # type: ignore def console(element, instance: Console): set_basic_props(instance, element['props']) if 'show' in element['props']: instance.Show(element['props']['show']) return instance