/* * Copyright 2011 Vancouver Ywebb Consulting Ltd * * 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. * -------- * This class contains modified sources from gwtmobile-ui project. * * Copyright (c) 2010 Zhihua (Dennis) Jiang * * 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. */ package next.i.view; import next.i.XStyle; import next.i.mobile.DragController; import next.i.mobile.DragEvent; import next.i.mobile.DragEventsHandler; import next.i.mobile.SwipeEvent; import next.i.mobile.SwipeEventsHandler; import next.i.util.FxUtil; import next.i.util.Utils; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.Widget; /** * This view class accepts finger drag actions and can be scrolled vertically. * * * <p> * <img class='ai' src='../../../resources/XScrollView.png' /> * </p> */ public class XVerticalScrollView extends MPanelBase implements HasWidgets, DragEventsHandler, SwipeEventsHandler, IView { private boolean _hasTextBox = false; private Element widgetElement; protected int panelHeight = -1; protected int widgetHeight = -1; public XVerticalScrollView() { setStyleName(XStyle.scrollPanel.name()); } public void setHasTextBox(boolean hasTextBox) { _hasTextBox = hasTextBox && Utils.isAndroid(); } public boolean getHasTextBox() { return _hasTextBox; } @Override public void onLoad() { DragController.get().addDragEventsHandler(this); DragController.get().addSwipeEventsHandler(this); } @Override public void onUnload() { DragController.get().removeDragEventsHandler(this); DragController.get().removeSwipeEventHandler(this); } @Override public Widget getWidget() { return _panel.getWidget(0); } public void reset() { FxUtil.setTransitionDuration(el(), 0); FxUtil.setTranslateY(el(), 0); } public void setPostionToTop() { FxUtil.setTransitionDuration(el(), 0); FxUtil.setTranslateY(el(), 0); } public void setPositionToBottom() { FxUtil.setTransitionDuration(el(), 0); FxUtil.setTranslateY(el(), this.getElement().getClientHeight() - this.getElement().getScrollHeight()); } public void setScrollPositionY(double pos) { if (_hasTextBox) { FxUtil.setStyleTop(this, pos); } else { FxUtil.setTranslateY(el(), pos); } } public double getScrollPositionY() { if (_hasTextBox) { return FxUtil.getStyleTop(this); } else { return FxUtil.getTranslateY(el()); } } public double getScrollToPositionY() { if (_hasTextBox) { return FxUtil.getStyleTop(this); } else { return FxUtil.getMatrixY(el()); } } @Override public void onDragStart(DragEvent e) { _lazyInit(); double matrixY = getScrollToPositionY(); double currY = getScrollPositionY(); FxUtil.setTransitionDuration(el(), 0); if (currY != matrixY) { // scroll on going double diffY = currY - matrixY; double offsetY = diffY > 2 ? 2 : diffY > -2 ? diffY : -2; setScrollPositionY(matrixY + offsetY); DragController.get().suppressNextClick(); } } @Override public void onDragMove(DragEvent e) { double currY = getScrollPositionY(); if (currY > 0) { // exceed top boundary if (e.OffsetY > 0) { // resist scroll down. currY += (int) (e.OffsetY / 2); // need the cast for production mode. } else { currY += e.OffsetY * 2; } } else if (-currY + panelHeight > widgetHeight) { // exceed bottom boundary if (e.OffsetY < 0) { // resist scroll up. currY += (int) (e.OffsetY / 2); } else { currY += e.OffsetY * 2; } } else { currY += e.OffsetY; } setScrollPositionY(currY); } @Override public void onDragEnd(DragEvent e) { double currY = getScrollPositionY(); if (currY == 0) { return; } // exceed top boundary if (currY > 0 || panelHeight > widgetHeight) { FxUtil.setTransitionDuration(el(), 500); setScrollPositionY(0); } else if (-currY + panelHeight > widgetHeight) { // exceed bottom boundary FxUtil.setTransitionDuration(el(), 500); setScrollPositionY(panelHeight - widgetHeight); } } @Override public void onSwipeVertical(SwipeEvent e) { double currY = getScrollPositionY(); // exceed top boundary if ((currY >= 0) || (-currY + panelHeight >= widgetHeight)) { // exceed bottom boundary return; } double speed = e.getSpeed(); double timeFactor = 2800; long time = (long) Math.abs(speed * timeFactor); double dicstanceFactor = 0.24; long distance = (long) (speed * time * dicstanceFactor); // Utils.Console("speed " + speed + " time " + time + " distance " + // distance + " current " + current); currY += distance; if (currY > 0) { // exceed top boundary double timeAdj = 1 - (double) currY / distance; time = (long) (time * timeAdj); currY = 0; } else if (-currY + panelHeight > widgetHeight) { // exceed bottom boundary long bottom = panelHeight - widgetHeight; double timeAdj = 1 - (double) (currY - bottom) / distance; time = (long) (time * timeAdj); currY = bottom; } FxUtil.setTransitionDuration(el(), time); setScrollPositionY(currY); } @Override public void onSwipeHorizontal(SwipeEvent e) { } @Override public void add(Widget w) { assert _panel.getWidgetCount() == 0 : "Can only add one widget to MScrollPanel."; super.add(w); } private Element el() { if (widgetElement == null) { widgetElement = getWidget().getElement(); } return widgetElement; } private void _lazyInit() { // lazy init. no reason to calculate each time in onDragMove // if (panelHeight < 1) { panelHeight = FxUtil.getHeight(this.getElement()); // } // if (widgetHeight < 1) { widgetHeight = el().getOffsetHeight(); // } } @Override public void onDragMoveHorizontal(DragEvent e) { // Not implemented } @Override public void onDragMoveVertical(DragEvent e) { // Not implemented } }