Package com.sencha.gxt.widget.core.client.grid

Source Code of com.sencha.gxt.widget.core.client.grid.GroupingView$GroupSummaryTemplate

/**
* Sencha GXT 3.1.0-beta - Sencha for GWT
* Copyright(c) 2007-2014, Sencha, Inc.
* licensing@sencha.com
*
* http://www.sencha.com/products/gxt/license/
*/
package com.sencha.gxt.widget.core.client.grid;

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

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;
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.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.safecss.shared.SafeStyles;
import com.google.gwt.safecss.shared.SafeStylesUtils;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.core.client.GXT;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.core.client.dom.XElement;
import com.sencha.gxt.core.client.util.Point;
import com.sencha.gxt.core.client.util.Util;
import com.sencha.gxt.data.shared.SortDir;
import com.sencha.gxt.data.shared.SortInfo;
import com.sencha.gxt.data.shared.SortInfoBean;
import com.sencha.gxt.data.shared.Store.StoreSortInfo;
import com.sencha.gxt.messages.client.DefaultMessages;
import com.sencha.gxt.widget.core.client.event.CheckChangeEvent;
import com.sencha.gxt.widget.core.client.event.CheckChangeEvent.CheckChangeHandler;
import com.sencha.gxt.widget.core.client.event.CollapseItemEvent;
import com.sencha.gxt.widget.core.client.event.CollapseItemEvent.CollapseItemHandler;
import com.sencha.gxt.widget.core.client.event.CollapseItemEvent.HasCollapseItemHandlers;
import com.sencha.gxt.widget.core.client.event.ExpandItemEvent;
import com.sencha.gxt.widget.core.client.event.ExpandItemEvent.ExpandItemHandler;
import com.sencha.gxt.widget.core.client.event.ExpandItemEvent.HasExpandItemHandlers;
import com.sencha.gxt.widget.core.client.menu.CheckMenuItem;
import com.sencha.gxt.widget.core.client.menu.Item;
import com.sencha.gxt.widget.core.client.menu.Menu;
import com.sencha.gxt.widget.core.client.menu.MenuItem;
import com.sencha.gxt.widget.core.client.menu.SeparatorMenuItem;

/**
* <code>GridView</code> that groups data based on a given grouping column.
*
* @param <M> the model type
*/
public class GroupingView<M> extends GridView<M> implements HasCollapseItemHandlers<List<M>>,
    HasExpandItemHandlers<List<M>> {

  /**
   * Wrapper describing a given group, with the items in the group, and the value they hold in common. These are not
   * presently persisted, but only analyzed when changes occur to the grid's data.
   *
   * @param <M> the type of row in the grid
   */
  public static class GroupingData<M> {
    private final Object value;
    private final int startRow;
    private final List<M> items = new ArrayList<M>();
    private boolean collapsed;

    public GroupingData(Object value, int startRow) {
      this.value = value;
      this.startRow = startRow;
    }

    @Override
    public boolean equals(Object other) {
      if (other instanceof GroupingData) {
        return Util.equalWithNull(((GroupingData<?>) other).value, value);
      }
      return false;
    }

    public List<M> getItems() {
      return items;
    }

    public int getStartRow() {
      return startRow;
    }

    public Object getValue() {
      return value;
    }

    @Override
    public int hashCode() {
      return value == null ? 0 : value.hashCode();
    }

    public boolean isCollapsed() {
      return collapsed;
    }

    public void setCollapsed(boolean collapsed) {
      this.collapsed = collapsed;
    }

  }

  public interface GroupingViewAppearance {

    XElement findHead(XElement element);

    XElement getGroup(XElement head);

    ImageResource groupByIcon();

    boolean isCollapsed(XElement group);

    void onGroupExpand(XElement group, boolean expanded);

    SafeHtml renderGroupHeader(GroupingData<?> groupInfo);

    GroupingViewStyle style();
  }

  public interface GroupingViewStyle extends CssResource {

    String group();

    String groupCollapsed();

    String groupHead();

    String bodyCollapsed();
  }

  public interface GroupSummaryTemplate<M> {
    SafeHtml renderGroupSummary(GroupingData<M> groupInfo);
  }

  protected ColumnConfig<M, ?> lastGroupField;
  protected ColumnConfig<M, ?> groupingColumn;

  protected boolean enableGrouping;

  @SuppressWarnings("unused")
  private GroupSummaryTemplate<M> groupSummaryTemplate;
  private final GroupingViewAppearance groupAppearance;

  private boolean enableGroupingMenu = true;
  private boolean enableNoGroups = true;
  private boolean showGroupedColumn = true;
  private boolean startCollapsed = false;
  protected final Map<Object, Boolean> state = new HashMap<Object, Boolean>();

  private boolean isUpdating = false;
  private StoreSortInfo<M> lastStoreSort;
  private SortInfo lastSort;

  /**
   * Creates a new grouping view instance.
   */
  public GroupingView() {
    this(GWT.<GridAppearance> create(GridAppearance.class),
        GWT.<GroupingViewAppearance> create(GroupingViewAppearance.class));
  }

  /**
   * Creates a new grouping view instance.
   *
   * @param appearance the grid appearance
   * @param groupingAppearance the grouping appearance
   */
  public GroupingView(GridAppearance appearance, GroupingViewAppearance groupingAppearance) {
    super(appearance);
    this.groupAppearance = groupingAppearance;
  }

  /**
   * Creates a new grouping view instance.
   *
   * @param groupAppearance the group appearance
   */
  public GroupingView(GroupingViewAppearance groupAppearance) {
    this(GWT.<GridAppearance> create(GridAppearance.class), groupAppearance);
  }

  @Override
  public HandlerRegistration addCollapseHandler(CollapseItemHandler<List<M>> handler) {
    return addHandler(CollapseItemEvent.getType(), handler);
  }

  @Override
  public HandlerRegistration addExpandHandler(ExpandItemHandler<List<M>> handler) {
    return addHandler(ExpandItemEvent.getType(), handler);
  }

  @Override
  protected void afterRender() {
    ColumnConfig<M, ?> column = groupingColumn;

    // set groupingColumn to null to force regrouping only if grouping
    // hasn't already occurred
    if (lastStoreSort == null && lastSort == null && column != null) {
      groupingColumn = null;
    }
    groupBy(column);
    super.afterRender();
  }

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

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

    if (menu != null && enableGroupingMenu) {
      if (cm.isGroupable(colIndex)) {
        MenuItem groupBy = new MenuItem(DefaultMessages.getMessages().groupingView_groupByText());
        groupBy.setIcon(groupAppearance.groupByIcon());
        groupBy.addSelectionHandler(new SelectionHandler<Item>() {
          @Override
          public void onSelection(SelectionEvent<Item> event) {
            groupBy(cm.getColumn(colIndex));
          }
        });
        menu.add(new SeparatorMenuItem());
        menu.add(groupBy);

        groupBy.setEnabled(cm.getColumnCount(true) > 1);

        initMenuColumnShowHideHandling(menu, groupBy);
      }
      if (enableGrouping && enableNoGroups) {
        final CheckMenuItem showInGroups = new CheckMenuItem(
            DefaultMessages.getMessages().groupingView_showGroupsText());
        showInGroups.setChecked(true);
        showInGroups.addSelectionHandler(new SelectionHandler<Item>() {
          @Override
          public void onSelection(SelectionEvent<Item> event) {
            if (showInGroups.isChecked()) {
              groupBy(cm.getColumn(colIndex));
            } else {
              groupBy(null);
            }
          }
        });
        menu.add(showInGroups);
      }
    }

    return menu;
  }

  @Override
  protected SafeHtml doRender(List<ColumnData> cs, List<M> rows, int startRow) {
    enableGrouping = groupingColumn != null;

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

    GroupingData<M> curGroup = null;

    List<GroupingData<M>> groups = new ArrayList<GroupingData<M>>();

    // iterate through each item, creating a new group as needed. Assumes the
    // list is sorted
    for (int j = 0; j < rows.size(); j++) {
      M model = rows.get(j);

      int rowIndex = (j + startRow);

      // the value for the group field
      final Object gvalue;
      if (ds.hasRecord(model)) {
        gvalue = ds.getRecord(model).getValue(groupingColumn.getValueProvider());
      } else {
        gvalue = groupingColumn.getValueProvider().getValue(model);
      }

      if (curGroup == null || !Util.equalWithNull(curGroup.getValue(), gvalue)) {
        curGroup = new GroupingData<M>(gvalue, rowIndex);
        curGroup.setCollapsed(state.containsKey(gvalue) ? state.get(gvalue) : isStartCollapsed());
        curGroup.getItems().add(model);
        assert !groups.contains(curGroup);
        groups.add(curGroup);

      } else {
        curGroup.getItems().add(model);
      }
    }

    SafeHtmlBuilder buf = new SafeHtmlBuilder();

    String styles = "width:" + getTotalWidth() + "px;";
    SafeStyles tableStyles = SafeStylesUtils.fromTrustedString(styles);

    for (int i = 0, len = groups.size(); i < len; i++) {
      GroupingData<M> g = groups.get(i);
      SafeHtml renderedRows = tpls.table(getAppearance().styles().dataTable(), tableStyles,
          super.doRender(cs, g.getItems(), g.getStartRow()), renderHiddenHeaders(getColumnWidths()));
      renderGroup(buf, g, renderedRows);
    }

    return buf.toSafeHtml();
  }

  @Override
  protected void doSort(int colIndex, SortDir sortDir) {
    ColumnConfig<M, ?> column = cm.getColumn(colIndex);
    if (groupingColumn != null) {
      if (grid.getLoader() == null || !grid.getLoader().isRemoteSort()) {
        // first sort is lastStoreSort
        assert lastStoreSort != null;
        ds.getSortInfo().clear();

        StoreSortInfo<M> sortInfo = createStoreSortInfo(column, sortDir);

        if (sortDir == null && storeSortInfo != null
            && storeSortInfo.getValueProvider().getPath().equals(column.getValueProvider().getPath())) {
          sortInfo.setDirection(storeSortInfo.getDirection() == SortDir.ASC ? SortDir.DESC : SortDir.ASC);
        } else if (sortDir == null) {
          sortInfo.setDirection(SortDir.ASC);
        }

        ds.getSortInfo().add(0, lastStoreSort);
        ds.getSortInfo().add(1, sortInfo);

        if (GWT.isProdMode()) {
          ds.applySort(false);
        } else {
          try {
            // applySort will apply its sort when called, which might trigger an
            // exception if the column passed in's data isn't Comparable
            ds.applySort(false);
          } catch (ClassCastException ex) {
            GWT.log("Column can't be sorted " + column.getValueProvider().getPath() + " is not Comparable. ", ex);
            throw ex;
          }
        }
      } else {
        assert lastSort != null;
        ValueProvider<? super M, ?> vp = column.getValueProvider();
        grid.getLoader().clearSortInfo();
        grid.getLoader().addSortInfo(0, lastSort);
        grid.getLoader().addSortInfo(1, new SortInfoBean(vp, sortDir));
        grid.getLoader().load();
      }

    } else {
      super.doSort(colIndex, sortDir);
    }
  }

  protected void doLastSort() {
    StoreSortInfo<M> info = getSortState();
    if (info == null) {
      return;
    }

    ValueProvider<? super M, ?> vp = info.getValueProvider();
    if (vp == null) {
      return;
    }

    String p = vp.getPath();
    if (p == null) {
      return;
    }

    ColumnConfig<M, ?> config = cm.findColumnConfig(p);
    if (config == null) {
      return;
    }

    int index = cm.indexOf(config);
    doSort(index, info.getDirection());
  }

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

  protected List<GroupingData<M>> getGroupData() {
    List<GroupingData<M>> groups = new ArrayList<GroupingData<M>>();

    GroupingData<M> curGroup = null;
    for (int i = 0, len = ds.size(); i < len; i++) {
      M m = ds.get(i);
      final Object gvalue;
      if (ds.hasRecord(m)) {
        gvalue = ds.getRecord(m).getValue(groupingColumn.getValueProvider());
      } else {
        gvalue = groupingColumn.getValueProvider().getValue(m);
      }
      if (curGroup == null || !Util.equalWithNull(curGroup.getValue(), gvalue)) {
        curGroup = new GroupingData<M>(gvalue, i);
        curGroup.setCollapsed(state.containsKey(gvalue) ? state.get(gvalue) : isStartCollapsed());
        curGroup.getItems().add(m);
        assert !groups.contains(curGroup);
        groups.add(curGroup);
      } else {
        curGroup.getItems().add(m);
      }
    }

    return groups;
  }

  /**
   * Returns the grouping view appearance.
   *
   * @return the grouping appearance
   */
  public GroupingViewAppearance getGroupingAppearance() {
    return groupAppearance;
  }

  protected NodeList<Element> getGroups() {
    if (!enableGrouping) {
      return JsArray.createArray().cast();
    }
    return dataTable.<XElement> cast().select("." + groupAppearance.style().group());
  }

  @Override
  protected NodeList<Element> getRows() {
    if (!enableGrouping || !hasRows()) {
      return super.getRows();
    }
    return dataTable.<XElement> cast().select("." + styles.row());
  }

  @Override
  public StoreSortInfo<M> getSortState() {
    if (groupingColumn != null) {
      if (ds.getSortInfo().size() > 1) {
        return ds.getSortInfo().get(1);
      }
    }
    return super.getSortState();
  }

  public void groupBy(ColumnConfig<M, ?> column) {
    if (grid == null) {
      // if still being configured, save the grouping column for later
      groupingColumn = column;
    }

    if (column != groupingColumn) {
      // remove the existing group, if any
      if (groupingColumn != null) {
        if (grid.getLoader() == null || !grid.getLoader().isRemoteSort()) {
          assert lastStoreSort != null && ds.getSortInfo().contains(lastStoreSort);
          // remove the lastStoreSort from the listStore
          ds.getSortInfo().remove(lastStoreSort);
        } else {
          assert lastSort != null;
          grid.getLoader().removeSortInfo(lastSort);
        }
      } else {// groupingColumn == null;
        assert lastStoreSort == null && lastSort == null;
      }

      // set the new one
      groupingColumn = column;
      if (column != null) {
        if (grid.getLoader() == null || !grid.getLoader().isRemoteSort()) {
          lastStoreSort = createStoreSortInfo(column, SortDir.ASC);
          ds.addSortInfo(0, lastStoreSort);// this triggers the sort
        } else {
          lastSort = new SortInfoBean(column.getValueProvider(), SortDir.ASC);
          grid.getLoader().addSortInfo(0, lastSort);
          grid.getLoader().load();
        }
      } else {// new column == null
        lastStoreSort = null;
        lastSort = null;
        // full redraw without groups
        refresh(false);
      }
    }

    if (column == null) {
      doLastSort();
    }
  }

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

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

  /**
   * Returns true if the group is expanded.
   *
   * @param group the group
   * @return true if expanded
   */
  public boolean isExpanded(Element group) {
    return !groupAppearance.isCollapsed(group.<XElement> cast());
  }

  /**
   * 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;
  }

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

  @Override
  protected void onMouseDown(Event ge) {
    super.onMouseDown(ge);
    XElement head = ge.getEventTarget().cast();
    head = groupAppearance.findHead(head);
    if (head != null) {
      ge.stopPropagation();
      XElement group = groupAppearance.getGroup(head);
      int index = getGroupIndex(group);
      toggleGroup(index, groupAppearance.isCollapsed(group));
    }
  }

  protected int getGroupIndex(XElement group) {
    return group.getParentElement().<XElement> cast().indexOf(group) / 2;
  }

  @Override
  protected void onRemove(M m, int index, boolean isUpdate) {
    Element parentToRemove = null;
    if (enableGrouping) {
      Element row = getRow(index).cast();

      // TODO appearance this
      Element groupContainer = row.getParentElement().cast();
      if (groupContainer.getChildCount() == 1) {
        parentToRemove = groupContainer.getParentElement().cast();
      }
    }
    super.onRemove(m, index, isUpdate);
    if (parentToRemove != null) {
      parentToRemove.removeFromParent();
    }
  }

  @Override
  protected void refreshRow(int row) {
    isUpdating = true;
    super.refreshRow(row);
    isUpdating = false;
  }

  protected void renderGroup(SafeHtmlBuilder buf, GroupingData<M> g, SafeHtml renderedRows) {
    String groupClass = groupAppearance.style().group();
    String bodyClass = "";
    if (g.isCollapsed()) {
      groupClass += " " + groupAppearance.style().groupCollapsed();
      bodyClass = groupAppearance.style().bodyCollapsed();
    }
    String headClass = groupAppearance.style().groupHead();
    final SafeHtml groupHtml;
    String cellClasses = headClass + " " + styles.cell() + " " + states.cell();
    if (selectable) {
      groupHtml = (tpls.tr(groupClass,
          tpls.tdWrap(cm.getColumnCount(), cellClasses, styles.cellInner() + " " + states.cellInner(), renderGroupHeader(g))));
    } else {
      String innerCellClasses = styles.cellInner() + " " + states.cellInner() + " " + styles.noPadding();
      if (GXT.isIE()) {
        groupHtml = (tpls.tr(groupClass, tpls.tdWrapUnselectable(cm.getColumnCount(), cellClasses,
                innerCellClasses, renderGroupHeader(g))));
      } else {
        groupHtml = (tpls.tr(groupClass,
            tpls.tdWrap(cm.getColumnCount(), cellClasses, innerCellClasses, renderGroupHeader(g))));
      }

    }
    buf.append(groupHtml);

    buf.append(tpls.tr(bodyClass, tpls.tdWrap(cm.getColumnCount(), "", "", renderedRows)));
  }

  protected SafeHtml renderGroupHeader(GroupingData<M> groupInfo) {
    return groupAppearance.renderGroupHeader(groupInfo);
  }

  @Override
  protected SafeHtml renderRows(int startRow, int endRow) {
    boolean eg = groupingColumn != null;
    if (!showGroupedColumn) {
      int colIndex = cm.indexOf(groupingColumn);
      if (!eg && lastGroupField != null) {
        dataTableBody.removeChildren();
        cm.setHidden(cm.indexOf(lastGroupField), false);
        cm.getColumn(cm.indexOf(lastGroupField)).setHideable(true);
        lastGroupField = groupingColumn;
      } else if (eg && (lastGroupField == null || lastGroupField == groupingColumn)) {
        lastGroupField = groupingColumn;
        cm.setHidden(colIndex, true);
        cm.getColumn(colIndex).setHideable(false);
      } else if (eg && lastGroupField != null && !groupingColumn.equals(lastGroupField)) {
        dataTableBody.removeChildren();
        int oldIndex = cm.indexOf(lastGroupField);
        cm.setHidden(oldIndex, false);
        cm.getColumn(oldIndex).setHideable(true);
        lastGroupField = groupingColumn;
        cm.setHidden(colIndex, true);
        cm.getColumn(colIndex).setHideable(false);
      }
    }
    return super.renderRows(startRow, endRow);
  }

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

  /**
   * True to enable the no groups menu item in the header context menu (defaults to true).
   *
   * @param enableNoGroups true to enable no groups menu item
   */
  public void setEnableNoGroups(boolean enableNoGroups) {
    this.enableNoGroups = enableNoGroups;
  }

  /**
   * 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();
    List<GroupingData<M>> groupData = getGroupData();
    for (int i = 0; i < groups.getLength(); i++) {
      toggleGroup(groups.getItem(i), expanded);
      GroupingData<M> groupingData = groupData.get(i);
      if (expanded) {
        fireEvent(new ExpandItemEvent<List<M>>(groupingData.getItems()));
      } else {
        fireEvent(new CollapseItemEvent<List<M>>(groupingData.getItems()));
      }
    }
  }

  /**
   * Toggles the given group index, dealing with all logical and view details.
   */
  protected void toggleGroup(int i, boolean expanded) {
    GroupingData<M> groupingData = getGroupData().get(i);
    Object key = groupingData.getValue();
    state.put(key, !expanded);
    toggleGroup(getGroups().getItem(i), expanded);
    if (expanded) {
      fireEvent(new ExpandItemEvent<List<M>>(groupingData.getItems()));
    } else {
      fireEvent(new CollapseItemEvent<List<M>>(groupingData.getItems()));
    }
  }

  /**
   * Toggles the visibility of the group elements, but does not handle the internal state details or events.
   */
  protected void toggleGroup(Element group, boolean expanded) {
    assert group != null;
    groupAppearance.onGroupExpand(group.<XElement> cast(), expanded);
    calculateVBar(false);
  }

  private void initMenuColumnShowHideHandling(Menu menu, final MenuItem groupBy) {
    // Loop through the menu and find the columns
    for (int i = 0; i < menu.getWidgetCount(); i++) {
      Widget subMenuWidget = menu.getWidget(i);
      // Only work with the columns MenuItem instances
      if (subMenuWidget instanceof MenuItem) {
        MenuItem columnsMenu = (MenuItem) subMenuWidget;
        String hasColumns = columnsMenu.getData("gxt-columns");
        // Find the columns and add handlers onto the CheckMenuItems columns
        if (hasColumns != null && hasColumns.equals("true")) {
          Menu colMenu = columnsMenu.getSubMenu();
          for (int b = 0; b < colMenu.getWidgetCount(); b++) {
            CheckMenuItem colItem = (CheckMenuItem) colMenu.getWidget(b);
            // Observe column events 'showing' and 'hiding' events
            colItem.addCheckChangeHandler(new CheckChangeHandler<CheckMenuItem>() {
              @Override
              public void onCheckChange(CheckChangeEvent<CheckMenuItem> event) {
                Scheduler.get().scheduleDeferred(new ScheduledCommand() {
                  @Override
                  public void execute() {
                    // Disable the group by option when only *one* column is displayed
                    groupBy.setEnabled(cm.getColumnCount(true) > 1);
                  }
                });
              }
            });
          }
        }
      }
    }
  }

}
TOP

Related Classes of com.sencha.gxt.widget.core.client.grid.GroupingView$GroupSummaryTemplate

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.