Package com.denisk.appengine.nl.client.thirdparty.com.reveregroup.carousel.client

Source Code of com.denisk.appengine.nl.client.thirdparty.com.reveregroup.carousel.client.Carousel

package com.denisk.appengine.nl.client.thirdparty.com.reveregroup.carousel.client;

import java.util.ArrayList;
import java.util.List;

import com.denisk.appengine.nl.client.thirdparty.com.reveregroup.carousel.client.events.PhotoClickEvent;
import com.denisk.appengine.nl.client.thirdparty.com.reveregroup.carousel.client.events.PhotoClickHandler;
import com.denisk.appengine.nl.client.thirdparty.com.reveregroup.carousel.client.events.PhotoFocusHandler;
import com.denisk.appengine.nl.client.thirdparty.com.reveregroup.carousel.client.events.PhotoToFrontEvent;
import com.denisk.appengine.nl.client.thirdparty.com.reveregroup.carousel.client.events.PhotoToFrontHandler;
import com.denisk.appengine.nl.client.thirdparty.com.reveregroup.carousel.client.events.PhotoUnfocusHandler;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.event.dom.client.MouseWheelEvent;
import com.google.gwt.event.dom.client.MouseWheelHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
/**
* Copied from http://code.google.com/p/spiral-carousel-gwt/
*/

public class Carousel extends Composite {
  private List<Photo> photos = new ArrayList<Photo>();
  private CarouselImage[] images;
 
  // Panels and label for the UI
  private DockPanel carouselDock;

  private AbsolutePanel imagePanel;

  private Label caption;
 
  private double currentRotation = 0.0;

  private int currentPhotoIndex = 0; // the photo that is currently in front

  private int carouselSize = 9;

  private int preLoadSize = 3;

  boolean timerOn;
  double velocity;
  Timer timer = new RotationTimer();
  long lastTime;

  double acceleration = .998;
  double velocityThreshold = .00002;

  private boolean mouseMoved = false;

  private MouseBehavior mouseBehavior;

  private FocusBehavior focusBehavior;
 
  public Carousel() {
    this(true, true);
  }
 
  public Carousel(boolean useDefaultMouseBehavior, boolean useDefaultFocusBehavior) {
    // Set up UI structure
    carouselDock = new DockPanel();
    imagePanel = new AbsolutePanel();
    imagePanel.setSize("100%", "100%");
    caption = new Label();
    carouselDock.add(caption, DockPanel.SOUTH);
    carouselDock.add(imagePanel, DockPanel.NORTH);
    carouselDock.setCellHeight(caption, "15");
    carouselDock.setCellHeight(imagePanel, "100%");
    carouselDock.setCellHorizontalAlignment(caption, DockPanel.ALIGN_CENTER);
    imagePanel.getElement().getStyle().setProperty("overflow", "hidden");
    carouselDock.setStyleName("photoCarousel");
    caption.setStyleName("photoCarouselCaption");
   
    // Set up images
    images = new CarouselImage[this.carouselSize + (this.preLoadSize * 2)];
    for (int i = 0; i < images.length; i++) {
      images[i] = new CarouselImage();
      //hack for IE
      if (Window.Navigator.getUserAgent().contains("MSIE")) {
        images[i].getElement().getStyle().setProperty("height", "auto");
      }
      //images[i].setSize("1", "1");
      Utils.preventDrag(images[i]);
      Utils.preventSelection(images[i].getElement());
      images[i].getElement().getStyle().setProperty("display", "none");
      images[i].addClickHandler(new ClickHandler() {
        public void onClick(ClickEvent event) {
          if (mouseMoved) {
            return; // make sure a photo click is not registered
          }
          // when the mouse is dragged.
          Image img = (Image) event.getSource();
          for (int i = 0; i < carouselSize; i++) {
            if (images[i + preLoadSize] == img) {
              int pIndex = i - 4 + currentPhotoIndex;
              pIndex = Utils.modulus(pIndex, photos.size());
              // fire off photo clicked event
              PhotoClickEvent pcEvent = new PhotoClickEvent();
              pcEvent.setPhotoIndex(pIndex);
              pcEvent.setPhoto(photos.get(pIndex));
              fireEvent(pcEvent);
              break;
            }
          }
        }
      });
      imagePanel.add(images[i]);
    }
    this.initWidget(carouselDock);

    // Sync caption with front-most photo.
    addPhotoToFrontHandler(new PhotoToFrontHandler() {
      public void photoToFront(PhotoToFrontEvent event) {
        caption.setText(event.getPhoto().getTitle());
      }
    });

    // Rotate when mouse is dragged
    mouseBehavior = new MouseBehavior(this);
    if (useDefaultMouseBehavior)
      mouseBehavior.start();
    // Focus when current photo clicked
    focusBehavior = new FocusBehavior(this);
    if (useDefaultFocusBehavior) {
      focusBehavior.start();
    }

    // These are used to help make sure a photo click is not registered when
    // the mouse is dragged.
    addMouseDownHandler(new MouseDownHandler() {
      public void onMouseDown(MouseDownEvent event) {
        mouseMoved = false;
      }
    });
    addMouseMoveHandler(new MouseMoveHandler() {
      public void onMouseMove(MouseMoveEvent event) {
        mouseMoved = true;
      }
    });
    addMouseWheelHandler(new MouseWheelHandler(){
      public void onMouseWheel(MouseWheelEvent event){
        if(event.isNorth()){
          next();
        } else if(event.isSouth()){
          prev();
        }
      }
    });
   
  }
 
  public void setUseDefaultMouseBehavior(boolean useDefaultMouseBehavior) {
    if (useDefaultMouseBehavior) {
      mouseBehavior.start();
    } else {
      mouseBehavior.stop();
    }
  }
 
  public void setUseDefaultFocusBehavior(boolean useDefaultFocusBehavior) {
    if (useDefaultFocusBehavior) {
      focusBehavior.start();
    } else {
      focusBehavior.stop();
    }
  }

  /**
   * Lay out the images based on the current rotation.
   */
  public void placeImages() {
    ImageData imageData = new ImageData();

    for (int i = 0; i < carouselSize; i++) {
      placeImage(i, imageData);
    }
  }

  /**
   *
   * @param i - should not exceed carouselSize
   */
  private void placeImage(int i, ImageData imageData) {
    int containerWidth = imageData.getContainerWidth();
    int containerHeight = imageData.getContainerHeight();
    double boxHeight = imageData.getBoxHeight();
    double boxWidth = imageData.getBoxWidth();
    double xRadius = imageData.getxRadius();
    double yRadius = imageData.getyRadius();
    double spiralSpread = imageData.getSpiralSpread();
    double decimalOffset = imageData.getDecimalOffset();
    double angleOffset = imageData.getAngleOffset();
   
    CarouselImage image = images[i + preLoadSize];
    // The actual angle of the given image from the front.
    double angle = ((i * Math.PI) / 4) + angleOffset;
    // These are the simple x and y coordinates of the angel in a unit
    // circle. We flipped some of the signs and dimensions around
    // because our coordinate plane is a little turned around.
    double x = -Math.sin(angle);
    double y = -Math.cos(angle);
    // The factor by which to scale the image (i.e. make it smaller or
    // larger). This is based solely on the 'y' coordinate.
    double scale = Math.pow(2, y);
    // set the zindex so that images in the front appear on top of
    // images behind.
    int zindex = (int) (y * 10) + 10;
    image.getElement().getStyle().setProperty("zIndex", Integer.toString(zindex));

    // set the size of the image. The aspect ratio of the image is
    // maintained as the image is scaled so that it fits inside the
    // correct "box" dimensions.
    image.sizeToBounds((int) (scale * boxWidth), (int) (scale * boxHeight));

    // The x coordinate is obtained by simply scaling the unit-circle x
    // coordinate to fit the container.
    int xcoord = (int) Math.round((x * xRadius) + (containerWidth - image.getWidth()) / 2.0);
    // The y coordinate is similarly calculated, except that the spiral
    // factor is also added. Basically, the farther the image is around
    // the circle, the farther down it is shifted to give the spiral
    // effect.
    int ycoord = (int) Math.round((y * yRadius) + containerHeight - boxHeight - yRadius - image.getHeight()
        / 2.0 - Math.round(spiralSpread * (i - 4 - decimalOffset)));

    imagePanel.setWidgetPosition(image, xcoord, ycoord);

    // Finally, fade out the images that are at the very back. Make sure
    // the rest have full opacity.
    if (i == 0) {
      image.setOpacity(.5 - decimalOffset);
    } else if (i == carouselSize - 1) {
      image.setOpacity(.5 + decimalOffset);
    } else {
      image.setOpacity(1.0);
    }
  }

  /**
   * Set a list of photos to be displayed in the carousel.
   */
  public void setPhotos(List<Photo> photos) {
    this.photos = photos;
    currentPhotoIndex = Utils.modulus(currentPhotoIndex, photos.size());
    for (int i = 0; i < images.length; i++) {
      int pIndex = i - preLoadSize - 4 + currentPhotoIndex;
      pIndex = Utils.modulus(pIndex, photos.size());
      images[i].setUrl(photos.get(pIndex).getUrl());
    }
    PhotoToFrontEvent evt = new PhotoToFrontEvent();
    evt.setPhotoIndex(currentPhotoIndex);
    evt.setPhoto(photos.get(currentPhotoIndex));
    fireEvent(evt);
   
    final ImageData imageData = new ImageData();
    for (int i = 0; i < carouselSize; i++) {
      images[i + preLoadSize].getElement().getStyle().setProperty("display", "");
      //for visible images only
      final int iFinal = i;
      images[i + preLoadSize].addLoadHandler(new LoadHandler() {
        @Override
        public void onLoad(LoadEvent event) {
          placeImage(iFinal, imageData);
        }
      });
    }
   
  }

  private void setCurrentPhotoIndex(int photoIndex) {
    if (photoIndex == this.currentPhotoIndex){
      return;
    }
    photoIndex = Utils.modulus(photoIndex, photos.size());
    if (this.currentPhotoIndex == photoIndex) {
      return;
    } else {
      int shiftOffset = photoIndex - this.currentPhotoIndex;

      int halfPhotos = photos.size() / 2;
      if (shiftOffset < -halfPhotos) {
        shiftOffset += photos.size();
      } else if (shiftOffset > halfPhotos) {
        shiftOffset -= photos.size();
      }
      if (shiftOffset > 0) {
        // Next
        // Creating temp array of images to hold shifted images
        CarouselImage[] temps = new CarouselImage[shiftOffset];
        for (int j = 0; j < temps.length; j++) {
          temps[j] = images[j];
        }
        for (int i = 0; i < images.length - (shiftOffset); i++) {
          images[i] = images[i + (shiftOffset)];
        }
        // update from large array
        for (int k = 0; k < temps.length; k++) {
          int pIndex = photoIndex - 4 + carouselSize + preLoadSize - shiftOffset + k;
          pIndex = Utils.modulus(pIndex, photos.size());
          images[k + images.length - shiftOffset] = temps[k];
          temps[k].setUrl(photos.get(pIndex).getUrl());
        }
      } else if (shiftOffset < 0) {
        shiftOffset *= -1;
        // Prev
        CarouselImage[] temps = new CarouselImage[shiftOffset];
        for (int j = 0; j < temps.length; j++) {
          temps[j] = images[j + images.length - shiftOffset];
        }
        for (int i = images.length - 1; i >= shiftOffset; i--) {
          images[i] = images[i - shiftOffset];
        }
        // update from large array
        for (int k = 0; k < temps.length; k++) {
          int pIndex = photoIndex - 4 - preLoadSize + k;
          pIndex = Utils.modulus(pIndex, photos.size());
          images[k] = temps[k];
          temps[k].setUrl(photos.get(pIndex).getUrl());
        }
      }
      for (int i = 0; i < preLoadSize; i++) {
        images[i].getElement().getStyle().setProperty("display", "none");
        images[images.length - i - 1].getElement().getStyle().setProperty("display", "none");
      }
      for (int i = 0; i < carouselSize; i++) {
        images[i + preLoadSize].getElement().getStyle().setProperty("display", "");
      }
      this.currentPhotoIndex = photoIndex;
    }
  }

  /**
   * Acceleration determines how fast the carousel slows down or speeds up as
   * it rotates. A value of 1.0 will cause the carousel to rotate at a
   * constant speed. A value greater than 1.0 will cause it to speed up over
   * time. A value less than 1.0 will cause it to slow down.
   */
  public double getAcceleration() {
    return acceleration;
  }

  /**
   * Acceleration determines how fast the carousel slows down or speeds up as
   * it rotates. A value of 1.0 will cause the carousel to rotate at a
   * constant speed. A value greater than 1.0 will cause it to speed up over
   * time. A value less than 1.0 will cause it to slow down.
   */
  public void setAcceleration(double acceleration) {
    this.acceleration = acceleration;
  }

  private class RotationTimer extends Timer {
    public void run() {
      long currentTime = System.currentTimeMillis();
      int ticks = (int) (currentTime - lastTime);
      lastTime = currentTime;

      if (acceleration == 1.0) {
        setRotation(currentRotation + ticks * velocity);
      } else {
        double newVelocity = velocity * Math.pow(acceleration, ticks);
        if (newVelocity < velocityThreshold && newVelocity > -velocityThreshold) {
          setRotation(currentRotation
              + Utils.distanceFromStartingVelocity(velocity, acceleration, velocityThreshold));
          setVelocity(0.0);
        } else {
          setRotation(currentRotation + Utils.distanceForXTicks(velocity, acceleration, ticks));
          setVelocity(velocity * Math.pow(acceleration, ticks));
        }
      }
    }
  }

  /**
   * Set the speed for the carousel to rotate.
   */
  public void setVelocity(double velocity) {
    this.velocity = velocity;
    if (velocity > -velocityThreshold && velocity < velocityThreshold) {
      if (timerOn) {
        timer.cancel();
        timerOn = false;
      }
      this.velocity = 0;
    } else if (!timerOn) {
      lastTime = System.currentTimeMillis();
      timer.scheduleRepeating(20);
      timerOn = true;
      timer.run();
    }
  }
 
  public double getVelocity() {
    return velocity;
  }

  /**
   * The current rotational position of the carousel. Rotation is based on
   * indices in the photo list. So if the 3rd photo in the list is in the
   * front of the carousel, currentRotation will be 2.0 (indicies are 0
   * based).
   */
  public double getRotation() {
    return currentRotation;
  }

  /**
   * The current rotational position of the carousel. Rotation is based on
   * indices in the photo list. So if the 3rd photo in the list is in the
   * front of the carousel, currentRotation will be 2.0 (indicies are 0
   * based).
   */
  public void setRotation(double value) {
    int pi = getPhotoIndex();
    currentRotation = Utils.modulus(value, photos.size());
    setCurrentPhotoIndex((int) Math.round(currentRotation));
    if (pi != getPhotoIndex()) {
      PhotoToFrontEvent event = new PhotoToFrontEvent();
      event.setPhoto(photos.get(getPhotoIndex()));
      event.setPhotoIndex(getPhotoIndex());
      fireEvent(event);
    }
    placeImages();
  }

  /**
   * Start an animated rotation to the given position. Position is based on
   * indices in the photo list. So to rotate to the 3rd photo in the list,
   * pass 2.0 (indicies are 0 based) as the position.
   */
  public void rotateTo(double position) {
    if (acceleration >= 1.0) {
      setRotation(position);
      return;
    }
    double distance = Utils.modulus(position, photos.size()) - currentRotation;
    if (distance > photos.size() / 2) {
      distance -= photos.size();
    } else if (distance < photos.size() / -2) {
      distance += photos.size();
    }
    setVelocity(Utils.velocityForDistance(distance, acceleration, velocityThreshold));
  }

  /**
   * Start an animated rotation that will rotate the carousel by the given
   * distance. A distance of 1.0 is equivalent to moving by one photo in the
   * carousel, and 2.0 is two photos, etc.
   */
  public void rotateBy(double distance) {
    if (acceleration >= 1.0) {
      setRotation(currentRotation + distance);
      return;
    }
    setVelocity(Utils.velocityForDistance(distance, acceleration, velocityThreshold));
  }

  /**
   * Start an animated rotation to the previous photo.
   */
  public void prev() {
    rotateBy(- 1.0);
  }

  /**
   * Start an animated rotation to the next photo.
   */
  public void next() {
    rotateBy(+ 1.0);
  }

  /**
   * Returns the zero-based index in the photo list of the photo that is
   * currently in front.
   */
  public int getPhotoIndex() {
    return currentPhotoIndex;
  }
 
  public Photo getCurrentPhoto() {
    return photos.get(currentPhotoIndex);
  }

  /**
   * This handler is fired each time a photo rotates to the front, becoming
   * the current photo.
   */
  public HandlerRegistration addPhotoToFrontHandler(PhotoToFrontHandler handler) {
    return addHandler(handler, PhotoToFrontEvent.getType());
  }

  /**
   * This handler is fired when any photo in the carousel is clicked.
   */
  public HandlerRegistration addPhotoClickHandler(PhotoClickHandler handler) {
    return addHandler(handler, PhotoClickEvent.getType());
  }

  /**
   * This handler is fired when a photo is focused (i.e. it is clicked and
   * opens full-size).
   */
  public HandlerRegistration addPhotoFocusHandler(PhotoFocusHandler handler) {
    if (focusBehavior == null)
      return null;
    return focusBehavior.addPhotoFocusHandler(handler);
  }

  /**
   * This handler is fired when a photo is un-focused (i.e. when the expanded
   * photo box is closed).
   */
  public HandlerRegistration addPhotoUnfocusHandler(PhotoUnfocusHandler handler) {
    if (focusBehavior == null)
      return null;
    return focusBehavior.addPhotoUnfocusHandler(handler);
  }

  public HandlerRegistration addClickHandler(ClickHandler handler) {
    return imagePanel.addDomHandler(handler, ClickEvent.getType());
  }

  public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
    return imagePanel.addDomHandler(handler, MouseDownEvent.getType());
  }

  public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
    return imagePanel.addDomHandler(handler, MouseMoveEvent.getType());
  }

  public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
    return imagePanel.addDomHandler(handler, MouseUpEvent.getType());
  }
 
  public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler){
    return imagePanel.addDomHandler(handler, MouseWheelEvent.getType());
  }

  public List<Photo> getPhotos() {
    return photos;
  }

  /**
   * A class that represents necessary numeric data for carousel images
   * @author denisk
   *
   */
  private class ImageData {
    // The size of the container the holds the images.
    private int containerWidth;
    private int containerHeight;
    // The base dimensions for each image. Images are scaled from these base
    // dimensions.
    private double boxHeight;
    private double boxWidth;
    // The radius of the ellipse that the images are set around.
    private double xRadius;
    private double yRadius;
    // A factor for achieving the spiral affect. The greater this value, the
    // more pronounced the spiral effect.
    private double spiralSpread;
    // The fraction that the images are offset from a whole number rotation.
    // This value will be between -0.5 and 0.5.
    private double decimalOffset;
    // The angle (in radians) that the images are offset from the base
    // positions. Base positions are 0*, 45*, 90*, 135*, etc. This value
    // will be between -22.5* and 22.5*.
    private double angleOffset;
   
    public ImageData(){
      //Carousel.this. is just for clarity
      containerWidth = Carousel.this.imagePanel.getOffsetWidth();
      containerHeight = Carousel.this.imagePanel.getElement().getClientHeight();

      boxHeight = containerHeight * 3.0 / 8.0;
      boxWidth = boxHeight * 1.2;
      xRadius = (containerWidth - boxWidth) / 2.0;
      yRadius = boxHeight / 3.0;
      spiralSpread = yRadius * .5;

      decimalOffset = currentRotation - Math.round(currentRotation);
      angleOffset = -(decimalOffset * ((Math.PI) / 4));
    }

    public int getContainerWidth() {
      return containerWidth;
    }

    public int getContainerHeight() {
      return containerHeight;
    }

    public double getBoxHeight() {
      return boxHeight;
    }

    public double getBoxWidth() {
      return boxWidth;
    }

    public double getxRadius() {
      return xRadius;
    }

    public double getyRadius() {
      return yRadius;
    }

    public double getSpiralSpread() {
      return spiralSpread;
    }

    public double getDecimalOffset() {
      return decimalOffset;
    }

    public double getAngleOffset() {
      return angleOffset;
    }

    @Override
    public String toString() {
      return "ImageData [containerWidth=" + containerWidth
          + ", containerHeight=" + containerHeight + ", boxHeight="
          + boxHeight + ", boxWidth=" + boxWidth + ", xRadius="
          + xRadius + ", yRadius=" + yRadius + ", spiralSpread="
          + spiralSpread + ", decimalOffset=" + decimalOffset
          + ", angleOffset=" + angleOffset + "]";
    }
   
   
  }
}
TOP

Related Classes of com.denisk.appengine.nl.client.thirdparty.com.reveregroup.carousel.client.Carousel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.