def bitmapbutton(element, parent): return update(element, wx.BitmapButton(parent))
def frame(element, parent) -> wx.Frame: return update(element, wx.Frame(None))
def patch(dom: wx.Window, vdom): parent = dom.GetParent() try: # if parent: # parent.Freeze() if not isclass(vdom['type']): # because stateless functions are just opaque wrappers # they have no relevant diffing logic -- there is no # associated top-level WX element produced from a SFC, only # their inner contents matter. As such, we evaluate it and # push the result back into `patch` return patch(dom, vdom['type'](vdom['props'])) if isclass(vdom['type']) and issubclass(vdom['type'], Component): return Component.patch_component(dom, vdom) elif not isinstance(dom, vdom['type']): for child in dom.GetChildren(): dom.RemoveChild(child) child.Destroy() dom.Destroy() newdom = render(vdom, parent) elif isinstance(dom, vdom['type']) and getattr(dom, 'self_managed', False): # self-managed components manage their children by hand rather than # automatically via the rewx dom. As such, we don't perform any child # diffing or reconciliation operations for them. The virtualdom will NOT # match the actual dom for these widgets. # # Background: These components are legacy/vanilla wx components the user created # which have been introduced into rewx land through custom mount/update handlers. # These are commonly used while porting over existing code or for wx components # which are sufficiently cranky about their child management. update(vdom, dom) newdom = dom elif isinstance(dom, vdom['type']): update(vdom, dom) pool = {f'__index_{index}': child for index, child in enumerate(dom.GetChildren())} for index, child in enumerate(vdom['props'].get('children', [])): key = f'__index_{index}' if key in pool: patch(pool[key], child) del pool[key] else: # TODO: this IS the addition case, right? # why would I need this removeChild line..? if key in pool: # if we're adding something new to the # tree, it won't be present in the pool parent.RemoveChild(pool[key]) # TODO: need to understand this case more # if we're not updating, we're adding # in which case.. why doesn't this fall to the # `dom` instance..? inst = render(child, dom) if dom.GetSizer(): dom.GetSizer().Add( inst, child['props'].get('proportion', 0), child['props'].get('flag', 0), child['props'].get('border', 0) ) # any keys which haven't been removed in the # above loop represent wx.Objects which are no longer # part of the virtualdom and should thus be removed. for key, orphan in pool.items(): # Debugging InspectionFrame gets lumped in with the # top-level hierarchy. We want to leave this alone as # it's there for debugging and not part of the actual # declared component tree if not isinstance(orphan, wx.lib.inspection.InspectionFrame): dom.RemoveChild(orphan) orphan.Destroy() newdom = dom else: raise Exception("unexpected case!") p = parent while p: p.Layout() p = p.GetParent() return newdom finally: # TODO: we sometimes call parent.Thaw() when # parent isn't frozen. I think this has something # to do with the child removal case. Not sure tho # if parent and parent.IsFrozen(): # parent.Thaw() pass
def staticbitmap(element, parent): return update(element, wx.StaticBitmap(parent))
def radiobox(element, parent): return update(element, wx.RadioBox(parent, choices=element['props'].get('choices', [])))
def block(element, parent): panel = update(element, Block(parent)) sizer = wx.BoxSizer(element['props'].get('orient', wx.VERTICAL)) panel.SetSizer(sizer) return panel
def grid(element, parent): props = element['props'] panel = Grid(parent) sizer = wx.GridSizer(props.get('cols', 1), gap=props.get('gap', (0, 0))) panel.SetSizer(sizer) return update(element, panel)
def mediactrl(element, parent): return update(element, wx.media.MediaCtrl(parent, style=wx.SIMPLE_BORDER))
def svg(element, parent): return update(element, SVG(parent))
def combobox(element, parent): return update(element, wx.ComboBox(parent, choices=element['props'].get('choices', [])))
def listctrl(element, parent): return update(element, wx.ListCtrl(parent, style=wx.LC_REPORT))
def collapsiblepanel(element, parent): return update(element, wx.CollapsiblePane(parent))
def checkbox(element, parent): return update(element, wx.CheckBox(parent))
def calendarctrl(element, parent): return update(element, wx.adv.CalendarCtrl(parent))
def textarea(element, parent): return update(element, TextArea(parent, style=wx.TE_MULTILINE))
def svgbutton(element, parent): return update(element, SVGButton(parent))
def panel(element, parent): return update(element, wx.Panel(parent))
def radiobox(element, parent): return update(element, wx.RadioBox(parent))
def scrolledpanel(element, parent): panel = update(element, ScrolledPanel(parent)) sizer = wx.BoxSizer(element['props'].get('orient', wx.VERTICAL)) panel.SetSizer(sizer) return panel
def staticbox(element, parent): instance = wx.StaticBox(parent) sizer = wx.BoxSizer(element['props'].get('orient', wx.VERTICAL)) instance.SetSizer(sizer) return update(element, instance)
def textctrl(element, parent): return update(element, wx.TextCtrl(parent))
def slider(element, parent): return update(element, wx.Slider(parent))
def staticline(element, parent): return update(element, wx.StaticLine(parent))
def spinctrl(element, parent): return update(element, wx.SpinCtrl(parent))
def radiobutton(element, parent): # we force the style RB_SINGLE here and don't # allow it to be overriden so that these individual # buttons can act as controlled components return update(element, wx.RadioButton(parent, style=wx.RB_SINGLE))
def spinctrldouble(element, parent): return update(element, wx.SpinCtrlDouble(parent))
def activity_indicator(element, parent): return update(element, wx.ActivityIndicator(parent))
def statictext(element, parent): return update(element, wx.StaticText(parent))
def patch(dom: wx.Window, vdom): parent = dom.GetParent() try: # if parent: # parent.Freeze() if not isclass(vdom['type']): # because stateless functions are just opaque wrappers # they have no relevant diffing logic -- there is no # associated top-level WX element produced from a SFC, only # their inner contents matter. As such, we evaluate it and # push the result back into `patch` return patch(dom, vdom['type'](vdom['props'])) if isclass(vdom['type']) and issubclass(vdom['type'], Component): return Component.patch_component(dom, vdom) elif not isinstance(dom, vdom['type']): for child in dom.GetChildren(): dom.RemoveChild(child) child.Destroy() dom.Destroy() newdom = render(vdom, parent) elif isinstance(dom, vdom['type']): update(vdom, dom) pool = { f'__index_{index}': child for index, child in enumerate(dom.GetChildren()) } for index, child in enumerate(vdom['props'].get('children', [])): key = f'__index_{index}' if key in pool: patch(pool[key], child) del pool[key] else: # TODO: this IS the addition case, right? # why would I need this removeChild line..? if key in pool: # if we're adding something new to the # tree, it won't be present in the pool parent.RemoveChild(pool[key]) # TODO: need to understand this case more # if we're not updating, we're adding # in which case.. why doesn't this fall to the # `dom` instance..? inst = render(child, dom) if dom.GetSizer(): dom.GetSizer().Add(inst, child['props'].get('proportion', 0), child['props'].get('flag', 0), child['props'].get('border', 0)) # any keys which haven't been removed in the # above loop represent wx.Objects which are no longer # part of the virtualdom and should thus be removed. for key, orphan in pool.items(): dom.RemoveChild(orphan) orphan.Destroy() newdom = dom else: raise Exception("unexpected case!") p = parent while p: p.Layout() p = p.GetParent() return newdom finally: # TODO: we sometimes call parent.Thaw() when # parent isn't frozen. I think this has something # to do with the child removal case. Not sure tho # if parent and parent.IsFrozen(): # parent.Thaw() pass
def button(element, parent): return update(element, wx.Button(parent))