From e8ef53d3af9ba663a8f9b60f819be62767da886e Mon Sep 17 00:00:00 2001 From: Chris Kiehl Date: Fri, 17 Jan 2014 01:12:40 -0500 Subject: [PATCH] nightly work. Added unittests from advanced_config. Fixed bug in ActionSorter, tweaked display elements, fixed wrapping --- src/app/dialogs/action_sorter.py | 9 +- src/app/dialogs/action_sorter_unittest.py | 80 +++++++++++++++ src/app/dialogs/advanced_config.py | 74 +++++++++++--- src/app/dialogs/advanced_config.pyc | Bin 1914 -> 4229 bytes src/app/dialogs/advanced_config_unittest.py | 26 +++-- src/app/dialogs/argparse_test_data.py | 22 ++++ src/app/dialogs/component_factory.py | 29 ++++-- src/app/dialogs/component_factory.pyc | Bin 2725 -> 3070 bytes src/app/dialogs/components.py | 105 ++++++++++++++++++-- src/app/dialogs/components_unittest.py | 10 +- src/app/dialogs/simple_config_panel.py | 3 +- src/experiments/__init__.py | 0 src/experiments/command.py | 22 ++++ 13 files changed, 324 insertions(+), 56 deletions(-) create mode 100644 src/app/dialogs/action_sorter_unittest.py create mode 100644 src/app/dialogs/argparse_test_data.py create mode 100644 src/experiments/__init__.py create mode 100644 src/experiments/command.py diff --git a/src/app/dialogs/action_sorter.py b/src/app/dialogs/action_sorter.py index 6296bf0..ae3832e 100644 --- a/src/app/dialogs/action_sorter.py +++ b/src/app/dialogs/action_sorter.py @@ -9,7 +9,7 @@ import wx from argparse import ( _StoreAction, _StoreConstAction, _StoreFalseAction, _StoreTrueAction, - _CountAction, _AppendAction) + _CountAction, _AppendAction, _HelpAction) DEBUG = 1 @@ -58,7 +58,7 @@ class ActionSorter(object): self._positionals = self.get_positionals(self._actions) self._choices = self.get_optionals_with_choices(self._actions) self._optionals = self.get_optionals_without_choices(self._actions) - self._flags = self.get_flag_style_optionals(self._actions) + self._flags = self.get_flag_style_optionals(self._actions) self._counters = self.get_counter_actions(self._actions) if DEBUG: @@ -67,6 +67,7 @@ class ActionSorter(object): self._display('ActionSorter: optionals', self._optionals) self._display('ActionSorter: booleans', self._flags) self._display('ActionSorter: counters', self._counters) + print '|-------------------------' def _display(self, _type, something): for i in something: @@ -106,7 +107,9 @@ class ActionSorter(object): for action in actions if action.option_strings and not action.choices - and action not in boolean_actions] + and not isinstance(action, _CountAction) + and not isinstance(action, _HelpAction) + and type(action) not in boolean_actions] def get_optionals_with_choices(self, actions): ''' diff --git a/src/app/dialogs/action_sorter_unittest.py b/src/app/dialogs/action_sorter_unittest.py new file mode 100644 index 0000000..bcbe5bb --- /dev/null +++ b/src/app/dialogs/action_sorter_unittest.py @@ -0,0 +1,80 @@ +''' +Created on Jan 16, 2014 + +@author: Chris +''' + +import time +import unittest +import argparse_test_data +from functools import partial +from argparse import _StoreAction, _HelpAction +from action_sorter import ActionSorter + +class Test(unittest.TestCase): + + + def setUp(self): + self._actions = argparse_test_data.parser._actions + self.sorted_actions = ActionSorter(self._actions) + # pain in the A... PEP8 be damned! + self.expected_positionals = [ + "_StoreAction(option_strings=[], dest='filename', nargs=None, const=None, default=None, type=None, choices=None, help='Name of the file you want to read', metavar=None)", + '''_StoreAction(option_strings=[], dest='outfile', nargs=None, const=None, default=None, type=None, choices=None, help="Name of the file where you'll save the output", metavar=None)''' + ] + self.expected_choices = [ + '''_StoreAction(option_strings=['-T', '--tester'], dest='tester', nargs=None, const=None, default=None, type=None, choices=['yes', 'no'], help="Yo, what's up man? I'm a help message!", metavar=None)''' + ] + self.expected_optionals = [ + '''_StoreAction(option_strings=['-o', '--outfile'], dest='outfile', nargs=None, const=None, default=None, type=None, choices=None, help='Redirects output to the file specified by you, the awesome user', metavar=None)''', + '''_StoreAction(option_strings=['-v', '--verbose'], dest='verbose', nargs=None, const=None, default=None, type=None, choices=None, help='Toggles verbosity off', metavar=None)''', + '''_StoreAction(option_strings=['-s', '--schimzammy'], dest='schimzammy', nargs=None, const=None, default=None, type=None, choices=None, help='Add in an optional shimzammy parameter', metavar=None)''' + ] + self.expected_counters = [ + '''_CountAction(option_strings=['-e', '--repeat'], dest='repeat', nargs=0, const=None, default=None, type=None, choices=None, help='Set the number of times to repeat', metavar=None)''' + ] + + self.expected_flags = [ + '''_StoreConstAction(option_strings=['-c', '--constoption'], dest='constoption', nargs=0, const='myconstant', default=None, type=None, choices=None, help='Make sure the const action is correctly sorted', metavar=None)''', + '''_StoreTrueAction(option_strings=['-t', '--truify'], dest='truify', nargs=0, const=True, default=False, type=None, choices=None, help='Ensure the store_true actions are sorted', metavar=None)''', + '''_StoreFalseAction(option_strings=['-f', '--falsificle'], dest='falsificle', nargs=0, const=False, default=True, type=None, choices=None, help='Ensure the store_false actions are sorted', metavar=None)''' + ] + + def testPositionalsReturnsOnlyPositionalActions(self): + positionals = self.sorted_actions._positionals + self.assertEqual(len(positionals), 2) + + self.assertForAllActionsInList(positionals,self.expected_positionals) + + def testHelpActionNotInOptionals(self): + _isinstance = lambda x: isinstance(x, _HelpAction) + self.assertFalse(any(map(_isinstance, self.sorted_actions._optionals))) + + def testChoicesOnlyReturnsChoices(self): + self.assertForAllActionsInList(self.sorted_actions._choices, + self.expected_choices) + + def testOptionalsOnlyReturnsOptionals(self): + self.assertForAllActionsInList(self.sorted_actions._optionals, + self.expected_optionals) + + def testCounterSortOnlyReturnsCounters(self): + self.assertForAllActionsInList(self.sorted_actions._counters, + self.expected_counters) + + def testFlagSortReturnsOnlyFlags(self): + self.assertForAllActionsInList(self.sorted_actions._flags, + self.expected_flags) + + def assertForAllActionsInList(self, actions, expected_actions): + for index, action in enumerate(actions): + self.assertEqual(str(action), expected_actions[index]) + + + + + + +if __name__ == "__main__": + #import sys;sys.argv = ['', 'Test.testName'] + unittest.main() \ No newline at end of file diff --git a/src/app/dialogs/advanced_config.py b/src/app/dialogs/advanced_config.py index e32e984..9f5a130 100644 --- a/src/app/dialogs/advanced_config.py +++ b/src/app/dialogs/advanced_config.py @@ -5,11 +5,13 @@ Created on Dec 28, 2013 ''' import wx - +import components +from wx.lib import wordwrap +from itertools import chain from component_factory import ComponentFactory from wx.lib.scrolledpanel import ScrolledPanel - +PADDING = 10 class AdvancedConfigPanel(ScrolledPanel): @@ -23,25 +25,67 @@ class AdvancedConfigPanel(ScrolledPanel): self.components = ComponentFactory(parser) self.container = wx.BoxSizer(wx.VERTICAL) + self.container.AddSpacer(15) + + self.AddHeaderMsg("Required Arguments") self.container.AddSpacer(10) - self.AddRequiredArgsHeaderMsg() - self.AddWidgets(self.components.positionals) + box = wx.StaticBox(self, label="") + boxsizer = wx.StaticBoxSizer(box, wx.VERTICAL) + self.AddWidgets(self.container, self.components.positionals, add_space=True) + self.container.AddSpacer(10) + self.container.Add(self._draw_horizontal_line(), + 0, wx.LEFT | wx.RIGHT | wx.EXPAND, PADDING) + + self.container.AddSpacer(10) + self.AddHeaderMsg("Optional Arguments") + self.container.AddSpacer(15) + + flag_grids = self.CreateComponentGrid(self.components.flags, vgap=15) + opt_choice_counter_grid = self.CreateComponentGrid(c for c in self.components + if not isinstance(c, components.Flag) + and not isinstance(c, components.Positional)) + self.container.Add(opt_choice_counter_grid, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, PADDING) + self.container.AddSpacer(30) + self.container.Add(flag_grids, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, PADDING) + +# sizer_params = [(grid, 0, wx.LEFT|wx.RIGHT|wx.EXPAND, PADDING) +# for grid in component_grids] +# self.container.AddMany(sizer_params) self.SetSizer(self.container) + self.Bind(wx.EVT_SIZE, self.OnResize) - def AddRequiredArgsHeaderMsg(self): - required_msg = wx.StaticText(self, label="Required Arguments") - self.container.Add(required_msg, 0, wx.LEFT | wx.RIGHT, 20) - - def AddWidgets(self, components): - if not components: - return - component = components[0] - widget_group = component.Build(parent=self) - self.container.Add(widget_group) - self.AddWidgets(components[1:]) + def AddHeaderMsg(self, label): + required_msg = wx.StaticText(self, label=label) + font_size = required_msg.GetFont().GetPointSize() + bold = wx.Font(font_size*1.2, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD) + required_msg.SetFont(bold) + self.container.Add(required_msg, 0, wx.LEFT | wx.RIGHT, PADDING) + + + def AddWidgets(self, sizer, components, add_space=False, padding=PADDING): + for component in components: + widget_group = component.Build(parent=self) + sizer.Add(widget_group, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, padding) + if add_space: + sizer.AddSpacer(8) + + def CreateComponentGrid(self, components, cols=2, vgap=10): + gridsizer = wx.GridSizer(rows=0, cols=cols, vgap=vgap,hgap=4) + self.AddWidgets(gridsizer, components) + return gridsizer + + def _draw_horizontal_line(self): + line = wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL) + line.SetSize((10, 10)) + return line + + def OnResize(self, evt): + print evt.m_size + for component in self.components: + component.Update(evt.m_size) diff --git a/src/app/dialogs/advanced_config.pyc b/src/app/dialogs/advanced_config.pyc index aa35c90763cde28719d85aac50021a844ca813b2..81da9b857b5dee72e725476fb6be2ecaae1942cf 100644 GIT binary patch literal 4229 zcmcInTXP##67CsYEXg)DPGT0qg4lwJNKvi;FBF@~B41;0WY@?^HY%s4#xrAi%t)im z9K|*jS5akN_JM!3KVtvFKC|z;-`7XJzzaOAWuMl$pFZ7Re|=Q?Ww!C3fBwr0W%4QE z`x}(vXNX9o2kA)UO6o`t66OLdSXt7F464$r+IB_KDH+tHSF`P^ zq;(lIq}M=uN_x{0)g*4n0oK;#Cy{fJ7rhyYXC-RL_papskReoXrQ4dOTAxBRR`NJ7 zan#I)&DA(;e(}|3%`YB&{$-=_O)xfxS^jl%-DG*R#yTd2>XKi=}3x9@4qA18@EvO7U-) z#)up_@ycHoor2Ina8gwN;F5XkGh_)>l_r)SaQlJA|s<)j6wb=OV!h&sa5Aac}&e zO=%lCLMQn24{9@gT>-2FEPi+8pC%_=82nwm@_X8Qm*#XLAhg|z9vSE;3tu|$hz3vC2kOAkS zaHoRhuMjZK%g^P^A>aTt<0!^lnaNAny5J1kg(=URSBMd6&J8;)?r#`+Ns$Z-!@$#K zcoDUQs<560eeK`Lio`0}qBe$N=>ZN#+_xY^Me!|aD_`$DE#kb`Q{vcL&9l*dcCt6h zV`EPJ{y5p&$g=o!ugJr_U^Lo`k|53c#a=Lpe?L?LSQ?!cwAaIaJd969`J*K?iYi1^ zO3p1O`2f|{`w$*uQAx@7lVM_f-@JvMZfwRQ%QeZc?@?n<$%eJ#6J4;Joph5Q;#?cg z*1X-#mG+jp2}&678HT7tJBqsWS#Icfv>wMn6z5Nhz7BUyV3H7<*@G`yc59xA70;8X zADhCEdPkSmv}WGT$1&(Z=OLy<{3s8Oeb8_61NBJ#6so94w$|2n5q-GJ=Emb)Lwl_K zeW%@7HB+eWv{zR*I~&TUmf0_9cq30DU3dVW7J6Y=$f`&*EGNTAd)J=r`rXamnl`qF zUR=OJEpnYIP{iqh9yZOybQdqd*GW}$GPKt=*~L}&Igd}x$C@Ny6?<8 z_bc;GNZ`=)EGsC*j}Vuf4;n+Dk%e6ny=DC)1fj^8h9zhhNdaVjn`MMBVGbT>XR zij#ie!3QFQD4w6E5`!lju6Y4n7g2 zy6tCabaU`ngenhF3Yts+hXv;o03oEF3^2xdU8^W04Z|fd_Iv7folN zWncnX$0cC`3Y2Ad4__5ork|NTOOhkMVX{73n0Q`I3I3m7bML1(PQ98i5L;A5gL!$J zq>;5OJ?&kYx5*}vu9H2QOjl?qDiM0R3&jXY2^={gzR9~yopG$Jg_z97qnoq(yU<}3 zWn%SNSpA+;brJ@gCen}~rw>TRYX7fLVMyR1h<}X`#)%Cveej)2nIVNah(}Zqn|zOz zkpp?>j-n~gjtjM`w!$neJQ`SAhseJP4{ntpY$Wk~GHI8D=27o!5GH24HihoNxyp2$ zdvnJ73y#qjD6uKd$6%{py&BY9pJB+F3kImvt zL7ck`XhMr_Wl;+~K!s+2e;=QGq_}Yq+lz8Z=XO-%b72yk_A$jhH2DpbrtB+&-gr8S z@Z-wDhu71z7{4~&BQ$RAzV~=E%H+N^AVPofX*Tx#VK9jCMj~2$e~?AvlubIv_oFQI zeNB=csZf2t9;8LAbgh8*2sn>6^?16TC4@#z3d@4EMf#^!f+(x2irC4U?8#y;Mwo tvg!{&eQ#QODEOaX-pyJ;Z~D->>JcNepl(%n#+iX{_0O%A7QdTu{s+mpi3tDz delta 907 zcmX|;&2G~`5XWcMA4!}vHcbOmDbOHw-qz?2c>%vEXCBR|Vg|q-k0bU50K7%npBA^o% zPrmKwGTzj8vFRZdZ}9^+bRU~*iN%+xp6rCS{*HHin>N`V^Pvx*Q5^12ahwAT%D~=+ zK?RohFSTY;MH44LuL-)>&OGvAm7GNV&bd~j737?ZC!?2>aXQYG{_5P{x=5+LB$4T> zSvF0Rz3H)fm_|uDJy6H`g1cQU(t%Ezce1zXlobAQZ|mP)_dWNCi>iPeU=2Oti#i6v z!A)*PB~dw?Mk0RZcENsXTvqO6wi!_8hrjbnc@YYi#B?= zjsb?Q{!+bFW-iItvZ7D@=#gY#F0FX{uH|CMFWETT-$>9u{YzzrF(u^|l~)0)a79G~7&zyf75od~dzOd* diff --git a/src/app/dialogs/advanced_config_unittest.py b/src/app/dialogs/advanced_config_unittest.py index 3942a35..63f703b 100644 --- a/src/app/dialogs/advanced_config_unittest.py +++ b/src/app/dialogs/advanced_config_unittest.py @@ -9,24 +9,18 @@ import os import sys import unittest import advanced_config +import argparse_test_data from argparse import ArgumentParser -class Test(unittest.TestCase): - +class TestAdvancedConfigPanel(unittest.TestCase): def setUp(self): - parser = ArgumentParser(description='Example Argparse Program') - parser.add_argument("filename", help="Name of the file you want to read") - parser.add_argument('-T', '--tester', choices=['yes','no']) - parser.add_argument('-o', '--outfile', help='Redirects output to the specified file') - parser.add_argument('-v', '--verbose', help='Toggles verbosity off') - parser.add_argument('-e', '--repeat', action='count', help='Set the number of times to repeat') - self.parser = parser + self.parser = argparse_test_data.parser def buildWindow(self): app = wx.PySimpleApp() module_name = os.path.split(sys.argv[0])[-1] - frame = wx.Frame(None, -1, module_name) + frame = wx.Frame(None, -1, module_name, size=(640,480)) panel = advanced_config.AdvancedConfigPanel(frame, self.parser) frame.Show() @@ -38,4 +32,14 @@ class Test(unittest.TestCase): if __name__ == "__main__": #import sys;sys.argv = ['', 'Test.testName'] - unittest.main() \ No newline at end of file + unittest.main() + + + + + + + + + + \ No newline at end of file diff --git a/src/app/dialogs/argparse_test_data.py b/src/app/dialogs/argparse_test_data.py new file mode 100644 index 0000000..032cc17 --- /dev/null +++ b/src/app/dialogs/argparse_test_data.py @@ -0,0 +1,22 @@ +''' +Created on Jan 16, 2014 + +@author: Chris +''' + +from argparse import ArgumentParser + + +parser = ArgumentParser(description='Example Argparse Program') +parser.add_argument("filename", help="Name of the file you want to read") # positional +parser.add_argument("outfile", help="Name of the file where you'll save the output") # positional +parser.add_argument('-T', '--tester', choices=['yes','no'], help="Yo, what's up man? I'm a help message!") # Choice +parser.add_argument('-o', '--outfile', help='Redirects output to the file specified by you, the awesome user') # Optional +parser.add_argument('-v', '--verbose', help='Toggles verbosity off') # Optional +parser.add_argument('-s', '--schimzammy', help='Add in an optional shimzammy parameter') # Optional +parser.add_argument('-e', '--repeat', action='count', help='Set the number of times to repeat') # Counter +parser.add_argument('-c', '--constoption', action="store_const", const="myconstant", help='Make sure the const action is correctly sorted') # Flag +parser.add_argument('-t', '--truify', action="store_true", help='Ensure the store_true actions are sorted') # Flag +parser.add_argument('-f', '--falsificle', action="store_false", help='Ensure the store_false actions are sorted') # Flag + + \ No newline at end of file diff --git a/src/app/dialogs/component_factory.py b/src/app/dialogs/component_factory.py index 98f1af8..5fbbd16 100644 --- a/src/app/dialogs/component_factory.py +++ b/src/app/dialogs/component_factory.py @@ -4,9 +4,10 @@ Created on Dec 8, 2013 @author: Chris ''' -import wx +import itertools import components import action_sorter +import argparse_test_data class ComponentFactory(object): @@ -22,16 +23,16 @@ class ComponentFactory(object): self.positionals = self.BuildPositionals(self._actions) self.choices = self.BuildChoices(self._actions) self.optionals = self.BuildOptionals(self._actions) - self.booleans = self.BuildFlags(self._actions) + self.flags = self.BuildFlags(self._actions) self.counters = self.BuildCounters(self._actions) self._components = [ - self.positionals, - self.choices, - self.optionals, - self.booleans, - self.counters - ] + self.positionals, + self.choices, + self.optionals, + self.flags, + self.counters + ] def BuildPositionals(self, actions): return self._AssembleWidgetsFromActions(actions, 'Positional', '_positionals') @@ -53,11 +54,19 @@ class ComponentFactory(object): actions_list = getattr(actions, actiontype) return [cls(action) for action in actions_list] + +# def __getitem__(self, slice): +# return self._components[slice] + def __iter__(self): + ''' + return an iterator for all of the contained + components + ''' + return itertools.chain(*self._components) if __name__ == '__main__': - pass - + a = ComponentFactory(argparse_test_data.parser) diff --git a/src/app/dialogs/component_factory.pyc b/src/app/dialogs/component_factory.pyc index 6c2b340d637e8c687920fc2f75fb93c6d40d4da5..d73e05acaffb590af7e5c7ce39ebf0f74f3c36f4 100644 GIT binary patch delta 554 zcmX|7J!{-R5S`K2X%%12Tu1_T5kW8!F&GSnfJ4BL-h~VXUtzJ4_Re>aC8Hg81{aso zg%71qmC{AHACNzgCXGp*K9&368DXs9Jv|NYX=eBP^Zzf`-MfBtd-EsF;o))ly~nWC zVtwm9Lg7H^!N`Nc1>?h*J05%im;)S*0x&%&eE94@GXuk)9?U|RBaGByI>E!m@BMxe zihmSAdXT8)Yy63!&jZG#p0xj*ANXwf%?%MZTGiWa|9aP$bn3?cikqFf2(EC8)i2y$ z-uAZfa!2+HnE(e|F6Jnj;V?cj>?#uh%n&Y^9k>EGNW@|HnBqvO#?X0F#kz{8WExF% z6OS3XEaQ3{(}{`mx*|QTOdbkTfhssYlkUnMA4NC{@ zz&~Ci*)_|=nq?nYTiFx*^63EQ#2Y zz7^UKdL<<1BMIwfa;6(=GBTF3LX)O|+x4fJ$*G%@CKBjwNm4oi*|eQU!=Y>+I4jtd J`{LaS-UGmAY<~a% delta 305 zcmew-zEo72`7IDLy`Z)mUKqniEsQ^f`T{gSRStl^6gIVWTr!Z=PS##NX7vf`BZBAXOj%wjge@0T=7!``o+&AWPVoco>0@Sxk?I5dbbG BH{<{S diff --git a/src/app/dialogs/components.py b/src/app/dialogs/components.py index 25c3210..b3fc3eb 100644 --- a/src/app/dialogs/components.py +++ b/src/app/dialogs/components.py @@ -26,21 +26,26 @@ class AbstractComponent(object): self._widget = None def Build(self, parent): + self._widget = self.BuildWidget(parent, self._action) - sizer = wx.BoxSizer(wx.VERTICAL) + self._msg = (self.CreateHelpMsgWidget(parent, self._action) + if self.HasHelpMsg(self._action) + else None) + sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.CreateDestNameWidget(parent, self._action)) sizer.AddSpacer(2) - if self.HasHelpMsg(self._action): - sizer.Add(self.CreateHelpMsgWidget(parent, self._action)) + if self._msg: + sizer.Add(self._msg, 0, wx.EXPAND) sizer.AddSpacer(2) else: - sizer.AddSpacer(10) - + sizer.AddStretchSpacer(1) + if self.HasNargs(self._action): sizer.Add(self.AddNargsMsg(parent, self._action)) - + + sizer.AddStretchSpacer(1) sizer.Add(self._widget, 0, wx.EXPAND) return sizer @@ -80,6 +85,9 @@ class AbstractComponent(object): darkgray = (54,54,54) statictext.SetForegroundColour(darkgray) + def __str__(self): + return str(self._action) + @abstractmethod def BuildWidget(self, parent, action): @@ -90,6 +98,36 @@ class AbstractComponent(object): def GetValue(self): ''' Returns the state of the given widget ''' pass + +# @abstractmethod + 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 + window 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) + + print 'wiget size', help_msg.Size[0] + wiggle_room = range(int(content_area - content_area * .05), int(content_area + content_area * .05)) + print '(',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) + @@ -148,16 +186,61 @@ class Flag(AbstractComponent): self._widget = None self.contents = None + def Build(self, parent): + self._widget = self.BuildWidget(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.CreateDestNameWidget(parent, self._action)) + sizer.AddSpacer(6) + + if self.HasNargs(self._action): + sizer.Add(self.AddNargsMsg(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 BuildWidget(self, parent, action): - if len(action.option_strings) > 1: - label = action.option_strings[0] - else: - label = '' - return wx.CheckBox(parent, -1, label=label) + 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): return self._widget.GetValue() + 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/2)*.70) + + print 'wiget size', help_msg.Size[0] + wiggle_room = range(int(content_area - content_area * .05), int(content_area + content_area * .05)) + print '(',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): diff --git a/src/app/dialogs/components_unittest.py b/src/app/dialogs/components_unittest.py index a7a2631..b604923 100644 --- a/src/app/dialogs/components_unittest.py +++ b/src/app/dialogs/components_unittest.py @@ -24,7 +24,7 @@ class ComponentsTest(unittest.TestCase): parser.add_argument('-T', '--tester', choices=['yes','no']) parser.add_argument('-o', '--outfile', help='Redirects output to the specified file') parser.add_argument('-v', '--verbose', help='Toggles verbosity off') - parser.add_argument('-e', '--repeat', action='count', help='Set the number of times to repeat') + parser.add_argument('-e', '--repeat', action='count') action = parser._actions self.actions = { 'help' : action[0], @@ -36,10 +36,10 @@ class ComponentsTest(unittest.TestCase): } - def BuildWindow(self, component): + def BuildWindow(self, component, _type): app = wx.PySimpleApp() module_name = os.path.split(sys.argv[0])[-1] - frame = wx.Frame(None, -1, module_name) + frame = wx.Frame(None, -1, _type) panel = wx.Panel(frame, -1, size=(320,240)) component_sizer = component.Build(panel) @@ -65,10 +65,10 @@ class ComponentsTest(unittest.TestCase): def testCounterWidgetBuild(self): self.SetupWidgetAndBuildWindow('Counter') - def SetupWidgetAndBuildWindow(self, _type): component = getattr(components, _type)(self.actions[_type]) - self.BuildWindow(component) + print component + self.BuildWindow(component, _type) if __name__ == "__main__": diff --git a/src/app/dialogs/simple_config_panel.py b/src/app/dialogs/simple_config_panel.py index 3a44594..781a567 100644 --- a/src/app/dialogs/simple_config_panel.py +++ b/src/app/dialogs/simple_config_panel.py @@ -45,8 +45,9 @@ class BodyDisplayPanel(wx.Panel): return self.cmd_textbox.GetValue() def _bold_static_text(self, text_label): - bold = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD) text = wx.StaticText(self, label=text_label) + font_size = text.GetFont().GetPointSize() + bold = wx.Font(font_size, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD) text.SetFont(bold) return text diff --git a/src/experiments/__init__.py b/src/experiments/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/experiments/command.py b/src/experiments/command.py new file mode 100644 index 0000000..0b21f8f --- /dev/null +++ b/src/experiments/command.py @@ -0,0 +1,22 @@ +''' +Created on Jan 7, 2014 + +@author: Chris +''' + +class Command(object): + def __init__(self): + pass + + def execute(self): + pass + + +class NextButton(Command): + def execute(self): + print "Next Button" + +class CancelButton(Command): + def execute(self): + print 'Cancel button!' +