001    package edu.nrao.sss.html;
002    
003    import java.io.IOException;
004    import java.io.Writer;
005    import java.util.ArrayList;
006    import java.util.List;
007    
008    import javax.swing.text.html.HTML;
009    
010    /**
011     * A row in an HTML table.
012     * <p>
013     * <b>Version Info:</b>
014     * <table style="margin-left:2em">
015     *   <tr><td>$Revision: 483 $</td></tr>
016     *   <tr><td>$Date: 2007-03-23 16:48:30 -0600 (Fri, 23 Mar 2007) $</td></tr>
017     *   <tr><td>$Author: dharland $</td></tr>
018     * </table></p>
019     * 
020     * @author David M. Harland
021     * @since 2007-03-15
022     */
023    public class HtmlTableRow
024      extends HtmlElement
025    {
026      Type                type;
027      HtmlTable           parentTable; //Not publicly mutable
028      List<HtmlTableCell> cells;       //Publicly mutable, not publicly settable
029      
030      /** Creates a new data row. */
031      public HtmlTableRow()
032      {
033        this(Type.DATA);
034      }
035      
036      /**
037       * Creates a new row of the given type.
038       * 
039       * @param rowType the type of this row, either header, data, or footer.
040       *                If this value is <i>null</i>, this row will
041       *                be a data row.
042       */
043      public HtmlTableRow(Type rowType)
044      {
045        super(HTML.Tag.TR);
046        
047        setType(rowType); //tag c/b reset here
048        
049        parentTable = null;
050        cells       = new ArrayList<HtmlTableCell>();
051      }
052      
053      /** Returns <i>false</i>. */
054      @Override
055      public boolean isSimple()  { return false; }
056      
057      /**
058       * Returns the table to which this row belongs.
059       * 
060       * @return the table to which this row belongs.
061       *         If this row does not belong to a table, the returned
062       *         value will be <i>null</i>.
063       */
064      public HtmlTable getParentTable()
065      {
066        return parentTable;
067      }
068      
069      /**
070       * Returns the position of this row in its table.
071       * The first position is zero.
072       * 
073       * @return the position of this row in its table.
074       *         If this row is not part of a table, the
075       *         value returned is -1.
076       */
077      public int getPositionInTable()
078      {
079        return (parentTable == null) ? -1 : parentTable.rows.indexOf(this);
080      }
081      
082      /**
083       * Sets the type of this row.
084       * 
085       * @param newType the type of this row.  If this value is <i>null</i>,
086       *                this cell will be set to a data row.
087       */
088      public void setType(Type newType)
089      {
090        type = (newType == null) ? Type.DATA : newType;
091      }
092      
093      /**
094       * Returns the type of this row.
095       * @return the type of this row.
096       */
097      public Type getType()
098      {
099        return type;
100      }
101    
102      //============================================================================
103      // CELLS
104      //============================================================================
105    
106      //TODO addCell(index, newCell) and other "listy" methods?
107      
108      /**
109       * Adds {@code newCell} to this row.
110       * <p>
111       * If the new cell is <i>null</i> or already in this row,
112       * this method does nothing.  Otherwise the new cell is
113       * removed from its previous row, if any, and added to this
114       * one.  The new cell's parent row is set to this one.</p>
115       * 
116       * @param newCell a new cell for this row.
117       */
118      public void addCell(HtmlTableCell newCell)
119      {
120        //Nothing to do if new cell is null or already in this row
121        if ((newCell != null) && (newCell.parentRow != this))
122        {
123          if (newCell.parentRow != null)
124            newCell.parentRow.removeCell(newCell);
125          
126          cells.add(newCell);
127          
128          newCell.parentRow = this;
129        }
130      }
131      
132      /**
133       * Removes {@code unwantedCell} from this row.
134       * <p>
135       * If the unwanted cell is <i>null</i> or not part of this
136       * row, this method does nothing.  Otherwise the unwanted cell
137       * is removed from this row, and its parent row is set to <i>null</i>.</p>
138       * 
139       * @param unwantedCell the cell to be removed from this row.
140       * 
141       * @return <i>true</i> if {@code unwantedCell} was removed from this row.
142       */
143      public boolean removeCell(HtmlTableCell unwantedCell)
144      {
145        boolean removed;
146        
147        if ((unwantedCell != null) && cells.contains(unwantedCell))
148        {
149          removed = cells.remove(unwantedCell);
150          
151          unwantedCell.parentRow = null;
152        }
153        else //cell was not in this row
154        {
155          removed = false;
156        }
157        
158        return removed;
159      }
160      
161      /**
162       * Removes the cell at {@code index} from this row.
163       * @param index the index of the unwanted cell.
164       * @return the cell formerly at {@code index}.
165       */
166      public HtmlTableCell removeCell(int index)
167      {
168        return cells.remove(index);
169      }
170      
171      /**
172       * Returns a copy of this row's list of cells.
173       * <p>
174       * While the list is a copy, the cells in the returned list are
175       * the actual cells held in this row.</p>
176       * 
177       * @return a copy of this row's list of cells.
178       */
179      public List<HtmlTableCell> getCells()
180      {
181        return new ArrayList<HtmlTableCell>(cells);
182      }
183      
184      /**
185       * Returns the number of cells in this row.
186       * The returned value does <i>not</i> consider how many columns a
187       * cell spans.
188       * 
189       * @return the number of cells in this row.
190       */
191      public int size()
192      {
193        return cells.size();
194      }
195      
196      //============================================================================
197      // WRITING
198      //============================================================================
199      
200      @Override
201      void writeContentsAsHtml(Writer device, int padding, int depth) throws IOException
202      {
203        //New line after <tr name=...> tag
204        device.write(System.getProperty("line.separator"));
205        
206        for (HtmlTableCell cell : cells)
207          cell.writeHtmlTo(device, padding, depth+1, true);
208        
209        //Padding before </tr> tag
210        device.write(getPadding(padding, depth));
211      }
212    
213      //============================================================================
214      // 
215      //============================================================================
216      
217      /** Types of table rows. */
218      public enum Type
219      {
220        /** A row in the &lt;thead&gt; section of a table. */
221        HEADER,
222        
223        /**
224         * A row in the &lt;tbody&gt; section of a table, or one that is
225         * held directly by (i.e., not in a &lt;thead&gt;, &lt;tbody&gt;, or
226         * &lt;tfoot&gt; section of) a table. 
227         */
228        DATA,
229        
230        /** A row in the &lt;tfoot&gt; section of a table. */
231        FOOTER;
232      }
233    }