Initialize
[sdk/ide/product.git] / org.eclipse.jst.pagedesigner / src / org / eclipse / jst / pagedesigner / css2 / layout / table / CSSTableLayout2.java
1 /*******************************************************************************\r
2  * Copyright (c) 2006 Sybase, Inc. and others.\r
3  *\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     Sybase, Inc. - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.eclipse.jst.pagedesigner.css2.layout.table;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.List;\r
16 \r
17 import org.eclipse.draw2d.ColorConstants;\r
18 import org.eclipse.draw2d.Graphics;\r
19 import org.eclipse.draw2d.IFigure;\r
20 import org.eclipse.draw2d.geometry.Dimension;\r
21 import org.eclipse.draw2d.geometry.Insets;\r
22 import org.eclipse.draw2d.geometry.Rectangle;\r
23 import org.eclipse.jst.jsf.common.ui.internal.logging.Logger;\r
24 import org.eclipse.jst.pagedesigner.PDPlugin;\r
25 import org.eclipse.jst.pagedesigner.css2.ICSSStyle;\r
26 import org.eclipse.jst.pagedesigner.css2.layout.CSSBlockFlowLayout;\r
27 import org.eclipse.jst.pagedesigner.css2.layout.CSSFigure;\r
28 import org.eclipse.jst.pagedesigner.css2.layout.ICSSPainter;\r
29 import org.eclipse.jst.pagedesigner.css2.property.ICSSPropertyID;\r
30 import org.eclipse.jst.pagedesigner.css2.style.ITagEditInfo;\r
31 import org.eclipse.swt.SWT;\r
32 \r
33 /**\r
34  * see also http://www.w3.org/TR/REC-CSS2/tables.html\r
35  * \r
36  * @author mengbo\r
37  * @version 1.5\r
38  */\r
39 public class CSSTableLayout2 extends CSSBlockFlowLayout implements ICSSPainter {\r
40         static Logger _log = PDPlugin.getLogger(CSSTableLayout2.class);\r
41 \r
42         int _hspacing;\r
43 \r
44         int _vspacing;\r
45 \r
46         int[] _columnWidths;\r
47 \r
48         int[] _rowHeights;\r
49 \r
50         Dimension _captionSize;\r
51 \r
52         // _tableInfo will be initialized in preLayout\r
53         TableInfo _tableInfo;\r
54 \r
55         private int _internalTableWidth;\r
56 \r
57         private int _internalTableHeight;\r
58 \r
59         private int _rowx;\r
60 \r
61         private int _rowwidth;\r
62 \r
63         /**\r
64          * @param flowfigure\r
65          */\r
66         public CSSTableLayout2(CSSFigure flowfigure) {\r
67                 super(flowfigure);\r
68         }\r
69 \r
70         /*\r
71          * (non-Javadoc)\r
72          * \r
73          * @see org.eclipse.jst.pagedesigner.css2.layout.CSSBlockFlowLayout#preLayout()\r
74          */\r
75         protected void preLayout() {\r
76                 // super.preLayout will setup the block box.\r
77                 super.preLayout();\r
78 \r
79                 ICSSStyle style = this.getCSSStyle();\r
80 \r
81                 _hspacing = _vspacing = 3; // default value\r
82 \r
83                 if (style != null) {\r
84                         Object borderspacing = style\r
85                                         .getStyleProperty(ICSSPropertyID.ATTR_BORDER_SPACING);\r
86                         if (borderspacing instanceof int[]) {\r
87                                 int[] intvalues = (int[]) borderspacing;\r
88                                 _hspacing = intvalues[0];\r
89                                 _vspacing = intvalues[1];\r
90                         } else {\r
91                                 ITagEditInfo info = (ITagEditInfo) style\r
92                                                 .getAdapter(ITagEditInfo.class);\r
93                                 if (info != null && info.needTableDecorator()) {\r
94                                         // default decorating value. to make things look more\r
95                                         // separated.\r
96                                         if (_hspacing < 5) {\r
97                                                 _hspacing = 5;\r
98                                         }\r
99                                         if (_vspacing < 5) {\r
100                                                 _vspacing = 5;\r
101                                         }\r
102                                 }\r
103                         }\r
104                 }\r
105 \r
106                 // TODO: support caption\r
107                 _tableInfo = new TableInfo(getCSSFigure());\r
108 \r
109                 // construct the table structure.\r
110                 _tableInfo.constructTable();\r
111 \r
112                 // calculate the user specified width/height for table and cells.\r
113                 // contentWidth is the user specified content width. If <= 0 means no\r
114                 // user\r
115                 // specification.\r
116                 int contentWidth = this._blockBox.getContentWidth();\r
117                 int availableWidth = this._blockBox.getRecommendedContentWidth();\r
118                 int contentHeight = this._blockBox.getContentHeight();\r
119 \r
120                 _tableInfo.calculateWidth(contentWidth, availableWidth);\r
121                 _tableInfo.calculateHeight(contentHeight);\r
122 \r
123                 int columnCount = _tableInfo.getColumnCount();\r
124 \r
125                 int columnMinWidths[] = new int[columnCount];\r
126                 int columnMaxWidths[] = new int[columnCount];\r
127 \r
128                 // For each column, determine a maximum and minimum column width from\r
129                 // the cells that span only that column. The minimum is that required by\r
130                 // the cell with the largest minimum cell width (or the column 'width',\r
131                 // whichever is larger). The maximum is that required by the cell with\r
132                 // the\r
133                 // largest maximum cell width (or the column 'width', whichever is\r
134                 // larger).\r
135                 List cells = _tableInfo.getCells();\r
136                 for (int i = 0, size = cells.size(); i < size; i++) {\r
137                         TableCellInfo cellinfo = (TableCellInfo) cells.get(i);\r
138                         if (cellinfo.getColSpan() == 1) {\r
139                                 int column = cellinfo.getColumnIndex();\r
140                                 Dimension mincw = cellinfo.getMinCWDimension();\r
141                                 Dimension maxcw = cellinfo.getMaxCWDimension();\r
142                                 if (maxcw.width < mincw.width) {\r
143                                         maxcw.width = mincw.width;\r
144                                 }\r
145                                 if (mincw.width > columnMinWidths[column]) {\r
146                                         columnMinWidths[column] = mincw.width;\r
147                                 }\r
148                                 if (maxcw.width > columnMaxWidths[column]) {\r
149                                         columnMaxWidths[column] = maxcw.width;\r
150                                 }\r
151                         }\r
152                 }\r
153                 // For caption, determine a maximum and minimum width from it.\r
154                 int captionWidth = 0;\r
155                 if (_tableInfo.getCaption() != null) {\r
156                         captionWidth = _tableInfo.getCaption().getDimension().width;\r
157                 }\r
158 \r
159                 // For each cell that spans more than one column, increase the\r
160                 // minimum widths of the columns it spans so that together, they\r
161                 // are at least as wide as the cell. Do the same for the maximum\r
162                 // widths. If possible, widen all spanned columns by approximately\r
163                 // the same amount.\r
164                 for (int i = 0, size = cells.size(); i < size; i++) {\r
165                         TableCellInfo cellinfo = (TableCellInfo) cells.get(i);\r
166                         int colspan = cellinfo.getColSpan();\r
167                         if (colspan > 1) {\r
168                                 int column = cellinfo.getColumnIndex();\r
169                                 Dimension mincw = cellinfo.getMinCWDimension();\r
170                                 Dimension maxcw = cellinfo.getMaxCWDimension();\r
171 \r
172                                 adjustWidth(column, colspan, mincw.width, columnMinWidths);\r
173                                 adjustWidth(column, colspan, maxcw.width, columnMaxWidths);\r
174                         }\r
175                 }\r
176 \r
177                 int sigmaMinWidth = 0;\r
178                 int sigmaMaxWidth = 0;\r
179                 for (int i = 0; i < columnMinWidths.length; i++) {\r
180                         sigmaMinWidth += columnMinWidths[i];\r
181                         if (columnMaxWidths[i] == Integer.MAX_VALUE) {\r
182                                 sigmaMaxWidth = Integer.MAX_VALUE;\r
183                         } else if (sigmaMaxWidth != Integer.MAX_VALUE) {\r
184                                 sigmaMaxWidth += columnMaxWidths[i];\r
185                                 if (sigmaMaxWidth < 0) {\r
186                                         sigmaMaxWidth = Integer.MAX_VALUE;\r
187                                 }\r
188                         }\r
189                 }\r
190                 int spacingall = (columnMinWidths.length + 1) * _hspacing;\r
191                 sigmaMinWidth += spacingall;\r
192                 if (sigmaMaxWidth != Integer.MAX_VALUE) {\r
193                         sigmaMaxWidth += spacingall;\r
194                         if (sigmaMaxWidth < 0) {\r
195                                 sigmaMaxWidth = Integer.MAX_VALUE;\r
196                         }\r
197                 }\r
198 \r
199                 int tableWidth = _tableInfo.getTableWidth();\r
200                 if (tableWidth > 0) {\r
201                         // If the 'table' or 'inline-table' element's 'width' property has a\r
202                         // specified value (W) other than 'auto', the property's computed\r
203                         // value\r
204                         // is the greater of W and the minimum width required by all the\r
205                         // columns\r
206                         // plus cell spacing or borders (MIN). If W is greater than MIN, the\r
207                         // extra\r
208                         // width should be distributed over the columns.\r
209                         int maxMin = Math.max(captionWidth, sigmaMinWidth);\r
210                         if (maxMin >= tableWidth) {\r
211                                 tableWidth = maxMin;\r
212                         }\r
213                         distribute(tableWidth - sigmaMinWidth, columnMinWidths,\r
214                                         columnMaxWidths);\r
215                 } else {\r
216                         // If the 'table' or 'inline-table' element has 'width: auto', the\r
217                         // computed\r
218                         // table width is the greater of the table's containing block width\r
219                         // and MIN.\r
220                         // However, if the maximum width required by the columns plus cell\r
221                         // spacing or\r
222                         // borders (MAX) is less than that of the containing block, use MAX.\r
223                         // int availableWidth = this.getCurrentLine().getAvailableWidth();\r
224                         int maxMin = Math.max(captionWidth, sigmaMaxWidth);\r
225                         if (maxMin <= availableWidth) {\r
226                                 // TODO: if _tableInfo.hasWidthPercentage, then we need take\r
227                                 // that into consideration\r
228                                 // to distribute the column width. Left to next version.\r
229                                 tableWidth = maxMin;\r
230                                 // columnMinWidths = columnMaxWidths;\r
231                         } else {\r
232                                 tableWidth = availableWidth;\r
233                         }\r
234                         distribute(tableWidth - sigmaMinWidth, columnMinWidths,\r
235                                         columnMaxWidths);\r
236                 }\r
237 \r
238                 // now columnMinWidths contains width for each column\r
239                 _columnWidths = columnMinWidths;\r
240 \r
241                 // ok, we have finished calculating column width.\r
242                 // next we need to find out row heights.\r
243                 _rowHeights = new int[_tableInfo.getRowCount()];\r
244 \r
245                 // first find out those TR that has height settings and use them.\r
246                 List rows = _tableInfo.getRows();\r
247                 for (int i = 0, size = rows.size(); i < size && i < _rowHeights.length; i++) {\r
248                         TableRowInfo rowInfo = (TableRowInfo) rows.get(i);\r
249                         if (rowInfo.getSpecifiedRowHeight() > 0) {\r
250                                 _rowHeights[i] = rowInfo.getSpecifiedRowHeight();\r
251                         }\r
252                 }\r
253 \r
254                 // First the cells don't span multiple rows.\r
255                 cells = _tableInfo.getCells();\r
256                 for (int i = 0, size = cells.size(); i < size; i++) {\r
257                         TableCellInfo cellinfo = (TableCellInfo) cells.get(i);\r
258                         IFigure figure = cellinfo.getFigure();\r
259                         int rowspan = cellinfo.getRowSpan();\r
260                         if (rowspan == 1) {\r
261                                 int cellWidth = getCellWidth(cellinfo, _columnWidths);\r
262                                 Dimension d = figure.getPreferredSize(cellWidth, cellinfo\r
263                                                 .getHeight());\r
264                                 if (d.height > _rowHeights[cellinfo.getRowIndex()]) {\r
265                                         _rowHeights[cellinfo.getRowIndex()] = d.height;\r
266                                 }\r
267                         }\r
268                 }\r
269 \r
270                 // Next those cells span multiple rows.\r
271                 cells = _tableInfo.getCells();\r
272                 for (int i = 0, size = cells.size(); i < size; i++) {\r
273                         TableCellInfo cellinfo = (TableCellInfo) cells.get(i);\r
274                         IFigure figure = cellinfo.getFigure();\r
275                         int rowspan = cellinfo.getRowSpan();\r
276                         if (rowspan > 1) {\r
277                                 int cellWidth = getCellWidth(cellinfo, _columnWidths);\r
278                                 Dimension d = figure.getPreferredSize(cellWidth, cellinfo\r
279                                                 .getHeight());\r
280                                 if (d.height > getCellHeight(cellinfo, _rowHeights)) {\r
281                                         adjustHeight(cellinfo.getRowIndex(), rowspan, d.height,\r
282                                                         _rowHeights);\r
283                                 }\r
284                         }\r
285                 }\r
286 \r
287                 // Next we may need distribute height.\r
288                 int sigmaHeight = (_tableInfo.getRowCount() + 1) * _vspacing;\r
289                 for (int i = 0; i < _rowHeights.length; i++) {\r
290                         sigmaHeight += _rowHeights[i];\r
291                 }\r
292                 if (sigmaHeight < contentHeight) {\r
293                         distributeHeights(contentHeight - sigmaHeight, _rowHeights);\r
294                 }\r
295 \r
296                 // now we have calculated the width and height of all cells.\r
297                 // FIXME: border?\r
298                 Insets insets = (style == null ? new Insets() : style.getBorderInsets()\r
299                                 .getAdded(style.getPaddingInsets()));\r
300                 _internalTableWidth = (_tableInfo.getColumnCount() + 1) * _hspacing;\r
301                 for (int i = 0; i < _columnWidths.length; i++) {\r
302                         _internalTableWidth += _columnWidths[i];\r
303                 }\r
304                 int minWidth = getLengthValue(style, ICSSPropertyID.ATTR_MIN_WIDTH);\r
305                 _internalTableWidth = _internalTableWidth > minWidth ? _internalTableWidth\r
306                                 : minWidth;\r
307 \r
308                 _blockBox.setWidth(_internalTableWidth + insets.getWidth());\r
309                 _internalTableHeight = (_tableInfo.getRowCount() + 1) * _vspacing;\r
310                 for (int i = 0; i < _rowHeights.length; i++) {\r
311                         _internalTableHeight += _rowHeights[i];\r
312                 }\r
313                 int minHeight = getLengthValue(style, ICSSPropertyID.ATTR_MIN_HEIGHT);\r
314                 _internalTableHeight = _internalTableHeight > minHeight ? _internalTableHeight\r
315                                 : minHeight;\r
316 \r
317                 int captionHeight = 0;\r
318                 if (_tableInfo.getCaption() != null) {\r
319                         _captionSize = _tableInfo.getCaption().getFigure().getPreferredSize(\r
320                                         _internalTableWidth, SWT.DEFAULT);\r
321                         captionHeight = _captionSize.height;\r
322                 } else {\r
323                         _captionSize = null;\r
324                 }\r
325                 _internalTableHeight += captionHeight;\r
326 \r
327                 _blockBox.setHeight(_internalTableHeight + insets.getHeight());\r
328 \r
329                 _rowwidth = _internalTableWidth - 2 * _hspacing;\r
330                 _rowx = _hspacing; // XXX: table border width left?\r
331         }\r
332 \r
333         /*\r
334          * (non-Javadoc)\r
335          * \r
336          * @see org.eclipse.jst.pagedesigner.css2.layout.CSSBlockFlowLayout#endBlock()\r
337          */\r
338         protected void endBlock() {\r
339                 _blockBox.setWidth(_internalTableWidth\r
340                                 + _blockBox.getBorderPaddingWidth());\r
341                 _blockBox.setHeight(_internalTableHeight\r
342                                 + _blockBox.getBorderPaddingHeight());\r
343                 super.endBlock();\r
344         }\r
345 \r
346         //\r
347         // /**\r
348         // * when some of the column has percentage width, and sigmaMax smaller than\r
349         // container,\r
350         // * @param containerWidth\r
351         // * @param columnMinWidths\r
352         // * @param columnMaxWidths\r
353         // * @return\r
354         // */\r
355         // private int distribute2(int containerWidth, int[] columnMinWidths, int[]\r
356         // columnMaxWidths)\r
357         // {\r
358         //        \r
359         // }\r
360         //    \r
361         /**\r
362          * Distribute the additional width to columnMinWidths, using max width as a\r
363          * possible reference on how to distribute.\r
364          * \r
365          * @param toDistribute\r
366          * @param columnMinWidths\r
367          * @param columnMaxWidths\r
368          */\r
369         private void distribute(int toDistribute, int[] columnMinWidths,\r
370                         int[] columnMaxWidths) {\r
371                 if (toDistribute <= 0)\r
372                         return;\r
373                 if (columnMinWidths.length == 0)\r
374                         return;\r
375 \r
376                 int[] delta = new int[columnMinWidths.length];\r
377                 int sigmaDelta = 0;\r
378                 for (int i = 0; i < columnMinWidths.length; i++) {\r
379                         if (_tableInfo.getWidthSpecified()[i]) {\r
380                                 delta[i] = 0;\r
381                         } else {\r
382                                 delta[i] = columnMaxWidths[i] - columnMinWidths[i];\r
383                                 if (delta[i] <= 0) {\r
384                                         delta[i] = 0;\r
385                                 }\r
386                                 sigmaDelta += delta[i];\r
387                         }\r
388                 }\r
389 \r
390                 // re-calculate the width of columns that use a percentage\r
391                 int[] widthPercentages = _tableInfo.getWidthPercentages();\r
392                 int[] calculatedWidths = new int[columnMaxWidths.length];\r
393                 int percentageWidthsTotal = 0;\r
394                 for (int i=0; i < widthPercentages.length; i++) {\r
395                         if (widthPercentages[i] > 0) {\r
396                                 // add the widths of the percent width columns\r
397                                 // back into the available pool\r
398                                 toDistribute += columnMinWidths[i];\r
399                         }\r
400                 }\r
401 \r
402                 for (int i=0; i < widthPercentages.length; i++) {\r
403                         if (widthPercentages[i] > 0) {\r
404                                 double val = toDistribute * (widthPercentages[i] / 100.0);\r
405                                 calculatedWidths[i] = (int) val;\r
406                                 if (calculatedWidths[i] < columnMinWidths[i]) {\r
407                                         // percent width is too small, so use\r
408                                         // the columnMinWidth instead\r
409                                         calculatedWidths[i] = columnMinWidths[i];\r
410                                 }\r
411                                 percentageWidthsTotal += calculatedWidths[i];\r
412                         } else {\r
413                                 calculatedWidths[i] = 0;\r
414                         }\r
415                 }\r
416 \r
417                 if (percentageWidthsTotal > toDistribute) {\r
418                         // calculated width is too large, so shrink the columns\r
419                         // to fit the available space\r
420                         int widthColumnCount = 0;\r
421                         for (int i=0; i < widthPercentages.length; i++) {\r
422                                 if (widthPercentages[i] > 0) {\r
423                                         widthColumnCount++;\r
424                                 }\r
425                         }\r
426 \r
427                         int extraSpace = percentageWidthsTotal - toDistribute;\r
428                         int shrinkBy = (int)\r
429                                 Math.ceil((double) extraSpace / (double) widthColumnCount);\r
430 \r
431                         for (int i=0; i < calculatedWidths.length; i++) {\r
432                                 if (calculatedWidths[i] > 0) {\r
433                                         calculatedWidths[i] -= shrinkBy;\r
434                                 }\r
435                         }\r
436                 }\r
437 \r
438                 // adjust the columnMinWidth values to compensate for the\r
439                 // calculated percentages\r
440                 for (int i=0; i < calculatedWidths.length; i++) {\r
441                         // if column size was calculated, then re-calculate the delta\r
442                         if (calculatedWidths[i] > 0) {\r
443                                 // remove the previous calculation from the sigmaDelta\r
444                                 int len = columnMaxWidths[i] - columnMinWidths[i];\r
445                                 delta[i] = 0;\r
446                                 if (len <= 0) {\r
447                                         len = 0;\r
448                                 }\r
449                                 sigmaDelta -= len;\r
450 \r
451                                 // change the minSize to the calculated size\r
452                                 columnMinWidths[i] = calculatedWidths[i];\r
453                                 toDistribute -= columnMinWidths[i];\r
454                         }\r
455                 }\r
456 \r
457                 if (sigmaDelta == 0) {\r
458                         // may happen with percent width column calculations.\r
459                         // find out how much space is left and distribute it\r
460                         // equally to all columns that are not fixed-width.\r
461                         int extraSpace = toDistribute;\r
462                         for (int i=0; i < columnMinWidths.length; i++) {\r
463                                 extraSpace -= columnMinWidths[i];\r
464                         }\r
465 \r
466                         averageDeltaToCell(columnMinWidths, extraSpace);\r
467                 } else {\r
468                         int left = toDistribute;\r
469                         for (int i = 0; i < columnMinWidths.length - 1; i++) {\r
470                                 if (delta[i] > 0) {\r
471                                         int add = delta[i] * toDistribute / sigmaDelta;\r
472                                         left -= add;\r
473                                         columnMinWidths[i] += add;\r
474                                 }\r
475                         }\r
476                         columnMinWidths[columnMinWidths.length - 1] += left;\r
477                 }\r
478         }\r
479 \r
480         private void averageDeltaToCell(int[] columnMinWidths, int toDistribute) {\r
481 \r
482                 if (toDistribute <= 0) {\r
483                         return;\r
484                 }\r
485                 ArrayList list = new ArrayList();\r
486                 for (int i = 0; i < columnMinWidths.length; i++) {\r
487                         if (!_tableInfo.getWidthSpecified()[i]) {\r
488                                 list.add(new Integer(i));\r
489                         }\r
490                 }\r
491                 if (list.size() == 0) {\r
492                         for (int i = 0; i < columnMinWidths.length; i++) {\r
493                                 list.add(new Integer(i));\r
494                         }\r
495                 }\r
496                 int padding = toDistribute / list.size();\r
497                 int left = toDistribute % list.size();\r
498                 for (int i = 0, n = list.size(); i < n; i++) {\r
499                         columnMinWidths[((Integer) list.get(i)).intValue()] += padding;\r
500                 }\r
501                 if (left > 0) {\r
502                         for (int i = 0; i < left; i++) {\r
503                                 columnMinWidths[((Integer) list.get(i)).intValue()] += 1;\r
504                         }\r
505                 }\r
506         }\r
507 \r
508         /**\r
509          * @param i\r
510          * @param heights\r
511          */\r
512         private void distributeHeights(int toDistribute, int[] heights) {\r
513                 if (heights.length == 0)\r
514                         return;\r
515                 int eachDelta = toDistribute / heights.length;\r
516                 for (int i = 0; i < heights.length - 1; i++) {\r
517                         heights[i] += eachDelta;\r
518                 }\r
519                 heights[heights.length - 1] += toDistribute - (heights.length - 1)\r
520                                 * eachDelta;\r
521         }\r
522 \r
523         /**\r
524          * @param cellinfo\r
525          * @param heights\r
526          * @return the cell height\r
527          */\r
528         public int getCellHeight(TableCellInfo cellinfo, int[] heights) {\r
529                 int rowIndex = cellinfo.getRowIndex();\r
530                 int rowspan = cellinfo.getRowSpan();\r
531                 int h = 0;\r
532                 for (int i = 0; i < rowspan; i++) {\r
533                         h += heights[rowIndex + i];\r
534                 }\r
535                 h += (rowspan - 1) * _vspacing;\r
536                 return h;\r
537         }\r
538 \r
539         /**\r
540          * @param cellinfo\r
541          * @param widths\r
542          * @return the cell width\r
543          */\r
544         public int getCellWidth(TableCellInfo cellinfo, int[] widths) {\r
545                 int columnIndex = cellinfo.getColumnIndex();\r
546                 int colspan = cellinfo.getColSpan();\r
547                 int w = 0;\r
548                 for (int i = 0; i < colspan; i++) {\r
549                         w += widths[columnIndex + i];\r
550                 }\r
551                 w += (colspan - 1) * _hspacing;\r
552                 return w;\r
553         }\r
554 \r
555         /**\r
556          * @param column\r
557          *            the start column\r
558          * @param colspan\r
559          *            number of columns\r
560          * @param width\r
561          *            desired width\r
562          * @param columnWidths\r
563          *            current columns widths. After the adjust, need make sure the\r
564          *            columnWidths to be bigger than desired width\r
565          */\r
566         private void adjustWidth(int column, int colspan, int width,\r
567                         int[] columnWidths) {\r
568                 adjustSpan(column, colspan, width, columnWidths, _hspacing);\r
569         }\r
570 \r
571         /**\r
572          * @see #adjustWidth(int, int, int, int[])\r
573          */\r
574         private void adjustHeight(int rowIndex, int rowspan, int height,\r
575                         int[] heights) {\r
576                 adjustSpan(rowIndex, rowspan, height, heights, _vspacing);\r
577         }\r
578 \r
579         static private void adjustSpan(int column, int colspan, int width,\r
580                         int[] columnWidths, int spacing) {\r
581                 int spanwidth = 0;\r
582                 for (int i = 0; i < colspan; i++) {\r
583                         spanwidth += columnWidths[column + i];\r
584                 }\r
585                 // XXX: vspacing here?\r
586                 spanwidth += (colspan - 1) * spacing;\r
587 \r
588                 if (spanwidth >= width) {\r
589                         return;\r
590                 }\r
591         int delta = width - spanwidth;\r
592         int deltaeach = delta / colspan;\r
593         for (int i = 0; i < colspan - 1; i++) {\r
594                 columnWidths[column + i] += deltaeach;\r
595         }\r
596         columnWidths[column + colspan - 1] += (delta - (colspan - 1)\r
597                         * deltaeach);\r
598         }\r
599 \r
600         /**\r
601          * @return the row heights\r
602          */\r
603         public int[] getRowHeights() {\r
604                 return _rowHeights;\r
605         }\r
606 \r
607         /**\r
608          * @return the column widths\r
609          */\r
610         public int[] getColumnWidths() {\r
611                 return _columnWidths;\r
612         }\r
613 \r
614         /**\r
615          * @return the vertical spacing value\r
616          */\r
617         public int getVSpacing() {\r
618                 return _vspacing;\r
619         }\r
620 \r
621         /**\r
622          * @return the horizontal spacing value\r
623          */\r
624         public int getHSpacing() {\r
625                 return _hspacing;\r
626         }\r
627 \r
628         /**\r
629          * @param figure\r
630          * @return the table row info for the figure\r
631          */\r
632         public TableRowInfo getRowInfo(CSSFigure figure) {\r
633                 return _tableInfo.findRowInfo(figure);\r
634         }\r
635 \r
636         /**\r
637          * @return the table caption info\r
638          */\r
639         public TableCaptionInfo getCaptionInfo() {\r
640                 return _tableInfo.getCaption();\r
641         }\r
642 \r
643         /**\r
644          * @param figure\r
645          * @return the table row group info for the figure\r
646          */\r
647         public TableRowGroupInfo getGroupInfo(CSSFigure figure) {\r
648                 return _tableInfo.findGroupInfo(figure);\r
649         }\r
650 \r
651         /**\r
652          * @return the row's x\r
653          */\r
654         public int getRowX() {\r
655                 return _rowx;\r
656         }\r
657 \r
658         /**\r
659          * @return the row's width\r
660          */\r
661         public int getRowWidth() {\r
662                 return _rowwidth;\r
663         }\r
664 \r
665         /*\r
666          * (non-Javadoc)\r
667          * \r
668          * @see org.eclipse.jst.pagedesigner.css2.layout.CSSBlockFlowLayout#shouldExpand()\r
669          */\r
670         public boolean shouldExpand() {\r
671                 return false;\r
672         }\r
673 \r
674         /**\r
675          * @return the rendered dimensions of the table caption\r
676          */\r
677         public Dimension getCaptionSize() {\r
678                 return _captionSize;\r
679         }\r
680 \r
681         /*\r
682          * (non-Javadoc)\r
683          * \r
684          * @see org.eclipse.jst.pagedesigner.css2.layout.ICSSPainter#paintFigure(org.eclipse.draw2d.Graphics)\r
685          */\r
686         public void paintFigure(Graphics g) {\r
687                 ICSSStyle style = this.getCSSStyle();\r
688                 if (style != null) {\r
689                         ITagEditInfo info = (ITagEditInfo) style\r
690                                         .getAdapter(ITagEditInfo.class);\r
691                         if (info != null && info.needTableDecorator()) {\r
692                                 List cells = _tableInfo.getCells();\r
693                                 for (int i = 0, size = cells.size(); i < size; i++) {\r
694                                         TableCellInfo cellInfo = (TableCellInfo) cells.get(i);\r
695                                         IFigure cellfigure = cellInfo.getFigure();\r
696                                         Rectangle rect = cellfigure.getBounds().getCopy();\r
697                                         rect = rect.expand(1, 1);\r
698                                         g.setLineStyle(Graphics.LINE_SOLID);\r
699                                         g.setLineWidth(1);\r
700                                         g.setForegroundColor(ColorConstants.lightGray);\r
701                                         g.drawRectangle(rect);\r
702                                 }\r
703                         }\r
704                 }\r
705         }\r
706 \r
707 }\r