001package org.gwtbootstrap3.extras.gallery.client.ui;
002
003/*
004 * #%L
005 * GwtBootstrap3
006 * %%
007 * Copyright (C) 2013 - 2014 GwtBootstrap3
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 * 
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import com.google.gwt.dom.client.Document;
024import com.google.gwt.dom.client.Element;
025import com.google.gwt.event.dom.client.LoadEvent;
026import com.google.gwt.event.dom.client.LoadHandler;
027import com.google.gwt.event.shared.HandlerRegistration;
028import com.google.gwt.user.client.Event;
029import com.google.gwt.user.client.ui.RootPanel;
030import com.google.gwt.user.client.ui.Widget;
031import org.gwtbootstrap3.client.ui.Anchor;
032import org.gwtbootstrap3.client.ui.Heading;
033import org.gwtbootstrap3.client.ui.base.ComplexWidget;
034import org.gwtbootstrap3.client.ui.constants.HeadingSize;
035import org.gwtbootstrap3.client.ui.constants.IconType;
036import org.gwtbootstrap3.client.ui.html.Div;
037import org.gwtbootstrap3.client.ui.html.OrderedList;
038import org.gwtbootstrap3.extras.gallery.client.events.GalleryCloseEvent;
039import org.gwtbootstrap3.extras.gallery.client.events.GalleryCloseHandler;
040import org.gwtbootstrap3.extras.gallery.client.events.GalleryClosedEvent;
041import org.gwtbootstrap3.extras.gallery.client.events.GalleryClosedHandler;
042import org.gwtbootstrap3.extras.gallery.client.events.GalleryOpenEvent;
043import org.gwtbootstrap3.extras.gallery.client.events.GalleryOpenHandler;
044import org.gwtbootstrap3.extras.gallery.client.events.GalleryOpenedEvent;
045import org.gwtbootstrap3.extras.gallery.client.events.GalleryOpenedHandler;
046import org.gwtbootstrap3.extras.gallery.client.events.GallerySlideCompleteEvent;
047import org.gwtbootstrap3.extras.gallery.client.events.GallerySlideCompleteHandler;
048import org.gwtbootstrap3.extras.gallery.client.events.GallerySlideEndEvent;
049import org.gwtbootstrap3.extras.gallery.client.events.GallerySlideEndHandler;
050import org.gwtbootstrap3.extras.gallery.client.events.GallerySlideEvent;
051import org.gwtbootstrap3.extras.gallery.client.events.GallerySlideHandler;
052
053/**
054 * Bootstrap Gallery
055 *
056 * https://github.com/blueimp/Bootstrap-Image-Gallery
057 *
058 * @author Ben Dol
059 */
060public class Gallery extends ComplexWidget {
061
062    private static Div galleryRoot;
063
064    // Controls
065    private Heading title;
066    private Anchor prev;
067    private Anchor next;
068    private Anchor close;
069    private OrderedList indicator;
070
071    // Options
072    private String thumbnailHeight;
073    private String thumbnailWidth;
074
075    public Gallery() {
076        setElement(Document.get().createDivElement());
077        getElement().setId("links");
078
079        // Ensure the root gallery components are setup
080        if(galleryRoot == null) {
081            setupRootGallery();
082        }
083    }
084
085    @Override
086    public String getTitle() {
087        return title.getText();
088    }
089
090    @Override
091    public void setTitle(String title) {
092        this.title.setText(title);
093    }
094
095    public void setPrevIcon(IconType iconType) {
096        prev.setIcon(iconType);
097    }
098
099    public void setShowPrevButton(boolean show) {
100        prev.setVisible(show);
101    }
102
103    public void setNextIcon(IconType iconType) {
104        next.setIcon(iconType);
105    }
106
107    public void setShowNextButton(boolean show) {
108        next.setVisible(show);
109    }
110
111    public void setCloseIcon(IconType iconType) {
112        close.setIcon(iconType);
113    }
114
115    public void setShowCloseButton(boolean show) {
116        close.setVisible(show);
117    }
118
119    public void setShowIndicator(boolean show) {
120        indicator.setVisible(show);
121    }
122
123    public String getThumbnailHeight() {
124        return thumbnailHeight;
125    }
126
127    public void setThumbnailHeight(String thumbnailHeight) {
128        this.thumbnailHeight = thumbnailHeight;
129    }
130
131    public String getThumbnailWidth() {
132        return thumbnailWidth;
133    }
134
135    public void setThumbnailWidth(String thumbnailWidth) {
136        this.thumbnailWidth = thumbnailWidth;
137    }
138
139    @Override
140    public void add(final Widget child) {
141        if(child instanceof GalleryImage) {
142            ((GalleryImage) child).addLoadHandler(new LoadHandler() {
143                @Override
144                public void onLoad(LoadEvent event) {
145                    if(thumbnailWidth != null) {
146                        child.setWidth(thumbnailWidth);
147                    }
148                    if(thumbnailHeight != null) {
149                        child.setHeight(thumbnailHeight);
150                    }
151                }
152            });
153
154            super.add(child);
155        } else {
156            throw new IllegalArgumentException("Gallery can only contain GalleryImage's.");
157        }
158    }
159
160    /**
161     * Executed when the Gallery is initialized.
162     */
163    public HandlerRegistration addGalleryOpenHandler(final GalleryOpenHandler handler) {
164        return addHandler(handler, GalleryOpenEvent.getType());
165    }
166
167    /**
168     * Executed when the Gallery has been initialized
169     * and the initialization transition has been completed.
170     */
171    public HandlerRegistration addGalleryOpenedHandler(final GalleryOpenedHandler handler) {
172        return addHandler(handler, GalleryOpenedEvent.getType());
173    }
174
175    /**
176     * Executed when the Gallery is about to be closed.
177     */
178    public HandlerRegistration addGalleryCloseHandler(final GalleryCloseHandler handler) {
179        return addHandler(handler, GalleryCloseEvent.getType());
180    }
181
182    /**
183     * Executed when the Gallery has been closed and the closing
184     * transition has been completed.
185     */
186    public HandlerRegistration addGalleryClosedHandler(final GalleryClosedHandler handler) {
187        return addHandler(handler, GalleryClosedEvent.getType());
188    }
189
190    /**
191     * Executed on slide change.
192     */
193    public HandlerRegistration addGallerySlideHandler(final GallerySlideHandler handler) {
194        return addHandler(handler, GallerySlideEvent.getType());
195    }
196
197    /**
198     * Executed after the slide change transition.
199     */
200    public HandlerRegistration addGallerySlideEndHandler(final GallerySlideEndHandler handler) {
201        return addHandler(handler, GallerySlideEndEvent.getType());
202    }
203
204    /**
205     * Executed on slide content load.
206     */
207    public HandlerRegistration addGallerySlideCompleteHandler(final GallerySlideCompleteHandler handler) {
208        return addHandler(handler, GallerySlideCompleteEvent.getType());
209    }
210
211    /**
212     * Triggered when the gallery opens.
213     *
214     * @param event the event
215     */
216    private void onOpen(final Event event) {
217        GalleryOpenEvent.fire(this, event);
218    }
219
220    /**
221     * Triggered when the gallery is opened.
222     *
223     * @param event the event
224     */
225    private void onOpened(final Event event) {
226        GalleryOpenedEvent.fire(this, event);
227    }
228
229    /**
230     * Triggered when the gallery is closing.
231     *
232     * @param event the event
233     */
234    private void onClose(final Event event) {
235        GalleryCloseEvent.fire(this, event);
236    }
237
238    /**
239     * Triggered when the gallery is closed.
240     *
241     * @param event the event
242     */
243    private void onClosed(final Event event) {
244        GalleryClosedEvent.fire(this, event);
245    }
246
247    /**
248     * Triggered when the gallery is sliding.
249     *
250     * @param event the event
251     */
252    private void onSlide(final Event event, int index) {
253        GallerySlideEvent.fire(this, event, index);
254    }
255
256    /**
257     * Triggered when the gallery is slide ends.
258     *
259     * @param event the event
260     */
261    private void onSlideEnd(final Event event, int index) {
262        GallerySlideEndEvent.fire(this, event, index);
263    }
264
265    /**
266     * Triggered when the gallery is slide completes.
267     *
268     * @param event the event
269     */
270    private void onSlideComplete(final Event event, int index) {
271        GallerySlideCompleteEvent.fire(this, event, index);
272    }
273
274    public void reconfigure() {
275        if(galleryRoot != null) {
276            destroy(galleryRoot.getElement());
277            configure();
278        }
279    }
280
281    private void setupRootGallery() {
282        galleryRoot = new Div();
283        galleryRoot.getElement().setId("blueimp-gallery");
284        galleryRoot.getElement().setClassName("blueimp-gallery");
285        galleryRoot.getElement().setAttribute("data-use-bootstrap-modal", "false");
286
287        Div slides = new Div();
288        slides.getElement().setClassName("slides");
289        galleryRoot.add(slides);
290
291        title = new Heading(HeadingSize.H3);
292        title.getElement().setClassName("title");
293        galleryRoot.add(title);
294
295        prev = new Anchor("");
296        prev.getElement().setClassName("prev");
297        prev.setIcon(IconType.CARET_LEFT);
298        galleryRoot.add(prev);
299
300        next = new Anchor("");
301        next.getElement().setClassName("next");
302        next.setIcon(IconType.CARET_RIGHT);
303        galleryRoot.add(next);
304
305        close = new Anchor("");
306        close.getElement().setClassName("close");
307        close.setIcon(IconType.CLOSE);
308        galleryRoot.add(close);
309
310        indicator = new OrderedList();
311        indicator.getElement().setClassName("indicator");
312        galleryRoot.add(indicator);
313    }
314
315    @Override
316    protected void onLoad() {
317        if(galleryRoot != null) {
318            if (!galleryRoot.isAttached()) {
319                // Add the gallery to the root panel
320                RootPanel.get().add(galleryRoot);
321            }
322
323            configure();
324        }
325    }
326
327    @Override
328    protected void onUnload() {
329        if(galleryRoot != null) {
330            destroy(galleryRoot.getElement());
331        }
332    }
333
334    protected void configure() {
335        if(galleryRoot != null) {
336            configure(galleryRoot.getElement());
337        }
338    }
339
340    private native void configure(Element e) /*-{
341        var that = this;
342        $wnd.jQuery(e)
343            .on('open', function (e) {
344                // Callback function executed when the Gallery is initialized.
345                that.@org.gwtbootstrap3.extras.gallery.client.ui.Gallery::onOpen(Lcom/google/gwt/user/client/Event;)(e);
346            })
347            .on('opened', function (e) {
348                // Callback function executed when the Gallery has been initialized
349                // and the initialization transition has been completed.
350                that.@org.gwtbootstrap3.extras.gallery.client.ui.Gallery::onOpened(Lcom/google/gwt/user/client/Event;)(e);
351            })
352            .on('close', function (e) {
353                // Callback function executed when the Gallery is about to be closed.
354                that.@org.gwtbootstrap3.extras.gallery.client.ui.Gallery::onClose(Lcom/google/gwt/user/client/Event;)(e);
355            })
356            .on('closed', function (e) {
357                // Callback function executed when the Gallery has been closed
358                // and the closing transition has been completed.
359                that.@org.gwtbootstrap3.extras.gallery.client.ui.Gallery::onClosed(Lcom/google/gwt/user/client/Event;)(e);
360            })
361            .on('slide', function (e, index, slide) {
362                // Callback function executed on slide change.
363                that.@org.gwtbootstrap3.extras.gallery.client.ui.Gallery::onSlide(*)(e, index);
364            })
365            .on('slideend', function (e, index, slide) {
366                // Callback function executed after the slide change transition.
367                that.@org.gwtbootstrap3.extras.gallery.client.ui.Gallery::onSlideEnd(*)(e, index);
368            })
369            .on('slidecomplete', function (e, index, slide) {
370                // Callback function executed on slide content load.
371                that.@org.gwtbootstrap3.extras.gallery.client.ui.Gallery::onSlideComplete(*)(e, index);
372            });
373    }-*/;
374
375    private native void destroy(Element e) /*-{
376        $wnd.jQuery(e).off('open');
377        $wnd.jQuery(e).off('opened');
378        $wnd.jQuery(e).off('close');
379        $wnd.jQuery(e).off('closed');
380        $wnd.jQuery(e).off('slide');
381        $wnd.jQuery(e).off('slideend');
382        $wnd.jQuery(e).off('slidecomplete');
383    }-*/;
384}