API Reference 0.3.24dart_web_toolkit_activityActivityManager

ActivityManager class

Manages {@link Activity} objects that should be kicked off in response to {@link PlaceChangeEvent} events. Each activity can start itself asynchronously, and provides a widget to be shown when it's ready to run.

class ActivityManager implements PlaceChangeEventHandler, PlaceChangeRequestEventHandler {

 static final Activity NULL_ACTIVITY = new _AbstractActivity();

 final ActivityMapper mapper;

 final EventBus eventBus;

 /*
  * Note that we use the legacy class from com.google.gwt.event.shared, because
  * we can't change the Activity interface.
  */
 ResettableEventBus stopperedEventBus;

 Activity currentActivity = NULL_ACTIVITY;

 AcceptsOneWidget display;

 bool startingNext = false;

 HandlerRegistration handlerRegistration;

 /**
  * Create an ActivityManager. Next call {@link #setDisplay}.
  * 
  * @param mapper finds the {@link Activity} for a given
  *          {@link com.google.gwt.place.shared.Place}
  * @param eventBus source of {@link PlaceChangeEvent} and
  *          {@link PlaceChangeRequestEvent} events.
  */
 ActivityManager(this.mapper, this.eventBus) {
   stopperedEventBus = new ResettableEventBus(eventBus);
 }

 /**
 * Returns an event bus which is in use by the currently running activity.
 * <p>
 * Any handlers attached to the returned event bus will be de-registered when
 * the current activity is stopped.
 *
 * @return the event bus used by the current activity
 */
 EventBus getActiveEventBus() {
   return stopperedEventBus;
 }

 /**
  * Deactivate the current activity, find the next one from our ActivityMapper,
  * and start it.
  * <p>
  * The current activity's widget will be hidden immediately, which can cause
  * flicker if the next activity provides its widget asynchronously. That can
  * be minimized by decent caching. Perenially slow activities might mitigate
  * this by providing a widget immediately, with some kind of "loading"
  * treatment.
  */
 void onPlaceChange(PlaceChangeEvent event) {
   Activity nextActivity = getNextActivity(event);

   Exception caughtOnStop = null;
   Exception caughtOnCancel = null;
   Exception caughtOnStart = null;

   if (nextActivity == null) {
     nextActivity = NULL_ACTIVITY;
   }

   if (currentActivity == nextActivity) {
     return;
   }

   if (startingNext) {
     // The place changed again before the new current activity showed its
     // widget
     caughtOnCancel = tryStopOrCancel(false);
     currentActivity = NULL_ACTIVITY;
     startingNext = false;
   } else if (currentActivity != NULL_ACTIVITY) {
     showWidget(null);

     /*
      * Kill off the activity's handlers, so it doesn't have to worry about
      * them accidentally firing as a side effect of its tear down
      */
     stopperedEventBus.removeHandlers();
     caughtOnStop = tryStopOrCancel(true);
   }

   currentActivity = nextActivity;

   if (currentActivity == NULL_ACTIVITY) {
     showWidget(null);
   } else {
     startingNext = true;
     caughtOnStart = tryStart();
   }

   if (caughtOnStart != null || caughtOnCancel != null || caughtOnStop != null) {
     Set<Exception> causes = new dart_collection.LinkedHashSet<Exception>();
     if (caughtOnStop != null) {
       causes.add(caughtOnStop);
     }
     if (caughtOnCancel != null) {
       causes.add(caughtOnCancel);
     }
     if (caughtOnStart != null) {
       causes.add(caughtOnStart);
     }

     throw new UmbrellaException(causes);
   }
 }

 /**
  * Reject the place change if the current activity is not willing to stop.
  * 
  * @see com.google.gwt.place.shared.PlaceChangeRequestEvent.Handler#onPlaceChangeRequest(PlaceChangeRequestEvent)
  */
 void onPlaceChangeRequest(PlaceChangeRequestEvent event) {
   event.setWarning(currentActivity.mayStop());
 }

 /**
  * Sets the display for the receiver, and has the side effect of starting or
  * stopping its monitoring the event bus for place change events.
  * <p>
  * If you are disposing of an ActivityManager, it is important to call
  * setDisplay(null) to get it to deregister from the event bus, so that it can
  * be garbage collected.
  * 
  * @param display an instance of AcceptsOneWidget
  */
 void setDisplay(AcceptsOneWidget display) {
   bool wasActive = (null != this.display);
   bool willBeActive = (null != display);
   this.display = display;
   if (wasActive != willBeActive) {
     updateHandlers(willBeActive);
   }
 }

 Activity getNextActivity(PlaceChangeEvent event) {
   if (display == null) {
     /*
      * Display may have been nulled during PlaceChangeEvent dispatch. Don't
      * bother the mapper, just return a null to ensure we shut down the
      * current activity
      */
     return null;
   }
   return mapper.getActivity(event.getNewPlace());
 }

 void showWidget(IsWidget view) {
   if (display != null) {
     display.setWidgetIsWidget(view);
   }
 }

 Exception tryStart() {
   Exception caughtOnStart = null;
   try {
     /*
      * Wrap the actual display with a per-call instance that protects the
      * display from canceled or stopped activities, and which maintains our
      * startingNext state.
      */
     currentActivity.start(new _ProtectedDisplay(this, currentActivity), stopperedEventBus);
   } on Exception catch (t) {
     caughtOnStart = t;
   }
   return caughtOnStart;
 }

 Exception tryStopOrCancel(bool stop) {
   Exception caughtOnStop = null;
   try {
     if (stop) {
       currentActivity.onStop();
     } else {
       currentActivity.onCancel();
     }
   } on Exception catch (t) {
     caughtOnStop = t;
   } finally {
     /*
      * Kill off the handlers again in case it was naughty and added new ones
      * during onstop or oncancel
      */
     stopperedEventBus.removeHandlers();
   }
   return caughtOnStop;
 }

 void updateHandlers(bool activate) {
   if (activate) {
     final HandlerRegistration placeReg = eventBus.addHandler(PlaceChangeEvent.TYPE, this);
     final HandlerRegistration placeRequestReg =
         eventBus.addHandler(PlaceChangeRequestEvent.TYPE, this);

     this.handlerRegistration = new _ActivityHandlerRegistration(placeReg, placeRequestReg);
   } else {
     if (handlerRegistration != null) {
       handlerRegistration.removeHandler();
       handlerRegistration = null;
     }
   }
 }
}

Implements

PlaceChangeRequestEventHandler, PlaceChangeEventHandler

Static Properties

final Activity NULL_ACTIVITY #

static final Activity NULL_ACTIVITY = new _AbstractActivity()

Constructors

new ActivityManager(ActivityMapper mapper, EventBus eventBus) #

Create an ActivityManager. Next call {@link #setDisplay}.

@param mapper finds the {@link Activity} for a given

     {@link com.google.gwt.place.shared.Place}

@param eventBus source of {@link PlaceChangeEvent} and

     {@link PlaceChangeRequestEvent} events.
ActivityManager(this.mapper, this.eventBus) {
 stopperedEventBus = new ResettableEventBus(eventBus);
}

Properties

Activity currentActivity #

Activity currentActivity = NULL_ACTIVITY

AcceptsOneWidget display #

AcceptsOneWidget display

final EventBus eventBus #

final EventBus eventBus

HandlerRegistration handlerRegistration #

HandlerRegistration handlerRegistration

final ActivityMapper mapper #

final ActivityMapper mapper

bool startingNext #

bool startingNext = false

ResettableEventBus stopperedEventBus #

ResettableEventBus stopperedEventBus

Methods

EventBus getActiveEventBus() #

Returns an event bus which is in use by the currently running activity. <p> Any handlers attached to the returned event bus will be de-registered when the current activity is stopped.

@return the event bus used by the current activity

EventBus getActiveEventBus() {
 return stopperedEventBus;
}

Activity getNextActivity(PlaceChangeEvent event) #

Activity getNextActivity(PlaceChangeEvent event) {
 if (display == null) {
   /*
    * Display may have been nulled during PlaceChangeEvent dispatch. Don't
    * bother the mapper, just return a null to ensure we shut down the
    * current activity
    */
   return null;
 }
 return mapper.getActivity(event.getNewPlace());
}

void onPlaceChange(PlaceChangeEvent event) #

Deactivate the current activity, find the next one from our ActivityMapper, and start it. <p> The current activity's widget will be hidden immediately, which can cause flicker if the next activity provides its widget asynchronously. That can be minimized by decent caching. Perenially slow activities might mitigate this by providing a widget immediately, with some kind of "loading" treatment.

void onPlaceChange(PlaceChangeEvent event) {
 Activity nextActivity = getNextActivity(event);

 Exception caughtOnStop = null;
 Exception caughtOnCancel = null;
 Exception caughtOnStart = null;

 if (nextActivity == null) {
   nextActivity = NULL_ACTIVITY;
 }

 if (currentActivity == nextActivity) {
   return;
 }

 if (startingNext) {
   // The place changed again before the new current activity showed its
   // widget
   caughtOnCancel = tryStopOrCancel(false);
   currentActivity = NULL_ACTIVITY;
   startingNext = false;
 } else if (currentActivity != NULL_ACTIVITY) {
   showWidget(null);

   /*
    * Kill off the activity's handlers, so it doesn't have to worry about
    * them accidentally firing as a side effect of its tear down
    */
   stopperedEventBus.removeHandlers();
   caughtOnStop = tryStopOrCancel(true);
 }

 currentActivity = nextActivity;

 if (currentActivity == NULL_ACTIVITY) {
   showWidget(null);
 } else {
   startingNext = true;
   caughtOnStart = tryStart();
 }

 if (caughtOnStart != null || caughtOnCancel != null || caughtOnStop != null) {
   Set<Exception> causes = new dart_collection.LinkedHashSet<Exception>();
   if (caughtOnStop != null) {
     causes.add(caughtOnStop);
   }
   if (caughtOnCancel != null) {
     causes.add(caughtOnCancel);
   }
   if (caughtOnStart != null) {
     causes.add(caughtOnStart);
   }

   throw new UmbrellaException(causes);
 }
}

void onPlaceChangeRequest(PlaceChangeRequestEvent event) #

Reject the place change if the current activity is not willing to stop.

@see com.google.gwt.place.shared.PlaceChangeRequestEvent.Handler#onPlaceChangeRequest(PlaceChangeRequestEvent)

void onPlaceChangeRequest(PlaceChangeRequestEvent event) {
 event.setWarning(currentActivity.mayStop());
}

void setDisplay(AcceptsOneWidget display) #

Sets the display for the receiver, and has the side effect of starting or stopping its monitoring the event bus for place change events. <p> If you are disposing of an ActivityManager, it is important to call setDisplay(null) to get it to deregister from the event bus, so that it can be garbage collected.

@param display an instance of AcceptsOneWidget

void setDisplay(AcceptsOneWidget display) {
 bool wasActive = (null != this.display);
 bool willBeActive = (null != display);
 this.display = display;
 if (wasActive != willBeActive) {
   updateHandlers(willBeActive);
 }
}

void showWidget(IsWidget view) #

void showWidget(IsWidget view) {
 if (display != null) {
   display.setWidgetIsWidget(view);
 }
}

Exception tryStart() #

Exception tryStart() {
 Exception caughtOnStart = null;
 try {
   /*
    * Wrap the actual display with a per-call instance that protects the
    * display from canceled or stopped activities, and which maintains our
    * startingNext state.
    */
   currentActivity.start(new _ProtectedDisplay(this, currentActivity), stopperedEventBus);
 } on Exception catch (t) {
   caughtOnStart = t;
 }
 return caughtOnStart;
}

Exception tryStopOrCancel(bool stop) #

Exception tryStopOrCancel(bool stop) {
 Exception caughtOnStop = null;
 try {
   if (stop) {
     currentActivity.onStop();
   } else {
     currentActivity.onCancel();
   }
 } on Exception catch (t) {
   caughtOnStop = t;
 } finally {
   /*
    * Kill off the handlers again in case it was naughty and added new ones
    * during onstop or oncancel
    */
   stopperedEventBus.removeHandlers();
 }
 return caughtOnStop;
}

void updateHandlers(bool activate) #

void updateHandlers(bool activate) {
 if (activate) {
   final HandlerRegistration placeReg = eventBus.addHandler(PlaceChangeEvent.TYPE, this);
   final HandlerRegistration placeRequestReg =
       eventBus.addHandler(PlaceChangeRequestEvent.TYPE, this);

   this.handlerRegistration = new _ActivityHandlerRegistration(placeReg, placeRequestReg);
 } else {
   if (handlerRegistration != null) {
     handlerRegistration.removeHandler();
     handlerRegistration = null;
   }
 }
}