home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / jfc.bin / DefaultTableModel.java < prev    next >
Text File  |  1998-02-26  |  30KB  |  795 lines

  1. /*
  2.  * @(#)DefaultTableModel.java    1.14 98/02/02
  3.  * 
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20.  
  21. package com.sun.java.swing.table;
  22.  
  23. import java.io.Serializable;
  24. import java.util.Date;
  25. import java.util.Vector;
  26. import java.util.Enumeration;
  27. import com.sun.java.swing.event.TableModelEvent;
  28.  
  29.  
  30. /**
  31.  * This is an implementation of TableModel that uses a Vector of Vectors
  32.  * to store the cell value objects.
  33.  * <p>
  34.  * <b>Note:</b><br>
  35.  * The DefaultTableModel's API contains the methods addColumn(),
  36.  * removeColumn(), but not methods to insert a column at an index
  37.  * nor methods to move the columns.  This is because JTable does
  38.  * not display the columns based on the order of the columns in
  39.  * this model.  So rearranging them here doesn't do much.  See
  40.  * the column ordering methods in TableColumnModel.
  41.  * <p>
  42.  * Warning: serialized objects of this class will not be compatible with
  43.  * future swing releases.  The current serialization support is appropriate
  44.  * for short term storage or RMI between Swing1.0 applications.  It will
  45.  * not be possible to load serialized Swing1.0 objects with future releases
  46.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  47.  * baseline for the serialized form of Swing objects.
  48.  *
  49.  * @version 1.14 02/02/98
  50.  * @author Alan Chung
  51.  *
  52.  * @see TableModel
  53.  * @see #getDataVector()
  54.  */
  55. public class DefaultTableModel extends AbstractTableModel
  56. implements Serializable {
  57. //
  58. // Instance Variables
  59. //
  60.  
  61.     /** The Vector of Vector of Object values */
  62.     protected Vector    dataVector;
  63.  
  64.     /** The Vector column identifiers */
  65.     protected Vector    columnIdentifiers;
  66.  
  67.     /** The number of columns in the table */
  68.     int                 numColumns;
  69.  
  70.     /** The number of rows in the table */
  71.     int                 numRows;
  72.  
  73. //
  74. // Constructors
  75. //
  76.     
  77.     /**
  78.      *  Constructs a default DefaultTableModel which is a table of
  79.      *  zero columns and zero rows.
  80.      */
  81.     public DefaultTableModel() {
  82.         this((Vector)null,0);
  83.     }
  84.  
  85.     /**
  86.      *  Constructs a DefaultTableModel with <i>numColumns</i> and
  87.      *  <i>numRows</i> of <b>null</b> object values.  
  88.      *
  89.      * @param numColumns        The number of columns the table holds
  90.      * @param numRows           The number of rows the table holds
  91.      *
  92.      * @see #setValueAt()
  93.      */
  94.     public DefaultTableModel(int numColumns, int numRows) {
  95.         this(new Vector(numColumns), numRows);
  96.     }
  97.  
  98.     /**
  99.      *  Constructs a DefaultTableModel with as many columns as there are
  100.      *  elements in <i>columnIds</i> and
  101.      *  <i>numRows</i> of <b>null</b> object values.  Each column's
  102.      *  identifier object will be taken from the <i>columnIds</i>
  103.      *  vector.
  104.      *
  105.      * @param columnIds         Vector containing identifier objects
  106.      *                          to be used to identify the columns.  If this
  107.      *                          null then the model has no columns
  108.      * @param numRows           The number of rows the table holds
  109.      * @see #setValueAt()
  110.      */
  111.     public DefaultTableModel(Vector columnIds, int numRows) {
  112.         super();
  113.  
  114.         if (columnIds != null) {
  115.             numColumns = columnIds.size();
  116.             columnIdentifiers = columnIds;
  117.         }
  118.         else {
  119.             numColumns = 0;
  120.             columnIdentifiers = new Vector();
  121.         }
  122.             
  123.         dataVector = new Vector();
  124.         this.numRows = 0;
  125.         if (numRows != 0)
  126.             this.setNumRows(numRows);
  127.     }
  128.  
  129.     /**
  130.      *  Constructs a DefaultTableModel with as many columns as there are
  131.      *  elements in <i>columnIds</i> and
  132.      *  <i>numRows</i> of <b>null</b> object values.  Each column's
  133.      *  identifier object will be taken from the <i>columnIds</i>
  134.      *  array.
  135.      *
  136.      * @param columnIds         Array containing identifier objects
  137.      *                          to be used to identify the columns.  If this
  138.      *                          null then the model has no columns
  139.      * @param numRows           The number of rows the table holds
  140.      * @see #setValueAt()
  141.      */
  142.     public DefaultTableModel(Object[] columnIds, int numRows) {
  143.         this(DefaultTableModel.convertToVector(columnIds), numRows);
  144.     }
  145.  
  146.     /**
  147.      *  Constructs a DefaultTableModel and initialize the table
  148.      *  by passing <i>data</i> and <i>columnIds</i> to the setDataVector()
  149.      *  method.  See the documentation of the getDataVector() method for details
  150.      *  on how to structure <i>data</i> properly.
  151.      *
  152.      * @exception IllegalArgumentException see setDataVector().
  153.      * @param data              The data of the table
  154.      * @param columnIds         Vector containing identifier objects
  155.      *                          to be used to identify the columns.
  156.      * @see #getDataVector()
  157.      * @see #setDataVector()
  158.      */
  159.     public DefaultTableModel(Vector data, Vector columnIds) {
  160.         this((Vector)null,0);
  161.         this.setDataVector(data, columnIds);
  162.     }
  163.     
  164.     /**
  165.      *  Constructs a DefaultTableModel and initialize the table
  166.      *  by passing <i>data</i> and <i>columnIds</i> to the setDataVector()
  167.      *  method.    The first index in the Object[][] is the row index and
  168.      *  the second is the column index.
  169.      *
  170.      * @exception IllegalArgumentException see setDataVector().
  171.      * @param data              The data of the table
  172.      * @param columnIds         Array containing identifier objects
  173.      *                          to be used to identify the columns.
  174.      * @see #getDataVector()
  175.      * @see #setDataVector()
  176.      */
  177.     public DefaultTableModel(Object[][] data, Object[] columnIds) {
  178.         this((Vector)null,0);
  179.         this.setDataVector(data, columnIds);
  180.     }
  181.     
  182. //
  183. // Querying and Modifying the Column Identifies
  184. //
  185.  
  186. //
  187. // Querying and Modifying the data structure
  188. //
  189.  
  190.     /**
  191.      *  This returns the Vector of Vectors that contains the table's
  192.      *  data values.  The vectors contained in the outer vector are
  193.      *  each a single row of values.  In other words, to get to the cell
  194.      *  at row 1, column 5 <p>
  195.      *
  196.      *  <code>((Vector)getDataVector().elementAt(1)).elementAt(5);</code><p>
  197.      *
  198.      *  You can directly alter the returned Vector.  You can change the cell
  199.      *  values, the number of rows, but you may <b>not</b> change the number
  200.      *  of columns in the model.  If you need to alter the number of columns
  201.      *  in the model, you can do so with addColumn(), removeColumn(), or
  202.      *  the setDataVector() methods.  Once you have finished modifying the
  203.      *  dataVector,  you <b>must</b> inform the model of the new data using
  204.      *  the newDataAvailable(), rowsRemoved() or the newRowsAdded() methods.
  205.      *  Depending on which one of the three best describes the changes made.
  206.      *  These methods will give the model a chance to modify its internal
  207.      *  variables based upon the new data vector.  The new data methods
  208.      *  will also generate the appropriate TableModelListener
  209.      *  messages to notify any listeners of this model.
  210.      *
  211.      * @see #newDataAvailable()
  212.      * @see #newRowsAdded()
  213.      * @see #rowsRemoved()
  214.      * @see #setDataVector()
  215.      */
  216.     public Vector getDataVector() {
  217.         return dataVector;
  218.     }
  219.  
  220.     /**
  221.      *  This replaces the current dataVector instance variable with the
  222.      *  parameter <i>newData</i>.  <i>columnIds</i> are the identifiers
  223.      *  of the new columns.  The first identifier in <i>columnIds</i> is
  224.      *  mapped to column 1 in <i>newData</i>.  <p>
  225.      *
  226.      *  The size of the <i>columnIds</i> vector must
  227.      *  equal the size of the <i>newData</i> vector.  If <i>columnIds</i> is
  228.      *  <b>null</b> then it will reuse the currect vector of column identifiers.
  229.      *  Finally, this method calls newDataAvailable() to generate the
  230.      *  appropriate notification.
  231.      *
  232.      * @param   newData         The new data vector
  233.      * @param   columnIds       The corresponding column identifiers for
  234.      *                          the new data vector
  235.      * @exception IllegalArgumentException if newData is null or if the number
  236.      *                          of columns in newData does not equal the 
  237.      *                          number of the column identifiers in columnIds.
  238.      * @see #newDataAvailable()
  239.      * @see #getDataVector()
  240.      */
  241.     public void setDataVector(Vector newData, Vector columnIds) {
  242.         Vector oldIds = columnIdentifiers;
  243.  
  244.         if (newData == null)
  245.             throw new IllegalArgumentException("setDataVector() - Null parameter");
  246.  
  247.         if (columnIds != null) {
  248.             columnIdentifiers = columnIds;
  249.         }
  250.         dataVector = newData;
  251.         numColumns = ((Vector)dataVector.elementAt(0)).size(); 
  252.         this.newDataAvailable(null);
  253.     }
  254.     
  255.     /**
  256.      *  This replaces the value in the dataVector instance variable with the
  257.      *  values in the array <i>newData</i>.  The first index in the Object[][]
  258.      *  array is the row index and the second is the column index.
  259.      *  <i>columnIds</i> are the identifiers of the new columns. 
  260.      *  Finally, this method calls newDataAvailable() to generate the
  261.      *  appropriate notification.
  262.      *
  263.      * @param   newData         The new data array
  264.      * @param   columnIds       The corresponding column identifiers for
  265.      *                          the new data array
  266.      * @exception IllegalArgumentException if newData is null or if the number
  267.      *                          of columns in newData does not equal the 
  268.      *                          number of the column identifiers in columnIds.
  269.      * @see #newDataAvailable()
  270.      * @see #getDataVector()
  271.      */
  272.     public void setDataVector(Object[][] newData, Object[] columnIds) {
  273.         Vector ids = null;
  274.         if (columnIds != null)
  275.             ids = DefaultTableModel.convertToVector(columnIds);
  276.         
  277.         setDataVector(DefaultTableModel.convertToVector(newData), ids);
  278.     }
  279.  
  280.     /**
  281.      *  This method is used to informed the model that the model's dataVector
  282.      *  has been changed directly.  The <i>event</i> describes the extent
  283.      *  of the update.  This method will send the tableChanged() notification
  284.      *  message to all the listeners. <p>
  285.      *
  286.      *  If <i>event</i> is <b>null</b> or if the number of rows in dataVector
  287.      *  is different from numRows, then it will assume all the data
  288.      *  in dataVector is new or updated.  It will recalculate numRows, and
  289.      *  will generate the correct TableModelEvent to send out with the
  290.      *  nofication.
  291.      *
  292.      * @parameter event         This TableModelEvent describes where the
  293.      *                          change happened.  If <b>null</b> it assumes
  294.      *                          all data is new or updated
  295.      *
  296.      * @see #getDataVector()
  297.      * @see #newRowsAdded()
  298.      * @see #rowsRemoved()
  299.      */
  300.     public void newDataAvailable(TableModelEvent event) {
  301.         if ((event == null) || (dataVector.size() != numRows)) {
  302.             // Assume all changed
  303.             numRows = dataVector.size();
  304.             
  305.             event = new TableModelEvent(this, TableModelEvent.HEADER_ROW);
  306.  
  307.             // Because the new data rows might not have the correct number
  308.             // of columns we need to do this to make sure dataVector is not
  309.             // malformed.
  310.             this.setColumnIdentifiers(columnIdentifiers);
  311.         }
  312.  
  313.         // Now we sent the notification
  314.         fireTableChanged(event);
  315.     }
  316.  
  317.     /**
  318.      *  This method will recalculate numRows, it will also make sure
  319.      *  the new rows have the correct number of columns.  Then it 
  320.      *  will send out the tableChanged() notification message
  321.      *  to all the listeners.
  322.      *
  323.      * @parameter event         This TableModelEvent describes where the
  324.      *                          rows were added.  If <b>null</b> it assumes
  325.      *                          all the rows were newly added.
  326.      * @see #getDataVector()
  327.      */
  328.     public void newRowsAdded(TableModelEvent event) {
  329.         numRows = dataVector.size();
  330.         int start = event.getFirstRow();
  331.         int end = event.getLastRow();
  332.         if (start < 0) start = 0;
  333.         if (end < 0) end = numRows-1;
  334.  
  335.         // Have to make sure all the new columns have the correct
  336.         // number of columns
  337.         for (int i=start; i <= end; i++)
  338.             ((Vector)dataVector.elementAt(i)).setSize(numColumns);
  339.  
  340.         // Now we send the notification
  341.         fireTableChanged(event);
  342.     }
  343.  
  344.     /**
  345.      *  This method will recalculate numRows, then it
  346.      *  will send out the tableRowsRemoved() notification message
  347.      *  to all the listeners.
  348.      *
  349.      * @parameter event         This TableModelEvent describes where the
  350.      *                          rows were removed.
  351.      * @exception IllegalArgumentException      if event is null
  352.      * @see #getDataVector()
  353.      */
  354.     public void rowsRemoved(TableModelEvent event) {
  355.         if (event == null)
  356.             throw new IllegalArgumentException("rowsRemoved() - null parameter");
  357.  
  358.         numRows = dataVector.size();
  359.  
  360.         // Now we send the notification
  361.         fireTableChanged(event);
  362.     }
  363.  
  364.     /**
  365.      * Replaces the column identifiers in the model. 
  366.      *
  367.      * @param   newIdentifiers  Vector of column identifiers.  A null means
  368.      *                          setting the model to zero columns
  369.      * @see #setNumRows()
  370.      */
  371.     public void setColumnIdentifiers(Vector newIdentifiers) {
  372.         if (newIdentifiers != null) {
  373.             columnIdentifiers = newIdentifiers;
  374.             numColumns = newIdentifiers.size();
  375.         }
  376.         else {
  377.             columnIdentifiers = new Vector();
  378.             numColumns = 0;
  379.         }
  380.  
  381.         // Generate notification
  382.         fireTableStructureChanged();
  383.     }
  384.     
  385.     /**
  386.      * Replaces the column identifiers in the model.  If the number of
  387.      * <i>newIdentifiers</i> is greater than the current numColumns,
  388.      * new columns are added to the end of each row in the model.
  389.      * If the number of <i>newIdentifier</i> is less than the current
  390.      * number of columns, all the extra columns at the end of a row are
  391.      * discarded. <p>
  392.      *
  393.      * @param   newIdentifiers  Array of column identifiers.  A null means
  394.      *                          setting the model to zero columns
  395.      * @see #setNumRows()
  396.      */
  397.     public void setColumnIdentifiers(Object[] newIdentifiers) {
  398.         this.setColumnIdentifiers(DefaultTableModel.convertToVector(newIdentifiers));
  399.     }
  400.  
  401.     /**
  402.      *  Sets the number of rows in the model.  If the new size is greater
  403.      *  than the current size, new rows are added to the end of the model
  404.      *  If the new size is less than the current size, all 
  405.      *  rows at index <i>newSize</i> and greater are discarded. <p>
  406.      *
  407.      * @param   newSize   the new number of rows
  408.      * @see #setColumnIdentifiers()
  409.      */
  410.     public void setNumRows(int newSize) {
  411.         if ((newSize < 0) || (newSize == numRows))
  412.             return;
  413.  
  414.         int oldNumRows = numRows;
  415.         if (newSize <= numRows) {
  416.             // newSize is smaller than our current size, so we can just
  417.             // let Vector discard the extra rows
  418.             numRows = newSize;
  419.             dataVector.setSize(numRows);
  420.  
  421.             // Generate notification
  422.             rowsRemoved(new TableModelEvent(this, numRows, oldNumRows-1, 
  423.                                 TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE));
  424.         }
  425.         else {
  426.             // We are adding rows to the model
  427.             while(numRows < newSize) {
  428.                 Vector newRow = new Vector(numColumns);
  429.                 dataVector.addElement(newRow);
  430.                 numRows++;
  431.             }
  432.  
  433.             // Generate notification
  434.             newRowsAdded(new TableModelEvent(this, oldNumRows, numRows-1, 
  435.                              TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  436.         }
  437.     }
  438.  
  439.     /**
  440.      *  Add a column to the model.  The new column will have the
  441.      *  idenitifier <i>columnIdentifier</i>.  This method will send a
  442.      *  tableChanged() notification message to all the listeners. 
  443.      *  This method is a cover for <i>addColumn(Object, Vector)</i> which 
  444.      *  uses null as the data vector. 
  445.      *
  446.      * @param   columnIdentifier the identifier of the column being added
  447.      * @exception IllegalArgumentException      if columnIdentifier is null
  448.      */
  449.     public void addColumn(Object columnIdentifier) {
  450.         addColumn(columnIdentifier, (Vector)null); 
  451.     }
  452.  
  453.     /**
  454.      *  Add a column to the model.  The new column will have the
  455.      *  idenitifier <i>columnIdentifier</i>.  <i>columnData</i> is the
  456.      *  optional Vector of data for the column.  If it is <b>null</b>
  457.      *  the column is filled with <b>null</b> values.  Otherwise,
  458.      *  the new data will be added to model starting with the first
  459.      *  element going to row 0, etc.  This method will send a
  460.      *  tableChanged() notification message to all the listeners.
  461.      *
  462.      * @param   columnIdentifier the identifier of the column being added
  463.      * @param   columnData       optional data of the column being added
  464.      * @exception IllegalArgumentException      if columnIdentifier is null
  465.      */
  466.     public void addColumn(Object columnIdentifier, Vector columnData) {
  467.         if (columnIdentifier == null)
  468.             throw new IllegalArgumentException("addColumn() - null parameter");
  469.  
  470.         columnIdentifiers.addElement(columnIdentifier);
  471.         numColumns++;
  472.  
  473.         // Fill in the new column, with nulls or with columnData
  474.         int index = 0;
  475.         Enumeration enumeration = dataVector.elements();
  476.         while (enumeration.hasMoreElements()) {
  477.             Object value;
  478.  
  479.             if ((columnData != null) && (index < columnData.size()))
  480.                 value = columnData.elementAt(index);
  481.             else
  482.                 value = null;
  483.  
  484.             ((Vector)enumeration.nextElement()).addElement(value);
  485.             index++;
  486.         }
  487.  
  488.         // Generate notification
  489.         fireTableChanged(null);
  490.     }
  491.  
  492.     /**
  493.      *  Add a column to the model.  The new column will have the
  494.      *  idenitifier <i>columnIdentifier</i>.  <i>columnData</i> is the
  495.      *  optional array of data for the column.  If it is <b>null</b>
  496.      *  the column is filled with <b>null</b> values.  Otherwise,
  497.      *  the new data will be added to model starting with the first
  498.      *  element going to row 0, etc.  This method will send a
  499.      *  tableChanged() notification message to all the listeners.
  500.      *
  501.      * @param   columnIdentifier the identifier of the column being added
  502.      * @param   columnData       optional data of the column being added
  503.      * @exception IllegalArgumentException      if columnIdentifier is null
  504.      */
  505.     public void addColumn(Object columnIdentifier, Object[] columnData) {
  506.         if (columnIdentifier == null)
  507.             throw new IllegalArgumentException("addColumn() - null parameter");
  508.  
  509.         columnIdentifiers.addElement(columnIdentifier);
  510.         numColumns++;
  511.  
  512.         // Fill in the new column, with nulls or with columnData
  513.         int index = 0;
  514.         Enumeration enumeration = dataVector.elements();
  515.         while (enumeration.hasMoreElements()) {
  516.             Object value;
  517.  
  518.             if ((columnData != null) && (index < columnData.length))
  519.                 value = columnData[index];
  520.             else
  521.                 value = null;
  522.  
  523.             ((Vector)enumeration.nextElement()).addElement(value);
  524.             index++;
  525.         }
  526.  
  527.         // Generate notification
  528.         fireTableChanged(null);
  529.     }
  530.  
  531.     /**
  532.      *  Add a row to the end of the model.  The new row will contain
  533.      *  <b>null</b> values unless <i>rowData</i> is specified.  Notification
  534.      *  of the row being added will be generated.  
  535.      *
  536.      * @param   rowData          optional data of the row being added
  537.      */
  538.     public void addRow(Vector rowData) {
  539.         Vector newRow = rowData;
  540.  
  541.         if (newRow == null)
  542.             newRow = new Vector(numColumns);
  543.  
  544.         dataVector.addElement(rowData);
  545.         numRows++;
  546.  
  547.         // Generate notification
  548.         newRowsAdded(new TableModelEvent(this, numRows-1, numRows-1, 
  549.                              TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  550.     }
  551.  
  552.     /**
  553.      *  Add a row to the end of the model.  The new row will contain
  554.      *  <b>null</b> values unless <i>rowData</i> is specified.  Notification
  555.      *  of the row being added will be generated.  
  556.      *
  557.      * @param   rowData          optional data of the row being added
  558.      */
  559.     public void addRow(Object[] rowData) {
  560.         Vector newVector = null;
  561.  
  562.         if (rowData != null)
  563.             newVector = DefaultTableModel.convertToVector(rowData);
  564.  
  565.         this.addRow(newVector);
  566.     }
  567.  
  568.     /**
  569.      *  Insert a row at <i>row</i> in the model.  The new row will contain
  570.      *  <b>null</b> values unless <i>rowData</i> is specified.  Notification
  571.      *  of the row being added will be generated.  
  572.      *
  573.      * @param   row             the row index of the row to be inserted
  574.      * @param   rowData         optional data of the row being added
  575.      * @exception  ArrayIndexOutOfBoundsException  if the row was invalid.
  576.      */
  577.     public void insertRow(int row, Vector rowData) {
  578.         Vector newRow = rowData;
  579.  
  580.         if (newRow == null)
  581.             newRow = new Vector(numColumns);
  582.  
  583.         newRow.setSize(numColumns);
  584.         dataVector.insertElementAt(newRow, row);
  585.         numRows++;
  586.  
  587.         // Generate notification
  588.         newRowsAdded(new TableModelEvent(this, row, numRows-1, 
  589.                              TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  590.     }
  591.  
  592.     /**
  593.      *  Insert a row at <i>row</i> in the model.  The new row will contain
  594.      *  <b>null</b> values unless <i>rowData</i> is specified.  Notification
  595.      *  of the row being added will be generated.  
  596.      *
  597.      * @param   row      the row index of the row to be inserted
  598.      * @param   rowData          optional data of the row being added
  599.      * @exception  ArrayIndexOutOfBoundsException  if the row was invalid.
  600.      */
  601.     public void insertRow(int row, Object[] rowData) {
  602.         Vector newVector = null;
  603.  
  604.         if (rowData != null)
  605.             newVector = DefaultTableModel.convertToVector(rowData);
  606.  
  607.         this.insertRow(row, newVector);
  608.     }
  609.  
  610.     /**
  611.      *  Moves one or more rows starting at <i>startIndex</i> to <i>endIndex</i>
  612.      *  in the model to the <i>toIndex</i>.    This method will send a
  613.      *  tableChanged() notification message to all the listeners. <p>
  614.      *
  615.      *  Examples of moves:<p>
  616.      *  1. moveRow(1,3,5);<p>
  617.      *          a|B|C|D|e|f|g|h|i|j|k   - before
  618.      *          a|e|f|B|C|D|g|h|i|j|k   - after
  619.      *  2. moveRow(6,7,1);<p>
  620.      *          a|b|c|d|e|f|G|H|i|j|k   - before
  621.      *          a|G|H|b|c|d|e|f|i|j|k   - after
  622.      *
  623.      * @param   startIndex       the starting row index to be moved
  624.      * @param   endIndex         the ending row index to be moved
  625.      * @param   toIndex          the destination of the rows to be moved
  626.      * @exception  ArrayIndexOutOfBoundsException  if any of the indices are out of
  627.      *                           range.  Or if endIndex is less than startIndex.
  628.      */
  629.     public void moveRow(int startIndex, int endIndex, int toIndex) {
  630.         if ((startIndex < 0) || (startIndex >= numColumns))
  631.             throw new ArrayIndexOutOfBoundsException(startIndex);
  632.         if ((endIndex < 0) || (endIndex >= numColumns))
  633.             throw new ArrayIndexOutOfBoundsException(endIndex);
  634.         if (startIndex < endIndex)
  635.             throw new ArrayIndexOutOfBoundsException();
  636.             
  637.         if ((startIndex <= toIndex) && (toIndex <= endIndex))
  638.             return;                     // Nothing to move
  639.  
  640.         boolean shift = toIndex < startIndex;
  641.  
  642.         // Generate the proper event
  643.         TableModelEvent event = null;
  644.         if (shift) {
  645.             event = new TableModelEvent(this, toIndex, endIndex);
  646.         } else {
  647.             event = new TableModelEvent(this, startIndex, toIndex);
  648.         }
  649.  
  650.         // Do the move by first removing the row, then reinserting it
  651.         for (int i = startIndex; i <= endIndex; i++) {
  652.             Object aRow = dataVector.elementAt(i);
  653.             dataVector.removeElementAt(i);
  654.             dataVector.insertElementAt(aRow, toIndex);
  655.  
  656.             if (shift)
  657.                 toIndex++;
  658.         }
  659.  
  660.         // Generate notification
  661.         fireTableChanged(event);
  662.     }
  663.  
  664.     /**
  665.      *  Remove the row at <i>row</i> from the model.  Notification
  666.      *  of the row being removed, rowsRemoved(), will be sent to all
  667.      *  the listeners.
  668.      *
  669.      * @param   row      the row index of the row to be removed
  670.      * @exception  ArrayIndexOutOfBoundsException  if the row was invalid.
  671.      */
  672.     public void removeRow(int row) {
  673.         dataVector.removeElementAt(row);
  674.         numRows--;
  675.  
  676.         // Generate notification
  677.         rowsRemoved(new TableModelEvent(this, row, numRows-1, 
  678.                         TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE));
  679.     }
  680.  
  681. //
  682. // Implementing the TableModel interface
  683. //
  684.  
  685.     /**
  686.      * @return the number of rows in the model.
  687.      */
  688.     public int getRowCount() {
  689.         return numRows;
  690.     }
  691.  
  692.     /**
  693.      * @return the number of columns in the model.
  694.      */
  695.     public int getColumnCount() {
  696.         return numColumns;
  697.     }
  698.  
  699.     /**
  700.      * @return a name for this column using the string value of the 
  701.      * appropriate member in <I>columnIdentfiers</I>. If <I>columnIdentfiers</I>
  702.      * is null or does not have and entry for this index return the default 
  703.      * name provided by the superclass. 
  704.      */
  705.     public String getColumnName(int column) {
  706.         if (columnIdentifiers == null || columnIdentifiers.size() <= column) {
  707.             return super.getColumnName(column); 
  708.         } 
  709.         Object id = columnIdentifiers.elementAt(column);
  710.         if (id == null) { 
  711.             return super.getColumnName(column); 
  712.         } 
  713.         else {
  714.             return id.toString(); 
  715.         }
  716.     }
  717.  
  718.     /**
  719.      * Returns true if the cell at <I>row</I> and <I>column</I>
  720.      * is editable.  Otherwise, the setValueAt() on the cell will not change
  721.      * the value of that cell.
  722.      *
  723.      * @param   row             the row whose value is to be looked up
  724.      * @param   column          the column whose value is to be looked up
  725.      * @return                  true if the cell is editable.
  726.      * @see #setValueAt()
  727.      */
  728.     public boolean isCellEditable(int row, int column) {
  729.         return true;
  730.     }
  731.     
  732.     /**
  733.      * Returns an attribute value for the cell at <I>row</I>
  734.      * and <I>column</I>.
  735.      *
  736.      * @param   row             the row whose value is to be looked up
  737.      * @param   column          the column whose value is to be looked up
  738.      * @return                  the value Object at the specified cell
  739.      * @exception  ArrayIndexOutOfBoundsException  if an invalid row or
  740.      *               column was given.
  741.      */
  742.     public Object getValueAt(int row, int column) {
  743.         Vector rowVector = (Vector)dataVector.elementAt(row);
  744.         return rowVector.elementAt(column);
  745.     }
  746.                                     
  747.     /**
  748.      * Sets the object value for the cell at <I>column</I> and
  749.      * <I>row</I>.  <I>aValue</I> is the new value.  This method
  750.      * will generate a tableChanged() notification.  
  751.      * 
  752.      * @param   aValue          the new value.  This can be null.
  753.      * @param   row             the row whose value is to be changed
  754.      * @param   column          the column whose value is to be changed
  755.      * @exception  ArrayIndexOutOfBoundsException  if an invalid row or
  756.      *               column was given.
  757.      */
  758.     public void setValueAt(Object aValue, int row, int column) {
  759.         Vector rowVector = (Vector)dataVector.elementAt(row);
  760.         rowVector.setElementAt(aValue, column);
  761.  
  762.         // generate notification
  763.         fireTableChanged(new TableModelEvent(this, row, row, column));
  764.     }
  765.  
  766. //
  767. // Protected Methods
  768. //
  769.  
  770.     /** Returns a Vector that contains the same objects as the array */
  771.     protected static Vector convertToVector(Object[] anArray) {
  772.         if (anArray == null)
  773.             return new Vector();
  774.  
  775.         Vector v = new Vector(anArray.length);
  776.         for (int i=0; i < anArray.length; i++) {
  777.             v.addElement(anArray[i]);
  778.         }
  779.         return v;
  780.     }
  781.  
  782.     /** Returns a Vector of Vectors that contains the same objects as the array */
  783.     protected static Vector convertToVector(Object[][] anArray) {
  784.         if (anArray == null)
  785.             return new Vector();
  786.  
  787.         Vector v = new Vector(anArray.length);
  788.         for (int i=0; i < anArray.length; i++) {
  789.             v.addElement(DefaultTableModel.convertToVector(anArray[i]));
  790.         }
  791.         return v;
  792.     }
  793.  
  794. } // End of class DefaultTableModel
  795.