Menu component - communicating with root component

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

Menu component - communicating with root component

Edward Stow
Hi,

Sorry if these questions seem very simple -- but I wanted to check
that my overall architecture was ok.

I have an application that has a RootComponent and several sub
components that can be selected by actions in the MenuComponent.

RootComponent
    MenuComponent
    Body1Component
    Body2Component
    .. etc ...

The menu component in the anchor callbacks sends #triggerEvent: to
notify the Root of the menu selection.
The Root then renders the selected Body component.

Is this a reasonable Seaside-way of structuring the application.    I
know that Pier has the sidebar menus ... but Pier is difficult for me
to follow due to the highly abstracted nature of the application.


Thanks

--

Edward Stow
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Menu component - communicating with root component

Philippe Marschall
http://onsmalltalk.com/programming/smalltalk/maintaining-loose-coupling-in-seaside-components/

2008/4/19, Edward Stow <[hidden email]>:

> Hi,
>
>  Sorry if these questions seem very simple -- but I wanted to check
>  that my overall architecture was ok.
>
>  I have an application that has a RootComponent and several sub
>  components that can be selected by actions in the MenuComponent.
>
>  RootComponent
>     MenuComponent
>     Body1Component
>     Body2Component
>     .. etc ...
>
>  The menu component in the anchor callbacks sends #triggerEvent: to
>  notify the Root of the menu selection.
>  The Root then renders the selected Body component.
>
>  Is this a reasonable Seaside-way of structuring the application.    I
>  know that Pier has the sidebar menus ... but Pier is difficult for me
>  to follow due to the highly abstracted nature of the application.
>
>
>  Thanks
>
>
>  --
>
>  Edward Stow
>  _______________________________________________
>  seaside mailing list
>  [hidden email]
>  http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Menu component - communicating with root component

Edward Stow
On Sat, Apr 19, 2008 at 6:41 PM, Philippe Marschall
<[hidden email]> wrote:
> http://onsmalltalk.com/programming/smalltalk/maintaining-loose-coupling-in-seaside-components/
>
Thanks -- that confirms my approach as being ok.  Perhaps its a good
time to brush up on announcements.

--
Edward Stow
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Menu component - communicating with root component

keith1y
Edward Stow wrote:
> On Sat, Apr 19, 2008 at 6:41 PM, Philippe Marschall
> <[hidden email]> wrote:
>  
>> http://onsmalltalk.com/programming/smalltalk/maintaining-loose-coupling-in-seaside-components/
>>
>>    
> Thanks -- that confirms my approach as being ok.  Perhaps its a good
> time to brush up on announcements.
>  
I keep coming up against this one, AND I have to figure it out by next
Thursday. Last time I said this I hacked a workaround instead.

Essentially seaside is architected so that for components, children do
not know their parents. The rationale for this is that it enables
children to be more reusable if there are no explicit interfaces to
their containers.

However I have always found it essential to have children be able to
"look around" and know their position in the world. After a year of
using seaside and pier seriously, I have constantly had to find
work-arounds, for what I know should be really simple.

My workarounds are not particularly elegant, and the code has smelt bad
from the beginning. They have involved using some form of global as a
holder for information that a child and a parent want to share.

Example 1)

In my pier-shop the WACurrentSession or the PRCurrentContext ends up
holding the "current product being viewed", and all the components look
to the current context as a kind of "global" data structure as to what
to display. This has significant limitations, since you cannot have more
than one current product at a time, and it violates the whole
component-encapsulation model.

I implemented an Announcements helper in Seaside28Jetsam, which simply
makes an instance of Announcer available via "WACurrentSession
announcer". This appears to me to be a more complex and flexible form of
the "put the communication in a global place, so parents and children
can communicate"

What I want to do is to click on a product and have that call: the
product display, which is a pier page, a template which has been
assembled out of content and components, giving the pier page the
current product, or the current users cart-model as a property, and have
the child components be able to query the parents as to what product to
display.

This would allow an administrator to have a side by side view of all the
current carts of the currently logged in users. The cart displays would
be generic container components, pier pages, with specialised children
components, and the users' carts-models would be a property of outer
page of each individual cart display. The inner cart display components
would need to be able to query their containers as to what is in their
cart that is to be displayed. This then allows components to be more
granular, e.g. "Total cost" component, which could appear anywhere in
the template. In contrast to the monolthic, Cart display, with tax
calulations, and totals etc... component.

Example 2) (a simpler one)

In migrating a complex Magritte form to use Magritte-scriptaculous, I
successfully wire up the models so that a change in one select drop
down, changes items in other fields in the same form. The child field
which has changed needs to trigger its form, so that all of changes in
all of the the relevant fields are received by the model, and then
scriptaculous update rendering, of not just its own component, but one
of its parents (at some level). Since it is the components onChanged:
event and callback: which is triggered when the user has changed the
select box, it is the component which needs to trigger the form and the
update.  But as per usual, the inner component has no means for
dynamically discovering "what is the form id that I am in", or asking
the relevant parent to update.

Solution Background
----------------------------

I have modelled complex physical assemblies before. The case that comes
to mind was that of physical telecomunications equipment, where a card
gets put in a slot or pulled out of a slot. Some cards specifically
handle the alarms generated by all of the cards in their part of the
rack, and they also translate the physical events into alarms which are
sent up to the management interface.

The important concept I adopted in modelling physical heirarchies, was
to allow the actual structure to influence behaviour. For example a lone
card generating an alarm, would have no effect on the rest of the system
if it is not physically plugged in.

To achieve this, I always had the child know its parent. But, in keeping
with the loose-coupling principle I did not have any hard wired interface.

Instead I had an announcements like approach, called a SemanticMessage.
A SemanticMessage when triggered would walk up the hierarchy, calling
#smParent on each component and if it found either...

a) someone able to respond to the message, the message would be sent and
the response value returned to the triggerer.
b) someone who had registered an interest in the message at some point
in the hierarchy.

The Alarm card is sent a #cardInserted:intoSlot: SemanticMessage by the
rack, it responds to this by registering an interest in any alarm events
which arrive at the rack, from any card. Alarm events migrate up the
heirarchy from the source card to the rack where the dependant is informed.

--

I present this in an effort to dispel what I believe is a myth, that
children should not have any explicit knowledge their parents. I am sure
enough to say that it is essential that this knowledge be there, the
child should have a direct instVar (or property) to its parent. What is
more important is how you use that instVar. Direct usage of the parents
interface creates the inflexibility that we are trying to avoid.

So out use of the #parent instVar should be event or query based, rather
than being a direct use of the parents interface. e.g. A child can
trigger "I have Changed", and it is up to the parent to respond
appropriately. Or a child can seek information #lookupContainingFormId,
as long as it can handle the case that a heirarchy of parent which
doesnt contain a form may not respond appropriately.

I am really looking forward to solving this one

best regards

Keith



_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

RE: Menu component - communicating with root component

Sebastian Sastre-2
> So out use of the #parent instVar should be event or query
> based, rather
> than being a direct use of the parents interface. e.g. A child can
> trigger "I have Changed", and it is up to the parent to respond
> appropriately. Or a child can seek information
> #lookupContainingFormId,
> as long as it can handle the case that a heirarchy of parent which
> doesnt contain a form may not respond appropriately.
>
> I am really looking forward to solving this one
>
> best regards
>
> Keith
>

Hi Keith,

        my components have the #parent instVar in their abstract superclass so
they have a proper structure. The only case they are using it is when they have
to anwer if they are children of some other component. They need to look there
because the question is deep (answering true if the component is included as
child of any in its whole parent chain).

        Surprisingly now I've found I've made that #isParentOf: method to
satisfy something I have now deprecated months ago in favor of something simpler
and cleaner. So I really can depracate the isParentOf: also letting me with no
formal need of having the instVar(?). I'll let it there by now :)

        For the announcements part I do use one announcer per component instead
of trying to centralize announcements. Kind of same idea of events and objects.
Every event has its own place to register events. Requires an inst var but it's
simpler and cleaner when components are CG'd.

        I disagree on making exceptions about children querying stuff to
parents. That could easily increase the scoring of the confusivity of concerns
for developers when they have to think of children and parents so encouraging
any trend to mix responsabilities and generate problems.

        The announcements (also events) works in an asyncrhonous style and that
could be a major benefit (depending on your requeriments).

        cheers,

Sebastian

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

RE: Menu component - communicating with root component

Ramon Leon-5
In reply to this post by keith1y
> In migrating a complex Magritte form to use
> Magritte-scriptaculous, I successfully wire up the models so
> that a change in one select drop down, changes items in other
> fields in the same form. The child field which has changed
> needs to trigger its form, so that all of changes in all of
> the the relevant fields are received by the model, and then
> scriptaculous update rendering, of not just its own
> component, but one of its parents (at some level). Since it
> is the components onChanged:
> event and callback: which is triggered when the user has
> changed the select box, it is the component which needs to
> trigger the form and the update.  But as per usual, the inner
> component has no means for dynamically discovering "what is
> the form id that I am in", or asking the relevant parent to update.

Isn't that the whole point of an event based system?  Loosely coupled
systems are easier to compose into complex scenarios like this without
becoming bound to one scenario.  Rather than all the children having
intimate knowledge about how they're hooked together, you make the system
dead simple, keep all the children totally ignorant, have them just fire
events, and use the parent as a mediator to coordinate all the necessary
actions.  

Then all the coupling is in the parent, having references to all its
children, it is in a perfect position to know in this particular
scenario/context how the children need to interact, so it subscribes to the
appropriate events and executes the necessary actions when those events are
fired.  The child need only trigger an event that something happened,
nothing more.  I just don't see why you feel the child needs to do more than
that.

Ramon Leon
http://onsmalltalk.com

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Menu component - communicating with root component

keith1y
Ramon Leon wrote:

>> In migrating a complex Magritte form to use
>> Magritte-scriptaculous, I successfully wire up the models so
>> that a change in one select drop down, changes items in other
>> fields in the same form. The child field which has changed
>> needs to trigger its form, so that all of changes in all of
>> the the relevant fields are received by the model, and then
>> scriptaculous update rendering, of not just its own
>> component, but one of its parents (at some level). Since it
>> is the components onChanged:
>> event and callback: which is triggered when the user has
>> changed the select box, it is the component which needs to
>> trigger the form and the update.  But as per usual, the inner
>> component has no means for dynamically discovering "what is
>> the form id that I am in", or asking the relevant parent to update.
>>    
>
> Isn't that the whole point of an event based system?  Loosely coupled
> systems are easier to compose into complex scenarios like this without
> becoming bound to one scenario.  Rather than all the children having
> intimate knowledge about how they're hooked together, you make the system
> dead simple, keep all the children totally ignorant, have them just fire
> events, and use the parent as a mediator to coordinate all the necessary
> actions.  
>
> Then all the coupling is in the parent, having references to all its
> children, it is in a perfect position to know in this particular
> scenario/context how the children need to interact, so it subscribes to the
> appropriate events and executes the necessary actions when those events are
> fired.  The child need only trigger an event that something happened,
> nothing more.  I just don't see why you feel the child needs to do more than
> that.
>
> Ramon Leon
> http://onsmalltalk.com
>  
How does the child tell the parent of the event if it doesnt know the
parent.

Are you suggesting that every child has an announcer, and that the
parent registers an interest in events happening to the child, when it
adds the child. The problem I see with that is that it expects all of
the parents to do the wiring to all of the children, thats a lot of wiring.
And parents are a multitude of generic components such as rendered
PRPages with an embedded component at some arbitary depth.

Keith

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Menu component - communicating with root component

squeakman
In reply to this post by Philippe Marschall
Philippe Marschall wrote:
> http://onsmalltalk.com/programming/smalltalk/maintaining-loose-coupling-in-seaside-components/
>

With respect to the example in the link above, it is fine to have one
child that announces RemoveChild. I cannot figure out how a more complex
example would work.

Assume a situation where you have a parent (aMenu) that had multiple
children (like MenuItems in a menu) and each child can announce
ItemClicked.  Wouldn't the parent code end up looking a huge case
statement when trying to figure out which child was clicked?

Each child is of he same type (same class) but I want to do something
different for each instance, i.e., if menuItem1 is clicked I want to do
something unique to that instance.  How would you do this and avoid a
monster case statement?

Hope my question is not too badly phrased.

Thanks for any help you can offer on this,
Frank

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Menu component - communicating with root component

squeakman
In reply to this post by Philippe Marschall
Philippe Marschall wrote:
> http://onsmalltalk.com/programming/smalltalk/maintaining-loose-coupling-in-seaside-components/
>

One more point about the "children knowing their parent" question.

I always thought that objects should be anthropomorphic; in the real
world it is normal for children to know who their parents are so why
should not a child component know its parent?

Maybe this is too simplistic a view but why not?

Thanks,
Frank

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Re: Menu component - communicating with root component

Steve Aldred-3
In reply to this post by squeakman
Squeaker wrote:
> ...
> Assume a situation where you have a parent (aMenu) that had multiple
> children (like MenuItems in a menu) and each child can announce
> ItemClicked.  Wouldn't the parent code end up looking a huge case
> statement when trying to figure out which child was clicked?
> ...

That's the point of announcements, they are an instance of a class and
carry whatever data you desire. If you need the instance of the menu
item in the announcement then put it there.

I'd be inclined to then put the behaviour you want on the menu items
themselves and the receiver of the announcement just asks the
announcement item to process the necessary data. The menu item doesn't
know about the data per se, it just holds the behavior to apply to the
data when the behavior method gets invoked with the data as an argument.

HTH
Steve
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

RE: Re: Menu component - communicating with root component

Ramon Leon-5
> That's the point of announcements, they are an instance of a
> class and carry whatever data you desire. If you need the
> instance of the menu item in the announcement then put it there.
>
> I'd be inclined to then put the behavior you want on the
> menu items themselves and the receiver of the announcement
> just asks the announcement item to process the necessary
> data. The menu item doesn't know about the data per se, it
> just holds the behavior to apply to the data when the
> behavior method gets invoked with the data as an argument.
>
> HTH
> Steve

Exactly the point, rather than just fire some generic event or symbol, you
reify the message, the announcement as a full blown object able to carry
both information and behavior if necessary with them.  You could announce a
block with a callback so the parent doesn't even know what the child is
doing.  

Say I keep a parent component broken up into children such as header,
footer, menu, and body and I want the currently loaded X to be able to be
reloaded by an even triggered by Y.  The menu to change the body, the body
to change the navigation, the navigation to change the body and header at
the same time, i.e. multiple other parties interested in the event, etc.  I
could just design an event that when fired, gives me the component I want to
talk to, as if it were a phone call where the interested party would pick
up...

self announce: (ReloadBody with: [:body | body call: (SomeOtherReport model:
self model) ]).

And any component anywhere in the system could fire off that same line and
have the correct "body" component answer and react appropriately without
coupling them together in some hard coded parent/child relationship.

Ramon Leon
http://onsmalltalk.com

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Re: Menu component - communicating with root component

Stefan Schmiedl
In reply to this post by squeakman
On Sat, 19 Apr 2008 23:05:14 -0400
Squeaker <[hidden email]> wrote:

> I always thought that objects should be anthropomorphic; in the real
> world it is normal for children to know who their parents are so why
> should not a child component know its parent?

Maybe it's the wrong metaphor.

Does a CPU know that it's working inside a computer?

Look at me, I'm a CPU knowing that my parent is a PC running Windows XP.
Now bugger off with that linux install disk :-P

s.
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Re: Menu component - communicating with root component

Philippe Marschall
In reply to this post by squeakman
2008/4/20, Squeaker <[hidden email]>:

> Philippe Marschall wrote:
>
> >
> http://onsmalltalk.com/programming/smalltalk/maintaining-loose-coupling-in-seaside-components/
> >
> >
>
>  With respect to the example in the link above, it is fine to have one child
> that announces RemoveChild. I cannot figure out how a more complex example
> would work.
>
>  Assume a situation where you have a parent (aMenu) that had multiple
> children (like MenuItems in a menu) and each child can announce ItemClicked.
>  Wouldn't the parent code end up looking a huge case statement when trying
> to figure out which child was clicked?

No, the announcement would capture all the necessary information, in
this case the child.

Cheers
Philippe

>  Each child is of he same type (same class) but I want to do something
> different for each instance, i.e., if menuItem1 is clicked I want to do
> something unique to that instance.  How would you do this and avoid a
> monster case statement?
>
>  Hope my question is not too badly phrased.
>
>  Thanks for any help you can offer on this,
>  Frank
>
>
>  _______________________________________________
>  seaside mailing list
>  [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Menu component - communicating with root component

Philippe Marschall
In reply to this post by keith1y
2008/4/20, Keith Hodges <[hidden email]>:

> Ramon Leon wrote:
>
> >
> > > In migrating a complex Magritte form to use Magritte-scriptaculous, I
> successfully wire up the models so that a change in one select drop down,
> changes items in other fields in the same form. The child field which has
> changed needs to trigger its form, so that all of changes in all of the the
> relevant fields are received by the model, and then scriptaculous update
> rendering, of not just its own component, but one of its parents (at some
> level). Since it is the components onChanged: event and callback: which is
> triggered when the user has changed the select box, it is the component
> which needs to trigger the form and the update.  But as per usual, the inner
> component has no means for dynamically discovering "what is the form id that
> I am in", or asking the relevant parent to update.
> > >
> > >
> >
> > Isn't that the whole point of an event based system?  Loosely coupled
> > systems are easier to compose into complex scenarios like this without
> > becoming bound to one scenario.  Rather than all the children having
> > intimate knowledge about how they're hooked together, you make the system
> > dead simple, keep all the children totally ignorant, have them just fire
> > events, and use the parent as a mediator to coordinate all the necessary
> > actions.
> > Then all the coupling is in the parent, having references to all its
> > children, it is in a perfect position to know in this particular
> > scenario/context how the children need to interact, so it subscribes to
> the
> > appropriate events and executes the necessary actions when those events
> are
> > fired.  The child need only trigger an event that something happened,
> > nothing more.  I just don't see why you feel the child needs to do more
> than
> > that.
> >
> > Ramon Leon
> > http://onsmalltalk.com
> >
> >
>  How does the child tell the parent of the event if it doesnt know the
> parent.

It doesn't and that's the whole a point about it. All it does it
announces an event and the parent may listen to this event.

>  Are you suggesting that every child has an announcer,

No, you'll generally have more broadly scoped announcers.

Cheers
Philippe

> and that the parent
> registers an interest in events happening to the child, when it adds the
> child. The problem I see with that is that it expects all of the parents to
> do the wiring to all of the children, thats a lot of wiring.
>  And parents are a multitude of generic components such as rendered PRPages
> with an embedded component at some arbitary depth.
>
>  Keith
>
>
>  _______________________________________________
>  seaside mailing list
>  [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Re: Menu component - communicating with root component

keith1y
In reply to this post by Ramon Leon-5
Dear Ramon,

I still dont get it.

> Exactly the point, rather than just fire some generic event or symbol, you
> reify the message, the announcement as a full blown object able to carry
> both information and behavior if necessary with them.  You could announce a
> block with a callback so the parent doesn't even know what the child is
> doing.  
>
> Say I keep a parent component broken up into children such as header,
>  
> footer, menu, and body and I want the currently loaded X to be able to be
>  
Ok so this is a component:

ParentA-(AnnouncerA)
    |
(headerA bodyA footerA)
   |
(headerMenuA)
   |
(menuItemA1 menuItemA2)

And this is a second instance of this component in the same page

ParentB-(AnnouncerB)
    |
(headerB bodyB footerB)
   |
(headerMenuB)
   |
(menuItemB1 menuItemB2)
> reloaded by an even triggered by Y.
So for example we want, bodyA to be updated by an event on menuItemA1.
and
we want, bodyB to be updated by an event on menuItemB1.

>  The menu to change the body, the body
> to change the navigation, the navigation to change the body and header at
> the same time, i.e. multiple other parties interested in the event, etc.  I
> could just design an event that when fired, gives me the component I want to
> talk to, as if it were a phone call where the interested party would pick
> up..
>  
> self announce: (ReloadBody with: [:body | body call: (SomeOtherReport model:
> self model) ]).
>  
Great, so the plan is that this event ReloadBody, when triggered will
put the correct body into the block.

I assume then that bodyB, when added, said to its annnouncer, if any
ReloadBody events come up I am able to respond. I assume this, because
in my system the parents dont know any details about their chidren, a
pier page is merely a container and can have anything put into it to any
level of depth.

So... where is this announcer, how does bodyB obtain its announcer? If
there is one global announcer, then what routes a ReloadBody to the
Correct BodyA or B.

So menuItemB, performs "self announce: (anAnnouncement)" on an announcer.

ok... where is this announcer? How does it know about it?

Is it a global or is it told about it when it was added to its parent?

ParentA says to each of its children, "your announcer is AnnouncerA."
and likewise
headerB says to each of its children, headerMenuB "your announcer is
AnnouncerB." and likewise
The Menus says to each of their MenuItems, your announcer is AnnouncerB.

But all we are doing is here is replacing, child knows his parent, with
child knows his announcer, or in the case above child knows his
global-announcer.  I think that first is more useful than the last two,
because last two give neither the child nor the announcer any spatial
information at all.

Ok so thats all connected and would work...

but what if there were two menus, and we want the menu to flash when an
item is selected.
For this, each Menu will need its own Announcer, and each menuItem is
given the MenuAnnouncer when it is added to the Menu...

Hang on there, each MenuItem ends up having the announcer of ifs
Parent... why not just have a reference to its parent, and ask its
parent for an announcer.

thanks in advance for any help, I am still really struggling to
understand how announcements are supposed to work in a heirarchical
system of nested components, without any spatial relationship
information at all.

Keith









_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Menu component - communicating with root component

squeakman
Keith Hodges wrote:
> Dear Ramon,
>
> I still dont get it.

Me too. An example would be a great aid in understanding.  Are there any
simple examples that exist?

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

RE: Menu component - communicating with root component

Ramon Leon-5
In reply to this post by keith1y
> >  
> How does the child tell the parent of the event if it doesnt
> know the parent.

It doesn't know who it's telling, it just launches the announcement.


> Are you suggesting that every child has an announcer, and
> that the parent registers an interest in events happening to
> the child, when it adds the child. The problem I see with
> that is that it expects all of the parents to do the wiring
> to all of the children, thats a lot of wiring.
> And parents are a multitude of generic components such as
> rendered PRPages with an embedded component at some arbitary depth.
>
> Keith

Not at all, it's up to you to decide where to put the announcer, but just
think of it as a global communications channel, put one on the session so
that parents don't need to know their children either.

self session announce: MyAnnouncement new.

Then any component, when initialized, can register itself as interested in
certain announcements.  The root component for example might register as
interested in the ReloadBody announcement.  So it doesn't matter who fires
it or from where, it'll catch it and act accordingly.

Ramon Leon
http://onsmalltalk.com

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

RE: Re: Menu component - communicating with root component

Ramon Leon-5
In reply to this post by keith1y
> I assume then that bodyB, when added, said to its annnouncer,
> if any ReloadBody events come up I am able to respond. I
> assume this, because in my system the parents dont know any
> details about their chidren, a pier page is merely a
> container and can have anything put into it to any level of depth.
>
> So... where is this announcer, how does bodyB obtain its
> announcer? If there is one global announcer, then what routes
> a ReloadBody to the Correct BodyA or B.

OK, consider this, in Seaside, all components answer #children, so all
parents have access to their children.  The ChangeBody announcement could be
fired like this...

self session announce: (ChangeBody sender: self with: [:body | body call:
BlaBla new])

Now, both parent components catch the event, check to make sure the #sender
is one of their children or grandchildren with a quick recursive check on
#children, before deciding to process the announcement.  This way you scope
the ChangeBody to the correct parent.

>
> So menuItemB, performs "self announce: (anAnnouncement)" on
> an announcer.
>
> ok... where is this announcer? How does it know about it?

Put it on the session and then every component has access to a single global
announcer.

> But all we are doing is here is replacing, child knows his
> parent, with child knows his announcer, or in the case above
> child knows his global-announcer.  I think that first is more
> useful than the last two, because last two give neither the
> child nor the announcer any spatial information at all.

Yes and no, yes a global announcer, but you're wrong about the spatial
information because all components know their children, you can always
iterate and check this.

> Ok so thats all connected and would work...
>
> but what if there were two menus, and we want the menu to
> flash when an item is selected.
> For this, each Menu will need its own Announcer, and each
> menuItem is given the MenuAnnouncer when it is added to the Menu...

Not necessarily.

> Hang on there, each MenuItem ends up having the announcer of
> ifs Parent... why not just have a reference to its parent,
> and ask its parent for an announcer.
>
> thanks in advance for any help, I am still really struggling
> to understand how announcements are supposed to work in a
> heirarchical system of nested components, without any spatial
> relationship information at all.
>
> Keith

But there is spatial information, you're just not using it because you're
stuck on wanting the hardcoded parent path because it seems easier to you.
It's not easier, it's messy and results in fragile hierarchies of components
that become really hard to reuse when you change the structure.
Announcements allow you to loosely couple them so changing the structure
doesn't break things.  As a solution to message sending, #parent is fragile,
#includesChildRecursively: is not.  Just think of the announcer as a global
message queue where all objects can exchange messages as peers rather than
parents and children.  A parent can easily ignore messages that aren't from
it's family because it can check the sender against it's known family
(#children) whenever it likes.

Ramon Leon
http://onsmalltalk.com

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Re: Menu component - communicating with root component

Holger Kleinsorgen-3
>> So... where is this announcer, how does bodyB obtain its
>> announcer? If there is one global announcer, then what routes
>> a ReloadBody to the Correct BodyA or B.
>
> OK, consider this, in Seaside, all components answer #children, so all
> parents have access to their children.  The ChangeBody announcement could be
> fired like this...

> self session announce: (ChangeBody sender: self with: [:body | body call:
> BlaBla new])
> Now, both parent components catch the event, check to make sure the #sender
> is one of their children or grandchildren with a quick recursive check on
> #children, before deciding to process the announcement.  This way you scope
> the ChangeBody to the correct parent.

Peeking at grandchildren is IMHO even worse than accessing a parent.
It's the same princicple (traversing the component hierarchy), just more
laborious.

>> So menuItemB, performs "self announce: (anAnnouncement)" on
>> an announcer.
>>
>> ok... where is this announcer? How does it know about it?
>
> Put it on the session and then every component has access to a single global
> announcer.

Using the session as global variable dump and central router for
application logic isn't very auspicious, too.

I faced a similiar problem recently, and initially used the
give-components-its-parent-but-only-use-it-for-announcing-approach.
however, it was doomed once I had to announce events between siblings.

Subscribing each and every component with potentially a lot of other
components didn't look very promising, too.

For instance, in VisualWorks, window events are sometimes dispatched in
both directions. First down, then up, with multiple interested parties
in the middle. It's hard to follow, and often fails as soon as the
hierarchy differs from the expected structure.

I finally ended up using an "environment" object, that holds some shared
data (selection etc.) and also acts as an announcer. Parent components
create it and pass it to their children. Children, when creating
grand-children, may decide to either pass the environment object to them
or create a new one.

In the example, there would be two such objects (one for A, one for B).
Let's call them EnvironmentA and EnvironmentB.

ParentA is subscribed to EnvironmentA. And for the menu flashing, MenuA
is subscribed to EnvironmentA, too (however, MenuA doesnt exactly know
that it is the EnvironmentA, for MenuA it's just "an Environment").

page reload goes like this:

   MenuItem>>triggerReload
      self environment announce: (Reload page: ...)

menu flashing

   MenuItem>>flash
      self envronment announce: (Flash ...)

and to make it work:

    Menu>>initialize
      self environment when: Flash do: [ : gordon | self flash: gordon ]

    Parent>>initialize
      self environment when: Reload do: [ : page | self call: page ].

the advantage of this approach is, that it won't break when you leave
the strictly hierarchical approach. And you don't need a central router.
And you don't break encapsulation rules.

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

RE: Re: Menu component - communicating with root component

Boris Popov, DeepCove Labs (SNN)
I'm not convinced that adding a third-party negotiator is easier than,

Menu>>addItem: item
 self items add: item.
 item when: Clicked do: [self select: item].

MenuItem>>renderContentOn: html
 html anchor
  callback: [self announce: Clicked];
  with: self label.

-Boris

-----Original Message-----
From: [hidden email]
[mailto:[hidden email]] On Behalf Of Holger
Kleinsorgen
Sent: Sunday, April 20, 2008 12:10 PM
To: Seaside - general discussion
Subject: Re: [Seaside] Re: Menu component - communicating with root
component

>> So... where is this announcer, how does bodyB obtain its
>> announcer? If there is one global announcer, then what routes
>> a ReloadBody to the Correct BodyA or B.
>
> OK, consider this, in Seaside, all components answer #children, so all
> parents have access to their children.  The ChangeBody announcement
could be
> fired like this...

> self session announce: (ChangeBody sender: self with: [:body | body
call:
> BlaBla new])
> Now, both parent components catch the event, check to make sure the
#sender
> is one of their children or grandchildren with a quick recursive check
on
> #children, before deciding to process the announcement.  This way you
scope
> the ChangeBody to the correct parent.

Peeking at grandchildren is IMHO even worse than accessing a parent.
It's the same princicple (traversing the component hierarchy), just more

laborious.

>> So menuItemB, performs "self announce: (anAnnouncement)" on
>> an announcer.
>>
>> ok... where is this announcer? How does it know about it?
>
> Put it on the session and then every component has access to a single
global
> announcer.

Using the session as global variable dump and central router for
application logic isn't very auspicious, too.

I faced a similiar problem recently, and initially used the
give-components-its-parent-but-only-use-it-for-announcing-approach.
however, it was doomed once I had to announce events between siblings.

Subscribing each and every component with potentially a lot of other
components didn't look very promising, too.

For instance, in VisualWorks, window events are sometimes dispatched in
both directions. First down, then up, with multiple interested parties
in the middle. It's hard to follow, and often fails as soon as the
hierarchy differs from the expected structure.

I finally ended up using an "environment" object, that holds some shared

data (selection etc.) and also acts as an announcer. Parent components
create it and pass it to their children. Children, when creating
grand-children, may decide to either pass the environment object to them

or create a new one.

In the example, there would be two such objects (one for A, one for B).
Let's call them EnvironmentA and EnvironmentB.

ParentA is subscribed to EnvironmentA. And for the menu flashing, MenuA
is subscribed to EnvironmentA, too (however, MenuA doesnt exactly know
that it is the EnvironmentA, for MenuA it's just "an Environment").

page reload goes like this:

   MenuItem>>triggerReload
      self environment announce: (Reload page: ...)

menu flashing

   MenuItem>>flash
      self envronment announce: (Flash ...)

and to make it work:

    Menu>>initialize
      self environment when: Flash do: [ : gordon | self flash: gordon ]

    Parent>>initialize
      self environment when: Reload do: [ : page | self call: page ].

the advantage of this approach is, that it won't break when you leave
the strictly hierarchical approach. And you don't need a central router.

And you don't break encapsulation rules.

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
123