|
|
@@ -21,7 +21,10 @@ import com.google.gwt.dom.client.Element; |
|
|
|
import com.google.gwt.event.dom.client.KeyCodes; |
|
|
|
import com.google.gwt.user.client.Event; |
|
|
|
import com.google.gwt.user.client.ui.Widget; |
|
|
|
import com.vaadin.client.ComponentConnector; |
|
|
|
import com.vaadin.client.Util; |
|
|
|
import com.vaadin.client.WidgetUtil; |
|
|
|
import com.vaadin.client.ui.AbstractFieldConnector; |
|
|
|
import com.vaadin.client.ui.FocusUtil; |
|
|
|
import com.vaadin.client.widgets.Grid; |
|
|
|
import com.vaadin.client.widgets.Grid.Editor; |
|
|
@@ -124,6 +127,46 @@ public class DefaultEditorEventHandler<T> implements Editor.EventHandler<T> { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Specifies the direction at which the focus should move. |
|
|
|
*/ |
|
|
|
public enum CursorMoveDelta { |
|
|
|
UP(-1, 0), RIGHT(0, 1), DOWN(1, 0), LEFT(0, -1); |
|
|
|
|
|
|
|
public final int rowDelta; |
|
|
|
public final int colDelta; |
|
|
|
|
|
|
|
CursorMoveDelta(int rowDelta, int colDelta) { |
|
|
|
this.rowDelta = rowDelta; |
|
|
|
this.colDelta = colDelta; |
|
|
|
} |
|
|
|
|
|
|
|
public boolean isChanged() { |
|
|
|
return rowDelta != 0 || colDelta != 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns the direction to which the cursor should move. |
|
|
|
* |
|
|
|
* @param event |
|
|
|
* the mouse event, not null. |
|
|
|
* @return the direction. May return null if the cursor should not move. |
|
|
|
*/ |
|
|
|
protected CursorMoveDelta getDeltaFromKeyDownEvent( |
|
|
|
EditorDomEvent<T> event) { |
|
|
|
Event e = event.getDomEvent(); |
|
|
|
if (e.getKeyCode() == KEYCODE_MOVE_VERTICAL) { |
|
|
|
return e.getShiftKey() ? CursorMoveDelta.UP : CursorMoveDelta.DOWN; |
|
|
|
} else if (e.getKeyCode() == KEYCODE_MOVE_HORIZONTAL) { |
|
|
|
// Prevent tab out of Grid Editor |
|
|
|
event.getDomEvent().preventDefault(); |
|
|
|
return e.getShiftKey() ? CursorMoveDelta.LEFT |
|
|
|
: CursorMoveDelta.RIGHT; |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Moves the editor to another row or another column if the received event |
|
|
|
* is a move event. The default implementation moves the editor to the |
|
|
@@ -150,47 +193,37 @@ public class DefaultEditorEventHandler<T> implements Editor.EventHandler<T> { |
|
|
|
return true; |
|
|
|
} else if (e.getTypeInt() == Event.ONKEYDOWN) { |
|
|
|
|
|
|
|
int rowDelta = 0; |
|
|
|
int colDelta = 0; |
|
|
|
|
|
|
|
if (e.getKeyCode() == KEYCODE_MOVE_VERTICAL) { |
|
|
|
rowDelta = (e.getShiftKey() ? -1 : +1); |
|
|
|
} else if (e.getKeyCode() == KEYCODE_MOVE_HORIZONTAL) { |
|
|
|
colDelta = (e.getShiftKey() ? -1 : +1); |
|
|
|
// Prevent tab out of Grid Editor |
|
|
|
event.getDomEvent().preventDefault(); |
|
|
|
} |
|
|
|
|
|
|
|
final boolean changed = rowDelta != 0 || colDelta != 0; |
|
|
|
CursorMoveDelta delta = getDeltaFromKeyDownEvent(event); |
|
|
|
final boolean changed = delta != null; |
|
|
|
|
|
|
|
if (changed) { |
|
|
|
|
|
|
|
int columnCount = event.getGrid().getVisibleColumns().size(); |
|
|
|
|
|
|
|
int colIndex = colDelta > 0 |
|
|
|
int colIndex = delta.colDelta > 0 |
|
|
|
? findNextEditableColumnIndex(event.getGrid(), |
|
|
|
event.getFocusedColumnIndex() + colDelta) |
|
|
|
event.getFocusedColumnIndex() + delta.colDelta) |
|
|
|
: findPrevEditableColumnIndex(event.getGrid(), |
|
|
|
event.getFocusedColumnIndex() + colDelta); |
|
|
|
event.getFocusedColumnIndex() + delta.colDelta); |
|
|
|
int rowIndex = event.getRowIndex(); |
|
|
|
|
|
|
|
// Handle row change with horizontal move when column goes out |
|
|
|
// of range. |
|
|
|
if (rowDelta == 0 && colIndex < 0) { |
|
|
|
if (colDelta > 0 |
|
|
|
if (delta.rowDelta == 0 && colIndex < 0) { |
|
|
|
if (delta.colDelta > 0 |
|
|
|
&& rowIndex < event.getGrid().getDataSource().size() |
|
|
|
- 1) { |
|
|
|
rowDelta = 1; |
|
|
|
delta = CursorMoveDelta.DOWN; |
|
|
|
colIndex = findNextEditableColumnIndex(event.getGrid(), |
|
|
|
0); |
|
|
|
} else if (colDelta < 0 && rowIndex > 0) { |
|
|
|
rowDelta = -1; |
|
|
|
} else if (delta.colDelta < 0 && rowIndex > 0) { |
|
|
|
delta = CursorMoveDelta.UP; |
|
|
|
colIndex = findPrevEditableColumnIndex(event.getGrid(), |
|
|
|
columnCount - 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
editRow(event, rowIndex + rowDelta, colIndex); |
|
|
|
editRow(event, rowIndex + delta.rowDelta, colIndex); |
|
|
|
} |
|
|
|
|
|
|
|
return changed; |
|
|
@@ -212,16 +245,44 @@ public class DefaultEditorEventHandler<T> implements Editor.EventHandler<T> { |
|
|
|
* <code>startingWith</code> itself. Returns -1 if there is no such |
|
|
|
* column. |
|
|
|
*/ |
|
|
|
private int findNextEditableColumnIndex(Grid<T> grid, int startingWith) { |
|
|
|
protected int findNextEditableColumnIndex(Grid<T> grid, int startingWith) { |
|
|
|
final List<Grid.Column<?, T>> columns = grid.getVisibleColumns(); |
|
|
|
for (int i = startingWith; i < columns.size(); i++) { |
|
|
|
if (columns.get(i).isEditable()) { |
|
|
|
if (isEditable(grid, columns.get(i))) { |
|
|
|
return i; |
|
|
|
} |
|
|
|
} |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
protected boolean isEditable(Grid<T> grid, Grid.Column<?, T> column) { |
|
|
|
if (!column.isEditable()) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// figure out whether the widget nested in the editor cell is editable. |
|
|
|
// if it is disabled or read-only then it is not editable. |
|
|
|
|
|
|
|
final Widget editorCell = grid.getEditorWidget(column); |
|
|
|
final ComponentConnector connector = Util.findConnectorFor(editorCell); |
|
|
|
if (connector == null) { |
|
|
|
// not a Vaadin Connector, perhaps something generated by the |
|
|
|
// renderer? Assume it's enabled. |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
if (!connector.isEnabled()) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
if (connector instanceof AbstractFieldConnector) { |
|
|
|
final AbstractFieldConnector field = (AbstractFieldConnector) connector; |
|
|
|
if (field.isReadOnly()) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Finds index of the last editable column, searching backwards starting at |
|
|
|
* the specified index. |
|
|
@@ -235,10 +296,10 @@ public class DefaultEditorEventHandler<T> implements Editor.EventHandler<T> { |
|
|
|
* <code>startingWith</code> itself. Returns -1 if there is no such |
|
|
|
* column. |
|
|
|
*/ |
|
|
|
private int findPrevEditableColumnIndex(Grid<T> grid, int startingWith) { |
|
|
|
protected int findPrevEditableColumnIndex(Grid<T> grid, int startingWith) { |
|
|
|
final List<Grid.Column<?, T>> columns = grid.getVisibleColumns(); |
|
|
|
for (int i = startingWith; i >= 0; i--) { |
|
|
|
if (columns.get(i).isEditable()) { |
|
|
|
if (isEditable(grid, columns.get(i))) { |
|
|
|
return i; |
|
|
|
} |
|
|
|
} |