All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.webtoolkit.jwt.WTable Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2009 Emweb bvba, Leuven, Belgium.
 *
 * See the LICENSE file for terms of use.
 */
package eu.webtoolkit.jwt;

import java.util.*;
import java.util.regex.*;
import java.io.*;
import java.lang.ref.*;
import java.util.concurrent.locks.ReentrantLock;
import javax.servlet.http.*;
import javax.servlet.*;
import eu.webtoolkit.jwt.*;
import eu.webtoolkit.jwt.chart.*;
import eu.webtoolkit.jwt.utils.*;
import eu.webtoolkit.jwt.servlet.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A container widget which provides layout of children in a table grid.
 * 

* * A WTable arranges its children in a table. *

* To insert or access contents, use * {@link WTable#getElementAt(int row, int column) getElementAt()} to access the * {@link WTableCell cell} at a particular location in the table. The WTable * expands automatically to create the indexed (row, column) as necessary. *

* It is possible to insert and delete entire rows or columns from the table * using the {@link WTable#insertColumn(int column) insertColumn()}, * {@link WTable#insertRow(int row) insertRow()}, * {@link WTable#deleteColumn(int column) deleteColumn()}, or * {@link WTable#deleteRow(int row) deleteRow()} methods. *

* You may indicate a number of rows and columns that act as headers using * {@link WTable#setHeaderCount(int count, Orientation orientation) * setHeaderCount()}. Header cells are rendered as <th> * instead of <td> elements. By default, no rows or columns * are configured as headers. *

* WTable is displayed as a {@link WWidget#setInline(boolean inlined) block}. *

*

CSS

*

* The widget corresponds to the HTML <table> tag and does * not provide styling. It can be styled using inline or external CSS as * appropriate. *

* * @see WTableCell * @see WTableRow * @see WTableColumn */ public class WTable extends WInteractWidget { private static Logger logger = LoggerFactory.getLogger(WTable.class); /** * Creates an empty table. */ public WTable(WContainerWidget parent) { super(parent); this.flags_ = new BitSet(); this.rows_ = new ArrayList(); this.columns_ = new ArrayList(); this.rowsChanged_ = null; this.rowsAdded_ = 0; this.headerRowCount_ = 0; this.headerColumnCount_ = 0; this.setInline(false); this.setIgnoreChildRemoves(true); } /** * Creates an empty table. *

* Calls {@link #WTable(WContainerWidget parent) * this((WContainerWidget)null)} */ public WTable() { this((WContainerWidget) null); } /** * Deletes the table and its entire contents. */ public void remove() { for (int i = 0; i < this.rows_.size(); ++i) { ; } for (int i = 0; i < this.columns_.size(); ++i) { ; } ; this.rowsChanged_ = null; super.remove(); } /** * Accesses the table element at the given row and column. *

* If the row/column is beyond the current table dimensions, then the table * is expanded automatically. */ public WTableCell getElementAt(int row, int column) { this.expand(row, column, 1, 1); WTableRow.TableData d = this.itemAt(row, column); return d.cell; } /** * Returns the row object for the given row. *

* Like with {@link WTable#getElementAt(int row, int column) getElementAt()} * , the table expands automatically when the row is beyond the current * table dimensions. *

* * @see WTable#getElementAt(int row, int column) * @see WTable#getColumnAt(int column) */ public WTableRow getRowAt(int row) { this.expand(row, 0, 1, 0); return this.rows_.get(row); } /** * Returns the column object for the given column. *

* Like with {@link WTable#getElementAt(int row, int column) getElementAt()} * , the table expands automatically when the column is beyond the current * table dimensions. *

* * @see WTable#getElementAt(int row, int column) * @see WTable#getRowAt(int row) */ public WTableColumn getColumnAt(int column) { this.expand(0, column, 0, 1); return this.columns_.get(column); } /** * Deletes a table cell and its contents. *

* The table cell at that position is recreated. */ public void removeCell(WTableCell item) { this.removeCell(item.getRow(), item.getColumn()); } /** * Deletes the table cell at the given position. *

* * @see WTable#removeCell(WTableCell item) */ public void removeCell(int row, int column) { WTableRow.TableData d = this.itemAt(row, column); if (d.cell != null) d.cell.remove(); d.cell = new WTableCell(this.rows_.get(row), column); } /** * Inserts an empty row. */ public WTableRow insertRow(int row) { if (row == this.getRowCount()) { return this.getRowAt(row); } else { WTableRow tableRow = new WTableRow(this, this.getColumnCount()); this.rows_.add(0 + row, tableRow); this.flags_.set(BIT_GRID_CHANGED); this.repaint(EnumSet.of(RepaintFlag.RepaintInnerHtml)); return tableRow; } } /** * Deletes a row and all its contents. *

* Rows below the given row are shifted up. */ public void deleteRow(int row) { if (this.rowsChanged_ != null) { this.rowsChanged_.remove(this.rows_.get(row)); if (this.rowsChanged_.isEmpty()) { ; this.rowsChanged_ = null; } } for (int i = 0; i < this.getColumnCount(); ++i) { WTableCell cell = this.rows_.get(row).cells_.get(i).cell; if (cell != null) cell.remove(); } if (row >= (int) (this.getRowCount() - this.rowsAdded_)) { --this.rowsAdded_; } else { this.flags_.set(BIT_GRID_CHANGED); this.repaint(EnumSet.of(RepaintFlag.RepaintInnerHtml)); } ; this.rows_.remove(0 + row); } /** * Inserts an empty column. */ public WTableColumn insertColumn(int column) { for (int i = 0; i < this.rows_.size(); ++i) { this.rows_.get(i).insertColumn(column); } WTableColumn tableColumn = null; if ((int) column <= this.columns_.size()) { tableColumn = new WTableColumn(this); this.columns_.add(0 + column, tableColumn); } this.flags_.set(BIT_GRID_CHANGED); this.repaint(EnumSet.of(RepaintFlag.RepaintInnerHtml)); return tableColumn; } /** * Delete a column and all its contents. */ public void deleteColumn(int column) { for (int i = 0; i < this.getRowCount(); ++i) { this.rows_.get(i).deleteColumn(column); } if ((int) column <= this.columns_.size()) { ; this.columns_.remove(0 + column); } this.flags_.set(BIT_GRID_CHANGED); this.repaint(EnumSet.of(RepaintFlag.RepaintInnerHtml)); } /** * Clears the entire table. *

* This method clears the entire table: all cells and their contents are * deleted. */ public void clear() { while (this.getRowCount() > 0) { this.deleteRow(this.getRowCount() - 1); } while (this.getColumnCount() > 0) { this.deleteColumn(this.getColumnCount() - 1); } } /** * Returns the number of rows in the table. */ public int getRowCount() { return this.rows_.size(); } /** * Returns the number of columns in the table. */ public int getColumnCount() { return this.columns_.size(); } /** * Sets the number of header rows or columns. *

* The default values are 0. *

*

* Note: This must be set before the initial rendering and cannot * be changed later. *

*/ public void setHeaderCount(int count, Orientation orientation) { if (orientation == Orientation.Horizontal) { this.headerRowCount_ = count; } else { this.headerColumnCount_ = count; } } /** * Sets the number of header rows or columns. *

* Calls {@link #setHeaderCount(int count, Orientation orientation) * setHeaderCount(count, Orientation.Horizontal)} */ public final void setHeaderCount(int count) { setHeaderCount(count, Orientation.Horizontal); } /** * Returns the number of header rows or columns. *

* * @see WTable#setHeaderCount(int count, Orientation orientation) */ public int getHeaderCount(Orientation orientation) { if (orientation == Orientation.Horizontal) { return this.headerRowCount_; } else { return this.headerColumnCount_; } } /** * Returns the number of header rows or columns. *

* Returns {@link #getHeaderCount(Orientation orientation) * getHeaderCount(Orientation.Horizontal)} */ public final int getHeaderCount() { return getHeaderCount(Orientation.Horizontal); } /** * Move a table row from its original position to a new position. *

* The table expands automatically when the to row is beyond * the current table dimensions. *

* * @see WTable#moveColumn(int from, int to) */ public void moveRow(int from, int to) { if (from < 0 || from >= (int) this.rows_.size()) { logger.error(new StringWriter().append( "moveRow: the from index is not a valid row index.") .toString()); return; } WTableRow from_tr = this.getRowAt(from); this.rows_.remove(from_tr); if (to > (int) this.rows_.size()) { this.getRowAt(to); } this.rows_.add(0 + to, from_tr); this.flags_.set(BIT_GRID_CHANGED); this.repaint(EnumSet.of(RepaintFlag.RepaintInnerHtml)); } /** * Move a table column from its original position to a new position. *

* The table expands automatically when the to column is beyond * the current table dimensions. *

* * @see WTable#moveRow(int from, int to) */ public void moveColumn(int from, int to) { if (from < 0 || from >= (int) this.columns_.size()) { logger.error(new StringWriter().append( "moveColumn: the from index is not a valid column index.") .toString()); return; } WTableColumn from_tc = this.getColumnAt(from); this.columns_.remove(from_tc); if (to > (int) this.columns_.size()) { this.getColumnAt(to); } this.columns_.add(0 + to, from_tc); for (int i = 0; i < this.rows_.size(); i++) { List cells = this.rows_.get(i).cells_; WTableRow.TableData cell = cells.get(from); cells.remove(0 + from); cells.add(0 + to, cell); } this.flags_.set(BIT_GRID_CHANGED); this.repaint(EnumSet.of(RepaintFlag.RepaintInnerHtml)); } static final int BIT_GRID_CHANGED = 0; private static final int BIT_COLUMNS_CHANGED = 1; BitSet flags_; List rows_; List columns_; private Set rowsChanged_; private int rowsAdded_; private int headerRowCount_; private int headerColumnCount_; void expand(int row, int column, int rowSpan, int columnSpan) { int newNumRows = row + rowSpan; int curNumColumns = this.getColumnCount(); int newNumColumns = Math.max(curNumColumns, column + columnSpan); if (newNumRows > this.getRowCount() || newNumColumns > curNumColumns) { if (newNumColumns == curNumColumns && this.getRowCount() >= this.headerRowCount_) { this.rowsAdded_ += newNumRows - this.getRowCount(); } else { this.flags_.set(BIT_GRID_CHANGED); } this.repaint(EnumSet.of(RepaintFlag.RepaintInnerHtml)); for (int r = this.getRowCount(); r < newNumRows; ++r) { this.rows_.add(new WTableRow(this, newNumColumns)); } if (newNumColumns > curNumColumns) { for (int r = 0; r < this.getRowCount(); ++r) { WTableRow tr = this.rows_.get(r); tr.expand(newNumColumns); } for (int c = curNumColumns; c <= column; ++c) { this.columns_.add(new WTableColumn(this)); } } } } private WTableRow.TableData itemAt(int row, int column) { return this.rows_.get(row).cells_.get(column); } void repaintRow(WTableRow row) { if (row.getRowNum() >= (int) (this.getRowCount() - this.rowsAdded_)) { return; } if (!(this.rowsChanged_ != null)) { this.rowsChanged_ = new HashSet(); } this.rowsChanged_.add(row); this.repaint(EnumSet.of(RepaintFlag.RepaintInnerHtml)); } void repaintColumn(WTableColumn column) { this.flags_.set(BIT_COLUMNS_CHANGED); this.repaint(EnumSet.of(RepaintFlag.RepaintInnerHtml)); } void updateDom(DomElement element, boolean all) { super.updateDom(element, all); } DomElementType getDomElementType() { return DomElementType.DomElement_TABLE; } DomElement createDomElement(WApplication app) { boolean withIds = !app.getEnvironment().agentIsSpiderBot(); DomElement table = DomElement.createNew(this.getDomElementType()); this.setId(table, app); DomElement thead = null; if (this.headerRowCount_ != 0) { thead = DomElement.createNew(DomElementType.DomElement_THEAD); if (withIds) { thead.setId(this.getId() + "th"); } } DomElement tbody = DomElement .createNew(DomElementType.DomElement_TBODY); if (withIds) { tbody.setId(this.getId() + "tb"); } for (int col = 0; col < this.columns_.size(); ++col) { DomElement c = DomElement.createNew(DomElementType.DomElement_COL); if (withIds) { c.setId(this.columns_.get(col).getId()); } this.columns_.get(col).updateDom(c, true); table.addChild(c); } this.flags_.clear(BIT_COLUMNS_CHANGED); for (int row = 0; row < (int) this.getRowCount(); ++row) { for (int col = 0; col < (int) this.getColumnCount(); ++col) { this.itemAt(row, col).overSpanned = false; } } for (int row = 0; row < (int) this.getRowCount(); ++row) { DomElement tr = this.createRow(row, withIds, app); if (row < (int) this.headerRowCount_) { thead.addChild(tr); } else { tbody.addChild(tr); } } this.rowsAdded_ = 0; if (thead != null) { table.addChild(thead); } table.addChild(tbody); this.updateDom(table, true); this.flags_.clear(BIT_GRID_CHANGED); ; this.rowsChanged_ = null; return table; } void getDomChanges(List result, WApplication app) { DomElement e = DomElement.getForUpdate(this, this.getDomElementType()); if (!this.isStubbed() && this.flags_.get(BIT_GRID_CHANGED)) { DomElement newE = this.createDomElement(app); e.replaceWith(newE); } else { if (this.rowsChanged_ != null) { for (Iterator i_it = this.rowsChanged_.iterator(); i_it .hasNext();) { WTableRow i = i_it.next(); DomElement e2 = DomElement.getForUpdate(i, DomElementType.DomElement_TR); i.updateDom(e2, false); result.add(e2); } ; this.rowsChanged_ = null; } if (this.rowsAdded_ != 0) { DomElement etb = DomElement.getForUpdate(this.getId() + "tb", DomElementType.DomElement_TBODY); for (int i = 0; i < (int) this.rowsAdded_; ++i) { DomElement tr = this.createRow(this.getRowCount() - this.rowsAdded_ + i, true, app); etb.addChild(tr); } result.add(etb); this.rowsAdded_ = 0; } if (this.flags_.get(BIT_COLUMNS_CHANGED)) { for (int i = 0; i < this.columns_.size(); ++i) { DomElement e2 = DomElement.getForUpdate(this.columns_ .get(i), DomElementType.DomElement_COL); this.columns_.get(i).updateDom(e2, false); result.add(e2); } this.flags_.clear(BIT_COLUMNS_CHANGED); } this.updateDom(e, false); } result.add(e); } void propagateRenderOk(boolean deep) { this.flags_.clear(); if (this.rowsChanged_ != null) { ; this.rowsChanged_ = null; } this.rowsAdded_ = 0; super.propagateRenderOk(deep); } private DomElement createRow(int row, boolean withIds, WApplication app) { DomElement tr = DomElement.createNew(DomElementType.DomElement_TR); if (withIds) { tr.setId(this.rows_.get(row).getId()); } this.rows_.get(row).updateDom(tr, true); tr.setWasEmpty(false); int spanCounter = 0; for (int col = 0; col < this.getColumnCount(); ++col) { WTableRow.TableData d = this.itemAt(row, col); if (!d.overSpanned) { DomElement td = d.cell.createSDomElement(app); if (col < this.headerColumnCount_ || row < this.headerRowCount_) { tr.addChild(td); } else { tr.insertChildAt(td, col - spanCounter); } for (int i = 0; i < d.cell.getRowSpan(); ++i) { for (int j = 0; j < d.cell.getColumnSpan(); ++j) { if (i + j > 0) { this.itemAt(row + i, col + j).overSpanned = true; this.itemAt(row + i, col + j).cell .setRendered(false); } } } } else { spanCounter++; } } return tr; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy