
com.googlecode.mgwt.ui.client.MGWT Maven / Gradle / Ivy
/*
* Copyright 2010 Daniel Kurka
*
* 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.googlecode.mgwt.ui.client;
import java.util.logging.Logger;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.BodyElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.LinkElement;
import com.google.gwt.dom.client.MetaElement;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Float;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.StyleInjector;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.RootPanel;
import com.googlecode.mgwt.dom.client.event.orientation.OrientationChangeEvent;
import com.googlecode.mgwt.dom.client.event.orientation.OrientationChangeEvent.ORIENTATION;
import com.googlecode.mgwt.dom.client.event.orientation.OrientationChangeHandler;
import com.googlecode.mgwt.ui.client.MGWTSettings.ViewPort;
import com.googlecode.mgwt.ui.client.theme.base.UtilCss;
import com.googlecode.mgwt.ui.client.util.AddressBarUtil;
/**
* The MGWT Object is used to apply settings for an MGWT App. It also provides an instance of
* {@link OsDetection}, as well a way to determine the device orientation
*
*
*
* @author Daniel Kurka
*/
public class MGWT {
private static final Logger logger = Logger.getLogger("MGWT");
private static final OsDetection OS_DETECTION = GWT.create(OsDetection.class);
private final static EventBus manager = new SimpleEventBus();
private static ORIENTATION currentOrientation;
private static Timer timer;
private static boolean scrollingDisabled;
private static JavaScriptObject nativeJsFunction;
private static AddressBarUtil addressBarUtil;
/**
* Add a orientation handler to detect the device orientation
*
* @param handler the handler to add
* {@link com.googlecode.mgwt.dom.client.event.orientation.OrientationChangeHandler} .
* @return a {@link com.google.gwt.event.shared.HandlerRegistration} object.
*/
public static HandlerRegistration addOrientationChangeHandler(OrientationChangeHandler handler) {
maybeSetupOrientation();
return manager.addHandler(OrientationChangeEvent.getType(), handler);
}
/**
* Apply settings for this mgwt app. Every app should call this method with the options its wants
* for their app
*
* The options are documented in @link {@link MGWTSettings}
*
* @param settings the settings for this app
*
*/
public static void applySettings(MGWTSettings settings) {
// This is a very nasty workaround because GWT CssResource does not
// support @media correctly!
StyleInjector.inject(MGWTStyle.getTheme().getMGWTClientBundle().utilTextResource().getText());
Element head = getHead();
if (settings.getIconUrl() != null) {
LinkElement iconUrlLinkElement = Document.get().createLinkElement();
if (settings.isAddGlosToIcon()) {
iconUrlLinkElement.setRel("apple-touch-startup-image");
} else {
iconUrlLinkElement.setRel("apple-touch-startup-image-precomposed");
}
iconUrlLinkElement.setHref(settings.getIconUrl());
head.appendChild(iconUrlLinkElement);
}
if (settings.getStartUrl() != null) {
LinkElement startUrlLinkElement = Document.get().createLinkElement();
startUrlLinkElement.setRel("apple-touch-startup-image");
startUrlLinkElement.setHref(settings.getStartUrl());
head.appendChild(startUrlLinkElement);
}
ViewPort viewPort = settings.getViewPort();
if (viewPort != null) {
MetaElement fixViewPortElement = Document.get().createMetaElement();
fixViewPortElement.setName("viewport");
fixViewPortElement.setContent(viewPort.getContent());
head.appendChild(fixViewPortElement);
}
if (settings.isFullscreen()) {
MetaElement fullScreenMetaTag = Document.get().createMetaElement();
fullScreenMetaTag.setName("apple-mobile-web-app-capable");
fullScreenMetaTag.setContent("yes");
head.appendChild(fullScreenMetaTag);
if (settings.getStatusBar() != null) {
MetaElement statusBarMetaTag = Document.get().createMetaElement();
statusBarMetaTag.setName("apple-mobile-web-app-status-bar-style");
statusBarMetaTag.setContent(settings.getStatusBar());
head.appendChild(statusBarMetaTag);
}
}
scrollingDisabled = settings.isPreventScrolling();
if (settings.isPreventScrolling() && getOsDetection().isIOs()) {
BodyElement body = Document.get().getBody();
setupPreventScrolling(body);
}
if (settings.isDisablePhoneNumberDetection()) {
MetaElement fullScreenMetaTag = Document.get().createMetaElement();
fullScreenMetaTag.setName("format-detection");
fullScreenMetaTag.setContent("telephone=no");
head.appendChild(fullScreenMetaTag);
}
if (settings.getStatusBarStyle() != null) {
MetaElement statusBarTag = Document.get().createMetaElement();
statusBarTag.setName("apple-mobile-web-app-status-bar-style");
switch (settings.getStatusBarStyle()) {
case BLACK:
statusBarTag.setContent("black");
break;
case BLACK_TRANSLUCENT:
statusBarTag.setContent("black-translucent");
break;
case DEFAULT:
default:
statusBarTag.setContent("default");
break;
}
head.appendChild(statusBarTag);
}
}
/**
* Detect if a web app is in full screen mode
*
* fullscreen currently only exits on ios
*
* @return true if the web app is in full screen mode, otherwise false
*/
public static native boolean isFullScreen()/*-{
if ($wnd.navigator.standalone) {
return true;
}
return false;
}-*/;
/**
*
* Considered internal don`t call!
*
* fixIOSScrollIssueBlur
*
*/
public static void fixIOSScrollIssueBlur() {
if (!scrollingDisabled) {
return;
}
if (timer != null) {
timer.cancel();
}
timer = new Timer() {
@Override
public void run() {
Window.scrollTo(0, 0);
}
};
timer.schedule(100);
}
/**
* Considered internal don`t call!
*
* fixIOSScrollIssueFocus
*
*/
public static void fixIOSScrollIssueFocus() {
if (!scrollingDisabled) {
return;
}
if (timer != null) {
timer.cancel();
}
timer = null;
}
/**
* Get the os detection interface
*
* @return a {@link com.googlecode.mgwt.ui.client.OsDetection} object.
*/
public static OsDetection getOsDetection() {
return OS_DETECTION;
}
/**
* Get the current orientation of the device
*
* @return the current orientation of the device
*/
public static ORIENTATION getOrientation() {
if (!orientationSupport()) {
int height = Window.getClientHeight();
int width = Window.getClientWidth();
if (width > height) {
return ORIENTATION.LANDSCAPE;
} else {
return ORIENTATION.PORTRAIT;
}
} else {
int orientation = getOrientation0();
ORIENTATION o;
switch (orientation) {
case 0:
case 180:
o = ORIENTATION.PORTRAIT;
break;
case 90:
case -90:
o = ORIENTATION.LANDSCAPE;
break;
default:
throw new IllegalStateException("this should not happen!?");
}
return o;
}
}
private static void fireOrientationChangedEvent(ORIENTATION orientation) {
setClasses(orientation);
manager.fireEvent(new OrientationChangeEvent(orientation));
}
private static Element getHead() {
NodeList elementsByTagName = Document.get().getElementsByTagName("head");
if (elementsByTagName.getLength() != 1) {
throw new RuntimeException("there is no head element");
}
return elementsByTagName.getItem(0);
}
private static native int getOrientation0()/*-{
if (typeof ($wnd.orientation) == 'undefined') {
return 0;
}
return $wnd.orientation;
}-*/;
private static void onorientationChange(int orientation) {
ORIENTATION o;
switch (orientation) {
case 0:
case 180:
o = ORIENTATION.PORTRAIT;
break;
case 90:
case -90:
o = ORIENTATION.LANDSCAPE;
break;
default:
logger.warning("on orientation changed called with invalid value: '" + orientation + "' - defaulting to Portrait");
o = ORIENTATION.PORTRAIT;
break;
}
currentOrientation = o;
fireOrientationChangedEvent(o);
}
// update styles on body
private static void setClasses(ORIENTATION o) {
UtilCss utilCss = MGWTStyle.getTheme().getMGWTClientBundle().getUtilCss();
switch (o) {
case PORTRAIT:
Document.get().getBody().addClassName(utilCss.portrait());
Document.get().getBody().removeClassName(utilCss.landscape());
break;
case LANDSCAPE:
Document.get().getBody().addClassName(utilCss.landscape());
Document.get().getBody().removeClassName(utilCss.portrait());
break;
default:
break;
}
}
private native static boolean orientationSupport()/*-{
var ua = window.navigator.userAgent.toLowerCase();
if (ua.indexOf('android') != -1) {
return false;
}
if (ua.indexOf('iphone') != -1) {
return true;
}
if (ua.indexOf('ipad') != -1) {
return true;
}
return false;
}-*/;
private static boolean orientationInitialized;
private static void maybeSetupOrientation() {
if (orientationInitialized)
return;
if (!GWT.isClient()) {
return;
}
if (!orientationSupport()) {
Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(ResizeEvent event) {
ORIENTATION orientation = getOrientation();
if (orientation != currentOrientation) {
currentOrientation = orientation;
fireOrientationChangedEvent(orientation);
}
}
});
} else {
nativeJsFunction = setupOrientation0();
Window.addCloseHandler(new CloseHandler() {
@Override
public void onClose(CloseEvent event) {
destroyOrientation(nativeJsFunction);
}
});
}
}
private static native JavaScriptObject setupOrientation0()/*-{
var func = $entry(function() {
@com.googlecode.mgwt.ui.client.MGWT::onorientationChange(I)($wnd.orientation);
});
$doc.body.onorientationchange = func;
$doc.addEventListener("orientationChanged", func);
return func;
}-*/;
private static native void destroyOrientation(JavaScriptObject o)/*-{
$doc.body.onorientationchange = null;
$doc.removeEventListener("orientationChanged", o);
}-*/;
private static native void setupPreventScrolling(Element el)/*-{
var func = function(event) {
event.preventDefault();
return false;
};
el.ontouchmove = func;
}-*/;
/**
* A utility method to hide the soft keyboard
*/
public static void hideKeyBoard() {
final Anchor anchor = new Anchor(" ");
anchor.getElement().getStyle().setWidth(1, Unit.PX);
anchor.getElement().getStyle().setHeight(1, Unit.PX);
anchor.getElement().getStyle().setDisplay(Display.INLINE);
anchor.getElement().getStyle().setFloat(Float.LEFT);
RootPanel.get().add(anchor);
anchor.setFocus(true);
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
anchor.removeFromParent();
}
});
}
public static void showAddressBar(boolean s) {
if (s) {
getAddressBarUtil().showAddressBar();
} else {
getAddressBarUtil().hideAddressBar();
}
}
private static AddressBarUtil getAddressBarUtil() {
if (addressBarUtil == null) {
addressBarUtil = GWT.create(AddressBarUtil.class);
}
return addressBarUtil;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy