[Seaside] Wandering Announcements - Design
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
Installer ss project: 'Jetsam'; install: 'Sea28WA'.
(This design is based upon Lukas' simple Announcements framework as a
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).
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.
self announce: (HtmlUpdateAnnouncement on: html)
self announcer on: HtmlUpdateAnouncement send: #renderOn: to: anObject.
^ Array with: html
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:
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