def RSidebar(props): return wsx([ c.Block, { 'orient': wx.HORIZONTAL, 'show': props.get('show', True), 'flag': props['flag'], 'proportion': props['proportion'], 'ref': props['ref'] }, [SidebarControls, { **props, 'show': props['show_sidebar'] }], [ c.StaticLine, { 'style': wx.LI_VERTICAL, 'flag': wx.EXPAND, 'min_size': (1, -1) } ], *[[ TabbedConfigPage if props['tabbed_groups'] else ConfigPage, { 'flag': wx.EXPAND, 'proportion': 3, 'config': config, 'show': i == props['activeSelection'] } ] for i, config in enumerate(props['config'].values())] ])
def test_gauge(self): cases = [ # {'uri': None}, {}, {'uri': images.red_uri}, {'uri': images.red_uri, 'size': (64, 64)}, {'uri': images.red_uri, 'size': (16, 16)} ] # expected_state = { # 'uri': images.kirbs_uri # } app = wx.App() for props in cases: with self.subTest(props): component = wsx( [c.Frame, {'show': True, 'size': (100,100)}, [c.Block, {}, [c.StaticBitmap, {**props, 'proportion': 0}]]]) frame = render(component, None) bitmap = frame.Children[0].Children[0] if 'uri' in props: self.assertIsNotNone(bitmap.GetBitmap().RefData) else: # when no URI is defined, there should similarly # be no bitmap data present self.assertEqual(bitmap.GetBitmap().RefData, None)
def render(self): return wsx([ c.StaticText, { **self.props, 'label': self.props['label'], 'ref': self.ref } ])
def render(self): return wsx([ c.Frame, { "show": True, "size": (200, 100) }, [ c.Block, {}, [ LabeledGauge, { "value": self.state["some_value"], "range": 100, "min_size": (100, 20), "size": (100, 20), }, ], [c.StaticText, { "label": str(self.state["some_value"]) }], # checkout the arbitrary prop we've defined here [ Child, { "click_handler": self.update_value, "label": "Click me!" } ], ], ])
def ErrorWarning(props): return wsx([ c.Block, { 'orient': wx.HORIZONTAL, 'background_color': '#fdeded', 'style': wx.SIMPLE_BORDER, 'flag': wx.EXPAND | wx.ALL, 'proportion': 0, 'border': 5, 'min_size': (-1, 45), 'show': props.get('show', True) }, [ c.StaticBitmap, { 'size': (24, 24), 'flag': wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 'border': 6, 'uri': props['uri'] } ], [ c.StaticText, { 'label': 'Whoops! You have some errors which must be corrected', 'flag': wx.ALIGN_CENTER_VERTICAL } ] ])
def render(self): return wsx([ c.Button, { "on_click": self.props["click_handler"], "label": self.props["label"] }, ])
def render(self): return wsx([ c.Frame, { 'show': True }, [Nested, { 'label': self.state['label'] }] ])
def render(self): return wsx([ c.Frame, { 'title': self.buildSpec['program_name'], 'background_color': self.buildSpec['body_bg_color'], 'double_buffered': True, 'min_size': (400, 300), 'icon_uri': self.state['images']['programIcon'], 'size': self.buildSpec['default_size'], 'ref': self.frameRef }, [ c.Block, { 'orient': wx.VERTICAL }, [RHeader, self.headerprops(self.state)], [c.StaticLine, { 'style': wx.LI_HORIZONTAL, 'flag': wx.EXPAND }], [ProgressSpinner, { 'show': self.state['fetchingUpdate'] }], [ ErrorWarning, { 'show': self.state['show_error_alert'], 'uri': self.state['images']['errorIcon'] } ], [ Console, { **self.buildSpec, 'flag': wx.EXPAND, 'proportion': 1, 'show': self.state['screen'] == 'CONSOLE', 'ref': self.consoleRef } ], [ RTabbedLayout if self.buildSpec['navigation'] == constants.TABBED else RSidebar, { 'bg_color': self.buildSpec['sidebar_bg_color'], 'label': 'Some Action!', 'tabbed_groups': self.buildSpec['tabbed_groups'], 'show_sidebar': self.state['show_sidebar'], 'ref': self.configRef, 'show': self.state['screen'] == 'FORM', 'activeSelection': self.state['activeSelection'], 'options': list(self.buildSpec['widgets'].keys()), 'on_change': self.handleSelectAction, 'config': self.buildSpec['widgets'], 'flag': wx.EXPAND, 'proportion': 1 } ], [c.StaticLine, { 'style': wx.LI_HORIZONTAL, 'flag': wx.EXPAND }], [RFooter, self.fprops(self.state)] ] ])
def test_textctrl(self): mocked_change_handler = MagicMock() mocked_enter_handler = MagicMock() expected_state = { 'value': '123', 'name': 'My Cool Control', 'style': wx.TE_PROCESS_ENTER, 'on_change': mocked_change_handler, 'size': (100, 20) } app = wx.App() component = wsx([ c.Frame, { 'show': True, 'size': (999, 999) }, # note: the inner block is required so that the widget's # size prop can be honored (without it, it'd get resized to # the parent frame's size after `Layout` gets called. [c.Block, {}, [c.TextCtrl, { **expected_state, 'proportion': 0 }]] ]) frame = render(component, None) instance = frame.Children[0].Children[0] try: instance.Bind(wx.EVT_TEXT_ENTER, mocked_enter_handler) except Exception: self.fail(""" Unexpected failure. Either the test definition has regressed, and it is now missing `wx.TE_PROCESS_ENTER` as a style argument, or the widget dispatcher has regressed and is no longer applying `style` props correctly""" ) # our props are honored self.assertEqual(instance.Name, expected_state['name']) self.assertEqual(instance.Value, expected_state['value']) self.assertEqual(instance.Size, expected_state['size']) # our enter has picked up and installed self.assertFalse(mocked_enter_handler.called) event = wx.KeyEvent(wx.wxEVT_TEXT_ENTER) instance.ProcessEvent(event) self.assertTrue(mocked_enter_handler.called) # our change handler prop is honored self.assertFalse(mocked_change_handler.called) event = wx.CommandEvent(wx.wxEVT_TEXT, wx.Window.NewControlId()) event.SetString('a') instance.ProcessEvent(event) self.assertTrue(mocked_change_handler.called)
def render(self): return wsx( [c.Frame, {'show': True, 'size': (200, 100)}, [c.Block, {}, [c.StaticText, {'label': str(self.state['some_value'])}], # checkout the arbitrary prop we've defined here [Child, { 'click_handler': self.update_value, 'label': 'Click me!' }]]] )
def render(self): return wsx( [c.Frame, {'title': 'My Cool Application', 'show': True}, [c.Block, {'orient': wx.HORIZONTAL}, [c.TextCtrl, { 'style': wx.TE_PROCESS_ENTER, 'value': self.state['value'], 'on_change': self.on_input, 'ref': self.input_ref, }]]] )
def test_wsx(self): # calling as function result = wsx(['foo', {'bar': 'baz'}]) self.assertEqual(result, create_element('foo', {'bar': 'baz'})) @wsx def my_component(props): return ['foo', props] # asserting the function name gets @wrapped correctly self.assertEqual(my_component.__name__, 'my_component') self.assertEqual(my_component({'bar': 'baz'}), create_element('foo', {'bar': 'baz'}))
def render(self): return wsx([ c.Block, { 'orient': wx.VERTICAL, 'min_size': (30, 53), 'background_color': self.props['bg_color'] }, [c.Block, { 'orient': wx.VERTICAL, 'proportion': 1 }], [ c.Block, { 'orient': wx.HORIZONTAL, 'border': 20, 'flag': wx.EXPAND | wx.LEFT | wx.RIGHT, 'ref': self.ref }, [ c.Gauge, { 'range': 100, 'proportion': 1, 'value': self.props['progress']['value'], 'show': self.props['progress']['show'] } ], [ c.StaticText, { 'label': present_time(self.props['timing']), 'flag': wx.LEFT, 'wx_name': 'timing', 'show': self.props['timing']['show'], 'border': 20 } ], [c.Block, { 'orient': wx.HORIZONTAL, 'proportion': 1 }], *[[ c.Button, { **btn, 'label': _(btn['label_id']), 'min_size': (90, 23), 'flag': wx.LEFT, 'border': 10, 'on_click': self.handle(btn) } ] for btn in self.props['buttons']] ], [c.Block, { 'orient': wx.VERTICAL, 'proportion': 1 }] ])
def ProgressSpinner(props): return wsx([ c.Block, { 'flag': wx.EXPAND, 'show': props['show'] }, [c.Gauge, { 'flag': wx.EXPAND, 'value': -1, 'size': (-1, 4) }], [c.StaticLine, { 'style': wx.LI_HORIZONTAL, 'flag': wx.EXPAND }] ])
def _html_window(html): return wsx([ c.Block, { 'orient': wx.VERTICAL, 'flag': wx.EXPAND }, [ c.HtmlWindow, { 'style': wx.TE_READONLY, 'flag': wx.EXPAND | wx.ALL, 'proportion': 1, 'value': html } ] ])
def render(self): return wsx( [Block, {}, [Block, {'orient': wx.HORIZONTAL}, [StaticText, {'label': 'Download #1'}], [Gauge, {"value": self.state["download_1"], "range": 100}]], [Block, {'orient': wx.HORIZONTAL}, [StaticText, {'label': 'Download #2'}], [Gauge, {"value": self.state["download_2"], "range": 100}]], [Button, {"label": "Download" if self.state['status'] == 'READY' else 'In Progress', 'enabled': self.state['status'] == 'READY', "on_click": self.start_download, "flag": wx.CENTER | wx.ALL}], ] )
def render(self): if 'running' not in self.props['image_uri']: imageProps = { 'uri': self.props['image_uri'], 'size': self.props['image_size'], 'flag': wx.RIGHT, 'border': 10 } else: imageProps = { 'size': self.props['image_size'], 'flag': wx.RIGHT, 'border': 10 } return wsx([ c.Block, { 'orient': wx.HORIZONTAL, 'ref': self.parentRef, 'min_size': (120, self.props['height']), 'background_color': self.props['background_color'] }, [ c.Block, { 'orient': wx.VERTICAL, 'flag': wx.ALIGN_CENTER_VERTICAL | wx.ALL, 'proportion': 1, 'border': 10 }, [ TitleText, { 'label': self.props['title'], 'show': self.props['show_title'], 'wx_name': 'header_title' } ], [ c.StaticText, { 'label': self.props['subtitle'], 'show': self.props['show_subtitle'], 'wx_name': 'header_subtitle' } ] ], [c.StaticBitmap, imageProps] ])
def test_gauge(self): expected_state = { 'value': 123, 'range': 3000, 'name': 'Counter', 'size': (500, 30), } app = wx.App() component = wsx( [c.Frame, {'show': True, 'size': (999,999)}, [c.Block, {}, [c.Gauge, {**expected_state, 'proportion': 0}]]]) frame = render(component, None) gauge = frame.Children[0].Children[0] self.assertEqual(gauge.Size, expected_state['size']) self.assertEqual(gauge.Range, expected_state['range']) self.assertEqual(gauge.Name, expected_state['name']) self.assertEqual(gauge.Value, expected_state['value'])
def render(self): return wsx([ c.Block, { "orient": wx.HORIZONTAL, }, [ c.StaticText, { "label": str(self.props.get("value", "Download")) } ], [ c.Gauge, { "value": self.props.get("value", 0), "range": 100, "min_size": (100, 20), }, ], ], )
def SidebarControls(props): return wsx([ c.Block, { 'orient': wx.VERTICAL, 'min_size': (180, 0), 'size': (180, 0), 'show': props.get('show', True), 'flag': wx.EXPAND, 'proportion': 0, 'background_color': props['bg_color'] }, [ c.Block, { 'orient': wx.VERTICAL, 'min_size': (180, 0), 'size': (180, 0), 'flag': wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, 'border': 10, 'proportion': 1, 'background_color': props['bg_color'] }, [VerticalSpacer, { 'height': 15 }], [TitleText, { 'label': props['label'] }], [VerticalSpacer, { 'height': 5 }], [ c.ListBox, { 'choices': props['options'], 'value': props['activeSelection'], 'proportion': 1, 'on_change': props['on_change'], 'flag': wx.EXPAND } ], [VerticalSpacer, { 'height': 10 }] ] ])
def RTabbedLayout(props): return wsx([ c.Notebook, { 'flag': wx.EXPAND | wx.ALL, 'show': props.get('show', True), 'proportion': 1, 'on_change': props['on_change'], 'ref': props['ref'] }, *[[ c.NotebookItem, { 'title': props['options'][i], 'selected': props['activeSelection'] == i }, [ TabbedConfigPage if props['tabbed_groups'] else ConfigPage, { 'flag': wx.EXPAND, 'proportion': 3, 'config': config, 'show': i == props['activeSelection'] } ] ] for i, config in enumerate(props['config'].values())] ])
def testUriUpdatesChangeImage(self): """ Testing that swapping URI leads to the new images being loaded. """ app = wx.App() with self.subTest("initializing with no URI"): component = wsx( [c.Frame, {'show': True, 'size': (100, 100)}, [c.StaticBitmap, {}]]) frame = render(component, None) bitmap = frame.Children[0] # no images loaded self.assertEqual(bitmap.GetBitmap().RefData, None) with self.subTest('Adding a URI loads the image'): patch(bitmap, create_element(c.StaticBitmap, {'uri': images.red_uri})) original_rgb = self.get_rgb(bitmap) self.assertEqual(original_rgb, images.red_rgb) with self.subTest("updating props with new URI"): patch(bitmap, create_element(c.StaticBitmap, {'uri': images.pink_uri})) updated_rgb = self.get_rgb(bitmap) # colors should now be different because the image was updated self.assertNotEqual(original_rgb, updated_rgb) # and we should have our pink color: self.assertEqual(updated_rgb, images.pink_rgb) with self.subTest("updating props with same URI keeps existing image"): # attaching a mock so we can assert the same URI doesn't cause # a reloading of the image mock = MagicMock() bitmap.SetBitmap = mock patch(bitmap, create_element(c.StaticBitmap, {'uri': images.pink_uri})) mock.assert_not_called()
def render(self): return wsx([ Block, {}, [ Gauge, { "value": self.state["counter"], "range": 3000, "name": "Counter", "flag": wx.CENTER | wx.ALL, "size": (5000, 200), # How to set size of this Gauge? "border": 30, "pulse": False } ], [ Button, { "label": "Update", "on_click": self.update_count, "flag": wx.CENTER | wx.ALL } ], ])
def render(self): return wsx()
def VerticalSpacer(props): return wsx( [c.Block, { 'orient': wx.VERTICAL, 'min_size': (-1, props['height']) }])
def render(self): return wsx([c.Button, { 'on_click': self.props['click_handler'], 'label': self.props['label'] }])
def render(self): return wsx([c.Frame, {'show': True}, [Nested, {'label': self.state}], [c.Button, {'label': 'click', 'on_click': self.update_label}]])