Browse Source

Initial commit for #1739, implements Table.addGeneratedColumn()

svn changeset:4911/svn branch:trunk
tags/6.7.0.beta1
Marc Englund 16 years ago
parent
commit
3807919023
1 changed files with 151 additions and 24 deletions
  1. 151
    24
      src/com/itmill/toolkit/ui/Table.java

+ 151
- 24
src/com/itmill/toolkit/ui/Table.java View File

@@ -179,6 +179,11 @@ public class Table extends AbstractSelect implements Action.Container,
*/
private final HashMap columnWidths = new HashMap();

/**
* Holds column generators
*/
private final HashMap columnGenerators = new HashMap();

/**
* Holds value of property pageLength. 0 disables paging.
*/
@@ -319,13 +324,14 @@ public class Table extends AbstractSelect implements Action.Container,
/* Table functionality ************************************************** */

/**
* Gets the array of visible column property id:s.
* Gets the array of visible column id:s, including generated columns.
*
* <p>
* The columns are show in the order of their appearance in this array.
* </p>
*
* @return the Value of property availableColumns.
* @return an array of currently visible propertyIds and generated column
* ids.
*/
public Object[] getVisibleColumns() {
if (visibleColumns == null) {
@@ -357,15 +363,16 @@ public class Table extends AbstractSelect implements Action.Container,
final Collection properties = getContainerPropertyIds();
for (int i = 0; i < visibleColumns.length; i++) {
if (visibleColumns[i] == null) {
throw new NullPointerException("Properties must be non-nulls");
} else if (!properties.contains(visibleColumns[i])) {
throw new NullPointerException("Ids must be non-nulls");
} else if (!properties.contains(visibleColumns[i])
&& !columnGenerators.containsKey(visibleColumns[i])) {
throw new IllegalArgumentException(
"Properties must exist in the Container, missing property: "
"Ids must exist in the Container or as a generated column , missing id: "
+ visibleColumns[i]);
}
}

// If this is called befor the constructor is finished, it might be
// If this is called before the constructor is finished, it might be
// uninitialized
final LinkedList newVC = new LinkedList();
for (int i = 0; i < visibleColumns.length; i++) {
@@ -374,13 +381,19 @@ public class Table extends AbstractSelect implements Action.Container,

// Removes alignments, icons and headers from hidden columns
if (this.visibleColumns != null) {
for (final Iterator i = this.visibleColumns.iterator(); i.hasNext();) {
final Object col = i.next();
if (!newVC.contains(col)) {
setColumnHeader(col, null);
setColumnAlignment(col, null);
setColumnIcon(col, null);
disableContentRefreshing();
try {
for (final Iterator i = this.visibleColumns.iterator(); i
.hasNext();) {
final Object col = i.next();
if (!newVC.contains(col)) {
setColumnHeader(col, null);
setColumnAlignment(col, null);
setColumnIcon(col, null);
}
}
} finally {
enableContentRefreshing(false);
}
}

@@ -1199,8 +1212,8 @@ public class Table extends AbstractSelect implements Action.Container,
final int headmode = getRowHeaderMode();
final boolean[] iscomponent = new boolean[cols];
for (int i = 0; i < cols; i++) {
iscomponent[i] = Component.class
.isAssignableFrom(getType(colids[i]));
iscomponent[i] = columnGenerators.containsKey(colids[i])
|| Component.class.isAssignableFrom(getType(colids[i]));
}
int firstIndexNotInCache;
if (pageBuffer != null && pageBuffer[CELL_ITEMID].length > 0) {
@@ -1229,11 +1242,18 @@ public class Table extends AbstractSelect implements Action.Container,

if (cols > 0) {
for (int j = 0; j < cols; j++) {
final Property p = getContainerProperty(id, colids[j]);
Object value = null;
Property p = null;
Object value = "";
boolean isGenerated = columnGenerators
.containsKey(colids[j]);

if (!isGenerated) {
p = getContainerProperty(id, colids[j]);
}

// check in current pageBuffer already has row
int index = firstIndex + i;
if (p != null) {
if (p != null || isGenerated) {
if (p instanceof Property.ValueChangeNotifier) {
if (oldListenedProperties == null
|| !oldListenedProperties.contains(p)) {
@@ -1251,8 +1271,13 @@ public class Table extends AbstractSelect implements Action.Container,
- pageBufferFirstIndex;
value = pageBuffer[CELL_FIRSTCOL + j][indexInOldBuffer];
} else {
if (isGenerated) {
ColumnGenerator cg = (ColumnGenerator) columnGenerators
.get(colids[j]);
value = cg
.generateCell(this, id, colids[j]);

if (iscomponent[j]) {
} else if (iscomponent[j]) {
value = p.getValue();
} else if (p != null) {
value = getPropertyValue(id, colids[j], p);
@@ -1261,8 +1286,6 @@ public class Table extends AbstractSelect implements Action.Container,
null);
}
}
} else {
value = "";
}

if (value instanceof Component) {
@@ -1470,13 +1493,28 @@ public class Table extends AbstractSelect implements Action.Container,
if (collapsedColumns != null) {
collapsedColumns.clear();
}
setVisibleColumns(getContainerPropertyIds().toArray());

// columnGenerators 'override' properties, don't add the same id twice
Collection col = new LinkedList();
for (Iterator it = getContainerPropertyIds().iterator(); it.hasNext();) {
Object id = it.next();
if (columnGenerators == null || !columnGenerators.containsKey(id)) {
col.add(id);
}
}
// generators added last
if (columnGenerators != null && columnGenerators.size() > 0) {
col.addAll(columnGenerators.keySet());
}

setVisibleColumns(col.toArray());

// null value as we may not be sure that currently selected identifier
// exits in new ds
setValue(null);

// Assure visual refresh
resetPageBuffer();
refreshRenderedCells();
}

@@ -1739,9 +1777,13 @@ public class Table extends AbstractSelect implements Action.Container,
for (final Iterator it = visibleColumns.iterator(); it.hasNext()
&& iscomponentIndex < iscomponent.length;) {
final Object columnId = it.next();
final Class colType = getType(columnId);
iscomponent[iscomponentIndex++] = colType != null
&& Component.class.isAssignableFrom(colType);
if (columnGenerators.containsKey(columnId)) {
iscomponent[iscomponentIndex++] = true;
} else {
final Class colType = getType(columnId);
iscomponent[iscomponentIndex++] = colType != null
&& Component.class.isAssignableFrom(colType);
}
}
target.startTag("rows");
// cells array contains all that are supposed to be visible on client,
@@ -2234,6 +2276,66 @@ public class Table extends AbstractSelect implements Action.Container,
return true;
}

/**
* Adds a generated column to the Table.
* <p>
* A generated column is a column that exists only in the Table, not as a
* property in the underlying Container. It shows up just as a regular
* column.
* </p>
* <p>
* A generated column will override a property with the same id, so that the
* generated column is shown instead of the column representing the
* property. Note that getContainerProperty() will still get the real
* property.
* </p>
* <p>
* Also note that getVisibleColumns() will return the generated columns,
* while getContainerPropertyIds() will not.
* </p>
*
* @param id
* the id of the column to be added
* @param generatedColumn
* the {@link ColumnGenerator} to use for this column
*/
public void addGeneratedColumn(Object id, ColumnGenerator generatedColumn) {
if (generatedColumn == null) {
throw new IllegalArgumentException(
"Can not add null as a GeneratedColumn");
}
if (columnGenerators.containsKey(id)) {
throw new IllegalArgumentException(
"Can not add the same GeneratedColumn twice, id:" + id);
} else {
columnGenerators.put(id, generatedColumn);
visibleColumns.add(id);
resetPageBuffer();
refreshRenderedCells();
}
}

/**
* Removes a generated column previously added with addGeneratedColumn.
*
* @param id
* id of the generated column to remove
* @return true if the column could be removed (existed in the Table)
*/
public boolean removeGeneratedColumn(Object id) {
if (columnGenerators.containsKey(id)) {
columnGenerators.remove(id);
if (!items.containsId(id)) {
visibleColumns.remove(id);
}
resetPageBuffer();
refreshRenderedCells();
return true;
} else {
return false;
}
}

/**
* Returns the list of items on the current page
*
@@ -2652,4 +2754,29 @@ public class Table extends AbstractSelect implements Action.Container,
+ super.toString();
}

/**
* Used to create "generated columns"; columns that exist only in the Table,
* not in the underlying Container. Implement this interface and pass it to
* Table.addGeneratedColumn along with an id for the column to be generated.
*
*/
public interface ColumnGenerator {

/**
* Called by Table when a cell in a generated column needs to be
* generated.
*
* @param source
* the source Table
* @param itemId
* the itemId (aka rowId) for the of the cell to be
* generated
* @param columnId
* the id for the generated column (as specified in
* addGeneratedColumn)
* @return
*/
public abstract Component generateCell(Table source, Object itemId,
Object columnId);
}
}

Loading…
Cancel
Save