2
votes

I'm currently working on a GWT project, in which I need to use a "carousel" widget. The carousel widget is supposed to display pieces of information and 2 arrows - when the user clicks on one of the arrow, the content is moved with an animation and replaced with new content.

I've been looking through the available widget libs, but the "carousel" widget does not seem to be that available. The only real candidate I found is the gwt-yui-carousel widget (see link below), but this seems to be an overload of ressources - though it does almost exactly what I need, but instead of displaying simple images, I'll have to display, in MVP terms, a view/presenter.

Here is the widget running : http://gwt-yui-carousel.googlecode.com/svn/trunk/www/com.gwtyuicarousel.javascriptload.JavaScriptLoad/javascriptload.html

(coming from here : http://code.google.com/p/gwt-yui-carousel/ ).

Is there a better carousel widget available that I would not know of ? Or should I extend an existing one to create the desired effect ? Would you recommend to use the gwt-yui-carousel (I don't think so) ? If there is no better option, do you think that it would be a good idea to create the widget myself ?

Note that I think that the key thing is, here, that I'll have to display presenter/views, which will fetch data in DataBase on arrow clicks and so on - so a customisation of an existing widget would be required, or the chosen widget should be able to display a list of GWT Widgets.

Again I don't think that I can use one of the existing usual carousel widgets, since those are not "gwt-oriented" and could not support view/presenters and all this gwt stuff ;)

Any answer would be greatly appreciated :)

Best regards,

Nils

3

3 Answers

1
votes

Don't know of any available implementation but you can write this widget in no time.

Create a widget holding a list of URLs (your images):

CarouselWidget(ArrayList<String> urls) extends HorizontalPanel

then add to the panel two buttons and the desired images to show.

Left button / image / image / image ... / image / Right button

The images are feed from your url list and when the left or right button is clicked you move the starting index -- or ++ ... and refresh the image view.

From the starting index you calculate the "real" index in your array.

1
votes

Another home brewed solution can be based on GWT LayoutPanel. This will allow to show animation of the scrolling as LayoutPanel implements the AnimatedLayout interface.

   public class CarouselPanel extends LayoutPanel {

    int itsCurrentWidget = 0;
    private ArrayList<Widget> itsWidgets;
    private Button itsLeftButton;
    private Button itsRightButton;

addToCarousel(Widget widget) will add the widget to the widget list but not to the panel. The actual widgets in the panel are the ones that should be displayed.

You can control the layout of the displayed center widget by:

    private void setCenter(Widget widget, boolean newWidget) {
    if (widget != null) {
        if (newWidget)
            add(widget);
        setWidgetLeftWidth(widget, 10, Unit.PCT, 80, Unit.PCT);   
        setWidgetTopHeight(widget, 10, Unit.PCT, 80, Unit.PCT);
        widget.removeStyleName("sideCarousel");
        widget.setStylePrimaryName("centerCarousel");
    }       
}

and the right widget by:

    private void setRight(Widget widget, boolean newWidget) {
    if (widget != null) {
        if (newWidget)
            add(widget);
        setWidgetLeftWidth(widget, 50, Unit.PCT, 45, Unit.PCT);  
        setWidgetTopHeight(widget, 20, Unit.PCT, 60, Unit.PCT);
        widget.removeStyleName("centerCarousel");
        widget.setStylePrimaryName("sideCarousel");
        if (itsRightHandler != null)
            itsRightHandler.removeHandler();
        itsRightHandler = widget.addDomHandler(new ClickHandler() {
            public void onClick(final ClickEvent event) {
                scrollRight();
            }
        }, ClickEvent.getType());
    }
}

You can also use the right (or left) widget as scrolling buttons by adding click listener to them.

and the scrolling method can look like this:

    public void scrollRight() {
    if (itsCurrentWidget >= getWidgetCountInCarousel()-1)
        return;
    if (itsCurrentWidget > 0) {
        Widget hideWidget = getWidgetInCarousel(itsCurrentWidget-1);
        remove(hideWidget);
    }
    Widget leftWidget = getWidgetInCarousel(itsCurrentWidget);
    Widget centerWidget = getWidgetInCarousel(++itsCurrentWidget);
    Widget rightWidget = null;
    if (itsCurrentWidget+1 < getWidgetCountInCarousel()) {
        rightWidget = getWidgetInCarousel(itsCurrentWidget+1);
    }
    setLeft(leftWidget, false);
    setRight(rightWidget, true);
    setCenter(centerWidget, false);
    animate(500);
}

Note the animate method at the end to move the widgets in a smooth way.

Dont forget to define the CSS rules to control the z-index of the center widget:

 .sideCarousel {
    z-index: 0;
}

.centerCarousel {
    z-index: 1;
}

I hope that it helps.

0
votes

This is a carousel implementation, it uses gwt-query and gwt-queryui. It can be used horizontally as well as vertically. The purpose of gwt-query usage is to enable animations as carousel moves. Additionally, it suports spiral behavior. I've not added java-docs to the code, but as long as you read, you will find explanatory comments.

Hope this would be useful.

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
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.FlexTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.query.client.Function;
import java.util.ArrayList;
import java.util.List;
import static com.google.gwt.query.client.GQuery.$;

/** 
GWTCrousel implementation. 
    @author: Andrés82 
*/
public class GWTCarousel extends Composite {

    /*
        Public constants
    */
public static final int HORIZONTAL = 0; // used for orientation
public static final int VERTICAL = 1;

/*
        Constructor
    */
public GWTCarousel () {

            // inits the widget
    mainPanel = new FlexTable ();
    initWidget(mainPanel);

            // structure
    viewport = new AbsolutePanel ();
    widgetsTable = new FlexTable ();
    viewport.add(widgetsTable);
    viewport.setWidgetPosition(widgetsTable,0,0);

    // default behavior (not spiral, not animations enabled)
    spiral = false; animationEnabled = false;
    nextRow = 0; nextCol = 0; numberOfWidgetsToShow = 0;
    movement = 0; animationTime = DEFAULT_ANIMATION_TIME;
    widgetsList = new ArrayList<Widget> ();

    // basics styling
            $(viewport).css("overflow","hidden");
    widgetsTable.setCellSpacing(SPACING);
    mainPanel.setCellSpacing(SPACING);
}

    // sets the carousel orientation
public void setOrientation (int orientation) {
    switch (orientation) {
        case HORIZONTAL:
            setHorizontalOrientation ();
            break;
        case VERTICAL:
            setVerticalOrientation ();
            break;
        default:;
    }
    previous.addClickHandler(getpreviousClickHandler());
    next.addClickHandler(getnextClickHandler());

}

    /*
        Getters and setters
    */

public int getOrientation () { return orientation; }

public void setSpiral(boolean spiral) { this.spiral = spiral; }

public boolean isSpiral() { return spiral; }

public T2VoiceButton getprevious() { return previous; }

public T2VoiceButton getnext() { return next; }

public int getNumberOfWidgetsToShow() { return numberOfWidgetsToShow; }

    // sets the number of widgets to show in the viewport
public void setNumberOfWidgetsToShow(int numberOfWidgetsToShow) { this.numberOfWidgetsToShow = numberOfWidgetsToShow; }

public void setAnimationEnabled(boolean animationEnabled) { this.animationEnabled = animationEnabled; }

public boolean isAnimationEnabled() { return animationEnabled; }

public double getWidgetWidth() { return widgetWidth; }

public void setWidgetWidth(double widgetWidth) {
    this.widgetWidth = widgetWidth;
    double viewportWidth = orientation == HORIZONTAL ? widgetWidth * numberOfWidgetsToShow + (numberOfWidgetsToShow + 1) * SPACING : widgetWidth + 2 * SPACING;
    viewport.setWidth(viewportWidth + "px");
}

public double getWidgetHeight() { return widgetHeight; }

public void setWidgetHeight(double widgetHeight) {
    this.widgetHeight = widgetHeight;
    double viewportHeight = orientation == VERTICAL ? widgetHeight * numberOfWidgetsToShow + (numberOfWidgetsToShow + 1) * SPACING : widgetHeight + 2 * SPACING; 
    viewport.setHeight(viewportHeight + "px");
}

public void setanimationTime(int animationTime) { this.animationTime = animationTime; }

public int getanimationTime() { return animationTime; }

    /*
        Other methods
    */

public void addWidget (Widget widgetToAdd) {
    switch (orientation) {
        case HORIZONTAL:
            addWidgetHorizontally(widgetToAdd);
            break;
        case VERTICAL:
            addWidgetVertically(widgetToAdd);
            break;
        default:;
    }

}

    /*
        Fields and constants
    */

    // constants
private final int SPACING = 5; 
private final int DEFAULT_ANIMATION_TIME = 300; // defined in millis 

// structure
private Button previous;
private Button next;
private AbsolutePanel viewport;
private FlexTable widgetsTable;
private FlexTable mainPanel;

// control variables
private boolean spiral;
private boolean animationEnabled;
private long animationTime; // defined in millis
private double widgetWidth;
private double widgetHeight;
private int orientation;
private int numberOfWidgetsToShow;
private int nextRow;
private int nextCol;
private int movement;
private List<Widget> widgetsList;

    /*
        Private methods
    */  

private void addWidgetVertically(Widget widgetToAdd) {
    nextRow++;
    widgetsList.add(widgetToAdd);
    widgetsTable.setWidget(nextRow, nextCol, widgetToAdd);
    widgetsTable.getCellFormatter().setAlignment(nextRow, nextCol, HasHorizontalAlignment.ALIGN_CENTER, HasVerticalAlignment.ALIGN_MIDDLE);
    if (spiral && nextRow > numberOfWidgetsToShow) {
        shiftDown();
        $(widgetsTable).css("top", -(widgetHeight + SPACING) + "px");
    }
}

private void addWidgetHorizontally(Widget widgetToAdd) {
    nextCol++;
    widgetsList.add(widgetToAdd);
    widgetsTable.setWidget(nextRow, nextCol, widgetToAdd);
    widgetsTable.getCellFormatter().setAlignment(nextRow, nextCol, HasHorizontalAlignment.ALIGN_CENTER, HasVerticalAlignment.ALIGN_MIDDLE);
    if (spiral && nextCol > numberOfWidgetsToShow) {
        shiftRight();
        $(widgetsTable).css("left", -(widgetWidth + SPACING) + "px");
    }
}

private void setHorizontalOrientation () {
    orientation = HORIZONTAL;
    // botones
    previous = new T2VoiceButton (null,null,null);
    next = new T2VoiceButton (null,null,null);
    mainPanel.setWidget(0, 0, previous);
    mainPanel.setWidget(0, 1, viewport);
    mainPanel.setWidget(0, 2, next);
    mainPanel.getFlexCellFormatter().setAlignment(0, 0, HasHorizontalAlignment.ALIGN_CENTER, HasVerticalAlignment.ALIGN_MIDDLE);
    mainPanel.getFlexCellFormatter().setAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER, HasVerticalAlignment.ALIGN_MIDDLE);
    mainPanel.getFlexCellFormatter().setAlignment(0, 2, HasHorizontalAlignment.ALIGN_CENTER, HasVerticalAlignment.ALIGN_MIDDLE);
}

private void setVerticalOrientation () {
    orientation = VERTICAL;
    // botones
    previous = new T2VoiceButton (null,null,null);
    next = new T2VoiceButton (null,null,null);
    mainPanel.setWidget(0, 0, previous);
    mainPanel.setWidget(1, 0, viewport);
    mainPanel.setWidget(2, 0, next);
    mainPanel.getFlexCellFormatter().setAlignment(0, 0, HasHorizontalAlignment.ALIGN_CENTER, HasVerticalAlignment.ALIGN_MIDDLE);
    mainPanel.getFlexCellFormatter().setAlignment(1, 0, HasHorizontalAlignment.ALIGN_CENTER, HasVerticalAlignment.ALIGN_MIDDLE);
    mainPanel.getFlexCellFormatter().setAlignment(2, 0, HasHorizontalAlignment.ALIGN_CENTER, HasVerticalAlignment.ALIGN_MIDDLE);
}

private ClickHandler getpreviousClickHandler () {
    switch (orientation) {
        case HORIZONTAL:
            return new ClickHandler () {
                @Override
                public void onClick(ClickEvent event) {
                    moveLeft();
                }
            };
        case VERTICAL:
            return new ClickHandler () {
                @Override
                public void onClick(ClickEvent event) {
                    moveUp();
                }
            };
        default: 
            return null;
    }
}

private ClickHandler getnextClickHandler () {
    switch (orientation) {
        case HORIZONTAL:
            return new ClickHandler () {
                @Override
                public void onClick(ClickEvent event) {
                    moveRight();
                }
            };
        case VERTICAL:
            return new ClickHandler () {
                @Override
                public void onClick(ClickEvent event) {
                    moveDown();
                }
            };
        default: 
            return null;
    }
}

private void moveLeft() {
    if (!spiral && movement > (numberOfWidgetsToShow - nextCol - 1)) {
        movement--;
        $(widgetsTable).animate("left: -=" + (widgetWidth + SPACING), animationEnabled ? animationTime : 0);
    } else if (spiral) {    
        $(widgetsTable).animate("left: -=" + (widgetWidth + SPACING), animationEnabled ? animationTime : 0, new Function () {
            @Override
            public void f () {
                shiftLeft();
                $(widgetsTable).css("left", -(widgetWidth + SPACING + 1) + "px");
            }
        });
    }
}

private void shiftLeft() {
    Widget widgetToMove = widgetsList.get(0);
    widgetsList.remove(0);
    widgetsList.add(widgetToMove);
    for (int column = 0; column < nextCol; column++) {
        widgetsTable.setWidget(0, column, widgetsList.get(column));
    }
}

private void moveRight() {
    if (!spiral && movement < 1) {
        movement++;
        $(widgetsTable).animate("left: +=" + (widgetWidth + SPACING), animationEnabled ? animationTime : 0);
    } else if (spiral) {
        $(widgetsTable).animate("left: +=" + (widgetWidth + SPACING), animationEnabled ? animationTime : 0, new Function () {
            @Override
            public void f () {
                shiftRight();
                $(widgetsTable).css("left", -(widgetWidth + SPACING + 1) + "px");
            }
        });
    }
}

private void shiftRight() {
    Widget widgetToMove = widgetsList.get(nextCol - 1);
    widgetsList.remove(nextCol - 1);
    widgetsList.add(0, widgetToMove);
    for (int column = 0; column < nextCol; column++) {
        widgetsTable.setWidget(0, column, widgetsList.get(column));
    }
}

private void moveUp() {
    if (!spiral && movement < (nextRow - numberOfWidgetsToShow)) {
        movement++;
        $(widgetsTable).animate("top: -=" + (widgetHeight + SPACING), animationEnabled ? animationTime : 0);
    } else if (spiral) {
        $(widgetsTable).animate("top: -=" + (widgetHeight + SPACING), animationEnabled ? animationTime : 0, new Function () {
            @Override
            public void f () {
                shiftUp();
                $(widgetsTable).css("top", -(widgetHeight + SPACING + 1) + "px");
            }
        });
    }
}

private void shiftUp () {
    Widget widgetToMove = widgetsList.get(0);
    widgetsList.remove(0);
    widgetsList.add(widgetToMove);
    for (int row = 0; row < nextRow; row++) {
        widgetsTable.setWidget(row, 0, widgetsList.get(row));
    }
}

private void moveDown() {
    if (!spiral && movement > 0) {
        movement--;
        $(widgetsTable).animate("top: +=" + (widgetHeight + SPACING), animationEnabled ? animationTime : 0);
    } else if (spiral) {
        $(widgetsTable).animate("top: +=" + (widgetHeight + SPACING), animationEnabled ? animationTime : 0, new Function () {
            @Override
            public void f () {
                shiftDown();
                $(widgetsTable).css("top", -(widgetHeight + SPACING + 1) + "px");
            }
        });
    }
}

private void shiftDown () {
    Widget widgetToMove = widgetsList.get(nextRow - 1);
    widgetsList.remove(nextRow - 1);
    widgetsList.add(0, widgetToMove);
    for (int row = 0; row < nextRow; row++) {
        widgetsTable.setWidget(row, 0, widgetsList.get(row));
    }
}

}

USAGE EXAMPLE

// shows 5 widgets in the viewport
GWTCarousel horizontalSpiralCarousel = new GWTCarousel ();
horizontalSpiralCarousel.setAnimationEnabled(true);
horizontalSpiralCarousel.setSpiral(true);
horizontalSpiralCarousel.setMillisToMove(200);
horizontalSpiralCarousel.setOrientation(T2VoiceCarousel.HORIZONTAL);
horizontalSpiralCarousel.setNumberOfWidgetsToShow(5);
horizontalSpiralCarousel.setWidgetWidth(100.0);
horizontalSpiralCarousel.setWidgetHeight(100.0);

// adding widgets to carousel
HorizontalPanel maroonTile = new HorizontalPanel ();
$(maroonTile).css("background-color","maroon"); 
$(maroonTile).css("width", 100.0 + "px");
$(maroonTile).css("height", 100.0 + "px");
HorizontalPanel greenTile = new HorizontalPanel ();
$(greenTile).css("background-color","green");
$(greenTile).css("width", 100.0 + "px");
$(greenTile).css("height", 100.0 + "px");
HorizontalPanel redTile = new HorizontalPanel ();
$(redTile).css("background-color","red");
$(redTile).css("width", 100 + "px");
$(redTile).css("height", 100 + "px");
HorizontalPanel yellowTile = new HorizontalPanel ();
$(yellowTile).css("background-color","yellow");
$(yellowTile).css("width", 100.0 + "px");
$(yellowTile).css("height", 100.0 + "px");
HorizontalPanel blueTile = new HorizontalPanel ();
$(blueTile).css("background-color","blue");
$(blueTile).css("width", 100.0 + "px");
$(blueTile).css("height", 100.0 + "px");

horizontalCarousel.addWidget(maroonTile);
horizontalCarousel.addWidget(greenTile);
horizontalCarousel.addWidget(redTile);
horizontalCarousel.addWidget(blueTile);
horizontalCarousel.addWidget(yellowTile);