Package net.xoetrope.swing

Source Code of net.xoetrope.swing.XSwingTableModel

package net.xoetrope.swing;

import java.awt.Color;
import java.awt.Component;
import java.util.Vector;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.TableModelListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import net.xoetrope.swing.table.GroupableTableHeader;
import net.xoetrope.xui.XAttributedComponent;
import net.xoetrope.xui.XModelHolder;
import net.xoetrope.xui.XProject;
import net.xoetrope.xui.XProjectManager;
import net.xoetrope.xui.data.XModel;
import net.xoetrope.xui.style.XStyleComponent;
import net.xoetrope.xui.style.XStyle;
import net.xoetrope.xui.data.XRowSelector;
import net.xoetrope.xui.events.XHandlerInvoker;
import net.xoetrope.xui.events.XListenerHelper;
import net.xoetrope.xui.style.XStyleManager;
import net.xoetrope.xui.data.XBaseModel;
import net.xoetrope.xui.data.table.XTableModel;
import net.xoetrope.xui.helper.XTranslator;

/**
* <p>Provides a wrapper for the JTable and offer some compatibility with the
* AWT version of the XTable.</p>
* <p>Copyright (c) Xoetrope Ltd., 1998-2004<br>
* License:      see license.txt
* $Revision: 2.12 $
*/
public class XTable extends JTable  implements XAttributedComponent, XModelHolder,
    XStyleComponent, XRowSelector,
    XListenerHelper, ListSelectionListener
{
  protected XProject currentProject;
  protected XModel model;
  protected boolean updateModelSelection = false;
  protected XHandlerInvoker invoker;
  protected int oldRowSelection = -1;
  protected boolean usesDatabase = false;
  protected String headerStyle;

  /**
   * Create a new table
   */
  public XTable()
  {
    super();
    currentProject = XProjectManager.getCurrentProject();

    setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
    getTableHeader().setReorderingAllowed( false );

    getSelectionModel().addListSelectionListener( this );
  }

  protected JTableHeader createDefaultTableHeader()
  {
    return new GroupableTableHeader( columnModel );
  }
 
  public void update()
  {
    if ( dataModel != null ) {
      int selRowIdx = getSelectedRow();

      updateTable();
      int newRowIdx = getSelectedRow();
      if (( newRowIdx < 0 ) && ( selRowIdx >= 0 ))
        setSelectedRow( selRowIdx );
    }
  }

  /**
   * Force the scroll pane to set the component size if there is no data - otherwise the
   * table would have no height
   */
  public boolean getScrollableTracksViewportHeight()
  {
    if ( model == null ) {
      if ( getParent() instanceof JViewport )
        return true;
    }
   
    return super.getScrollableTracksViewportHeight();
  }
 
  /**
   * Force the table to update itself
   */
  public void updateTable()
  {
    tableChanged( new TableModelEvent( dataModel ));
  }

  /**
   * Add an event handler response method to a component such that the page's
   * response method is invoked when the event occurs
   * @param page the page containing the method
   * @param handlerType the type of event handler
   * @param methodName the method to invoke
   * @throws NoSuchMethodException cannot add the handler
   */
  public void addHandler( Object page, String handlerType, String methodName ) throws NoSuchMethodException
  {
    invoker = new XHandlerInvoker( page, this, methodName );
  }

  /**
   * The row selection has changes, update the model if required.
   * @param le the list selection event
   */
  public void valueChanged( ListSelectionEvent le )
  {
    super.valueChanged( le );

    if ( model instanceof XRowSelector ) {
      int selRowIdx = getSelectedRow();
      if ( selRowIdx >= 0 ) {
        if ( updateModelSelection )
          ((XRowSelector)model).setSelectedRow( selRowIdx );
       
        if (( oldRowSelection != selRowIdx ) && ( invoker != null ))
          invoker.invoke();
       
        oldRowSelection = selRowIdx;
      }
    }
  }

  /**
   * 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 ) {
      usesDatabase = ( model instanceof XTableModel );
      model.get();
      setModel( new XSwingTableModel( currentProject, model ));
    }
  }

  /**
   * Get the underlying model.
   * @return the model
   */
  public XModel getXModel()
  {
    return model;
  }

  /**
   * Set the general style of the XTable
   * @param style XStyle
   */
  public void setStyle( String style )
  {
    XStyleManager styleMgr = currentProject.getStyleManager();
    XStyle xstyle = styleMgr.getStyle( style );
    setForeground( xstyle.getStyleAsColor( XStyle.COLOR_FORE ));
    setBackground( xstyle.getStyleAsColor( XStyle.COLOR_BACK ));
    setFont( styleMgr.getFont( xstyle ));
  }
 
  /**
   * Set the background color of the table's viewport
   * @param viewportBkColor the viewport background color
   */
  public void setViewportBackground( Color viewportBkColor )
  {
    Component p = getParent();
    if ( p instanceof JViewport )
      p.setBackground( viewportBkColor );
  }

  /**
   * Set the style of the header data
   * @param style XStyle
   */
  public void setHeaderStyle( String style )
  {
    if ( style != null ) {
      headerStyle = style;
      XStyleManager styleMgr = currentProject.getStyleManager();
      XStyle xstyle = styleMgr.getStyle( style );
      JTableHeader th = getTableHeader();
   
      th.setForeground( xstyle.getStyleAsColor( XStyle.COLOR_FORE ));
      th.setBackground( xstyle.getStyleAsColor( XStyle.COLOR_BACK ));
      th.setFont( styleMgr.getFont( xstyle ));
    }
  }

  /**
   * Retrieve the name of the header style
   * @return the header style name;
   */
  public String getHeaderStyle()
  {
    return headerStyle;
  }

  /**
   * Set the style of the selected row
   * @param style XStyle
   */
  public void setSelectedStyle( String style )
  {
    XStyle xstyle = currentProject.getStyleManager().getStyle( style );
    Color c = xstyle.getStyleAsColor( XStyle.COLOR_FORE );
    if ( c != null )
      setSelectionForeground( c );
   
    c = xstyle.getStyleAsColor( XStyle.COLOR_BACK );
    if ( c != null )
      setSelectionBackground( c );
  }

  /**
   * Set the style of the border
   * @param styleName the style name
   */
  public void setBorderStyle( String styleName )
  {
    XStyle style = currentProject.getStyleManager().getStyle( styleName );

    Color borderColor = style.getStyleAsColor( XStyle.COLOR_FORE );
    setBorder( new LineBorder( borderColor ));
  }

  /**
   * Check the if the table is interactive
   * @return true if the table supports user interaction
   * @deprecated
   */
  public boolean isInteractiveTable()
  {
//    return content.isInteractiveTable();
    return false;
  }

  /**
   * Set the user interaction state
   * @param state true for an user interactive table.
   * @deprecated
   */
  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 )
  {
    setRowSelectionInterval( idx, idx );
  }
 
  /**
   * Deselects all selected columns and rows.
   */
  public void clearSelection()
  {
    oldRowSelection = -1;
    super.clearSelection();
  }
 
  /**
   * Set the translateable state of the model
   * @param state 'true' for a transalted table
   */
  public void setTranslated( boolean state )
  {
    ((XSwingTableModel)getModel()).setTranslated( state );
  }
 
  /**
   * Get the translateable state of the table
   * @return true if the table is translateable
   */
  public boolean getTranslated()
  {
    return ((XSwingTableModel)getModel()).getTranslated();
  }
 
 
  /**
   * Move to the first row
   */
  public void first()
  {
    if ( getRowCount() > 0 )
      setSelectedRow( 0 );
  }

  /**
   * Move to the previous row
   */
  public void prev()
  {
    int selRow = getSelectedRow() - 1;
    if ( selRow >= 0 )
      setSelectedRow( selRow );
  }

  /**
   * Move to the next row
   */
  public void next()
  {
    int selRow = getSelectedRow() + 1;
    if ( selRow <= ( getRowCount() -1 ))
      setSelectedRow( selRow );
  }

  /**
   * Move to the last row
   */
  public void last()
  {
    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 )
  {
    updateModelSelection = doUpdate;
  }

  /**
   * Set the column width. Sets the maximum width as a workaround for a Swing problem
   * @param columnIdx the column index
   * @param width the new width
   */
  public void setColWidth( int columnIdx, int width
  {
    if ( isShowing() && isVisible()) {
      DefaultTableColumnModel colModel = (DefaultTableColumnModel)getColumnModel();
      TableColumn column = colModel.getColumn( columnIdx );
      column.setMaxWidth( width );
    }
    else {
      try {
        final int w = width;
        final int col = columnIdx;
        SwingUtilities.invokeLater( new Runnable() {
          public void run()
          {
            /**
             * This is intended to be called after the component is displayed,
             * so rthis delay may not work. Some die effects can be caused by
             * the L&F delegate resetting properties and therefore whatever
             * calls this probably shouldn't call this method till after
             * addNotify is called.
             */
            DefaultTableColumnModel colModel = (DefaultTableColumnModel)getColumnModel();
            TableColumn column = colModel.getColumn( col );
            column.setMaxWidth( w );
          }
        });
      }
      catch ( Exception e ) {}
    }
  }

  /**
   * 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 - no longer used</LI>
   * <LI>updateModel, value=true|false update the underlying model selection (the selected row)</LI>
   * <LI>border, 0 to turn off the border</LI>
   * <LI>selectionmode, value=multiple for multiple selection ranges, single=a single selection range, singleSelection for a single item/row selection</LI>
   * <LI>grid, value=true|false turn the grid on or off</LI>
   * <LI>vertlines, value=true|false turn the vertical grid on or off</LI>
   * <LI>horzlines, value=true|false turn the horizontal grid on or off</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 = null;
//    if ( attribValue != null )
//      attribValueLwr = attribValueStr.toLowerCase();
    if ( attribNameLwr.equals( "headingstyle" ) || attribNameLwr.equals( "headerstyle" ))
      setHeaderStyle( attribValueStr );
    else if ( attribNameLwr.equals( "selectionstyle" ))
      setSelectedStyle( attribValueStr );
    else if ( attribNameLwr.equals( "borderstyle" ))
      setBorderStyle( attribValueStr );
    else if ( attribNameLwr.equals( "border" )) {
      if ( "0".equals( attribValueStr ))
        setBorder( new EmptyBorder( 0, 0, 0, 0 ));
    }
    else if ( attribNameLwr.equals( "interactive" ))
      ;//setInteractiveTable( attribValueStr.equals( "true" ));
    else if ( attribNameLwr.equals( "updatemodel" ))
      setUpdateModelSelection( attribValueStr.equals( "true" ));
    else if ( attribNameLwr.equals( "selectionmode" ))
      setSelectionMode( attribValueStr );
    else if ( attribNameLwr.equals( "grid" ))
      setShowGrid( attribValue.toString().equals( "true" ));
    else if ( attribNameLwr.equals( "vertlines" ))
      setShowVerticalLines( attribValue.toString().equals( "true" ));
    else if ( attribNameLwr.equals( "horzlines" ))
      setShowHorizontalLines( attribValue.toString().equals( "true" ));
    else
      return -1;

    return 0;
  }
 
  /**
   * Set the table selection mode
   * @param value 'multiple' for ListSelectionModel.MULTIPLE_INTERVAL_SELECTION,
   * other wise ListSelectionModel.SINGLE_INTERVAL_SELECTION
   */
  public void setSelectionMode( String value )
  {
    if ( value.equals( "multiple" ) )
      setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
    else if ( value.equals( "single" ) )
      setSelectionMode( ListSelectionModel.SINGLE_INTERVAL_SELECTION );
    else
      setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
  }

  /**
   * 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 = getSelectedRow();
    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 + 0/*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 );
  }
 
  /**
   * Retrieves the TableCellEditor for a cell if one has been specified with the
   * "editor" attribute
   * @param row the row/record index (zero based)
   * @param column the column/field index (zero based)
   */
  public TableCellEditor getCellEditor( int row, int column )
  {
    Object obj = getValueAt( row, column );
    if ( obj instanceof XModel ) {
      XModel model = (XModel)obj;
      String editor = model.getAttribValueAsString( model.getAttribute( "editor" ));
      if ( editor == null )
        return super.getCellEditor( row, column );     
    }
   
    return null;
  }
}


/**
* Create a new table model for use by the Table2 class
*/
class XSwingTableModel implements TableModel
{
  /**
   * The data model
   */
  private XModel model;
 
  /**
   * the table listeners
   */
  private Vector listeners;
 
  /**
   * true to display a header
   */
  private boolean hasHeaderRow;

  private boolean usesDatabase;
 
  private boolean translateable;
  private XTranslator translator;
 
  /**
   * Create a new table model
   * @param currentProject the owner project
   * @param newModel the data model source
   */
  public XSwingTableModel( XProject currentProject, XModel newModel )
  {
    model = newModel;
    usesDatabase = ( model instanceof XTableModel );
    listeners = new Vector();
    hasHeaderRow = false;
    translateable = false;
    translator = currentProject.getTranslator();
  }

  /**
   * Set the translateable state of the model
   * @param state 'true' for a transalted table
   */
  public void setTranslated( boolean state )
  {
    translateable = state;
  }
 
  /**
   * Get the translateable state of the table
   * @return true if the table is translateable
   */
  public boolean getTranslated()
  {
    return translateable;
  }
 
  /**
   * 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()
  {
    if ( hasHeaderRow )
      return model.getNumChildren() -1;
    return model.getNumChildren();
  }

  /**
   * 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 ) {
      if ( usesDatabase )
        return model.getNumAttributes();
      else if ( model instanceof XBaseModel ) {
        XBaseModel row0 = (XBaseModel)((XBaseModel)model).get( 0 );
        if ( row0.getTagName().equals( "th" )) {
          hasHeaderRow = true;
          return row0.getNumChildren();
        }
      }
    }
    return model.getNumAttributes();
  }

  /**
   * 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)
  {
    if ( hasHeaderRow ) {
      if ( model instanceof XBaseModel ) {//usesDatabase ) {
        XBaseModel row0 = ( XBaseModel ) ( ( XBaseModel ) model ).get( 0 );
        return row0.get( columnIndex ).getAttribValueAsString( XBaseModel.VALUE_ATTRIBUTE );
      }
    }

    return model.getAttribName( columnIndex );
  }

  /**
   * 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.
   *
   * @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 )
  {
    return false;
  }

  /**
   * 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 )
  {
    Object obj = model.get( rowIndex + ( hasHeaderRow ? 1 : 0 )).get( columnIndex ).get();
    if (( obj instanceof String ) && translateable )
      return translator.translate( (String)obj );
     
    return obj;
  }

  /**
   * 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 )
  {

  }

  /**
   * 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 );
  }
}
TOP

Related Classes of net.xoetrope.swing.XSwingTableModel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.