/*
* Copyright 2012 Daniel Kurka
*
* 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.googlecode.mgwt.ui.client.widget.panel.pull;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import com.googlecode.mgwt.ui.client.widget.base.HasRefresh;
import com.googlecode.mgwt.ui.client.widget.panel.flex.IsFlexible;
import com.googlecode.mgwt.ui.client.widget.panel.pull.PullPanel.PullWidget.PullState;
import com.googlecode.mgwt.ui.client.widget.panel.scroll.ScrollEndEvent;
import com.googlecode.mgwt.ui.client.widget.panel.scroll.ScrollMoveEvent;
import com.googlecode.mgwt.ui.client.widget.panel.scroll.ScrollPanel;
import com.googlecode.mgwt.ui.client.widget.panel.scroll.ScrollRefreshEvent;
import com.googlecode.mgwt.ui.client.widget.panel.scroll.ScrollStartEvent;
import java.util.Iterator;
public class PullPanel extends Composite implements HasWidgets, HasRefresh, IsFlexible {
public interface PullWidget extends IsWidget {
enum PullState {
NORMAL, PULLED
}
public void onScroll(int positionY);
public int getHeight();
/**
* get the position in px that triggers a state change
*
* @return the position in px that triggers the state change
*/
public int getStateSwitchPosition();
/**
* set the html of a pull header
*
* @param html the html as String
*/
public void setHTML(String html);
}
public interface Pullhandler {
/**
* this method get called if the pull state of the panel changes
*
* @param pullWidget the PullWidget set for the region (header, footer)
* @param state the current state of the pull panel
*/
public void onPullStateChanged(PullWidget pullWidget, PullState state);
/**
* called if a pull got executed
*
* @param pullWidget the PullWidget set for the region (header, footer)
*/
public void onPullAction(PullWidget pullWidget);
}
public static final PullPanelAppearance DEFAULT_APPEARANCE = GWT.create(PullPanelAppearance.class);
@UiField
protected FlowPanel main;
@UiField
protected ScrollPanel scrollPanel;
@UiField
protected FlowPanel container;
protected PullWidget header;
protected PullWidget footer;
protected PullState headerState = PullState.NORMAL;
protected Pullhandler headerPullhandler;
protected Pullhandler footerPullhandler;
protected PullState footerState = PullState.NORMAL;
private PullPanelAppearance apperance;
public PullPanel() {
this(DEFAULT_APPEARANCE);
}
public PullPanel(PullPanelAppearance apperance) {
this.apperance = apperance;
scrollPanel = this.apperance.uiBinder().createAndBindUi(this);
initWidget(scrollPanel);
scrollPanel.setBounceFactor(1.0);
scrollPanel.addScrollRefreshHandler(new ScrollRefreshEvent.Handler() {
@Override
public void onScrollRefresh(ScrollRefreshEvent event) {
if (header != null) {
headerState = PullState.NORMAL;
}
if (footer != null) {
footerState = PullState.NORMAL;
}
}
});
scrollPanel.addScrollStartHandler(new ScrollStartEvent.Handler() {
@Override
public void onScrollStart(ScrollStartEvent event) {
if (header != null && headerPullhandler != null) {
headerState = PullState.NORMAL;
headerPullhandler.onPullStateChanged(header, headerState);
}
if (footer != null && footerPullhandler != null) {
footerState = PullState.NORMAL;
footerPullhandler.onPullStateChanged(footer, footerState);
}
}
});
scrollPanel.addScrollMoveHandler(new ScrollMoveEvent.Handler() {
@Override
public void onScrollMove(ScrollMoveEvent event) {
int y = scrollPanel.getY();
if (header != null) {
if (y > header.getStateSwitchPosition() && headerState != PullState.PULLED) {
headerState = PullState.PULLED;
scrollPanel.setMinScrollY(0);
if (headerPullhandler != null)
headerPullhandler.onPullStateChanged(header, headerState);
} else {
if (y <= header.getStateSwitchPosition() && headerState != PullState.NORMAL) {
headerState = PullState.NORMAL;
scrollPanel.setMinScrollY(-header.getHeight());
if (headerPullhandler != null)
headerPullhandler.onPullStateChanged(header, headerState);
}
}
header.onScroll(y);
}
int y_off = y;
// footer
if (footer != null && y < -footer.getHeight()) {
if (footerState == PullState.PULLED) {
y_off = y_off - footer.getHeight();
}
if (footerState == PullState.NORMAL) {
y_off = y_off + footer.getHeight();
}
if (y_off < (scrollPanel.getMaxScrollY() - footer.getStateSwitchPosition())
&& footerState != PullState.PULLED) {
footerState = PullState.PULLED;
scrollPanel.setMaxScrollY(scrollPanel.getMaxScrollY() - footer.getHeight());
if (footerPullhandler != null) {
footerPullhandler.onPullStateChanged(footer, footerState);
}
} else {
if (y_off > (scrollPanel.getMaxScrollY() - footer.getStateSwitchPosition())
&& footerState != PullState.NORMAL) {
footerState = PullState.NORMAL;
scrollPanel.setMaxScrollY(scrollPanel.getMaxScrollY() + footer.getHeight());
if (footerPullhandler != null) {
footerPullhandler.onPullStateChanged(footer, footerState);
}
}
}
footer.onScroll(y_off - scrollPanel.getMaxScrollY());
}
}
});
scrollPanel.addScrollEndHandler(new ScrollEndEvent.Handler() {
@Override
public void onScrollEnd(ScrollEndEvent event) {
if (header != null) {
if (headerState == PullState.PULLED) {
headerState = PullState.NORMAL;
if (headerPullhandler != null)
headerPullhandler.onPullAction(header);
}
}
if (footer != null) {
if (footerState == PullState.PULLED) {
footerState = PullState.NORMAL;
if (footerPullhandler != null)
footerPullhandler.onPullAction(footer);
}
}
}
});
}
public void setHeader(PullWidget header) {
if (this.header != null) {
this.main.remove(this.header);
}
this.header = header;
if (this.header != null) {
main.insert(this.header, 0);
scrollPanel.setOffSetY(this.header.getHeight());
} else {
scrollPanel.setOffSetY(0);
}
scrollPanel.refresh();
}
public void setFooter(PullWidget footer) {
if (this.footer != null) {
this.main.remove(this.footer);
}
this.footer = footer;
if (this.footer != null) {
main.insert(this.footer, main.getWidgetCount());
scrollPanel.setOffSetMaxY(this.footer.getHeight());
} else {
scrollPanel.setOffSetMaxY(0);
}
scrollPanel.refresh();
}
public void refresh() {
scrollPanel.refresh();
}
@Override
public void add(Widget w) {
container.add(w);
}
@Override
public void clear() {
container.clear();
}
@Override
public Iterator<Widget> iterator() {
return container.iterator();
}
@Override
public boolean remove(Widget w) {
return container.remove(w);
}
public void setHeaderPullHandler(Pullhandler headerPullhandler) {
this.headerPullhandler = headerPullhandler;
}
public void setFooterPullHandler(Pullhandler headerPullhandler) {
this.footerPullhandler = headerPullhandler;
}
public ScrollPanel getScrollPanel() {
return scrollPanel;
}
@UiFactory
protected PullPanelAppearance getApperance() {
return apperance;
}
}