Browse Source

Changes in Table:

- Changed keyboard selection mechanism 
- Added keyboard control with Home,End,Page Up and Page Down
- Added focus outline

svn changeset:13023/svn branch:6.4
tags/6.7.0.beta1
John Alhroos 14 years ago
parent
commit
2924b070b4

+ 11
- 5
WebContent/VAADIN/themes/base/styles.css View File

@@ -1,5 +1,5 @@
.v-theme-version:after {content:"6_4_0_dev-20100420";}
.v-theme-version-6_4_0_dev-20100420 {display: none;}
.v-theme-version:after {content:"6_4_0_dev-20100504";}
.v-theme-version-6_4_0_dev-20100504 {display: none;}
/* Automatically compiled css file from subdirectories. */

.v-absolutelayout-wrapper {
@@ -1423,6 +1423,9 @@ div.v-progressindicator-indeterminate-disabled {
.v-ie7 .v-table {
overflow: visible;
}
.v-table-body.focused{
border-color: #388ddd;
}
.v-table-header-wrap {
overflow: hidden;
border: 1px solid #aaa;
@@ -1452,10 +1455,9 @@ div.v-progressindicator-indeterminate-disabled {
border-top: none;
background: #efefef;
}
.v-table-footer table,
.v-table-table {
.v-table-footer table{
border-spacing: 0;
border-collapse: separate;
border-collapse: collapse;
margin: 0;
padding: 0;
border: 0;
@@ -1575,6 +1577,10 @@ div.v-progressindicator-indeterminate-disabled {
display: block;
text-align: center;
}
.v-table-body:focus,
.v-table-body-wrapper:focus{
outline: none;
}
/* row in column selector */
.v-on {

+ 3
- 0
WebContent/VAADIN/themes/base/table/table.css View File

@@ -29,6 +29,9 @@
.v-ie7 .v-table {
overflow: visible;
}
.v-table-body.focused{
border-color: #388ddd;
}
.v-table-header-wrap {
overflow: hidden;
border: 1px solid #aaa;

+ 22
- 5
WebContent/VAADIN/themes/reindeer/styles.css View File

@@ -1,5 +1,5 @@
.v-theme-version:after {content:"6_4_0_dev-20100420";}
.v-theme-version-6_4_0_dev-20100420 {display: none;}
.v-theme-version:after {content:"6_4_0_dev-20100504";}
.v-theme-version-6_4_0_dev-20100504 {display: none;}
/* Automatically compiled css file from subdirectories. */

.v-absolutelayout-wrapper {
@@ -1423,6 +1423,9 @@ div.v-progressindicator-indeterminate-disabled {
.v-ie7 .v-table {
overflow: visible;
}
.v-table-body.focused{
border-color: #388ddd;
}
.v-table-header-wrap {
overflow: hidden;
border: 1px solid #aaa;
@@ -1452,10 +1455,9 @@ div.v-progressindicator-indeterminate-disabled {
border-top: none;
background: #efefef;
}
.v-table-footer table,
.v-table-table {
.v-table-footer table{
border-spacing: 0;
border-collapse: separate;
border-collapse: collapse;
margin: 0;
padding: 0;
border: 0;
@@ -1575,6 +1577,10 @@ div.v-progressindicator-indeterminate-disabled {
display: block;
text-align: center;
}
.v-table-body:focus,
.v-table-body-wrapper:focus{
outline: none;
}
/* row in column selector */
.v-on {
@@ -4240,6 +4246,17 @@ td.v-datefield-calendarpanel-nextyear {
.v-table .v-selected .v-table-cell-content {
border-right-color: #466c90;
}
.v-table-body:focus{
outline: none;
}
.v-table .v-table-focus .v-table-cell-content{
border-top: 1px dotted black;
border-bottom: 1px dotted black;
}
.v-table .v-table-focus .v-table-cell-content .v-table-cell-wrapper{
padding-top:2px;
padding-bottom:2px;
}
.v-table-column-selector {
width: 16px;
height: 20px;

+ 5
- 2
WebContent/VAADIN/themes/runo/styles.css View File

@@ -1,5 +1,5 @@
.v-theme-version:after {content:"6_4_0_dev-20100429";}
.v-theme-version-6_4_0_dev-20100429 {display: none;}
.v-theme-version:after {content:"6_4_0_dev-20100504";}
.v-theme-version-6_4_0_dev-20100504 {display: none;}
/* Automatically compiled css file from subdirectories. */

.v-absolutelayout-wrapper {
@@ -1423,6 +1423,9 @@ div.v-progressindicator-indeterminate-disabled {
.v-ie7 .v-table {
overflow: visible;
}
.v-table-body.focused{
border-color: #388ddd;
}
.v-table-header-wrap {
overflow: hidden;
border: 1px solid #aaa;

+ 512
- 120
src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java View File

@@ -145,12 +145,33 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* are selecting a range which is over several pages long
*/
private int lastSelectedRowKey = -1;

/*
* These are used when jumping between pages when pressing Home and End
*/
private boolean selectLastItemInNextRender = false;
private boolean selectFirstItemInNextRender = false;
private boolean focusFirstItemInNextRender = false;
private boolean focusLastItemInNextRender = false;

/*
* The currently focused row
*/
private VScrollTableRow focusedRow;

/*
* Flag for notifying when the selection has changed and should be sent to
* the server
*/
private boolean selectionChanged = false;

/*
* The speed (in pixels) which the scrolling scrolls vertically/horizontally
*/
private int scrollingVelocity = 10;

private Timer scrollingVelocityTimer = null;;

/**
* Represents a select range of rows
*/
@@ -187,6 +208,18 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
public String toString() {
return startRowKey + "-" + endRowKey;
}

public boolean inRange(int key) {
return key >= startRowKey && key <= endRowKey;
}

public int getStartKey() {
return startRowKey;
}

public int getEndKey() {
return endRowKey;
}
};

private final HashSet<SelectionRange> selectedRowRanges = new HashSet<SelectionRange>();
@@ -246,15 +279,13 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,

private int multiselectmode;


public VScrollTable() {
bodyContainerFocus.setStyleName(CLASSNAME + "-body-wrapper");

/*
* Firefox handler auto-repeat works correctly only if we use a key
* press handler, other browsers handle it correctly when using a key
* down handler
* Firefox auto-repeat works correctly only if we use a key press
* handler, other browsers handle it correctly when using a key down
* handler
*/
if (BrowserInfo.get().isGecko()) {
bodyContainerFocus.addKeyPressHandler(this);
@@ -275,24 +306,64 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
add(tFoot);

rowRequestHandler = new RowRequestHandler();

/*
* We need to use the sinkEvents method to catch the keyUp events so we
* can cache a single shift. KeyUpHandler cannot do this.
*/
sinkEvents(Event.ONKEYUP);
}

/*
* (non-Javadoc)
*
* @see
* com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt.user
* .client.Event)
*/
@Override
public void onBrowserEvent(Event event) {
if (event.getTypeInt() == Event.ONKEYUP) {
if (event.getKeyCode() == KeyCodes.KEY_SHIFT) {
sendSelectedRows();
} else if ((event.getKeyCode() == getNavigationUpKey()
|| event.getKeyCode() == getNavigationDownKey()
|| event.getKeyCode() == getNavigationPageUpKey() || event
.getKeyCode() == getNavigationPageDownKey())
&& !event.getShiftKey()) {
sendSelectedRows();
}

scrollingVelocityTimer.cancel();
scrollingVelocityTimer = null;
scrollingVelocity = 10;
}
}

/**
* Moves the focus one step down
*
* @return Returns true if succeeded
*/
private boolean moveFocusDown() {
return moveFocusDown(0);
}

/**
* Moves the selection head one row downloads
* Moves the focus down by 1+offset rows
*
* @return Returns true if succeeded, else false if the selection could not
* be move downwards
*/
private boolean moveSelectionDown() {
private boolean moveFocusDown(int offset) {
if (selectMode > VScrollTable.SELECT_MODE_NONE) {
if (focusedRow == null) {
setRowFocus((VScrollTableRow) scrollBody.iterator().next());
return true;
if (focusedRow == null && scrollBody.iterator().hasNext()) {
return setRowFocus((VScrollTableRow) scrollBody.iterator()
.next());
} else {
VScrollTableRow next = getNextRow(focusedRow);
VScrollTableRow next = getNextRow(focusedRow, offset);
if (next != null) {
setRowFocus(next);
return true;
return setRowFocus(next);
}
}
}
@@ -301,22 +372,30 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}

/**
* Moves the selection head one row upwards
* Moves the selection one step up
*
* @return Returns true if succeeded
*/
private boolean moveFocusUp() {
return moveFocusUp(0);
}

/**
* Moves the focus row upwards
*
* @return Returns true if succeeded, else false if the selection could not
* be move upwards
*
*/
private boolean moveSelectionUp() {
private boolean moveFocusUp(int offset) {
if (selectMode > VScrollTable.SELECT_MODE_NONE) {
if (focusedRow == null) {
setRowFocus((VScrollTableRow) scrollBody.iterator().next());
return true;
if (focusedRow == null && scrollBody.iterator().hasNext()) {
return setRowFocus((VScrollTableRow) scrollBody.iterator()
.next());
} else {
VScrollTableRow prev = getPreviousRow(focusedRow);
VScrollTableRow prev = getPreviousRow(focusedRow, offset);
if (prev != null) {
setRowFocus(prev);
return true;
return setRowFocus(prev);
}
}
}
@@ -335,21 +414,80 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
*/
private void selectFocusedRow(boolean ctrlSelect, boolean shiftSelect) {
if (focusedRow != null) {
if (ctrlSelect && !shiftSelect && selectMode == SELECT_MODE_MULTI) {
focusedRow.toggleSelection(ctrlSelect);
} else if (!ctrlSelect && shiftSelect
&& selectMode == SELECT_MODE_MULTI) {
focusedRow.toggleShiftSelection(true);
} else if (ctrlSelect && shiftSelect
&& selectMode == SELECT_MODE_MULTI) {
focusedRow.toggleShiftSelection(false);
} else {
// Arrows moves the selection and clears previous selections
if (selectMode > SELECT_MODE_NONE && !ctrlSelect && !shiftSelect) {
deselectAll();
focusedRow.toggleSelection(true);
focusedRow.toggleSelection(!ctrlSelect);
}

// Ctrl+arrows moves selection head
else if (selectMode > SELECT_MODE_NONE && ctrlSelect
&& !shiftSelect) {
// No selection, only selection head is moved
}

// Shift+arrows selection selects a range
else if (selectMode == SELECT_MODE_MULTI && !ctrlSelect
&& shiftSelect) {
focusedRow.toggleShiftSelection(shiftSelect);
}
}
}

/**
* Sends the selection to the server
*/
private void sendSelectedRows(){
// Don't send anything if selection has not changed
if (!selectionChanged) {
return;
}

// Reset selection changed flag
selectionChanged = false;

// Note: changing the immediateness of this
// might
// require changes to "clickEvent" immediateness
// also.
if (multiselectmode == MULTISELECT_MODE_DEFAULT) {
// Convert ranges to a set of strings
Set<String> ranges = new HashSet<String>();
for (SelectionRange range : selectedRowRanges) {
ranges.add(range.toString());
}

/*
* Clear ranges since they are transformed
* on the server side to row selections
*/
if (immediate) {
selectedRowRanges.clear();
}

// Send the selected row ranges
client
.updateVariable(
paintableId,
"selectedRanges",
ranges
.toArray(new String[selectedRowRanges
.size()]),
false);
}

// Send the selected rows
client
.updateVariable(
paintableId,
"selected",
selectedRowKeys
.toArray(new String[selectedRowKeys
.size()]),
immediate);

}

/**
* Get the key that moves the selection head upwards. By default it is the
* up arrow key but by overriding this you can change the key to whatever
@@ -405,6 +543,57 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
return 32;
}

/**
* Get the key the moves the selection one page up in the table. By default
* this is the Page Up key but by overriding this you can change the key to
* whatever you want.
*
* @return
*/
protected int getNavigationPageUpKey() {
return KeyCodes.KEY_PAGEUP;
}

/**
* Get the key the moves the selection one page down in the table. By
* default this is the Page Down key but by overriding this you can change
* the key to whatever you want.
*
* @return
*/
protected int getNavigationPageDownKey() {
return KeyCodes.KEY_PAGEDOWN;
}

/**
* Get the key the moves the selection to the beginning of the table. By
* default this is the Home key but by overriding this you can change the
* key to whatever you want.
*
* @return
*/
protected int getNavigationStartKey() {
return KeyCodes.KEY_HOME;
}

/**
* Get the key the moves the selection to the end of the table. By default
* this is the End key but by overriding this you can change the key to
* whatever you want.
*
* @return
*/
protected int getNavigationEndKey() {
return KeyCodes.KEY_END;
}

/*
* (non-Javadoc)
*
* @see
* com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal
* .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection)
*/
@SuppressWarnings("unchecked")
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
rendering = true;
@@ -590,10 +779,62 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,

hideScrollPositionAnnotation();
purgeUnregistryBag();

// This is called when the Home button has been pressed and the pages
// changes
if (selectFirstItemInNextRender) {
selectFirstRenderedRow(false);
selectFirstItemInNextRender = false;
}

if (focusFirstItemInNextRender) {
selectFirstRenderedRow(true);
focusFirstItemInNextRender = false;
}

// This is called when the End button has been pressed and the pages
// changes
if (selectLastItemInNextRender) {
selectLastRenderedRow(false);
selectLastItemInNextRender = false;
}

if (focusLastItemInNextRender) {
selectLastRenderedRow(true);
focusLastItemInNextRender = false;
}

rendering = false;
headerChangedDuringUpdate = false;
}

private void selectLastRenderedRow(boolean focusOnly) {
VScrollTableRow row = null;
Iterator<Widget> it = scrollBody.iterator();
while (it.hasNext()) {
row = (VScrollTableRow) it.next();
}
if (row != null) {
setRowFocus(row);
if (!focusOnly) {
deselectAll();
selectFocusedRow(false, false);
sendSelectedRows();
}
}

}

private void selectFirstRenderedRow(boolean focusOnly) {
setRowFocus((VScrollTableRow) scrollBody.iterator().next());
if (!focusOnly) {
deselectAll();
selectFocusedRow(false, false);
sendSelectedRows();
}

}

private void setCacheRate(double d) {
if (cache_rate != d) {
cache_rate = d;
@@ -812,25 +1053,27 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
return null;
}
/**
* Returns the next row to the given row
*
* @param row
* The row to calculate from
*
* @return The next row or null if no row exists
*/
private VScrollTableRow getNextRow(VScrollTableRow row){
private VScrollTableRow getNextRow(VScrollTableRow row, int offset) {
final Iterator<Widget> it = scrollBody.iterator();
VScrollTableRow r = null;
while (it.hasNext()) {
r = (VScrollTableRow) it.next();
if(r == row){
if (it.hasNext()) {
return (VScrollTableRow) it.next();
} else {
break;
r = null;
while (offset >= 0 && it.hasNext()) {
r = (VScrollTableRow) it.next();
offset--;
}
return r;
}
}
@@ -844,18 +1087,22 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* The row to calculate from
* @return The previous row or null if no row exists
*/
private VScrollTableRow getPreviousRow(VScrollTableRow row) {
private VScrollTableRow getPreviousRow(VScrollTableRow row, int offset) {
final Iterator<Widget> it = scrollBody.iterator();
final Iterator<Widget> offsetIt = scrollBody.iterator();
VScrollTableRow r = null;
VScrollTableRow prev = null;
while (it.hasNext()) {
r = (VScrollTableRow) it.next();
if (offset < 0) {
prev = (VScrollTableRow) offsetIt.next();
}
if (r == row) {
return prev;
} else {
prev = r;
}
offset--;
}

return null;
}

@@ -3449,35 +3696,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
.setPropertyJSO("onselectstart",
null);
}

// Note: changing the immediateness of this
// might
// require changes to "clickEvent" immediateness
// also.
if (multiselectmode == MULTISELECT_MODE_DEFAULT) {
Set<String> ranges = new HashSet<String>();
for (SelectionRange range : selectedRowRanges) {
ranges.add(range.toString());
}
client
.updateVariable(
paintableId,
"selectedRanges",
ranges
.toArray(new String[selectedRowRanges
.size()]),
false);
}

// Send the selected rows
client
.updateVariable(
paintableId,
"selected",
selectedRowKeys
.toArray(new String[selectedRowKeys
.size()]),
immediate);
sendSelectedRows();
}
break;
case Event.ONCONTEXTMENU:
@@ -3641,6 +3860,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
*/
public void toggleSelection(boolean ctrlSelect) {
selected = !selected;
selectionChanged = true;
if (selected) {
if (ctrlSelect) {
lastSelectedRowKey = rowKey;
@@ -3650,6 +3870,40 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
} else {
removeStyleName("v-selected");
selectedRowKeys.remove(String.valueOf(rowKey));
removeKeyFromSelectedRange(rowKey);
}
}

/**
* Removes a key from a range if the key is found in a selected
* range
*
* @param key
* The key to remove
*/
private void removeKeyFromSelectedRange(int key){
for(SelectionRange range : selectedRowRanges){
if (range.inRange(key)) {
int start = range.getStartKey();
int end = range.getEndKey();

if (start < key && end > key) {
selectedRowRanges.add(new SelectionRange(start,
key - 1));
selectedRowRanges.add(new SelectionRange(key + 1,
end));
} else if (start == key && start < end) {
selectedRowRanges.add(new SelectionRange(start + 1,
end));
} else if (end == key && start < end) {
selectedRowRanges.add(new SelectionRange(start,
end - 1));
}

selectedRowRanges.remove(range);

break;
}
}
}

@@ -3690,19 +3944,31 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}

// Select the range (not including this row)
for (int r = startKey; r <= endKey; r++) {
if (r != rowKey) {
VScrollTableRow row = getRenderedRowByKey(String
.valueOf(r));
if (row != null && !row.isSelected()) {
row.toggleSelection(false);
selectedRowKeys.add(String.valueOf(r));
}
}
VScrollTableRow startRow = getRenderedRowByKey(String
.valueOf(startKey));
VScrollTableRow endRow = getRenderedRowByKey(String
.valueOf(endKey));
// If start row is null then we have a multipage selection from
// above
if (startRow == null) {
startRow = (VScrollTableRow) scrollBody.iterator().next();
}

// Toggle clicked rows selection
toggleSelection(false);
Iterator<Widget> rows = scrollBody.iterator();
boolean startSelection = false;
while (rows.hasNext()) {
VScrollTableRow row = (VScrollTableRow) rows.next();
if (row == startRow || startSelection) {
startSelection = true;
row.toggleSelection(false);
selectedRowKeys.add(row.getKey());
}

if (row == endRow && row != null) {
startSelection = false;
}
}

// Add range
selectedRowRanges.add(new SelectionRange(startKey, endKey));
@@ -4376,11 +4642,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
*
* @param row
* The row to where the selection head should move
* @return Returns true if focus was moved successfully, else false
*/
private void setRowFocus(VScrollTableRow row) {
private boolean setRowFocus(VScrollTableRow row) {

if (selectMode == SELECT_MODE_NONE) {
return;
return false;
}

// Remove previous selection
@@ -4389,8 +4656,16 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}

if (row != null) {
// Apply focus style to new selection

// Trying to set focus on already focused row
if (row == focusedRow) {
return false;
}

// Set new focused row
focusedRow = row;

// Apply focus style to new selection
focusedRow.addStyleName(CLASSNAME_SELECTION_FOCUS);

// Scroll up or down if needed
@@ -4407,7 +4682,13 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
.getScrollPosition()
- focusedRow.getOffsetHeight());
}

return true;
} else {
focusedRow = null;
}

return false;
}

/**
@@ -4417,64 +4698,149 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* The keyboard event received
*/
private void handleNavigation(Event event) {
if (event.getKeyCode() == KeyCodes.KEY_TAB) {
// Do not handle tab key
return;
}

// Down navigation
if (selectMode == SELECT_MODE_NONE
&& event.getKeyCode() == getNavigationDownKey()) {
bodyContainer
.setScrollPosition(bodyContainer.getScrollPosition() + 5);
event.preventDefault();
bodyContainer.setScrollPosition(bodyContainer.getScrollPosition()
+ scrollingVelocity);
} else if (event.getKeyCode() == getNavigationDownKey()) {
if (moveSelectionDown()) {
if (event.getShiftKey()) {
selectFocusedRow(false, true);
}
event.preventDefault();
if (selectMode == SELECT_MODE_MULTI && moveFocusDown()) {
selectFocusedRow(event.getCtrlKey() || event.getMetaKey(),
event.getShiftKey());
} else if (selectMode == SELECT_MODE_SINGLE && !event.getShiftKey()
&& moveFocusDown()) {
selectFocusedRow(event.getCtrlKey() || event.getMetaKey(),
event.getShiftKey());
}
}

// Up navigation
if (selectMode == SELECT_MODE_NONE
&& event.getKeyCode() == getNavigationUpKey()) {
bodyContainer
.setScrollPosition(bodyContainer.getScrollPosition() - 5);
event.preventDefault();
bodyContainer.setScrollPosition(bodyContainer.getScrollPosition()
- scrollingVelocity);
} else if (event.getKeyCode() == getNavigationUpKey()) {
if (moveSelectionUp()) {
if (event.getShiftKey()) {
selectFocusedRow(false, true);
}
event.preventDefault();
if (selectMode == SELECT_MODE_MULTI && moveFocusUp()) {
selectFocusedRow(event.getCtrlKey() || event.getMetaKey(),
event.getShiftKey());
} else if (selectMode == SELECT_MODE_SINGLE && !event.getShiftKey()
&& moveFocusUp()) {
selectFocusedRow(event.getCtrlKey() || event.getMetaKey(),
event.getShiftKey());
}
}

// Left navigation
} else if (event.getKeyCode() == getNavigationLeftKey()) {
// Left navigation
if (event.getKeyCode() == getNavigationLeftKey()) {
bodyContainer.setHorizontalScrollPosition(bodyContainer
.getHorizontalScrollPosition() - 5);
event.preventDefault();
.getHorizontalScrollPosition()
- scrollingVelocity);

// Right navigation
} else if (event.getKeyCode() == getNavigationRightKey()) {
bodyContainer.setHorizontalScrollPosition(bodyContainer
.getHorizontalScrollPosition() + 5);
event.preventDefault();
.getHorizontalScrollPosition()
+ scrollingVelocity);
}

// Select navigation
if (selectMode > SELECT_MODE_NONE
&& event.getKeyCode() == getNavigationSelectKey()) {
selectFocusedRow(event.getCtrlKey() || event.getMetaKey(),
event.getShiftKey());
&& event.getKeyCode() == getNavigationSelectKey()) {
if (selectMode == SELECT_MODE_SINGLE) {
boolean wasSelected = focusedRow.isSelected();
deselectAll();
lastSelectedRowKey = -1;
if (!wasSelected) {
focusedRow.toggleSelection(true);
}

event.preventDefault();
} else {
focusedRow.toggleSelection(true);
}

sendSelectedRows();
}

// Page Down navigation
if (event.getKeyCode() == getNavigationPageDownKey()) {
int rowHeight = (int) scrollBody.getRowHeight();
int offset = pageLength * rowHeight - rowHeight;
bodyContainer.setScrollPosition(bodyContainer.getScrollPosition()
+ offset);
if (selectMode > SELECT_MODE_NONE) {
if (!moveFocusDown(pageLength - 2)) {
final int lastRendered = scrollBody.getLastRendered();
if (lastRendered == totalRows - 1) {
selectLastRenderedRow(false);
} else {
selectLastItemInNextRender = true;
}
} else {
selectFocusedRow(false, false);
sendSelectedRows();
}
}
}

// Send the selected rows
client
.updateVariable(paintableId, "selected",
selectedRowKeys
.toArray(new String[selectedRowKeys
.size()]), immediate);
// Page Up navigation
if (event.getKeyCode() == getNavigationPageUpKey()) {
int rowHeight = (int) scrollBody.getRowHeight();
int offset = pageLength * rowHeight - rowHeight;
bodyContainer.setScrollPosition(bodyContainer.getScrollPosition()
- offset);
if (selectMode > SELECT_MODE_NONE) {
if (!moveFocusUp(pageLength - 2)) {
final int firstRendered = scrollBody.getFirstRendered();
if (firstRendered == 0) {
selectFirstRenderedRow(false);
} else {
selectFirstItemInNextRender = true;
}
} else {
selectFocusedRow(false, false);
sendSelectedRows();
}
}
}

// Goto start navigation
if (event.getKeyCode() == getNavigationStartKey()) {
if (selectMode > SELECT_MODE_NONE) {
final int firstRendered = scrollBody.getFirstRendered();
boolean focusOnly = event.getCtrlKey() || event.getMetaKey();
if (firstRendered == 0) {
selectFirstRenderedRow(focusOnly);
} else if (focusOnly) {
focusFirstItemInNextRender = true;
} else {
selectFirstItemInNextRender = true;
}
}
bodyContainer.setScrollPosition(0);
}

// Goto end navigation
if (event.getKeyCode() == getNavigationEndKey()) {
if (selectMode > SELECT_MODE_NONE) {
final int lastRendered = scrollBody.getLastRendered();
boolean focusOnly = event.getCtrlKey() || event.getMetaKey();
if (lastRendered == totalRows - 1) {
selectLastRenderedRow(focusOnly);
} else if (focusOnly) {
focusLastItemInNextRender = true;
} else {
selectLastItemInNextRender = true;
}
}
bodyContainer.setScrollPosition(scrollBody.getOffsetHeight());
}

event.preventDefault();
}

/*
@@ -4486,6 +4852,17 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
*/
public void onKeyPress(KeyPressEvent event) {
handleNavigation((Event) event.getNativeEvent().cast());

// Start the velocityTimer
if (scrollingVelocityTimer == null) {
scrollingVelocityTimer = new Timer() {
@Override
public void run() {
scrollingVelocity++;
}
};
scrollingVelocityTimer.scheduleRepeating(100);
}
}

/*
@@ -4497,6 +4874,17 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
*/
public void onKeyDown(KeyDownEvent event) {
handleNavigation((Event) event.getNativeEvent().cast());

// Start the velocityTimer
if (scrollingVelocityTimer == null) {
scrollingVelocityTimer = new Timer() {
@Override
public void run() {
scrollingVelocity++;
}
};
scrollingVelocityTimer.scheduleRepeating(100);
}
}

/*
@@ -4507,10 +4895,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* .dom.client.FocusEvent)
*/
public void onFocus(FocusEvent event) {
// Move focus from wrapper to container in FF, ignored in other browsers
if (BrowserInfo.get().isFF3()) {
bodyContainer.getElement().focus();
}
bodyContainer.addStyleName("focused");

// Focus a row if no row is in focus
if (focusedRow == null) {
setRowFocus((VScrollTableRow) scrollBody.iterator().next());
}
@@ -4524,7 +4911,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* .dom.client.BlurEvent)
*/
public void onBlur(BlurEvent event) {
bodyContainer.removeStyleName("focused");

// Unfocus any row
setRowFocus(null);
}



}

+ 4
- 2
tests/src/com/vaadin/tests/components/table/KeyControl.java View File

@@ -64,7 +64,8 @@ public class KeyControl extends TestBase {

table2.addListener(new Table.ValueChangeListener() {
public void valueChange(ValueChangeEvent event) {
String value = table2.getValue().toString();
String value = table2.getValue() == null ? "No selected items"
: table2.getValue().toString();
selected2.setValue(value);
}
});
@@ -87,7 +88,8 @@ public class KeyControl extends TestBase {
table3.addListener(new Table.ValueChangeListener() {
public void valueChange(ValueChangeEvent event) {
Set<String> value = (Set<String>) table3.getValue();
selected3.setValue(value);
selected3.setValue(value.size() == 0 ? "No selected items"
: value);
}
});


+ 93
- 0
tests/src/com/vaadin/tests/components/table/TableContextMenuOnField.java View File

@@ -0,0 +1,93 @@
package com.vaadin.tests.components.table;

import com.vaadin.event.Action;
import com.vaadin.event.LayoutEvents.LayoutClickEvent;
import com.vaadin.event.LayoutEvents.LayoutClickListener;
import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.Link;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;

public class TableContextMenuOnField extends TestBase {

private static final Action ACTION_MYACTION = new Action("Action!!");

@Override
protected void setup() {
Table table = new Table();
table.setSelectable(true);
table.setMultiSelect(true);

table.addActionHandler(new Action.Handler() {
public void handleAction(Action action, Object sender, Object target) {
// TODO Auto-generated method stub

}

public Action[] getActions(Object target, Object sender) {
return new Action[] { ACTION_MYACTION };
}
});

table.addGeneratedColumn("layout", new Table.ColumnGenerator() {

public Component generateCell(Table source, Object itemId,
Object columnId) {

VerticalLayout layout = new VerticalLayout();
layout.addComponent(new TextField());

layout.addListener(new LayoutClickListener() {

public void layoutClick(LayoutClickEvent event) {
getMainWindow().showNotification("HELLO");

}
});

return layout;
}
});

table.addGeneratedColumn("textfield", new Table.ColumnGenerator() {
public Component generateCell(Table source, Object itemId,
Object columnId) {
return new TextField();
}
});

table.addGeneratedColumn("link", new Table.ColumnGenerator() {
public Component generateCell(Table source, Object itemId,
Object columnId) {
return new Link("Link", null);
}
});

table.addGeneratedColumn("button", new Table.ColumnGenerator() {
public Component generateCell(Table source, Object itemId,
Object columnId) {
return new Button("Button");
}
});

table.addItem();
table.addItem();
table.addItem();
addComponent(table);
}

@Override
protected String getDescription() {
return "Right clicking on an item without a context menu should bring"
+ "up the Tables context menu";
}

@Override
protected Integer getTicketNumber() {
return 4264;
}

}

Loading…
Cancel
Save