Java tutorial
/** * GwtFancyPanel.java (FancyLayouts) * * Copyright 2012 Vaadin Ltd, Sami Viitanen <alump@vaadin.org> * * 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 org.vaadin.alump.fancylayouts.gwt.client; import java.util.HashSet; import java.util.Set; import java.util.logging.Logger; import org.vaadin.alump.fancylayouts.gwt.client.model.BrowserMode; import org.vaadin.alump.fancylayouts.gwt.client.model.ElementStyler; import org.vaadin.alump.fancylayouts.gwt.client.model.ElementStyler.Value; import org.vaadin.alump.fancylayouts.gwt.client.model.FadeOutListener; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Display; import com.google.gwt.dom.client.Style.Overflow; import com.google.gwt.dom.client.Style.Position; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; public class GwtFancyPanel extends SimplePanel { private Widget previousWidget = null; private Widget currentWidget = null; private final Set<Widget> contentWidgets = new HashSet<Widget>(); public static final String CLASS_NAME = "fancy-panel"; protected ElementStyler elementStyler = new ElementStyler(); private static BrowserMode browserMode; protected String height = ""; protected String width = ""; protected ContentPanel contentPanel; protected Boolean scrollEnabled; protected FadeOutListener fadeOutListener; protected boolean activeTransition = false; private final static Logger logger = Logger.getLogger(GwtFancyPanel.class.getName()); protected class ContentPanel extends ComplexPanel { public ContentPanel() { setElement(Document.get().createDivElement()); setStyleName(CLASS_NAME + "-container"); getElement().getStyle().setPosition(Position.RELATIVE); getElement().getStyle().setLeft(0, Unit.PX); getElement().getStyle().setTop(0, Unit.PX); getElement().getStyle().setWidth(100, Unit.PCT); getElement().getStyle().setHeight(100, Unit.PCT); } @Override public void add(Widget widget) { DivElement contentWrapper = Document.get().createDivElement(); contentWrapper.setClassName(CLASS_NAME + "-cwrapper"); contentWrapper.getStyle().setWidth(100, Unit.PCT); if (!GwtFancyPanel.this.isScrollable()) { contentWrapper.getStyle().setHeight(100, Unit.PCT); } getElement().appendChild(contentWrapper); add(widget, (com.google.gwt.user.client.Element) Element.as(contentWrapper)); hide(widget); } @Override public boolean remove(Widget widget) { hide(widget); Element wrapper = getWrapper(widget); boolean removed = super.remove(widget); if (removed) { if (wrapper != null) { getElement().removeChild(wrapper); } } else { logger.warning("Failed to remove child!"); } return removed; } public Element getWrapper(Widget widget) { Element ret = null; if (widget != null && widget.getParent() == this && widget.getElement() != null) { ret = widget.getElement().getParentElement(); } return ret; } public void hide(Widget widget) { Element wrapper = getWrapper(widget); if (wrapper != null) { wrapper.getStyle().setDisplay(Display.NONE); } } public void show(Widget widget) { Element wrapper = getWrapper(widget); if (wrapper != null) { wrapper.getStyle().setDisplay(Display.BLOCK); } } public void hideAndShow(Widget hideWidget, Widget showWidget) { hide(hideWidget); show(showWidget); } } public GwtFancyPanel() { getElement().addClassName(CLASS_NAME); getElement().getStyle().setOverflow(Overflow.HIDDEN); contentPanel = new ContentPanel(); super.add(contentPanel); if (browserMode == null) { browserMode = BrowserMode.resolve(); } setScrollable(false); setFade(true); } public void setFadeOutListener(FadeOutListener listener) { fadeOutListener = listener; } private boolean addTransitionEndListener(Element element) { if (hasTransitionEndListener(element)) { return true; } String eventName = browserMode.getTransitionEnd(); if (eventName != null) { addTransitionEndListener(eventName, element); return true; } return false; } private native boolean hasTransitionEndListener(Element element) /*-{ return element.hasTransitionEndListener == true; }-*/; private native void addTransitionEndListener(String eventName, Element element) /*-{ var that = this; element.addEventListener(eventName, function(event){ that.@org.vaadin.alump.fancylayouts.gwt.client.GwtFancyPanel::onTransitionEnd(Ljava/lang/Object;)(element); },false); element.hasTransitionEndListener = true; }-*/; private void onTransitionEnd(Object object) { if (!activeTransition) { logger.warning("onTransitionEnd after transitions cancelled"); return; } if (!(object instanceof Element)) { return; } Element element = (Element) object; if (previousWidget != null) { if (element == contentPanel.getWrapper(previousWidget)) { if (elementStyler.isElementStyledOut(element)) { onFadeOutEnded(); } else { logger.warning("onTransitionEnd for hidden: wrong state?"); } } } else { if (element == contentPanel.getWrapper(currentWidget)) { if (elementStyler.isElementStyledOn(element)) { onFadeInEnded(); } else { logger.warning("onTransitionEnd for shown: wrong state?"); } } } } private void onFadeOutEnded() { clearWrapperTransitionPosition(getContentElement(previousWidget)); contentPanel.hideAndShow(previousWidget, currentWidget); previousWidget = null; final Widget currentWidgetWas = currentWidget; final Element wrapper = getContentElement(currentWidget); if (wrapper != null) { Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { if (currentWidgetWas == currentWidget) { elementStyler.styleElementOn(wrapper); } } }); } else { logger.warning("Failed to fade in new widget"); } } private void onFadeInEnded() { clearWrapperTransitionPosition(getContentElement(currentWidget)); activeTransition = false; } @Override public void add(Widget widget) { if (widget == null) { logger.warning("null widget can not be added to fancy panel"); return; } if (contentWidgets.contains(widget)) { return; } contentWidgets.add(widget); contentPanel.add(widget); } protected void skipTransition() { activeTransition = false; clearWrapperTransitionPosition(contentPanel.getWrapper(currentWidget)); changeContentWithoutTransition(currentWidget); } @Override public boolean remove(Widget widget) { if (widget == previousWidget) { if (activeTransition) { skipTransition(); } previousWidget = null; } else if (widget == currentWidget) { currentWidget = null; } if (!contentPanel.remove(widget)) { return false; } contentWidgets.remove(widget); return true; } private void changeContentWithTransition(Widget content) { Element prevWrapper = getContentElement(currentWidget); if (prevWrapper == null) { logger.fine("Missing wrapper of old widget, transition skipped."); changeContentWithoutTransition(content); return; } previousWidget = currentWidget; currentWidget = content; Element nextWrapper = getContentElement(currentWidget); addTransitionEndListener(prevWrapper); addTransitionEndListener(nextWrapper); activeTransition = true; setWrapperTransitionPosition(prevWrapper); setWrapperTransitionPosition(nextWrapper); elementStyler.styleElementOut(prevWrapper); elementStyler.styleElementIn(nextWrapper); } protected void changeContentWithoutTransition(Widget content) { if (currentWidget != null) { contentPanel.hide(currentWidget); } currentWidget = content; contentPanel.show(currentWidget); } public boolean hasWidget(Widget widget) { return contentWidgets.contains(widget); } public void setContent(Widget content) { if (content == currentWidget) { return; } if (!contentWidgets.contains(content)) { logger.warning("Setting widget not found from children as current."); add(content); } if (browserMode.hasTransitionEndEvent() && elementStyler.hasValues() && previousWidget == null) { changeContentWithTransition(content); } else { changeContentWithoutTransition(content); } } protected Element getContentElement(Widget widget) { return contentPanel.getWrapper(widget); } public boolean isScrollable() { return scrollEnabled != null && scrollEnabled; } public void setScrollable(boolean scroll) { if (scrollEnabled != null && scrollEnabled == scroll) { return; } Style style = contentPanel.getElement().getStyle(); if (scroll) { style.setOverflow(Overflow.AUTO); } else { style.clearOverflow(); } scrollEnabled = scroll; } public void setScrollTop(int value) { contentPanel.getElement().setScrollTop(value); } public int getScrollTop() { return contentPanel.getElement().getScrollTop(); } public void setScrollLeft(int value) { contentPanel.getElement().setScrollLeft(value); } public int getScrollLeft() { return contentPanel.getElement().getScrollLeft(); } @Override public void setWidth(String width) { if (this.width.endsWith(width)) { return; } this.width = width; super.setWidth(width); } @Override public void setHeight(String height) { if (this.height.endsWith(height)) { return; } this.height = height; super.setHeight(height); } public void setFade(boolean enabled) { if (enabled == elementStyler.isValueEnabled(Value.OPACITY)) { return; } if (enabled) { contentPanel.addStyleName("fancy-fade"); } else { contentPanel.removeStyleName("fancy-fade"); } elementStyler.setValueEnabled(Value.OPACITY, enabled); if (!enabled) { if (!elementStyler.hasValues()) { activeTransition = false; } for (Widget child : contentWidgets) { elementStyler.removeStylingFromElement(contentPanel.getWrapper(child), Value.OPACITY); } } } public void setZoom(boolean enabled) { if (enabled == elementStyler.isValueEnabled(Value.SCALE)) { return; } if (enabled) { contentPanel.addStyleName("fancy-zoom"); } else { contentPanel.removeStyleName("fancy-zoom"); } elementStyler.setValueEnabled(Value.SCALE, enabled); if (!enabled) { if (!elementStyler.hasValues()) { activeTransition = false; } for (Widget child : contentWidgets) { elementStyler.removeStylingFromElement(contentPanel.getWrapper(child), Value.SCALE); } } } public void setRotate(boolean enabled, boolean horizontal) { if (!enabled) { contentPanel.removeStyleName("fancy-rotate"); elementStyler.setValueEnabled(Value.VERTICAL_ROTATE, false); elementStyler.setValueEnabled(Value.HORIZONTAL_ROTATE, false); if (!elementStyler.hasValues()) { activeTransition = false; } for (Widget child : contentWidgets) { elementStyler.removeStylingFromElement(contentPanel.getWrapper(child), Value.VERTICAL_ROTATE); } } else { if (horizontal) { elementStyler.setValueEnabled(Value.VERTICAL_ROTATE, false); elementStyler.setValueEnabled(Value.HORIZONTAL_ROTATE, true); } else { elementStyler.setValueEnabled(Value.HORIZONTAL_ROTATE, false); elementStyler.setValueEnabled(Value.VERTICAL_ROTATE, true); } contentPanel.addStyleName("fancy-rotate"); } } /** * Clear hardcoded position on the screen * * @param wrapper */ private void clearWrapperTransitionPosition(Element wrapper) { Style style = wrapper.getStyle(); style.clearPosition(); if (this.isScrollable()) { style.clearHeight(); } else { style.setHeight(100, Unit.PCT); } style.clearTop(); style.clearLeft(); style.clearOverflow(); } /** * Set wrapper to hard coded position on the screen * * @param wrapper */ private void setWrapperTransitionPosition(Element wrapper) { Style style = wrapper.getStyle(); style.setTop(0, Unit.PX); style.setLeft(0, Unit.PX); style.setHeight(100, Unit.PCT); style.setPosition(Position.ABSOLUTE); style.setOverflow(Overflow.HIDDEN); } }