[PEAK] Trellis-ified wx Dialog

Phillip J. Eby pje at telecommunity.com
Thu Jul 19 14:43:51 EDT 2007


At 10:13 AM 7/19/2007 -0700, Grant Baillie wrote:
>I've attached a small I example I quickly cons'ed up to use Trellis
>synchronization in a data-binding style wxDialog. Essentially, it's a
>wx.Dialog-ified version of the TempConverter example in the Trellis
>README.
>
>Comments welcome ... The code (and dialog!) both have their
>uglinesses: In particular, I could certainly seeing mixing in Cells
>and wx classes rather than the existing approach.

My main suggestion would be to make each field (c, f, and summary) in 
its own rule, e.g.:

     @trellis.rule
     def cField(self):
         cField = ...
         cField.Bind(...)
         return cField

Rather than having a single rule for "fields".  This would get rid of 
the need for the "if" calls in other rules.

I probably also would've put all the updates to the widgets in a 
single rule, just for brevity's sake, although that approach wouldn't 
make sense for a more sophisticated example.  Of course, for 
something more sophisticated, you'd use some sort of 
text-editing-field object linked directly to the cells in question, 
perhaps something like:

     class EditBridge(trellis.Component):
         cell = None
         widget = None

         def __init__(self, **kw):
             super(EditBridge, self).__init__(**kw)
             self.widget.Bind(wx.EVT_KILL_FOCUS, self.write)

         @trellis.rule
         def read(self):
             self.widget.SetValue(self.cell.value)

         def write(self, event):
             self.cell.value = self.widget.GetValue()


Then your main code could be reduced to something like this (omitting 
the TemperatureDialog class):

class ConverterDialog(trellis.Component):
     trellis.rules(
         fField = lambda self: EditBridge(
             widget = wx.xrc.XRCCTRL(self.dialog, "ID_F_FIELD"),
             cell = self.converter.__cells__['F']
         ),
         cField = lambda self: EditBridge(
             widget = wx.xrc.XRCCTRL(self.dialog, "ID_C_FIELD"),
             cell = self.converter.__cells__['C']
         ),
         summary = lambda self: wx.xrc.XRCCTRL(self.dialog, "ID_SUMMARY"),
         converter = lambda self: TempConverter(),
         dialog = lambda self: TemperatureDialog(parent=None, id=-1)
     )

     @trellis.rule
     def updateSummary(self):
         if self.converter.F > 80.0:
             self.summary.SetLabel(u"Phew!")
         elif self.converter.C < 5.0:
             self.summary.SetLabel(u"Brrr!")
         else:
             self.summary.SetLabel(u"")


if __name__ == "__main__":
     app = wx.PySimpleApp(redirect=False)
     ConverterDialog().dialog.Show()
     app.MainLoop()


As you can see, having a little bit of glue helps a lot -- I believe 
the result is shorter than the original, even if you include the new 
EditBridge class.

By the way, the general rule of Trellis programming is that if you're 
assigning to cells in a rule, you're probably doing something 
wrong.  (That is, you're not thinking declaratively enough.)  The 
revised version here only assigns cells from non-Trellis code (i.e., 
widget callbacks), which is how things should almost always be.




More information about the PEAK mailing list