/*
* 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.
*/
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 horizontally.
*
*
*/
public class XHorizontalScrollView extends MPanelBase implements HasWidgets, DragEventsHandler, SwipeEventsHandler,
IView {
private boolean _hasTextBox = false;
private Element widgetElement;
private int panelWidth = -1;
private int widgetWidth = -1;
public XHorizontalScrollView() {
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.setTranslateX(el(), 0);
}
public void setPostionToTop() {
FxUtil.setTransitionDuration(el(), 0);
FxUtil.setTranslateX(el(), 0);
}
public void setPositionToBottom() {
FxUtil.setTransitionDuration(el(), 0);
FxUtil.setTranslateX(el(), this.getElement().getClientWidth() - this.getElement().getScrollWidth());
}
public void setScrollPositionX(double pos) {
if (_hasTextBox) {
FxUtil.setStyleLeft(this, pos);
} else {
FxUtil.setTranslateX(el(), pos);
}
}
public double getScrollPositionX() {
if (_hasTextBox) {
return FxUtil.getStyleLeft(this);
} else {
return FxUtil.getTranslateX(el());
}
}
public double getScrollToPositionX() {
if (_hasTextBox) {
return FxUtil.getStyleLeft(this);
} else {
return FxUtil.getMatrixX(el());
}
}
@Override
public void onDragStart(DragEvent e) {
_lazyInit();
double matrixX = getScrollToPositionX();
double currX = getScrollPositionX();
FxUtil.setTransitionDuration(el(), 0);
if (currX != matrixX) {
// scroll on going
double diffX = currX - matrixX;
double offsetX = diffX > 2 ? 2 : diffX > -2 ? diffX : -2;
setScrollPositionX(matrixX + offsetX);
DragController.get().suppressNextClick();
}
}
@Override
public void onDragMove(DragEvent e) {
double currX = getScrollPositionX();
// exceed left boundary
if (currX > 0) {
// resist scroll right.
if (e.OffsetX > 0) {
currX += (int) (e.OffsetX / 2);
} else {
currX += e.OffsetX * 2;
}
// exceed right boundary
} else if (-currX + panelWidth > widgetWidth) {
// resist scroll left.
if (e.OffsetX < 0) {
currX += (int) (e.OffsetX / 2);
} else {
currX += e.OffsetX * 2;
}
} else {
currX += e.OffsetX;
}
// XLog.info("current: " + current + ", e.OffsetX: " + e.OffsetX +
// ", e.OffsetY: " + e.OffsetY + ", e.X: " + e.X
// + ", e.Y: " + e.Y);
setScrollPositionX(currX);
}
@Override
public void onDragEnd(DragEvent e) {
double currX = getScrollPositionX();
if (currX == 0) {
return;
}
// exceed left boundary
if (currX > 0 || panelWidth > widgetWidth) {
FxUtil.setTransitionDuration(el(), 500);
setScrollPositionX(0);
} else if (-currX + panelWidth > widgetWidth) {
// exceed right boundary
FxUtil.setTransitionDuration(el(), 500);
setScrollPositionX(panelWidth - widgetWidth);
}
}
@Override
public void onSwipeVertical(SwipeEvent e) {
}
@Override
public void onSwipeHorizontal(SwipeEvent e) {
double currX = getScrollPositionX();
// exceed left boundary
if ((currX >= 0) || (-currX + panelWidth >= widgetWidth)) {
// exceed right 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 + " currX " + currX);
currX += distance;
if (currX > 0) {
// exceed left boundary
double timeAdj = 1 - (double) currX / distance;
time = (long) (time * timeAdj);
currX = 0;
} else if (-currX + panelWidth > widgetWidth) {
// exceed right boundary
long bottom = panelWidth - widgetWidth;
double timeAdj = 1 - (double) (currX - bottom) / distance;
time = (long) (time * timeAdj);
currX = bottom;
}
FxUtil.setTransitionDuration(el(), time);
setScrollPositionX((int) currX);
}
@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 (panelWidth < 1) {
panelWidth = FxUtil.getWidth(this.getElement());
}
if (widgetWidth < 1) {
widgetWidth = el().getOffsetWidth();
}
}
@Override
public void onDragMoveHorizontal(DragEvent e) {
// Not implemented
}
@Override
public void onDragMoveVertical(DragEvent e) {
// Not implemented
}
}