public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
VHasDropHandler, FocusHandler, BlurHandler, Focusable, ActionOwner {
+ private static final String ROW_HEADER_COLUMN_KEY = "0";
public static final String CLASSNAME = "v-table";
public static final String CLASSNAME_SELECTION_FOCUS = CLASSNAME + "-focus";
}
+ /**
+ * Non-immediate variable update of column resize events for a bunch of
+ * columns.
+ *
+ * @param columns
+ * the columns to trigger the events for.
+ */
+ private void enqueueColumnResizeEventsForColumns(
+ Collection<HeaderCell> columns) {
+ String[] newSizes = new String[columns.size()];
+ int ix = 0;
+ for (HeaderCell cell : columns) {
+ newSizes[ix++] = cell.getColKey() + ":" + cell.getWidth();
+ }
+ client.updateVariable(paintableId, "columnResizeEvents", newSizes,
+ false);
+ }
+
/**
* Moves the focus one step down
*
int visibleCols = strings.length;
int colIndex = 0;
if (showRowHeaders) {
- tHead.enableColumn("0", colIndex);
+ tHead.enableColumn(ROW_HEADER_COLUMN_KEY, colIndex);
visibleCols++;
visibleColOrder = new String[visibleCols];
- visibleColOrder[colIndex] = "0";
+ visibleColOrder[colIndex] = ROW_HEADER_COLUMN_KEY;
colIndex++;
} else {
visibleColOrder = new String[visibleCols];
- tHead.removeCell("0");
+ tHead.removeCell(ROW_HEADER_COLUMN_KEY);
}
int i;
// Add dummy column if row headers are present
int colIndex = 0;
if (showRowHeaders) {
- tFoot.enableColumn("0", colIndex);
+ tFoot.enableColumn(ROW_HEADER_COLUMN_KEY, colIndex);
colIndex++;
} else {
- tFoot.removeCell("0");
+ tFoot.removeCell(ROW_HEADER_COLUMN_KEY);
}
int i;
*/
private int getColIndexByKey(String colKey) {
// return 0 if asked for rowHeaders
- if ("0".equals(colKey)) {
+ if (ROW_HEADER_COLUMN_KEY.equals(colKey)) {
return 0;
}
for (int i = 0; i < visibleColOrder.length; i++) {
setAlign(ALIGN_LEFT);
}
+ public void disableAutoWidthCalculation() {
+ definedWidth = true;
+ expandRatio = 0;
+ }
+
public void setWidth(int w, boolean ensureDefinedWidth) {
if (ensureDefinedWidth) {
definedWidth = true;
case Event.ONMOUSEUP:
isResizing = false;
DOM.releaseCapture(getElement());
- // readjust undefined width columns
- lazyAdjustColumnWidths.cancel();
- lazyAdjustColumnWidths.schedule(1);
+ tHead.disableAutoColumnWidthCalculation(this);
fireColumnResizeEvent(cid, originalWidth, getColWidth(cid));
break;
case Event.ONMOUSEMOVE:
public class RowHeadersHeaderCell extends HeaderCell {
RowHeadersHeaderCell() {
- super("0", "");
+ super(ROW_HEADER_COLUMN_KEY, "");
this.setStyleName(CLASSNAME + "-header-cell-rowheader");
}
DOM.sinkEvents(columnSelector, Event.ONCLICK);
- availableCells.put("0", new RowHeadersHeaderCell());
+ availableCells.put(ROW_HEADER_COLUMN_KEY,
+ new RowHeadersHeaderCell());
}
@Override
removeCell(cid);
}
availableCells.clear();
- availableCells.put("0", new RowHeadersHeaderCell());
+ availableCells.put(ROW_HEADER_COLUMN_KEY,
+ new RowHeadersHeaderCell());
}
public void updateCellsFromUIDL(UIDL uidl) {
Iterator<?> it = uidl.getChildIterator();
HashSet<String> updated = new HashSet<String>();
- updated.add("0");
while (it.hasNext()) {
final UIDL col = (UIDL) it.next();
final String cid = col.getStringAttribute("cid");
}
return aligns;
}
+
+ /**
+ * Disables the automatic calculation of all column widths by forcing
+ * the widths to be "defined" thus turning off expand ratios and such.
+ */
+ public void disableAutoColumnWidthCalculation(HeaderCell source) {
+ for (HeaderCell cell : availableCells.values()) {
+ cell.disableAutoWidthCalculation();
+ }
+ // fire column resize events for all columns but the source of the
+ // resize action, since an event will fire separately for this.
+ ArrayList<HeaderCell> columns = new ArrayList<HeaderCell>(
+ availableCells.values());
+ columns.remove(source);
+ enqueueColumnResizeEventsForColumns(columns);
+ }
}
/**
public class RowHeadersFooterCell extends FooterCell {
RowHeadersFooterCell() {
- super("0", "");
+ super(ROW_HEADER_COLUMN_KEY, "");
}
@Override
setStyleName(CLASSNAME + "-footer-wrap");
- availableCells.put("0", new RowHeadersFooterCell());
+ availableCells.put(ROW_HEADER_COLUMN_KEY,
+ new RowHeadersFooterCell());
}
@Override
removeCell(cid);
}
availableCells.clear();
- availableCells.put("0", new RowHeadersFooterCell());
+ availableCells.put(ROW_HEADER_COLUMN_KEY,
+ new RowHeadersFooterCell());
}
/*
public void updateCellsFromUIDL(UIDL uidl) {
Iterator<?> columnIterator = uidl.getChildIterator();
HashSet<String> updated = new HashSet<String>();
- updated.add("0");
while (columnIterator.hasNext()) {
final UIDL col = (UIDL) columnIterator.next();
final String cid = col.getStringAttribute("cid");
updated.add(cid);
- String caption = col.getStringAttribute("fcaption");
+ String caption = col.hasAttribute("fcaption") ? col
+ .getStringAttribute("fcaption") : "";
FooterCell c = getFooterCell(cid);
if (c == null) {
c = new FooterCell(cid, caption);
* @return html snippet containing possibly an icon + caption text
*/
protected String buildCaptionHtmlSnippet(UIDL uidl) {
- String s = uidl.getStringAttribute("caption");
+ String s = uidl.hasAttribute("caption") ? uidl
+ .getStringAttribute("caption") : "";
if (uidl.hasAttribute("icon")) {
s = "<img src=\""
+ client.translateVaadinUri(uidl.getStringAttribute("icon"))
*/
private static final double CACHE_RATE_DEFAULT = 2;
+ private static final String ROW_HEADER_COLUMN_ID = "0";
+ private static final Object MAGIC_ROW_HEADER_ID = new Object();
+
/* Private table extensions to Select */
/**
* Column can either have a fixed width or expand ratio. The latter one set
* is used. See @link {@link #setColumnExpandRatio(Object, float)}.
*
- * @param columnId
+ * @param propertyId
* colunmns property id
* @param width
* width to be reserved for colunmns content
* @since 4.0.3
*/
- public void setColumnWidth(Object columnId, int width) {
+ public void setColumnWidth(Object propertyId, int width) {
+ if (propertyId == null) {
+ // Since propertyId is null, this is the row header. Use the magic
+ // id to store the width of the row header.
+ propertyId = MAGIC_ROW_HEADER_ID;
+ }
if (width < 0) {
- columnWidths.remove(columnId);
+ columnWidths.remove(propertyId);
} else {
- columnWidths.put(columnId, Integer.valueOf(width));
+ columnWidths.put(propertyId, Integer.valueOf(width));
}
}
* implementation.
*
* <p>
- * If terminal implementation supports re-sizeable columns the column
- * becomes fixed width column if users resizes the column.
+ * If terminal implementation supports re-sizable columns the column becomes
+ * fixed width column if users resizes the column.
*
- * @param columnId
- * colunmns property id
+ * @param propertyId
+ * columns property id
* @param expandRatio
* the expandRatio used to divide excess space for this column
*/
- public void setColumnExpandRatio(Object columnId, float expandRatio) {
+ public void setColumnExpandRatio(Object propertyId, float expandRatio) {
if (expandRatio < 0) {
- columnWidths.remove(columnId);
+ columnWidths.remove(propertyId);
} else {
- columnWidths.put(columnId, new Float(expandRatio));
+ columnWidths.put(propertyId, new Float(expandRatio));
}
}
* Gets the pixel width of column
*
* @param propertyId
- * @return width of colun or -1 when value not set
+ * @return width of column or -1 when value not set
*/
public int getColumnWidth(Object propertyId) {
+ if (propertyId == null) {
+ // Since propertyId is null, this is the row header. Use the magic
+ // id to retrieve the width of the row header.
+ propertyId = MAGIC_ROW_HEADER_ID;
+ }
final Object width = columnWidths.get(propertyId);
if (width == null || !(width instanceof Integer)) {
return -1;
* Sets the column header for the specified column;
*
* @param propertyId
- * the propertyId indentifying the column.
+ * the propertyId identifying the column.
* @param header
* the header to set.
*/
handleClickEvent(variables);
- handleColumnResizeEvent(variables);
+ handleColumnResizeEvents(variables);
disableContentRefreshing();
*
* @param variables
*/
- private void handleColumnResizeEvent(Map<String, Object> variables) {
+ private void handleColumnResizeEvents(Map<String, Object> variables) {
+ if (variables.containsKey("columnResizeEvents")) {
+ handleMultipleColumnResizeEvents(variables);
+ }
if (variables.containsKey("columnResizeEventColumn")) {
- Object cid = variables.get("columnResizeEventColumn");
- Object propertyId = null;
- if (cid != null) {
- propertyId = columnIdMap.get(cid.toString());
- }
+ handleSingleColumnResizeEvent(variables);
+ }
+ }
- Object prev = variables.get("columnResizeEventPrev");
- int previousWidth = -1;
- if (prev != null) {
- previousWidth = Integer.valueOf(prev.toString());
- }
+ private void handleSingleColumnResizeEvent(Map<String, Object> variables) {
+ Object cid = variables.get("columnResizeEventColumn");
+ Object propertyId = null;
+ if (cid != null) {
+ propertyId = columnIdMap.get(cid.toString());
+ }
- Object curr = variables.get("columnResizeEventCurr");
- int currentWidth = -1;
- if (curr != null) {
- currentWidth = Integer.valueOf(curr.toString());
- }
+ Object prev = variables.get("columnResizeEventPrev");
+ int previousWidth = -1;
+ if (prev != null) {
+ previousWidth = Integer.valueOf(prev.toString());
+ }
- /*
- * Update the sizes on the server side. If a column previously had a
- * expand ratio and the user resized the column then the expand
- * ratio will be turned into a static pixel size.
- */
- setColumnWidth(propertyId, currentWidth);
+ Object curr = variables.get("columnResizeEventCurr");
+ int currentWidth = -1;
+ if (curr != null) {
+ currentWidth = Integer.valueOf(curr.toString());
+ }
+
+ fireColumnResizeEvent(propertyId, previousWidth, currentWidth);
+ }
+
+ private void handleMultipleColumnResizeEvents(Map<String, Object> variables) {
+ String[] events = (String[]) variables.get("columnResizeEvents");
+ for (String str : events) {
+ String[] eventDetails = str.split(":");
+ Object propertyId = columnIdMap.get(eventDetails[0]);
+ int curWidth = Integer.valueOf(eventDetails[1]);
+ int prevWidth = getColumnWidth(propertyId);
- fireEvent(new ColumnResizeEvent(this, propertyId, previousWidth,
- currentWidth));
+ fireColumnResizeEvent(propertyId, prevWidth, curWidth);
}
}
+ private void fireColumnResizeEvent(Object propertyId, int previousWidth,
+ int currentWidth) {
+ /*
+ * Update the sizes on the server side. If a column previously had a
+ * expand ratio and the user resized the column then the expand ratio
+ * will be turned into a static pixel size.
+ */
+ setColumnWidth(propertyId, currentWidth);
+
+ fireEvent(new ColumnResizeEvent(this, propertyId, previousWidth,
+ currentWidth));
+ }
+
/**
* Go to mode where content updates are not done. This is due we want to
* bypass expensive content for some reason (like when we know we may have
if (colheads) {
target.addAttribute("colheaders", true);
}
- if (getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN) {
+ if (rowHeadersAreEnabled()) {
target.addAttribute("rowheaders", true);
}
target.addVariable(this, "collapsedcolumns", collapsedkeys);
}
target.startTag("visiblecolumns");
+ if (rowHeadersAreEnabled()) {
+ target.startTag("column");
+ target.addAttribute("cid", ROW_HEADER_COLUMN_ID);
+ paintColumnWidth(target, MAGIC_ROW_HEADER_ID);
+ target.endTag("column");
+ }
int i = 0;
for (final Iterator<Object> it = visibleColumns.iterator(); it
.hasNext(); i++) {
if (!ALIGN_LEFT.equals(getColumnAlignment(columnId))) {
target.addAttribute("align", getColumnAlignment(columnId));
}
- if (columnWidths.containsKey(columnId)) {
- if (getColumnWidth(columnId) > -1) {
- target.addAttribute("width",
- String.valueOf(getColumnWidth(columnId)));
- } else {
- target.addAttribute("er",
- getColumnExpandRatio(columnId));
- }
- }
+ paintColumnWidth(target, columnId);
target.endTag("column");
}
}
}
}
+ private void paintColumnWidth(PaintTarget target, final Object columnId)
+ throws PaintException {
+ if (columnWidths.containsKey(columnId)) {
+ if (getColumnWidth(columnId) > -1) {
+ target.addAttribute("width",
+ String.valueOf(getColumnWidth(columnId)));
+ } else {
+ target.addAttribute("er", getColumnExpandRatio(columnId));
+ }
+ }
+ }
+
+ private boolean rowHeadersAreEnabled() {
+ return getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN;
+ }
+
private void paintRow(PaintTarget target, final Object[][] cells,
final boolean iseditable, final Set<Action> actionSet,
final boolean[] iscomponent, int indexInRowbuffer,
protected void paintRowHeader(PaintTarget target, Object[][] cells,
int indexInRowbuffer) throws PaintException {
- if (getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN) {
+ if (rowHeadersAreEnabled()) {
if (cells[CELL_HEADER][indexInRowbuffer] != null) {
target.addAttribute("caption",
(String) cells[CELL_HEADER][indexInRowbuffer]);
protected void paintRowIcon(PaintTarget target, final Object[][] cells,
int indexInRowbuffer) throws PaintException {
- if (getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN
+ if (rowHeadersAreEnabled()
&& cells[CELL_ICON][indexInRowbuffer] != null) {
target.addAttribute("icon",
(Resource) cells[CELL_ICON][indexInRowbuffer]);