Shell View not updating

Skip to first unread message

F Bek

Dec 22, 2020, 6:16:18 PM12/22/20
Beginner's question.
DS 7.1.18

I have a small model with 2 inputs and 6 calculated outputs. The model works fine in a test Workspace and the outputs recalculate when any of the 2 inputs change.

The corresponding Presenter and simple Shell View will load and show all initial values correctly. The 2 inputs, when edited in the View, will cause all calculated values to update in the model - confirmed by an Inspector on the model.

Only they do not update in the View!!

Am I missing anything?

My reCalculate method ends with a series of: self trigger: #objectChanged messages for all 6 calculated outputs, which the View is supposed to capture automatically?

Thanks for reading and eventually answering.


F Bek

Dec 23, 2020, 10:58:07 AM12/23/20
Hmmm. I've just found out that I have to add some: 'xxxxPresenter model aspectTriggers: aSymbol' to the 'Presenter model' for all the changes to update in the View. It just wasn't obvious.

Dec 24, 2020, 3:05:45 PM12/24/20
A quick note that the idiomatic event name for this sort of thing is #valueChanged, not #objectChanged.

I'm also curious what you mean by "a series of trigger: messages for all 6 calculated outputs"? Taking you literally, a trigger of #objectChanged can't have any parameters... If you'd like further advice, might be simplest for you to show me some of the code—relevant parts I can think of include:
* The last bit of your reCalculate method (where the triggers occur)
* Any model: override on your Presenter (or wherever you assign models to the sub-presenters)
* If you have a createSchematicWiring on the Presenter, that too

F Bek

Dec 25, 2020, 6:16:54 AM12/25/20
Your comment on #valueChanged is noted.

As for the code, I have rewritten it and cleaned it up a bit, and got it to work. But I am not sure I am on the right track as I am unable to find any clear documentation. I have included the relevant parts here below for your kind advice. It is a simple project I am undertaking to learn Dolphin Smalltalk. Also, I am following, in parallel, Ted Bracht’s ‘The Dolphin Smalltalk Companion’ book I got ages ago, but not all is evident as this was written for DS 3.0.

- First, the Model's method that triggers a #valueChanged message, indicating that the 'section properties' need to be updated in the View. This is called when the rectangle width or height changes:

"Private - re-calculates all section properties - AND triggers a change message"
self setProperties.
self trigger: #sectionPropertiesChanged.

- Second, the Presenter's model, where, in the second part, Presenters register interest (if that's correct) in the change message described above.
(The book, chapter 4, does not mention this at all; hence my confusion):

model: aFB_Rectangle
"Create the link between presenter INSTANCE VARIABLES and the model INSTANCE VARIABLES"
super model: aFB_Rectangle.
namePresenter model: (aFB_Rectangle aspectValue: #name).
widthPresenter model: (aFB_Rectangle aspectValue: #width).
heightPresenter model: (aFB_Rectangle aspectValue: #height).
perimeterPresenter model: (aFB_Rectangle aspectValue: #perimeter).
areaPresenter model: (aFB_Rectangle aspectValue: #area).
xcPresenter model: (aFB_Rectangle aspectValue: #xc).
ycPresenter model: (aFB_Rectangle aspectValue: #yc).
ixPresenter model: (aFB_Rectangle aspectValue: #ix).
iyPresenter model: (aFB_Rectangle aspectValue: #iy).

perimeterPresenter model aspectTriggers: #sectionPropertiesChanged.
areaPresenter model aspectTriggers: #sectionPropertiesChanged.
xcPresenter model aspectTriggers: #sectionPropertiesChanged.
ycPresenter model aspectTriggers: #sectionPropertiesChanged.
ixPresenter model aspectTriggers: #sectionPropertiesChanged.
iyPresenter model aspectTriggers: #sectionPropertiesChanged.

With those changes, I got the View to update correctly. But maybe there is a better or simpler way?

Thanks & regards,

Jan 2, 2021, 7:32:20 PMJan 2
Doing some more digging around, I realize I'm sorta wrong about #valueChanged. It's certainly the standard event name for reporting changes *for objects conforming to the <ValueModel> protocol*, but your model object doesn't, so there's no particular reason to prefer #valueChanged—the #sectionPropertiesChanged name you used is fine, and #aspectTriggers: is definitely the way you inform the sub-presenters' models that this is the event they should observe. And yes, I believe #model: is the correct place to do this. Especially as the number of sub-presenters watching the same event grows large, one refinement might be (this is new syntax as of Dolphin 7.0.something, but is fairly common in other Smalltalk dialects as well):

{perimeterPresenter. areaPresenter. xcPresenter. ...etc... }
do: [:presenter | presenter model aspectTriggers: #sectionPropertiesChanged].

One note unrelated to events and Views, however. It looks to me like your FB_Rectangle might have instance variables for each of the computed properties like width, height, area, etc, which you assign to in #setProperties, with the #width, #height etc. messages simply returning those values. Is that correct? I'm making a pretty big leap here, so if I'm totally off-base...well, what I have to say next might still be *somewhat* useful, but disregard anything that doesn't apply.

The thing is, there's no difference, from the outside, between an accessor (for our purposes right now, a unary message that simply returns the value of a same-named instance variable), and a unary message that computes a value on-the-fly and returns it. For a variety of reasons, I would tend to choose the latter implementation. Your presenter code would not change, but instead of the #reSetProperties method (or #setProperties for that matter), you would simply define methods like:

"Compute the width somehow—I don't know how you actually store the bounds of the rect, this is from the core Rectangle class"
^corner x - origin x

And then in any method which changes the underlying values (`origin` and `corner` in this case) you would add a `self trigger: #sectionPropertiesChanged`. Actually, if this happens from several places, you would want to define:

FB_Rectangle>>origin: aPoint
origin := aPoint
self trigger: #sectionPropertiesChanged

and direct all access to the ivar through this method. In the middle column of the Class Browser, if you click on the Variables tab and right-click on a particular variable, you can choose "Abstract" to create the accessors and rewrite other methods to use them. Then you can just add the trigger line to this method.

Have fun learning Dolphin!

F Bek

Jan 12, 2021, 8:04:11 PMJan 12
Thanks for the valuable feedback, please see here in some clarifications and further details:  

-- #valueChanged and <ValueModel> : discussion noted and agreed.

-- #aspectTriggers: and {...} do: [...] : noted and implemented; this is definitely a welcome refinement.

-- note on FB_Rectangle : you guessed right, I started with creating instance variables for all properties, not knowing what would be needed. But I then realized I could do without most of them, so I've eliminated all except the main two: width and height. 

--  #reSetProperties vs setProperties : the latter was called by #initialize to calculate all properties at instance creation and store them in their respective variables. The former was called by subsequent changes to width and height, and adds a change trigger. I have since deleted both methods as they were not needed when the property variables were deleted. The triggering was then part of the #width: and #height: methods, as you suggested, and as implemented in the code below:    FB_Rectangle >> width: aNumber
          ^width = aNumberifFalse: [ width := aNumber. self trigger: #sectionPropertiesChanged ] .

-- The core <Rectangle> class : I have not used this class [at first] but built my own FB_Rectangle with width and height as parameters. This was a quick and dirty choice to move forward and have a working code I could test and learn from. It served its purpose and got me a working MVP fast enough. I have started rewriting the codes for the third time now, using the core <Rectangle> class and origin/corner as a basis. It offers flexibility for an eventual graphical representation at a later stage, and is needed by subclasses, e.g. FB_SymetricalTee, which basically is 2 rectangles, mounted as a "Tee". Other sections should follow as well, hopefully.

-- Extending the <Rectangle> class : in the process, I had to extend the Rectangle class, by adding the needed properties there. While #area was already available, I've added #perimeter, #centroid, Inertia_xx and Ineria_yy. I might add more properties if and when needed and create other classes of sections as <Triangle>, <Circle> etc. 

-- right-click Abstract : interesting helping shortcut; worth experimenting with.

That summarises where I've reached so far. Comments appreciated.
Reply all
Reply to author
0 new messages