1 // ======================================================================== 2 // $Id: Table.java,v 1.3 2004/05/09 20:31:28 gregwilkins Exp $ 3 // Copyright 1996-2004 Mort Bay Consulting Pty. Ltd. 4 // ------------------------------------------------------------------------ 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // ======================================================================== 15 16 package org.mortbay.html; 17 import java.util.Hashtable; 18 19 /* --------------------------------------------------------------------- */ 20 /** A HTML Table element. 21 * <p> The Table Element works by calling newRow and then adding cells or 22 * headings. 23 * <p>Notes<br> 24 * Tables are implemented by nesting a cell Block within a row Block 25 * within the table which is also a Block (see nest() on class Composite). 26 * Once a row and cell have been created, calling add or attributes on 27 * the table actually calls the cell. 28 * 29 * @see org.mortbay.html.Element 30 */ 31 public class Table extends Block 32 { 33 /* ----------------------------------------------------------------- */ 34 private Block row = null; 35 private Block cell = null; 36 private static Hashtable threadNestingMap = null; 37 private CompositeFactory cellNestFactory = null; 38 private Block _defaultHead=null; 39 private Block _defaultCell=null; 40 private Block _defaultRow=null; 41 42 /* ----------------------------------------------------------------- */ 43 /** Construct Table. 44 */ 45 public Table() 46 { 47 super("table"); 48 if (threadNestingMap!=null) 49 cellNestFactory = (CompositeFactory) 50 threadNestingMap.get(Thread.currentThread()); 51 } 52 53 /* ----------------------------------------------------------------- */ 54 /** Construct Table. 55 */ 56 public Table(int border) 57 { 58 super("table"); 59 attribute("border",border); 60 if (threadNestingMap!=null) 61 cellNestFactory = (CompositeFactory) 62 threadNestingMap.get(Thread.currentThread()); 63 } 64 65 /* ----------------------------------------------------------------- */ 66 /** Construct Table with attributes. 67 */ 68 public Table(int border, String attributes) 69 { 70 this(border); 71 attribute(attributes); 72 } 73 74 /* ----------------------------------------------------------------- */ 75 /** Create new table row. 76 * Attributes set after this call and before a call to newCell or 77 * newHeader are considered row attributes. 78 */ 79 public Table newRow() 80 { 81 unnest(); 82 nest(row = new Block("tr")); 83 if (_defaultRow!=null) 84 { 85 row.setAttributesFrom(_defaultRow); 86 if (_defaultRow.size()>0) 87 row.add(_defaultRow.contents()); 88 } 89 cell=null; 90 return this; 91 } 92 93 /* ----------------------------------------------------------------- */ 94 /** Create new table row with attributes. 95 * Attributes set after this call and before a call to newCell or 96 * newHeader are considered row attributes. 97 */ 98 public Table newRow(String attributes) 99 { 100 newRow(); 101 row.attribute(attributes); 102 return this; 103 } 104 105 /* ----------------------------------------------------------------- */ 106 /* Create a new Cell in the current row. 107 * Adds to the table after this call and before next call to newRow, 108 * newCell or newHeader are added to the cell. 109 */ 110 private void newBlock(String m) 111 { 112 if (row==null) 113 newRow(); 114 else 115 row.unnest(); 116 row.nest(cell=new Block(m)); 117 118 if (cellNestFactory!=null) 119 cell.nest(cellNestFactory.newComposite()); 120 } 121 122 /* ----------------------------------------------------------------- */ 123 /* Create a new Cell in the current row. 124 * Adds to the table after this call and before next call to newRow, 125 * newCell or newHeader are added to the cell. 126 */ 127 public Table newCell() 128 { 129 newBlock("td"); 130 if (_defaultCell!=null) 131 { 132 cell.setAttributesFrom(_defaultCell); 133 if (_defaultCell.size()>0) 134 cell.add(_defaultCell.contents()); 135 } 136 return this; 137 } 138 139 /* ----------------------------------------------------------------- */ 140 /* Create a new Cell in the current row. 141 * Adds to the table after this call and before next call to newRow, 142 * newCell or newHeader are added to the cell. 143 * @return This table for call chaining 144 */ 145 public Table newCell(String attributes) 146 { 147 newCell(); 148 cell.attribute(attributes); 149 return this; 150 } 151 152 /* ----------------------------------------------------------------- */ 153 /* Add a new Cell in the current row. 154 * Adds to the table after this call and before next call to newRow, 155 * newCell or newHeader are added to the cell. 156 * @return This table for call chaining 157 */ 158 public Table addCell(Object o) 159 { 160 newCell(); 161 cell.add(o); 162 return this; 163 } 164 165 /* ----------------------------------------------------------------- */ 166 /* Add a new Cell in the current row. 167 * Adds to the table after this call and before next call to newRow, 168 * newCell or newHeader are added to the cell. 169 * @return This table for call chaining 170 */ 171 public Table addCell(Object o, String attributes) 172 { 173 addCell(o); 174 cell.attribute(attributes); 175 return this; 176 } 177 178 /* ----------------------------------------------------------------- */ 179 /* Create a new Heading in the current row. 180 * Adds to the table after this call and before next call to newRow, 181 * newCell or newHeader are added to the cell. 182 */ 183 public Table newHeading() 184 { 185 newBlock("th"); 186 if (_defaultHead!=null) 187 { 188 cell.setAttributesFrom(_defaultHead); 189 if (_defaultHead.size()>0) 190 cell.add(_defaultHead.contents()); 191 } 192 return this; 193 } 194 195 /* ----------------------------------------------------------------- */ 196 /* Add a new heading Cell in the current row. 197 * Adds to the table after this call and before next call to newRow, 198 * newCell or newHeader are added to the cell. 199 * @return This table for call chaining 200 */ 201 public Table addHeading(Object o) 202 { 203 newHeading(); 204 cell.add(o); 205 return this; 206 } 207 208 /* ----------------------------------------------------------------- */ 209 /* Add a new heading Cell in the current row. 210 * Adds to the table after this call and before next call to newRow, 211 * newCell or newHeader are added to the cell. 212 * @return This table for call chaining 213 */ 214 public Table addHeading(Object o,String attributes) 215 { 216 addHeading(o); 217 cell.attribute(attributes); 218 return this; 219 } 220 221 /* ------------------------------------------------------------ */ 222 /** Set the table cell spacing. 223 * @param s spacing in pixels 224 * @return This table for call chaining 225 */ 226 public Table cellSpacing(int s) 227 { 228 attribute("cellspacing",s); 229 return this; 230 } 231 232 233 /* ------------------------------------------------------------ */ 234 /** Set the table cell padding. 235 * @param padding the cell padding in pixels 236 * @return This table for call chaining 237 */ 238 public Table cellPadding(int padding) 239 { 240 attribute("cellpadding",padding); 241 return this; 242 } 243 244 /* ------------------------------------------------------------ */ 245 /** Set horizontal and vertical spacing. 246 * @param h horizontal spacing 247 * @param v vertical spacing 248 * @return This table for call chaining 249 */ 250 public Table spacing(int h, int v) 251 { 252 if (h>=0) 253 attribute("hspace",h); 254 if (v>=0) 255 attribute("vspace",v); 256 return this; 257 } 258 259 /* ----------------------------------------------------------------- */ 260 /** Get the current row Block element. 261 * Use this call for setting row attributes. 262 * @return The Block instance which has been nested in the table as 263 * the row 264 */ 265 public Block row() 266 { 267 return row; 268 } 269 270 /* ----------------------------------------------------------------- */ 271 /** Get the current cell Block element. 272 * Use this call for setting cell attributes. 273 * @return The Block instance which has been nested in the row as 274 * the cell 275 */ 276 public Block cell() 277 { 278 return cell; 279 } 280 281 /* ----------------------------------------------------------------- */ 282 /** Add cell nesting factory. 283 * Set the CompositeFactory for this thread. Each new cell in the 284 * table added by this thread will have a new Composite from this 285 * factory nested in the Cell. 286 * @param factory The factory for this Thread. If null clear this 287 * threads factory. 288 * @deprecated Use setNestingFactory or setThreadNestingFactory 289 */ 290 public static void setCellNestingFactory(CompositeFactory factory) 291 { 292 if (threadNestingMap==null) 293 threadNestingMap= new Hashtable(); 294 295 if (factory == null) 296 threadNestingMap.remove(Thread.currentThread()); 297 else 298 threadNestingMap.put(Thread.currentThread(),factory); 299 } 300 301 /* ----------------------------------------------------------------- */ 302 /** Add cell nesting factory for thread. 303 * Set the CompositeFactory for this thread. Each new cell in the 304 * table added by this thread will have a new Composite from this 305 * factory nested in the Cell. 306 * @param factory The factory for this Thread. If null clear this 307 * threads factory. 308 */ 309 public static void setThreadNestingFactory(CompositeFactory factory) 310 { 311 if (threadNestingMap==null) 312 threadNestingMap= new Hashtable(); 313 314 if (factory == null) 315 threadNestingMap.remove(Thread.currentThread()); 316 else 317 threadNestingMap.put(Thread.currentThread(),factory); 318 } 319 320 /* ----------------------------------------------------------------- */ 321 /** Add cell nesting factory for table. 322 * Set the CompositeFactory for this thread. Each new cell in the 323 * table added by this thread will have a new Composite from this 324 * factory nested in the Cell. 325 * @param factory The factory for this Thread. If null clear this 326 * threads factory. 327 */ 328 public void setNestingFactory(CompositeFactory factory) 329 { 330 cellNestFactory = factory; 331 } 332 333 334 /* ------------------------------------------------------------ */ 335 /** Access the default row template. 336 * The Block returned is used as a template for all new rows added 337 * to the table. Thus if attributes or content are added to the 338 * default row, the these are added to each new row in the table. 339 * @return The default row template 340 */ 341 public Block defaultRow() 342 { 343 if (_defaultRow==null) 344 _defaultRow=new Block("tr"); 345 return _defaultRow; 346 } 347 348 /* ------------------------------------------------------------ */ 349 /** Access the default header cell template. 350 * The Block returned is used as a template for all new header cells added 351 * to the table. Thus if attributes or content are added to the 352 * default cell, the these are added to each new cell in the table. 353 * @return The default head cell template 354 */ 355 public Block defaultHead() 356 { 357 if (_defaultHead==null) 358 _defaultHead=new Block("th"); 359 return _defaultHead; 360 } 361 362 /* ------------------------------------------------------------ */ 363 /** Access the default cell template. 364 * The Block returned is used as a template for all new cells added 365 * to the table. Thus if attributes or content are added to the 366 * default cell, the these are added to each new cell in the table. 367 * @return The default cell template 368 */ 369 public Block defaultCell() 370 { 371 if (_defaultCell==null) 372 _defaultCell=new Block("td"); 373 return _defaultCell; 374 } 375 } 376 377 378 379 380 381 382 383