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

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

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

import com.extjs.gxt.ui.client.GXT;
import com.extjs.gxt.ui.client.Style.SelectionMode;
import com.extjs.gxt.ui.client.aria.FocusFrame;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ColumnModelEvent;
import com.extjs.gxt.ui.client.event.DomEvent;
import com.extjs.gxt.ui.client.event.EventType;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.util.KeyNav;
import com.extjs.gxt.ui.client.widget.grid.ColumnHeader.Head;
import com.extjs.gxt.ui.client.widget.selection.AbstractStoreSelectionModel;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.Element;

/**
* Grid selection model.
*
* <dl>
* <dt>Inherited Events:</dt>
* <dd>AbstractStoreSelectionModel BeforeSelect</dd>
* <dd>AbstractStoreSelectionModel SelectionChange</dd>
* </dl>
*/
@SuppressWarnings("rawtypes")
public class GridSelectionModel<M extends ModelData> extends AbstractStoreSelectionModel<M> implements
    Listener<BaseEvent> {

  public static class Callback {

    private GridSelectionModel sm;

    public Callback(GridSelectionModel sm) {
      this.sm = sm;
    }

    public boolean isSelectable(int row, int cell, boolean acceptsNav) {
      return sm.isSelectable(row, cell, acceptsNav);
    }
  }

  public static class Cell {
    public int cell;
    public int row;

    public Cell(int row, int cell) {
      this.row = row;
      this.cell = cell;
    }

  }

  protected boolean enableNavKeys = true;
  protected Grid<M> grid;
  protected boolean grouped = false;
  protected GroupingView groupingView;
  protected KeyNav<GridEvent<M>> keyNav = new KeyNav<GridEvent<M>>() {

    @Override
    public void onDown(GridEvent<M> e) {
      onKeyDown(e);
    }

    @Override
    public void onKeyPress(GridEvent<M> ce) {
      GridSelectionModel.this.onKeyPress(ce);
    }

    @Override
    public void onLeft(GridEvent<M> ce) {
      onKeyLeft(ce);
    }

    @Override
    public void onRight(GridEvent<M> ce) {
      onKeyRight(ce);
    }

    @Override
    public void onUp(GridEvent<M> e) {
      onKeyUp(e);
    }

  };
  protected ListStore<M> listStore;
  protected Element selectedGroup;
  protected Head selectedHeader;

  private Callback callback = new Callback(this);
  private boolean moveEditorOnEnter;

  @SuppressWarnings("unchecked")
  @Override
  public void bind(Store store) {
    super.bind(store);
    if (store instanceof ListStore) {
      listStore = (ListStore<M>) store;
    } else {
      listStore = null;
    }
  }

  @SuppressWarnings("unchecked")
  public void bindGrid(Grid grid) {
    if (this.grid != null) {
      this.grid.removeListener(Events.RowMouseDown, this);
      this.grid.removeListener(Events.RowClick, this);
      this.grid.removeListener(Events.ContextMenu, this);
      this.grid.removeListener(Events.ViewReady, this);
      this.grid.getView().removeListener(Events.RowUpdated, this);
      this.grid.getView().removeListener(Events.Refresh, this);
      this.grid.getColumnModel().removeListener(Events.HiddenChange, this);
      keyNav.bind(null);
      bind(null);
    }
    this.grid = grid;
    if (grid != null) {
      grid.addListener(Events.RowMouseDown, this);
      grid.addListener(Events.RowClick, this);
      grid.addListener(Events.ContextMenu, this);
      grid.addListener(Events.ViewReady, this);
      grid.getView().addListener(Events.RowUpdated, this);
      grid.getView().addListener(Events.Refresh, this);
      grid.getColumnModel().addListener(Events.HiddenChange, this);
      keyNav.bind(grid);
      bind(grid.getStore());
      grouped = grid.getView() instanceof GroupingView;
      if (grouped) groupingView = (GroupingView) grid.getView();
    }
  }

  @SuppressWarnings("unchecked")
  public void handleEvent(BaseEvent e) {
    EventType type = e.getType();
    if (type == Events.RowMouseDown) {
      handleMouseDown((GridEvent) e);
    } else if (type == Events.RowClick) {
      handleMouseClick((GridEvent) e);
    } else if (type == Events.RowUpdated) {
      onRowUpdated((GridEvent) e);
    } else if (type == Events.Refresh || type == Events.ViewReady) {
      refresh();
      if (getLastFocused() != null) {
        grid.getView().onHighlightRow(listStore.indexOf(getLastFocused()), true);
      }
    } else if (type == Events.HiddenChange) {
      handleColumnHidden((ColumnModelEvent) e);
    }
  }

  /**
   * Returns true of the editor moves on enter.
   *
   * @return true if editor moves on enter
   */
  public boolean isMoveEditorOnEnter() {
    return moveEditorOnEnter;
  }

  public void onEditorKey(DomEvent e) {
    int k = e.getKeyCode();
    Cell newCell = null;
    CellEditor editor = grid.editSupport.getActiveEditor();
    switch (k) {
      case KeyCodes.KEY_ENTER:
      case KeyCodes.KEY_TAB:
        e.stopEvent();
        if (editor != null) {
          editor.completeEdit();
        }
        if ((k == KeyCodes.KEY_ENTER && moveEditorOnEnter) || k == KeyCodes.KEY_TAB) {
          if (e.isShiftKey()) {
            newCell = grid.walkCells(editor.row, editor.col - 1, -1, callback, true);
          } else {
            newCell = grid.walkCells(editor.row, editor.col + 1, 1, callback, true);
          }
        }
        break;
      case KeyCodes.KEY_ESCAPE:
        if (editor != null) {
          editor.cancelEdit();
        }
        break;
    }
    if (newCell != null) {
      grid.editSupport.startEditing(newCell.row, newCell.cell);
    } else {
      if (k == KeyCodes.KEY_ENTER || k == KeyCodes.KEY_TAB || k == KeyCodes.KEY_ESCAPE) {
        grid.getView().focusCell(editor.row, editor.col, false);
      }
    }
  }

  /**
   * Selects the next row.
   *
   * @param keepexisting true to keep existing selections
   */
  public void selectNext(boolean keepexisting) {
    if (hasNext()) {
      int idx = listStore.indexOf(lastSelected) + 1;
      select(idx, keepexisting);
      grid.getView().focusRow(idx);
    }
  }

  /**
   * Selects the previous row.
   *
   * @param keepexisting true to keep existing selections
   */
  public void selectPrevious(boolean keepexisting) {
    if (hasPrevious()) {
      int idx = listStore.indexOf(lastSelected) - 1;
      select(idx, keepexisting);
      grid.getView().focusRow(idx);
    }
  }

  /**
   * Set this to true to move the editor to the next editable cell on pressing
   * enter.
   *
   * @param moveEditorOnEnter true to move the editor on pressing enter.
   */
  public void setMoveEditorOnEnter(boolean moveEditorOnEnter) {
    this.moveEditorOnEnter = moveEditorOnEnter;
  }

  protected void handleColumnHidden(ColumnModelEvent e) {
    ColumnHeader header = grid.getView().getHeader();
    if (header != null) {
      int col = e.getColIndex();
      Head h = header.getHead(col);
      if (h == selectedHeader) {
        selectedHeader = null;
      }
    }
  }

  @SuppressWarnings("unchecked")
  protected void handleMouseClick(GridEvent<M> e) {
    if (isLocked() || isInput(e.getTarget())) {
      return;
    }
    if (e.getRowIndex() == -1) {
      deselectAll();
      return;
    }
    if (selectionMode == SelectionMode.MULTI) {
      M sel = listStore.getAt(e.getRowIndex());
      if (e.isControlKey() && isSelected(sel)) {
        doDeselect(Arrays.asList(sel), false);
      } else if (e.isControlKey()) {
        doSelect(Arrays.asList(sel), true, false);
        grid.getView().focusCell(e.getRowIndex(), e.getColIndex(), false);
      } else if (isSelected(sel) && !e.isShiftKey() && !e.isControlKey() && selected.size() > 1) {
        doSelect(Arrays.asList(sel), false, false);
        grid.getView().focusCell(e.getRowIndex(), e.getColIndex(), false);
      }
    }

  }

  @SuppressWarnings("unchecked")
  protected void handleMouseDown(GridEvent<M> e) {
    if (e.getRowIndex() == -1 || isLocked() || isInput(e.getTarget())) {
      return;
    }
    if (e.isRightClick()) {
      if (selectionMode != SelectionMode.SINGLE && isSelected(listStore.getAt(e.getRowIndex()))) {
        return;
      }
      select(e.getRowIndex(), false);
      grid.getView().focusCell(e.getRowIndex(), e.getColIndex(), false);
    } else {
      M sel = listStore.getAt(e.getRowIndex());
      if (selectionMode == SelectionMode.SIMPLE) {
        if (!isSelected(sel)) {
          select(sel, true);
          grid.getView().focusCell(e.getRowIndex(), e.getColIndex(), false);
        }

      } else if (selectionMode == SelectionMode.SINGLE) {
        if (e.isControlKey() && isSelected(sel)) {
          deselect(sel);
        } else if (!isSelected(sel)) {
          select(sel, false);
          grid.getView().focusCell(e.getRowIndex(), e.getColIndex(), false);
        }
      } else if (!e.isControlKey()) {
        if (e.isShiftKey() && lastSelected != null) {
          int last = listStore.indexOf(lastSelected);
          int index = e.getRowIndex();
          select(last, index, e.isControlKey());
          grid.getView().focusCell(index, e.getColIndex(), false);
        } else if (!isSelected(sel)) {
          doSelect(Arrays.asList(sel), false, false);
          grid.getView().focusCell(e.getRowIndex(), e.getColIndex(), false);
        }
      }
    }
  }

  protected boolean hasNext() {
    return lastSelected != null && listStore.indexOf(lastSelected) < (listStore.getCount() - 1);
  }

  protected boolean hasPrevious() {
    return lastSelected != null && listStore.indexOf(lastSelected) > 0;
  }

  protected boolean isInput(Element target) {
    String tag = target.getTagName();
    return "input".equalsIgnoreCase(tag) || "textarea".equalsIgnoreCase(tag);
  }

  protected boolean isSelectable(int row, int cell, boolean acceptsNav) {
    if (acceptsNav) {
      return !grid.getColumnModel().isHidden(cell) && grid.getColumnModel().isCellEditable(cell);
    } else {
      return !grid.getColumnModel().isHidden(cell);
    }
  }

  protected void onKeyDown(GridEvent<M> e) {
    if (GXT.isFocusManagerEnabled()) {
      if (selectedGroup == null && (selectedHeader != null || selected.size() == 0)) {
        e.cancelBubble();
        if (e.isAltKey()) {
          grid.getView().getHeader().showColumnMenu(selectedHeader.column);
          return;
        }
        if (selectedHeader != null) {
          selectedHeader.deactivate();
        }
        select(0, false);
        return;
      }
      if (grouped) {
        GroupingView view = (GroupingView) grid.getView();
        NodeList<Element> groups = view.getGroups().cast();
        int gc = view.getGroups().getLength();

        if (selectedGroup != null) {
          int gindex = indexOf(groups, selectedGroup);
          if (!view.isExpanded(selectedGroup)) {
            if (gindex < gc - 1) {
              view.onGroupSelect(selectedGroup, false);
              selectedGroup = groups.getItem(gindex + 1);
              view.onGroupSelect(selectedGroup, true);
            }
            return;
          }
          view.onGroupSelect(selectedGroup, false);
          Element r = view.getGroupRow(selectedGroup, 0).cast();

          selectedGroup = null;

          if (r != null) {
            int idx = view.findRowIndex(r);
            select(idx, false);
            view.focusRow(idx);
            return;
          }
        }
        if (lastSelected != null) {
          Element row = view.getRow(lastSelected).cast();
          Element group = view.findGroup(row).cast();

          int totalGroups = groups.getLength();
          int groupIndex = indexOf(groups, group);

          NodeList<Element> groupRows = group.getChildNodes().getItem(1).getChildNodes().cast();

          int rowsInGroup = group.getChildNodes().getItem(1).getChildNodes().getLength();
          int rowInGroupIndex = indexOf(groupRows, row);
          if (rowInGroupIndex == rowsInGroup - 1) {
            if (groupIndex < totalGroups - 1) {
              deselectAll();
              selectedGroup = groups.getItem(groupIndex + 1);
              view.onGroupSelect(selectedGroup, true);
              return;

            }
          }
        }
      }
    }
    if (!e.isControlKey() && selected.size() == 0 && getLastFocused() == null) {
      select(0, false);
    } else {
      int idx = listStore.indexOf(getLastFocused());
      if (idx >= 0) {
        if (e.isControlKey() || (e.isShiftKey() && isSelected(listStore.getAt(idx + 1)))) {
          if (!e.isControlKey()) {
            deselect(idx);
          }

          M lF = listStore.getAt(idx + 1);
          if (lF != null) {
            setLastFocused(lF);
            grid.getView().focusCell(idx + 1, 0, false);
          }

        } else {
          if (e.isShiftKey() && lastSelected != getLastFocused()) {
            select(listStore.indexOf(lastSelected), idx + 1, true);
            grid.getView().focusCell(idx + 1, 0, false);
          } else {
            if (idx + 1 < listStore.getCount()) {
              selectNext(e.isShiftKey());
              grid.getView().focusCell(idx + 1, 0, false);
            }
          }
        }
      }
    }

    e.preventDefault();
  }

  protected void onKeyLeft(GridEvent<M> ce) {
    if (GXT.isFocusManagerEnabled() && selectedHeader != null) {
      ColumnHeader ch = grid.getView().getHeader();
      int idx = ch.indexOf(selectedHeader) - 1;
      ColumnConfig config = grid.getColumnModel().getColumn(idx);
      while (config != null) {
        if (!config.isHidden()) {
          Head h = getHead(idx, false);
          selectedHeader = h;
          grid.getView().getHeader().selectHeader(idx);
          break;
        } else {
          idx--;
          config = grid.getColumnModel().getColumn(idx);
        }
      }
    }
    if (GXT.isFocusManagerEnabled() && selectedGroup != null) {
      groupingView.toggleGroup(selectedGroup, false);
    }
  }

  @SuppressWarnings("unchecked")
  protected void onKeyPress(GridEvent<M> e) {
    int kc = e.getKeyCode();
    if (GXT.isFocusManagerEnabled()) {
      if (selectedHeader != null) {
        if (kc == KeyCodes.KEY_ENTER) {
          grid.getView().onHeaderClick((Grid) grid, grid.getColumnModel().indexOf(selectedHeader.config));
          return;
        } else if (kc == 32) {
          ColumnHeader ch = grid.getView().getHeader();
          int idx = ch.indexOf(selectedHeader);
          String id = grid.getColumnModel().getColumnId(idx);
          if (id == null || !id.equals("checker")) {
            grid.getView().getHeader().showColumnMenu(idx);
          }
          return;
        }
      }
    }
    if (lastSelected != null && enableNavKeys) {
      if (kc == KeyCodes.KEY_PAGEUP) {
        e.stopEvent();
        select(0, false);
        grid.getView().focusRow(0);
      } else if (kc == KeyCodes.KEY_PAGEDOWN) {
        e.stopEvent();
        int idx = listStore.indexOf(listStore.getAt(listStore.getCount() - 1));
        select(idx, false);
        grid.getView().focusRow(idx);
      }
    }
    // if space bar is pressed
    if (e.getKeyCode() == 32) {
      if (getLastFocused() != null) {
        if (e.isShiftKey() && lastSelected != null) {
          int last = listStore.indexOf(lastSelected);
          int i = listStore.indexOf(getLastFocused());
          select(last, i, e.isControlKey());
          grid.getView().focusCell(i, 0, false);
        } else {
          if (isSelected(getLastFocused())) {
            deselect(getLastFocused());
          } else {
            select(getLastFocused(), true);
            grid.getView().focusCell(listStore.indexOf(getLastFocused()), 0, false);
          }
        }
      }
    }
  }

  protected void onKeyRight(GridEvent<M> ce) {
    if (GXT.isFocusManagerEnabled() && selectedHeader != null) {
      ColumnHeader ch = grid.getView().getHeader();
      int idx = ch.indexOf(selectedHeader) + 1;
      ColumnConfig config = grid.getColumnModel().getColumn(idx);
      while (config != null) {
        if (!config.isHidden()) {
          Head h = getHead(idx, false);
          selectedHeader = h;
          grid.getView().getHeader().selectHeader(idx);
          break;
        } else {
          idx++;
          config = grid.getColumnModel().getColumn(idx);
        }
      }
    }
    if (GXT.isAriaEnabled() && selectedGroup != null) {
      groupingView.toggleGroup(selectedGroup, true);
    }
  }

  protected void onKeyUp(GridEvent<M> e) {
    if (GXT.isFocusManagerEnabled()) {
      if (selectedHeader != null) {
        return;
      }
      if (listStore.indexOf(lastSelected) == 0 && !grouped) {
        deselectAll();
        ColumnHeader header = grid.getView().getHeader();
        Head h = getHead(0, false);
        if (h != null) {
          selectedHeader = h;
          header.selectHeader(header.indexOf(h));
        }
      }
      if (grouped) {
        GroupingView view = (GroupingView) grid.getView();
        NodeList<Element> groups = view.getGroups().cast();
        if (selectedGroup != null) {
          int gindex = indexOf(groups, selectedGroup);

          if (gindex == 0) {
            deselectAll();
            ColumnHeader header = grid.getView().getHeader();
            Head h = getHead(0, false);
            if (h != null) {
              selectedHeader = h;
              header.selectHeader(header.indexOf(h));
            }
          }

          view.onGroupSelect(selectedGroup, false);
          selectedGroup = null;

          if (gindex > 0) {
            selectedGroup = groups.getItem(gindex - 1);
            if (view.isExpanded(selectedGroup)) {
              int grows = view.getGroupRowCount(selectedGroup);
              Element r = view.getGroupRow(selectedGroup, grows - 1).cast();
              selectedGroup = null;
              select(view.findRowIndex(r), false);
              view.focusRow(view.findRowIndex(r));

            } else {
              view.onGroupSelect(selectedGroup, true);
            }
            return;
          }
        }
        if (lastSelected != null) {
          Element row = view.getRow(lastSelected).cast();
          Element group = view.findGroup(row).cast();
          if (row == view.getGroupRow(group, 0)) {
            deselectAll();
            selectedGroup = group;
            view.onGroupSelect(selectedGroup, true);
            return;
          }
        }
      }
    }
    int idx = listStore.indexOf(getLastFocused());
    if (idx >= 0) {
      if (e.isControlKey() || (e.isShiftKey() && isSelected(listStore.getAt(idx - 1)))) {
        if (!e.isControlKey()) {
          deselect(idx);
        }

        M lF = listStore.getAt(idx - 1);
        if (lF != null) {
          setLastFocused(lF);
          grid.getView().focusCell(idx - 1, 0, false);
        }

      } else {

        if (e.isShiftKey() && lastSelected != getLastFocused()) {
          select(listStore.indexOf(lastSelected), idx - 1, true);
          grid.getView().focusCell(idx - 1, 0, false);
        } else {
          if (idx > 0) {
            selectPrevious(e.isShiftKey());
            grid.getView().focusCell(idx - 1, 0, false);
          }
        }

      }
    }

    e.preventDefault();
  }

  @Override
  protected void onLastFocusChanged(M oldFocused, M newFocused) {
    int i;
    if (oldFocused != null) {
      i = listStore.indexOf(oldFocused);
      if (i >= 0) {
        grid.getView().onHighlightRow(i, false);
      }
    }
    if (newFocused != null) {
      i = listStore.indexOf(newFocused);
      if (i >= 0) {
        grid.getView().onHighlightRow(i, true);
      }
    }
  }

  protected void onRowUpdated(GridEvent<M> ge) {
    if (isSelected(ge.getModel())) {
      onSelectChange(ge.getModel(), true);
    }
    if (getLastFocused() == ge.getModel()) {
      setLastFocused(getLastFocused());
    }
  }

  @Override
  protected void onSelectChange(M model, boolean select) {
    int idx = listStore.indexOf(model);
    if (idx != -1) {
      if (GXT.isFocusManagerEnabled() && selectedHeader != null) {
        selectedHeader = null;
        FocusFrame.get().frame(grid);
      }
      if (select) {
        grid.getView().onRowSelect(idx);
      } else {
        grid.getView().onRowDeselect(idx);
      }
    }
  }

  private Head getHead(int index, boolean back) {
    ColumnHeader header = grid.getView().getHeader();
    int cols = grid.getColumnModel().getColumnCount();

    if (!back) {
      for (int i = index; i < cols; i++) {
        ColumnConfig config = grid.getColumnModel().getColumn(i);
        if (!config.isHidden() && !config.ariaIgnore) {
          return header.getHead(i);
        }
      }
    } else {
      for (int i = index; i > -1; i--) {
        ColumnConfig config = grid.getColumnModel().getColumn(i);
        if (!config.isHidden() && !config.ariaIgnore) {
          return header.getHead(i);
        }
      }
    }
    return null;
  }

  private int indexOf(NodeList<Element> elems, Element elem) {
    for (int i = 0; i < elems.getLength(); i++) {
      if (elems.getItem(i) == elem) {
        return i;
      }
    }
    return -1;
  }
}
TOP

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

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.