Example #1
0
    def __init__(self, parent, widgetInfo, *args, **kwargs):
        super(TextContainer, self).__init__(parent, *args, **kwargs)

        self.info = widgetInfo
        self._id = widgetInfo['id']
        self.widgetInfo = widgetInfo
        self._meta = widgetInfo['data']
        self._options = widgetInfo['options']
        self.label = wx.StaticText(self,
                                   label=widgetInfo['data']['display_name'])
        self.help_text = AutoWrappedStaticText(self,
                                               label=widgetInfo['data']['help']
                                               or '')
        self.error = AutoWrappedStaticText(self, label='')
        self.error.Hide()
        self.widget = self.getWidget(self)
        self.layout = self.arrange(*args, **kwargs)
        self.setColors()
        self.SetSizer(self.layout)
        self.bindMouseEvents()
        self.Bind(wx.EVT_SIZE, self.onSize)

        # 1.0.7 initial_value should supersede default when both are present
        if self._options.get('initial_value') is not None:
            self.setValue(self._options['initial_value'])
        # Checking for None instead of truthiness means False-evaluaded defaults can be used.
        elif self._meta['default'] is not None:
            self.setValue(self._meta['default'])

        if self._options.get('placeholder'):
            self.setPlaceholder(self._options.get('placeholder'))

        self.onComponentInitialized()
Example #2
0
    def __init__(self, parent, widgetInfo, *args, **kwargs):
        super(TextContainer, self).__init__(parent, *args, **kwargs)

        self.info = widgetInfo
        self._id = widgetInfo['id']
        self._meta = widgetInfo['data']
        self._options = widgetInfo['options']
        self.label = wx.StaticText(self, label=widgetInfo['data']['display_name'])
        self.help_text = AutoWrappedStaticText(self, label=widgetInfo['data']['help'] or '')
        self.error = AutoWrappedStaticText(self, label='')
        self.error.Hide()
        self.widget = self.getWidget(self)
        self.layout = self.arrange(*args, **kwargs)
        self.setColors()
        self.SetSizer(self.layout)
        self.Bind(wx.EVT_SIZE, self.onSize)
        if self._meta['default']:
            self.setValue(self._meta['default'])
    def __init__(self, parent, widgetInfo, *args, **kwargs):
        super(TextContainer, self).__init__(parent, *args, **kwargs)

        self.info = widgetInfo
        self._id = widgetInfo['id']
        self._meta = widgetInfo['data']
        self._options = widgetInfo['options']
        self.label = wx.StaticText(self,
                                   label=widgetInfo['data']['display_name'])
        self.help_text = AutoWrappedStaticText(self,
                                               label=widgetInfo['data']['help']
                                               or '')
        self.error = AutoWrappedStaticText(self, label='')
        self.error.Hide()
        self.widget = self.getWidget(self)
        self.layout = self.arrange(*args, **kwargs)
        self.setColors()
        self.SetSizer(self.layout)
        self.Bind(wx.EVT_SIZE, self.onSize)
        # Checking for None instead of truthiness means False-evaluaded defaults can be used.
        if self._meta['default'] is not None:
            self.setValue(self._meta['default'])
Example #4
0
    def makeGroup(self, parent, thissizer, group, *args):
        '''
        Messily builds the (potentially) nested and grouped layout

        Note! Mutates `self.reifiedWidgets` in place with the widgets as they're
        instantiated! I cannot figure out how to split out the creation of the
        widgets from their styling without WxPython violently exploding

        TODO: sort out the WX quirks and clean this up.
        '''

        # determine the type of border , if any, the main sizer will use
        if getin(group, ['options', 'show_border'], False):
            boxDetails = wx.StaticBox(parent, -1, self.getName(group) or '')
            boxSizer = wx.StaticBoxSizer(boxDetails, wx.VERTICAL)
        else:
            boxSizer = wx.BoxSizer(wx.VERTICAL)
            boxSizer.AddSpacer(10)
            if group['name']:
                groupName = wx_util.h1(parent, self.getName(group) or '')
                groupName.SetForegroundColour(getin(group, ['options', 'label_color']))
                groupName.Bind(wx.EVT_LEFT_DOWN, notifyMouseEvent)
                boxSizer.Add(groupName, 0, wx.TOP | wx.BOTTOM | wx.LEFT, 8)

        group_description = getin(group, ['description'])
        if group_description:
            description = AutoWrappedStaticText(parent, label=group_description, target=boxSizer)
            description.SetForegroundColour(getin(group, ['options', 'description_color']))
            description.SetMinSize((0, -1))
            description.Bind(wx.EVT_LEFT_DOWN, notifyMouseEvent)
            boxSizer.Add(description, 1,  wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, 10)

        # apply an underline when a grouping border is not specified
        # unless the user specifically requests not to show it
        if not getin(group, ['options', 'show_border'], False) and group['name'] \
                and getin(group, ['options', 'show_underline'], True):
            boxSizer.Add(wx_util.horizontal_rule(parent), 0, wx.EXPAND | wx.LEFT, 10)

        ui_groups = self.chunkWidgets(group)

        for uigroup in ui_groups:
            sizer = wx.BoxSizer(wx.HORIZONTAL)
            for item in uigroup:
                widget = self.reifyWidget(parent, item)
                if not getin(item, ['options', 'visible'], True):
                    widget.Hide()
                # !Mutate the reifiedWidgets instance variable in place
                self.reifiedWidgets.append(widget)
                sizer.Add(widget, 1, wx.ALL | wx.EXPAND, 5)
            boxSizer.Add(sizer, 0, wx.ALL | wx.EXPAND, 5)

        # apply the same layout rules recursively for subgroups
        hs = wx.BoxSizer(wx.HORIZONTAL)
        for e, subgroup in enumerate(group['groups']):
            self.makeGroup(parent, hs, subgroup, 1, wx.EXPAND)
            if len(group['groups']) != e:
                hs.AddSpacer(5)

            # self.makeGroup(parent, hs, subgroup, 1, wx.ALL | wx.EXPAND, 5)
            itemsPerColumn = getin(group, ['options', 'columns'], 2)
            if e % itemsPerColumn or (e + 1) == len(group['groups']):
                boxSizer.Add(hs, *args)
                hs = wx.BoxSizer(wx.HORIZONTAL)


        group_top_margin = getin(group, ['options', 'margin_top'], 1)

        marginSizer = wx.BoxSizer(wx.VERTICAL)
        marginSizer.Add(boxSizer, 1, wx.EXPAND | wx.TOP, group_top_margin)

        thissizer.Add(marginSizer, *args)
Example #5
0
class TextContainer(BaseWidget):
    # TODO: fix this busted-ass inheritance hierarchy.
    # Cracking at the seems for more advanced widgets
    # problems:
    #   - all the usual textbook problems of inheritance
    #   - assumes there will only ever be ONE widget created
    #   - assumes those widgets are all created in `getWidget`
    #   - all the above make for extremely awkward lifecycle management
    #      - no clear point at which binding is correct.
    #   - I think the core problem here is that I couple the interface
    #     for shared presentation layout with the specification of
    #     a behavioral interface
    #     - This should be broken apart.
    #     - presentation can be ad-hoc or composed
    #     - behavioral just needs a typeclass of get/set/format for Gooey's purposes
    widget_class = None  # type: ignore

    def __init__(self, parent, widgetInfo, *args, **kwargs):
        super(TextContainer, self).__init__(parent, *args, **kwargs)

        self.info = widgetInfo
        self._id = widgetInfo['id']
        self.widgetInfo = widgetInfo
        self._meta = widgetInfo['data']
        self._options = widgetInfo['options']
        self.label = wx.StaticText(self,
                                   label=widgetInfo['data']['display_name'])
        self.help_text = AutoWrappedStaticText(self,
                                               label=widgetInfo['data']['help']
                                               or '')
        self.error = AutoWrappedStaticText(self, label='')
        self.error.Hide()
        self.widget = self.getWidget(self)
        self.layout = self.arrange(*args, **kwargs)
        self.setColors()
        self.SetSizer(self.layout)
        self.bindMouseEvents()
        self.Bind(wx.EVT_SIZE, self.onSize)

        # 1.0.7 initial_value should supersede default when both are present
        if self._options.get('initial_value') is not None:
            self.setValue(self._options['initial_value'])
        # Checking for None instead of truthiness means False-evaluaded defaults can be used.
        elif self._meta['default'] is not None:
            self.setValue(self._meta['default'])

        if self._options.get('placeholder'):
            self.setPlaceholder(self._options.get('placeholder'))

        self.onComponentInitialized()

    def onComponentInitialized(self):
        pass

    def bindMouseEvents(self):
        """
        Send any LEFT DOWN mouse events to interested
        listeners via pubsub. see: gooey.gui.mouse for background.
        """
        self.Bind(wx.EVT_LEFT_DOWN, notifyMouseEvent)
        self.label.Bind(wx.EVT_LEFT_DOWN, notifyMouseEvent)
        self.help_text.Bind(wx.EVT_LEFT_DOWN, notifyMouseEvent)
        self.error.Bind(wx.EVT_LEFT_DOWN, notifyMouseEvent)
        self.widget.Bind(wx.EVT_LEFT_DOWN, notifyMouseEvent)

    def arrange(self, *args, **kwargs):
        wx_util.make_bold(self.label)
        wx_util.withColor(self.label, self._options['label_color'])
        wx_util.withColor(self.help_text, self._options['help_color'])
        wx_util.withColor(self.error, self._options['error_color'])

        self.help_text.SetMinSize((0, -1))

        layout = wx.BoxSizer(wx.VERTICAL)

        if self._options.get('show_label', True):
            layout.Add(self.label, 0, wx.EXPAND)
        else:
            self.label.Show(False)
            layout.AddStretchSpacer(1)

        layout.AddSpacer(2)
        if self.help_text and self._options.get('show_help', True):
            layout.Add(self.help_text, 1, wx.EXPAND)
            layout.AddSpacer(2)
        else:
            self.help_text.Show(False)
            layout.AddStretchSpacer(1)
        layout.Add(self.getSublayout(), 0, wx.EXPAND)
        layout.Add(self.error, 1, wx.EXPAND)

        # self.error.SetLabel("HELLOOOOO??")
        # self.error.Show()
        # print(self.error.Shown)
        return layout

    def setColors(self):
        wx_util.make_bold(self.label)
        wx_util.withColor(self.label, self._options['label_color'])
        wx_util.withColor(self.help_text, self._options['help_color'])
        wx_util.withColor(self.error, self._options['error_color'])
        if self._options.get('label_bg_color'):
            self.label.SetBackgroundColour(self._options.get('label_bg_color'))
        if self._options.get('help_bg_color'):
            self.help_text.SetBackgroundColour(
                self._options.get('help_bg_color'))
        if self._options.get('error_bg_color'):
            self.error.SetBackgroundColour(self._options.get('error_bg_color'))

    def getWidget(self, *args, **options):
        return self.widget_class(*args, **options)

    def getWidgetValue(self):
        raise NotImplementedError

    def getSublayout(self, *args, **kwargs):
        layout = wx.BoxSizer(wx.HORIZONTAL)
        layout.Add(self.widget, 1, wx.EXPAND)
        return layout

    def onSize(self, event):
        # print(self.GetSize())
        # self.error.Wrap(self.GetSize().width)
        # self.help_text.Wrap(500)
        # self.Layout()
        event.Skip()

    def getUiState(self) -> t.FormField:
        return t.TextField(id=self._id,
                           type=self.widgetInfo['type'],
                           value=self.getWidgetValue(),
                           placeholder=self.widget.widget.GetHint(),
                           error=self.error.GetLabel().replace('\n', ' '),
                           enabled=self.IsEnabled(),
                           visible=self.IsShown())

    def syncUiState(self, state: FormField):  # type: ignore
        self.widget.setValue(state['value'])  # type: ignore
        self.error.SetLabel(state['error'] or '')
        self.error.Show(state['error'] is not None
                        and state['error'] is not '')

    def getValue(self) -> t.FieldValue:
        regexFunc: Callable[[str],
                            bool] = lambda x: bool(re.match(userValidator, x))

        userValidator = getin(self._options, ['validator', 'test'], 'True')
        message = getin(self._options, ['validator', 'message'], '')
        testFunc = regexFunc \
                   if getin(self._options, ['validator', 'type'], None) == 'RegexValidator'\
                   else eval('lambda user_input: bool(%s)' % userValidator)
        satisfies = testFunc if self._meta['required'] else ifPresent(testFunc)
        value = self.getWidgetValue()

        return t.FieldValue(  # type: ignore
            id=self._id,
            cmd=self.formatOutput(self._meta, value),
            meta=self._meta,
            rawValue=value,
            # type=self.info['type'],
            enabled=self.IsEnabled(),
            visible=self.IsShown(),
            test=runValidator(satisfies, value),
            error=None if runValidator(satisfies, value) else message,
            clitype=('positional' if self._meta['required']
                     and not self._meta['commands'] else 'optional'))

    def setValue(self, value):
        self.widget.SetValue(value)

    def setPlaceholder(self, value):
        if getattr(self.widget, 'SetHint', None):
            self.widget.SetHint(value)

    def setErrorString(self, message):
        self.error.SetLabel(message)
        self.error.Wrap(self.Size.width)
        self.Layout()

    def showErrorString(self, b):
        self.error.Wrap(self.Size.width)
        self.error.Show(b)

    def setOptions(self, values):
        return None

    def receiveChange(self, metatdata, value):
        raise NotImplementedError

    def dispatchChange(self, value, **kwargs):
        raise NotImplementedError

    def formatOutput(self, metadata, value) -> str:
        raise NotImplementedError
Example #6
0
class TextContainer(BaseWidget):
    widget_class = None

    def __init__(self, parent, widgetInfo, *args, **kwargs):
        super(TextContainer, self).__init__(parent, *args, **kwargs)

        self.info = widgetInfo
        self._id = widgetInfo['id']
        self._meta = widgetInfo['data']
        self._options = widgetInfo['options']
        self.label = wx.StaticText(self, label=widgetInfo['data']['display_name'])
        self.help_text = AutoWrappedStaticText(self, label=widgetInfo['data']['help'] or '')
        self.error = AutoWrappedStaticText(self, label='')
        self.error.Hide()
        self.widget = self.getWidget(self)
        self.layout = self.arrange(*args, **kwargs)
        self.setColors()
        self.SetSizer(self.layout)
        self.Bind(wx.EVT_SIZE, self.onSize)
        if self._meta['default']:
            self.setValue(self._meta['default'])


    def arrange(self, *args, **kwargs):
        wx_util.make_bold(self.label)
        wx_util.withColor(self.label, self._options['label_color'])
        wx_util.withColor(self.help_text, self._options['help_color'])
        wx_util.withColor(self.error, self._options['error_color'])

        self.help_text.SetMinSize((0,-1))

        layout = wx.BoxSizer(wx.VERTICAL)

        if self._options.get('show_label', True):
            layout.Add(self.label, 0, wx.EXPAND)
        else:
            self.label.Show(False)
            layout.AddStretchSpacer(1)

        layout.AddSpacer(2)
        if self.help_text and self._options.get('show_help', True):
            layout.Add(self.help_text, 1, wx.EXPAND)
            layout.AddSpacer(2)
        else:
            self.help_text.Show(False)
            layout.AddStretchSpacer(1)
        layout.Add(self.getSublayout(), 0, wx.EXPAND)
        layout.Add(self.error, 1, wx.EXPAND)

        self.error.Hide()
        return layout


    def setColors(self):
        wx_util.make_bold(self.label)
        wx_util.withColor(self.label, self._options['label_color'])
        wx_util.withColor(self.help_text, self._options['help_color'])
        wx_util.withColor(self.error, self._options['error_color'])
        if self._options.get('label_bg_color'):
            self.label.SetBackgroundColour(self._options.get('label_bg_color'))
        if self._options.get('help_bg_color'):
            self.help_text.SetBackgroundColour(self._options.get('help_bg_color'))
        if self._options.get('error_bg_color'):
            self.error.SetBackgroundColour(self._options.get('error_bg_color'))

    def getWidget(self, *args, **options):
        return self.widget_class(*args, **options)

    def getWidgetValue(self):
        raise NotImplementedError

    def getSublayout(self, *args, **kwargs):
        layout = wx.BoxSizer(wx.HORIZONTAL)
        layout.Add(self.widget, 1, wx.EXPAND)
        return layout

    def onSize(self, event):
        # print(self.GetSize())
        # self.error.Wrap(self.GetSize().width)
        # self.help_text.Wrap(500)
        # self.Layout()
        event.Skip()


    def getValue(self):
        userValidator = getin(self._options, ['validator', 'test'], 'True')
        message = getin(self._options, ['validator', 'message'], '')
        testFunc = eval('lambda user_input: bool(%s)' % userValidator)
        satisfies = testFunc if self._meta['required'] else ifPresent(testFunc)
        value = self.getWidgetValue()

        return {
            'id': self._id,
            'cmd': self.formatOutput(self._meta, value),
            'rawValue': value,
            'test': runValidator(satisfies, value),
            'error': None if runValidator(satisfies, value) else message,
            'clitype': 'positional'
                        if self._meta['required'] and not self._meta['commands']
                        else 'optional'
        }

    def setValue(self, value):
        self.widget.SetValue(value)

    def setErrorString(self, message):
        self.error.SetLabel(message)
        self.error.Wrap(self.Size.width)
        self.Layout()

    def showErrorString(self, b):
        self.error.Wrap(self.Size.width)
        self.error.Show(b)

    def setOptions(self, values):
        return None

    def receiveChange(self, metatdata, value):
        raise NotImplementedError

    def dispatchChange(self, value, **kwargs):
        raise NotImplementedError

    def formatOutput(self, metadata, value):
        raise NotImplementedError