I have totally restructured my app to follow the "page setup by event" type idea that you've suggested in your email. I have been through all four samples in the samples repo but can't answer my own question.
I have set up based on the "nested sample" but now I have a HeaderPresenter like you have in your email, present on all pages, Home, AboutUs, ContactUs. So essentially it's a singleton and will never be removed/replaced. Ok, now I see how you have this idea in your "leaf" presenters: @Override protected void revealInParent() { RevealContentEvent.fire(eventBus, MainPresenter.TYPE_SetMainContent, this); } ... but now, what about the Header? I can't get it to be injected or revealed. I'm not sure what the correct way is (maintaining loose coupling). Currently I have: @Override protected void revealInParent() { RevealContentEvent.fire(eventBus, MainPresenter.TYPE_SetHeaderContent, this); } ... in my HeaderPresenter, and then in my MainPagePresenter I have: @ContentSlot public static final Type<RevealContentHandler<?>> TYPE_SetMainContent = new Type<RevealContentHandler<?>>(); @ContentSlot public static final Type<RevealContentHandler<?>> TYPE_SetHeaderContent = new Type<RevealContentHandler<?>>(); ... and then in my MainPageView: @Override public void setContent(Object slot, Widget content) { if (slot == MainPresenter.TYPE_SetMainContent) { setMainContent(content); } else if (slot == MainPresenter.TYPE_SetHeaderContent) { setHeaderContent(content); } else { super.setContent(slot, content); } } private void setHeaderContent(Widget content) { mainHeaderPanel.clear(); if (content != null) mainHeaderPanel.add(content); } private void setMainContent(Widget content) { mainContentPanel.clear(); if (content != null) mainContentPanel.add(content); } On Jun 28, 7:09 pm, Paul Schwarz <paulsschw...@gmail.com> wrote: > Thanks so much for this answer. I have printed it and pinned it up > right beside my screen so will be referring to it often until these > concepts become solid in my mind. I think the largest mind gap here > for me is the concept that a presenter's view is used to fill the > whole screen, and then it has children presenter+view but the parent > doesn't explicitly create or know about them!? I'm getting my head > around these concepts slowly. Thanks for the info. > > Just a question for now though. An example really. Say you have an app > with: > - main screen > - settings screen > > It also has a login panel that is essentially a singleton and popups > up from time to time when your session expires, no presenter really > owns it, it just lives in a void until your session expires. > > Now, your main screen should be accessible at /#main and your settings > at /#settings. > > And lastly, your main page a header that is constantly present at the > top of the page, but then in the main area it is like the "Expenses" > example. i.e. it is a table of rows of data, but if you click on one > of the rows it slides across to reveal more data for that row you > clicked. So the main table would be available only at /#main, but > then /#main;item=20 (or should it be /#item;id=20?) would slide across > to reveal the details page for item 20. Then hitting /#main would > slide you back to the main table. > > You can see from this example that there are a variety of Places, page > states and widgets usages. Would you be so kind as to explain where > you would apply Presenters, PresenterWidgets, etc and how you should > handle the history tokens in order to give this app coherent "state" > based on history, but optimal usage of GWTP in terms of correct MVP > patterns (which then assist greatly with JUnit testing!). > > On Jun 27, 7:48 am, PhilBeaudoin <philippe.beaud...@gmail.com> wrote: > > > > > I answer to this earlier, but it somehow got gobbled by Google Groups. > > If you see it around, let me know. ;) > > > Re: Complex widgets and PresenterWidgets > > > You're exactly right. PresenterWidgets are GWTP's way of doing a > > complex widget with a nice testable class. Your PresenterWidget has > > all the widget's logic and gets injected with the EventBus (and the > > dispatcher if needed, or other services). The view is the complex > > widget itself. > > > Re: Presenters vs PresenterWidget > > > Presenters are singletons. They are totally decoupled from one another > > and communicate only via the Event bus. They can be organized > > hierarchically, but the hierarchical structure is very loose: parent's > > don't know their children in advance, and child don't know their > > parent. The hierarchy gets sets up entirely via the EventBus. The > > lowest-level Presenters of this hierarchy (so-called leaf Presenters) > > need to be attached to a Place. They are (lazily) instanciated > > whenever their history token is invoked, and at that point they set-up > > the hierarchy. > > > PresenterWidget, on the other hand, are not singletons. Also, they are > > meant to be injected in their parent Presenter (a bit like you would > > expect complex widgets to contain one another). They are never > > attached to a place: they get setup when their containing presenter is > > set-up. Their parent presenter can communicate with them through > > method invocation if desired, it does not have to use the event bus. > > Really, PresenterWidget can be thought of as "widget with a testable > > layer". > > > A typical complex page in a GWTP app might look something like: > > > PresenterA (splits the page in a header and a main area ) > > | > > +-- HeaderPresenter > > | > > +-- MainContentPresenter > > | > > +--> ClientListPresenterWidget > > | > > +--> CliendDetailPopupPresenterWidget > > > Where: > > "--" denotes an indirect relationship (via the event bus) > > "-->" denotes an owned relationship (typically injected with GIN) > > > There are some examples of the sort on the gwt-platform website, you > > may want to check them out. > > > Cheers, > > > Philippe > > > On Jun 26, 4:08 am, Paul Schwarz <paulsschw...@gmail.com> wrote: > > > > Ok, I didn't implement it this way, but would prefer to. > > > > At the moment I have 3 mother-sized presenters + views. These have > > > EventBus injected into them by gwt-platform. Then the widgets that are > > > "owned" by this view are then constructed manually. I think I can > > > still test them atomically but I'm not sure... the concepts are still > > > a little hazy, learning UiBinder, Mocking and GWTP at the same time > > > causes some head spin. > > > > My question now is when is it appropriate to make a new Presenter? and > > > how does a PresenterWidget compare? I'm confused because in GWTP a > > > presenter has a Place, so it seems like Presenters are "virtual" pages > > > in an ajax app. But now you're saying to make Presenters for all my > > > widgets individually... or is this where PresenterWidget comes in? > > > > At the moment things are scruffy because my presenter gets an EventBus > > > injected, but then has to bubble it up through @UiFactory constructors > > > into the owned Widgets. > > > > On Jun 24, 5:35 pm, PhilBeaudoin <philippe.beaud...@gmail.com> wrote: > > > > > In gwt-platform (http://code.google.com/p/gwt-platform/) we use gin to > > > > inject the EventBus to whoever needs it. The framework is designed > > > > such that only the presenters communicate on it. > > > > > In your example, the gwt-platform way would be to create a > > > > PresenterWidget for WidgetA and another for WidgetB. This way they act > > > > like widgets, but have a nice testable Presenter layer that can be > > > > used to decouple interactions via the EventBus. If your custom > > > > presenter for WidgetA has too many of these "addClickHandler" methods, > > > > you can break things down further, getting an entire hierarchy of > > > > PresenterWidget. > > > > > Hope it helps, > > > > > Philippe > > > > > On Jun 23, 5:13 pm, Paul Schwarz <paulsschw...@gmail.com> wrote: > > > > > > I looked into that, and (unless I'm wrong), I think that > > > > > @UiField(provided=true) will cause the UiBinder to look in the .ui.xml > > > > > file for argument to satisfy Foo. In my case I am trying to "inject" > > > > > an EventBus into the widget, not a visual element. > > > > > > On Jun 24, 2:18 am, Filipe Sousa <nat...@gmail.com> wrote:> I believe > > > > > you can use @UiField(provided=true): > > > > > > > @UiField(provided=true) Foo foo > > > > > > > @Inject > > > > > > UserDashboard(Foo foo) { > > > > > > this.foo = foo > > > > > > > } > > > > > > > On Jun 23, 10:03 pm, Paul Schwarz <paulsschw...@gmail.com> wrote: > > > > > > > > To answer my own question: > > > > > > > > 1. Gin can be used to inject the EventBus into the View as well > > > > > > > as the > > > > > > > Presenter, so now our View has a reference to the EventBus > > > > > > > > 2. In order to give the EventBus to the Widgets "owned" by the > > > > > > > View > > > > > > > those Widgets will require a constructor argument which will be > > > > > > > the > > > > > > > EventBus instance. UiBinder will fail if it doesn't find a default > > > > > > > constructor, except that they have provided some nice work > > > > > > > arounds. > > > > > > > The appropriate workaround in this case is to provide a widget > > > > > > > factory. Notice the use of @UiFactory in the example below: > > > > > > > > public class UserDashboard extends Composite { > > > > > > > interface MyUiBinder extends UiBinder<Widget, UserDashboard>; > > > > > > > private static final MyUiBinder uiBinder = > > > > > > > GWT.create(MyUiBinder.class); > > > > > > > > private final String[] teamNames; > > > > > > > > public UserDashboard(String... teamNames) { > > > > > > > this.teamNames = teamNames; > > > > > > > initWidget(uiBinder.createAndBindUi(this)); > > > > > > > } > > > > > > > > /** Used by MyUiBinder to instantiate CricketScores */ > > > > > > > @UiFactory CricketScores makeCricketScores() { // method name is > > > > > > > insignificant > > > > > > > return new CricketScores(teamNames); > > > > > > > } > > > > > > > > } > > > > > > > > On Jun 23, 11:04 pm, Paul Schwarz <paulsschw...@gmail.com> wrote: > > > > > > > > > Working with the MVP pattern, or more like the VP pattern at > > > > > > > > this > > > > > > > > point, I have: > > > > > > > > MainPagePresenter > > > > > > > > MainPageView > > > > > > > > WidgetA > > > > > > > > WidgetB > > > > > > > > > ... so imagine that WidgetA and WidgetB will be attached to > > > > > > > > MainPageView. > > > > > > > > > Using Gin I have an EventBus injected into the > > > > > > > > MainPagePresenter. I > > > > > > > > can then add click handlers that place an event on the EventBus > > > > > > > > from > > > > > > > > within my MainPagePresenter. This might look like: > > > > > > > > > getMainPageView().getSendButton().addClickHandler(new > > > > > > > > ClickHandler(){ > > > > > > > > public void onClick(ClickEvent event) { > > > > > > > > eventBus.fireEvent(new SendEvent()); > > > > > > > > } > > > > > > > > > } > > > > > > > > > But now let's say that WidgetA and WidgetB actually have quite > > > > > > > > a few > > > > > > > > user interactions, you'll end up with a lot of methods that > > > > > > > > look like > > > > > > > > the one above sitting in your Presenter class. > > > > > > > > 1. Is this correct? > > > > > > > > Or > > > > > > > > 2. should the Presenter hand the reference to the EventBus > > > > > > > > through to > > > > > > > > its View, who may even hand it through to the Widgets so that > > > > > > > > they can > > > > > > > > talk directly to the EventBus? > > > > > > > > > If the second option is the better option from an architecture/ > > > > > > > > separation of concerns point of view, then what is the best way > > > > > > > > to > > > > > > > > hand the reference over to the View in such a way that keeps the > > > > > > > > coupling between Presenter and View as loose as possible? > > > > > > > > > Note, currently my Presenter defines a View interface which my > > > > > > > > View > > > > > > > > implements, so the coupling is loose but... > > read more » -- You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group. To post to this group, send email to google-web-tool...@googlegroups.com. To unsubscribe from this group, send email to google-web-toolkit+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.