Package com.googlecode.mgwt.ui.client.widget.list.celllist

Source Code of com.googlecode.mgwt.ui.client.widget.list.celllist.HeaderList

/*
* 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.list.celllist;

import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.TouchCancelEvent;
import com.google.gwt.event.dom.client.TouchEndEvent;
import com.google.gwt.event.dom.client.TouchMoveEvent;
import com.google.gwt.event.dom.client.TouchStartEvent;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;

import com.googlecode.mgwt.collection.shared.LightArrayInt;
import com.googlecode.mgwt.dom.client.event.touch.TouchHandler;
import com.googlecode.mgwt.ui.client.MGWT;
import com.googlecode.mgwt.ui.client.util.CssUtil;
import com.googlecode.mgwt.ui.client.widget.list.celllist.CellListAppearance.CellListCss;
import com.googlecode.mgwt.ui.client.widget.list.celllist.GroupingCellList.CellGroup;
import com.googlecode.mgwt.ui.client.widget.list.celllist.GroupingCellListAppearance.GroupingListCss;
import com.googlecode.mgwt.ui.client.widget.panel.flex.FlexPanel;
import com.googlecode.mgwt.ui.client.widget.panel.flex.IsFlexible;
import com.googlecode.mgwt.ui.client.widget.panel.scroll.ScrollAnimationMoveEvent;
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.touch.TouchWidget;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* This widget uses a {@link GroupingCellList} to render children within groups.
* On top of that it provides a fast selection through a bar on the right by
* displaying symbols for group names.
*
* It also animates a header group so that the user can always see which group
* he is currently scrolling in.
*
* @author Daniel Kurka
*
* @param <G> type of the group
* @param <T> type of the children1
*/
public class HeaderList<G, T> extends Composite implements IsFlexible {

  private static class SelectionBar<G, T> extends TouchWidget implements TouchHandler, HasSelectionHandlers<Integer> {

    private int selectedIndex;
    private int renderedEntries;
    private final GroupingListCss css;

    public SelectionBar(GroupingListCss css) {
      this.css = css;
      setElement(Document.get().createULElement());

      addStyleName(css.selectionBar());

      selectedIndex = 0;

      mapping = new HashMap<Integer, Integer>();

      addTouchHandler(this);
    }

    @Override
    public void onTouchStart(TouchStartEvent event) {
      calculateSelection(event.getTouches().get(0).getPageY());
      addStyleName(css.selectionBarActive());

    }

    @Override
    public void onTouchMove(TouchMoveEvent event) {
      calculateSelection(event.getTouches().get(0).getPageY());
      if (MGWT.getOsDetection().isAndroid()) {
        event.preventDefault();
      }
    }

    @Override
    public void onTouchEnd(TouchEndEvent event) {
      removeStyleName(css.selectionBarActive());
    }

    @Override
    public void onTouchCancel(TouchCancelEvent event) {
      removeStyleName(css.selectionBarActive());
    }

    protected void calculateSelection(int y) {

      int absoluteTop = getElement().getAbsoluteTop();
      int absoluteBottom = getElement().getAbsoluteBottom();

      int normalized_y = y - absoluteTop;
      int height = absoluteBottom - absoluteTop;

      int index = (normalized_y * renderedEntries) / height;

      if (index != selectedIndex) {
        SelectionEvent.fire(this, mapping.get(index));
      }

      selectedIndex = index;

    }

    @Override
    public HandlerRegistration addSelectionHandler(SelectionHandler<Integer> handler) {
      return addHandler(handler, SelectionEvent.getType());
    }

    public void render(List<CellGroup<G, T>> list) {

      mapping.clear();
      StringBuffer buffer = new StringBuffer();

      renderedEntries = 0;
      int target = 0;
      for (CellGroup<?, ?> cellGroup : list) {
        buffer.append("<li>" + cellGroup.getKey() + "</li>");

        mapping.put(renderedEntries, target);

        if (!cellGroup.getMember().isEmpty()) {
          target++;
        }

        renderedEntries++;

      }

      getElement().setInnerHTML(buffer.toString());
    }

    private Map<Integer, Integer> mapping;

  }

  private static class MovingHeader extends Widget {

    public MovingHeader(CellListCss listCss, GroupingListCss css) {

      setElement(Document.get().createDivElement());
      addStyleName(listCss.listHeadElement());
      addStyleName(css.movingHeader());

    }

    public void setHTML(String string) {
      getElement().setInnerHTML(string);

    }
  }

  private FlexPanel main;
  private ScrollPanel scrollPanel;
  private MovingHeader movingHeader;
  private LightArrayInt pagesY;

  private int currentPage;
  private final GroupingCellList<G, T> cellList;

  private boolean needReset = false;

  private int lastPage = -1;
  private SelectionBar<G, T> selectionBar;
  private List<CellGroup<G, T>> list;

  private boolean headerVisible = true;
  private GroupingListCss css;

  /**
   * Construct a HeaderList
   *
   * @param cellList the cell list that renders its children inside this
   *            widget.
   */
  public HeaderList(GroupingCellList<G, T> cellList) {
    this(cellList, GroupingCellList.DEFAULT_APPEARANCE);
  }

  /**
   * Construct a cell list with a given cell list and css
   *
   * @param cellList the cell list that renders its children inside this
   *            widget
   * @param css the css to use
   */
  public HeaderList(GroupingCellList<G, T> cellList, GroupingCellListAppearance appearance) {

    this.cellList = cellList;
    this.css = appearance.groupCss();

    css.ensureInjected();
    main = new FlexPanel();
    initWidget(main);

    main.addStyleName(css.groupingHeaderList());

    currentPage = 0;

    selectionBar = new SelectionBar<G, T>(css);
    main.add(selectionBar);

    scrollPanel = new ScrollPanel();

    scrollPanel.setWidget(cellList);
    scrollPanel.setSnapSelector(cellList.getHeaderSelector());

    scrollPanel.setShowScrollBarX(false);

    main.add(scrollPanel);
    movingHeader = new MovingHeader(cellList.getListCss(), css);
    main.add(movingHeader);

    scrollPanel.addScrollRefreshHandler(new ScrollRefreshEvent.Handler() {

      @Override
      public void onScrollRefresh(ScrollRefreshEvent event) {
        pagesY = scrollPanel.getPagesY();
      }
    });

    selectionBar.addSelectionHandler(new SelectionHandler<Integer>() {

      @Override
      public void onSelection(SelectionEvent<Integer> event) {

        scrollPanel.scrollToPage(0, event.getSelectedItem(), 0);
        currentPage = event.getSelectedItem();
        updateCurrentPage(scrollPanel.getY());
        updateHeaderPositionAndTitle(scrollPanel.getY());

      }
    });

    scrollPanel.addScrollMoveHandler(new ScrollMoveEvent.Handler() {

      @Override
      public void onScrollMove(ScrollMoveEvent event) {
        updateCurrentPage(scrollPanel.getY());
        updateHeaderPositionAndTitle(scrollPanel.getY());

      }
    });

    scrollPanel.addScrollAnimationMoveHandler(new ScrollAnimationMoveEvent.Handler() {

      @Override
      public void onScrollAnimationMove(ScrollAnimationMoveEvent event) {
        updateCurrentPage(scrollPanel.getY());
        updateHeaderPositionAndTitle(scrollPanel.getY());

      }
    });
  }

  /**
   * Render the list of models
   *
   * @param list the models to render
   */
  public void render(List<CellGroup<G, T>> list) {
    this.list = list;
    selectionBar.render(list);
    cellList.renderGroup(list);

    scrollPanel.refresh();

  }

  private void updateCurrentPage(int y) {
    int i;
    for (i = 0; i < pagesY.length(); i++) {
      int page_start = pagesY.get(i);
      if (page_start < y) {
        break;
      }
    }

    currentPage = i - 1;

    if (currentPage < 0)
      currentPage = 0;
    if (currentPage > pagesY.length() - 1) {
      currentPage = pagesY.length() - 1;
    }

  }

  private void updateHeaderPositionAndTitle(int y) {

    int headerHeight = movingHeader.getOffsetHeight();

    if (lastPage != currentPage) {
      lastPage = currentPage;
      int modelIndex = cellList.getMapping().get(currentPage);
      movingHeader.setHTML(cellList.renderGroupHeader(list.get(modelIndex).getGroup()));
    }

    if (y > 0) {
      if (headerVisible) {
        headerVisible = false;
        movingHeader.setVisible(false);
      }

      return;
    } else {
      if (!headerVisible) {
        headerVisible = true;
        movingHeader.setVisible(true);
      }

    }

    if (currentPage + 1 < pagesY.length()) {

      int nextHeader = pagesY.get(currentPage + 1);

      if (nextHeader + headerHeight - y > 0) {
        int move = -(nextHeader + headerHeight - y);
        CssUtil.translate(movingHeader.getElement(), 0, move);

        needReset = true;
      } else {
        if (needReset) {
          needReset = false;
          CssUtil.translate(movingHeader.getElement(), 0, 0);
        }

      }
    }
  }

}
TOP

Related Classes of com.googlecode.mgwt.ui.client.widget.list.celllist.HeaderList

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.