Browse Source

Fix for multi page selection #3520

svn changeset:12714/svn branch:6.4
tags/6.7.0.beta1
John Alhroos 14 years ago
parent
commit
30850c74c0
2 changed files with 151 additions and 12 deletions
  1. 66
    4
      src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
  2. 85
    8
      src/com/vaadin/ui/Table.java

+ 66
- 4
src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java View File

@@ -127,6 +127,46 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,

private final HashSet<String> selectedRowKeys = new HashSet<String>();

/**
* Represents a select range of rows
*/
private class SelectionRange {
/**
* The starting key of the range
*/
private int startRowKey;

/**
* The ending key of the range
*/
private int endRowKey;

/**
* Constuctor.
*
* @param startRowKey
* The range start. Must be less than endRowKey
* @param endRowKey
* The range end. Must be bigger than startRowKey
*/
public SelectionRange(int startRowKey, int endRowKey) {
this.startRowKey = startRowKey;
this.endRowKey = endRowKey;
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return startRowKey + "-" + endRowKey;
}
};

private final HashSet<SelectionRange> selectedRowRanges = new HashSet<SelectionRange>();

private boolean initializedAndAttached = false;

/**
@@ -275,6 +315,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
final Set<String> selectedKeys = uidl
.getStringArrayVariableAsSet("selected");
selectedRowKeys.clear();
selectedRowRanges.clear();
for (String string : selectedKeys) {
selectedRowKeys.add(string);
}
@@ -3183,6 +3224,21 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
// 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);
}

client
.updateVariable(
paintableId,
@@ -3380,6 +3436,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* previous selection which was not a deselection
*/
if (selectedRowKeys.isEmpty() || lastSelectedRowKey < 0) {
// No previous selection found
deselectAll();
toggleSelection(true);
return;
@@ -3403,17 +3460,19 @@ 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) {
selectedRowKeys.add(String.valueOf(r));
VScrollTableRow row = getRenderedRowByKey(String
.valueOf(r));
if (!row.isSelected()) {
if (row != null && !row.isSelected()) {
row.toggleSelection(false);
}
}
}
// Toggle clicked rows selection
toggleSelection(false);

// Add range
selectedRowRanges.add(new SelectionRange(startKey, endKey));
}

/*
@@ -3515,6 +3574,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
}

/**
* Deselects all items
*/
public void deselectAll() {
final Object[] keys = selectedRowKeys.toArray();
for (int i = 0; i < keys.length; i++) {
@@ -3525,7 +3587,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
// still ensure all selects are removed from (not necessary rendered)
selectedRowKeys.clear();
selectedRowRanges.clear();
}

/**

+ 85
- 8
src/com/vaadin/ui/Table.java View File

@@ -1863,7 +1863,77 @@ public class Table extends AbstractSelect implements Action.Container,
resetPageBuffer();

enableContentRefreshing(true);
}

/**
* Gets items ids from a range of key values
*
* @param startRowKey
* The start key
* @param endRowKey
* The end key
* @return
*/
private Set<Object> getItemIdsInRange(int startRowKey, int endRowKey) {
HashSet<Object> ids = new HashSet<Object>();

Object startItemId = itemIdMapper.get(String.valueOf(startRowKey));
ids.add(startItemId);

Object endItemId = itemIdMapper.get(String.valueOf(endRowKey));
ids.add(endItemId);

Object currentItemId = startItemId;

Container.Ordered ordered = (Container.Ordered) items;
while (currentItemId != endItemId) {
currentItemId = ordered.nextItemId(currentItemId);
if (currentItemId != null) {
ids.add(currentItemId);
}
}

return ids;
}

/**
* Handles selection if selection is a multiselection
*
* @param variables
* The variables
*/
private void handleSelectedItems(Map<String, Object> variables) {
final String[] ka = (String[]) variables.get("selected");
final String[] ranges = (String[]) variables.get("selectedRanges");

// Converts the key-array to id-set
final LinkedList s = new LinkedList();
for (int i = 0; i < ka.length; i++) {
final Object id = itemIdMapper.get(ka[i]);
if (!isNullSelectionAllowed()
&& (id == null || id == getNullSelectionItemId())) {
// skip empty selection if nullselection is not allowed
requestRepaint();
} else if (id != null && containsId(id)) {
s.add(id);
}
}

if (!isNullSelectionAllowed() && s.size() < 1) {
// empty selection not allowed, keep old value
requestRepaint();
return;
}

// Add range items
for (String range : ranges) {
String[] limits = range.split("-");
int start = Integer.valueOf(limits[0]);
int end = Integer.valueOf(limits[1]);
s.addAll(getItemIdsInRange(start, end));
}

setValue(s, true);
}

/* Component basics */
@@ -1890,6 +1960,18 @@ public class Table extends AbstractSelect implements Action.Container,
variables.remove("selected");
}

/*
* The AbstractSelect cannot handle the multiselection properly, instead
* we handle it ourself
*/
else if (isSelectable() && isMultiSelect()
&& variables.containsKey("selected")
&& multiSelectMode == MultiSelectMode.DEFAULT) {
handleSelectedItems(variables);
variables = new HashMap<String, Object>(variables);
variables.remove("selected");
}

super.changeVariables(source, variables);

// Client might update the pagelength if Table height is fixed
@@ -2164,15 +2246,10 @@ public class Table extends AbstractSelect implements Action.Container,

// selection support
LinkedList<String> selectedKeys = new LinkedList<String>();
if (isMultiSelect()) {
// only paint selections that are currently visible in the client
if (isMultiSelect()) {
HashSet sel = new HashSet((Set) getValue());
Collection vids = getVisibleItemIds();
for (Iterator it = vids.iterator(); it.hasNext();) {
Object id = it.next();
if (sel.contains(id)) {
selectedKeys.add(itemIdMapper.key(id));
}
for (Object id : sel) {
selectedKeys.add(itemIdMapper.key(id));
}
} else {
Object value = getValue();

Loading…
Cancel
Save