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 based upon this > > > > > > > interface. -- 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.