KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > joshy > html > TableLayout


1 package org.joshy.html;
2
3
4 //import java.awt.Color;
5
//import java.util.ArrayList;
6
//import java.util.List;
7
//import org.joshy.html.box.BlockBox;
8
import java.awt.Point JavaDoc;
9 import java.awt.Rectangle JavaDoc;
10
11 import org.joshy.html.box.*;
12 import org.joshy.html.util.*;
13
14 import org.joshy.u;
15 import org.joshy.x;
16
17 import org.w3c.dom.Element JavaDoc;
18 import org.w3c.dom.Node JavaDoc;
19 import org.w3c.dom.NodeList JavaDoc;
20
21
22 /*
23 joshy:
24     new features to add
25     columns to specify width
26     first row of cells to specify width
27     //calculate height
28     //draw margins, border, padding of outside table
29     //draw borders and padding and background of inside cells
30     //make cells fill their width
31     
32     do inner cell vertical and horizontal alignment
33     implement spanned cells
34     
35     include these boxes in the redesign of the overall layout flow
36
37 */

38
39 /**
40     TableLayout performs the layout and painting of an XHTML Table
41     on screen. It makes use of the TableBox and CellBox classes in the
42     box package. It currently implements only the fixed layout algorithm,
43     meaning width must be explictly set on the table or the columns. Width
44     will not be calculated by the size of the contents of each cell. That
45     will be implemented later.
46 */

47
48 public class TableLayout
49     extends BoxLayout {
50
51     private static final int fudge = 0; // is this used anymore?
52

53     public Box createBox(Context c, Node JavaDoc node) {
54
55         Box box = new TableBox(0, 0, 0, 0);
56         box.node = node;
57
58         return box;
59     }
60
61     
62     
63     
64     /** this is the core layout code of the table. it should be
65     heavily overhauled.*/

66     public Box layout(Context c, Element JavaDoc elem) {
67
68         TableBox table = (TableBox)createBox(c, elem);
69         
70         // calculate the available space
71
getMargin(c, table);
72         getPadding(c, table);
73         getBorder(c, table);
74         float border_spacing = c.css.getFloatProperty(elem, "border-spacing");
75         table.spacing = new Point JavaDoc((int)border_spacing, (int)border_spacing);
76         //input available width
77
//int fixed_width = (int) c.css.getFloatProperty(elem,"width");
78
int fixed_width = c.getExtents().width;
79
80         //u.p("initial fixed width = " + fixed_width);
81
int orig_fixed_width = fixed_width;
82         fixed_width -= table.margin.left + table.border.left + table.padding.left +
83             table.spacing.x + table.padding.right + table.border.right + table.margin.right;
84
85         //u.p("fixed width = " + fixed_width);
86
int col_count = getColumnCount(elem);
87
88         //u.p("col count = " + col_count);
89
int[] col_widths = new int[col_count];
90
91         // initalize them all to -1
92
for (int i = 0; i < col_count; i++) {
93             col_widths[i] = -1;
94         }
95
96         //leftover space = table.width - sum(columns.widths)
97
int leftover_width = (int)fixed_width - 0;
98
99         // calculate how wide each column should be and return the total
100
leftover_width -= calculateColumnWidths(c,elem,col_widths);
101
102         // distribute the remaining space to the unset columns
103
distributeRemainingColumnWidth(c,col_widths,leftover_width,table);
104
105         //table.width = max(table.width, sum(columns.widths))
106
table.width = fixed_width;
107             
108         layoutTableRows(c, table, elem, col_widths, orig_fixed_width);
109         return table;
110     }
111     
112     protected int calculateColumnWidths(Context c, Element JavaDoc elem, int[] col_widths) {
113         int total_width = 0;
114         
115         Element JavaDoc tr = x.child(elem, "tr");
116         NodeList JavaDoc nl = elem.getChildNodes();
117
118         //NodeList nl = x.children(tr,"td");
119
int count = 0;
120
121         for (int i = 0; i < nl.getLength(); i++) {
122
123             if (nl.item(i).getNodeName().equals("td") ||
124                 nl.item(i).getNodeName().equals("th")) {
125
126                 Element JavaDoc td = (Element JavaDoc)nl.item(i);
127                 u.p("got td: " + td + " " + i + " count = " + count);
128
129                 //if(cell.width)
130
if (c.css.hasProperty(td, "width", false)) {
131
132                     //save column.width;
133
if (count > col_widths.length) {
134                         u.p("elem = ");
135
136                         //x.p(elem);
137
}
138
139                     col_widths[count] = (int)c.css.getFloatProperty(td,
140                                                                     "width");
141                     
142                     total_width += col_widths[count];
143                 }
144
145                 count++;
146             }
147         }
148         return total_width;
149     }
150
151     public void distributeRemainingColumnWidth(Context c, int[]col_widths, int leftover_width, TableBox table) {
152         
153         // count the remaining unset columns
154
int unset_count = 0;
155
156         for (int i = 0; i < col_widths.length; i++) {
157
158             if (col_widths[i] == -1) {
159                 unset_count++;
160             }
161         }
162
163         //if(leftover space > 0) {
164
if (leftover_width > 0) {
165
166             //distribute leftover space to columns
167
for (int i = 0; i < col_widths.length; i++) {
168
169                 // set width only if it's not already set
170
if (col_widths[i] == -1) {
171                     col_widths[i] = (leftover_width -
172                                     table.spacing.x * col_widths.length) / unset_count;
173                 }
174             }
175         }
176     }
177     
178     protected void layoutTableRows(Context c, TableBox table, Element JavaDoc elem, int[] col_widths, int orig_fixed_width) {
179         
180         // create dummy previous row
181
RowBox prev_row = new RowBox(0, 0, 0, 0);
182         prev_row.y = table.margin.top + table.border.top +
183                      table.padding.top - fudge;
184
185         // loop through all of the table rows
186
NodeList JavaDoc rows = elem.getChildNodes();
187         for (int i = 0; i < rows.getLength(); i++) {
188             Node JavaDoc row = rows.item(i);
189             if (row.getNodeName().equals("tr")) {
190
191                 prev_row = layoutRow(c,row,prev_row,table,col_widths);
192             }
193         }
194         
195         
196         table.height = prev_row.y + prev_row.height + table.spacing.y +
197                        table.padding.bottom + table.border.bottom +
198                        table.margin.bottom;
199         table.width = orig_fixed_width;
200     }
201     
202     
203     public RowBox layoutRow(Context c, Node JavaDoc row, RowBox prev_row, TableBox table, int[] col_widths) {
204         // create a new rowbox
205
RowBox rowbox = new RowBox(0, 0, 0, 0);
206         rowbox.node = row;
207
208         // create dummy previous cell
209
CellBox prev_cell = new CellBox(0, 0, 0, 0);
210         
211         // loop through all of the cells in the current row
212
NodeList JavaDoc cells = row.getChildNodes();
213         int col_counter = 0;
214         for (int j = 0; j < cells.getLength(); j++) {
215             Node JavaDoc cell = cells.item(j);
216             if (cell.getNodeName().equals("td") ||
217                 cell.getNodeName().equals("th")) {
218                 
219                 // if there are too many cells on this line then skip the rest
220
if (col_counter >= col_widths.length) {
221                     u.p("WARNING: too many cells on this row");
222                     continue;
223                 }
224
225                 prev_cell = layoutCell(c, cell, prev_cell, rowbox, table, col_widths[col_counter]);
226
227                 //u.p("col counter = " + col_counter);
228
col_counter++;
229
230                 //u.p("now its: " + col_counter);
231
}
232         }
233
234         // x is always 0 (rel to the parent table)
235
rowbox.x = +table.margin.left + table.border.left +
236                    table.padding.left;
237
238         // y is prev row.y + prev row.height
239
rowbox.y = prev_row.y + prev_row.height + table.spacing.y +
240                    fudge;
241
242         // width is width of table
243
rowbox.width = table.width;
244
245         // set the heights on all of the cells
246
for (int k = 0; k < rowbox.cells.size(); k++) {
247             ((CellBox)rowbox.cells.get(k)).height = rowbox.height;
248         }
249
250         table.rows.add(rowbox);
251
252         //u.p("row = " + rowbox);
253
return rowbox;
254     }
255     
256     public CellBox layoutCell(Context c, Node JavaDoc cell, CellBox prev_cell, RowBox rowbox, TableBox table, int cellwidth) {
257         CellBox cellbox = new CellBox(0, 0, cellwidth, 0);
258         
259         // attach the node
260
cellbox.node = cell;
261         getBorder(c, cellbox);
262         getMargin(c, cellbox);
263         getPadding(c, cellbox);
264
265         //layout cell w/ modified inline
266
cellbox.x = prev_cell.x + prev_cell.width +
267                     table.spacing.x + fudge;
268
269         // y is 0 relative to the parent row
270
cellbox.y = 0;
271
272         // set height to 50 until it's set by the cell contents
273
cellbox.height = 50;
274
275         Rectangle JavaDoc oe = c.getExtents();
276
277         // new extents = old extents but smaller. same origin tho
278
c.setExtents(new Rectangle JavaDoc(c.getExtents().x,
279                                    c.getExtents().y,
280                                    cellbox.width, 100));
281
282         // lay out the cell's contents
283
Layout layout = LayoutFactory.getLayout(cell);
284         Box cell_contents = layout.layout(c, (Element JavaDoc)cellbox.node);
285         cellbox.sub_box = cell_contents;
286
287         // restore old extents
288
c.setExtents(oe);
289
290         // height of the cell will be based on the height of it's
291
// contents
292
cellbox.height = cell_contents.height;
293
294         //save cellbox
295
// height of row is max height of cells
296
rowbox.height = Math.max(cellbox.height, rowbox.height);
297         rowbox.cells.add(cellbox);
298
299         return cellbox;
300     }
301     
302     
303     /* =========== painting code ============= */
304     /** The entry point to the painting routines. It takes the
305     table box to be painted and the current context. It will call
306     paintBackground(), paintComponent(), and paintBorder() on it's
307     own. */

308     public void paint(Context c, Box box) {
309
310         //u.p("TableLayout.paint( " + c);
311
// copy the bounds to we don't mess it up
312
Rectangle JavaDoc oldBounds = new Rectangle JavaDoc(c.getExtents());
313
314         //Rectangle contents = layout(c,elem);
315
//adjustWidth(c,elem);
316
paintBackground(c, box);
317         paintComponent(c, box);
318
319         //paintChildren(c,elem);
320
paintBorder(c, box);
321
322         // move the origin down to account for the contents plus the margin, borders, and padding
323
oldBounds.y = oldBounds.y + box.height;
324         c.setExtents(oldBounds);
325     }
326
327     public void paintComponent(Context c, Box box) {
328         paintTable(c, (TableBox)box);
329     }
330
331     public void paintChildren(Context c, Box box) {
332     }
333
334     protected void paintTable(Context c, TableBox table) {
335         c.getGraphics().translate(table.x, table.y);
336         c.getGraphics().translate(
337                 table.margin.left + table.border.left + table.padding.left,
338                 table.margin.top + table.border.top + table.padding.top);
339
340         // loop over the rows
341
for (int i = 0; i < table.rows.size(); i++) {
342
343             RowBox row = (RowBox)table.rows.get(i);
344
345             // save the old extents
346
Rectangle JavaDoc oe = c.getExtents();
347
348             // move origin by row.x and row.y
349
c.setExtents(new Rectangle JavaDoc(oe.x + row.x, oe.y + row.y, oe.width,
350                                        oe.height));
351             c.getGraphics().translate(row.x, row.y);
352
353             // paint the row
354
paintRow(c, row);
355
356             // restore the old extents and translate
357
c.getGraphics().translate(-row.x, -row.y);
358             c.setExtents(oe);
359         }
360
361         c.getGraphics().translate(
362                 -table.margin.left - table.border.left - table.padding.left,
363                 -table.margin.top - table.border.top - table.padding.top);
364         c.getGraphics().translate(-table.x, -table.y);
365
366         //c.getGraphics().translate(-c.getExtents().x, -c.getExtents().y);
367
}
368
369     protected void paintRow(Context c, RowBox row) {
370
371         //u.p("Paint Row c = " + c);
372
//u.p("paint row = " + row);
373
// debug
374
for (int i = 0; i < row.cells.size(); i++) {
375
376             CellBox cell = (CellBox)row.cells.get(i);
377             Rectangle JavaDoc oe = c.getExtents();
378             c.setExtents(new Rectangle JavaDoc(cell.x, cell.y, oe.width, oe.height));
379             paintCell(c, cell);
380             c.setExtents(oe);
381         }
382     }
383
384     protected void paintCell(Context c, CellBox cell) {
385         if(cell.isReal()) {
386             Rectangle JavaDoc oe = c.getExtents();
387             c.getGraphics().translate(oe.x, oe.y);
388             c.setExtents(new Rectangle JavaDoc(0, 0, cell.width, cell.height));
389     
390             Layout layout = LayoutFactory.getLayout(cell.node);
391             u.p("doing cell: " + cell);
392             layout.paint(c, cell.sub_box);
393     
394             c.getGraphics().translate(-oe.x, -oe.y);
395             c.setExtents(oe);
396     
397         }
398     }
399
400     
401     
402     
403     
404     
405     
406     /* =============== utility code ================ */
407     private int getColumnCount(Element JavaDoc tb) {
408
409         int count = 0;
410         NodeList JavaDoc nl = tb.getChildNodes();
411
412         for (int i = 0; i < nl.getLength(); i++) {
413
414             Node JavaDoc row = nl.item(i);
415
416             if (row.getNodeName().equals("tr")) {
417
418                 NodeList JavaDoc cells = row.getChildNodes();
419
420                 for (int j = 0; j < cells.getLength(); j++) {
421
422                     Node JavaDoc cell = cells.item(j);
423
424                     if (cell.getNodeName().equals("td") ||
425                         cell.getNodeName().equals("th")) {
426                         count++;
427                     }
428                 }
429
430                 // return now since we only go through the first row
431
return count;
432             }
433         }
434
435         return count;
436     }
437 }
438
Popular Tags