/*
* Copyright (c) 2010 Zhihua (Dennis) Jiang
*
* 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.gwtmobile.ui.client.page;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.gwtmobile.ui.client.CSS.StyleNames.Primary;
import com.gwtmobile.ui.client.page.PageHistory.NavigateInfo;
import com.gwtmobile.ui.client.utils.Utils;
import com.gwtmobile.ui.client.widgets.HeaderPanel;
import com.gwtmobile.ui.client.widgets.IsGwtMobilePanel;
import com.gwtmobile.ui.client.widgets.PagePanel;
import com.gwtmobile.ui.client.widgets.WidgetBase;
public abstract class Page extends WidgetBase implements IsGwtMobilePanel {
final static private String CONSUMED_TOKEN = "#?#";
private Transition _transition = Transition.SLIDE; // assume SLIDE as default transition
protected String _tokenStateInfo = CONSUMED_TOKEN;
protected static boolean _inTransition = false;
static {
if (!Utils.isDesktop() && !Utils.hasPhoneGap()) {
hideAddressBar();
Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(ResizeEvent event) {
hideAddressBar();
scrollToHideAddressBar();
}
});
}
}
public static boolean isInTransition() {return _inTransition;};
@Override
protected void initWidget(Widget widget) {
super.initWidget(widget);
setStyleName(Primary.PagePanel);
// we might need to assert that the given widget has to be a PagePanel
if (widget.getClass().getName().endsWith("PagePanel"))
setTransition(((PagePanel)widget).getTransitionFlavor().getTransition());
// TODO: use permutation instead?
if (Utils.isAndroid()) {
addStyleName("Android");
} else if (Utils.isIOS()) {
addStyleName("iOS");
} else {
addStyleName("Desktop");
}
}
private static void hideAddressBar() {
int barHeight = Utils.isIOS() ? 60 : Utils.isAndroid() ? 1 : 0;
if (barHeight > 0) {
RootLayoutPanel.get().setHeight(Window.getClientHeight() + barHeight + "px");
}
}
private static void scrollToHideAddressBar() {
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
Window.scrollTo(0, 1);
}
});
}
@Override
public void onLoad() {
super.onLoad();
if (!Utils.isDesktop() && !Utils.hasPhoneGap()) {
scrollToHideAddressBar();
}
}
/**
* Gives the page an opportunity to load state that was sent as part of the
* history token prior to display.
*
* @see PageHistory#navigateTo(String, String)
* @see BrowserPageHistory#onValueChange(com.google.gwt.event.logical.shared.ValueChangeEvent)
*
* @param stateInfo
*/
protected void initNavigationalState(String stateInfo) {
}
@Override
public void onTransitionEnd(TransitionDirection direction) {
if (direction != TransitionDirection.To) {
return;
}
final Page to;
final PageHistory pageHistory = PageHistory.Instance;
final NavigateInfo info = pageHistory.getNavigateInfo();
if (false == info.isGoBack()) { // goto
to = this;
// TODO: change to use scheduler deferred command.
Timer timer = new Timer() {
@Override
public void run() {
to.onNavigateTo(info.getFromPage(), info.getValue());
to.initNavigationIfRequired();
}
};
timer.schedule(1);
} else { // goback
to = pageHistory.current();
Timer timer = new Timer() {
@Override
public void run() {
to.onNavigateBack(info.getFromPage(), info.getValue());
to.initNavigationIfRequired();
}
};
timer.schedule(1);
}
_inTransition = false;
}
protected void initNavigationIfRequired() {
if (!CONSUMED_TOKEN.equals(_tokenStateInfo)) {
initNavigationalState(_tokenStateInfo);
_tokenStateInfo = CONSUMED_TOKEN;
}
}
protected void onNavigateTo(Page from, Object object) {
}
protected void onNavigateBack(Page from, Object object) {
}
public void goTo(final Page toPage) {
goTo(toPage, toPage.getTransition());
}
public void goTo(final Page toPage, Object params) {
goTo(toPage, params, toPage.getTransition());
}
public void goTo(final Page toPage, final Transition transition) {
goTo(toPage, null, transition);
}
public void goTo(final Page toPage, Object params, final Transition transition) {
if (_inTransition) {
return;//can't start a new page transition until last one is complete.
}
_inTransition = true;
PageHistory.Instance.goTo(toPage, params, transition);
}
public void goBack(Object returnValue) {
if (_inTransition) {
return;//can't start a new page transition until last one is complete.
}
_inTransition = true;
PageHistory.Instance.goBack(returnValue);
}
public void setTransition(Transition transition) {
this._transition = transition;
}
public Transition getTransition() {
return _transition;
}
public static void load(Page mainPage) {
setPageResolution();
PageHistory.Instance.startUp(mainPage);
}
// public static void setDefaultTransition(Transition transition) {
// _defaultTransition = transition;
// }
@Override
public Widget getWidget() { // make getWidget() public
return super.getWidget();
}
private static void setPageResolution() {
int clientWidth = Window.getClientWidth();
if (Utils.isDesktop()) {
Document.get().getDocumentElement().setClassName("HVGA");
}
else if (clientWidth < 320) {
Document.get().getDocumentElement().setClassName("QVGA");
}
else if (clientWidth < 480) {
Document.get().getDocumentElement().setClassName("HVGA");
}
else if (clientWidth < 560) {
Document.get().getDocumentElement().setClassName("WVGA");
}
else {
Document.get().getDocumentElement().setClassName("WXGA");
}
}
public static native double getDevicePixelRatio() /*-{
return $wnd.devicePixelRatio;
}-*/;
/**
* Adds a home button handler. It assumes the right button in the header is
* the home button.
* </br>
* By Frank Mena 2012-04-11
*
* @param header the header
*/
//FIXME: remove "right button" assumption
public void addHomeHandler(HeaderPanel header) {
header.setRightButtonClickHandler(new ClickHandler()
{
@Override
public void onClick(ClickEvent event)
{
goHome();
}
});
}
/**
* Go home. Only works if you are using {@link SerialPageHistory}.
* </br>
* By Frank Mena 2012-04-11
*/
public void goHome() {
if (PageHistory.Instance instanceof SerialPageHistory) {
SerialPageHistory history = (SerialPageHistory) PageHistory.Instance;
history.goHome(this);
}
}
/**
* Push a page into the stack. Only works if you are using
* {@link SerialPageHistory}.
*
* By Frank Mena 2012-04-11
*
* @param page the page to push
*/
public static void push(Page page)
{
if (PageHistory.Instance instanceof SerialPageHistory) {
SerialPageHistory history = (SerialPageHistory) PageHistory.Instance;
history.add(page);
}
}
/**
* Exposes the onNavigate method of a page. Useful when restoring from
* passivated state.
*
* By Frank Mena 2012-04-11
*/
public void doOnNavigateTo()
{
this.onNavigateTo(null, null);
}
}