package com.xoetrope.swing.table;
import java.awt.Component;
import java.util.Vector;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
import net.xoetrope.xui.data.XModelHelper;
import net.xoetrope.xui.XProjectManager;
import net.xoetrope.xui.data.XBaseModel;
import net.xoetrope.xui.data.XModel;
import net.xoetrope.xui.data.XModelListener;
/**
* <p>A TableModel which uses an XModel as the storage for an XBaseTable</p>
*
* <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
* the GNU Public License (GPL), please see license.txt for more details. If
* you make commercial use of this software you must purchase a commercial
* license from Xoetrope.</p>
* <p> $Revision: 1.9 $</p>
*/
public class XTableModelAdapter implements TableModel
{
protected XModel model, rootModel;
protected Vector listeners;
protected boolean editable = false;
protected boolean disabledColumns[];
protected Component component;
protected XModelListener modelListener;
public XTableModelAdapter( XModel newModel )
{
this( newModel, null );
}
public XTableModelAdapter( XModel newModel, XModelListener listener )
{
rootModel = XProjectManager.getModel();
modelListener = listener;
model = newModel;
if ( model.getNumChildren() == 0 )
disabledColumns = new boolean[ 0 ];
else
disabledColumns = new boolean[ model.get( 0 ).getNumChildren() ];
listeners = new Vector();
}
public XModel getModel()
{
return model;
}
public void setModelListener( XModelListener listener )
{
modelListener = listener;
}
public void init( XModelListener listener )
{
int numRows = model.getNumChildren();
for ( int i = 0; i < numRows; i++ ) {
XModel rowModel = model.get( i );
addEvents( listener, rowModel, i, -1 );
int numCols = rowModel.getNumChildren();
for ( int iCol = 0; iCol < numCols; iCol++ ) {
XModel cellModel = rowModel.get( iCol );
addEvents( listener, cellModel, i, iCol );
}
}
for ( int i = 0; i < numRows; i++ ) {
XModel rowModel = model.get( i );
initBindings( model, i, -1 );
int numCols = rowModel.getNumChildren();
for ( int iCol = 0; iCol < numCols; iCol++ ) {
XModel cellModel = rowModel.get( iCol );
initBindings( cellModel, i, iCol );
}
}
}
private void initBindings( XModel model, int row, int col )
{
String bindPath = XModelHelper.getAttrib( model, "bind" );
String editor = XModelHelper.getAttrib( model, "editor" );
if ( bindPath != null ) {
if (( editor != null ) && editor.equals( "Combo" )) {
XBaseModel dataModel = ( XBaseModel ) rootModel.get( bindPath );
model.set( dataModel.get( 0 ).get() );
}
}
}
private void addEvents( XModelListener listener, XModel cellModel, int row, int col )
{
String onChange = XModelHelper.getAttrib( cellModel, "onchange" );
if (( onChange != null ) && ( listener != null ) )
cellModel.addModelListener( listener, onChange );
}
/**
* Returns the number of rows in the model. A
* <code>JTable</code> uses this method to determine how many rows it
* should display. This method should be quick, as it
* is called frequently during rendering.
*
* @return the number of rows in the model
* @see #getColumnCount
*/
public int getRowCount()
{
return model.getNumChildren() - 1;
}
/**
* Returns the number of columns in the model. A
* <code>JTable</code> uses this method to determine how many columns it
* should create and display by default.
*
* @return the number of columns in the model
* @see #getRowCount
*/
public int getColumnCount()
{
if ( model.getNumChildren() == 0 )
return 0;
else
return model.get( 0 ).getNumChildren();
}
/**
* Returns the name of the column at <code>columnIndex</code>. This is used
* to initialize the table's column header name. Note: this name does
* not need to be unique; two columns in a table can have the same name.
*
* @param columnIndex the index of the column
* @return the name of the column
*/
public String getColumnName(int columnIndex)
{
return (String)model.get( 0 ).get( columnIndex ).get();
}
/**
* Returns the most specific superclass for all the cell values
* in the column. This is used by the <code>JTable</code> to set up a
* default renderer and editor for the column.
*
* @param columnIndex the index of the column
* @return the common ancestor class of the object values in the model.
*/
public Class getColumnClass(int columnIndex)
{
return String.class;
}
/**
* Returns true if the cell at <code>rowIndex</code> and
* <code>columnIndex</code>
* is editable. Otherwise, <code>setValueAt</code> on the cell will not
* change the value of that cell. The cell is editable if its 'edit' attribute
* is 'true'
*
* @param rowIndex the row whose value to be queried
* @param columnIndex the column whose value to be queried
* @return true if the cell is editable
* @see #setValueAt
*/
public boolean isCellEditable( int rowIndex, int columnIndex )
{
if ( disabledColumns[ columnIndex ] )
return false;
XModel cellModel = model.get( rowIndex + 1 ).get( columnIndex );
String edit = cellModel.getAttribValueAsString( cellModel.getAttribute( "edit" ) );
if (( edit != null ) && edit.equals( "false" ))
return false;
return editable;
}
/**
* Set the editable state of the cell
* @param state the new editable state
*/
public void setCellEditable( boolean state )
{
editable = state;
}
/**
* Set the enabled state of the column
* @param col the column index
* @param enabled the new enabled state
*/
public void setColumnEnabled( int col, boolean enabled )
{
if ( disabledColumns.length > col )
disabledColumns[ col ] = !enabled;
}
/**
* Returns the value for the cell at <code>columnIndex</code> and
* <code>rowIndex</code>.
*
* @param rowIndex the row whose value is to be queried
* @param columnIndex the column whose value is to be queried
* @return the value Object at the specified cell
*/
public Object getValueAt( int rowIndex, int columnIndex )
{
XModel cellModel = model.get( rowIndex + 1 ).get( columnIndex );
String dataType = XModelHelper.getAttrib( cellModel, "datatype" );
Object value = cellModel.get();
if ( dataType != null ) {
if ( dataType.equals( "currency" )) {
//if (price != null)
// return CurrencyUtils.formatPriceValue( value );
//else
return "";
}
else {
XBaseModel typeModel = (XBaseModel)rootModel.get( "units/" + dataType );
return ((String)value) + " " + typeModel.get().toString();
}
}
else
return value;
}
/**
* Get the model value
* @param rowIndex the row index
* @param columnIndex the column index
*/
public Object getModelAt( int rowIndex, int columnIndex )
{
try {
String datatype = XModelHelper.getAttrib( model.get( rowIndex + 1 ).get( columnIndex ), "datatype" );
return model.get( rowIndex + 1 ).get( columnIndex );
}
catch ( Exception e )
{
return null;
}
}
/**
* Get the model for the specified row
* @param rowIndex the row index
* @return the model value
*/
public Object getModelAt( int rowIndex )
{
return model.get( rowIndex + 1 );
}
/**
* Sets the value in the cell at <code>columnIndex</code> and
* <code>rowIndex</code> to <code>aValue</code>.
*
* @param aValue the new value
* @param rowIndex the row whose value is to be changed
* @param columnIndex the column whose value is to be changed
* @see #getValueAt
* @see #isCellEditable
*/
public void setValueAt(Object aValue, int rowIndex, int columnIndex)
{
model.get( rowIndex + 1 ).get( columnIndex ).set( aValue );
}
/**
* Set the editor component
* @param the component instance
*/
public void setComponent( Component comp )
{
component = comp;
}
/**
* Get the editor component
* @return the component instance
*/
public Component getComponent()
{
return component;
}
/**
* Adds a listener to the list that is notified each time a change
* to the data model occurs.
*
* @param l the TableModelListener
*/
public void addTableModelListener(TableModelListener l)
{
listeners.add( l );
}
/**
* Removes a listener from the list that is notified each time a
* change to the data model occurs.
*
* @param l the TableModelListener
*/
public void removeTableModelListener(TableModelListener l)
{
listeners.remove( l );
}
}
|