[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