[Seaside] Wandering Announcements - Design

Keith Hodges keith_hodges at yahoo.co.uk
Fri Apr 25 08:04:19 UTC 2008

Further to the announcements debate.... here is a code design overview 
for your considered appraisal.

"Wandering Announcements" inSeaside.

I am throwing some code together so there is some untested code 
available in

Installer ss project: 'Jetsam'; install: 'Sea28WA'.

best regards



(This design is based upon Lukas' simple Announcements framework as a 
starting point)

Whereas Announcements are often used with a centralized Announcer, 
Wandering announcements may
look for someone to respond to their message in the given surroundings. 
They may "bubble up" a component hierarchy, or interrogate siblings, or 
decorations as they wish.

Each WAComponent in seaside is a node in this communications network. 
Nodes function as potential announcers, and as a source of potential 
routes for wandering announcements to follow.

Routing is provided by #ann* methods, which are private to the 
Announcers for use by instances of WanderingAnnouncements, no one else 
should call them.  e.g. #annParent #annSiblingsIn: [ :siblings | .... 
].  #annChildrenIn: [ :children | .... ].

Unlike the original framework in which Announcements allow the Announcer 
to figure out what to announce to whom, as much responsibility passed 
over to each Announcement as is possible so that behaviour can be 
overridden completely for different needs.

I.e. when handling an announcement we double back #announceTo: to the 
announcement itself to give it complete control, over what it does 
before or after informing dependants. It typically passes straight back 
to the anouncers #dependantsAnnounce: for the default behavior. This 
allows an Announcement to replace the behaviour of 
Announcer-#dependantsAnnounce: altogether if it wants to.

Triggering example: (we always return the original announcer)

theAnnouncement := self announcer announce: (SomeAnnouncement param: arg1).

Subscriptions example:

self announcer on: SomeAnouncement do: [ :announcement | ...  ].
self announcer on: SomeAnouncement send: tellMe: to: anObject.

Normally, the announcer is passed as the argument to the 
Block/MessageSend, however, each announcement implements #args, so it 
can call a method that is not expecting an Announcement as the 
parameter. This enables you to wire up objects that were not designed 
with announcements in mind.

example trigger:

self announce: (HtmlUpdateAnnouncement on: html)

self announcer on: HtmlUpdateAnouncement send: #renderOn: to: anObject.


^ Array with: html

Wandering around

Example... we have a list of items, and one of the items in the list has 
just been clicked. It would like to inform the current selection, one of 
its "siblings" that it is being de-selected. I say siblings, because it 
doesnt really know where in the world it is.

The nature of this Seaside component world, is that there are some 
objects that might be naturally considered to be siblings, so these are 
automatically traversed by WALookupSideways. But we can also register 
other objects/components which also respond to a sideways query, see below:

Client Code:

foundItem := ((aComponent announce:  (WALookupSideways selector: 
#isSelected)) detect: [ :found | found isSelected ]) result.
foundItem ifNotNil: [ foundItem deselect ].

Walking through this example...  we give our announcement, 
WALookupSideways, a selector to look out for. Every object in its 
wandering that responds to the selector is passed into the detect block. 
When the result of the detect block is true, wandering stops, and the 
announcer is returned (remember we always return the announcer). We send 
#result to the announcer to obtain the found item.

If there is an object that is not in the search path that would like to 
participate, it can be registered like so.

aComponent announcer on: WALookupSideways do: [ :announcement | 
announcement query: someObject ]


hows that for starters..


More information about the seaside mailing list