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 |
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 |
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 |
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 |
> 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 |
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 |
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 > 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 |
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 |
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 |
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 |
> 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 |
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 |
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 |
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 |
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 > 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) ]). > 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 |
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 |
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 |
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 |
>> 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 |
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 |
Free forum by Nabble | Edit this page |