com.cgxlib.core.component.carousel.Carousel.java Source code

Java tutorial

Introduction

Here is the source code for com.cgxlib.core.component.carousel.Carousel.java

Source

package com.cgxlib.core.component.carousel;

/*
 * #%L
 * CGXlib
 * %%
 * Copyright (C) 2016 CGXlib (http://www.cgxlib.com)
 * %%
 * 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.
 * #L%
 */

import com.cgxlib.core.*;
import com.cgxlib.xq.client.Function;
import com.cgxlib.xq.client.XQ;
import com.cgxlib.xq.client.js.JsUtils;
import com.cgxlib.xq.client.plugins.events.EventsListener;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;

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

/**
 *
 */
public class Carousel extends CGXComponentBase<CarouselView.ViewHandler> {

    public static final Class<Carousel> CGX = CGXlib.registerPlugin(Carousel.class,
            new CGXPlugin<Carousel, CarouselView.ViewHandler>() {
                @Override
                public List<HTML5DataAPILoader> autoLoaders() {
                    HTML5DataAPILoader selector = GWT.create(CarouselHTML5Loader.class);

                    List<HTML5DataAPILoader> selectors = new ArrayList<HTML5DataAPILoader>();
                    selectors.add(selector);

                    return selectors;
                }

                @Override
                public Carousel init(CGXComponentBase xq,
                        ViewHandlerFactory<? extends CarouselView.ViewHandler> factory) {
                    return createOrGetData(xq, factory.make());
                }

                @Override
                public Carousel init(XQ xq) {
                    return createOrGetData(xq, null);
                }
            });

    protected XQ $indicators;
    protected CarouselOptions options;
    protected boolean paused = false;
    protected boolean sliding = false;
    protected Timer interval;
    protected XQ $active;
    protected XQ $items;
    protected CarouselView.ViewHandler viewHandler;
    protected CarouselView view;

    public Carousel() {
        this(new CarouselBSView());
    }

    public Carousel(CarouselView view) {
        this(view.render(null));
    }

    public Carousel(CarouselView view, CarouselView.ViewHandler viewHandler) {
        this(view.render(null), viewHandler);
    }

    protected Carousel(XQ xq) {
        this(xq, new CarouselBSViewHandler());
    }

    protected Carousel(XQ xq, CarouselView.ViewHandler viewHandler) {
        super(xq, viewHandler);
    }

    protected static Carousel createOrGetData(XQ xq, CarouselView.ViewHandler viewHandler) {
        String name = "cgx.carousel";
        Carousel car = xq.data(name);
        if (car == null) {
            if (viewHandler == null) {
                car = new Carousel(xq);
            } else {
                car = new Carousel(xq, viewHandler);
            }
            xq.data(name, car);
        }

        return car;
    }

    protected static XQ getTarget(XQ $this) {
        String href = $this.attr("data-target");
        ;
        if (href == null || href.length() < 1) {
            href = $this.attr("href");
        }
        XQ $target = $(href);

        return $target;
    }

    @Override
    protected void apply(XQ xq, CarouselView.ViewHandler viewHandler) {
        viewHandler.init(this);
        this.viewHandler = viewHandler;
        $indicators = viewHandler.indicators();
        transitionDuration = 600;
    }

    public Carousel carousel() {
        return carousel(new CarouselOptions());
    }

    public Carousel carousel(CarouselOptions options) {
        this.options = options;

        if (options.keyboard()) {
            this.on("keydown.cgx.carousel", new Function() {
                @Override
                public boolean f(Event e) {
                    return Carousel.this.carouselKeydown(e);
                }
            });
        }

        if ("hover".equals(options.pause()) && !document.getDocumentElement().hasAttribute("ontouchstart")) {
            this.on("mouseenter.cgx.carousel", new Function() {
                @Override
                public boolean f(Event e) {
                    Carousel.this.pause(true);
                    return true;
                }
            }).on("mouseleave.cgx.carousel", new Function() {
                @Override
                public boolean f(Event e) {
                    Carousel.this.cycle(true);
                    return true;
                }
            });
        }

        cycle(false);

        return this;
    }

    protected void slide(String action) {
        if ("next".equals(action)) {
            carouselNext();
        } else if ("prev".equals(action)) {
            carouselPrev();
        }
    }

    public Carousel carouselGoTo(final int pos) {
        final Carousel that = this;
        int activeIndex = getItemIndex($active = viewHandler.active());

        if (pos > ($items.length() - 1) || pos < 0) {
            return this;
        }

        if (sliding) {
            this.one(EventsListener.BITLESS, "slid.cgx.carousel", new Function() {
                @Override
                public void f() {
                    that.carouselGoTo(pos);
                }
            });
            return that;
        }
        if (activeIndex == pos) {
            this.pause(false);

            this.cycle(false);
        }

        slide(pos > activeIndex ? "next" : "prev", $items.eq(pos));

        return this;
    }

    public Carousel carouselCycle() {
        cycle(false);

        return this;
    }

    protected void cycle(boolean e) {
        if (!e) {
            this.paused = false;
        }

        if (interval != null) {
            interval.cancel();
        }
        if (options.interval() > 0 && !paused) {
            if (interval == null) {
                interval = new Timer() {
                    @Override
                    public void run() {
                        Carousel.this.carouselNext();
                    }
                };
            }
            interval.scheduleRepeating(options.interval());
        }

    }

    public Carousel carouselNext() {
        if (!sliding) {
            slide("next", null);
        }

        return this;
    }

    public Carousel carouselPause() {
        pause(false);
        return this;
    }

    protected void pause(boolean e) {
        if (!e) {
            paused = true;
        }

        if (viewHandler.isTransitioning()) {
            this.trigger(browserTransitionEnd);
            this.cycle(true);
        }
        if (interval != null) {
            interval.cancel();
        }

    }

    public Carousel carouselPrev() {
        if (!sliding) {
            slide("prev", null);
        }

        return this;
    }

    protected boolean carouselKeydown(Event e) {
        boolean inputOrTextArea = viewHandler.inputOrTextArea(e);

        if (inputOrTextArea) {
            return true;
        }
        int which = CGXHelper.which(e);
        switch (which) {
        case 37:
            this.carouselPrev();
            break;
        case 39:
            this.carouselNext();
            break;
        default:
            return true;
        }

        return false;
    }

    protected int getItemIndex(XQ item) {
        $items = viewHandler.getItems(item);
        XQ source = item == null ? $active : item;

        return viewHandler.getItemIndex($items, source);
    }

    protected XQ getItemForDirection(String direction, XQ active) {
        int activeIndex = getItemIndex(active);
        boolean willWrap = ("prev".equals(direction) && activeIndex == 0)
                || ("next".equals(direction) && activeIndex == ($items.length() - 1));
        if (willWrap && !this.options.wrap()) {
            return active;
        }
        int delta = "prev".equals(direction) ? -1 : 1;
        int itemIndex = (activeIndex + delta) % $items.length();
        return $items.eq(itemIndex);
    }

    protected boolean slide(final String type, XQ next) {
        final XQ $active = viewHandler.active();
        XQ $next = next != null ? next : this.getItemForDirection(type, $active);
        boolean isCycling = interval != null;
        final String direction = "next".equals(type) ? "left" : "right";
        final Carousel that = this;

        if (viewHandler.isActive($next)) {
            return (sliding = false);
        }

        Element relatedTarget = $next.get(0);
        NativeEvent slideEvent = CGXHelper.createNativeEvent("slide", "cgx.carousel", relatedTarget);
        JsUtils.prop(slideEvent, "direction", direction);
        this.trigger(slideEvent);
        if (JsUtils.isDefaultPrevented(slideEvent)) {
            return false;
        }

        this.sliding = true;
        if (isCycling) {
            pause(false);
        }

        if ($indicators.length() > 0) {
            viewHandler.deactivateIndicators($indicators);
            int itemIndex = getItemIndex($next);
            XQ $nextIndicator = viewHandler.getIndicator($indicators, itemIndex);
            if ($nextIndicator != null && $nextIndicator.length() > 0) {
                viewHandler.activateIndicator($nextIndicator);
            }
        }

        final NativeEvent slidEvent = CGXHelper.createNativeEvent("slid", "cgx.carousel", relatedTarget);
        JsUtils.prop(slidEvent, "direction", direction);
        if (viewHandler.shouldSlide()) {
            viewHandler.slide($next, $active, type, direction);

            final XQ $fNext = $next;
            Function callback = new Function() {
                @Override
                public void f() {
                    viewHandler.postSlide($fNext, $active, type, direction);
                    that.sliding = false;
                    Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
                        @Override
                        public void execute() {
                            that.trigger(slidEvent);
                        }
                    });
                }
            };

            if (transitions()) {
                $active.as(CGX).onceWhenTransitionEnds(callback).emulateTransitionEnd(transitionDuration());
            } else {
                callback.f();
            }

        } else {
            viewHandler.deactivateSlide($active);
            viewHandler.activateSlide($next);
            this.sliding = false;
            this.trigger(slidEvent);
        }

        if (isCycling) {
            cycle(false);
        }

        return true;
    }

    protected CarouselView getOrCreateView() {
        if (view == null) {
            view = createDefaultView();
        }

        return view;
    }

    protected CarouselView createDefaultView() {
        return new CarouselBSView();
    }

    public Carousel carouselAddItem(CarouselSlide item) {
        CarouselView view = getOrCreateView();

        XQ $indicator = view.renderIndicator();
        viewHandler.addIndicator($indicator);

        XQ $item = view.renderItem(item);
        viewHandler.addItem($item);

        int idx = viewHandler.slideIndex($indicator);
        if (idx == 0) {
            viewHandler.activateIndicator($indicator);
            viewHandler.activateSlide($item);
        }

        return this;
    }

}