/** * GwtFancyImage.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.ArrayList; import java.util.List; 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 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.ImageElement; import com.google.gwt.dom.client.Style.Display; import com.google.gwt.dom.client.Style.Position; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.Widget; public class GwtFancyImage extends Widget { private final List<ImageElement> images = new ArrayList<ImageElement>(); private int currentIndex = 0; private Timer autoBrowseTimer; private int autoBrowseTimeoutMs = 3000; protected final static String ROTATE_VALUE_VISIBLE = "rotateX(0deg)"; protected final static String ROTATE_VALUE_HIDDEN = "rotateX(180deg)"; protected final static String ROTATE_VALUE_DISABLED = "none"; protected static BrowserMode browserMode; public final static String CLASS_NAME = "fancy-image"; protected final ElementStyler styler = new ElementStyler(); public GwtFancyImage() { DivElement root = Document.get().createDivElement(); root.getStyle().setPosition(Position.RELATIVE); root.addClassName(CLASS_NAME); this.setElement(root); } private void stopAutoBrowseTimer() { if (autoBrowseTimer != null) { getAutoBrowseTimer().cancel(); autoBrowseTimer = null; } } private Timer getAutoBrowseTimer() { if (autoBrowseTimer == null) { autoBrowseTimer = new Timer() { @Override public void run() { if (GwtFancyImage.this.isVisible()) { showNextImage(); } } }; } return autoBrowseTimer; } public void setAutoBrowseEnabled(boolean on) { if (on) { getAutoBrowseTimer().scheduleRepeating(autoBrowseTimeoutMs); getAutoBrowseTimer().run(); } else { stopAutoBrowseTimer(); } } public void setAutoBrowseTimeout(int millis) { if (millis > 0 && autoBrowseTimeoutMs != millis) { autoBrowseTimeoutMs = millis; getAutoBrowseTimer().scheduleRepeating(autoBrowseTimeoutMs); } } private ImageElement createImageElement(String url) { ImageElement image = Document.get().createImageElement(); image.setSrc(url); image.getStyle().setPosition(Position.ABSOLUTE); image.getStyle().setLeft(0.0, Unit.PX); image.getStyle().setTop(0.0, Unit.PX); styler.styleElementOut(image); return image; } public void setImage(String url, int index) { if (index >= images.size()) { addImage(url); } else { ImageElement replaced = images.get(index); if (!replaced.getSrc().equals(url)) { replaced.setSrc(url); } } } public int addImage(String url) { ImageElement image = createImageElement(url); images.add(image); getElement().appendChild(image); if (images.size() == 1) { showImage(0); } applyTransitionStyleNames(image, false); return images.size(); } public void trimImages(int amount) { while (images.size() > amount) { removeImage(images.get(amount).getSrc()); } if (currentIndex >= images.size()) { showImage(0); } } public void removeImage(String url) { for (ImageElement image : images) { if (image.getSrc().equals(url)) { getElement().removeChild(image); images.remove(image); break; } } } public void showImage(String url) { for (int i = 0; i < images.size(); ++i) { if (images.get(i).getSrc().endsWith(url)) { showImage(i); break; } } } public void showImage(int index) { if (images.isEmpty()) { return; } if (index >= images.size()) { index = 0; } if (index != currentIndex) { ImageElement prevImage = images.get(currentIndex); ImageElement currentImage = images.get(index); currentIndex = index; prevImage.getStyle().setDisplay( styler.hasValues() ? Display.BLOCK : Display.NONE); currentImage.getStyle().setDisplay(Display.BLOCK); if (styler.hasValues()) { applyTransitionStyleNames(prevImage, true); applyTransitionStyleNames(currentImage, true); } } } private void showNextImage() { int nextIndex = currentIndex + 1; if (nextIndex >= images.size()) { nextIndex = 0; } showImage(nextIndex); } public void setFadeImages(boolean fade) { if (styler.isValueEnabled(Value.OPACITY) != fade) { styler.setValueEnabled(Value.OPACITY, fade); if (fade) { updateStylingOfImages(); } else { for (ImageElement element : images) { styler.removeStylingFromElement(element, Value.OPACITY); } } } } public void setRotateImages(boolean rotate, boolean horizontal) { if (rotate) { if (horizontal) { styler.setValueEnabled(Value.VERTICAL2_ROTATE, false); styler.setValueEnabled(Value.HORIZONTAL2_ROTATE, true); } else { styler.setValueEnabled(Value.HORIZONTAL2_ROTATE, false); styler.setValueEnabled(Value.VERTICAL2_ROTATE, true); } addStyleName(CLASS_NAME + "-rotate"); } else { styler.setValueEnabled(Value.VERTICAL2_ROTATE, false); styler.setValueEnabled(Value.HORIZONTAL2_ROTATE, false); removeStyleName(CLASS_NAME + "-rotate"); for (ImageElement element : images) { styler.removeStylingFromElement(element, Value.VERTICAL2_ROTATE); } } } protected static BrowserMode getBrowserMode() { if (browserMode == null) { browserMode = BrowserMode.resolve(); } return browserMode; } protected void updateStylingOfImages() { for (ImageElement element : images) { applyTransitionStyleNames(element, false); } } protected void applyTransitionStyleNames(final ImageElement element, boolean animate) { boolean isCurrent = currentIndex == images.indexOf(element); if (isCurrent) { if (animate) { styler.styleElementIn(element); Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { styler.styleElementOn(element); } }); } else { styler.styleElementOn(element); } } else { styler.styleElementOut(element); } } }