Programming interactions with State Machines

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

Programming interactions with State Machines

Carla F. Griggio
Hello everyone!
I'm here to tell you that I started experimenting with a Pharo implementation of this idea: http://swingstates.sourceforge.net/. For those into UI programming I really recommend reading the first paper cited in that page. It's for programming user interface interactions with state machines, an approach to avoid the classical "callback spaghetti" that sometimes we get with event handlers everywhere.

I have a tiny first step that shows an example for changing the color of a button on mouse over and changing it back to the original color on mouse out.


Evaluate this for executing the example:

SMButton openWithStateMachineInteraction

And here is the code of the state machine for that example:

SMButton class >> openWithStateMachineInteraction
|button stateMachine iddle hover |
button := self new.
stateMachine := SMStateMachine newForWidget: button.
iddle := (SMState newWithName:'iddle')
enter:[:stMachine | stMachine widget color: Color yellow ];
addTransition: ((SMTransition forEvent: 'mouse enter' withOutputState: 'hover')
transitionAction: [:stMachine | stMachine widget color: Color red ]).
hover := (SMState newWithName:'hover')
addTransition: (SMTransition forEvent: 'mouse out' withOutputState: 'iddle');
addTransition: (SMTransition forEvent: 'mouse enter' withOutputState: 'hover').
stateMachine addState: iddle; addState: hover.
stateMachine attachTo: button.
^button openInWorld
 
That code corresponds to the following states diagram:

Inline image 2

I will keep experimenting with this during the next weeks, and specially try to compare the pros and cons with regular event handling.

Something cool about this approach is that the same widget could change its interactive behaviour on the fly by just attaching a different interaction state machine to it :) 

Also, I'm doing this for programming user interface interactions, but it could be useful for anything that can be modelled with a state pattern.

Is there something similar out there already working? I was so eager to try this that I didn't look for related existing projects.

Cheers!
Carla.
Reply | Threaded
Open this post in threaded view
|

Re: Programming interactions with State Machines

Igor Stasenko

I did something similar (experiment).

I introduced a mode stack for my morphs.
So, all morphs has an initial "default" mode on stack.
When mouse enters the morph, a new mode "over" pushed on stack.

So, the "state" is not singular, it is composite.
The intent to use stack of modes was to associate a visual style (and any properties , in general
for each mode).

For example, in default mode, the morph's color is red,
but when 'over' mode pushed on stack, it overrides color property with blue.
This means, that to get a property, morph asks top-most mode (on stack) if it defines it,
and if not, goes to next one, up until default mode, which responds with default value(s) for all properties.

Another example, is "disabled" mode..
when this mode is on stack, it prevents "over" mode to be pushed.

So, you can imagine, that when morph being dragged, it has "dragged" mode on stack,
or if it in some transition (showing sliding/zooming animation), it has "animated mode" and so on.

In my experiment i even made a draw method to be a property of mode..
so morph's draw method looks like:

drawOn: aCanvas
    "Draw a morph by using method, supplied by current mode"
    | method |
    method := mode styleAt: #drawMethod.
    ^ self perform: method with: aCanvas
   
like that, i could able to even control how morph is drawn, not just changing the colors.

On 6 May 2013 02:31, Carla F. Griggio <[hidden email]> wrote:
Hello everyone!
I'm here to tell you that I started experimenting with a Pharo implementation of this idea: http://swingstates.sourceforge.net/. For those into UI programming I really recommend reading the first paper cited in that page. It's for programming user interface interactions with state machines, an approach to avoid the classical "callback spaghetti" that sometimes we get with event handlers everywhere.

I have a tiny first step that shows an example for changing the color of a button on mouse over and changing it back to the original color on mouse out.


Evaluate this for executing the example:

SMButton openWithStateMachineInteraction

And here is the code of the state machine for that example:

SMButton class >> openWithStateMachineInteraction
|button stateMachine iddle hover |
button := self new.
stateMachine := SMStateMachine newForWidget: button.
iddle := (SMState newWithName:'iddle')
enter:[:stMachine | stMachine widget color: Color yellow ];
addTransition: ((SMTransition forEvent: 'mouse enter' withOutputState: 'hover')
transitionAction: [:stMachine | stMachine widget color: Color red ]).
hover := (SMState newWithName:'hover')
addTransition: (SMTransition forEvent: 'mouse out' withOutputState: 'iddle');
addTransition: (SMTransition forEvent: 'mouse enter' withOutputState: 'hover').
stateMachine addState: iddle; addState: hover.
stateMachine attachTo: button.
^button openInWorld
 
That code corresponds to the following states diagram:

Inline image 2

I will keep experimenting with this during the next weeks, and specially try to compare the pros and cons with regular event handling.

Something cool about this approach is that the same widget could change its interactive behaviour on the fly by just attaching a different interaction state machine to it :) 

Also, I'm doing this for programming user interface interactions, but it could be useful for anything that can be modelled with a state pattern.

Is there something similar out there already working? I was so eager to try this that I didn't look for related existing projects.

Cheers!
Carla.



--
Best regards,
Igor Stasenko.


Reply | Threaded
Open this post in threaded view
|

Re: Programming interactions with State Machines

Yanni Chiu
In reply to this post by Carla F. Griggio
On 05/05/13 8:31 PM, Carla F. Griggio wrote:
>
> I will keep experimenting with this during the next weeks, and specially
> try to compare the pros and cons with regular event handling.

I've always been curious to see how state machine transitions would map
to Announcements/event handling.

> Something cool about this approach is that the same widget could change
> its interactive behaviour on the fly by just attaching a different
> interaction state machine to it :)

Changing the state machine is called "subtype migration" in
Shlaer-Mellor parlance. It seems to get tricky when the supertype also
has a state machine.

> Also, I'm doing this for programming user interface interactions, but it
> could be useful for anything that can be modelled with a state pattern.
>
> Is there something similar out there already working? I was so eager to
> try this that I didn't look for related existing projects.

The PostgreSQL Client [1] (a native Smalltalk client connection to a
Postgres server) uses an internal state machine to drive the
client/server connection. It was built with the Shlaer-Mellor method [2]
concepts in mind. There was an accompanying state machine diagram drawn
with the Connectors [3] tool (the link from SqueakMap is long dead, but
I could try to dig up a copy).

The implementation is very awkward around where the public API to make
SQL queries interacts with the underlying state machine inside the
PGConnection object. There's a loop that continues until a "good" state
is reached. Then the result is gathered from the connection object.
Since the code making the SQL query is not event-driven, nor is it part
of the same state-machine architecture of the postgres client, the
result is the awkward loop.

I'd really like to see more examples of state machine usage.

[1] http://www.squeaksource.com/PostgresV2.html
[2] http://en.wikipedia.org/wiki/Shlaer–Mellor_method
[3] http://wiki.squeak.org/squeak/1773


Reply | Threaded
Open this post in threaded view
|

Re: Programming interactions with State Machines

stephane ducasse
In reply to this post by Carla F. Griggio

On May 6, 2013, at 2:31 AM, Carla F. Griggio <[hidden email]> wrote:

Hello everyone!
I'm here to tell you that I started experimenting with a Pharo implementation of this idea: http://swingstates.sourceforge.net/. For those into UI programming I really recommend reading the first paper cited in that page. It's for programming user interface interactions with state machines, an approach to avoid the classical "callback spaghetti" that sometimes we get with event handlers everywhere.

This is looking interesting. Now we should check how it works with inheritance. 
Keep us posted about your progress.

Stef

I have a tiny first step that shows an example for changing the color of a button on mouse over and changing it back to the original color on mouse out.


Evaluate this for executing the example:

SMButton openWithStateMachineInteraction

And here is the code of the state machine for that example:

SMButton class >> openWithStateMachineInteraction
|button stateMachine iddle hover |
button := self new.
stateMachine := SMStateMachine newForWidget: button.
iddle := (SMState newWithName:'iddle')
enter:[:stMachine | stMachine widget color: Color yellow ];
addTransition: ((SMTransition forEvent: 'mouse enter' withOutputState: 'hover')
transitionAction: [:stMachine | stMachine widget color: Color red ]).
hover := (SMState newWithName:'hover')
addTransition: (SMTransition forEvent: 'mouse out' withOutputState: 'iddle');
addTransition: (SMTransition forEvent: 'mouse enter' withOutputState: 'hover').
stateMachine addState: iddle; addState: hover.
stateMachine attachTo: button.
^button openInWorld
 
That code corresponds to the following states diagram:

<Screen Shot 2013-05-06 at 2.27.20 AM.png>

I will keep experimenting with this during the next weeks, and specially try to compare the pros and cons with regular event handling.

Something cool about this approach is that the same widget could change its interactive behaviour on the fly by just attaching a different interaction state machine to it :) 

Also, I'm doing this for programming user interface interactions, but it could be useful for anything that can be modelled with a state pattern.

Is there something similar out there already working? I was so eager to try this that I didn't look for related existing projects.

Cheers!
Carla.

Reply | Threaded
Open this post in threaded view
|

Re: Programming interactions with State Machines

Igor Stasenko
In reply to this post by Yanni Chiu
On 6 May 2013 08:22, Yanni Chiu <[hidden email]> wrote:

> On 05/05/13 8:31 PM, Carla F. Griggio wrote:
>>
>>
>> I will keep experimenting with this during the next weeks, and specially
>> try to compare the pros and cons with regular event handling.
>
>
> I've always been curious to see how state machine transitions would map to
> Announcements/event handling.
>
>
>> Something cool about this approach is that the same widget could change
>> its interactive behaviour on the fly by just attaching a different
>> interaction state machine to it :)
>
>
> Changing the state machine is called "subtype migration" in Shlaer-Mellor
> parlance. It seems to get tricky when the supertype also has a state
> machine.
>
>
>> Also, I'm doing this for programming user interface interactions, but it
>> could be useful for anything that can be modelled with a state pattern.
>>
>> Is there something similar out there already working? I was so eager to
>> try this that I didn't look for related existing projects.
>
>
> The PostgreSQL Client [1] (a native Smalltalk client connection to a
> Postgres server) uses an internal state machine to drive the client/server
> connection. It was built with the Shlaer-Mellor method [2] concepts in mind.
> There was an accompanying state machine diagram drawn with the Connectors
> [3] tool (the link from SqueakMap is long dead, but I could try to dig up a
> copy).
>
> The implementation is very awkward around where the public API to make SQL
> queries interacts with the underlying state machine inside the PGConnection
> object. There's a loop that continues until a "good" state is reached. Then
> the result is gathered from the connection object. Since the code making the
> SQL query is not event-driven, nor is it part of the same state-machine
> architecture of the postgres client, the result is the awkward loop.
>
> I'd really like to see more examples of state machine usage.
>
> [1] http://www.squeaksource.com/PostgresV2.html
> [2] http://en.wikipedia.org/wiki/Shlaer–Mellor_method
> [3] http://wiki.squeak.org/squeak/1773
>
>
What i often observing is that it is not matter, how good & sound the
scientific concept..
when it goes to implementation it has big chances to end up with messy code,
ineffective, inappropriate  and therefore useless :)

That not to say that science is just waste of time.. it is to say that
science alone is not enough.

--
Best regards,
Igor Stasenko.