Browse Source

plane commits

dynamic-values
Chris Kiehl 2 years ago
parent
commit
43364a3767
23 changed files with 265 additions and 60 deletions
  1. 2
      gooey/gui/cli.py
  2. 15
      gooey/gui/components/config.py
  3. 38
      gooey/gui/components/widgets/bases.py
  4. 20
      gooey/gui/components/widgets/checkbox.py
  5. 5
      gooey/gui/components/widgets/command.py
  6. 18
      gooey/gui/components/widgets/counter.py
  7. 14
      gooey/gui/components/widgets/dropdown.py
  8. 13
      gooey/gui/components/widgets/dropdown_filterable.py
  9. 14
      gooey/gui/components/widgets/listbox.py
  10. 27
      gooey/gui/components/widgets/numeric_fields.py
  11. 5
      gooey/gui/components/widgets/password.py
  12. 1
      gooey/gui/components/widgets/radio_group.py
  13. 2
      gooey/gui/components/widgets/richtextconsole.py
  14. 14
      gooey/gui/components/widgets/slider.py
  15. 4
      gooey/gui/components/widgets/textarea.py
  16. 12
      gooey/gui/components/widgets/textfield.py
  17. 58
      gooey/gui/containers/application.py
  18. 2
      gooey/gui/processor.py
  19. 2
      gooey/gui/state.py
  20. 2
      gooey/python_bindings/argparse_to_json.py
  21. 55
      gooey/python_bindings/types.py
  22. 1
      gooey/rewx
  23. 1
      requirements.txt

2
gooey/gui/cli.py

@ -8,7 +8,7 @@ from typing import List, Optional
from gooey.gui.constants import VALUE_PLACEHOLDER
from gooey.gui.formatters import formatArgument
from gooey.python_bindings.types import FieldValue
from util.functional import merge # type: ignore
from gooey.util.functional import merge # type: ignore
'''
primary :: Target -> Command -> Array Arg -> Array Arg -> Boolean -> CliString

15
gooey/gui/components/config.py

@ -1,10 +1,11 @@
from typing import Mapping
from typing import Mapping, List
import wx # type: ignore
from wx.lib.scrolledpanel import ScrolledPanel # type: ignore
from gooey.gui.components.util.wrapped_static_text import AutoWrappedStaticText
from gooey.gui.util import wx_util
from gooey.python_bindings.types import FormField
from gooey.util.functional import getin, flatmap, compact, indexunique
from gooey.gui.lang.i18n import _
from gooey.gui.components.mouse import notifyMouseEvent
@ -65,16 +66,18 @@ class ConfigPage(ScrolledPanel):
if widget.info['cli_type'] != 'positional']
def getFormState(self):
return [widget.getValue()
return [widget.getUiState()
for widget in self.reifiedWidgets]
def syncFormState(self, formState: List[FormField]):
for item in formState:
self.widgetsMap[item['id']].syncUiState(item)
def isValid(self):
return not any(self.getErrors())
def syncFromState(self, state):
pass
def getErrors(self):
states = [widget.getValue() for widget in self.reifiedWidgets]
return {state['meta']['dest']: state['error'] for state in states
@ -93,7 +96,7 @@ class ConfigPage(ScrolledPanel):
self.resetErrors()
radioWidgets = self.indexInternalRadioGroupWidgets()
widgetsByDest = {v._meta['dest']: v for k,v in self.widgetsMap.items()
if v.info['type'] is not 'RadioGroup'}
if v.info['type'] != 'RadioGroup'}
# if there are any errors, then all error blocks should
# be displayed so that the UI elements remain inline with

38
gooey/gui/components/widgets/bases.py

@ -7,11 +7,12 @@ from mypy_extensions import KwArg
from gooey.gui import formatters, events
from gooey.gui.util import wx_util
from gooey.python_bindings.types import FormField
from gooey.util.functional import getin, ifPresent
from gooey.gui.validators import runValidator
from gooey.gui.components.util.wrapped_static_text import AutoWrappedStaticText
from gooey.gui.components.mouse import notifyMouseEvent
from gooey.python_bindings.types import FieldValue, FormField, TextField
from gooey.python_bindings import types as t
class BaseWidget(wx.Panel):
@ -170,16 +171,21 @@ class TextContainer(BaseWidget):
# self.Layout()
event.Skip()
def getUiState(self) -> FormField:
return TextField(
def getUiState(self) -> t.FormField:
return t.TextField(
id=self._id,
type=self.widgetInfo['type'],
value=self.getWidgetValue(),
enabled=self.Enabled,
visible=self.Shown
placeholder=self.widget.widget.GetHint(),
error=self.error.GetLabel() or None,
enabled=self.IsEnabled(),
visible=self.IsShown()
)
def getValue(self) -> FieldValue:
def syncUiState(self, state: FormField):
raise NotImplementedError
def getValue(self) -> t.FieldValue:
regexFunc: Callable[[str], bool] = lambda x: bool(re.match(userValidator, x))
userValidator = getin(self._options, ['validator', 'test'], 'True')
@ -190,14 +196,14 @@ class TextContainer(BaseWidget):
satisfies = testFunc if self._meta['required'] else ifPresent(testFunc)
value = self.getWidgetValue()
return FieldValue(
return t.FieldValue(
id=self._id,
cmd=self.formatOutput(self._meta, value),
meta=self._meta,
rawValue= value,
type=self.info['type'],
enabled=self.Enabled,
visible=self.Shown,
# type=self.info['type'],
enabled=self.IsEnabled(),
visible=self.IsShown(),
test= runValidator(satisfies, value),
error=None if runValidator(satisfies, value) else message,
clitype=('positional'
@ -250,3 +256,15 @@ class BaseChooser(TextContainer):
def formatOutput(self, metatdata, value):
return formatters.general(metatdata, value)
def getUiState(self) -> t.FormField:
btn: wx.Button = self.button # type: ignore
return t.Chooser(
id=self._id,
type=self.widgetInfo['type'],
value=self.widget.GetValue(),
btn_label=btn.GetLabel(),
error=self.error.GetLabel() or None,
enabled=self.IsEnabled(),
visible=self.IsShown()
)

20
gooey/gui/components/widgets/checkbox.py

@ -4,6 +4,7 @@ from gooey.gui import formatters
from gooey.gui.components.widgets.bases import TextContainer
from gooey.gui.lang.i18n import _
from gooey.gui.util import wx_util
from gooey.python_bindings import types as t
class CheckBox(TextContainer):
@ -54,6 +55,25 @@ class CheckBox(TextContainer):
self.widget.Hide()
def getUiState(self) -> t.FormField:
return t.Checkbox(
id=self._id,
type=self.widgetInfo['type'],
checked=self.widget.GetValue(),
error=self.error.GetLabel() or None,
enabled=self.IsEnabled(),
visible=self.IsShown()
)
def syncUiState(self, state: t.Checkbox):
checkbox: wx.CheckBox = self.widget
checkbox.SetValue(state['checked'])
checkbox.Enable(state['enabled'])
self.Show(state['visible'])
if state['error']:
self.setErrorString(state['error'])

5
gooey/gui/components/widgets/command.py

@ -1,8 +1,11 @@
from gooey.gui.components.widgets.textfield import TextField
from gooey.python_bindings import types as t
__ALL__ = ('CommandField',)
class CommandField(TextField):
pass
def getUiState(self) -> t.FormField:
return t.Command(**super().getUiState())

18
gooey/gui/components/widgets/counter.py

@ -1,5 +1,7 @@
from gooey.gui.components.widgets.dropdown import Dropdown
import wx
from gooey.gui.components.widgets.dropdown import Dropdown
from gooey.python_bindings import types as t
from gooey.gui import formatters
@ -9,5 +11,19 @@ class Counter(Dropdown):
index = self._meta['choices'].index(value) + 1
self.widget.SetSelection(index)
def getUiState(self) -> t.FormField:
widget: wx.ComboBox = self.widget
return t.Counter(
id=self._id,
type=self.widgetInfo['type'],
selected=self.getWidgetValue(),
choices=widget.GetStrings(),
error=self.error.GetLabel() or None,
enabled=self.IsEnabled(),
visible=self.IsShown()
)
def formatOutput(self, metadata, value):
return formatters.counter(metadata, value)

14
gooey/gui/components/widgets/dropdown.py

@ -5,7 +5,7 @@ import wx # type: ignore
from gooey.gui import formatters
from gooey.gui.lang.i18n import _
from gooey.python_bindings import types as t
class Dropdown(TextContainer):
_gooey_options = {
@ -44,6 +44,18 @@ class Dropdown(TextContainer):
def formatOutput(self, metadata, value):
return formatters.dropdown(metadata, value)
def getUiState(self) -> t.FormField:
widget: wx.ComboBox = self.widget
return t.Dropdown(
id=self._id,
type=self.widgetInfo['type'],
selected=self.getWidgetValue(),
choices=widget.GetStrings(),
error=self.error.GetLabel() or None,
enabled=self.IsEnabled(),
visible=self.IsShown()
)
@contextmanager
def retainSelection(self):
""""

13
gooey/gui/components/widgets/dropdown_filterable.py

@ -9,6 +9,7 @@ from gooey.gui.components.mouse import notifyMouseEvent
from gooey.gui.components.widgets.dropdown import Dropdown
from gooey.gui.lang.i18n import _
from gooey.gui.pubsub import pub
from gooey.python_bindings import types as t
__ALL__ = ('FilterableDropdown',)
@ -110,6 +111,18 @@ class FilterableDropdown(Dropdown):
self.listbox.AcceptsFocusFromKeyboard = lambda *args, **kwargs: False
return self.comboCtrl
def getUiState(self) -> t.FormField:
widget: wx.ComboBox = self.widget
return t.DropdownFilterable(
id=self._id,
type=self.widgetInfo['type'],
selected=self.getWidgetValue(),
choices=widget.GetStrings(),
error=self.error.GetLabel() or None,
enabled=self.IsEnabled(),
visible=self.IsShown()
)
def OnGetItem(self, n):
return self.model.suggestions[n]

14
gooey/gui/components/widgets/listbox.py

@ -2,7 +2,7 @@ import wx # type: ignore
from gooey.gui import formatters
from gooey.gui.components.widgets.bases import TextContainer
from gooey.python_bindings import types as t
class Listbox(TextContainer):
@ -30,3 +30,15 @@ class Listbox(TextContainer):
def formatOutput(self, metadata, value):
return formatters.listbox(metadata, value)
def getUiState(self) -> t.FormField:
widget: wx.ComboBox = self.widget
return t.ListBox(
id=self._id,
type=self.widgetInfo['type'],
selected=self.getWidgetValue(),
choices=self._meta['choices'],
error=self.error.GetLabel() or None,
enabled=self.IsEnabled(),
visible=self.IsShown()
)

27
gooey/gui/components/widgets/numeric_fields.py

@ -2,7 +2,7 @@ import wx # type: ignore
from gooey.gui import formatters
from gooey.gui.components.widgets.bases import TextContainer
from gooey.python_bindings import types as t
class IntegerField(TextContainer):
"""
@ -27,6 +27,18 @@ class IntegerField(TextContainer):
# doesn't treat 0 as false/None
return formatters.general(metatdata, str(value))
def getUiState(self) -> t.FormField:
widget: wx.SpinCtrl = self.widget
return t.IntegerField(
id=self._id,
type=self.widgetInfo['type'],
value=self.getWidgetValue(),
min=widget.GetMin(),
max=widget.GetMax(),
error=self.error.GetLabel() or None,
enabled=self.IsEnabled(),
visible=self.IsShown()
)
class DecimalField(IntegerField):
"""
@ -47,4 +59,17 @@ class DecimalField(IntegerField):
def setValue(self, value):
self.widget.SetValue(value)
def getUiState(self) -> t.FormField:
widget: wx.SpinCtrlDouble = self.widget
return t.IntegerField(
id=self._id,
type=self.widgetInfo['type'],
value=self.getWidgetValue(),
min=widget.GetMin(),
max=widget.GetMax(),
error=self.error.GetLabel() or None,
enabled=self.IsEnabled(),
visible=self.IsShown()
)

5
gooey/gui/components/widgets/password.py

@ -1,6 +1,6 @@
from gooey.gui.components.widgets.core.text_input import PasswordInput
from gooey.gui.components.widgets.textfield import TextField
from gooey.python_bindings import types as t
__ALL__ = ('PasswordField',)
@ -10,3 +10,6 @@ class PasswordField(TextField):
def __init__(self, *args, **kwargs):
super(PasswordField, self).__init__(*args, **kwargs)
def getUiState(self) -> t.FormField:
return t.PasswordField(**super().getUiState())

1
gooey/gui/components/widgets/radio_group.py

@ -5,6 +5,7 @@ from gooey.gui.util import wx_util
from gooey.gui.components.widgets import CheckBox
from gooey.util.functional import getin, findfirst, merge
from gooey.python_bindings import types as t
from gooey.python_bindings import types as t
class RadioGroup(BaseWidget):
"""

2
gooey/gui/components/widgets/richtextconsole.py

@ -2,6 +2,8 @@ import wx # type: ignore
import wx.richtext # type: ignore
import colored # type: ignore
import re
from gooey.python_bindings import types as t
kColorList = ["#000000", "#800000", "#008000", "#808000", "#000080", "#800080", "#008080", "#c0c0c0",
"#808080", "#ff0000", "#00ff00", "#ffff00", "#0000ff", "#ff00ff", "#00ffff", "#ffffff", "#000000",

14
gooey/gui/components/widgets/slider.py

@ -2,6 +2,7 @@ import wx # type: ignore
from gooey.gui import formatters
from gooey.gui.components.widgets.bases import TextContainer
from gooey.python_bindings import types as t
class Slider(TextContainer):
@ -25,4 +26,15 @@ class Slider(TextContainer):
def formatOutput(self, metatdata, value):
return formatters.general(metatdata, str(value))
def getUiState(self) -> t.FormField:
widget: wx.Slider = self.widget
return t.Slider(
id=self._id,
type=self.widgetInfo['type'],
value=self.getWidgetValue(),
min=widget.GetMin(),
max=widget.GetMax(),
error=self.error.GetLabel() or None,
enabled=self.IsEnabled(),
visible=self.IsShown()
)

4
gooey/gui/components/widgets/textarea.py

@ -6,6 +6,7 @@ from gooey.gui.components.widgets.core.text_input import MultilineTextInput
from gooey.gui.components.widgets.textfield import TextField
from gooey.gui.components.widgets.bases import TextContainer
from gooey.gui import formatters
from gooey.python_bindings import types as t
class Textarea(TextContainer):
@ -36,4 +37,5 @@ class Textarea(TextContainer):
def formatOutput(self, metatdata, value: str):
return formatters.general(metatdata, value.replace('\n', os.linesep))
def getUiState(self) -> t.FormField:
return t.Textarea(**super().getUiState())

12
gooey/gui/components/widgets/textfield.py

@ -1,7 +1,9 @@
import wx
from gooey.gui import formatters
from gooey.gui.components.widgets.bases import TextContainer
from gooey.gui.components.widgets.core.text_input import TextInput
from gooey.python_bindings import types as t
class TextField(TextContainer):
widget_class = TextInput
@ -18,3 +20,11 @@ class TextField(TextContainer):
def formatOutput(self, metatdata, value):
return formatters.general(metatdata, value)
def syncUiState(self, state: t.TextField):
textctr: wx.TextCtrl = self.widget.widget
textctr.SetValue(state['value'])
textctr.SetHint(state['placeholder'])
textctr.Enable(state['enabled'])
self.Show(state['visible'])
if state['error']:
self.setErrorString(state['error'])

58
gooey/gui/containers/application.py

@ -12,10 +12,10 @@ import six
import wx # type: ignore
from rewx.widgets import set_basic_props
from gui.components.mouse import notifyMouseEvent
from gui.state import initial_state, present_time, form_page, ProgressEvent, TimingEvent
from gooey.gui.components.mouse import notifyMouseEvent
from gooey.gui.state import initial_state, present_time, form_page, ProgressEvent, TimingEvent
from gooey.gui import state as s
from gui.three_to_four import Constants
from gooey.gui.three_to_four import Constants
from rewx.core import Component, Ref, updatewx, patch
from typing_extensions import TypedDict
@ -49,7 +49,7 @@ from gooey.gui.image_repository import loadImages
from threading import Lock
from util.functional import associnMany
from gooey.util.functional import associnMany
lock = Lock()
@ -589,6 +589,7 @@ def RSidebar(props):
*[[ConfigPage, {'flag': wx.EXPAND,
'proportion': 3,
'config': config,
'ref': props['ref'],
'show': i == props['activeSelection']}]
for i, config in enumerate(props['config'].values())]
]
@ -609,6 +610,7 @@ class RGooey(Component):
super().__init__(props)
self.frameRef = Ref()
self.consoleRef = Ref()
self.configRef = Ref()
self.buildSpec = props
self.state = initial_state(props)
@ -651,7 +653,7 @@ class RGooey(Component):
"""
# navigates away from the button because a
# disabled focused button still looks enabled.
self.set_state(s.enable_buttons(self.state, []))
# self.set_state(s.enable_buttons(self.state, []))
if Events.VALIDATE_FORM in self.buildSpec.get('use_events', []):
# TODO: make this wx thread safe so that it can
# actually run asynchronously
@ -662,8 +664,8 @@ class RGooey(Component):
def onStartAsyncOLD(self, *args, **kwargs):
with transactUI(self):
try:
errors = self.validateForm().getOrThrow()
if errors: # TODO
# errors = self.validateForm().getOrThrow()
if False: # TODO
config = self.navbar.getActiveConfig()
config.setErrors(errors)
self.Layout()
@ -677,23 +679,25 @@ class RGooey(Component):
self.clientRunner.run(self.buildCliString())
self.showConsole()
except CalledProcessError as e:
self.showError()
self.console.appendText(str(e))
self.console.appendText(
'\n\nThis failure happens when Gooey tries to invoke your '
'code for the VALIDATE_FORM event and receives an expected '
'error code in response.'
)
wx.CallAfter(modals.showFailure)
pass
# self.showError()
# self.console.appendText(str(e))
# self.console.appendText(
# '\n\nThis failure happens when Gooey tries to invoke your '
# 'code for the VALIDATE_FORM event and receives an expected '
# 'error code in response.'
# )
# wx.CallAfter(modals.showFailure)
except JSONDecodeError as e:
self.showError()
self.console.appendText(str(e))
self.console.appendText(
'\n\nGooey was unable to parse the response to the VALIDATE_FORM event. '
'This can happen if you have additional logs to stdout beyond what Gooey '
'expects.'
)
wx.CallAfter(modals.showFailure)
pass
# self.showError()
# self.console.appendText(str(e))
# self.console.appendText(
# '\n\nGooey was unable to parse the response to the VALIDATE_FORM event. '
# 'This can happen if you have additional logs to stdout beyond what Gooey '
# 'expects.'
# )
# wx.CallAfter(modals.showFailure)
# for some reason, we have to delay the re-enabling of
# the buttons by a few ms otherwise they pickup pending
# events created while they were disabled. Trial and error
@ -705,7 +709,12 @@ class RGooey(Component):
def onStart(self, *args, **kwargs):
messages = {'title': _("running_title"), 'subtitle': _('running_msg')}
self.set_state(s.start(self.state, messages, self.buildSpec))
# self.set_state(s.start(self.state, messages, self.buildSpec))
ss = self.configRef.instance.getFormState()
self.configRef.instance.syncFormState([
{**ss[0], 'value': '11111'},
{**ss[1], 'checked': False}])
print()
def handleInterrupt(self, *args, **kwargs):
messages = {'title': 'Interrupted!!', 'subtitle': 'Boom'}
@ -771,6 +780,7 @@ class RGooey(Component):
'ref': self.consoleRef}],
[RSidebar, {'bg_color': self.buildSpec['sidebar_bg_color'],
'label': 'Some Action!',
'ref': self.configRef,
'show': self.state['screen'] == 'FORM',
'activeSelection': self.state['activeSelection'],
'on_change': self.handle_select_action,

2
gooey/gui/processor.py

@ -12,7 +12,7 @@ from gooey.gui import events
from gooey.gui.pubsub import pub
from gooey.gui.util.casting import safe_float
from gooey.util.functional import unit, bind
from python_bindings.types import GooeyParams
from gooey.python_bindings.types import GooeyParams
class ProcessController(object):

2
gooey/gui/state.py

@ -4,7 +4,7 @@ from typing_extensions import TypedDict
import wx
from gooey.gui import events
from gui.lang.i18n import _
from gooey.gui.lang.i18n import _
from gooey.python_bindings.types import GooeyParams
from gooey.util.functional import associn, assoc, associnMany

2
gooey/python_bindings/argparse_to_json.py

@ -468,7 +468,7 @@ def action_to_json(action, widget, options):
validate_gooey_options(action, widget, final_options)
return {
'id': action.option_strings[0] if action.option_strings else action.dest,
'id': action.dest,
'type': widget,
'cli_type': choose_cli_type(action),
'required': action.required,

55
gooey/python_bindings/types.py

@ -138,16 +138,22 @@ class GooeyField(TypedDict):
class Dropdown(TypedDict):
id: str
type: str
selected: int
choices: List[str]
selected: str
error: str
visible: bool
enabled: bool
class Chooser(TypedDict):
id: str
type: str
label: str
btn_label: str
value: str
placeholder: str
error: str
visible: bool
enabled: bool
class Command(TypedDict):
id: str
@ -159,21 +165,29 @@ class Command(TypedDict):
class Counter(TypedDict):
id: str
type: str
selected: str
selected: int
choices: List[str]
error: str
visible: bool
enabled: bool
class DropdownFilterable(TypedDict):
id: str
type: str
value: str
selected: str
choices: List[str]
error: str
visible: bool
enabled: bool
class ListBox(TypedDict):
id: str
type: str
selected: List[str]
choices: List[str]
selected: List[int]
error: str
visible: bool
enabled: bool
class IntegerField(TypedDict):
@ -182,6 +196,9 @@ class IntegerField(TypedDict):
value: str
min: int
max: int
error: str
visible: bool
enabled: bool
class DecimalField(TypedDict):
@ -191,12 +208,16 @@ class DecimalField(TypedDict):
min: float
max: float
class Slider(TypedDict):
id: str
type: str
value: float
min: float
max: float
error: str
visible: bool
enabled: bool
class Textarea(TypedDict):
id: str
@ -228,17 +249,25 @@ class FieldValue(TypedDict):
class TextField(TypedDict):
id: str
type: str
value: str
placeholder: str
error: Optional[str]
enabled: bool
visible: bool
class PasswordField(TextField):
pass
class Checkbox(TypedDict):
id: str
type: str
checked: bool
error: str
visible: bool
enabled: bool
class RadioGroup(TypedDict):
@ -248,7 +277,21 @@ class RadioGroup(TypedDict):
options: List['FormField']
FormField = Union[Dropdown, Chooser, FieldValue, RadioGroup]
FormField = Union[
Textarea,
Slider,
Command,
Counter,
Checkbox,
TextField,
Dropdown,
Chooser,
FieldValue,
RadioGroup,
DropdownFilterable,
ListBox,
IntegerField
]
class Group(TypedDict):

1
gooey/rewx

@ -1 +0,0 @@
C:/Users/Chris/Documents/re-wx/rewx

1
requirements.txt

@ -5,3 +5,4 @@ colored>=1.3.93
pygtrie>=2.3.3
re-wx>=0.0.2
typing-extensions==3.10.0.2
mypy-extensions==0.4.3
Loading…
Cancel
Save