Browse Source

Fixed issue in widget_pack that returned None for positional args. Minor code cleanup

pull/90/merge
chriskiehl 10 years ago
parent
commit
b1c2a9d0b1
6 changed files with 16 additions and 491 deletions
  1. 464
      gooey/gui/components.py
  2. 12
      gooey/gui/controller.py
  3. 5
      gooey/gui/settings.py
  4. 8
      gooey/gui/widgets/widget_pack.py
  5. 12
      gooey/gui/windows/advanced_config.py
  6. 6
      gooey/gui/windows/base_window.py

464
gooey/gui/components.py

@ -1,464 +0,0 @@
'''
Created on Jan 1, 2014
@author: Chris
TODO:
Sanitize all GetValue inputs
(to check that there's actual data there.
'''
import wx
from abc import ABCMeta
from abc import abstractmethod
from gooey.gui import styling
EMPTY = ''
class BuildException(RuntimeError):
pass
class AbstractGuiComponent(object):
'''
Template pattern-y abstract class for the gui.
Children must all implement the BuildWidget and getValue
methods.
'''
__metaclass__ = ABCMeta
def __init__(self):
self._widget = None
self.msg = EMPTY
def Build(self, parent):
self._widget = self.BuildInputWidget(parent, self._action)
if self.HasHelpMsg(self._action):
self._msg = self.CreateHelpMsgWidget(parent, self._action)
else:
self._msg = None
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.CreateNameLabelWidget(parent, self._action))
sizer.AddSpacer(2)
if self._msg:
sizer.Add(self._msg, 0, wx.EXPAND)
sizer.AddSpacer(2)
else:
sizer.AddStretchSpacer(1)
sizer.AddStretchSpacer(1)
sizer.Add(self._widget, 0, wx.EXPAND)
return sizer
@abstractmethod
def BuildInputWidget(self, parent, action):
''' Must construct the main widget type for the Action '''
pass
def HasHelpMsg(self, action):
return action.help is not None
def CreateHelpMsgWidget(self, parent, action):
base_text = wx.StaticText(parent, label=action.help)
if self.HasNargs(action):
base_text.SetLabelText(base_text.GetLabelText() + self.CreateNargsMsg(action))
styling.MakeDarkGrey(base_text)
return base_text
def HasNargs(self, action):
return action.nargs is not None and action.nargs is not 0
def CreateNargsMsg(self, action):
if isinstance(action.nargs, int):
return '\n(Note: exactly {0} arguments are required)'.format(action.nargs)
elif action.nargs == '+':
return '\n(Note: at least 1 or more arguments are required)'
return ''
def CreateNameLabelWidget(self, parent, action):
label = str(action.dest).title()
if len(action.option_strings) > 1:
label += ' (%s)' % action.option_strings[0]
text = wx.StaticText(parent, label=label)
styling.MakeBold(text)
return text
def AssertInitialization(self, clsname):
if not self._widget:
raise BuildException('%s was not correctly initialized' % clsname)
def __str__(self):
return str(self._action)
@abstractmethod
def GetValue(self):
''' Returns the state of the given widget '''
pass
def Update(self, size):
'''
Manually word wraps the StaticText help objects which would
otherwise not wrap on resize
Content area is based on each grid having two equally sized
columns, where the content area is defined as 87% of the halved
windows width. The wiggle room is the distance +- 10% of the
content_area.
Wrap calculation is run only when the size of the help_msg
extends outside of the wiggle_room. This was done to avoid
the "flickering" that comes from constantly resizing a
StaticText object.
'''
if self._msg is None:
return
help_msg = self._msg
width, height = size
content_area = int((width / 2) * .87)
wiggle_room = range(int(content_area - content_area * .05), int(content_area + content_area * .05))
if help_msg.Size[0] not in wiggle_room:
self._msg.SetLabel(self._msg.GetLabelText().replace('\n', ' '))
self._msg.Wrap(content_area)
class AbstractComponent(object):
'''
Template pattern-y abstract class for the gui.
Children must all implement the BuildWidget and getValue
methods.
'''
__metaclass__ = ABCMeta
def __init__(self):
self._widget = None
self.msg = EMPTY
def Build(self, parent):
self._widget = self.BuildInputWidget(parent, self._action)
if self.HasHelpMsg(self._action):
self._msg = self.CreateHelpMsgWidget(parent, self._action)
else:
self._msg = None
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.CreateNameLabelWidget(parent, self._action))
sizer.AddSpacer(2)
if self._msg:
sizer.Add(self._msg, 0, wx.EXPAND)
sizer.AddSpacer(2)
else:
sizer.AddStretchSpacer(1)
sizer.AddStretchSpacer(1)
sizer.Add(self._widget, 0, wx.EXPAND)
return sizer
@abstractmethod
def BuildInputWidget(self, parent, action):
''' Must construct the main widget type for the Action '''
pass
def HasHelpMsg(self, action):
return action.help is not None
def CreateHelpMsgWidget(self, parent, action):
base_text = wx.StaticText(parent, label=action.help)
if self.HasNargs(action):
base_text.SetLabelText(base_text.GetLabelText() + self.CreateNargsMsg(action))
styling.MakeDarkGrey(base_text)
return base_text
def HasNargs(self, action):
return action.nargs is not None and action.nargs is not 0
def CreateNargsMsg(self, action):
if isinstance(action.nargs, int):
return '\n(Note: exactly {} arguments are required)'.format(action.nargs)
elif action.nargs == '+':
return '\n(Note: at least 1 or more arguments are required)'
return ''
def CreateNameLabelWidget(self, parent, action):
label = str(action.dest).title()
if len(action.option_strings) > 1:
label += ' (%s)' % action.option_strings[0]
text = wx.StaticText(parent, label=label)
styling.MakeBold(text)
return text
def AssertInitialization(self, clsname):
if not self._widget:
raise BuildException('%s was not correctly initialized' % clsname)
def __str__(self):
return str(self._action)
@abstractmethod
def GetValue(self):
''' Returns the state of the given widget '''
pass
def Update(self, size):
'''
Manually word wraps the StaticText help objects which would
otherwise not wrap on resize
Content area is based on each grid having two equally sized
columns, where the content area is defined as 87% of the halved
windows width. The wiggle room is the distance +- 10% of the
content_area.
Wrap calculation is run only when the size of the help_msg
extends outside of the wiggle_room. This was done to avoid
the "flickering" that comes from constantly resizing a
StaticText object.
'''
if self._msg is None:
return
help_msg = self._msg
width, height = size
content_area = int((width / 2) * .87)
wiggle_room = range(int(content_area - content_area * .05), int(content_area + content_area * .05))
if help_msg.Size[0] not in wiggle_room:
self._msg.SetLabel(self._msg.GetLabelText().replace('\n', ' '))
self._msg.Wrap(content_area)
class Positional(AbstractComponent):
"""
Represents a positional argument in a program
e.g.
mypyfile.py param1 <-- this guy
"""
def __init__(self, action):
self._action = action
self._widget = None
self.contents = None
def BuildInputWidget(self, parent, action):
return wx.TextCtrl(parent)
def GetValue(self):
'''
Positionals have no associated options_string,
so only the supplied arguments are returned.
The order is assumed to be the same as the order
of declaration in the client code
Returns
"argument_value"
'''
self.AssertInitialization('Positional')
if str(self._widget.GetValue()) == EMPTY:
return None
return self._widget.GetValue()
class Choice(AbstractComponent):
""" A dropdown box """
_DEFAULT_VALUE = 'Select Option'
def __init__(self, action):
self._action = action
self._widget = None
self.contents = None
def GetValue(self):
'''
Returns
"--option_name argument"
'''
self.AssertInitialization('Choice')
if self._widget.GetValue() == self._DEFAULT_VALUE:
return None
return ' '.join(
[self._action.option_strings[0] if self._action.option_strings else '', # get the verbose copy if available
self._widget.GetValue()])
def BuildInputWidget(self, parent, action):
return wx.ComboBox(
parent=parent,
id=-1,
value=self._DEFAULT_VALUE,
choices=action.choices,
style=wx.CB_DROPDOWN
)
class Optional(AbstractComponent):
def __init__(self, action):
self._action = action
self._widget = None
self.contents = None
def BuildInputWidget(self, parent, action):
return wx.TextCtrl(parent)
def GetValue(self):
'''
General options are key/value style pairs (conceptually).
Thus the name of the option, as well as the argument to it
are returned
e.g.
>>> myscript --outfile myfile.txt
returns
"--Option Value"
'''
self.AssertInitialization('Optional')
value = self._widget.GetValue()
if not value or len(value) <= 0:
return None
return ' '.join(
[self._action.option_strings[0], # get the verbose copy if available
value])
class Flag(AbstractComponent):
def __init__(self, action):
self._action = action
self._widget = None
self.contents = None
def Build(self, parent):
self._widget = self.BuildInputWidget(parent, self._action)
self._msg = (self.CreateHelpMsgWidget(parent, self._action)
if self.HasHelpMsg(self._action)
else None)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.CreateNameLabelWidget(parent, self._action))
sizer.AddSpacer(6)
if self.HasNargs(self._action):
sizer.Add(self.CreateNargsMsg(parent, self._action))
if self._msg:
hsizer = self.buildHorizonalMsgSizer(parent)
sizer.Add(hsizer, 1, wx.EXPAND)
else:
sizer.AddStretchSpacer(1)
sizer.Add(self._widget, 0, wx.EXPAND)
return sizer
def BuildInputWidget(self, parent, action):
return wx.CheckBox(parent, -1, label='')
def buildHorizonalMsgSizer(self, panel):
if not self._msg:
return None
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self._widget, 0)
sizer.AddSpacer(6)
sizer.Add(self._msg, 1, wx.EXPAND)
return sizer
def GetValue(self):
'''
Flag options have no param associated with them.
Thus we only need the name of the option.
e.g
>>> Python -v myscript
returns
Options name for argument (-v)
'''
if not self._widget.GetValue() or len(self._widget.GetValue()) <= 0:
return None
else:
return self._action.option_strings[0]
def Update(self, size):
'''
Custom wrapper calculator to account for the
increased size of the _msg widget after being
inlined with the wx.CheckBox
'''
if self._msg is None:
return
help_msg = self._msg
width, height = size
content_area = int((width / 3) * .70)
wiggle_room = range(int(content_area - content_area * .05), int(content_area + content_area * .05))
if help_msg.Size[0] not in wiggle_room:
self._msg.SetLabel(self._msg.GetLabelText().replace('\n', ' '))
self._msg.Wrap(content_area)
class Counter(AbstractComponent):
def __init__(self, action):
self._action = action
self._widget = None
self.contents = None
def BuildInputWidget(self, parent, action):
levels = [str(x) for x in range(1, 7)]
return wx.ComboBox(
parent=parent,
id=-1,
value='',
choices=levels,
style=wx.CB_DROPDOWN
)
def GetValue(self):
'''
NOTE: Added on plane. Cannot remember exact implementation
of counter objects. I believe that they count sequentail
pairings of options
e.g.
-vvvvv
But I'm not sure. That's what I'm going with for now.
Returns
str(action.options_string[0]) * DropDown Value
'''
dropdown_value = self._widget.GetValue()
if not str(dropdown_value).isdigit():
return None
arg = str(self._action.option_strings[0]).replace('-', '')
repeated_args = arg * int(dropdown_value)
return '-' + repeated_args
class Group(AbstractComponent):
def __init__(self, action):
self._action = action
self._widget = None
self.contents = None
if __name__ == '__main__':
pass

12
gooey/gui/controller.py

@ -24,17 +24,13 @@ class Controller(object):
Main controller for the gui. Main controller for the gui.
All controlls are delegated to this central control point. All controlls are delegated to this central control point.
Args:
base_frame = Reference to the Basewindow
head_panel = reference to the BaseWindow's Head Panel
body_panel = reference to the BaseWindow's Body Panel
footer_panel = reference to the BaseWindow's Footer Panel
model = configuration model
translator = instance of the I18N class
''' '''
def __init__(self, base_frame, build_spec): def __init__(self, base_frame, build_spec):
'''
:param base_frame: BaseWindow
:param build_spec: Json
'''
self.core_gui = base_frame self.core_gui = base_frame
self.build_spec = build_spec self.build_spec = build_spec

5
gooey/gui/settings.py

@ -0,0 +1,5 @@
import os
CONFIG_PATH = os.getcwd()

8
gooey/gui/widgets/widget_pack.py

@ -58,11 +58,11 @@ class BaseChooser(WidgetPack):
return widget_sizer return widget_sizer
def getValue(self): def getValue(self):
if self.option_string and self.text_box.GetValue() and len(self.text_box.GetValue()) > 0:
return '{0} "{1}"'.format(self.option_string, self.text_box.GetValue())
value = self.text_box.GetValue()
if self.option_string and value:
return '{0} "{1}"'.format(self.option_string, value)
else: else:
#return '"{}"'.format(self.text_box.GetValue())
return None
return '"{}"'.format(value) if value else None
def onButton(self, evt): def onButton(self, evt):
raise NotImplementedError raise NotImplementedError

12
gooey/gui/windows/advanced_config.py

@ -114,17 +114,11 @@ class AdvancedConfigPanel(ScrolledPanel, OptionReader):
return ' '.join(values) return ' '.join(values)
def GetRequiredArgs(self): def GetRequiredArgs(self):
if not self.components.required_args:
return None
else:
return [arg.GetValue() for arg in self.components.required_args]
return [arg.GetValue() for arg in self.components.required_args]
def GetOptionalArgs(self): def GetOptionalArgs(self):
if not self.components.general_args:
return None
else:
return [arg.GetValue() for arg in
chain(self.components.general_options, self.components.flags)]
# Not used anywhere. Keep for debugging?
return filter(None, [arg.GetValue() for arg in chain(self.components.general_options, self.components.flags)])
if __name__ == '__main__': if __name__ == '__main__':

6
gooey/gui/windows/base_window.py

@ -97,9 +97,6 @@ class BaseWindow(wx.Frame):
self.runtime_display.Show() self.runtime_display.Show()
self.Layout() self.Layout()
# def AttachPayload(self, payload):
# self._payload = payload
def ManualStart(self): def ManualStart(self):
self._controller.ManualStart() self._controller.ManualStart()
@ -108,9 +105,6 @@ class BaseWindow(wx.Frame):
def PublishConsoleMsg(self, text): def PublishConsoleMsg(self, text):
self.runtime_display.cmd_textbox.AppendText(text) self.runtime_display.cmd_textbox.AppendText(text)
# evt = MessageEvent(message=text)
# self.GetEventHandler().ProcessEvent(evt)
# wx.PostEvent(self.runtime_display, evt)
if __name__ == '__main__': if __name__ == '__main__':

Loading…
Cancel
Save