RootLayoutPanel strange code using MVP

52 views
Skip to first unread message

Baloe

unread,
Nov 16, 2010, 4:57:41 AM11/16/10
to Google Web Toolkit
Hi all,

We are using MVP as much as possible, but it has been a pain so far,
not a lot of documentation. There is one thing that we really couldn't
get right. Please see how much boilerplate blabla this application
needs, and see how ugly the class at the end is. We don't want the
class near the end. And if someone has a tip how to clean up this
code, please! Thanks a lot!

Baloe

public class OurApp implements EntryPoint {

@Override
public void onModuleLoad() {

AppGinjector injector = GWT.create(AppGinjector.class);
Root app = new Root();

EventBus eventBus = injector.getEventBus();
PlaceController placeController = injector.getPlaceController();
ActivityMapper activityMapper = injector.getActivityMapper();

ActivityManager activityManager = new
ActivityManager(activityMapper, eventBus);
activityManager.setDisplay(app);

AppPlaceHistoryMapper historyMapper =
GWT.create(AppPlaceHistoryMapper.class);
PlaceHistoryHandler historyHandler = new
PlaceHistoryHandler(historyMapper);
historyHandler.register(placeController, eventBus,
((AppPlaceController) placeController).getDefault());

historyHandler.handleCurrentHistory();
RootLayoutPanel.get().add(app);

Resources.Instance.css().ensureInjected();
}

private class Root extends LayoutPanel implements AcceptsOneWidget {
@Override
public void setWidget(IsWidget w) {
if (w == null) {
clear();
} else {
add(w);
}
}

}

}


PhilBeaudoin

unread,
Nov 16, 2010, 2:18:41 PM11/16/10
to Google Web Toolkit
Why make the Root a inner class? I think it should be either a static
nested class or a top-level class.

Also, you can remove a lot of your boilerplate and ugly news there
using GIN and binding asEagerSingleton. In this way you could bind:
- Root
- PlaceController
- ActivityMapper
- MyActivityManager:
Inherit ActivityManager with a @Inject constructor receiving
ActivityMapper, EventBus and Root. Then call setDisplay(root)
- AppPlaceHistoryMapper
- MyPlaceHistoryHandler
Inherit PlaceHistoryHandler with a @Inject constructor receiving
all you need, then call regiser(...) handleCurrentHistory in your
constructor.

Also, instead of Root extending LayoutPanel, you can have it simply
implement AcceptsOneWidget, then in setWidget you call directly
RootLayoutMapnel.get().add(...)

Cheers,

Philippe

Baloe

unread,
Nov 17, 2010, 3:23:43 AM11/17/10
to Google Web Toolkit
Thanks for the tips!! I'll look into the EagerSingleton.

However, regarding the class Root: I don't really want to change it, I
want to remove it completely. It's not necessary for anything at all,
it's just because we need to start the code. This program goes to our
default Place (see getDefaultPlace() call in the code) , the class
Root is 100% unncessary fill-in code, and extremely ugly as well. How
can I get rid of it?

Thanks!,
Baloe

Thomas Broyer

unread,
Nov 17, 2010, 9:14:16 AM11/17/10
to Google Web Toolkit


On 17 nov, 09:23, Baloe <nielsba...@gmail.com> wrote:
> Thanks for the tips!! I'll look into the EagerSingleton.
>
> However, regarding the class Root: I don't really want to change it, I
> want to remove it completely. It's not necessary for anything at all,
> it's just because we need to start the code. This program goes to our
> default Place (see getDefaultPlace() call in the code) , the class
> Root is 100% unncessary fill-in code, and extremely ugly as well. How
> can I get rid of it?

Currently, you can't, there's no "SimpleLayoutPlanel" (and I can't
find an open issue, so feel free to file one)

BTW, shouldn't you always clear() your Root panel? (ActivityManager
always calls setWidget(null) in between activities, but just in
case...)

david

unread,
Nov 18, 2010, 10:42:39 AM11/18/10
to Google Web Toolkit
"ActivityManager always calls setWidget(null) in between activities,
but just in
case...)"

Its great that 2.1provides this intercept capability however I'm now
unclear as how to present a glass panel in the new activity if the
dom is already cleared before I get there. Am I missing something
about this new pattern?
Thanks.
David

Thomas Broyer

unread,
Nov 18, 2010, 12:42:00 PM11/18/10
to Google Web Toolkit


On 18 nov, 16:42, david <david.l...@restonrobotics.org> wrote:
> "ActivityManager always calls setWidget(null) in between activities,
> but just in
> case...)"
>
> Its great that 2.1provides this intercept capability however I'm now
> unclear as  how to present a glass panel in the new activity if the
> dom is already cleared before I get there.   Am I missing something
> about this new pattern?

If I understand you correctly, you'd like to have a glasspanel above
the "previous activity" while the "new one" starts? (until it calls
AcceptsOneWidget#setWidget to "reveal" itself) ?
IMO you should do this on your AcceptsOneWidget itself, not from
within your activities:
final SimplePanel realDisplay = new SimplePanel();
myActivitymanager.setDisplay(new AcceptsOneWidget {
public void setWidget(IsWidget w) {
if (w == null) {
// show a glass panel
} else {
// hide the glass panel, then:
realDisplay.setWidget(x);
}
}
});

david

unread,
Nov 18, 2010, 4:40:11 PM11/18/10
to Google Web Toolkit


On Nov 18, 12:42 pm, Thomas Broyer <t.bro...@gmail.com> wrote:
> If I understand you correctly, you'd like to have a glasspanel above
> the "previous activity" while the "new one" starts? (until it calls
> AcceptsOneWidget#setWidget to "reveal" itself) ?
> IMO you should do this on your AcceptsOneWidget itself, not from
> within your activities:
> final SimplePanel realDisplay = new SimplePanel();
> myActivitymanager.setDisplay(new AcceptsOneWidget {
>     public void setWidget(IsWidget w) {
>         if (w == null) {
>            // show a glass panel
>         } else {
>            // hide the glass panel, then:
>            realDisplay.setWidget(x);
>         }
>     }
>
> });

This looks like a good example for a basic dialog not a separate
activity that needs to be render its view in a glasspanel. So let me
try an give a better example.

There are actually two scenarios which I believe the invocation of
showWidgetr(null) in myActivityManager.onPlaceChange(.. ) trips me
up.

Scenario 1) Consider an app with a dozen or more independent
Activities. Let's say one of these independent activities will
manifest in a popup ( layer.. glasspanel... ). This is not a simple
dialog but an independent activity and it may appear above any of the
other activity places in the app. Using the pattern described in MVP
part I or part II this was fairly straightforward because the widget
representing the container was not touched until the Presenter
responsible for rendering itself as a glass panel was ready to
initialize its view. However with the latest mcv 2.1 framework ,
the container is cleared as a result of the request to go to the new
place . See show showWidgetr(null) in
myActivityManager.onPlaceChange(.. ) . As a result, the glasspanel
renders over a blank page.

Scenario 2) Consider View1 in Activity1 with a goToActivity2
button. Activity2 makes a fairly long , albeit async, rpc call so
a progress indicator is required. In addition , the View2 served by
Activity2 has nothing interesting on it except for the data coming
back from the async rpc call. Therefore it would be better to show
the progress indicator on View1's goToActivity2 button. Using the
pattern described in MVP part I or part II one would simply call the
container.setWigdet(view2) in the onSuccess method of the RPC
call. However with the latest mcv 2.1 framework , the container
is cleared as a result of the request to go to the new place . See
show showWidgetr(null) in myActivityManager.onPlaceChange(.. ) . As a
result, View1 clears immediately and an blank page is shown until
the rpc comes back in Activity2.

David

Thomas Broyer

unread,
Nov 19, 2010, 9:20:59 AM11/19/10
to Google Web Toolkit
If you ActivityManager's Display always displays a glasspanel over the
previous activity when called as setWidget(null), then I guess you
won't have the problem.
You could have a problem however if this ActivityManager's could
receive 'null' values because there's no activity returned by the
associated ActivityMapper; but I'm pretty sure that wouldn't happen in
your case, and you could workaround this by having your ActivityMapper
return a NullActivity instead that calls setWidget(new IsWidget()
{ public Widget asWidget() { return null; }) (because in the code I
gave, you only test w==null, not Widget.asWidgetOrNull(w)==null, so
there's a difference between a null IsWidget and an IsWidget that
returns a null Widget).

> Scenario 2) Consider  View1 in Activity1 with a goToActivity2
> button.   Activity2 makes a fairly long ,  albeit async,  rpc call so
> a progress indicator is required.  In addition , the View2 served by
> Activity2 has nothing interesting on it except for  the data coming
> back from the async rpc call.    Therefore it would be better to show
> the progress indicator on View1's goToActivity2 button.     Using the
> pattern described in MVP part I or part II  one would simply call the
> container.setWigdet(view2)  in the onSuccess method of the RPC
> call.      However with the latest mcv 2.1 framework , the container
> is cleared as a result of the request to go to the new place .  See
> show showWidgetr(null) in myActivityManager.onPlaceChange(.. ) .  As a
> result,  View1 clears immediately and an blank page is shown  until
> the rpc comes back in Activity2.

Again, using the code I gave (minus the glass panel, but still special-
casing 'null'), you wouldn't have the problem, and it's the
responsibility of Activity1/View1 to display the indicator in the
button.

david

unread,
Nov 19, 2010, 9:53:12 AM11/19/10
to Google Web Toolkit
Thanks Thomas. This is clear now.
> > pattern described inMVPpart I or part II  one would simply call the
Reply all
Reply to author
Forward
0 new messages