com.gwtmobile.ui.client.widgets.ScrollPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.gwtmobile.ui.client.widgets.ScrollPanel.java

Source

/*
 * 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 com.gwtmobile.ui.client.widgets;

import java.beans.Beans;
import java.util.Iterator;

import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.gwtmobile.ui.client.CSS.StyleNames.Primary;
import com.gwtmobile.ui.client.CSS.StyleNames.Secondary;
import com.gwtmobile.ui.client.event.DragController;
import com.gwtmobile.ui.client.event.DragEvent;
import com.gwtmobile.ui.client.event.DragEventsHandler;
import com.gwtmobile.ui.client.event.SwipeEvent;
import com.gwtmobile.ui.client.event.SwipeEventsHandler;
import com.gwtmobile.ui.client.utils.Utils;

public class ScrollPanel extends PanelBase implements DragEventsHandler, SwipeEventsHandler {

    private boolean _withPadding = true;
    private boolean _hasTextBox = false;
    private boolean _fullHeight = false;
    private Element _scrollbar;
    protected HTMLPanel _intPanel = new HTMLPanel("");

    public ScrollPanel() {
        super.add(_intPanel);
        setStyleName(Primary.ScrollPanel);
        setWithPadding(_withPadding);
        this.initScrollbar();
        if (Beans.isDesignTime()) {
            _intPanel.add(new Label("Empty ScrollPanel. " + getDesignTimeMessage()));
        }
    }

    public boolean isWithPadding() {
        return _withPadding;
    }

    public void setWithPadding(boolean withPadding) {
        this._withPadding = withPadding;
        if (withPadding) {
            addStyleName(Secondary.WithPadding);
        } else {
            removeStyleName(Secondary.WithPadding);
        }

    }

    private void initScrollbar() {
        _scrollbar = DOM.createDiv();
        _scrollbar.appendChild(DOM.createDiv());
        _scrollbar.setClassName(Primary.ScrollBar);
        this.getElement().insertFirst(_scrollbar);
        this.hideScrollBar();
    }

    private void adjustScrollbar(double scrollPannerPos) {
        Element widgetEle = getWidget().getElement();
        int scrollPannelHeight = widgetEle.getOffsetHeight();
        double scrollHeight = Utils.getHeight(this._scrollbar);

        double scrollbarHeight = (scrollHeight * scrollHeight) / scrollPannelHeight;
        if (scrollbarHeight >= scrollHeight) {
            this.hideScrollBar();
            return;
        } else {
            this.showScrollBar();
        }

        double scrollbarPos = -scrollHeight * scrollPannerPos / scrollPannelHeight;

        if (scrollPannerPos > 0) {
            scrollbarHeight = (scrollbarHeight - scrollPannerPos);
            scrollbarPos = 0;
            if (scrollbarHeight < 8)
                scrollbarHeight = 8;
        } else if ((-scrollPannerPos + scrollHeight) > (scrollPannelHeight)) {
            double outScroll = (-scrollPannerPos + scrollHeight) - scrollPannelHeight;
            scrollbarHeight = scrollbarHeight - outScroll;
            if (scrollbarHeight < 8) {
                scrollbarHeight = 8;
            } else {
                scrollbarPos = scrollbarPos + outScroll;
            }
            scrollbarPos = (scrollbarPos + scrollHeight) > scrollHeight ? scrollHeight - scrollbarHeight
                    : scrollbarPos;

        }

        Utils.setHeight(this._scrollbar.getFirstChildElement(), scrollbarHeight);
        Utils.setTranslateY(this._scrollbar.getFirstChildElement(), scrollbarPos);
    }

    private void showScrollBar() {
        this._scrollbar.setAttribute("style", "opacity:1");
    }

    private void hideScrollBar() {
        this._scrollbar.setAttribute("style", "opacity:0");
    }

    public void setHasTextBox(boolean hasTextBox) {
        hasTextBox = hasTextBox && Utils.isAndroid();
    }

    public boolean getHasTextBox() {
        return _hasTextBox;
    }

    public boolean isFullHeight() {
        return _fullHeight;
    }

    public void setFullHeight(boolean fullHeight) {
        this._fullHeight = fullHeight;
        if (fullHeight) {
            addStyleName(Secondary.FullHeight);
        } else {
            removeStyleName(Secondary.FullHeight);
        }
    }

    @Override
    public void onLoad() {
        DragController.get().addDragEventsHandler(this);
        DragController.get().addSwipeEventsHandler(this);
    }

    @Override
    public void onUnload() {
        DragController.get().removeDragEventsHandler(this);
        DragController.get().removeSwipeEventHandler(this);
    }

    public Widget getWidget() {
        //if (Beans.isDesignTime() an
        return getIntPanel();
        //return super.getWidget(0);
    }

    public void reset() {
        Utils.setTransitionDuration(getWidget().getElement(), 0);
        Utils.setTranslateY(getWidget().getElement(), 0);
    }

    public void setPostionToTop() {
        Utils.setTransitionDuration(getWidget().getElement(), 0);
        Utils.setTranslateY(getWidget().getElement(), 0);
    }

    public void setPositionToBottom() {
        Utils.setTransitionDuration(getWidget().getElement(), 0);

        Utils.setTranslateY(getWidget().getElement(),
                this.getElement().getClientHeight() - this.getElement().getScrollHeight());
    }

    public void setScrollPosition(int pos) {
        if (_hasTextBox) {
            setStyleTop(pos);
        } else {
            Element element = getWidget().getElement();
            Utils.setTranslateY(element, pos);
        }
        this.adjustScrollbar(pos);
    }

    public int getScrollPosition() {
        if (_hasTextBox) {
            return getStyleTop();
        } else {
            Element element = getWidget().getElement();
            return Utils.getTranslateY(element);
        }
    }

    public int getScrollToPosition() {
        if (_hasTextBox) {
            return getStyleTop();
        } else {
            Element element = getWidget().getElement();
            return Utils.getMatrixY(element);
        }
    }

    @Override
    public void onDragStart(DragEvent e) {
        int matrix = getScrollToPosition();
        int current = getScrollPosition();
        Utils.setTransitionDuration(getWidget().getElement(), 0);
        Utils.setTransitionDuration(this._scrollbar.getFirstChildElement(), 0);

        if (current != matrix) { //scroll on going
            int diff = current - matrix;
            int offset = diff > 2 ? 2 : diff > -2 ? diff : -2;
            setScrollPosition(matrix + offset);
            DragController.get().suppressNextClick();
        }
    }

    @Override
    public void onDragMove(DragEvent e) {
        Element widgetEle = getWidget().getElement();
        int panelHeight = Utils.getHeight(this.getElement());
        int widgetHeight = widgetEle.getOffsetHeight();
        int current = getScrollPosition();
        if (current > 0) {//exceed top boundary
            if (e.OffsetY > 0) { //resist scroll down.
                current += (int) (e.OffsetY / 2); // need the cast for production mode.
            } else {
                current += e.OffsetY * 2;
            }
        } else if (-current + panelHeight > widgetHeight) { //exceed bottom boundary
            if (e.OffsetY < 0) { //resist scroll up.
                current += (int) (e.OffsetY / 2);
            } else {
                current += e.OffsetY * 2;
            }
        } else {
            current += e.OffsetY;
        }

        setScrollPosition(current);
    }

    @Override
    public void onDragEnd(DragEvent e) {
        Element widgetEle = getWidget().getElement();
        int current = getScrollPosition();
        if (current == 0) {
            return;
        }
        int panelHeight = Utils.getHeight(this.getElement());
        int widgetHeight = widgetEle.getOffsetHeight();
        if (current > 0 //exceed top boundary
                || panelHeight > widgetHeight) {
            Utils.setTransitionDuration(widgetEle, 500);
            Utils.setTransitionDuration(this._scrollbar.getFirstChildElement(), 500);
            setScrollPosition(0);
        } else if (-current + panelHeight > widgetHeight) { //exceed bottom boundary
            Utils.setTransitionDuration(widgetEle, 500);
            Utils.setTransitionDuration(this._scrollbar.getFirstChildElement(), 500);
            setScrollPosition(panelHeight - widgetHeight);
        }
        this.hideScrollBar();

    }

    @Override
    public void onSwipeVertical(SwipeEvent e) {
        Element widgetEle = getWidget().getElement();
        int panelHeight = Utils.getHeight(this.getElement());
        int widgetHeight = widgetEle.getOffsetHeight();
        long current = getScrollPosition();
        if ((current >= 0) // exceed top boundary
                || (-current + panelHeight >= widgetHeight)) { // exceed bottom boundary
            return;
        }

        double speed = e.getSpeed();
        double timeFactor = 3000;
        long time = (long) Math.abs(speed * timeFactor);
        double dicstanceFactor = 0.25;
        long distance = (long) (speed * time * dicstanceFactor);
        //Utils.Console("speed " + speed + " time " + time + " distance " + distance + " current " + current);
        current += distance;
        if (current > 0) {//exceed top boundary
            double timeAdj = 1 - (double) current / distance;
            time = (long) (time * timeAdj);
            current = 0;
        } else if (-current + panelHeight > widgetHeight) { //exceed bottom boundary
            long bottom = panelHeight - widgetHeight;
            double timeAdj = 1 - (double) (current - bottom) / distance;
            time = (long) (time * timeAdj);
            current = bottom;
        }
        Utils.setTransitionDuration(widgetEle, time);
        Utils.setTransitionDuration(this._scrollbar.getFirstChildElement(), time);
        Utils.addEventListenerOnce(this._scrollbar.getFirstChildElement(), "webkitTransitionEnd", false,
                new EventListener() {
                    @Override
                    public void onBrowserEvent(Event event) {
                        hideScrollBar();
                    }
                });
        setScrollPosition((int) current);
    }

    @Override
    public void onSwipeHorizontal(SwipeEvent e) {
    }

    @Override
    public void add(Widget w) {
        if (Beans.isDesignTime()) {
            if (getWidgetCount() == 1 && isDesignTimeEmptyLabel(getWidget(0))) {
                clear();
            }
        }

        _intPanel.add(w);

        if (Utils.isIOS()) {
            Utils.setTranslateY(w.getElement(), 0); //anti-flickering on iOS.
        }
    }

    private int getStyleTop() {
        Style style = getWidget().getElement().getStyle();
        String top = style.getTop();
        if (top.isEmpty()) {
            return 0;
        } else {
            return Integer.parseInt(top.replace("px", ""));
        }
    }

    private void setStyleTop(int top) {
        Style style = getWidget().getElement().getStyle();
        style.setTop(top, Unit.PX);
    }

    public Widget getIntPanel() {
        return _intPanel;
    }

    @Override
    public void clear() {
        _intPanel.clear();
    }

    @Override
    public Iterator<Widget> iterator() {
        return _intPanel.iterator();
    }

    @Override
    public boolean remove(Widget w) {
        return _intPanel.remove(w);
    }

    @Override
    public Widget getWidget(int index) {
        return _intPanel.getWidget(index);
    }

    @Override
    public int getWidgetCount() {
        return _intPanel.getWidgetCount();
    }

}