Setting a model for a Spec UI in Pharo 8

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Setting a model for a Spec UI in Pharo 8

Brenda Larcom
Hi Pharo friends,

TL;DR: How should one open a presenter on a user-specified model?  Is SpPresenterWithModel>>setAnnouncingObject: missing a call to modelChanged?

The long version:
I am trying to write a UI for my threat modeling tool using Spec in Pharo 8.  I had trouble getting my first presenter to show me my model.  My current VERY WIP tiny code is available from [hidden email]:octotrike/groundhog.git, on branch pharo-sp-presenter-question.

I wanted to do something like this (paraphrased from the class comment for my BLFunctionPresenter class):

BLFunctionPresenter new
   model: aModel;
   openWithSpec

Unfortunately, the UI continued to show the default announcingObject (nil), even though announcingObject had changed as expected.

The examples I found showed either
- a containing presenter getting an event, changing instance variables on a presenter it contains, and sending modelChanged, or
- a presenter hard coded to show a model that is globally accessible.

In the end, I added self modelChanged to the end of SpPresenterWithModel>>setAnnouncingObject:.  It seemed like this method changed announcingObject and registered this presenter to receive modelChanged every time changes to the announcingObject occurred.  However, in cases like the one I am describing, the change is replacement of the entire announcingObject, so no announcingObject sends modelChanged.

Was/is this a bug in Spec?  Or is there something else I should be doing to open a Spec UI on a model that is neither global nor specified by a parent presenter?

Bren



Reply | Threaded
Open this post in threaded view
|

Re: Setting a model for a Spec UI in Pharo 8

Brenda Larcom
Hi fellow Pharo folks,

TL;DR: The only apparent way to open a standalone presenter on a user-specified model, SpPresenter>>on:, has a comment suggesting it will be deprecated.

As a follow-up to my previous question in case someone DuckDuckGoes it in the future, it seems that adding self modelChanged to SpPresenterWithModel>>setAnnouncingObject: breaks the Spec2 demos.  So, I backed my fix out of my image.  This has several implications:

- To actually change an SpPresenterWithModel's model, one must send model: and then modelChanged.  This seems to break encapsulation.
- The Spec2 demos seem to rely on modelChanged not arriving before the UI opens.  This seems fragile, and reduces the utility of using the demos as examples for writing non-demo code.
- Since I can't send modelChanged from model:, I must apparently use SpPresenter>>on: to open a standalone instance of my subclass of SpPresenterWithModel on a model I supply (e.g. (BLFunctionPresenter on: aModel) openWithSpec).  I was avoiding this because unfortunately, the comment foreshadows deprecation but does not explain what to use instead.  I do not understand how a subclass of SpPresenterWithModel can be composable after this deprecation.

So, I have a solution for now, but I am still looking for the supported way to open a standalone presenter on a user-specified model.

Bren

> On Feb 8, 2020, at 3:22 PM, Bren <[hidden email]> wrote:
>
> Hi Pharo friends,
>
> TL;DR: How should one open a presenter on a user-specified model?  Is SpPresenterWithModel>>setAnnouncingObject: missing a call to modelChanged?
>
> The long version:
> I am trying to write a UI for my threat modeling tool using Spec in Pharo 8.  I had trouble getting my first presenter to show me my model.  My current VERY WIP tiny code is available from [hidden email]:octotrike/groundhog.git, on branch pharo-sp-presenter-question.
>
> I wanted to do something like this (paraphrased from the class comment for my BLFunctionPresenter class):
>
> BLFunctionPresenter new
>  model: aModel;
>  openWithSpec
>
> Unfortunately, the UI continued to show the default announcingObject (nil), even though announcingObject had changed as expected.
>
> The examples I found showed either
> - a containing presenter getting an event, changing instance variables on a presenter it contains, and sending modelChanged, or
> - a presenter hard coded to show a model that is globally accessible.
>
> In the end, I added self modelChanged to the end of SpPresenterWithModel>>setAnnouncingObject:.  It seemed like this method changed announcingObject and registered this presenter to receive modelChanged every time changes to the announcingObject occurred.  However, in cases like the one I am describing, the change is replacement of the entire announcingObject, so no announcingObject sends modelChanged.
>
> Was/is this a bug in Spec?  Or is there something else I should be doing to open a Spec UI on a model that is neither global nor specified by a parent presenter?
>
> Bren


Reply | Threaded
Open this post in threaded view
|

Re: Setting a model for a Spec UI in Pharo 8

Pharo Smalltalk Users mailing list
Hi Bren.

Are you doing it with Spec2 ?

From my understanding, Spec2 is an MVP framework (Model-View-Presenter)
- The model represent the domain logic of the application
- The presenter let the developer do the UI programmaticaly and connect it to the Model.
- The UI drawing is then managed by Pharo through the Spec2 interperter.

First, I subclass Model for my domain model class.
For the UI, I subclass SpPresenterWithModel.
In the UI >> initialize method, I set the model with something like: 'self model: MyModel new'
In the UI >> connectPresenters, when one of my value changed, I called 'self announcingObject valueChanged'
I also overwrite UI >> modelChanged with 'self fillFormWithWorkingModel', where fillFormWithWorkingModel link the UI to the model to reflect change.

If you want to look at a fully working example, you can take a look at my sourdough calculator:
Metacello new
				baseline: 'Sourdough';
				repository: 'github://rvillemeur/Sourdough/src';
				load
It's a small project for calculating sourdough proportion when doing bread. The model is doing basic proportion calculation (the project includes tests). The UI is using Spec2, and is connected with the model.

Hope this helps.
Renaud



Feb. 12, 2020, 17:26 by [hidden email]:
Hi fellow Pharo folks,

TL;DR: The only apparent way to open a standalone presenter on a user-specified model, SpPresenter>>on:, has a comment suggesting it will be deprecated.

As a follow-up to my previous question in case someone DuckDuckGoes it in the future, it seems that adding self modelChanged to SpPresenterWithModel>>setAnnouncingObject: breaks the Spec2 demos. So, I backed my fix out of my image. This has several implications:

- To actually change an SpPresenterWithModel's model, one must send model: and then modelChanged. This seems to break encapsulation.
- The Spec2 demos seem to rely on modelChanged not arriving before the UI opens. This seems fragile, and reduces the utility of using the demos as examples for writing non-demo code.
- Since I can't send modelChanged from model:, I must apparently use SpPresenter>>on: to open a standalone instance of my subclass of SpPresenterWithModel on a model I supply (e.g. (BLFunctionPresenter on: aModel) openWithSpec). I was avoiding this because unfortunately, the comment foreshadows deprecation but does not explain what to use instead. I do not understand how a subclass of SpPresenterWithModel can be composable after this deprecation.

So, I have a solution for now, but I am still looking for the supported way to open a standalone presenter on a user-specified model.

Bren
On Feb 8, 2020, at 3:22 PM, Bren <[hidden email]> wrote:

Hi Pharo friends,

TL;DR: How should one open a presenter on a user-specified model? Is SpPresenterWithModel>>setAnnouncingObject: missing a call to modelChanged?

The long version:
I am trying to write a UI for my threat modeling tool using Spec in Pharo 8. I had trouble getting my first presenter to show me my model. My current VERY WIP tiny code is available from [hidden email]:octotrike/groundhog.git, on branch pharo-sp-presenter-question.

I wanted to do something like this (paraphrased from the class comment for my BLFunctionPresenter class):

BLFunctionPresenter new
model: aModel;
openWithSpec

Unfortunately, the UI continued to show the default announcingObject (nil), even though announcingObject had changed as expected.

The examples I found showed either
- a containing presenter getting an event, changing instance variables on a presenter it contains, and sending modelChanged, or
- a presenter hard coded to show a model that is globally accessible.

In the end, I added self modelChanged to the end of SpPresenterWithModel>>setAnnouncingObject:. It seemed like this method changed announcingObject and registered this presenter to receive modelChanged every time changes to the announcingObject occurred. However, in cases like the one I am describing, the change is replacement of the entire announcingObject, so no announcingObject sends modelChanged.

Was/is this a bug in Spec? Or is there something else I should be doing to open a Spec UI on a model that is neither global nor specified by a parent presenter?

Bren