All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.extjs.gxt.ui.client.widget.grid.Grid Maven / Gradle / Ivy

There is a newer version: 2.3.1-gwt22
Show newest version
/*
 * Sencha GXT 2.3.1a - Sencha for GWT
 * Copyright(c) 2007-2013, Sencha, Inc.
 * [email protected]
 * 
 * http://www.sencha.com/products/gxt/license/
 */
 package com.extjs.gxt.ui.client.widget.grid;

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

import com.extjs.gxt.ui.client.GXT;
import com.extjs.gxt.ui.client.Style.SortDir;
import com.extjs.gxt.ui.client.aria.FocusFrame;
import com.extjs.gxt.ui.client.core.El;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.ModelProcessor;
import com.extjs.gxt.ui.client.data.ModelStringProvider;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.BoxComponent;
import com.extjs.gxt.ui.client.widget.grid.GridSelectionModel.Callback;
import com.extjs.gxt.ui.client.widget.grid.GridSelectionModel.Cell;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Accessibility;

/**
 * This class represents the primary interface of a component based grid
 * control. The grid requires a ListStore and
 * ColumnModel when constructed. Each model in the store will be
 * rendered as a row in the grid. Any updates to the store are automatically
 * pushed to the grid. This includes inserting, removing, sorting and filter.
 * 
 * 

* Grid support several ways to manage column widths. * *

    *
  1. The most basic approach is to simply give pixel widths to each column. * Columns widths will match the specified values.
  2. *
  3. A column can be set to "fill" all available space. As the width of the * grid changes, or columns are resized, the "filling" column's width is * adjusted so that the column's fill the available width with no horizontal * scrolling. See @link {@link Grid#setAutoExpandColumn(String)}.
  4. *
  5. Grid can resize columns based on a "weight". As the width of the grid, or * columns change, the "weight" is used to allocate the extra space, or the * space needed to be reduced. Use {@link GridView#setAutoFill(boolean)} to * enable this feature. With auto fill, the calculations are only run once. * After the grid is rendered, the columns widths will not be adjusted when * available width changes. You can use @link * {@link GridView#setForceFit(boolean)} to always run the width calculations on * any changes to available width or column sizes. Columns can be "fixed" which * prevents their columns widths to be adjusted by the grid "weight" * calculations. See @link {@link ColumnConfig#setFixed(boolean)}.
  6. *
* *

* When state is enabled (default is false), Grid will save and restore the * column width, column hidden state, sort direction, and sort field. To enable * state, see {@link #setStateful(boolean)}. When the store uses a * PagingListLoader the offset and limit parameter are saved with * the Grid's state. These 2 values can be retrieved and used to make the first * load request to return the user to the same location they left the grid. * * Code snippet: * *

      PagingLoadConfig config = new BasePagingLoadConfig();
      config.setOffset(0);
      config.setLimit(50);
      
      Map state = grid.getState();
      if (state.containsKey("offset")) {
        int offset = (Integer)state.get("offset");
        int limit = (Integer)state.get("limit");
        config.setOffset(offset);
        config.setLimit(limit);
      }
      if (state.containsKey("sortField")) {
        config.setSortField((String)state.get("sortField"));
        config.setSortDir(SortDir.valueOf((String)state.get("sortDir")));
      }
      loader.load(config);
 * 
* *
*
Events:
* *
CellClick : GridEvent(grid, rowIndex, cellIndex, event)
*
Fires after a cell is clicked.
*
    *
  • grid : this
  • *
  • rowIndex : row index
  • *
  • cellIndex : cell index
  • *
  • event : the dom event
  • *
*
* *
CellDoubleClick : GridEvent(grid, rowIndex, cellIndex, event)
*
Fires after a cell is double clicked.
*
    *
  • grid : this
  • *
  • rowIndex : row index
  • *
  • cellIndex : cell index
  • *
  • event : the dom event
  • *
*
* *
CellMouseDown : GridEvent(grid, rowIndex, cellIndex, event)
*
Fires before a cell is clicked.
*
    *
  • grid : this
  • *
  • rowIndex : row index
  • *
  • cellIndex : cell index
  • *
  • event : the dom event
  • *
*
* *
RowClick : GridEvent(grid, rowIndex, cellIndex, event)
*
Fires after a row is clicked.
*
    *
  • grid : this
  • *
  • rowIndex : the row index
  • *
  • cellIndex : cell index
  • *
  • index : the cell index
  • *
  • event : the dom event
  • *
*
* *
RowDoubleClick : GridEvent(grid, rowIndex, cellIndex, event)
*
Fires after a row is double clicked.
*
    *
  • grid : this
  • *
  • rowIndex : the row index
  • *
  • index : the cell index
  • *
  • event : the dom event
  • *
*
* *
RowMouseDown : GridEvent(grid, rowIndex, colIndex, event)
*
Fires before a row is clicked.
*
    *
  • grid : this
  • *
  • rowIndex : row index
  • *
  • colIndex : column index
  • *
  • event : the dom event
  • *
*
* *
HeaderClick : GridEvent(grid, rowIndex, colIndex, event)
*
Fires a header is clicked.
*
    *
  • grid : this
  • *
  • rowIndex : row index
  • *
  • colIndex : column index
  • *
  • event : the dom event
  • *
*
* *
HeaderDoubleClick : GridEvent(grid, rowIndex, colIndex, event)
*
Fires a header is double clicked.
*
    *
  • grid : this
  • *
  • rowIndex : row index
  • *
  • colIndex : column index
  • *
  • event : the dom event
  • *
*
* *
HeaderMouseDown : GridEvent(grid, rowIndex, colIndex, event)
*
Fires before a header is clicked.
*
    *
  • grid : this
  • *
  • rowIndex : row index
  • *
  • colIndex : column index
  • *
  • event : the dom event
  • *
*
* *
ContextMenu : GridEvent(grid)
*
Fires before the grid's context menu is shown. Listeners can cancel the * action by calling {@link BaseEvent#setCancelled(boolean)}.
*
    *
  • grid : this
  • *
*
* *
HeaderContextMenu : GridEvent(grid, colIndex, menu)
*
Fires right before the header's context menu is displayed. Listeners can * cancel the action by calling {@link BaseEvent#setCancelled(boolean)}.
*
    *
  • grid : this
  • *
  • colIndex : the column index
  • *
  • menu : the context menu
  • *
*
* *
BodyScroll : GridEvent(grid, srollLeft, scrollTop)
*
Fires when the body element is scrolled.
*
    *
  • grid : this
  • *
  • scrollLeft : scrollLeft
  • *
  • scrollTop : scrollTop
  • *
*
* *
ColumnResize : GridEvent(grid, colIndex, width)
*
Fires when the user resizes a column.
*
    *
  • grid : this
  • *
  • colIndex : the column index
  • *
  • width : the new column width
  • *
*
* *
ColumnMove : GridEvent(grid, colIndex, size)
*
Fires when the user moves a column.
*
    *
  • grid : this
  • *
  • oldIndex : the old column index
  • *
  • newIndex : the new column index
  • *
*
* *
SortChange : GridEvent(grid, sortInfo)
*
Fires when the grid's store sort changes.
*
    *
  • grid : this
  • *
  • sortInfo : the sort field and direction
  • *
*
* *
ViewReady : GridEvent(grid)
*
Fires when the grid's view is ready.
*
    *
  • grid : this
  • *
*
* *
Reconfigure : GridEvent(grid)
*
Fires when the grid gets reconfigured.
*
    *
  • grid : this
  • *
*
*
* *
*
Inherited Events:
*
BoxComponent Move
*
BoxComponent Resize
*
Component Enable
*
Component Disable
*
Component BeforeHide
*
Component Hide
*
Component BeforeShow
*
Component Show
*
Component Attach
*
Component Detach
*
Component BeforeRender
*
Component Render
*
Component BrowserEvent
*
Component BeforeStateRestore
*
Component StateRestore
*
Component BeforeStateSave
*
Component SaveState
*
* * @param the model type */ public class Grid extends BoxComponent { protected ColumnModel cm; protected EditorSupport editSupport; protected GridSelectionModel sm; protected ListStore store; protected ModelStringProvider stringProvider; protected GridView view; protected boolean viewReady; private String autoExpandColumn; private int autoExpandMax = 500; private int autoExpandMin = 25; private boolean columnLines; private boolean enableColumnReorder; private boolean enableColumnResize = true; private boolean hideHeaders; private int lazyRowRender = 10; private boolean loadMask; private int minColumnWidth = 25; private ModelProcessor modelProcessor; private boolean stripeRows; private boolean trackMouseOver = true; private Map states = new HashMap(); /** * Creates a new grid. * * @param store the data store * @param cm the column model */ public Grid(ListStore store, ColumnModel cm) { this.store = store; this.cm = cm; this.view = new GridView(); disabledStyle = null; baseStyle = "x-grid-panel"; setSelectionModel(new GridSelectionModel()); disableTextSelection(true); } protected Grid() { } @Override public void disableTextSelection(boolean disable) { disableTextSelection = disable ? 1 : 0; } /** * Returns the auto expand column id. * * @return the auto expand column id */ public String getAutoExpandColumn() { return autoExpandColumn; } /** * Returns the auto expand maximum width. * * @return the max width in pixels */ public int getAutoExpandMax() { return autoExpandMax; } /** * Returns the auto expand minimum width. * * @return the minimum width in pixels */ public int getAutoExpandMin() { return autoExpandMin; } /** * Returns the column model. * * @return the column model */ public ColumnModel getColumnModel() { return cm; } /** * Returns the time in ms after the rows get rendered. * * @return the lazy row rendering time */ public int getLazyRowRender() { return lazyRowRender; } /** * Returns the minimum column width. * * @return the min width in pixels */ public int getMinColumnWidth() { return minColumnWidth; } /** * Returns the model processor. * * @return the model processor */ public ModelProcessor getModelProcessor() { return modelProcessor; } /** * Returns the grid's selection model. * * @return the selection model */ public GridSelectionModel getSelectionModel() { return sm; } /** * Returns the grid's store. * * @return the store */ public ListStore getStore() { return store; } /** * Returns the grid's view. * * @return the grid view */ public GridView getView() { return view; } /** * Returns true if column lines are enabled. * * @return true if column lines are enabled */ public boolean isColumnLines() { return columnLines; } /** * Returns true if column reordering is enabled. * * @return true if enabled */ public boolean isColumnReordering() { return enableColumnReorder; } /** * Returns true if column resizing is enabled. * * @return true if resizing is enabled */ public boolean isColumnResize() { return enableColumnResize; } /** * Returns true if the header is hidden. * * @return true for hidden */ public boolean isHideHeaders() { return hideHeaders; } /** * Returns true if the load mask in enabled. * * @return the load mask state */ public boolean isLoadMask() { return loadMask; } /** * Returns true if row striping is enabled. * * @return the strip row state */ public boolean isStripeRows() { return stripeRows; } /** * Returns true if rows are highlighted on mouse over. * * @return the track mouse state */ public boolean isTrackMouseOver() { return trackMouseOver; } /** * Returns true if the view is ready. * * @return the view ready state */ public boolean isViewReady() { return viewReady; } @Override @SuppressWarnings({"unchecked", "rawtypes"}) public void onComponentEvent(ComponentEvent ce) { super.onComponentEvent(ce); GridEvent ge = (GridEvent) ce; switch (ce.getEventTypeInt()) { case Event.ONCLICK: onClick(ge); break; case Event.ONDBLCLICK: onDoubleClick(ge); break; case Event.ONMOUSEDOWN: onMouseDown(ge); break; case Event.ONMOUSEUP: onMouseUp(ge); break; case Event.ONFOCUS: onFocus(ce); break; case Event.ONBLUR: onBlur(ce); break; } view.handleComponentEvent(ge); } /** * Reconfigures the grid to use a different Store and Column Model. The View * will be bound to the new objects and refreshed. * * @param store the new store * @param cm the new column model */ public void reconfigure(ListStore store, ColumnModel cm) { if (loadMask && rendered) { mask(GXT.MESSAGES.loadMask_msg()); } if (rendered) { view.initData(store, cm); } this.store = store; this.cm = cm; // rebind the sm setSelectionModel(sm); if (isViewReady()) { view.refresh(true); } if (loadMask && rendered) { unmask(); } fireEvent(Events.Reconfigure); } /** * The id of a column in this grid that should expand to fill unused space * (pre-render). This id can not be 0. * * @param autoExpandColumn the auto expand column id */ public void setAutoExpandColumn(String autoExpandColumn) { this.autoExpandColumn = autoExpandColumn; } /** * The maximum width the autoExpandColumn can have (if enabled) (defaults to * 500, pre-render). * * @param autoExpandMax the auto expand max */ public void setAutoExpandMax(int autoExpandMax) { this.autoExpandMax = autoExpandMax; } /** * The minimum width the autoExpandColumn can have (if enabled)(pre-render). * * @param autoExpandMin the auto expand min width */ public void setAutoExpandMin(int autoExpandMin) { this.autoExpandMin = autoExpandMin; } /** * True to enable column separation lines (defaults to false). * * @param columnLines true to enable column separation lines */ public void setColumnLines(boolean columnLines) { this.columnLines = columnLines; if (rendered) { el().setStyleName("x-grid-with-col-lines", columnLines); } } /** * True to enable column reordering via drag and drop (defaults to false). * * @param enableColumnReorder true to enable */ public void setColumnReordering(boolean enableColumnReorder) { this.enableColumnReorder = enableColumnReorder; } /** * Sets whether columns may be resized (defaults to true). * * @param enableColumnResize true to allow column resizing */ public void setColumnResize(boolean enableColumnResize) { this.enableColumnResize = enableColumnResize; } /** * Sets whether the header should be hidden (defaults to false). * * @param hideHeaders true to hide the header */ public void setHideHeaders(boolean hideHeaders) { this.hideHeaders = hideHeaders; } /** * Sets the time in ms after the row gets rendered (defaults to 10). 0 means * that the rows get rendered as soon as the grid gets rendered. * * @param lazyRowRender the time in ms after the rows get rendered. */ public void setLazyRowRender(int lazyRowRender) { this.lazyRowRender = lazyRowRender; } /** * Sets whether a load mask should be displayed during load operations * (defaults to false). * * @param loadMask true to show a mask */ public void setLoadMask(boolean loadMask) { this.loadMask = loadMask; } /** * The minimum width a column can be resized to (defaults to 25). * * @param minColumnWidth the min column width */ public void setMinColumnWidth(int minColumnWidth) { this.minColumnWidth = minColumnWidth; } /** * Sets the grid's model processor. * * @see ModelProcessor * @param modelProcessor */ public void setModelProcessor(ModelProcessor modelProcessor) { this.modelProcessor = modelProcessor; } /** * Sets the grid selection model. * * @param sm the selection model */ public void setSelectionModel(GridSelectionModel sm) { if (this.sm != null) { this.sm.bindGrid(null); } this.sm = sm; if (sm != null) { sm.bindGrid(this); } } /** * Sets the binder's string provider. * * @param stringProvider the string provider */ public void setStringProvider(ModelStringProvider stringProvider) { this.stringProvider = stringProvider; } /** * True to stripe the rows (defaults to false). * * @param stripeRows true to strip rows */ public void setStripeRows(boolean stripeRows) { this.stripeRows = stripeRows; } /** * True to highlight rows when the mouse is over (defaults to true). * * @param trackMouseOver true to highlight rows on mouse over */ public void setTrackMouseOver(boolean trackMouseOver) { this.trackMouseOver = trackMouseOver; } /** * Sets the view's grid (pre-render). * * @param view the view */ public void setView(GridView view) { this.view = view; // rebind the sm setSelectionModel(sm); } protected void afterRender() { view.render(); super.afterRender(); if (lazyRowRender > 0) { Timer t = new Timer() { @Override public void run() { afterRenderView(); } }; t.schedule(lazyRowRender); } else { afterRenderView(); } } protected void afterRenderView() { viewReady = true; view.afterRender(); onAfterRenderView(); for (String key : states.keySet()) { setAriaState(key, states.get(key)); } fireEvent(Events.ViewReady); } @Override protected void applyState(Map state) { super.applyState(state); if (isStateful()) { for (ColumnConfig c : cm.getColumns()) { String id = c.getId(); if (state.containsKey("hidden" + id)) { c.setHidden((Boolean) state.get("hidden" + id)); } if (state.containsKey("width" + id)) { c.setWidth((Integer) state.get("width" + id)); } } doApplyStoreState(state); } } @Override protected ComponentEvent createComponentEvent(Event event) { return view.createComponentEvent(event); } protected void doApplyStoreState(Map state) { String sortField = (String) state.get("sortField"); if ((store.getLoader() == null || !store.getLoader().isRemoteSort()) && sortField != null) { String sortDir = (String) state.get("sortDir"); SortDir dir = SortDir.findDir(sortDir); store.sort(sortField, dir); } } @Override protected void doAttachChildren() { super.doAttachChildren(); view.doAttach(); } @Override protected void doDetachChildren() { super.doDetachChildren(); view.doDetach(); } protected EditorSupport getEditSupport() { return new EditorSupport(); } @Override protected El getFocusEl() { if (isViewReady()) { return view.focusEl; } else { return super.getFocusEl(); } } @Override protected void notifyHide() { super.notifyHide(); view.notifyHide(); } @Override protected void notifyShow() { super.notifyShow(); view.notifyShow(); } protected void onAfterRenderView() { } protected void onBlur(ComponentEvent ce) { if (GXT.isFocusManagerEnabled()) { FocusFrame.get().unframe(); } } protected void onClick(GridEvent e) { if (e.getRowIndex() != -1) { fireEvent(Events.RowClick, e); if (e.getColIndex() != -1) { fireEvent(Events.CellClick, e); } } } @Override protected void onDisable() { super.onDisable(); mask(); } protected void onDoubleClick(GridEvent e) { if (e.getRowIndex() != -1) { fireEvent(Events.RowDoubleClick, e); if (e.getColIndex() != -1) { fireEvent(Events.CellDoubleClick, e); } } } @Override protected void onEnable() { super.onEnable(); unmask(); } protected void onFocus(ComponentEvent ce) { if (GXT.isFocusManagerEnabled()) { if (getSelectionModel().selectedHeader != null) { FocusFrame.get().frame(getSelectionModel().selectedHeader); } else { FocusFrame.get().frame(this); } } } protected void onMouseDown(GridEvent e) { if (isDisableTextSelection() && GXT.isWebKit) { String tagName = e.getEvent().getEventTarget(). cast().getTagName(); if (!"input".equalsIgnoreCase(tagName) && !"textarea".equalsIgnoreCase(tagName)) { e.preventDefault(); } } if (e.getRowIndex() != -1) { fireEvent(Events.RowMouseDown, e); if (e.getColIndex() != -1) { fireEvent(Events.CellMouseDown, e); } } } protected void onMouseUp(GridEvent e) { if (e.getRowIndex() != -1) { fireEvent(Events.RowMouseUp, e); if (e.getColIndex() != -1) { fireEvent(Events.CellMouseUp, e); } } } @Override protected void onRender(Element target, int index) { setElement(DOM.createDiv(), target, index); super.onRender(target, index); el().setStyleAttribute("position", "relative"); setColumnLines(isColumnLines()); view.init(this); el().setTabIndex(0); el().setElementAttribute("hideFocus", "true"); if (GXT.isAriaEnabled()) { Accessibility.setRole(getElement(), "grid"); setAriaState("aria-readonly", "true"); setAriaState("aria-multiselectable", "true"); } } @Override protected void onResize(int width, int height) { super.onResize(width, height); if (viewReady) { view.calculateVBar(true); } else { view.layout(); } } @Override protected void setAriaRole(String roleName) { if (isViewReady()) { Accessibility.setRole(view.focusEl.dom, roleName); } } protected void setAriaState(String stateName, String stateValue) { if (isViewReady()) { Accessibility.setState(view.focusEl.dom, stateName, stateValue); } else { states.put(stateName, stateValue); } } protected Cell walkCells(int row, int col, int step, Callback callback, boolean acceptNavs) { boolean first = true; int clen = cm.getColumnCount(); int rlen = store.getCount(); if (step < 0) { if (col < 0) { if (GXT.isFocusManagerEnabled()) { return new Cell(row, 0); } row--; first = false; } while (row >= 0) { if (!first) { col = clen - 1; } first = false; while (col >= 0) { if (callback.isSelectable(row, col, acceptNavs)) { return new Cell(row, col); } col--; } row--; } } else { if (col == clen && GXT.isFocusManagerEnabled()) { return new Cell(row, col - 1); } if (col >= clen) { row++; first = false; } while (row < rlen) { if (!first) { col = 0; } first = false; while (col < clen) { if (callback.isSelectable(row, col, acceptNavs)) { return new Cell(row, col); } col++; } row++; } } return null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy