package net.xoetrope.awt;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.ItemSelectable;
import java.awt.event.ItemListener;
import net.xoetrope.xui.XAttributedComponent;
import net.xoetrope.xui.XModelHolder;
import net.xoetrope.xui.data.XModel;
import net.xoetrope.xui.style.XStyleComponent;
import net.xoetrope.xui.XHashCode;
import java.awt.event.MouseListener;
import net.xoetrope.xui.data.XRowSelector;
/**
* <p>Provides a simple read-only tables/grid component.</p>
* <p>Copyright (c) Xoetrope Ltd., 1998-2004<br>
* License: see license.txt
* $Revision: 2.7 $
*/
public class XTable extends XScrollPane implements XAttributedComponent, XModelHolder, ItemSelectable, XStyleComponent, XHashCode, XRowSelector
{
private XTableRenderer content;
private XModel model;
private XPanel componentPanel;
private int numRows;
/**
* Create a new table
*/
public XTable()
{
super();
numRows = -1;
componentPanel = new XPanel();
componentPanel.setLayout( null );
add( componentPanel );
content = new XTableRenderer( this );
componentPanel.add( content );
}
/**
* implemented from XModelHolder interface
*/
public void update()
{
checkSize();
repaint();
}
/**
* Create a panel for components
* @return the component panel
*/
public Container getComponentPanel()
{
return componentPanel;
}
/**
* Set the XModel which we will be generating the table from
* @param xmodel The XModel of data
*/
public void setModel( XModel xmodel )
{
model = xmodel;
if ( model != null )
model.get();
content.setContent( xmodel );
checkSize();
}
/**
* Get the underlying model.
* @return the model
*/
public XModel getModel()
{
return model;
}
/**
* Recalculate and check the size of the content
*/
public void checkSize()
{
content.removeCurrentComponent();
Dimension d = content.calcSize();
componentPanel.setSize( d );
content.setSize( d );
invalidate();
validate();
repaint();
}
/**
* Set the type of component for a column
* @param col the field index
* @param className the class name
*/
public void setComponentAt( int col, String className )
{
content.setComponentAt( col, className );
}
/**
* Set the model's name
* @return the name
*/
public String getContent()
{
return model.getId();
}
/**
* Creates the scroll pane's peer and sizes the child element.
*/
public void addNotify()
{
super.addNotify();
setContentSize();
}
private void setContentSize()
{
if ( content != null ) {
int rows = content.getNumRows();
if (( rows != numRows ) || !content.hasRendered()) {
numRows = rows;
Dimension d = content.calcSize();
componentPanel.setBounds( 0, 0, Math.max( ( this.getSize().width - 20 ), d.width ), d.height );
// content.setBounds( componentPanel.getBounds() );
invalidate();
validate();
}
}
}
/**
* Set the general style of the XTable
* @param style XStyle
*/
public void setStyle( String style )
{
content.setStyle( style );
}
/**
* Set the style of the header data
* @param style XStyle
*/
public void setHeaderStyle( String style )
{
content.setHeaderStyle( style );
}
/**
* Set the style of the selected row
* @param style XStyle
*/
public void setSelectedStyle( String style )
{
content.setSelectedStyle( style );
}
/**
* Set the style of the border
* @param style XStyle
*/
public void setBorderStyle( String style )
{
content.setBorderStyle( style );
}
/**
* Check the if the table is interactive
* @return true if the table supports user interaction
*/
public boolean isInteractiveTable()
{
return content.isInteractiveTable();
}
/**
* Set the user interaction state
* @param state true for an user interactive table.
*/
public void setInteractiveTable( boolean state )
{
content.setInteractiveTable( state );
}
/**
* Sets the indexof the selected row
* @param idx the new selected row
*/
public void setSelectedRow( int idx )
{
content.setSelectedRow( idx );
}
/**
* Get the index of the selected row
* @return the index of the selected row
*/
public int getSelectedRow()
{
return content.getSelectedRow();
}
/**
* Move to the first row
*/
public void first()
{
content.setSelectedRow( 0 );
}
/**
* Move to the previous row
*/
public void prev()
{
content.setSelectedRow( content.getSelectedRow()-1 );
}
/**
* Move to the next row
*/
public void next()
{
content.setSelectedRow( content.getSelectedRow()+1 );
}
/**
* Move to the last row
*/
public void last()
{
content.setSelectedRow( model.getNumChildren()-1 );
}
/**
* Tie the model selection to this table's selection
* @param doUpdate true to tie the selections together, false to ignore
*/
public void setUpdateModelSelection( boolean doUpdate )
{
content.setUpdateModelSelection( doUpdate );
}
/**
* Sets the bounds for this component
* @param x the left coordinate
* @param y the top coordinate
* @param w the width dimension
* @param h the height dimension
*/
public void setBounds( int x, int y, int w, int h )
{
Dimension d = content.calcSize();
componentPanel.setBounds( 0, 0, ( int )d.getSize().width, ( int )d.getSize().height );
// content.setBounds( componentPanel.getBounds() );
super.setBounds( x, y, w, h );
invalidate();
validate();
}
/**
* recalculates the size of the scroll area for dynamic table;
*/
public void setBounds()
{
Dimension d = content.calcSize();
componentPanel.setBounds( 0, 0, ( int )d.getSize().width, ( int )d.getSize().height );
// content.setBounds( componentPanel.getBounds() );
invalidate();
validate();
}
/**
* recalculates the size of the scroll area for dynamic table;
*/
public void scrollToBottom()
{
setScrollPosition( 0, ( int )getSize().height );
}
/**
* Set the table column width;
* @param fieldIdx the field index
* @param w the new column width
*/
public void setColWidth( int fieldIdx, int w )
{
content.setColWidth( fieldIdx, w );
}
/**
* Set one or more attributes of the component. Currently this handles the
* attributes
* <OL>
* <LI>headingStyle, value=the table header style</LI>
* <LI>selectionStyle, value=the selected row style</LI>
* <LI>interactive, value=true|false</LI>
* <LI>updateModel, value=true|false update the underlying model selection (the selected row)</LI>
* </OL>
* @param attribName the attribute name
* @param attribValue the attribute value
* @return 0 for success, non zero for failure or to require some further action
*/
public int setAttribute( String attribName, Object attribValue )
{
String attribNameLwr = attribName.toLowerCase();
String attribValueStr = ((String)attribValue);
// String attribValueLwr = attribValueStr.toLowerCase();
if ( attribNameLwr.equals( "headingstyle" ))
setHeaderStyle( attribValueStr );
else if ( attribNameLwr.equals( "selectionstyle" ))
setSelectedStyle( attribValueStr );
else if ( attribNameLwr.equals( "borderstyle" ))
setBorderStyle( attribValueStr );
else if ( attribNameLwr.equals( "interactive" ))
setInteractiveTable( attribValueStr.equals( "true" ));
else if ( attribNameLwr.equals( "updatemodel" ))
setUpdateModelSelection( attribValueStr.equals( "true" ));
else
return super.setAttribute( attribName, attribValue );
return 0;
}
/**
* Gets a field value object from the currently selected row
* @param fieldIdx the field offset
* @return the value
*/
public Object getValue( int fieldIdx )
{
int row = content.getCurrentRow();
return getValue( row, fieldIdx );
}
/**
* Gets a field value object from the specified row
* @param rowIdx the row offset
* @param fieldIdx the field offset
* @return the value
*/
public Object getValue( int rowIdx, int fieldIdx )
{
XModel rowModel = model.get( rowIdx + content.getFirstRow() );
Object fieldModel = rowModel.get( fieldIdx );
if ( fieldModel instanceof XModel )
return ( ( XModel )fieldModel ).get();
return fieldModel;
}
/**
* Gets a field value as a string from the currently selected row
* @param fieldIdx the field offset
* @return the value
*/
public String getFieldValue( int fieldIdx )
{
return ( String )getValue( fieldIdx );
}
/**
* Gets a field value as a string from the specified row
* @param rowIdx the row offset
* @param fieldIdx the field offset
* @return the value
*/
public String getFieldValue( int rowIdx, int fieldIdx )
{
return ( String )getValue( rowIdx, fieldIdx );
}
/**
* Adds the specified item listener to receive item events from
* this list. Item events are sent in response to user input, but not
* in response to calls to <code>select</code> or <code>deselect</code>.
* If listener <code>l</code> is <code>null</code>,
* no exception is thrown and no action is performed.
*
* @param l the item listener
* @see #removeItemListener( ItemListener )
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @since JDK1.1
*/
public synchronized void addItemListener( ItemListener l )
{
content.addItemListener( l );
}
/**
* Removes the specified item listener so that it no longer
* receives item events from this list.
* If listener <code>l</code> is <code>null</code>,
* no exception is thrown and no action is performed.
*
* @param l the item listener
* @see #addItemListener
* @see java.awt.event.ItemEvent
* @see java.awt.event.ItemListener
* @since JDK1.1
*/
public synchronized void removeItemListener( ItemListener l )
{
content.removeItemListener( l );
}
/**
* Returns the selected items on the list in an array of objects.
* @see ItemSelectable
* @return an array of the selected components
*/
public Object[] getSelectedObjects()
{
return content.getSelectedObjects();
}
/**
* Request the component repaint itself
*/
public void repaint()
{
setContentSize();
content.repaint();
}
/**
* Render the component
* @param g the graphics context
*/
public void paint( Graphics g )
{
setContentSize();
content.repaint();
}
/**
* Add a mouse listener
* @param l the new mouse listener
*/
public void addMouseListener( MouseListener l )
{
content.addMouseListener( l );
}
/**
* Get the hash code to be used by the event handler for this component
* @return the hash code
*/
public long getComponentHashCode()
{
return content.hashCode();
}
/**
* Forward the focus request to the content/table renderer
*/
public void requestFocus()
{
content.requestFocus();
}
}