All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gwtplatform.mvp.client.Presenter Maven / Gradle / Ivy

There is a newer version: 1.6
Show newest version
/**
 * Copyright 2011 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.gwtplatform.mvp.client;

import com.google.gwt.event.shared.GwtEvent;
import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.mvp.client.proxy.PlaceRequest;
import com.gwtplatform.mvp.client.proxy.Proxy;
import com.gwtplatform.mvp.client.proxy.RevealContentEvent;
import com.gwtplatform.mvp.client.proxy.RevealContentHandler;
import com.gwtplatform.mvp.client.proxy.RevealRootContentEvent;
import com.gwtplatform.mvp.client.proxy.RevealRootLayoutContentEvent;
import com.gwtplatform.mvp.client.proxy.RevealRootPopupContentEvent;

/**
 * A singleton presenter, the basic building block of the
 * 
 * model-view-presenter architecture. Each logical page of your application will usually
 * correspond to a singleton {@link Presenter}. If you need to separate logic from view
 * in a simple graphical component, you might consider using a {@link PresenterWidget}.
 * 

* For more details on the hierarchical organization of presenters, see {@link PresenterWidget}. *

* Each presenter is associated to a {@link Proxy} which is responsible for listening to the * various events of interest for this presenter. This makes it possible to lazily instantiate * the presenter and use GWT code splitting. Proxies are automatically generated for you * based on the information contained in the presenter. For this purpose, your presenter has to * define an embedded interface extending {@link Proxy} or * {@link com.gwtplatform.mvp.client.proxy.ProxyPlace ProxyPlace}. Then you should apply various * annotations to that interface in order to specify the characteristics of your presenter. For example, * the following code indicates that the presenter will use GWT code splitting and will be * reachable at url {@code http://mydomain.com#main}: *

 * public class MainPagePresenter extends
 *     Presenter<MainPagePresenter.MyView, MainPagePresenter.MyProxy> {
 *
 *   public interface MyView extends View {}
 *
 *  {@literal @}ProxyCodeSplit
 *  {@literal @}NameToken("main")
 *   public interface MyProxy extends ProxyPlace<MainPagePresenter> {}
 *
 *  {@literal @}Inject
 *   public MainPagePresenter(EventBus eventBus, MyView view, MyProxy proxy) {
 *     super(eventBus, view, proxy, Presenter.RevealType.Root);
 *   }
 * }
 * 
* One of {@link com.gwtplatform.mvp.client.annotations.ProxyStandard ProxyStandard}, * {@link com.gwtplatform.mvp.client.annotations.ProxyCodeSplit ProxyCodeSplit} or * {@link com.gwtplatform.mvp.client.annotations.ProxyCodeSplitBundle ProxyCodeSplitBundle} * must always annotate the {@link Proxy} interface. *

* To reveal a presenter associated to a {@link com.gwtplatform.mvp.client.proxy.ProxyPlace ProxyPlace} * you can simply navigate to an hyperlink corresponding to this place's name token. The * {@link com.gwtplatform.mvp.client.proxy.PlaceManager PlaceManager} offers a number of method for building * such hyperlinks. If you want to reveal it programatically, you should build a * {@link com.gwtplatform.mvp.client.proxy.PlaceRequest PlaceRequest} and call one of the * following method: *

    *
  • {@link com.gwtplatform.mvp.client.proxy.PlaceManager#revealPlace(com.gwtplatform.mvp.client.proxy * .PlaceRequest) PlaceManager.revealPlace(PlaceRequest)}
  • *
  • {@link com.gwtplatform.mvp.client.proxy.PlaceManager#revealRelativePlace(com.gwtplatform.mvp.client.proxy * .PlaceRequest) PlaceManager.revealRelativePlace(PlaceRequest)}
  • *
  • {@link com.gwtplatform.mvp.client.proxy.PlaceManager#revealRelativePlace(com.gwtplatform.mvp.client.proxy * .PlaceRequest, int) PlaceManager.revealRelativePlace(PlaceRequest, int)}
  • *
* If the presenter is associated to a regular {@link Proxy} and does not have * a name token then you should call the {@link #forceReveal()} method. For such * presenters, it is customary to define an event responsible of revealing them in * order to enforce loose coupling. This event is then handled by the presenter * using the {@link com.gwtplatform.mvp.client.annotations.ProxyEvent ProxyEvent} * mechanism. *

* If the presenter is revealed and is not currently visible, then its {@link #revealInParent()} method * will be called. *

* To hide a presenter, you can reveal another one in the same slot or you can use * one of the methods described in {@link PresenterWidget}. *

* A presenter has a number of lifecycle methods that you can hook on to: *

    *
  • {@link #onBind()} *
  • {@link #onReveal()} *
  • {@link #onReset()} *
  • {@link #onHide()} *
  • {@link #onUnbind()} *
* Revealing or hiding a {@link PresenterWidget} triggers an internal chain of events that result * in these lifecycle methods being called. For an example, here is what happens when a presenter * is revealed (either via {@link #forceReveal()}, or through a * {@link com.gwtplatform.mvp.client.proxy.PlaceManager PlaceManager} method): *
    *
  • The presenter's {@link #revealInParent()} is call and it asks to be set in one of its * parent slot by firing a * {@link com.gwtplatform.mvp.client.proxy.RevealContentEvent RevealContentEvent}
  • *
  • If a presenter already occupies this slot it is removed.
  • *
    • If the presenter owning the slot is currently visible then * {@link #onHide()} is called on the removed presenter and, recursively, * on its children (bottom-up: first the children, then the parent)
    • *
    • If the parent is not visible, it asks to be set in one of its parent slot * by firing a {@link com.gwtplatform.mvp.client.proxy.RevealContentEvent RevealContentEvent} * too, this continues recursively until a visible presenter is reached, or until a presenter fires * {@link com.gwtplatform.mvp.client.proxy.RevealRootContentEvent RevealRootContentEvent} * or {@link com.gwtplatform.mvp.client.proxy.RevealRootLayoutContentEvent RevealRootLayoutContentEvent}
    • *
    *
  • When the above chain stops, {@link #onReveal} is called on all the presenters * that were traversed. (top down: first the parent, then the children);
  • *
  • Finally {@link #onReset()} is called on all the * currently visible presenters (top-down: first the parent, then * the children).
  • *
* * @param The {@link View} type. * @param The {@link Proxy} type. * @author Philippe Beaudoin * @author Christian Goudreau */ @Singleton public abstract class Presenter> extends PresenterWidget { /** * The RevealType define which event will be fired in the default {@link #revealInParent()}. *

* Root will fire a {@link RevealRootContentEvent}. * RootLayout will fire a {@link RevealRootLayoutContentEvent}. * RootPopup will fire a {@link RevealRootPopupContentEvent}. */ public enum RevealType { Root, RootLayout, RootPopup } /** * The light-weight {@Proxy} around this presenter. */ private final Proxy_ proxy; private RevealType revealType; private GwtEvent.Type> slot; /** * Creates a {@link Presenter} that is not necessarily using automatic * binding. Automatic binding will only work when instantiating this object using * Guice/GIN dependency injection. See * {@link HandlerContainerImpl#HandlerContainerImpl(boolean)} for * more details on automatic binding. * * @param autoBind {@code true} to request automatic binding, {@code false} otherwise. * @param eventBus The {@link EventBus}. * @param view The {@link View}. * @param proxy The {@link Proxy}. */ public Presenter(boolean autoBind, EventBus eventBus, V view, Proxy_ proxy) { super(eventBus, view); this.proxy = proxy; } /** * Creates a {@link Presenter} that uses automatic binding. This will * only work when instantiating this object using Guice/GIN dependency injection. * See {@link HandlerContainerImpl#HandlerContainerImpl()} for more details on * automatic binding. * * @param eventBus The {@link EventBus}. * @param view The {@link View}. * @param proxy The {@link Proxy}. */ public Presenter(EventBus eventBus, V view, Proxy_ proxy) { this(eventBus, view, proxy, null, null); } /** * Creates a {@link Presenter} that uses automatic binding. This will * only work when instantiating this object using Guice/GIN dependency injection. * See {@link HandlerContainerImpl#HandlerContainerImpl()} for more details on * automatic binding. * * @param eventBus The {@link EventBus}. * @param view The {@link View}. * @param proxy The {@link Proxy}. * @param revealType The {@link RevealType}. */ public Presenter(EventBus eventBus, V view, Proxy_ proxy, RevealType revealType) { this(eventBus, view, proxy, revealType, null); } /** * Creates a {@link Presenter} that uses automatic binding. This will * only work when instantiating this object using Guice/GIN dependency injection. * See {@link HandlerContainerImpl#HandlerContainerImpl()} for more details on * automatic binding. * * @param eventBus The {@link EventBus}. * @param view The {@link View}. * @param proxy The {@link Proxy}. * @param slot The slot where to reveal this presenter see {@see com.google.gwt.event.shared.GwtEvent.Type} and * {@see RevealContentHandler}. */ public Presenter(EventBus eventBus, V view, Proxy_ proxy, GwtEvent.Type> slot) { this(eventBus, view, proxy, null, slot); } /** * Creates a {@link Presenter} that uses automatic binding. This will * only work when instantiating this object using Guice/GIN dependency injection. * See {@link HandlerContainerImpl#HandlerContainerImpl()} for more details on * automatic binding. * * @param eventBus The {@link EventBus}. * @param view The {@link View}. * @param proxy The {@link Proxy}. * @param revealType The {@link RevealType}. * @param slot The slot where to reveal this presenter see {@see com.google.gwt.event.shared.GwtEvent.Type} * and {@see RevealContentHandler}. */ public Presenter(EventBus eventBus, V view, Proxy_ proxy, RevealType revealType, GwtEvent.Type> slot) { super(eventBus, view); this.proxy = proxy; this.revealType = revealType; this.slot = slot; } /** * Reveals the presenter, bypassing any service offered by the * {@link com.gwtplatform.mvp.client.proxy.PlaceManager PlaceManager}. * Since this method bypasses the {@link com.gwtplatform.mvp.client.proxy.PlaceManager PlaceManager} * it will not: *

    *
  • Update the browser history
  • *
  • Check accessibility via the {@link com.gwtplatform.mvp.client.proxy.Gatekeeper Gatekeeper}
  • *
  • Setup the presenter via {@link #prepareFromRequest(PlaceRequest)}
  • *
  • Uses the leave confirmation mechanism (see {@link com.gwtplatform.mvp.client.proxy * .PlaceManager#setOnLeaveConfirmation(String) PlaceManager.setOnLeaveConfirmation})
  • *
* Therefore, to reveal a presenter associated to a {@link com.gwtplatform.mvp.client.proxy.ProxyPlace ProxyPlace} * use one of the method provided by the {@link com.gwtplatform.mvp.client.proxy.PlaceManager PlaceManager}. * For more details see {@link Presenter}. */ public final void forceReveal() { if (isVisible()) { return; } revealInParent(); } /** * Returns the {@link Proxy} attached to this presenter. * * @return The {@link Proxy}. */ public final Proxy_ getProxy() { return proxy; } /** * Verifies if this presenter can be revealed automatically or if it is meant to be * revealed manually. * Normally, the user wants to reveal a presenter manually when it cannot be used * until some data is received from the server. For example, a form * to edit client details is unusable until all the data for this user has been * received. Fetching this data should be done in the {@link #prepareFromRequest(PlaceRequest)} * method. *

* In order to use manual reveal, override this method to return {@code true}. * Then, in your {@link #prepareFromRequest}, you can either: *

    *
  • Fetch the data using a {@link com.gwtplatform.mvp.client.proxy.ManualRevealCallback ManualRevealCallback}, * which will automatically reveal the presenter upon success.
  • *
  • Fetch the data by any other mean and call * {@link com.gwtplatform.mvp.client.proxy.ProxyPlace#manualReveal(Presenter)} when * your data is available. In this case you also have to call * {@link com.gwtplatform.mvp.client.proxy.ProxyPlace#manualRevealFailed()} * if loading fails, otherwise your application will become unusable.
  • *
* The default implementation uses automatic reveal, and therefore returns {@code false}. * * @return {@code true} if you want to use manual reveal, or {@code false} to use * automatic reveal. */ public boolean useManualReveal() { return false; } /** * Prepare the state of the presenter given the information contained in * the {@link PlaceRequest}. This method is called when the * {@link com.gwtplatform.mvp.client.proxy.PlaceManager PlaceManager} navigates * to this {@link Presenter}. You should override the method to extract any * parameters you need from the request. Make sure you call your parent's * {@link #prepareFromRequest} method. *

* If your presenter needs to fetch some information from the server while * preparing itself, consider using manual reveal. See {@link #useManualReveal()}. *

* If your presenter does not handle any parameter and does not want to fetch * extra information, then there is no need to override this method. * * @param request The {@link PlaceRequest}. */ public void prepareFromRequest(PlaceRequest request) { } /** * Returns the {@link RevealType} of this presenter. * * @return The {@link RevealType}. */ protected RevealType getRevealType() { return revealType; } /** * Set the {@link RevealType} of this presenter. * If the parent type is not null, the slot will be ignored in {@link #revealInParent()}. * * @param revealType The {@link RevealType}. */ protected void setRevealType(RevealType revealType) { this.revealType = revealType; } /** * Returns the slot where this presenter is to be revealed. * * @return The slot where to reveal this presenter see {@see com.google.gwt.event.shared.GwtEvent.Type} and {@see * RevealContentHandler}. */ protected GwtEvent.Type> getSlot() { return slot; } /** * Set the slot where this presenter is to be revealed. * The slot is ignored in {@link #revealInParent()} if the parent type is not null. * * @param slot The slot where to reveal this presenter see {@see com.google.gwt.event.shared.GwtEvent.Type} and * {@see RevealContentHandler}. */ protected void setSlot(GwtEvent.Type> slot) { this.slot = slot; } /** * Requests that the presenter reveal itself in its parent presenter. * You can override this method to either fire a * {@link com.gwtplatform.mvp.client.proxy.RevealContentEvent RevealContentEvent}, * a {@link com.gwtplatform.mvp.client.proxy.RevealRootContentEvent RevealRootContentEvent} * or a {@link com.gwtplatform.mvp.client.proxy.RevealRootLayoutContentEvent RevealRootLayoutContentEvent}. */ protected void revealInParent() { if (revealType != null) { switch (revealType) { case Root: RevealRootContentEvent.fire(this, this); break; case RootLayout: RevealRootLayoutContentEvent.fire(this, this); break; case RootPopup: RevealRootPopupContentEvent.fire(this, (PresenterWidget) this); break; } } else { RevealContentEvent.fire(this, slot, this); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy