/********************************************************************************* * TotalCross Software Development Kit * * Copyright (C) 2003-2004 Pierre G. Richard * * Copyright (C) 2003-2012 SuperWaba Ltda. * * All Rights Reserved * * * * This library and virtual machine is distributed in the hope that it will * * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * * This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 * * A copy of this license is located in file license.txt at the root of this * * SDK or can be downloaded here: * * http://www.gnu.org/licenses/lgpl-3.0.txt * * * *********************************************************************************/ package totalcross.ui.html; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!!! REMEMBER THAT ANY CHANGE YOU MAKE IN THIS CODE MUST BE SENT BACK TO SUPERWABA COMPANY !!!! //!!!! LEMBRE-SE QUE QUALQUER ALTERACAO QUE SEJA FEITO NESSE CODIGO DEVER� SER ENVIADA PARA NOS !!!! //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! import totalcross.sys.*; import totalcross.ui.*; import totalcross.ui.gfx.*; import totalcross.ui.html.Document.*; import totalcross.util.*; import totalcross.xml.*; /** * <code>Table</code> is the Tile associated to the <TABLE> tag. * * @author Pierre G. Richard */ class Table extends ScrollContainer implements CustomLayout, StopLayout, SizeDelimiter { int colCount; int borderWidth; int spacing; // distance between cell borders int padding; // distance between cell content and cell border IntVector colsPerRow = new IntVector(); int[] colMaxWidths, maxRowHeights; int maxColspan,curColspan,maxRowspan,curRowspan; int prefW; Style style; /** * Constructor * * @param tagHashId tag associated with the Table (i.e. Table) * @param atts tag attributes * @param style associated style */ Table(AttributeList atts, Style style) { super(false); this.style = style; borderWidth = atts.getAttributeValueAsInt("border",0); spacing = atts.getAttributeValueAsInt("cellspacing",0); padding = atts.getAttributeValueAsInt("cellpadding",0); String s = atts.getAttributeValue("width"); if (s != null) try { int perc = s.indexOf('%'); if (perc > 0) prefW = -Convert.toInt(s.substring(0,perc)); else prefW = Convert.toInt(s); } catch (Exception e) {if (Settings.onJavaSE) Vm.debug("Exception on Table's constructor: "+e+" "+e.getMessage()+"");} } /** * Add a row to the table * * @param atts tag attributes * @param style associated style */ void startRow(AttributeList atts, Style style) { } void endRow() { colsPerRow.addElement(colCount); maxColspan = Math.max(maxColspan, curColspan); maxRowspan = Math.max(maxRowspan, Math.max(colsPerRow.size(),curRowspan)); curColspan = colCount = 0; } void endTable() { } Container startCell(AttributeList atts, Style style) { colCount++; Cell cell = new Cell(style); int pad = padding; if (borderWidth >= 1) { cell.setBorderStyle(borderWidth == 1 ? BORDER_LOWERED : borderWidth == 2 ? BORDER_SIMPLE : BORDER_RAISED); pad++; } cell.setInsets(pad,pad,pad,pad); add(cell); curColspan += 1 + cell.colspan; curRowspan = Math.max(curRowspan, colsPerRow.size() + cell.rowspan); return cell; } static class CellSpan extends Control { Cell owner; CellSpan(Cell owner) { this.owner = owner; } } private Control[][] adjustSpan() { Control [] cs = bag.getChildren(); int rows = colsPerRow.size(); Control [][]matrix = new Control[maxRowspan][maxColspan]; // first, colspan: fill the span columns with CellSpan objects for (int r = 0,i=cs.length,jj=0; r < rows; r++,jj++) for (int c = 0,ii=0,maxCols = colsPerRow.items[r]; c < maxCols; c++,ii++) { Cell cell = (Cell)(matrix[jj][ii] = cs[--i]); if (cell.colspan > 1) { for (int z = 1; z < cell.colspan; z++) matrix[jj][ii+z] = new CellSpan(cell); ii += cell.colspan - 1; } } /* now, rowspan: shift columns to right when a rowspan is found (C=Cell, S=CellSpan, 0=null - see Sample6 in HtmlBrowser) C C C C C C C C C C C 0 S C C C C S C 0 => S C S C C C C C C C C C C S C 0 S C S C C 0 0 0 S S S C */ for (int c = 0; c < maxColspan; c++) for (int r = 0; r < maxRowspan; r++) { Control control = (Control)matrix[r][c]; Cell cell = control instanceof CellSpan ? ((CellSpan)control).owner : (Cell)control; if (cell == null) // guich@tc114_22 continue; int rowspan = cell.rowspan; if (rowspan > 1) { for (int z = 1; z < rowspan; z++) { Control[] row = matrix[r+z]; Vm.arrayCopy(row, c, row, c+1, row.length-c-1); matrix[r+z][c] = new CellSpan(cell); } r += rowspan - 1; } } // dump - for (int i = 0; i < rows; i++) for (int j =0; j < maxColspan; j++) System.out.print((matrix[i][j] == null ? "0 " : matrix[i][j] instanceof Cell ? "C " : "S ")+(j==maxColspan-1?"\n":"")); return matrix; } public void layout(LayoutContext lc) { this.width = this.height = 4096; // temporary lc.disjoin(); int k = borderWidth+spacing; setInsets(k,k,k,k); // 1. we fill the matrix with the cells, adjusting based on colspan/rowspan Control [][]matrix = adjustSpan(); // 2. we place the cells along the table int xx = 0, yy = 0, ww,hh; for (int r = 0; r < maxRowspan; r++) for (int c = 0; c < maxColspan; c++) { Control control = (Control)matrix[r][c]; if (control instanceof CellSpan) { Cell cell = ((CellSpan)control).owner; if (c == 0) ww = cell.getWidth(); else { Control c1 = matrix[r][c-1]; Cell cell1 = c1 instanceof CellSpan ? ((CellSpan)c1).owner : (Cell)c1; ww = cell1 == cell ? 0 : cell.getWidth(); // if its the same owner, the width was already computed, so assign 0 to ww } hh = cell.getHeight(); } else { Cell cell = (Cell)control; ww = colMaxWidths[c]; hh = maxRowHeights[r]; if (cell != null) // guich@tc114_22: google.com.br? { if (cell.colspan > 1) for (int cs = cell.colspan; --cs >= 1;) ww += colMaxWidths[c+cs]; if (cell.rowspan > 1) { hh = 0; for (int cs = cell.rowspan; --cs >= 0;) hh += maxRowHeights[r+cs]; hh = Math.max(cell.getPreferredHeight(),hh); // if the cell has a height bigger than the sum of the other rows, use it } cell.setRect(xx,yy,ww,hh); } } xx += ww + spacing; if (c == maxColspan-1) { yy += hh + spacing; xx = 0; } } resize(); setRect(lc.nextX,lc.nextY,PREFERRED+k+k,PREFERRED+k+k); lc.disjoin(); } public void onPaint(Graphics g) { g.backColor = style.backColor; g.fillRect(0,0,width,height); super.onPaint(g); // paint Table's border for (int i = borderWidth; --i >= 0;) g.drawRect(i,i,width-i-i,height-i-i); } public int getMaxWidth() { colMaxWidths = new int[maxColspan]; maxRowHeights = new int[colsPerRow.size()]; Control [] cs = bag.getChildren(); int rows = colsPerRow.size(); int maxRowSize = 0, currentRowSize; for (int r = 0,i=cs.length; r < rows; r++) { currentRowSize = 0; for (int c = 0, n = colsPerRow.items[r]; c < n; c++) { Cell cell = (Cell)cs[--i]; // compute max width int w = cell.getMaxWidth(); if (w > colMaxWidths[c]) colMaxWidths[c] = w; // compute max height - don't move from here! int h = cell.getPreferredHeight(); if (h > maxRowHeights[r] && cell.rowspan <= 1) maxRowHeights[r] = h; // also consider border and gaps if (borderWidth >= 1) w += 2; if (padding > 0) w += padding; if (spacing > 0) w += spacing; currentRowSize += w; } if (currentRowSize > maxRowSize) maxRowSize = currentRowSize; } return maxRowSize; } }