[PEAK] Towards a GUI facility for PEAK

Phillip J. Eby pje at telecommunity.com
Thu Dec 23 13:11:30 EST 2004


At 07:33 PM 12/23/04 +0200, Niki Spahiev wrote:

>>What I'm saying is that instead of having mapping items in the view like 
>>'data' and so forth, those items would be exposed as values on the model, 
>>and subscribed-to by the view.  In order for the mapping to be of any 
>>use, obviously the view has to know what they correspond to, so it's just 
>>as easy for the view to pull them off the model and subscribe to any of 
>>them that are needed.  Using your current design, you could literally 
>>just subscribe a function that calls the view's __setitem__ in order to 
>>keep the current implementation.  Thus, there's never a need for an 
>>InitAll().  Does that make sense?
>
>Yes, but looks too fine grained to me. For example pyro can be used 
>between view and presenter (for no better term). Sending value by value 
>over net is not good for performance. Also Web forms use batches forward 
>and back. Our first version was value by value, but we found that this is 
>not necessary.

But my point is that if you put the control of this in the view, the view 
can do that stuff in a batch or individually as it wishes.  Indeed, a 
batch-oriented view doesn't need to do any subscribing at all, it just sets 
what it wants and gets what it wants.  See what I mean?



>>Sure, but either the state machine is pure UI, or else it's part of the 
>>model.  If it's in the UI, sure, let the view manage the state machine 
>>and call the model when a model-level action is required.  If the state 
>>machine is part of the model, then do that.  The point is just that the 
>>model has no business interpreting UI events; it should just ultimately 
>>receive model method calls.  Thus, there's no need for an Action() method.
>
>In my code view is dumb web form like medium for displaying things and 
>receiving input from user. All intelligence is in middle translating layer 
>- CalcXXX in test_calc.py. Signal / slot like wiring is done in it in 
>order to allow using and changing many standard view-form implementations.

My meaning of "view" is "mapping from model to UI", not "widgets".  So, I'm 
looking at this as four things:

* domain model (doesn't know about anything)
* interaction model (knows about domain model + commands, can generate events)
* GUI objects (don't know about anything)
* view (maps from interaction model to GUI objects, setting up wiring 
between them)

The view in my concept, however, may use metadata to accomplish some of the 
wiring.  For example, it may ask the interaction model what "commands" are 
available, and consult key-binding and menu-mapping tables to find menu 
items to add and to register for key binding events.  So, in your 
calculator scenario, there would be digit commands, add command, and so on, 
able to be bound to both keystrokes and buttons.  A "view" in this case 
would be a generic function method that chooses GUI widgets to instantiate, 
and performs direct event wiring, e.g. from the button-click-ID to the 
command object it should invoke.

The result may be slightly more heavyweight when compared to your approach, 
since in the calculator example you can get away with consecutive 
ID's.  The tradeoff is a more composable system, especially if commands can 
be added by plugins.  That is, in principle a different piece of code could 
add a new calculator command, which is not possible with your basic 
design.  (That command would not be able to have a button added for it, but 
it could add a keystroke, menu item, or perhaps context (right-click popup) 
menu item to perform the operation.



>>>>Indeed, I'd do away with 'Action' and 'InitAll' altogether, because 
>>>>they're both artifacts of the GUI.  But apart from that, yes, this is 
>>>>very similar to the concept I proposed here.
>>>
>>>
>>>Main use of Action( view, .. ) is to call view.AttachFrame(..) to open 
>>>new windows.
>>
>>I think this could be handled by some sort of "ui.show(anotherModel)" 
>>operation, perhaps with some options.  But, it's actually more likely 
>>that this will be handled by views on command objects, because otherwise 
>>it would be difficult to handle "modal" windows in a web UI.  That is, 
>>there can't be a function called by the model to get input, because the 
>>model should receive input in the form of command instances populated 
>>with parameters.  The UI framework should handle finding and presenting a 
>>view for the command object, and then executing the command once the 
>>input has been obtained.
>
>GUIs usually need more parent/child information in order to work as expected.

Right, but the framework can know what GUI widgets correspond to what 
interaction model objects.  It's the model objects themselves that don't 
need to know.


>>>  Not sure about InitAll, its responsible for reconfiguring UI too.
>>
>>How do you mean?
>
>In test_calc2 InitAll enables/disables some view elements according to 
>current state. This can be observed too, but configuration space is too 
>big for effectively doing that.

I don't really see that.  I would put the knowledge of when to 
enable/disable in the view layer.


>>>Here is better example (still not using subscription). What is the 
>>>English name of concept represented by CalcXXX?
>>
>>I don't know; I wouldn't split the two up like that.  I'd make the 'oct' 
>>flag an events.Value on the model, and subscribe to it from the view.
>>I'd probably also make a 'display' attribute (also an events.Value) on 
>>the model that was the string to be displayed (decimal or octal).  The 
>>action mappings (digit->digit(), add/sub/etc.) I would put on the view, 
>>as calling methods or issuing Commands of some kind.  (Where the Commands 
>>call the model methods.)
>
>oct has nothing to do with model. Model always uses ints. Displaying and 
>entering digits is pure UI task IMO. Presenter is not good name, 
>especially as its taken for similar UI concept

The *domain model* uses ints.  The *interaction model* is that you have an 
octal/decimal calculator.

I think I see what is different here.  Your CalcXXX mixes what I consider 
"interaction model" with what I consider "view".  You then also have a GUI 
layer that mixes what I call "view" with what I call "GUI".  So, I am 
slicing the layers more thinly, and allowing only two of the layers to see 
lower layers:

              view
             /    \
            IM    GUI
           /
          DM

I think yours is more like this:

       XXX -- GUI
      /
    Model

where there is some crosstalk between the XXX and GUI, such that they are 
not really layered.




More information about the PEAK mailing list