/*
* Ext GWT - Ext for GWT
* Copyright(c) 2007-2009, Ext JS, LLC.
* licensing@extjs.com
*
* http://extjs.com/license
*/
package com.extjs.gxt.ui.client.widget.grid;
import java.util.List;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.event.BaseEvent;
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.store.StoreEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.Event;
/**
* Cell based selection model for a grid.
*
* @param <M> the model type
*/
public class CellSelectionModel<M extends ModelData> extends GridSelectionModel<M> {
public class CellSelection {
public M model;
public int row;
public int cell;
public CellSelection(M model, int row, int cell) {
this.model = model;
this.row = row;
this.cell = cell;
}
}
private Callback callback = new Callback(this);
private EditSupport editGrid;
protected CellSelection selection;
@Override
@SuppressWarnings("unchecked")
public void bindGrid(Grid grid) {
if (this.grid != null) {
this.grid.removeListener(Events.CellMouseDown, this);
this.grid.removeListener(Events.BeforeEdit, this);
this.grid.getView().removeListener(Events.Refresh, this);
keyNav.bind(null);
bind(null);
}
this.grid = grid;
if (grid != null) {
grid.setTrackMouseOver(false);
grid.addListener(Events.BeforeEdit, this);
grid.addListener(Events.CellMouseDown, this);
grid.getView().addListener(Events.Refresh, this);
editGrid = grid instanceof EditSupport ? ((EditSupport) grid) : null;
keyNav.bind(grid);
bind(grid.getStore());
this.listStore = (ListStore)grid.getStore();
}
bind(grid != null ? grid.getStore() : null);
}
@Override
public void deselectAll() {
if (selection != null) {
// index may change with tree grid on expand / collapse
// ask store for current row index
int row = listStore.indexOf(selection.model);
grid.getView().onCellDeselect(row, selection.cell);
selection = null;
}
}
/**
* Returns the selected cell.
*
* @return the selection cell
*/
public CellSelection getSelectCell() {
return selection;
}
@Override
@SuppressWarnings("unchecked")
public void handleEvent(BaseEvent e) {
if (e.getType() == Events.CellMouseDown) {
handleMouseDown((GridEvent) e);
} else if (e.getType() == Events.Refresh) {
refresh();
} else if (e.getType() == Events.BeforeEdit) {
GridEvent ge = (GridEvent) e;
selectCell(ge.getRowIndex(), ge.getColIndex());
}
}
/**
* Selects the cell.
*
* @param row the row index
* @param cell the cell index
*/
public void selectCell(int row, int cell) {
deselectAll();
M m = listStore.getAt(row);
selection = new CellSelection(m, row, cell);
grid.getView().onCellSelect(row, cell);
grid.getView().focusCell(row, cell, true);
}
@Override
protected void handleMouseDown(GridEvent<M> e) {
if (e.getEvent().getButton() != Event.BUTTON_LEFT || isLocked()) {
return;
}
selectCell(e.getRowIndex(), e.getColIndex());
}
@Override
protected void onAdd(List<? extends M> models) {
deselectAll();
}
@Override
protected void onClear(StoreEvent<M> se) {
super.onClear(se);
selection = null;
}
@Override
protected void onKeyPress(GridEvent<M> e) {
if (editGrid != null) {
// ignore events whose source is an input element
String tag = e.getTarget().getTagName();
if (tag.equals("INPUT") && !e.getTarget().getClassName().equals("_focus")) {
return;
}
}
if (selection == null) {
e.stopEvent();
Cell cell = grid.walkCells(0, 0, 1, callback, false);
if (cell != null) {
selectCell(cell.row, cell.cell);
}
return;
}
int r = selection.row;
int c = selection.cell;
Cell newCell = null;
switch (e.getKeyCode()) {
case KeyCodes.KEY_TAB:
if (e.isShiftKey()) {
newCell = grid.walkCells(r, c - 1, -1, callback, false);
} else {
newCell = grid.walkCells(r, c + 1, 1, callback, false);
}
break;
case KeyCodes.KEY_DOWN: {
newCell = grid.walkCells(r + 1, c, 1, callback, false);
break;
}
case KeyCodes.KEY_UP: {
newCell = grid.walkCells(r - 1, c, -1, callback, false);
break;
}
case KeyCodes.KEY_LEFT:
newCell = grid.walkCells(r, c - 1, -1, callback, false);
break;
case KeyCodes.KEY_RIGHT:
newCell = grid.walkCells(r, c + 1, 1, callback, false);
break;
case KeyCodes.KEY_ENTER:
if (editGrid != null) {
if (!editGrid.isEditing()) {
editGrid.startEditing(r, c);
e.stopEvent();
return;
}
}
break;
}
if (newCell != null) {
selectCell(newCell.row, newCell.cell);
e.stopEvent();
}
}
@Override
protected void onRemove(M model) {
super.onRemove(model);
if (selection != null && selection.model == model) {
selection = null;
}
}
}