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