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

org.karora.cooee.ng.TableEx Maven / Gradle / Ivy

Go to download

Cooee is a Web UI framework that closely follows the Swing API without the hassle of Javascript. This means that developers with little to no web application experience can immediately begin coding web applications with their existing Swing API knowledge. The code base represents a combined fork of the Echo2 source code and associated projects

The newest version!
/* 
 * This file is part of the Echo Point Project.  This project is a collection
 * of Components that have extended the Echo Web Application Framework.
 *
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 */
package org.karora.cooee.ng;

import java.io.Serializable;
import java.util.BitSet;
import java.util.EventListener;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.karora.cooee.app.Color;
import org.karora.cooee.app.Component;
import org.karora.cooee.app.Extent;
import org.karora.cooee.app.LayoutData;
import org.karora.cooee.app.Style;
import org.karora.cooee.app.Table;
import org.karora.cooee.app.event.ActionListener;
import org.karora.cooee.app.list.ListSelectionModel;
import org.karora.cooee.app.table.DefaultTableModel;
import org.karora.cooee.app.table.TableCellRenderer;
import org.karora.cooee.app.table.TableColumn;
import org.karora.cooee.app.table.TableColumnModel;
import org.karora.cooee.app.table.TableModel;
import org.karora.cooee.ng.able.Attributeable;
import org.karora.cooee.ng.able.Borderable;
import org.karora.cooee.ng.able.Stretchable;
import org.karora.cooee.ng.command.AttributesAdd;
import org.karora.cooee.ng.layout.TableLayoutDataEx;
import org.karora.cooee.ng.table.PageableTableModel;
import org.karora.cooee.ng.table.TableActionEventEx;
import org.karora.cooee.ng.table.TableColumnEx;
import org.karora.cooee.ng.util.ColorKit;
import org.karora.cooee.ng.util.TokenizerKit;
import org.karora.cooee.ng.xhtml.XhtmlFragment;

import org.karora.cooee.ng.list.ListSelectionModelEx;
import org.karora.cooee.ng.table.DefaultTableCellRendererEx;
import org.karora.cooee.ng.table.TableCellRendererEx;

/**
 * TableEx is an implementation of Table thats
 * adds support for light weight table cells and column and row spanning of
 * cells. This is achieved by supporting the TableCellRendererEx
 * interface, the TableLayoutDataEx layout data and the
 * XhtmlFragment object for specifying cell content.
 * 
 * @see org.karora.cooee.ng.table.TableCellRendererEx
 * @see org.karora.cooee.ng.layout.TableLayoutDataEx
 * @see org.karora.cooee.ng.xhtml.XhtmlFragment
 */
public class TableEx extends Table implements Attributeable, Stretchable {

	/**
	 * CellMatrix is used to hold the content for a given sized
	 * set of cells.
	 * 

* The index of the cell matrix is 0,0 to (rowCount,cellCount) unless there * is a isHeaderVisible in which case it is 0,-1 to ((rowCount*cellCount) * */ protected class CellMatrix implements Serializable { private Map cellContentMap; private Object cellSpanObject; private int columnCount; private int rowCount; private Map propertyMap; /** * Constructs a CellMatrix * * @param columnCount - * the maximum number of columns * @param rowCount - * the maximum number of rows * @param cellSpanObject - * the object to be stored in a cell if its is spanned via * rowCount and colSpan values. */ public CellMatrix(int columnCount, int rowCount, Object cellSpanObject) { super(); this.rowCount = rowCount; this.columnCount = columnCount; this.cellSpanObject = cellSpanObject; int cellCount = rowCount * columnCount; cellCount += (isHeaderVisible() ? columnCount : 0); cellContentMap = new HashMap(cellCount); } /** * Returns true if the specified value is part of the content in this * CellMatrix * * @param value - * what the check for * @return true if the specified value is part of the content in this * CellMatrix */ public boolean containsCellContent(Object value) { for (Iterator iter = cellContentMap.entrySet().iterator(); iter.hasNext();) { Entry entry = (Entry) iter.next(); if (entry.getValue() == value || entry.getValue().equals(value)) { return true; } } return false; } /** * Returns the cell content at the specified column and row co-ordinate. * * @param column * @param row * @return the cell content at the specified column and row co-ordinate. * @throws IllegalArgumentException * if the specified column and row co-ordinate is outside * the bounds of the CellMatrix. */ public Object getCellContent(int column, int row) { validateCoordinate(column, row); String key = getColRowKey(column, row); Object content = cellContentMap.get(key); return content; } /** * @return Returns the cellSpanObject in use */ public Object getCellSpanObject() { return cellSpanObject; } /** * @return a key by col/row */ private String getColRowKey(int column, int row) { StringBuffer sb = new StringBuffer("col:"); sb.append(column); sb.append("row:"); sb.append(row); return sb.toString(); } /** * @return Returns the columnCount. */ public int getColumnCount() { return columnCount; } /** * @return Returns the rowCount. */ public int getRowCount() { return rowCount; } /** * Sets the content of the cells at the specified column/row * co-ordinate. * * @param value - * the content value to be placed in the cell * @param column - * the column index * @param row - * the row index * @throws IllegalArgumentException * if the specified column and row co-ordinate is outside * the bounds of the CellMatrix. */ public void setCellContent(Object value, int column, int row) { setCellContent(value, column, row, 0, 0); } /** * Sets the content of the cells at the specified column/row * co-ordinate. The column span and row span can be specified as well. * If this is greater then 1, then cells at the appropriate spanned cell * co-ordinates are set the cellSpanObject. * * @param value - * the content value to be placed in the cell * @param column - * the column index * @param row - * the row index * @param colSpan - * the column span * @param rowSpan - * the row span * @throws IllegalArgumentException * if the specified column and row co-ordinate is outside * the bounds of the CellMatrix. */ public void setCellContent(Object value, int column, int row, int colSpan, int rowSpan) { validateCoordinate(column, row); String key = getColRowKey(column, row); cellContentMap.put(key, value); // handle col and row span by setting the content of the // cells that are skipped with the cellSpanObject if (rowSpan > 1 || colSpan > 1) { int maxRows = row; if (rowSpan > 1) { maxRows = Math.min(row + (rowSpan - 1), rowCount - 1); } int maxColumns = column; for (int rowIndex = row; rowIndex <= maxRows; rowIndex++) { if (colSpan > 1) { maxColumns = Math.min(column + (colSpan - 1), columnCount - 1); for (int columnIndex = column; columnIndex <= maxColumns; columnIndex++) { // protected against setting the current cell if (rowIndex == row && columnIndex == column) { continue; } setCellContent(cellSpanObject, columnIndex, rowIndex); } } // protected against setting the current cell if (rowIndex == row) { continue; } setCellContent(cellSpanObject, column, rowIndex); } } } /** * Called to set specific property information for a cell. * * @param column - * the column of the cell * @param row - * the row of the cell * @param propertyName - * the property name * @param value - * a value for that property at that cell */ public void setCellProperties(int column, int row, String propertyName, Object value) { if (propertyMap == null) { propertyMap = new HashMap(); } String key = makePropertyMapKey(column, row, propertyName); propertyMap.put(key, value); } /** * */ public Object getCellProperties(int column, int row, String propertyName) { if (propertyMap == null) { return null; } String key = makePropertyMapKey(column, row, propertyName); return propertyMap.get(key); } private String makePropertyMapKey(int column, int row, String propertyName) { String key = "r:" + row + "c:" + column + "pn:" + propertyName; return key; } private void validateCoordinate(int column, int row) { if (column < 0) { throw new IllegalArgumentException("The column index [" + column + "] is less than zero"); } if (column > columnCount) { throw new IllegalArgumentException("The column index [" + column + "] is greater than columnCount [" + columnCount + "]"); } if (row > rowCount) { throw new IllegalArgumentException("The row index [" + row + "] is greater than rowCount [" + rowCount + "]"); } int minRowIndex = 0; if (isHeaderVisible()) { minRowIndex = -1; } if (isFooterVisible()) { minRowIndex = -2; } if (row < minRowIndex) { throw new IllegalArgumentException("The row index [" + row + "] is less than the minimum allowed [" + minRowIndex + "]"); } } } /** * Inidicates that the row index of the footer row. */ public static final int FOOTER_ROW = -2; /** * This object is used to indicate cell content that is currently spanned * (and hence has no content). */ public static final Serializable CELL_SPANNER = new Serializable() {}; public static final Style DEFAULT_STYLE; static { MutableStyleEx style = new MutableStyleEx(); style.setProperty(PROPERTY_SELECTION_BACKGROUND, Color.YELLOW); style.setProperty(Borderable.PROPERTY_BORDER, BorderEx.DEFAULT); style.setProperty(PROPERTY_ROLLOVER_ENABLED, true); style.setProperty(PROPERTY_ROLLOVER_BACKGROUND, ColorKit.makeColor("#DEF3FF")); DEFAULT_STYLE = style; } /** * The default renderer for table cells for TableEx is a * DefaultTableCellRendererEx, this will be used as the last * resort when no TableColumns / Table Column Class and TableEx instances * have a cell renderer in play. */ public static final TableCellRendererEx DEFAULT_TABLE_CELL_RENDERER = new DefaultTableCellRendererEx(); public static final String PROPERTY_HEADER_BACKGROUND = "headerBackground"; public static final String PROPERTY_FOOTER_BACKGROUND = "footerBackground"; public static final String PROPERTY_FOOTER_VISIBLE = "footerVisible"; public static final String PROPERTY_HEIGHT = "height"; public static final String PROPERTY_IGNORE_META_KEYS = "ignoreMetaKeys"; public static final String PROPERTY_RESIZE_DRAG_BAR_USED = "resizeDragBarUsed"; public static final String PROPERTY_RESIZE_GROWS_TABLE = "resizeGrowsTable"; public static final String PROPERTY_RESIZEABLE = "resizeable"; public static final String PROPERTY_SCROLLABLE = "scrollable"; public static final String COLUMN_WIDTHS_CHANGED_PROPERTY = "columnWidthsChanged"; public static final String DEFAULT_FOOTER_RENDERER_CHANGED_PROPERTY = "defaultFooterRenderer"; private Map attributeMap; private TableCellRenderer defaultFooterRenderer; private TableCellRenderer defaultRenderer; /** * Tracks the content for the cells of the TableEx */ protected CellMatrix cellMatrix; /** * A boolean flag indicating whether the TableEx is valid or * not. */ protected boolean valid; /** * A boolean flag indicating whether the TableEx has a * visible footer or not */ protected boolean footerVisible; /** * Creates a new TableEx with an empty * DefaultTableModel. */ public TableEx() { this(new DefaultTableModel()); } /** * Creates a new TableEx with a new * DefaultTableModel with the specified dimensions. * * @param columns * the initial column count * @param rows * the initial row count */ public TableEx(int columns, int rows) { this(new DefaultTableModel(columns, rows)); } /** * Creates a TableEx using the supplied * TableModel. * * @param model * the initial model */ public TableEx(TableModel model) { this(model, null); } /** * Creates a TableEx with the supplied * TableModel and the specified TableColumnModel. * * @param model * the initial model * @param columnModel * the initial column model */ public TableEx(TableModel model, TableColumnModel columnModel) { super(model, columnModel); defaultRenderer = DEFAULT_TABLE_CELL_RENDERER; setFocusTraversalParticipant(false); } /** * @see org.karora.cooee.app.Table#processInput(java.lang.String, * java.lang.Object) */ public void processInput(String inputName, Object inputValue) { if (inputName.equals(SELECTION_CHANGED_PROPERTY)) { // are we a special case for selection if (getModel() instanceof PageableTableModel || (getSelectionModel() instanceof ListSelectionModelEx)) { setPageableSelectionEx((int[]) inputValue); } else { super.processInput(inputName, inputValue); } } if (INPUT_ACTION.equals(inputName)) { String value = String.valueOf(inputValue); String values[] = TokenizerKit.tokenize(value, ";", false); int metaKeyInfo = 0; int row = -1; int column = -1; for (int i = 0; i < values.length; i++) { if (values[i].startsWith("c:")) { column = Integer.parseInt(values[i].substring(2)); } if (values[i].startsWith("r:")) { row = Integer.parseInt(values[i].substring(2)); } if (values[i].startsWith("mk:")) { metaKeyInfo = Integer.parseInt(values[i].substring(3)); } } fireActionEvent(metaKeyInfo, column, row); } if (inputName.equals(COLUMN_WIDTHS_CHANGED_PROPERTY)) { int columnWidths[] = (int[]) inputValue; TableColumnModel columnModel = this.getColumnModel(); if (columnModel != null) { for (int i = 0; i < columnWidths.length; i++) { TableColumn tableColumn = columnModel.getColumn(i); if (tableColumn != null) { tableColumn.setWidth(new ExtentEx(columnWidths[i])); } } } } } /** * Selects only the specified row indices in response to a * selection data from the client but only for pageable tables. * * @param selectedIndices the indices to select */ protected void setPageableSelectionEx(int[] selectedIndices) { /* * If the TableModel is a PagedTableModel then we dont want to clear the selection * on other pages here. They are not visible to the user but they are still valid * So we only "clear" the selections on the page that is visible. */ BitSet incomingSelections = new BitSet(); for (int i = 0; i < selectedIndices.length; i++) { incomingSelections.set(selectedIndices[i]); } ListSelectionModel selectionModel = getSelectionModel(); if (selectionModel.getMaxSelectedIndex() != -1) { if (getModel() instanceof PageableTableModel) { // just a pages worth of data please int rowCount = getModel().getRowCount(); for (int row = 0; row < rowCount; row++) { if (selectionModel.isSelectedIndex(row)) { // if its in our incoming selection then dont clear it if (! incomingSelections.get(row)) { selectionModel.setSelectedIndex(row, false); } } } } else { // just clear it directly as it more efficient selectionModel.clearSelection(); } } /* * Now do the selection. If we can do it in one step then great. */ if (selectionModel instanceof ListSelectionModelEx) { ListSelectionModelEx listSelectionModelEx = (ListSelectionModelEx) selectionModel; listSelectionModelEx.setSelectedIndices(selectedIndices,true); } else { for (int i = 0; i < selectedIndices.length; ++i) { selectionModel.setSelectedIndex(selectedIndices[i], true); } } firePropertyChange(SELECTION_CHANGED_PROPERTY, null, selectedIndices); } /** * Fires an action event to all listeners. */ protected void fireActionEvent(int metaKeyInfo, int column, int row) { if (!hasEventListenerList()) { return; } EventListener[] listeners = getEventListenerList().getListeners(ActionListener.class); TableActionEventEx e = null; for (int i = 0; i < listeners.length; ++i) { if (e == null) { e = new TableActionEventEx(this, (String) getRenderProperty(PROPERTY_ACTION_COMMAND), metaKeyInfo, column, row); } ((ActionListener) listeners[i]).actionPerformed(e); } } /** * Re-renders the rows of the TableEx. */ protected void doRender() { TableModel model = getModel(); TableColumnModel columnModel = getColumnModel(); TableCellRenderer defaultHeaderRenderer = getDefaultHeaderRenderer(); TableCellRenderer defaultFooterRenderer = getDefaultFooterRenderer(); TableCellRenderer defaultRenderer = getDefaultRenderer(); defaultRenderer = (defaultRenderer == null ? DEFAULT_TABLE_CELL_RENDERER : defaultRenderer); int rowCount = model.getRowCount(); int columnCount = columnModel.getColumnCount(); boolean isHeaderVisible = isHeaderVisible(); boolean isFooterVisible = isFooterVisible(); Map encounteredComponentMap = new HashMap(); cellMatrix = new CellMatrix(columnCount, rowCount, TableEx.CELL_SPANNER); TableColumn[] tableColumns = new TableColumn[columnCount]; TableCellRenderer[] columnRenderers = new TableCellRenderer[columnCount]; for (int columnIndex = 0; columnIndex < columnCount; ++columnIndex) { tableColumns[columnIndex] = columnModel.getColumn(columnIndex); TableCellRenderer renderer = tableColumns[columnIndex].getCellRenderer(); if (renderer == null) { Class columnClass = model.getColumnClass(tableColumns[columnIndex].getModelIndex()); renderer = getDefaultRenderer(columnClass); if (renderer == null) { renderer = defaultRenderer; } } columnRenderers[columnIndex] = renderer; } if (isHeaderVisible) { for (int columnIndex = 0; columnIndex < columnCount; ++columnIndex) { int modelColumnIndex = tableColumns[columnIndex].getModelIndex(); Object headerValue = tableColumns[columnIndex].getHeaderValue(); if (headerValue == null) { headerValue = model.getColumnName(modelColumnIndex); } TableCellRenderer headerRenderer = tableColumns[columnIndex].getHeaderRenderer(); if (headerRenderer == null) { headerRenderer = defaultHeaderRenderer; if (headerRenderer == null) { headerRenderer = defaultRenderer; } } // // get header cell data Component renderedComponent = doRenderCellContent(headerRenderer, headerValue, modelColumnIndex, HEADER_ROW); if (renderedComponent != null) { encounteredComponentMap.put(renderedComponent, renderedComponent); } } } if (isFooterVisible) { for (int columnIndex = 0; columnIndex < columnCount; ++columnIndex) { TableColumn tableColumn = tableColumns[columnIndex]; int modelColumnIndex = tableColumn.getModelIndex(); Object footerValue = null; if (tableColumn instanceof TableColumnEx) { footerValue = ((TableColumnEx) tableColumn).getFooterValue(); } if (footerValue == null) { footerValue = model.getColumnName(modelColumnIndex); } TableCellRenderer footerRenderer = null; if (tableColumn instanceof TableColumnEx) { footerRenderer = ((TableColumnEx) tableColumn).getFooterRenderer(); } if (footerRenderer == null) { footerRenderer = defaultFooterRenderer; if (footerRenderer == null) { footerRenderer = defaultRenderer; } } // // get header cell data Component renderedComponent = doRenderCellContent(footerRenderer, footerValue, modelColumnIndex, FOOTER_ROW); if (renderedComponent != null) { encounteredComponentMap.put(renderedComponent, renderedComponent); } } } // // data cells next for (int rowIndex = 0; rowIndex < rowCount; ++rowIndex) { for (int columnIndex = 0; columnIndex < columnCount; ++columnIndex) { int modelColumnIndex = tableColumns[columnIndex].getModelIndex(); Object modelValue = model.getValueAt(modelColumnIndex, rowIndex); TableCellRenderer cellRenderer = columnRenderers[columnIndex]; Component renderedComponent = doRenderCellContent(cellRenderer, modelValue, modelColumnIndex, rowIndex); if (renderedComponent != null) { encounteredComponentMap.put(renderedComponent, renderedComponent); } } } // fix up our children that are no longer cells Component[] children = getComponents(); for (int i = 0; i < children.length; i++) { Component child = children[i]; if (!encounteredComponentMap.containsKey(child)) { this.remove(child); } } // we need to fire an event to make sure we have some sort of change to // make the TableEx re-paint. Children changing would do it but we cant // gaurantee that children will change because they might be xhtml // fragments. firePropertyChange("repaint", null, model); } /** * Renders the content of a cell, given a specific * TableCellRenderer. The internal CellMatrix * should be filled with the content in this method. Also it must be careful * to respect cell span parameters that might be in * TableLayoutDataEx. * * @param cellRenderer - * the TableCellRenderer in plat * @param modelValue - * the value from the TableModel * @param column - * the columnin play * @param row - * the row in play * @return the Component returned as cell content or null if its not a * Component to be used as cell content */ protected Component doRenderCellContent(TableCellRenderer cellRenderer, Object modelValue, int column, int row) { if (cellMatrix.getCellContent(column, row) != null) { // too bad we already have content in there. It must have been // col/row spanned return null; } Object content = null; int rowSpan = 0; int colSpan = 0; TableLayoutDataEx layoutDataEx = null; Component renderedComponent = cellRenderer.getTableCellRendererComponent(this, modelValue, column, row); if (renderedComponent == null) { if (cellRenderer instanceof TableCellRendererEx) { TableCellRendererEx cellRendererEx = (TableCellRendererEx) cellRenderer; XhtmlFragment fragment = cellRendererEx.getTableCellRendererContent(this, modelValue, column, row); content = fragment; if (fragment != null) { LayoutData layoutData = fragment.getLayoutData(); if (layoutData instanceof TableLayoutDataEx) { layoutDataEx = (TableLayoutDataEx) layoutData; } } boolean isActionCausing = cellRendererEx.isActionCausingCell(this, column, row); boolean isSelectionCausing = cellRendererEx.isSelectionCausingCell(this, column, row); // // we save on memory by only putting in a property value when // the cell is NOT action causing // or selection causing. The default is that they are action // causing. if (!isActionCausing) { cellMatrix.setCellProperties(column, row, "actionCausing", new Boolean(false)); } if (!isSelectionCausing) { cellMatrix.setCellProperties(column, row, "selectionCausing", new Boolean(false)); } } else { // we could do what the old table used to do to be backwards // compat // but its more expensive memory wise so we wont because it // gives us // nil benefit. // // renderedComponent = new Label(); content = null; } } else if (renderedComponent != null) { if (!this.isAncestorOf(renderedComponent)) { add(renderedComponent); } LayoutData layoutData = (LayoutData) renderedComponent.getRenderProperty(Component.PROPERTY_LAYOUT_DATA); if (layoutData instanceof TableLayoutDataEx) { layoutDataEx = (TableLayoutDataEx) layoutData; } content = renderedComponent; } else { content = null; } if (layoutDataEx != null) { colSpan = layoutDataEx.getColSpan(); rowSpan = layoutDataEx.getRowSpan(); } cellMatrix.setCellContent(content, column, row, colSpan, rowSpan); return renderedComponent; } /** * @see org.karora.cooee.ng.able.Attributeable#getAttribute(java.lang.String) */ public Object getAttribute(String attributeName) { if (attributeMap != null) { return attributeMap.get(attributeName); } return null; } /** * @see org.karora.cooee.ng.able.Attributeable#getAttributeNames() */ public String[] getAttributeNames() { if (attributeMap == null) { return new String[0]; } int count = 0; String[] attributeNames = new String[attributeMap.keySet().size()]; for (Iterator iter = attributeMap.keySet().iterator(); iter.hasNext();) { attributeNames[count++] = (String) iter.next(); } return attributeNames; } /** * Returns the Component at a specified cell co-ordinate. * * @throws IllegalArgumentException * if the specified column and row co-ordinate is outside the * bounds of the TableModel. * * @see org.karora.cooee.app.Table#getCellComponent(int, int) */ public Component getCellComponent(int column, int row) { Object value = getCellContent(column, row); if (value instanceof Component) { return (Component) value; } return null; } /** * Returns the cell content rendered at the specified cell position. This * can be a Component, TableEx.CELL_SPANNER, XhtmlFragment or * a null value indicating that the cell has no content (but * is still to be shown). * * @param column * the column * @param row * the row * @return the content or null if there is no content there * @throws IllegalArgumentException * if the specified column and row co-ordinate is outside the * bounds of the TableModel (including header). */ public Object getCellContent(int column, int row) { if (!valid) { validate(); } if (cellMatrix != null) { return cellMatrix.getCellContent(column, row); } return null; } /** * This method is intended to be called by the TableEx rendering peer. * * It returns true if the specified cell is an action causing cell, as * specified by a TableCellRendererEx. * * @param column - * the column in question * @param row - * the row in question * @return true if it can cause an action to be raise when clicked. */ public boolean isActionCausingCell(int column, int row) { if (cellMatrix == null) { return true; } Object value = cellMatrix.getCellProperties(column, row, "actionCausing"); return (value == null ? true : false); } /** * This method is intended to be called by the TableEx rendering peer. * * It returns true if the specified cell is an selection causing cell, as * specified by a TableCellRendererEx. * * @param column - * the column in question * @param row - * the row in question * @return true if it can cause an action to be raise when clicked. */ public boolean isSelectionCausingCell(int column, int row) { if (cellMatrix == null) { return true; } Object value = cellMatrix.getCellProperties(column, row, "selectionCausing"); return (value == null ? true : false); } /** * * @return the color to be used as the header background */ public Color getHeaderBackground() { return (Color) getProperty(PROPERTY_HEADER_BACKGROUND); } /** * * @return the color to be used as the footer background */ public Color getFooterBackground() { return (Color) getProperty(PROPERTY_FOOTER_BACKGROUND); } /** * Returns the height of the TableEx. * * @return the height of the TableEx */ public Extent getHeight() { return (Extent) getProperty(PROPERTY_HEIGHT); } /** * @see org.karora.cooee.app.Component#init() */ public void init() { // we implement Attributeable via a Command so we dont need peers // that are not owned by EPNG. super.init(); getApplicationInstance().enqueueCommand(new AttributesAdd(this, this)); } /** * @see org.karora.cooee.app.Table#invalidate() */ protected void invalidate() { valid = false; } /** * Determines if the table footer is visible. * * @return the footer visibility state */ public boolean isFooterVisible() { return ComponentEx.getProperty(this, PROPERTY_FOOTER_VISIBLE, false); } /** * Determines if meta keys are ignored during selection * * @return true if if meta keys are ignored during selection * @see TableEx#setIgnoreMetaKeys(boolean) */ public boolean isIgnoreMetaKeys() { return ComponentEx.getProperty(this, PROPERTY_IGNORE_META_KEYS, false); } /** * @return true if the TableEx is resizeable */ public boolean isResizeable() { return ComponentEx.getProperty(this, PROPERTY_RESIZEABLE, false); } /** * @return true if a visual bar artefact is used to when resizing columns */ public boolean isResizeDragBarUsed() { return ComponentEx.getProperty(this, PROPERTY_RESIZE_DRAG_BAR_USED, false); } /** * @return true if a resize operations is allowed to grow the table. */ public boolean isResizeGrowsTable() { return ComponentEx.getProperty(this, PROPERTY_RESIZE_GROWS_TABLE, true); } /** * @return - true if the TableEx is scrollable */ public boolean isScrollable() { return ComponentEx.getProperty(this, PROPERTY_SCROLLABLE, false); } /** * @see org.karora.cooee.ng.able.Attributeable#setAttribute(java.lang.String, * java.lang.Object) */ public void setAttribute(String attributeName, Object attributeValue) { if (attributeMap == null) { attributeMap = new HashMap(); } attributeMap.put(attributeName, attributeValue); } /** * Sets the color to be used as the header background * * @param newValue - * the color to be used as the header background */ public void setHeaderBackground(Color newValue) { setProperty(PROPERTY_HEADER_BACKGROUND, newValue); } /** * Sets the color to be used as the footer background * * @param newValue - * the color to be used as the footer background */ public void setFooterBackground(Color newValue) { setProperty(PROPERTY_FOOTER_BACKGROUND, newValue); } /** * Sets the height of the TableEx. * * @param newValue - * the new height value */ public void setHeight(Extent newValue) { setProperty(PROPERTY_HEIGHT, newValue); } /** * Controls whether the TableEx columns are resizeable. Other * properties resizeDragBarUsed and * resizeGrowsTable are dependant on resizeable * being set to true. *

* Conversely, scrollable must be true in * order for TableEx columns to be resizeable * * @param newValue - * whether the TableEx is resizeable */ public void setResizeable(boolean newValue) { ComponentEx.setProperty(this, PROPERTY_RESIZEABLE, newValue); } /** * If true, then a visual visual bar artefact is used when resizing columns. * If this is false then the columns themselves are resize in real time. * * @param newValue - * the new boolean value */ public void setResizeDragBarUsed(boolean newValue) { ComponentEx.setProperty(this, PROPERTY_RESIZE_DRAG_BAR_USED, newValue); } /** * If true, then the table content area will grow to accomidate the new * columns widths when they are resized. If false then the content area will * not grow and the column sizes will be restricted to maximum values. * * @param newValue - * the new boolean value */ public void setResizeGrowsTable(boolean newValue) { ComponentEx.setProperty(this, PROPERTY_RESIZE_GROWS_TABLE, newValue); } /** * Controls whether the TableEx is scrollable. Other * properties such as resizeable are dependant on * scrollable being set to true. * * @param newValue - * whether the TableEx is scrollable */ public void setScrollable(boolean newValue) { ComponentEx.setProperty(this, PROPERTY_SCROLLABLE, newValue); } /** * Sets the visibility state of the table footer. * * @param newValue * true if the footer should be displayed */ public void setFooterVisible(boolean newValue) { ComponentEx.setProperty(this, PROPERTY_FOOTER_VISIBLE, newValue); invalidate(); } /** * When the Table selection is in multiple selection mode, then the Table * will use the Control/Shift keys to control how selections are made. If * this flag is set to true, then the meta keys are ignored and clicking on * a table row will create a new selection/deselection. * * @param newValue * true the meta keys are to be ignored */ public void setIgnoreMetaKeys(boolean newValue) { ComponentEx.setProperty(this, PROPERTY_IGNORE_META_KEYS, newValue); } /** * Returns the default TableCellRenderer used to render * footer cells. The default footer renderer will be used in the event that * a TableColumn does not provide a specific footer renderer. * * @return the TableCellRenderer */ public TableCellRenderer getDefaultFooterRenderer() { return defaultFooterRenderer; } /** * Sets the default TableCellRenderer used to render footer * cells. The default footer renderer will be used in the event that a * TableColumn does not provide a specific footer renderer. * * @param newValue * the TableCellRenderer */ public void setDefaultFooterRenderer(TableCellRenderer newValue) { invalidate(); TableCellRenderer oldValue = defaultFooterRenderer; defaultFooterRenderer = newValue; firePropertyChange(DEFAULT_FOOTER_RENDERER_CHANGED_PROPERTY, oldValue, newValue); } public void setDefaultRenderer(TableCellRenderer newValue) { invalidate(); TableCellRenderer oldValue = defaultRenderer; defaultRenderer = newValue; firePropertyChange(DEFAULT_RENDERER_CHANGED_PROPERTY, oldValue, newValue); } /** * @return the default TableCellRenderer that is used after all other * combinations have been exhausted. It will look in the * TableColumns first for a cell renderer, followed by the * getDefaultRenderer(by class) and then finally getDefaultRender(), */ public TableCellRenderer getDefaultRenderer() { return defaultRenderer; } /** * @see org.karora.cooee.app.Table#validate() */ public void validate() { super.validate(); while (!valid) { valid = true; doRender(); } } /** * @see org.karora.cooee.ng.able.Stretchable#getMaximumStretchedHeight() */ public Extent getMaximumStretchedHeight() { return (Extent) getProperty(PROPERTY_MAXIMUM_STRETCHED_HEIGHT); } /** * @see org.karora.cooee.ng.able.Stretchable#getMinimumStretchedHeight() */ public Extent getMinimumStretchedHeight() { return (Extent) getProperty(PROPERTY_MINIMUM_STRETCHED_HEIGHT); } /** * @see org.karora.cooee.ng.able.Stretchable#isHeightStretched() */ public boolean isHeightStretched() { return ComponentEx.getProperty(this, PROPERTY_HEIGHT_STRETCHED, false); } /** * TableEx puts a particular restriction on * Stretchable. It will never stretch the table content to * fill a space bigger than its natural height. So if you have a small set * of rows in a large area, the table will not be "stretched forwards" to * fill the space, unlike a normal Stretchable. * * @see org.karora.cooee.ng.able.Stretchable#setHeightStretched(boolean) */ public void setHeightStretched(boolean newValue) { ComponentEx.setProperty(this, PROPERTY_HEIGHT_STRETCHED, newValue); } /** * @see org.karora.cooee.ng.able.Stretchable#setMaximumStretchedHeight(org.karora.cooee.app.Extent) */ public void setMaximumStretchedHeight(Extent newValue) { Extent.validate(newValue, Extent.PX); setProperty(PROPERTY_MAXIMUM_STRETCHED_HEIGHT, newValue); } /** * @see org.karora.cooee.ng.able.Stretchable#setMinimumStretchedHeight(org.karora.cooee.app.Extent) */ public void setMinimumStretchedHeight(Extent newValue) { Extent.validate(newValue, Extent.PX); setProperty(PROPERTY_MINIMUM_STRETCHED_HEIGHT, newValue); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy