Few questions about Spec (instance specific layout and skinning)

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

Few questions about Spec (instance specific layout and skinning)

Thomas Bany
Hi !

First, I apologyse for the wall of text.

I'm trying my hands at Spec and I have few questions:
  • How can I implement an instance-dependent layout ?
Regarding the layout method lookup, the documentation states that it "starts on instance side, which allows a UI to have a more specific layout depending on the state of the instance"

I tried to simply put a layout in an instance method with the <spec: #default> pragma. But not only was it not retrieved by ComposableModel>#defaultSpecSelector but ComposableModel>#retrieveSpec: will send the selector on the class anyway.

What I ended up doing was overiding #openWithSpec (which worked) but I'm pretty sure that my model is not composable at all.
  • Is it possible to change the "skin" of the basic widget ?

I would like to implement some sort of toggle button by changing the color of ButtonModel and so far, I failed. I was not able to trace my color change up to the PluggableButtonMorph because it seems to use anoucement and I'm a Smalltalk rookie.

I tried however to send #color: directly to the morph which does nothing: the #changed method rolls it back to its previous value. So I may be doing something wrong but it doesn't feel like the issue comes from Spec. Any clue ?

  • On a side note, I tried to send an argument to the selector that retrieve a widget in the layout method.
And I came up with this :

layout add: {#buttonAt: . 1}; add: {#buttonAt: . 2}; add: {#buttonAt: . 3}

Is it how it's done ?


Thanks in advance !

Thomas.



Reply | Threaded
Open this post in threaded view
|

Re: Few questions about Spec (instance specific layout and skinning)

Benjamin Van Ryseghem (Pharo)
On 02 Apr 2014, at 12:10, Thomas Bany <[hidden email]> wrote:

Hi !

First, I apologyse for the wall of text.

I'm trying my hands at Spec and I have few questions:
  • How can I implement an instance-dependent layout ?
The usual solution is to have a method looking like this on instance side

rebuildMyLayout

| layout | 
layout := self buildStateDependentLayout.
self buildWithLayout: layout.

buildStateDependentLayout
^ SpecLayout composed
etc...

Regarding the layout method lookup, the documentation states that it "starts on instance side, which allows a UI to have a more specific layout depending on the state of the instance"

I tried to simply put a layout in an instance method with the <spec: #default> pragma. But not only was it not retrieved by ComposableModel>#defaultSpecSelector but ComposableModel>#retrieveSpec: will send the selector on the class anyway.

What I ended up doing was overiding #openWithSpec (which worked) but I'm pretty sure that my model is not composable at all.

Indeed, overriding openWithSpec may be a bit hackish, but should still work :)

Another solution could be to override defaultSpecSelector and/or retrieveSpec:

  • Is it possible to change the "skin" of the basic widget ?
The hooks are basically here, but the Morphs have an issue with this.
The “skin” of a Morph is supposed to be immutable, hence it takes back its default value at each refresh :S


I would like to implement some sort of toggle button by changing the color of ButtonModel and so far, I failed. I was not able to trace my color change up to the PluggableButtonMorph because it seems to use anoucement and I'm a Smalltalk rookie.

I tried however to send #color: directly to the morph which does nothing: the #changed method rolls it back to its previous value. So I may be doing something wrong but it doesn't feel like the issue comes from Spec. Any clue ?

So far, it will not work, sorry :(

  • On a side note, I tried to send an argument to the selector that retrieve a widget in the layout method.
And I came up with this :

layout add: {#buttonAt: . 1}; add: {#buttonAt: . 2}; add: {#buttonAt: . 3}

Is it how it's done ?

That’s a solution.
Then if you have a fixed number of buttons, you could also implement a getter for each.

If you have an undetermined number of button, then DynamicComposableModel is for you.

Thanks in advance !

You are welcome :)
Ben
Reply | Threaded
Open this post in threaded view
|

Re: Few questions about Spec (instance specific layout and skinning)

Thomas Bany
The usual solution is to have a method looking like this on instance side

rebuildMyLayout

| layout | 
layout := self buildStateDependentLayout.
self buildWithLayout: layout.

buildStateDependentLayout
^ SpecLayout composed
etc...
 
I will defenitly look into that. The "rebuild" may be missleading, is it also called at first building ?

The hooks are basically here, but the Morphs have an issue with this.
The “skin” of a Morph is supposed to be immutable, hence it takes back its default value at each refresh :S

Well, I can't even manage to tweak it through hardcoding stuff on the adapter :p

Do you think it would be hard to use a SimpleSwitchMorph ? As I understood, there is #asSpecAdapter that permis to plug pretty much everything ? Plus, making a specific adapter seems doable (I mean for a rookie like me).
 
That’s a solution.
Then if you have a fixed number of buttons, you could also implement a getter for each.

If you have an undetermined number of button, then DynamicComposableModel is for you.

Well, I definitely have a variable number of buttons, depending on the model instance. Actualy, I want my model to be a matrix of toggle to specify a mask. I create instance with:

MaskModel class>#maxIndex: anInteger
    ^(self basicNew)
        maxIndex: anInteger;
        initialize;
        yourself

and instantiate a collection of buttons in #initializeWidgets.

It doesn't change much after that so a DynamicComposableModel didn't seem usefull. But I only though that because I never used it. I will give it a try.

Anyway, thanks again for your time !

Thomas.
Reply | Threaded
Open this post in threaded view
|

Re: Few questions about Spec (instance specific layout and skinning)

Benjamin Van Ryseghem (Pharo)
On 03 Apr 2014, at 12:50, Thomas Bany <[hidden email]> wrote:
>  
> I will defenitly look into that. The "rebuild" may be missleading, is it also called at first building ?

That’s your own ,method, call it as/when you want

> Well, I can't even manage to tweak it through hardcoding stuff on the adapter :p

Yes, it’s hardcoded in the morph themselves

>
> Do you think it would be hard to use a SimpleSwitchMorph ? As I understood, there is #asSpecAdapter that permis to plug pretty much everything ? Plus, making a specific adapter seems doable (I mean for a rookie like me).

That’s definitely a solution :)

> Well, I definitely have a variable number of buttons, depending on the model instance. Actualy, I want my model to be a matrix of toggle to specify a mask. I create instance with:
>
> MaskModel class>#maxIndex: anInteger
>     ^(self basicNew)
>         maxIndex: anInteger;
>         initialize;
>         yourself
>
> and instantiate a collection of buttons in #initializeWidgets.
>
> It doesn't change much after that so a DynamicComposableModel didn't seem usefull. But I only though that because I never used it. I will give it a try.

In DynamicComposableModel, when you instantiate a model using #instantiateModels:
it simulates accessors for you.

By example, if you do

1 to: 120 random do: [ :i |

        self instantiateModels: {
                (‘b’, i asString) asSymbol . #ButtonModel
        }

Then your layout can be

^ SpecLayout composed
        add: #b1;
        add: #b2;
        etc

Ben
Reply | Threaded
Open this post in threaded view
|

Re: Few questions about Spec (instance specific layout and skinning)

Thomas Bany
Hey,

I have a quick question. I'm trying to build an adapter (called MorphicSwitchAdapter) and a model for SimpleSwitchMorp. I based my layout on the ones in existing adapter (namely MorphicButtonAdapter).

And I get stuck in an infinite loop during the interpretation of the layout of the adapter.

The first lines are:

    ^ {#SimpleSwitchMorph.
            #onColor:. #(model onColor).
            #offColor:. #(model #offColor)
                        etc...

At some point, it tries to interpret #(#model #offColor)) and a few step latter, it comes back to step one and tries to interpret #(#MorphicSwitchAdapter #adapt: #model).

I tried this alternative {#model. #onColor} (though this one is equivalent to me) and this one #model. #onColor. but to no avail.

I have a feeling that the problem stems from the fact that PluggableButtonMorph seems to allready be an adapter which take a model while SimpleSwitchMorp does not.

Could you throw some light as to why the interpretation fails ?

Again, thanks for your help !

Thomas.
Reply | Threaded
Open this post in threaded view
|

Re: Few questions about Spec (instance specific layout and skinning)

Thomas Bany
Hum, I was pondering the problem at home and started from scratch. I don't have the issue anymore ...


2014-04-03 18:40 GMT+02:00 Thomas Bany <[hidden email]>:
Hey,

I have a quick question. I'm trying to build an adapter (called MorphicSwitchAdapter) and a model for SimpleSwitchMorp. I based my layout on the ones in existing adapter (namely MorphicButtonAdapter).

And I get stuck in an infinite loop during the interpretation of the layout of the adapter.

The first lines are:

    ^ {#SimpleSwitchMorph.
            #onColor:. #(model onColor).
            #offColor:. #(model #offColor)
                        etc...

At some point, it tries to interpret #(#model #offColor)) and a few step latter, it comes back to step one and tries to interpret #(#MorphicSwitchAdapter #adapt: #model).

I tried this alternative {#model. #onColor} (though this one is equivalent to me) and this one #model. #onColor. but to no avail.

I have a feeling that the problem stems from the fact that PluggableButtonMorph seems to allready be an adapter which take a model while SimpleSwitchMorp does not.

Could you throw some light as to why the interpretation fails ?

Again, thanks for your help !

Thomas.

Reply | Threaded
Open this post in threaded view
|

Re: Few questions about Spec (instance specific layout and skinning)

Thomas Bany
Okey so I looked deeper into the interpreter and found that the receiver of the next call is the returned value of the previous. I'm pretty sure it explains the infinite loop I was encountering.

It also made it problematic to register the morph to the anouncement of the adapter, since #addDependent: is send with a morph to the model and I needed the other way arround.

Adding #beDependentTo: somewhere in the class hierarchy of SimpleSwitchMorph make it work but I'm not sure I should do that.



2014-04-03 20:37 GMT+02:00 Thomas Bany <[hidden email]>:
Hum, I was pondering the problem at home and started from scratch. I don't have the issue anymore ...


2014-04-03 18:40 GMT+02:00 Thomas Bany <[hidden email]>:

Hey,

I have a quick question. I'm trying to build an adapter (called MorphicSwitchAdapter) and a model for SimpleSwitchMorp. I based my layout on the ones in existing adapter (namely MorphicButtonAdapter).

And I get stuck in an infinite loop during the interpretation of the layout of the adapter.

The first lines are:

    ^ {#SimpleSwitchMorph.
            #onColor:. #(model onColor).
            #offColor:. #(model #offColor)
                        etc...

At some point, it tries to interpret #(#model #offColor)) and a few step latter, it comes back to step one and tries to interpret #(#MorphicSwitchAdapter #adapt: #model).

I tried this alternative {#model. #onColor} (though this one is equivalent to me) and this one #model. #onColor. but to no avail.

I have a feeling that the problem stems from the fact that PluggableButtonMorph seems to allready be an adapter which take a model while SimpleSwitchMorp does not.

Could you throw some light as to why the interpretation fails ?

Again, thanks for your help !

Thomas.


Reply | Threaded
Open this post in threaded view
|

Re: Few questions about Spec (instance specific layout and skinning)

Benjamin Van Ryseghem (Pharo)
If you need it the other way around, then instead of calling it in the layout, 
there is a method on adapter named #buildWidget (or something close)
which is the perfect place for this :)

Ben

On 04 Apr 2014, at 01:53, Thomas Bany <[hidden email]> wrote:

Okey so I looked deeper into the interpreter and found that the receiver of the next call is the returned value of the previous. I'm pretty sure it explains the infinite loop I was encountering.

It also made it problematic to register the morph to the anouncement of the adapter, since #addDependent: is send with a morph to the model and I needed the other way arround.

Adding #beDependentTo: somewhere in the class hierarchy of SimpleSwitchMorph make it work but I'm not sure I should do that.



2014-04-03 20:37 GMT+02:00 Thomas Bany <[hidden email]>:
Hum, I was pondering the problem at home and started from scratch. I don't have the issue anymore ...


2014-04-03 18:40 GMT+02:00 Thomas Bany <[hidden email]>:

Hey,

I have a quick question. I'm trying to build an adapter (called MorphicSwitchAdapter) and a model for SimpleSwitchMorp. I based my layout on the ones in existing adapter (namely MorphicButtonAdapter).

And I get stuck in an infinite loop during the interpretation of the layout of the adapter.

The first lines are:

    ^ {#SimpleSwitchMorph.
            #onColor:. #(model onColor).
            #offColor:. #(model #offColor)
                        etc...

At some point, it tries to interpret #(#model #offColor)) and a few step latter, it comes back to step one and tries to interpret #(#MorphicSwitchAdapter #adapt: #model).

I tried this alternative {#model. #onColor} (though this one is equivalent to me) and this one #model. #onColor. but to no avail.

I have a feeling that the problem stems from the fact that PluggableButtonMorph seems to allready be an adapter which take a model while SimpleSwitchMorp does not.

Could you throw some light as to why the interpretation fails ?

Again, thanks for your help !

Thomas.