image-previewer-widget/src/main/java/org/gcube/portlets/widgets/imagepreviewerwidget/client/ui/Carousel.java

466 lines
12 KiB
Java

package org.gcube.portlets.widgets.imagepreviewerwidget.client.ui;
import java.util.ArrayList;
import java.util.List;
import org.gcube.portlets.widgets.imagepreviewerwidget.client.CarouselInterface;
import org.gcube.portlets.widgets.imagepreviewerwidget.client.EnhancedImage;
import org.gcube.portlets.widgets.imagepreviewerwidget.client.ImageService;
import org.gcube.portlets.widgets.imagepreviewerwidget.client.ImageServiceAsync;
import org.gcube.portlets.widgets.imagepreviewerwidget.client.resources.Resources;
import org.gcube.portlets.widgets.imagepreviewerwidget.shared.Orientation;
import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.Image;
import com.github.gwtbootstrap.client.ui.Modal;
import com.github.gwtbootstrap.client.ui.constants.Device;
import com.github.gwtbootstrap.client.ui.constants.IconSize;
import com.github.gwtbootstrap.client.ui.constants.IconType;
import com.github.gwtbootstrap.client.ui.resources.ButtonSize;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;
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.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* A carousel for image/file previews.
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*
*/
public class Carousel extends Composite implements CarouselInterface {
private static CarouselUiBinder uiBinder = GWT
.create(CarouselUiBinder.class);
interface CarouselUiBinder extends UiBinder<Widget, Carousel> {
}
private final ImageServiceAsync imageServices = GWT.create(ImageService.class);
@UiField
Modal mainModalPanel;
@UiField
Button prevButton;
@UiField
Button nextButton;
@UiField
Button downloadButton;
@UiField
Button closeButton;
@UiField
Button downloadButtonSmart;
@UiField
Button closeButtonSmart;
@UiField
Image shownImage;
@UiField
Image loadingImage;
@UiField
HorizontalPanel commands;
// list of enhanced images to show
private List<EnhancedImage> listOfAttachmentsToShow;
// index of the image shown
private int currentPreviewPosition;
// other resources
private Resources resources = GWT.create(Resources.class);
/**
* Build a carousel to show EnhancedImages.
* @param imagesToShow
*/
public Carousel() {
initWidget(uiBinder.createAndBindUi(this));
listOfAttachmentsToShow = new ArrayList<>();
// add custom styles to gwt-bootstrap-modal (just once)
mainModalPanel.addStyleName("modal-custom");
((Element)mainModalPanel.getElement().getChildNodes().getItem(1)).addClassName("modal-body-custom");
// set vertical alignment
commands.setCellVerticalAlignment(nextButton, VerticalPanel.ALIGN_MIDDLE);
commands.setCellVerticalAlignment(prevButton, VerticalPanel.ALIGN_MIDDLE);
// set alignment of the horizontal panel's children
commands.setCellHorizontalAlignment(closeButton, HorizontalPanel.ALIGN_CENTER);
commands.setCellHorizontalAlignment(downloadButton, HorizontalPanel.ALIGN_CENTER);
commands.setCellHorizontalAlignment(closeButtonSmart, HorizontalPanel.ALIGN_CENTER);
commands.setCellHorizontalAlignment(downloadButtonSmart, HorizontalPanel.ALIGN_CENTER);
commands.setCellHorizontalAlignment(prevButton, HorizontalPanel.ALIGN_LEFT);
commands.setCellHorizontalAlignment(nextButton, HorizontalPanel.ALIGN_RIGHT);
// set sizes
downloadButton.setWidth("90px");
closeButton.setWidth("90px");
downloadButtonSmart.setWidth("15px");
closeButtonSmart.setWidth("15px");
closeButtonSmart.setSize(ButtonSize.LARGE);
// set icons
downloadButton.setIcon(IconType.DOWNLOAD_ALT);
closeButton.setIcon(IconType.COLLAPSE);
downloadButtonSmart.setIcon(IconType.DOWNLOAD_ALT);
closeButtonSmart.setIcon(IconType.COLLAPSE);
prevButton.setIcon(IconType.CHEVRON_LEFT);
prevButton.setSize(ButtonSize.LARGE);
nextButton.setIcon(IconType.CHEVRON_RIGHT);
nextButton.setSize(ButtonSize.LARGE);
// set icons'size
prevButton.setIconSize(IconSize.LARGE);
nextButton.setIconSize(IconSize.LARGE);
// choose devices
closeButtonSmart.setShowOn(Device.PHONE);
downloadButtonSmart.setShowOn(Device.PHONE);
downloadButton.setShowOn(Device.DESKTOP);
closeButton.setShowOn(Device.DESKTOP);
downloadButton.setHideOn(Device.PHONE);
closeButton.setHideOn(Device.PHONE);
// add some other css style
downloadButton.addStyleName("buttons-style");
closeButton.addStyleName("buttons-style");
downloadButtonSmart.addStyleName("buttons-style");
closeButtonSmart.addStyleName("buttons-style");
//on user click on the image, go on
shownImage.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if(nextButton.isVisible())
nextButton.click();
}
});
// set url of the loading image
loadingImage.setResource(resources.loadingImage());
}
@UiHandler("closeButton")
public void hideOnClick(ClickEvent e){
closeButtonClickHanderBody();
}
@UiHandler("closeButtonSmart")
public void hideOnClickSmart(ClickEvent e){
closeButtonClickHanderBody();
}
/**
* Close button click handler body
*/
private void closeButtonClickHanderBody(){
mainModalPanel.hide();
}
@UiHandler("downloadButton")
/**
* When the user pushes this button, try to download the file.
* @param e
*/
public void downloadOnClick(ClickEvent e){
downloadButtonClickHanderBody();
}
@UiHandler("downloadButtonSmart")
/**
* When the user pushes this button, try to download the file.
* @param e
*/
public void downloadOnClickSmart(ClickEvent e){
downloadButtonClickHanderBody();
}
/**
* Download button click handler body
*/
public void downloadButtonClickHanderBody(){
String downloadUrl = listOfAttachmentsToShow.get(currentPreviewPosition).getDownloadUrl();
if(downloadUrl != null){
Window.open(downloadUrl, "_blank", "");
}
}
@Override
public void onClickPrev() {
// evaluate prev index
currentPreviewPosition = currentPreviewPosition == 0 ? listOfAttachmentsToShow.size() - 1 : currentPreviewPosition - 1;
// show the image
showImage(currentPreviewPosition);
}
@Override
public void onClickNext() {
// evaluate next index
currentPreviewPosition = currentPreviewPosition == listOfAttachmentsToShow.size() -1 ? 0 : currentPreviewPosition + 1;
// show the image
showImage(currentPreviewPosition);
}
@UiHandler("prevButton")
/**
* Show the previous image, if any.
* @param e
*/
public void onClickPrev(ClickEvent e) {
GWT.log("onClickPrev classic");
onClickPrev();
}
@UiHandler("nextButton")
/**
* Show the next image, if any.
* @param e
*/
public void onClickNext(ClickEvent e){
onClickNext();
}
/**
* Used to show this carousel (starting from the initial image).
*/
public void show(){
mainModalPanel.show();
// take the first image
currentPreviewPosition = 0;
// show the image
showImage(currentPreviewPosition);
}
/**
* Used to show a specific image of this carousel.
*/
public void show(EnhancedImage image){
GWT.log("image=" + image.getDownloadUrl());
GWT.log("image=" + image.getThumbnailUrl());
// evaluate where this image is
int index = evaluateImagePosition(image);
GWT.log("index=" + index);
if(index == -1) {
listOfAttachmentsToShow.clear();
listOfAttachmentsToShow.add(image);
index = 0;
showImage(index);
}
else {
// take the first object
currentPreviewPosition = index;
// show the image
showImage(currentPreviewPosition);
}
// show the panel
mainModalPanel.show();
}
/**
* Retrieve the index of such image.
* @param image
* @return -1 if no image matches
*/
private int evaluateImagePosition(EnhancedImage image) {
for(int index = 0; index < listOfAttachmentsToShow.size(); index++){
if(listOfAttachmentsToShow.get(index).equals(image))
return index;
}
return -1;
}
/**
* Change the set of images to show.
* @param imagesToShow
*/
public void updateImages(List<EnhancedImage> imagesToShow){
listOfAttachmentsToShow = imagesToShow;
}
/**
* use showArrows(boolean visible)
*/
@Deprecated
public void hideArrows() {
nextButton.setVisible(false);
prevButton.setVisible(false);
}
/**
* Hide/Show Previous and Next arrows of the carousel.
* @param visible the visibility of the command arrows
*/
public void showArrows(boolean visible) {
nextButton.setVisible(visible);
prevButton.setVisible(visible);
}
/**
* Show image function.
* @param index the index of the image to show
*/
private void showImage(int index){
showLoader();
final EnhancedImage imageToShow = listOfAttachmentsToShow.get(index);
final String url = imageToShow.getImageUrl();
// when image is downloaded ...
shownImage.addLoadHandler(new LoadHandler() {
@Override
public void onLoad(LoadEvent event) {
// call only if undefined
if(imageToShow.getOrientation().equals(Orientation.UNDEFINED)){
imageServices.getImageOrientation(url, new AsyncCallback<Orientation>() {
@Override
public void onSuccess(Orientation result) {
imageToShow.setOrientation(result);
setOrientation(imageToShow, result);
}
@Override
public void onFailure(Throwable caught) {
imageToShow.setOrientation(Orientation.DO_NOT_ROTATE);
setOrientation(imageToShow, Orientation.DO_NOT_ROTATE);
}
});
}else{
setOrientation(imageToShow, imageToShow.getOrientation());
}
}
});
// fetch the image from the url
shownImage.setUrl(url);
// change image tooltip
shownImage.setTitle(imageToShow.getToolTipToShow());
// change the title to the modal
String shownTitle = imageToShow.getTitleToShow().length() > 80 ?
imageToShow.getTitleToShow().substring(0, 80) + "..." :
imageToShow.getTitleToShow();
mainModalPanel.setTitle(shownTitle);
// to set the tooltip we have to lookup the title in the header (it's a <h3> element)
NodeList<Element> list = mainModalPanel.getElement().getElementsByTagName("h3");
list.getItem(0).setTitle(imageToShow.getTitleToShow());
// change header style
((Element)mainModalPanel.getElement().getChildNodes().getItem(0)).addClassName("modal-header-custom");
}
/**
* Show image loader
*/
protected void showLoader() {
loadingImage.setVisible(true);
shownImage.setVisible(false);
}
/**
* Remove image loader
*/
protected void removeLoader() {
shownImage.setVisible(true);
loadingImage.setVisible(false);
}
/**
* Set the orientation
* @param img
* @param o
*/
private void setOrientation(EnhancedImage img, Orientation o){
// remove all the possible secondary styles..
shownImage.removeStyleName("rotate-0");
shownImage.removeStyleName("rotate-90");
shownImage.removeStyleName("rotate-180");
shownImage.removeStyleName("rotate-270");
switch(o){
case ROTATE_90: shownImage.addStyleName("rotate-90");
break;
case ROTATE_180: shownImage.addStyleName("rotate-180");
break;
case ROTATE_270: shownImage.addStyleName("rotate-270");
break;
default: shownImage.addStyleName("rotate-0");
}
// few ms are needed to remove/add the style, after that we remove the loading image
Timer t = new Timer() {
@Override
public void run() {
removeLoader();
}
};
t.schedule(500);
}
}