mirror of https://github.com/chriskiehl/Gooey.git
Browse Source
Added WidgetPack interface, added components2 - experimental structure for gui elements
pull/61/head
Added WidgetPack interface, added components2 - experimental structure for gui elements
pull/61/head
6 changed files with 404 additions and 1 deletions
Unified View
Diff Options
-
2gooey/gui/chooser_runner.py
-
0gooey/gui/choosers.py
-
26gooey/gui/componenets2_runner.py
-
116gooey/gui/components.py
-
101gooey/gui/components2.py
-
160gooey/gui/widget_pack.py
@ -0,0 +1,26 @@ |
|||||
|
__author__ = 'Chris' |
||||
|
|
||||
|
import wx |
||||
|
import components2 |
||||
|
|
||||
|
|
||||
|
class MyFrame(wx.Frame): |
||||
|
def __init__(self, parent): |
||||
|
wx.Frame.__init__(self, parent, title="test", size=(320, 240)) |
||||
|
self.SetBackgroundColour('#ffffff') |
||||
|
|
||||
|
sizer = wx.BoxSizer(wx.VERTICAL) |
||||
|
f = components2.Counter({ |
||||
|
'title': 'cool title', |
||||
|
'help_msg': 'cool help msg that is super long and intense andd has lots of words!', 'nargs': '+', |
||||
|
'option_strings': ['-f', '--fudger'], |
||||
|
'choices': ['choice 1', 'choice 2', 'choice 3'] |
||||
|
}) |
||||
|
sizer.Add(f.build(self), 0, wx.EXPAND) |
||||
|
self.SetSizer(sizer) |
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
app = wx.App(False) |
||||
|
frame = MyFrame(None) |
||||
|
frame.Show(True) |
||||
|
app.MainLoop() |
@ -0,0 +1,101 @@ |
|||||
|
__author__ = 'Chris' |
||||
|
|
||||
|
import wx |
||||
|
import styling |
||||
|
|
||||
|
import widget_pack |
||||
|
|
||||
|
class BaseGuiComponent(object): |
||||
|
def __init__(self, data, widget_pack): |
||||
|
self.data = data |
||||
|
|
||||
|
# parent |
||||
|
self.panel = None |
||||
|
|
||||
|
# Widgets |
||||
|
self.title = None |
||||
|
self.help_msg = None |
||||
|
|
||||
|
# Internal WidgetPack |
||||
|
self.widget_pack = widget_pack |
||||
|
|
||||
|
def build(self, parent): |
||||
|
return self.do_layout(parent) |
||||
|
|
||||
|
def do_layout(self, parent): |
||||
|
self.panel = wx.Panel(parent) |
||||
|
|
||||
|
self.title = self.createTitle(self.panel) |
||||
|
self.help_msg = self.createHelpMsgWidget(self.panel) |
||||
|
core_widget_set = self.widget_pack.build(self.panel, self.data) |
||||
|
|
||||
|
vertical_container = wx.BoxSizer(wx.VERTICAL) |
||||
|
|
||||
|
vertical_container.Add(self.title) |
||||
|
vertical_container.AddSpacer(2) |
||||
|
|
||||
|
if self.help_msg.GetLabelText(): |
||||
|
vertical_container.Add(self.help_msg, 1, wx.EXPAND) |
||||
|
vertical_container.AddSpacer(2) |
||||
|
else: |
||||
|
vertical_container.AddStretchSpacer(1) |
||||
|
|
||||
|
vertical_container.Add(core_widget_set, 0, wx.EXPAND) |
||||
|
self.panel.SetSizer(vertical_container) |
||||
|
|
||||
|
self.panel.Bind(wx.EVT_SIZE, self.onResize) |
||||
|
return self.panel |
||||
|
|
||||
|
def createHelpMsgWidget(self, parent): |
||||
|
label_text = (self.formatExtendedHelpMsg(self.data) |
||||
|
if self.data['nargs'] |
||||
|
else self.data['help_msg']) |
||||
|
base_text = wx.StaticText(parent, label=label_text) |
||||
|
styling.MakeDarkGrey(base_text) |
||||
|
return base_text |
||||
|
|
||||
|
def createTitle(self, parent): |
||||
|
text = wx.StaticText(parent, label=self.data['title'].title()) |
||||
|
styling.MakeBold(text) |
||||
|
return text |
||||
|
|
||||
|
def formatExtendedHelpMsg(self, data): |
||||
|
base_text = data['help_msg'] |
||||
|
nargs = data['nargs'] |
||||
|
if isinstance(nargs, int): |
||||
|
return '{base}\n(Note: exactly {nargs} arguments are required)'.format(base=base_text, nargs=nargs) |
||||
|
elif nargs == '+': |
||||
|
return '{base}\n(Note: at least 1 or more arguments are required)'.format(base=base_text) |
||||
|
return base_text |
||||
|
|
||||
|
def onResize(self, evt): |
||||
|
# handle internal widgets |
||||
|
self._onResize(evt) |
||||
|
# propagate event to child widgets |
||||
|
self.widget_pack.onResize(evt) |
||||
|
evt.Skip() |
||||
|
|
||||
|
def _onResize(self, evt): |
||||
|
if self.help_msg is None: |
||||
|
return |
||||
|
container_width, _ = self.panel.Size |
||||
|
text_width, _ = self.help_msg.Size |
||||
|
|
||||
|
if text_width != container_width: |
||||
|
self.help_msg.SetLabel(self.help_msg.GetLabelText().replace('\n', ' ')) |
||||
|
self.help_msg.Wrap(container_width) |
||||
|
|
||||
|
def getValue(self): |
||||
|
return self.widget_pack.getValue() |
||||
|
|
||||
|
|
||||
|
FileChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.FileChooserPayload()) |
||||
|
DirChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.DirChooserPayload()) |
||||
|
DateChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.DateChooserPayload()) |
||||
|
TextField = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.TextInputPayload()) |
||||
|
Dropdown = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.DropdownPayload()) |
||||
|
Counter = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.CounterPayload()) |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
@ -0,0 +1,160 @@ |
|||||
|
|
||||
|
|
||||
|
__author__ = 'Chris' |
||||
|
|
||||
|
import wx |
||||
|
from abc import ABCMeta, abstractmethod |
||||
|
from calender_dialog import CalendarDlg |
||||
|
|
||||
|
|
||||
|
class WidgetPack(object): |
||||
|
""" |
||||
|
Interface specifying the contract to which |
||||
|
all `WidgetPack`s will adhere |
||||
|
""" |
||||
|
__metaclass__ = ABCMeta |
||||
|
|
||||
|
@abstractmethod |
||||
|
def build(self, parent, data): |
||||
|
pass |
||||
|
|
||||
|
@abstractmethod |
||||
|
def getValue(self): |
||||
|
pass |
||||
|
|
||||
|
def onResize(self, evt): |
||||
|
pass |
||||
|
|
||||
|
|
||||
|
|
||||
|
class BaseChooser(WidgetPack): |
||||
|
def __init__(self, button_text='Browse'): |
||||
|
self.button_text = button_text |
||||
|
|
||||
|
self.parent = None |
||||
|
self.text_box = None |
||||
|
self.button = None |
||||
|
|
||||
|
def build(self, parent, data=None): |
||||
|
self.parent = parent |
||||
|
self.text_box = wx.TextCtrl(self.parent) |
||||
|
self.button = wx.Button(self.parent, label=self.button_text, size=(73, 23)) |
||||
|
|
||||
|
widget_sizer = wx.BoxSizer(wx.HORIZONTAL) |
||||
|
widget_sizer.Add(self.text_box, 1, wx.EXPAND) |
||||
|
widget_sizer.AddSpacer(10) |
||||
|
widget_sizer.Add(self.button, 0) |
||||
|
|
||||
|
parent.Bind(wx.EVT_BUTTON, self.onButton, self.button) |
||||
|
return widget_sizer |
||||
|
|
||||
|
def getValue(self): |
||||
|
return self.text_box.GetValue() |
||||
|
|
||||
|
def onButton(self, evt): |
||||
|
raise NotImplementedError |
||||
|
|
||||
|
|
||||
|
class FileChooserPayload(BaseChooser): |
||||
|
def __init__(self): |
||||
|
BaseChooser.__init__(self) |
||||
|
|
||||
|
def onButton(self, evt): |
||||
|
dlg = wx.FileDialog(self.parent, style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) |
||||
|
result = (dlg.GetPath() |
||||
|
if dlg.ShowModal() == wx.ID_OK |
||||
|
else None) |
||||
|
if result: |
||||
|
# self.text_box references a field on the class this is passed into |
||||
|
# kinda hacky, but avoided a buncha boilerplate |
||||
|
self.text_box.SetLabelText(result) |
||||
|
|
||||
|
|
||||
|
class DirChooserPayload(BaseChooser): |
||||
|
def __init__(self): |
||||
|
BaseChooser.__init__(self) |
||||
|
|
||||
|
def onButton(self, evt): |
||||
|
dlg = wx.DirDialog(self.parent, 'Select directory', style=wx.DD_DEFAULT_STYLE) |
||||
|
result = (dlg.GetPath() |
||||
|
if dlg.ShowModal() == wx.ID_OK |
||||
|
else None) |
||||
|
if result: |
||||
|
self.text_box.SetLabelText(result) |
||||
|
|
||||
|
|
||||
|
class DateChooserPayload(BaseChooser): |
||||
|
def __init__(self): |
||||
|
BaseChooser.__init__(self, button_text='Pick Date') |
||||
|
|
||||
|
def onButton(self, evt): |
||||
|
dlg = CalendarDlg(self.parent) |
||||
|
dlg.ShowModal() |
||||
|
if dlg.GetPath(): |
||||
|
self.text_box.SetLabelText(dlg.GetPath()) |
||||
|
|
||||
|
|
||||
|
class TextInputPayload(WidgetPack): |
||||
|
def __init__(self): |
||||
|
self.widget = None |
||||
|
|
||||
|
def build(self, parent, data): |
||||
|
self.widget = wx.TextCtrl(parent) |
||||
|
return self.widget |
||||
|
|
||||
|
def getValue(self): |
||||
|
return self.widget.GetValue() |
||||
|
|
||||
|
|
||||
|
class DropdownPayload(WidgetPack): |
||||
|
default_value = 'Select Option' |
||||
|
def __init__(self): |
||||
|
self.option_string = None |
||||
|
self.widget = None |
||||
|
|
||||
|
def build(self, parent, data): |
||||
|
self.option_string = data['option_strings'][0] |
||||
|
self.widget = wx.ComboBox( |
||||
|
parent=parent, |
||||
|
id=-1, |
||||
|
value=self.default_value, |
||||
|
choices=data['choices'], |
||||
|
style=wx.CB_DROPDOWN |
||||
|
) |
||||
|
return self.widget |
||||
|
|
||||
|
def getValue(self): |
||||
|
if self.widget.GetValue() == self.default_value: |
||||
|
return None |
||||
|
return ' '.join([self.option_string, self.widget.GetValue()]) |
||||
|
|
||||
|
|
||||
|
class CounterPayload(WidgetPack): |
||||
|
def __init__(self): |
||||
|
self.option_string = None |
||||
|
self.widget = None |
||||
|
|
||||
|
def build(self, parent, data): |
||||
|
self.option_string = data['option_strings'][0] |
||||
|
self.widget = wx.ComboBox( |
||||
|
parent=parent, |
||||
|
id=-1, |
||||
|
value='', |
||||
|
choices=[str(x) for x in range(1, 7)], |
||||
|
style=wx.CB_DROPDOWN |
||||
|
) |
||||
|
return self.widget |
||||
|
|
||||
|
def getValue(self): |
||||
|
''' |
||||
|
Returns |
||||
|
str(option_string * DropDown Value) |
||||
|
e.g. |
||||
|
-vvvvv |
||||
|
''' |
||||
|
dropdown_value = self.widget.GetValue() |
||||
|
if not str(dropdown_value).isdigit(): |
||||
|
return None |
||||
|
arg = str(self.option_string).replace('-', '') |
||||
|
repeated_args = arg * int(dropdown_value) |
||||
|
return '-' + repeated_args |
xxxxxxxxxx