001package gwt.material.design.addins.client.swipeable;
002
003/*
004 * #%L
005 * GwtMaterial
006 * %%
007 * Copyright (C) 2015 - 2016 GwtMaterialDesign
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
023/*
024 * Copyright 2008 Google Inc.
025 *
026 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
027 * use this file except in compliance with the License. You may obtain a copy of
028 * the License at
029 *
030 * http://www.apache.org/licenses/LICENSE-2.0
031 *
032 * Unless required by applicable law or agreed to in writing, software
033 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
034 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
035 * License for the specific language governing permissions and limitations under
036 * the License.
037 */
038
039import com.google.gwt.dom.client.Document;
040import com.google.gwt.dom.client.Element;
041import com.google.gwt.event.shared.HandlerRegistration;
042import com.google.gwt.user.client.ui.Widget;
043import gwt.material.design.addins.client.MaterialAddins;
044import gwt.material.design.addins.client.swipeable.base.HasSwipeable;
045import gwt.material.design.addins.client.swipeable.events.SwipeLeftEvent;
046import gwt.material.design.addins.client.swipeable.events.SwipeRightEvent;
047import gwt.material.design.client.MaterialDesignBase;
048import gwt.material.design.client.base.MaterialWidget;
049
050/**
051 * A panel that allows any of its nested children to be swiped away.
052 *
053 * <h3>XML Namespace Declaration</h3>
054 * <pre>
055 * {@code
056 * xmlns:ma='urn:import:gwt.material.design.addins.client'
057 * }
058 * </pre>
059 *
060 * <h3>UiBinder Usage:</h3>
061 * <pre>
062 *{
063 * @code
064 * <ma:swipeable.MaterialSwipeablePanel ui:field="swipeablePanel" shadow="1" backgroundColor="white" padding="12">
065 *   <m:MaterialLabel text="You can swipe native components. This is a plain label" backgroundColor="yellow" padding="12" />
066 *   <m:MaterialCard>
067 *     <m:MaterialCardContent>
068 *       <m:MaterialLabel text="This is another Card Component that is swipeable." />
069 *       </m:MaterialCardContent>
070 *     </m:MaterialCard>
071 * </ma:swipeable.MaterialSwipeablePanel>
072 * }
073 * </pre>
074 * @see <a href="http://gwtmaterialdesign.github.io/gwt-material-demo/#swipeable">Material Swipeable</a>
075 * @author kevzlou7979
076 * @author Ben Dol
077 */
078//@formatter:on
079public class MaterialSwipeablePanel extends MaterialWidget implements HasSwipeable<Widget> {
080
081    static {
082        if(MaterialAddins.isDebug()) {
083            MaterialDesignBase.injectCss(MaterialSwipeableDebugClientBundle.INSTANCE.swipeableCssDebug());
084        } else {
085            MaterialDesignBase.injectCss(MaterialSwipeableClientBundle.INSTANCE.swipeableCss());
086        }
087    }
088
089    private final String DISABLED = "disabled-swipe";
090
091    public MaterialSwipeablePanel() {
092        super(Document.get().createDivElement(), "swipeable");
093    }
094
095    @Override
096    protected void onLoad() {
097        super.onLoad();
098        for(Widget w : getChildren()) {
099            if(!w.getStyleName().contains(DISABLED)) {
100                initSwipeable(w.getElement(), w);
101            }
102        }
103    }
104
105
106    @Override
107    public void initSwipeable(Element element, Widget target) {
108        initSwipeableElement(element, target);
109    }
110
111    /**
112     * Initialize the swipeable element
113     * @param element
114     * @param target
115     */
116    protected native void initSwipeableElement(Element element, Widget target) /*-{
117        var that = this;
118        var swipeLeftToRight;
119        var swipeRightToLeft;
120        // Dismissible Collections
121        $wnd.jQuery(element).each(function() {
122            $wnd.jQuery(this).hammer({
123                prevent_default: false
124            }).bind('pan', function(e) {
125                if (e.gesture.pointerType === "touch") {
126                    var parent = $wnd.jQuery(this);
127                    var direction = e.gesture.direction;
128                    var x = e.gesture.deltaX;
129                    var velocityX = e.gesture.velocityX;
130
131                    parent.velocity({ translateX: x
132                    }, {duration: 50, queue: false, easing: 'easeOutQuad'});
133
134                    // Swipe Left
135                    if (direction === 4 && (x > (parent.innerWidth() / 2) || velocityX < -0.75)) {
136                        swipeLeftToRight = true;
137                    }
138
139                    // Swipe Right
140                    if (direction === 2 && (x < (-1 * parent.innerWidth() / 2) || velocityX > 0.75)) {
141                        swipeRightToLeft = true;
142                    }
143                }
144            }).bind('panend', function(e) {
145                // Reset if collection is moved back into original position
146                if (Math.abs(e.gesture.deltaX) < ($wnd.jQuery(this).innerWidth() / 2)) {
147                    swipeRightToLeft = false;
148                    swipeLeftToRight = false;
149                }
150
151                if (e.gesture.pointerType === "touch") {
152                    var parent = $wnd.jQuery(this);
153                    if (swipeLeftToRight || swipeRightToLeft) {
154                        var fullWidth;
155                        if (swipeLeftToRight) {
156                            fullWidth = parent.innerWidth();
157                            that.@gwt.material.design.addins.client.swipeable.MaterialSwipeablePanel::fireSwipeRightEvent(*)(target);
158                        }
159                        else {
160                            fullWidth = -1 * parent.innerWidth();
161                            that.@gwt.material.design.addins.client.swipeable.MaterialSwipeablePanel::fireSwipeLeftEvent(*)(target);
162                        }
163
164                        parent.velocity({ translateX: fullWidth,
165                        }, {duration: 100, queue: false, easing: 'easeOutQuad', complete:
166                            function() {
167                                parent.css('border', 'none');
168                                parent.velocity({ height: 0, padding: 0,
169                                }, {duration: 200, queue: false, easing: 'easeOutQuad', complete:
170                                    function() {
171                                        parent.remove();
172                                    }
173                                });
174                            }
175                        });
176                    }
177                    else {
178                        parent.velocity({ translateX: 0,
179                        }, {duration: 100, queue: false, easing: 'easeOutQuad'});
180                    }
181                    swipeLeftToRight = false;
182                    swipeRightToLeft = false;
183                }
184            });
185
186        });
187    }-*/;
188
189    @Override
190    public HandlerRegistration addSwipeLeft(final SwipeLeftEvent.SwipeLeftHandler<Widget> handler) {
191        return addHandler(new SwipeLeftEvent.SwipeLeftHandler<Widget>() {
192            @Override
193            public void onSwipeLeft(SwipeLeftEvent<Widget> event) {
194                if(isEnabled()){
195                    handler.onSwipeLeft(event);
196                }
197            }
198        }, SwipeLeftEvent.getType());
199    }
200
201    @Override
202    public HandlerRegistration addSwipeRight(final SwipeRightEvent.SwipeRightHandler<Widget> handler) {
203        return addHandler(new SwipeRightEvent.SwipeRightHandler<Widget>() {
204            @Override
205            public void onSwipeRight(SwipeRightEvent<Widget> event) {
206                if(isEnabled()){
207                    handler.onSwipeRight(event);
208                }
209            }
210        }, SwipeRightEvent.getType());
211    }
212
213    /**
214     * Fire the Swipe left event listener
215     * @param target
216     */
217    public void fireSwipeLeftEvent(Widget target) {
218        SwipeLeftEvent.fire(MaterialSwipeablePanel.this, target);
219    }
220
221    /**
222     * Fire the Swipe right event listener
223     * @param target
224     */
225    public void fireSwipeRightEvent(Widget target) {
226        SwipeRightEvent.fire(MaterialSwipeablePanel.this, target);
227    }
228
229    public void setDisable(Widget... widgets) {
230        for(Widget w : widgets){
231            w.addStyleName(DISABLED);
232        }
233    }
234}