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

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

/*
* Ext GWT 2.2.4 - Ext for GWT
* Copyright(c) 2007-2010, 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.List;

import com.extjs.gxt.ui.client.GXT;
import com.extjs.gxt.ui.client.core.XDOM;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.Record;
import com.extjs.gxt.ui.client.util.DelayedTask;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.user.client.ui.Widget;

/**
* Renders the rows as they scroll into view. This GridView is fast for
* displaying many rows at once, but it does not support all features the normal
* {link @GridView} supports, such has expanding rows.
*
* <p />
* Only works with constant row heights that can be specified using
* {@link #setRowHeight(int)}.
*/
public class BufferView extends GridView {

  private boolean bufferEnabled = true;
  private int cacheSize = 20;
  private int cleanDelay = 500;
  private DelayedTask cleanTask;
  private DelayedTask renderTask;
  private int rowHeight = 21;
  private int scrollDelay = 0;

  /**
   * Returns the amount of rows that should be cached.
   *
   * @return the cache size
   */
  public int getCacheSize() {
    return cacheSize;
  }

  /**
   * Returns the amount of time before cleaning is done.
   *
   * @return the clean delay
   */
  public int getCleanDelay() {
    return cleanDelay;
  }

  /**
   * Returns the height of one row.
   *
   * @return the height of one row
   */
  public int getRowHeight() {
    return rowHeight;
  }

  /**
   * Returns the amount of time before new rows are displayed after scrolling
   *
   * @return the scroll delay
   */
  public int getScrollDelay() {
    return scrollDelay;
  }

  /**
   * Returns true if buffering is enabled.
   *
   * @return true for buffering
   */
  public boolean isBufferEnabled() {
    return bufferEnabled;
  }

  /**
   * True to enabled buffered functionality (defaults to true).
   *
   * @param bufferEnabled true to buffer, otherwise false
   */
  public void setBufferEnabled(boolean bufferEnabled) {
    this.bufferEnabled = bufferEnabled;
  }

  /**
   * Sets the amount of rows that should be cached (default to 20).
   *
   * @param cacheSize the new cache size
   */
  public void setCacheSize(int cacheSize) {
    this.cacheSize = cacheSize;
  }

  /**
   * Sets the amount of time before cleaning is done (defaults to 500).
   *
   * @param cleanDelay the new clean delay
   */
  public void setCleanDelay(int cleanDelay) {
    this.cleanDelay = cleanDelay;
  }

  /**
   * Sets the height of one row (defaults to 19).
   *
   * @param rowHeight the new row height.
   */
  public void setRowHeight(int rowHeight) {
    this.rowHeight = rowHeight;
  }

  /**
   * Sets the amount of time before new rows are displayed after scrolling
   * (defaults to 0).
   *
   * @param scrollDelay the new scroll delay.
   */
  public void setScrollDelay(int scrollDelay) {
    this.scrollDelay = scrollDelay;
  }

  // a buffered method to clean rows
  protected void clean() {
    if (grid == null || !grid.isViewReady() || !bufferEnabled) {
      return;
    }
    if (cleanTask == null) {
      cleanTask = new DelayedTask(new Listener<BaseEvent>() {
        public void handleEvent(BaseEvent be) {
          doClean();
        }
      });
    }
    cleanTask.delay(cleanDelay);
  }

  protected void cleanModel(ModelData at) {
  }

  @Override
  protected void doAttach() {
    super.doAttach();
    update();
  }

  protected void doClean() {
    if (grid == null || !grid.isViewReady() || !bufferEnabled) {
      return;
    }
    int count = getVisibleRowCount();
    if (count > 0) {
      int[] vr = getVisibleRows(count);
      vr[0] -= cacheSize;
      vr[1] += cacheSize;

      int i = 0;
      NodeList<Element> rows = getRows();
      // if first is less than 0, all rows have been rendered
      // so lets clean the end...
      if (vr[0] <= 0) {
        i = vr[1] + 1;
      }
      for (int len = grid.getStore().getCount(); i < len; i++) {
        // if current row is outside of first and last and
        // has content, update the innerHTML to nothing
        if ((i < vr[0] || i > vr[1])) {
          detachWidget(i, false);
          widgetList.set(i, null);
          cleanModel(ds.getAt(i));
          rows.getItem(i).setInnerHTML("");
        }
      }
    }
  }

  @Override
  protected String doRender(List<ColumnData> cs, List<ModelData> rows, int startRow, int colCount, boolean stripe) {
    if (!bufferEnabled) {
      return super.doRender(cs, rows, startRow, colCount, stripe);
    }
    return doRender(cs, rows, startRow, colCount, stripe, false);
  }

  protected String doRender(List<ColumnData> cs, List<ModelData> rows, int startRow, int colCount, boolean stripe,
      boolean onlyBody) {

    int last = colCount - 1;

    int rowBodyColSpanCount = colCount;
    if (enableRowBody) {
      if (grid.getSelectionModel() instanceof CheckBoxSelectionModel<?>) {
        CheckBoxSelectionModel<?> sm = (CheckBoxSelectionModel<?>) grid.getSelectionModel();
        if (cm.getColumnById(sm.getColumn().getId()) != null) {
          rowBodyColSpanCount--;
        }
      }
      for (ColumnConfig c : cm.getColumns()) {
        if (c instanceof RowExpander || c instanceof RowNumberer) {
          rowBodyColSpanCount--;
        }
      }
    }

    int rh = getStyleRowHeight();
    int[] vr = getVisibleRows(getVisibleRowCount());
    String tstyle = "width:" + getTotalWidth() + "px;height:" + rh + "px;";
    // buffers
    StringBuilder buf = new StringBuilder();
    StringBuilder cb = new StringBuilder();
    for (int j = 0, len = rows.size(); j < len; j++) {
      ModelData model = (ModelData) rows.get(j);

      model = prepareData(model);

      Record r = ds.hasRecord(model) ? ds.getRecord(model) : null;
      int rowIndex = (j + startRow);
      boolean visible = rowIndex >= vr[0] && rowIndex <= vr[1];
      if (!onlyBody) {
        widgetList.add(rowIndex, new ArrayList<Widget>());
      }
      if (visible) {
        for (int i = 0; i < colCount; i++) {
          ColumnData c = cs.get(i);
          c.css = c.css == null ? "" : c.css;
          String rv = getRenderedValue(c, rowIndex, i, model, c.name);

          String css = (i == 0 ? "x-grid-cell-first " : (i == last ? "x-grid3-cell-last " : " ")) + " "
              + (c.css == null ? "" : c.css);
          String attr = c.cellAttr != null ? c.cellAttr : "";
          String cellAttr = c.cellAttr != null ? c.cellAttr : "";

          if (isShowInvalidCells() && r != null && !r.isValid(c.id)) {
            buf.append(" x-grid3-invalid-cell");
          }
          if (isShowDirtyCells() && r != null && r.getChanges().containsKey(c.id)) {
            css += " x-grid3-dirty-cell";
          }

          cb.append("<td id=\"" + XDOM.getUniqueId()
              + "\" role=\"gridcell\" class=\"x-grid3-col x-grid3-cell x-grid3-td-");
          cb.append(c.id);
          cb.append(" ");
          cb.append(css);
          cb.append("\" style=\"");
          cb.append(c.style);
          cb.append("\" ");
          cb.append(cellAttr);
          cb.append("><div unselectable=\"on\" class=\"x-grid3-cell-inner x-grid3-col-");
          cb.append(c.id);
          cb.append("\" ");
          cb.append(attr);
          cb.append(">");
          cb.append(rv);
          cb.append("</div></td>");

        }
      }
      String alt = "";
      if (stripe && ((rowIndex + 1) % 2 == 0)) {
        alt += " x-grid3-row-alt";
      }

      if (isShowDirtyCells() && r != null && r.isDirty()) {
        alt += " x-grid3-dirty-row";
      }

      if (!selectable) {
        alt += " x-unselectable-single";
      }

      if (viewConfig != null) {
        alt += " " + viewConfig.getRowStyle(model, rowIndex, ds);
      }

      if (!onlyBody || !visible) {
        buf.append("<div role=\"row\" class=\"x-grid3-row ");
        buf.append(alt);
        buf.append("\" style=\"");
        buf.append(tstyle);
        buf.append("\" id=\"");
        buf.append(grid.getId());
        buf.append("_");
        buf.append(ds.getKeyProvider() != null ? ds.getKeyProvider().getKey(model) : XDOM.getUniqueId());
        buf.append("\">");
      }
      if (visible) {
        buf.append("<table role=presentation class=x-grid3-row-table border=0 cellspacing=0 cellpadding=0 style=\"");
        buf.append(tstyle);
        buf.append("\"><tbody role=presentation><tr role=presentation>");
        buf.append(cb.toString());
        buf.append("</tr>");
        if (enableRowBody) {
          buf.append("<tr class=x-grid3-row-body-tr style=\"\"><td colspan=");
          buf.append(rowBodyColSpanCount);
          buf.append(" class=x-grid3-body-cell><div class=x-grid3-row-body>${body}</div></td></tr>");
        }
        buf.append("</tbody></table>");

      }

      if (!onlyBody || !visible) {
        buf.append("</div>");
      }

      cb = new StringBuilder();
    }
    return buf.toString();
  }

  protected void doUpdate() {
    if (grid == null || !grid.isViewReady() || !bufferEnabled) {
      return;
    }
    int count = getVisibleRowCount();
    if (count > 0) {
      ColumnModel cm = grid.getColumnModel();

      ListStore<ModelData> store = grid.getStore();
      List<ColumnData> cs = getColumnData();
      boolean stripe = grid.isStripeRows();
      int[] vr = getVisibleRows(count);
      int cc = cm.getColumnCount();
      for (int i = vr[0]; i <= vr[1]; i++) {
        // if row is NOT rendered and is visible, render it
        if (!isRowRendered(i)) {
          List<ModelData> list = new ArrayList<ModelData>();
          list.add(store.getAt(i));
          widgetList.add(i, new ArrayList<Widget>());
          String html = doRender(cs, list, i, cc, stripe, true);
          getRow(i).setInnerHTML(html);
          renderWidgets(i, i);
        }
      }
      clean();
    }
  }

  protected int getCalculatedRowHeight() {
    return rowHeight + borderWidth;
  }

  protected int getStyleRowHeight() {
    return rowHeight + (GXT.isBorderBox ? borderWidth : 0);
  }

  protected int getVisibleRowCount() {
    int rh = getCalculatedRowHeight();
    int visibleHeight = scroller.getHeight(true);
    return (int) ((visibleHeight < 1) ? 0 : Math.ceil(((double) visibleHeight / rh)));
  }

  protected int[] getVisibleRows(int count) {
    int sc = scroller.getScrollTop();
    int start = sc / getCalculatedRowHeight();
    int first = Math.max(start, 0);
    int last = Math.min(start + count, grid.getStore().getCount() - 1);
    int[] i = new int[] {first, last};
    return i;
  }

  protected boolean isRowRendered(int index) {
    Element row = getRow(index);
    return row != null && row.hasChildNodes();
  }

  @Override
  protected void layout(boolean skipResize) {
    super.layout(skipResize);
    update();
  }

  @Override
  protected void notifyShow() {
    super.notifyShow();
    update();
  }

  @Override
  protected void onAdd(ListStore<ModelData> store, List<ModelData> models, int index) {
    super.onAdd(store, models, index);
    update();
  }

  @Override
  protected void onRemove(ListStore<ModelData> ds, ModelData m, int index, boolean isUpdate) {
    super.onRemove(ds, m, index, isUpdate);
    update();
  }

  @Override
  protected void syncScroll() {
    super.syncScroll();
    update();
  }

  protected void update() {
    if (grid == null || !grid.isViewReady() || !bufferEnabled) {
      return;
    }
    if (renderTask == null) {
      renderTask = new DelayedTask(new Listener<BaseEvent>() {
        public void handleEvent(BaseEvent be) {
          doUpdate();
        }
      });
    }
    renderTask.delay(scrollDelay);

  }
}
TOP

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

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.