Statusbar critique requested
Author |
Message |
Mark Wilde #1 / 13
|
 Statusbar critique requested
Here's how I link a statusbar to the model (without using a presenter). I'd appreciate any comments. The model is a Game and the statusbar shows the student's name, grade and remaining game time directly, plus massages some other status information into a single string. createSchematicWiring | statusBar | super createSchematicWiring. statusBar := self view viewNamed: 'statusBar'. (statusBar itemAtIndex: 1) model: (self model aspectValue: #studentName). (statusBar itemAtIndex: 2) model: (self model aspectValue: #grade). (statusBar itemAtIndex: 3) model: (ValueHolder with: self model); getTextBlock: [:game | game numberCorrect printString , ' out of ' , game numberWords printString, ' words completed, ' , game numberIncorrect printString, ' incorrect answers, ' , game percentCorrect printString, '% correct']. (statusBar itemAtIndex: 4) model: (self model aspectValue: #timeLeft). self model when: #statusChanged send: #refreshContents to: statusBar
|
Tue, 13 Sep 2005 11:33:24 GMT |
|
 |
Ian Bartholome #2 / 13
|
 Statusbar critique requested
Mark, Quote: > Here's how I link a statusbar to the model (without using a > presenter). I'd appreciate any comments.
A question first :-). Why not use a Presenter for each of the StatusBarItems?. It makes it much easier, both from a usability and maintenance viewpoint, and fits in with the normal Dolphin MVP scheme. Leaving the presenter issue aside the block in the third item look a bit strange. a) I'd have entered it using the aspect editor in the ViewComposer rather than updating the block programmatically. That may well just be a matter of taste though. b) Concatenating multiple strings using the comma operator is legal but, for reasons of readability, efficiency and (in this case) privacy, it is probably better to us a Stream. The following assumes that the method is implemented in your model class statusString ^String writeStream print: self numberCorrect; nextPutAll: ' out of '; print: self numberWords; nextPutAll: ' words completed,'; print: self numberIncorrect; nextPutAll: ' incorrect answers '; print: self percentCorrect; nextPutAll: ' %correct'; contents FWIW, I've put together a _very_ minimalist package that demonstrates using StatusBarItems with presenters. It only updates a couple of StatusBarItems with the current time, or resets them to 0:0:0, when a button is pressed but it should show how the bits can be wired together. http://www.idb.me.uk/files/mvpdemo.zip (2.5K) -- Ian
|
Tue, 13 Sep 2005 17:40:03 GMT |
|
 |
Mark Wilde #3 / 13
|
 Statusbar critique requested
Thanks for your response, Ian. Quote: > Why not use a Presenter for each of the StatusBarItems?.
Because in this case, the items are nothing but views on a model. They have no presenter/controller semantics. But I thought you'd ask. :) Quote: > It makes it much easier, both from a usability and maintenance viewpoint, and fits > in with the normal Dolphin MVP scheme.
I'm certainly looking for "easier," but that's why I did it like I did. All I want to do is connect a view to a read-only model. StatusBarItem makes it really easy to plug in display behavior. Part of it also was to see if I could make a read-only view that responded to model changes without writing too much code (or subclassing). It actually took me quite a while, since it seems people don't usually do this. But if even read-only views should really use Presenters, then I'll certainly rethink this. Quote: > a) I'd have entered it using the aspect editor in the ViewComposer > rather than updating the block programmatically. That may well just be > a matter of taste though.
I don't know how static the block will be. I may want to set it differently depending on the type of game being played. Quote: > b) Concatenating multiple strings using the comma operator is legal but, > for reasons of readability, efficiency and (in this case) privacy, it is > probably better to us a Stream.
I'm very comfortable using streams, but decided that the code was actually more readable using commas, in this case. I'm aware of the nextPutAll: <label>; print: <value> idiom and that , causes massive recopying and streams don't. I don't follow the remark about privacy, however--could you elaborate? Quote: > http://www.idb.me.uk/files/mvpdemo.zip
Thanks!
|
Tue, 13 Sep 2005 19:04:07 GMT |
|
 |
Mark Wilde #4 / 13
|
 Statusbar critique requested
Quote: > Why not use a Presenter for each of the StatusBarItems?. It makes it > much easier, both from a usability and maintenance viewpoint, and fits > in with the normal Dolphin MVP scheme.
BTW, there is a Presenter involved, of course, so it's still MVP. In this case, one Presenter (the Shell) is managing multiple Views (the StatusBarItems) by connecting them to a Model. Or at least that's my rationalisation. :)
|
Tue, 13 Sep 2005 19:09:58 GMT |
|
 |
Mark Wilde #5 / 13
|
 Statusbar critique requested
Quote: > The following assumes that the method > is implemented in your model class > statusString > ^String writeStream > print: self numberCorrect; > nextPutAll: ' out of '; > print: self numberWords; > nextPutAll: ' words completed,'; > print: self numberIncorrect; > nextPutAll: ' incorrect answers '; > print: self percentCorrect; > nextPutAll: ' %correct'; > contents
I didn't want to put anything like this in the model class because it is presentation, not data. I thought the choice of labels, the choice of values, the way the sentence reads and (of course) the language it's expressed in should all be in the view. You could imagine a different "status" view on this same model that would express status via hooting pie charts with Icelandic labels. )
|
Tue, 13 Sep 2005 19:16:06 GMT |
|
 |
Chris Uppa #6 / 13
|
 Statusbar critique requested
Quote:
> I didn't want to put anything like this in the model class because it > is presentation, not data. I thought the choice of labels, the choice > of values, the way the sentence reads and (of course) the language > it's expressed in should all be in the view.
That's sensible thinking, but at the risk of getting a bit "clever": Imagine that you had put your model and your GUI in different packages (not a bad idea in itself), the code for generating the presentation string would clearly be in the GUI package, but that doesn't mean that it has to be part of one of the GUI classes. You have the option of adding presentation-flavoured logic to the model as "loose methods" if you wish (provided that it doesn't break encapsulation). Sometimes I've done that, but -- I admit -- not very often. -- chris
|
Tue, 13 Sep 2005 19:30:52 GMT |
|
 |
Ian Bartholome #7 / 13
|
 Statusbar critique requested
Mark, Quote: > BTW, there is a Presenter involved, of course, so it's still MVP. In > this case, one Presenter (the Shell) is managing multiple Views (the > StatusBarItems) by connecting them to a Model. > Or at least that's my rationalisation. :)
I hadn't appreciated the last line in your original post, for some reason I thought you were generating the update request within the shell, so your solution is closer to MVP that I originally thought. However, I still think that as there is a standard way of doing this sort of thing then, to make it easier when you come back to maintain the code if nothing else, it would be better to stay with the norm. There's nothing wrong with your code but it doesn't, as far as I can see, provide anything extra over the existing scheme.. -- Ian
|
Wed, 14 Sep 2005 01:28:23 GMT |
|
 |
Ian Bartholome #8 / 13
|
 Statusbar critique requested
Mark/Chris, Quote: > I didn't want to put anything like this in the model class because it >> is presentation, not data. I thought the choice of labels, the choice [] > doesn't mean that it has to be part of one of the GUI classes. You > have the option of adding presentation-flavoured logic to the model > as "loose methods" if you wish (provided that it doesn't break > encapsulation).
My thinking was that in this case you are just providing an additional way of describing the current state of an object, in the same was as #printOn: and #displayOn: do. Like those operations it is best to ask the object to describe itself rather than having to expose it's internal workings to other classes - good 'ol encapsulation :-) If you want different strings in different situations then either provide a number of different methods in the model or pass it a template string and get it to fill in the blanks. -- Ian
|
Wed, 14 Sep 2005 01:29:21 GMT |
|
 |
Ian Bartholome #9 / 13
|
 Statusbar critique requested
Mark, Quote: > But if even read-only views should really use Presenters, then I'll > certainly rethink this.
There's no "should" involved but I personally think you will find it easier in the long run. Quote: > I'm very comfortable using streams, but decided that the code was > actually more readable using commas, in this case.
Hmmm. We'll just have to disagree there then :-) Quote: > I don't follow the remark about privacy, however--could you elaborate?
I was just alluding to the encapsulation argument that I mentioned in the reply to another post. -- Ian
|
Wed, 14 Sep 2005 01:39:22 GMT |
|
 |
Chris Uppa #10 / 13
|
 Statusbar critique requested
Ian, Quote: > My thinking was that in this case you are just providing an additional > way of describing the current state of an object, in the same was as > #printOn: and #displayOn: do. Like those operations it is best to ask > the object to describe itself rather than having to expose it's internal > workings to other classes - good 'ol encapsulation :-)
Ah yes. In fact I have a conventional message, #description, that I'm using more an more consistently in a similar way. It is supposed to "answer a short String describing the receiver, such as might be used for hover text, for example". The *method* is definitely part of the model, but the user is almost always part of some GUI. I haven't yet added it to Object, but I fear it's only a matter of time... -- chris
|
Wed, 14 Sep 2005 02:11:43 GMT |
|
 |
Mark Wilde #11 / 13
|
 Statusbar critique requested
Quote: > You have the option of adding presentation-flavoured logic to the model
That's what I'm trying to avoid. Models shouldn't know about presentation. My (very simple) app could be ported to Russian without changing the model. I'm not a big fan of displayOn:, in other words.
|
Wed, 14 Sep 2005 05:27:56 GMT |
|
 |
Mark Wilde #12 / 13
|
 Statusbar critique requested
Quote: > #printOn: and #displayOn: do. Like those operations it is best to ask > the object to describe itself rather than having to expose it's internal > workings to other classes - good 'ol encapsulation :-)
I take your point, but the information I'm using (number of questions asked, answered, etc.) are all "public" information. Quote: > If you want > different strings in different situations then either provide a number > of different methods in the model or pass it a template string and get > it to fill in the blanks.
The trouble is a) I wouldn't want to have to change the model if a new type of presentation is required (Latvian), and b) a template string might help, but it still exposes the number and semantics of those aspects (number of questions asked, etc.), albeit with the aid of some indirection, and it's not clear how much that indirection buys, compared to just changing the presentation.
|
Wed, 14 Sep 2005 05:35:22 GMT |
|
 |
Mark Wilde #13 / 13
|
 Statusbar critique requested
Quote: > Ah yes. In fact I have a conventional message, #description, that I'm using > more an more consistently in a similar way. It is supposed to "answer a short > String describing the receiver, such as might be used for hover text, for > example". The *method* is definitely part of the model, but the user is almost > always part of some GUI.
That works, because it's so generic. In my case, I need to get one (or more) strings describing "certain aspects of the player's status in the game being played." This is just one of the possible "description" strings.
|
Wed, 14 Sep 2005 05:41:40 GMT |
|
|
|