Package com.extjs.gxt.ui.client.widget.grid

Source Code of com.extjs.gxt.ui.client.widget.grid.GroupingView

/*
* Ext GWT - Ext for GWT
* Copyright(c) 2007, 2008, Ext JS, LLC.
* licensing@extjs.com
*
* http://extjs.com/license
*/
package com.extjs.gxt.ui.client.widget.grid;

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

import com.extjs.gxt.ui.client.Events;
import com.extjs.gxt.ui.client.GXT;
import com.extjs.gxt.ui.client.XDOM;
import com.extjs.gxt.ui.client.core.El;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MenuEvent;
import com.extjs.gxt.ui.client.event.SelectionEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.GroupingStore;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.util.Point;
import com.extjs.gxt.ui.client.widget.menu.CheckMenuItem;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.extjs.gxt.ui.client.widget.menu.SeparatorMenuItem;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;

public class GroupingView extends GridView {

  protected boolean enableGrouping;

  private GroupingStore groupingStore;
  private boolean showGroupedColumn = true;
  private boolean enableGroupingMenu = true;
  private boolean isUpdating;
  private boolean showGroupName;
  private String lastGroupField;
  private boolean startCollapsed;
  private GridGroupRenderer groupRenderer;
  private boolean enableNoGroups = true;
  private Map<String, Boolean> state = new HashMap<String, Boolean>();

  /**
   * Collapses all groups.
   */
  public void collapseAllGroups() {
    toggleAllGroups(false);
  }

  /**
   * Expands all groups.
   */
  public void expandAllGroups() {
    toggleAllGroups(true);
  }

  /**
   * Returns the group renderer.
   *
   * @return the group renderer
   */
  public GridGroupRenderer getGroupRenderer() {
    return groupRenderer;
  }

  @Override
  public void initData(ListStore ds, ColumnModel cm) {
    super.initData(ds, cm);
    groupingStore = (GroupingStore) ds;
  }

  /**
   * Returns true if the grouping menu is enabled.
   *
   * @return the enable grouping state
   */
  public boolean isEnableGroupingMenu() {
    return enableGroupingMenu;
  }

  /**
   * Returns true if the user can turn off grouping.
   *
   * @return the enable no groups state
   */
  public boolean isEnableNoGroups() {
    return enableNoGroups;
  }

  /**
   * Returns true if the grouped column is visible.
   *
   * @return the show grouped column
   */
  public boolean isShowGroupedColumn() {
    return showGroupedColumn;
  }

  /**
   * Returns true if start collapsed is enabled.
   *
   * @return the start collapsed state
   */
  public boolean isStartCollapsed() {
    return startCollapsed;
  }

  /**
   * True to enable the grouping entry in the header context menu (defaults to
   * true).
   *
   * @param enableGroupingMenu true to enable
   */
  public void setEnableGroupingMenu(boolean enableGroupingMenu) {
    this.enableGroupingMenu = enableGroupingMenu;
  }

  /**
   * True to allow the user to turn off grouping by adding a check item to the
   * header context menu (defaults to true).
   *
   * @param enableNoGroups true to enable turning off grouping
   */
  public void setEnableNoGroups(boolean enableNoGroups) {
    this.enableNoGroups = enableNoGroups;
  }

  /**
   * Sets the group renderer.
   *
   * @param groupRenderer the group renderer
   */
  public void setGroupRenderer(GridGroupRenderer groupRenderer) {
    this.groupRenderer = groupRenderer;
  }

  /**
   * Sets whether the grouped column is visible (defaults to true).
   *
   * @param showGroupedColumn true to show the grouped column
   */
  public void setShowGroupedColumn(boolean showGroupedColumn) {
    this.showGroupedColumn = showGroupedColumn;
  }

  /**
   * Sets whether the groups should start collapsed (defaults to false).
   *
   * @param startCollapsed true to start collapsed
   */
  public void setStartCollapsed(boolean startCollapsed) {
    this.startCollapsed = startCollapsed;
  }

  /**
   * Toggles all groups.
   *
   * @param expanded true to expand
   */
  public void toggleAllGroups(boolean expanded) {
    NodeList<Element> groups = getGroups();
    for (int i = 0, len = groups.getLength(); i < len; i++) {
      toggleGroup(groups.getItem(i), expanded);
    }
  }

  @Override
  protected Menu createContextMenu(final int colIndex) {
    Menu menu = super.createContextMenu(colIndex);

    if (menu != null && enableGroupingMenu && cm.isGroupable(colIndex)) {
      MenuItem groupBy = new MenuItem(GXT.MESSAGES.groupingView_groupByText());
      groupBy.setIconStyle("x-group-by-icon");
      groupBy.addSelectionListener(new SelectionListener<MenuEvent>() {

        @Override
        public void componentSelected(MenuEvent ce) {
          onGroupByClick(ce, colIndex);
        }

      });
      menu.add(new SeparatorMenuItem());
      menu.add(groupBy);
    }

    if (menu != null && enableGroupingMenu && enableGrouping && enableNoGroups) {
      final CheckMenuItem showInGroups = new CheckMenuItem(
          GXT.MESSAGES.groupingView_showGroupsText());
      showInGroups.setEnabled(cm.isGroupable(colIndex));
      showInGroups.setChecked(true);
      showInGroups.addSelectionListener(new SelectionListener<MenuEvent>() {

        @Override
        public void componentSelected(MenuEvent ce) {
          onShowGroupsClick(ce, showInGroups.isChecked());
        }
      });
      menu.add(showInGroups);
    }
    return menu;
  }

  protected void doGroupEnd(StringBuilder buf, GroupColumnData g, List<ColumnData> cs, int colCount) {
    buf.append(templates.endGroup());
  }

  protected void doGroupStart(StringBuilder buf, GroupColumnData g, List<ColumnData> cs,
      int colCount) {
    buf.append(templates.startGroup(g.groupId, g.css, g.style, g.group.toString()));
  }

  @Override
  protected String doRender(List<ColumnData> cs, List rows, int startRow, int colCount,
      boolean stripe) {
    if (rows.size() < 1) {
      return "";
    }

    String groupField = getGroupField();
    int colIndex = cm.findColumnIndex(groupField);

    enableGrouping = groupField != null;

    if (!enableGrouping || isUpdating) {
      return super.doRender(cs, rows, startRow, colCount, stripe);
    }

    String gstyle = "width:" + getTotalWidth() + ";";
    String gidPrefix = grid.getId();

    ColumnConfig cfg = cm.getColumn(colIndex);

    String prefix = showGroupName ? cfg.getHeader() + ": " : "";

    GroupColumnData curGroup = null;
    String gid = null;

    List<GroupColumnData> groups = new ArrayList<GroupColumnData>();

    for (int j = 0; j < rows.size(); j++) {
      ModelData model = (ModelData) rows.get(j);

      int rowIndex = (j + startRow);

      // the value for the group field
      Object gvalue = model.get(groupField);

      // the rendered group value
      String g = getGroup(gvalue, model, rowIndex, colIndex, ds);

      if (curGroup == null || !curGroup.group.equals(g)) {
        gid = gidPrefix + "-gp-" + groupField + "-" + g;

        boolean isCollapsed = state.get(gid) != null ? !state.get(gid) : startCollapsed;
        String gcls = isCollapsed ? "x-grid-group-collapsed" : "";

        curGroup = new GroupColumnData();
        curGroup.group = g;
        curGroup.field = groupField;
        curGroup.gvalue = gvalue;
        curGroup.text = prefix + g;
        curGroup.groupId = gid;
        curGroup.startRow = rowIndex;
        curGroup.style = gstyle;
        curGroup.css = gcls;
        curGroup.models.add(model);
        groups.add(curGroup);

      } else {
        curGroup.models.add(model);
      }
      model.set("_groupId", gid);

    }

    for (GroupColumnData group : groups) {
      if (groupRenderer != null) {
        String g = groupRenderer.render(group);
        if (g == null || g.equals("")) {
          g = "&nbsp;";
        }
        group.group = groupRenderer.render(group);
      }
    }

    StringBuilder buf = new StringBuilder();

    for (int i = 0, len = groups.size(); i < len; i++) {
      GroupColumnData g = groups.get(i);
      doGroupStart(buf, g, cs, colCount);
      buf.append(super.doRender(cs, g.models, g.startRow, colCount, stripe));
      doGroupEnd(buf, g, cs, colCount);
    }

    return buf.toString();
  }

  protected String getGroup(Object value, ModelData m, int rowIndex, int colIndex, ListStore ds) {
    return value == null ? "" : value.toString();
  }

  protected NodeList getGroups() {
    return mainBody.dom.getChildNodes();
  }

  @Override
  protected Element[] getRows() {
    if (!enableGrouping) {
      return super.getRows();
    }

    NodeList<Element> gs = getGroups();
    List<Element> rows = new ArrayList<Element>();
    for (int i = 0, len = gs.getLength(); i < len; i++) {
      NodeList g = gs.getItem(i).getChildNodes().getItem(1).getChildNodes();
      for (int j = 0, len2 = g.getLength(); j < len2; j++) {
        rows.add((Element) g.getItem(j));
      }
    }
    return rows.toArray(new Element[0]);
  }

  protected JavaScriptObject getRowsNative(Element body) {
    if (!enableGrouping) {
      return super.getRowsNative(mainBody.dom);
    }
    return getRowsFromGroups(mainBody.dom);
  }

  @Override
  protected void initTemplates() {
    super.initTemplates();

    GridSelectionModel sm = grid.getSelectionModel();
    if (sm instanceof CellSelectionModel) {
      sm.addListener(Events.BeforeSelect, new Listener<SelectionEvent>() {
        public void handleEvent(SelectionEvent be) {
          onBeforeRowSelect(be);
        }
      });
    } else {
      sm.addListener(Events.BeforeSelect, new Listener<SelectionEvent>() {
        public void handleEvent(SelectionEvent be) {
          onBeforeRowSelect(be);
        }
      });
    }
  }

  @Override
  protected void onAdd(ListStore store, List models, int index) {
    if (enableGrouping) {
      Point ss = getScrollState();
      refresh(false);
      restoreScroll(ss);
    } else {
      super.onAdd(store, models, index);
    }
  }

  @Override
  protected void onMouseDown(GridEvent ge) {
    El hd = ge.getTarget(".x-grid-group-hd", 10);
    if (hd != null) {
      ge.stopEvent();
      toggleGroup(hd.dom.getParentElement(), isGroupExpanded(hd.dom.getParentElement()));
    }
  }

  @Override
  protected void onRemove(ListStore ds, ModelData m, int index, boolean isUpdate) {
    super.onRemove(ds, m, index, isUpdate);
    Element g = XDOM.getElementById(m.<String> get("_groupId"));
    if (g != null && g.getChildNodes().getItem(1).getChildNodes().getLength() < 1) {
      fly(g).removeFromParent();
    }
    // appply empty text
  }

  protected void onShowGroupsClick(MenuEvent be, boolean checked) {
    if (checked) {
      onGroupByClick(be, activeHdIndex);
    } else {
      groupingStore.clearGrouping();
    }
  }

  @Override
  protected void refreshRow(int row) {
    if (ds.getCount() == 1) {
      refresh(false);
    } else {
      isUpdating = true;
      super.refreshRow(row);
      isUpdating = false;
    }
  }

  @Override
  protected String renderRows(int startRow, int endRow) {
    String groupField = getGroupField();
    boolean eg = groupField != null;
    if (!showGroupedColumn) {
      int colIndex = cm.findColumnIndex(groupField);
      if (!eg && lastGroupField != null) {
        mainBody.update("");
        cm.setHidden(cm.findColumnIndex(lastGroupField), false);
        lastGroupField = null;
      } else if (eg && lastGroupField == null) {
        lastGroupField = groupField;
        cm.setHidden(colIndex, true);
      } else if (eg && lastGroupField != null && !groupField.equals(lastGroupField)) {
        mainBody.update("");
        int oldIndex = cm.findColumnIndex(lastGroupField);
        cm.setHidden(oldIndex, false);
        lastGroupField = groupField;
        cm.setHidden(colIndex, true);
      }
    }
    return super.renderRows(startRow, endRow);
  }

  @Override
  protected void templateOnAllColumnWidthsUpdated(List<String> ws, String tw) {
    updateGroupWidths();
  }

  @Override
  protected void templateOnColumnWidthUpdated(int col, String w, String tw) {
    updateGroupWidths();
  }

  @Override
  protected void templateOnLayout(int vw, int vh) {
    updateGroupWidths();
  }

  private Element findGroup(Element el) {
    return fly(el).up(".x-grid-group", 10).dom;
  }

  private String getGroupField() {
    return groupingStore.getGroupState();
  }

  private native JavaScriptObject getRowsFromGroups(Element body) /*-{
      var r = [];
      var g, gs = body.childNodes;
      for(var i = 0, len = gs.length; i < len; i++){
          g = gs[i].childNodes[1].childNodes;
          for(var j = 0, jlen = g.length; j < jlen; j++){
              r[r.length] = g[j];
          }
      }
      return r;
    }-*/;

  private boolean isGroupExpanded(Element g) {
    return fly(g).hasStyleName("x-grid-group-collapsed");
  }

  private void onBeforeRowSelect(SelectionEvent se) {
    if (!enableGrouping) {
      return;
    }
    Element row = getRow(se.index);
    if (row != null && row.getOffsetParent() != null) {
      Element g = findGroup(row);
      toggleGroup(g, true);
    }
  }

  private void onGroupByClick(MenuEvent me, int colIndex) {
    groupingStore.groupBy(cm.getDataIndex(colIndex));
  }

  private void toggleGroup(Element g, boolean expanded) {
    if (grid instanceof EditorGrid) {
      ((EditorGrid) grid).stopEditing();
    }
    El gel = fly(g);
    state.put(gel.getId(), expanded);
    if (expanded) {
      gel.removeStyleName("x-grid-group-collapsed");
    } else {
      gel.addStyleName("x-grid-group-collapsed");
    }
  }

  private void updateGroupWidths() {
    if (!enableGrouping || ds.getCount() < 1) {
      return;
    }
    String tw = Math.max(cm.getTotalWidth(), el.dom.getOffsetWidth() - scrollOffset) + "px";
    NodeList gs = getGroups();
    for (int i = 0, len = gs.getLength(); i < len; i++) {
      Element e = gs.getItem(i).getFirstChild().cast();
      e.getStyle().setProperty("width", tw);
    }
  }

}
TOP

Related Classes of com.extjs.gxt.ui.client.widget.grid.GroupingView

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.