An idea about Pluggable widgets

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

An idea about Pluggable widgets

Igor Stasenko
I have an idea how to refactor the pluggable morphs mess.

The main principle behind all pluggables, that you have a model (which
is held in instance variable),
and then morph having additional ivars to speak with this model, which
the selector names you should use
to access certain state from model.

For example:

AlignmentMorph subclass: #PluggableButtonMorph
        instanceVariableNames: 'model label getStateSelector actionSelector
getLabelSelector getMenuSelector shortcutCharacter askBeforeChanging
triggerOnMouseDown offColor onColor feedbackColor
showSelectionFeedback allButtons arguments argumentsProvider
argumentsSelector gradientLook enabled actionBlock getColorSelector
getEnabledSelector'
        classVariableNames: 'UseGradientLook'
        poolDictionaries: ''
        category: 'Morphic-Pluggable Widgets'


as you can see it is crowded with all those ivars, where part of them
used to speak with model,
and part of them used for keeping flags and additional parameters
which you can customize when creating a button.
getStateSelector actionSelector getLabelSelector getMenuSelector
 arguments argumentsProvider argumentsSelector gradientLook
actionBlock getColorSelector getEnabledSelector

and this is really messy..
Take a look at code:

performAction
        "Inform the model that this button has been pressed. Sent by the
controller when this button is pressed. If the button's actionSelector
takes any arguments, they are obtained dynamically by sending the
argumentSelector to the argumentsProvider"

        enabled ifFalse: [^self].
        askBeforeChanging ifTrue: [model okToChange ifFalse: [^ self]].
        self actionBlock ifNotNil: [ ^ self actionBlock value].
        actionSelector ifNotNil:
                [actionSelector numArgs == 0
                        ifTrue: [model perform: actionSelector]
                        ifFalse:
                                [argumentsProvider ifNotNil:
                                        [arguments := argumentsProvider perform: argumentsSelector].
                                        model perform: actionSelector withArguments: arguments]]


Now think if we could replace this with simple:


performAction
        "Inform the model that this button has been pressed. Sent by the
controller when this button is pressed. If the button's actionSelector
takes any arguments, they are obtained dynamically by sending the
argumentSelector to the argumentsProvider"

        enabled ifFalse: [^self].
        model performAction.


so, in this case, we just put an obligation onto model to perform any
action in response to button clicked,
and button no longer cares about crappy logic how it should send a
message to model
(via action block, via actionSelector ... and whether it should pass
any additional arguments or not..)

So, in all places which using things in a way like:

getListItems
  ^ model perform: getListItemsSelector

now will be replaced with clean:

getListItems
  ^ model getListItems

So, a pluggable morph no longer cares about keeping all those
selectors and maintain an obscure logic whether selector is nil or not
nil etc etc..
Let model handle it!

Then you may ask, what if i have a model, which doesn't implements
such protocol (required for specific pluggable widget).
The answer is simple:
 - create a pluggable model class for given widget, which wraps around
your object and can keeps all those messy 'getLabelSelector'
'getMenuSelector' ,
inside and mediates between your model and widget.

The benefit of it that widgets code will be much more cleaner.
And another benefit is that you know what exact protocol is needed if
you want to use your object as a model to given widget (list, button
etc).
And in most of the cases, you don't need to use this messy
'getXYZSelector', because you can simply answer to messages sent by
widget and provide
necessary data.
But if you wanna go messy, you just use wrapper model, which contains
all those 'getXYZSelectors'  which you can set to whatever you like.

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: An idea about Pluggable widgets

EstebanLM
I'm using a similar approach for Mars.
Views in Mars always consume from a similar structure and we have the concept of "model adaptor" when you need to adapt from your model to the views. We also have a couple of generic adaptors who adapts nicely to your model.
Let's say we need to place a string into a MRLabel, and model for label is prepared to understand #content message.
so you say something like this:

        MRLabel new
                model: ('My label' adaptAccessor: #yourself);
                ...etc...

and that way you have "cleanness" in both sides :)

other problems is when widgets triggers events (like your example, a button click, named performAction).
I think here you should not trigger anything but an announcement.
Your performAction should look more like:

performAction
        self announce: ButtonPressed

and your "client code" should look:

MRButton new
        on: ButtonPressed do: [ ... whatever... ]


So, summarizing.... I "more or less" agree with your approach. Or better I mean: I agree in the "accessing" part, but I would like using announcements to trigger events.

cheers,
Esteban


El 07/04/2011, a las 10:26a.m., Igor Stasenko escribió:

> I have an idea how to refactor the pluggable morphs mess.
>
> The main principle behind all pluggables, that you have a model (which
> is held in instance variable),
> and then morph having additional ivars to speak with this model, which
> the selector names you should use
> to access certain state from model.
>
> For example:
>
> AlignmentMorph subclass: #PluggableButtonMorph
> instanceVariableNames: 'model label getStateSelector actionSelector
> getLabelSelector getMenuSelector shortcutCharacter askBeforeChanging
> triggerOnMouseDown offColor onColor feedbackColor
> showSelectionFeedback allButtons arguments argumentsProvider
> argumentsSelector gradientLook enabled actionBlock getColorSelector
> getEnabledSelector'
> classVariableNames: 'UseGradientLook'
> poolDictionaries: ''
> category: 'Morphic-Pluggable Widgets'
>
>
> as you can see it is crowded with all those ivars, where part of them
> used to speak with model,
> and part of them used for keeping flags and additional parameters
> which you can customize when creating a button.
> getStateSelector actionSelector getLabelSelector getMenuSelector
> arguments argumentsProvider argumentsSelector gradientLook
> actionBlock getColorSelector getEnabledSelector
>
> and this is really messy..
> Take a look at code:
>
> performAction
> "Inform the model that this button has been pressed. Sent by the
> controller when this button is pressed. If the button's actionSelector
> takes any arguments, they are obtained dynamically by sending the
> argumentSelector to the argumentsProvider"
>
> enabled ifFalse: [^self].
> askBeforeChanging ifTrue: [model okToChange ifFalse: [^ self]].
> self actionBlock ifNotNil: [ ^ self actionBlock value].
> actionSelector ifNotNil:
> [actionSelector numArgs == 0
> ifTrue: [model perform: actionSelector]
> ifFalse:
> [argumentsProvider ifNotNil:
> [arguments := argumentsProvider perform: argumentsSelector].
> model perform: actionSelector withArguments: arguments]]
>
>
> Now think if we could replace this with simple:
>
>
> performAction
> "Inform the model that this button has been pressed. Sent by the
> controller when this button is pressed. If the button's actionSelector
> takes any arguments, they are obtained dynamically by sending the
> argumentSelector to the argumentsProvider"
>
> enabled ifFalse: [^self].
>        model performAction.
>
>
> so, in this case, we just put an obligation onto model to perform any
> action in response to button clicked,
> and button no longer cares about crappy logic how it should send a
> message to model
> (via action block, via actionSelector ... and whether it should pass
> any additional arguments or not..)
>
> So, in all places which using things in a way like:
>
> getListItems
>  ^ model perform: getListItemsSelector
>
> now will be replaced with clean:
>
> getListItems
>  ^ model getListItems
>
> So, a pluggable morph no longer cares about keeping all those
> selectors and maintain an obscure logic whether selector is nil or not
> nil etc etc..
> Let model handle it!
>
> Then you may ask, what if i have a model, which doesn't implements
> such protocol (required for specific pluggable widget).
> The answer is simple:
> - create a pluggable model class for given widget, which wraps around
> your object and can keeps all those messy 'getLabelSelector'
> 'getMenuSelector' ,
> inside and mediates between your model and widget.
>
> The benefit of it that widgets code will be much more cleaner.
> And another benefit is that you know what exact protocol is needed if
> you want to use your object as a model to given widget (list, button
> etc).
> And in most of the cases, you don't need to use this messy
> 'getXYZSelector', because you can simply answer to messages sent by
> widget and provide
> necessary data.
> But if you wanna go messy, you just use wrapper model, which contains
> all those 'getXYZSelectors'  which you can set to whatever you like.
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>


Reply | Threaded
Open this post in threaded view
|

Re: An idea about Pluggable widgets

Igor Stasenko
On 7 April 2011 16:04, Esteban Lorenzano <[hidden email]> wrote:

> I'm using a similar approach for Mars.
> Views in Mars always consume from a similar structure and we have the concept of "model adaptor" when you need to adapt from your model to the views. We also have a couple of generic adaptors who adapts nicely to your model.
> Let's say we need to place a string into a MRLabel, and model for label is prepared to understand #content message.
> so you say something like this:
>
>        MRLabel new
>                model: ('My label' adaptAccessor: #yourself);
>                ...etc...
>
> and that way you have "cleanness" in both sides :)
>
> other problems is when widgets triggers events (like your example, a button click, named performAction).
> I think here you should not trigger anything but an announcement.
> Your performAction should look more like:
>
> performAction
>        self announce: ButtonPressed
>
> and your "client code" should look:
>
> MRButton new
>        on: ButtonPressed do: [ ... whatever... ]
>
>
> So, summarizing.... I "more or less" agree with your approach. Or better I mean: I agree in the "accessing" part, but I would like using announcements to trigger events.

Yes, but that is another step , another milestone. If you do it
gradually, first you clean the mess out, and then introduce
announcements,
otherwise you have good chances to not deliver, because for
announcements you need to use different api and rewrite things
everywhere.

While model adaptors (i like the naming btw) could be introduced
seamlessly without breaking existing code that much.

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: An idea about Pluggable widgets

Alain Plantec-3
In reply to this post by Igor Stasenko
Hi Igor,
I'm not sure to understand.
As an example:
TrafficLight is my model with an action for the red light.
If I build a view for it, I can use a Button with #performAction:

Button>> performAction
     ^ model performAction

So, my TrafficLight must implement a #performAction method.
Now, if I want also an action for the green light performed when another
button is pressed.
It means that I've to implement a specific model class for the red and
another for the green ?
cheers
Alain





for example, I have a simple UI with two buttons

Le 07/04/2011 15:26, Igor Stasenko a écrit :

> I have an idea how to refactor the pluggable morphs mess.
>
> The main principle behind all pluggables, that you have a model (which
> is held in instance variable),
> and then morph having additional ivars to speak with this model, which
> the selector names you should use
> to access certain state from model.
>
> For example:
>
> AlignmentMorph subclass: #PluggableButtonMorph
> instanceVariableNames: 'model label getStateSelector actionSelector
> getLabelSelector getMenuSelector shortcutCharacter askBeforeChanging
> triggerOnMouseDown offColor onColor feedbackColor
> showSelectionFeedback allButtons arguments argumentsProvider
> argumentsSelector gradientLook enabled actionBlock getColorSelector
> getEnabledSelector'
> classVariableNames: 'UseGradientLook'
> poolDictionaries: ''
> category: 'Morphic-Pluggable Widgets'
>
>
> as you can see it is crowded with all those ivars, where part of them
> used to speak with model,
> and part of them used for keeping flags and additional parameters
> which you can customize when creating a button.
> getStateSelector actionSelector getLabelSelector getMenuSelector
>   arguments argumentsProvider argumentsSelector gradientLook
> actionBlock getColorSelector getEnabledSelector
>
> and this is really messy..
> Take a look at code:
>
> performAction
> "Inform the model that this button has been pressed. Sent by the
> controller when this button is pressed. If the button's actionSelector
> takes any arguments, they are obtained dynamically by sending the
> argumentSelector to the argumentsProvider"
>
> enabled ifFalse: [^self].
> askBeforeChanging ifTrue: [model okToChange ifFalse: [^ self]].
> self actionBlock ifNotNil: [ ^ self actionBlock value].
> actionSelector ifNotNil:
> [actionSelector numArgs == 0
> ifTrue: [model perform: actionSelector]
> ifFalse:
> [argumentsProvider ifNotNil:
> [arguments := argumentsProvider perform: argumentsSelector].
> model perform: actionSelector withArguments: arguments]]
>
>
> Now think if we could replace this with simple:
>
>
> performAction
> "Inform the model that this button has been pressed. Sent by the
> controller when this button is pressed. If the button's actionSelector
> takes any arguments, they are obtained dynamically by sending the
> argumentSelector to the argumentsProvider"
>
> enabled ifFalse: [^self].
>          model performAction.
>
>
> so, in this case, we just put an obligation onto model to perform any
> action in response to button clicked,
> and button no longer cares about crappy logic how it should send a
> message to model
> (via action block, via actionSelector ... and whether it should pass
> any additional arguments or not..)
>
> So, in all places which using things in a way like:
>
> getListItems
>    ^ model perform: getListItemsSelector
>
> now will be replaced with clean:
>
> getListItems
>    ^ model getListItems
>
> So, a pluggable morph no longer cares about keeping all those
> selectors and maintain an obscure logic whether selector is nil or not
> nil etc etc..
> Let model handle it!
>
> Then you may ask, what if i have a model, which doesn't implements
> such protocol (required for specific pluggable widget).
> The answer is simple:
>   - create a pluggable model class for given widget, which wraps around
> your object and can keeps all those messy 'getLabelSelector'
> 'getMenuSelector' ,
> inside and mediates between your model and widget.
>
> The benefit of it that widgets code will be much more cleaner.
> And another benefit is that you know what exact protocol is needed if
> you want to use your object as a model to given widget (list, button
> etc).
> And in most of the cases, you don't need to use this messy
> 'getXYZSelector', because you can simply answer to messages sent by
> widget and provide
> necessary data.
> But if you wanna go messy, you just use wrapper model, which contains
> all those 'getXYZSelectors'  which you can set to whatever you like.
>


Reply | Threaded
Open this post in threaded view
|

Re: An idea about Pluggable widgets

Igor Stasenko
On 7 April 2011 18:59, Alain Plantec <[hidden email]> wrote:

> Hi Igor,
> I'm not sure to understand.
> As an example:
> TrafficLight is my model with an action for the red light.
> If I build a view for it, I can use a Button with #performAction:
>
> Button>> performAction
>    ^ model performAction
>
> So, my TrafficLight must implement a #performAction method.
> Now, if I want also an action for the green light performed when another
> button is pressed.
> It means that I've to implement a specific model class for the red and
> another for the green ?

For that case you use model adapters.
So, then you do something like:

button1 model: (self for: #performAction adapt: #turnRed)
button2 model: (self for: #performAction adapt: #turnGreen)

and so, a receiver (which is a model), will receive #turnRed, or
#turnGreen messages,
while button will still use same message for model - #performAction

> cheers
> Alain
>
>
> for example, I have a simple UI with two buttons
>
> Le 07/04/2011 15:26, Igor Stasenko a écrit :
>>
>> I have an idea how to refactor the pluggable morphs mess.
>>
>> The main principle behind all pluggables, that you have a model (which
>> is held in instance variable),
>> and then morph having additional ivars to speak with this model, which
>> the selector names you should use
>> to access certain state from model.
>>
>> For example:
>>
>> AlignmentMorph subclass: #PluggableButtonMorph
>>        instanceVariableNames: 'model label getStateSelector actionSelector
>> getLabelSelector getMenuSelector shortcutCharacter askBeforeChanging
>> triggerOnMouseDown offColor onColor feedbackColor
>> showSelectionFeedback allButtons arguments argumentsProvider
>> argumentsSelector gradientLook enabled actionBlock getColorSelector
>> getEnabledSelector'
>>        classVariableNames: 'UseGradientLook'
>>        poolDictionaries: ''
>>        category: 'Morphic-Pluggable Widgets'
>>
>>
>> as you can see it is crowded with all those ivars, where part of them
>> used to speak with model,
>> and part of them used for keeping flags and additional parameters
>> which you can customize when creating a button.
>> getStateSelector actionSelector getLabelSelector getMenuSelector
>>  arguments argumentsProvider argumentsSelector gradientLook
>> actionBlock getColorSelector getEnabledSelector
>>
>> and this is really messy..
>> Take a look at code:
>>
>> performAction
>>        "Inform the model that this button has been pressed. Sent by the
>> controller when this button is pressed. If the button's actionSelector
>> takes any arguments, they are obtained dynamically by sending the
>> argumentSelector to the argumentsProvider"
>>
>>        enabled ifFalse: [^self].
>>        askBeforeChanging ifTrue: [model okToChange ifFalse: [^ self]].
>>        self actionBlock ifNotNil: [ ^ self actionBlock value].
>>        actionSelector ifNotNil:
>>                [actionSelector numArgs == 0
>>                        ifTrue: [model perform: actionSelector]
>>                        ifFalse:
>>                                [argumentsProvider ifNotNil:
>>                                        [arguments := argumentsProvider
>> perform: argumentsSelector].
>>                                        model perform: actionSelector
>> withArguments: arguments]]
>>
>>
>> Now think if we could replace this with simple:
>>
>>
>> performAction
>>        "Inform the model that this button has been pressed. Sent by the
>> controller when this button is pressed. If the button's actionSelector
>> takes any arguments, they are obtained dynamically by sending the
>> argumentSelector to the argumentsProvider"
>>
>>        enabled ifFalse: [^self].
>>         model performAction.
>>
>>
>> so, in this case, we just put an obligation onto model to perform any
>> action in response to button clicked,
>> and button no longer cares about crappy logic how it should send a
>> message to model
>> (via action block, via actionSelector ... and whether it should pass
>> any additional arguments or not..)
>>
>> So, in all places which using things in a way like:
>>
>> getListItems
>>   ^ model perform: getListItemsSelector
>>
>> now will be replaced with clean:
>>
>> getListItems
>>   ^ model getListItems
>>
>> So, a pluggable morph no longer cares about keeping all those
>> selectors and maintain an obscure logic whether selector is nil or not
>> nil etc etc..
>> Let model handle it!
>>
>> Then you may ask, what if i have a model, which doesn't implements
>> such protocol (required for specific pluggable widget).
>> The answer is simple:
>>  - create a pluggable model class for given widget, which wraps around
>> your object and can keeps all those messy 'getLabelSelector'
>> 'getMenuSelector' ,
>> inside and mediates between your model and widget.
>>
>> The benefit of it that widgets code will be much more cleaner.
>> And another benefit is that you know what exact protocol is needed if
>> you want to use your object as a model to given widget (list, button
>> etc).
>> And in most of the cases, you don't need to use this messy
>> 'getXYZSelector', because you can simply answer to messages sent by
>> widget and provide
>> necessary data.
>> But if you wanna go messy, you just use wrapper model, which contains
>> all those 'getXYZSelectors'  which you can set to whatever you like.
>>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: An idea about Pluggable widgets

Igor Stasenko
On 7 April 2011 19:23, Igor Stasenko <[hidden email]> wrote:

> On 7 April 2011 18:59, Alain Plantec <[hidden email]> wrote:
>> Hi Igor,
>> I'm not sure to understand.
>> As an example:
>> TrafficLight is my model with an action for the red light.
>> If I build a view for it, I can use a Button with #performAction:
>>
>> Button>> performAction
>>    ^ model performAction
>>
>> So, my TrafficLight must implement a #performAction method.
>> Now, if I want also an action for the green light performed when another
>> button is pressed.
>> It means that I've to implement a specific model class for the red and
>> another for the green ?
>
> For that case you use model adapters.
> So, then you do something like:
>
> button1 model: (self for: #performAction adapt: #turnRed)
> button2 model: (self for: #performAction adapt: #turnGreen)
>
> and so, a receiver (which is a model), will receive #turnRed, or
> #turnGreen messages,
> while button will still use same message for model - #performAction
>

or alternatively, we could ask a widget to create and install an
instance of model adaptor
(so it will construct a properly initialized model adaptor, when you
only need to fill the data in it):

(button1 installModelAdaptorFor: self)
   actionSelector: #turnRed.

(button2 installModelAdaptorFor: self)
   actionSelector: #turnGreen.


>> cheers
>> Alain
>>
>>
>> for example, I have a simple UI with two buttons
>>
>> Le 07/04/2011 15:26, Igor Stasenko a écrit :
>>>
>>> I have an idea how to refactor the pluggable morphs mess.
>>>
>>> The main principle behind all pluggables, that you have a model (which
>>> is held in instance variable),
>>> and then morph having additional ivars to speak with this model, which
>>> the selector names you should use
>>> to access certain state from model.
>>>
>>> For example:
>>>
>>> AlignmentMorph subclass: #PluggableButtonMorph
>>>        instanceVariableNames: 'model label getStateSelector actionSelector
>>> getLabelSelector getMenuSelector shortcutCharacter askBeforeChanging
>>> triggerOnMouseDown offColor onColor feedbackColor
>>> showSelectionFeedback allButtons arguments argumentsProvider
>>> argumentsSelector gradientLook enabled actionBlock getColorSelector
>>> getEnabledSelector'
>>>        classVariableNames: 'UseGradientLook'
>>>        poolDictionaries: ''
>>>        category: 'Morphic-Pluggable Widgets'
>>>
>>>
>>> as you can see it is crowded with all those ivars, where part of them
>>> used to speak with model,
>>> and part of them used for keeping flags and additional parameters
>>> which you can customize when creating a button.
>>> getStateSelector actionSelector getLabelSelector getMenuSelector
>>>  arguments argumentsProvider argumentsSelector gradientLook
>>> actionBlock getColorSelector getEnabledSelector
>>>
>>> and this is really messy..
>>> Take a look at code:
>>>
>>> performAction
>>>        "Inform the model that this button has been pressed. Sent by the
>>> controller when this button is pressed. If the button's actionSelector
>>> takes any arguments, they are obtained dynamically by sending the
>>> argumentSelector to the argumentsProvider"
>>>
>>>        enabled ifFalse: [^self].
>>>        askBeforeChanging ifTrue: [model okToChange ifFalse: [^ self]].
>>>        self actionBlock ifNotNil: [ ^ self actionBlock value].
>>>        actionSelector ifNotNil:
>>>                [actionSelector numArgs == 0
>>>                        ifTrue: [model perform: actionSelector]
>>>                        ifFalse:
>>>                                [argumentsProvider ifNotNil:
>>>                                        [arguments := argumentsProvider
>>> perform: argumentsSelector].
>>>                                        model perform: actionSelector
>>> withArguments: arguments]]
>>>
>>>
>>> Now think if we could replace this with simple:
>>>
>>>
>>> performAction
>>>        "Inform the model that this button has been pressed. Sent by the
>>> controller when this button is pressed. If the button's actionSelector
>>> takes any arguments, they are obtained dynamically by sending the
>>> argumentSelector to the argumentsProvider"
>>>
>>>        enabled ifFalse: [^self].
>>>         model performAction.
>>>
>>>
>>> so, in this case, we just put an obligation onto model to perform any
>>> action in response to button clicked,
>>> and button no longer cares about crappy logic how it should send a
>>> message to model
>>> (via action block, via actionSelector ... and whether it should pass
>>> any additional arguments or not..)
>>>
>>> So, in all places which using things in a way like:
>>>
>>> getListItems
>>>   ^ model perform: getListItemsSelector
>>>
>>> now will be replaced with clean:
>>>
>>> getListItems
>>>   ^ model getListItems
>>>
>>> So, a pluggable morph no longer cares about keeping all those
>>> selectors and maintain an obscure logic whether selector is nil or not
>>> nil etc etc..
>>> Let model handle it!
>>>
>>> Then you may ask, what if i have a model, which doesn't implements
>>> such protocol (required for specific pluggable widget).
>>> The answer is simple:
>>>  - create a pluggable model class for given widget, which wraps around
>>> your object and can keeps all those messy 'getLabelSelector'
>>> 'getMenuSelector' ,
>>> inside and mediates between your model and widget.
>>>
>>> The benefit of it that widgets code will be much more cleaner.
>>> And another benefit is that you know what exact protocol is needed if
>>> you want to use your object as a model to given widget (list, button
>>> etc).
>>> And in most of the cases, you don't need to use this messy
>>> 'getXYZSelector', because you can simply answer to messages sent by
>>> widget and provide
>>> necessary data.
>>> But if you wanna go messy, you just use wrapper model, which contains
>>> all those 'getXYZSelectors'  which you can set to whatever you like.
>>>
>>
>>
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: An idea about Pluggable widgets

Alain Plantec-3
In reply to this post by Igor Stasenko
Le 07/04/2011 19:23, Igor Stasenko a écrit :
> button1 model: (self for: #performAction adapt: #turnRed)
> button2 model: (self for: #performAction adapt: #turnGreen)
yes, cool!
It seems to be a good way to clean morphic
cheers
Alain

Reply | Threaded
Open this post in threaded view
|

Re: An idea about Pluggable widgets

Nicolas Cellier
2011/4/7 Alain Plantec <[hidden email]>:

> Le 07/04/2011 19:23, Igor Stasenko a écrit :
>>
>> button1 model: (self for: #performAction adapt: #turnRed)
>> button2 model: (self for: #performAction adapt: #turnGreen)
>
> yes, cool!
> It seems to be a good way to clean morphic
> cheers
> Alain
>
>

Yes, it's delegating the job to specialized objects.
Specialized objects shall know how to.
That should prevent Morphs to be omniscient.

My favourite name for the opposite pattern is "god programming": we
all encountered the thousand lines functions with tons of imbricated
if/switch logic in C or C// world, didn't we ?

Somehow, Igor proposal reminds me the VW UI architecture were they
pushed the wrapper pattern very far.
Personnally, I found myself comfortable with it, but it had its detractors too.
It would be interesting to analyze their arguments.

cheers.

Nicolas

Reply | Threaded
Open this post in threaded view
|

Re: An idea about Pluggable widgets

Richard Durr-2
Why not do it like in Cocoa?
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html%23//apple_ref/doc/uid/TP40002974-CH6-SW16

On Thu, Apr 7, 2011 at 9:26 PM, Nicolas Cellier <[hidden email]> wrote:
2011/4/7 Alain Plantec <[hidden email]>:
> Le 07/04/2011 19:23, Igor Stasenko a écrit :
>>
>> button1 model: (self for: #performAction adapt: #turnRed)
>> button2 model: (self for: #performAction adapt: #turnGreen)
>
> yes, cool!
> It seems to be a good way to clean morphic
> cheers
> Alain
>
>

Yes, it's delegating the job to specialized objects.
Specialized objects shall know how to.
That should prevent Morphs to be omniscient.

My favourite name for the opposite pattern is "god programming": we
all encountered the thousand lines functions with tons of imbricated
if/switch logic in C or C// world, didn't we ?

Somehow, Igor proposal reminds me the VW UI architecture were they
pushed the wrapper pattern very far.
Personnally, I found myself comfortable with it, but it had its detractors too.
It would be interesting to analyze their arguments.

cheers.

Nicolas