include/HTMLRenderer/TableLayout.hpp

Go to the documentation of this file.
00001 #ifndef hpp_TableLayout_hpp
00002 #define hpp_TableLayout_hpp
00003 
00004 // We need DOM declaration, as we will render a DOM
00005 #include "../HTMLParser/DOM.hpp"
00006 // We need container classes (to be confirmed if it is really needed)
00007 #include "../Containers/Container.hpp"
00008 // We need the box hierarchy model
00009 #include "BoxHierarchy.hpp"
00010 
00011 namespace HTML
00012 {
00013     namespace Renderer
00014     {
00019         class TableLayout
00020         {
00021             // Types
00022         public:
00030             struct Cell
00031             {
00032             public:
00034                 enum { NoWidthDeclared = (uint32)-1 };
00036                 uint32      width;
00038                 uint32      horizontalSpan;
00040                 uint32      verticalSpan;
00041 
00043                 const void *    userData;
00044 
00046                 void *      userData2;
00048                 uint32      minimumWidth;
00050                 uint32      maximumWidth;
00051 
00053                 Cell(const uint32 _width = NoWidthDeclared, const uint32 hspan = 1, const uint32 vspan = 1, const void * user = 0) : width(_width), horizontalSpan(hspan), verticalSpan(vspan), userData(user), userData2(0) {}
00054             };
00055 
00060             struct Row
00061             {
00062             public:
00064                 Container::PlainOldData<Cell>::Array    cellArray;
00066                 enum RowType
00067                 {
00068                     Header   = 0,   
00069                     Data     = 1,   
00070                     Footer   = 2,   
00071                 }       rowType;
00072 
00073                 // Interface
00074             public:
00076                 inline Cell & operator[] (const uint32 index) { return cellArray[index]; }
00077 
00082                 inline Cell * getCellOnColumn(int32 index) 
00083                 { 
00084                     if (index > (int32)cellArray.getSize()) return 0;
00085                     for (uint32 i = 0; index > 0 && i < cellArray.getSize(); i++)
00086                     {
00087                         uint32 hspan = cellArray[i].horizontalSpan;
00088                         if (hspan > (uint32)index) return &cellArray[i];
00089                         index -=  hspan;
00090                     }
00091                     return 0;
00092                 }
00093 
00095                 inline const uint32 cellCount() const { return cellArray.getSize(); }
00097                 inline const RowType getRowType() const { return rowType; }
00098 
00102                 inline void appendCell(const Cell & cell) { cellArray.Append(cell); }
00109                 inline void ensureSize(const uint32 size, const bool multipleCells = true)    
00110                 {
00111                     if (size <= cellCount()) return;
00112                     uint32 nbMissing = size - cellCount();
00113                     if (multipleCells) while (nbMissing--) appendCell(Cell()); else appendCell(Cell(Cell::NoWidthDeclared, nbMissing));
00114                 }
00115 
00117                 Row(const RowType type = Data) : rowType(Data) {}
00118             };
00119 
00121             struct Column
00122             {
00125                 enum WidthType 
00126                 { 
00127                     Fixed       = 1,    
00128                     Percentage  = 2,    
00129                     Multiple    = 3,    
00130                 }           widthType;
00132                 uint32      width;
00134                 uint32      span;
00135 
00137                 uint32      maximumWidth;
00139                 uint32      minimumWidth;
00140 
00142                 Column(const WidthType type = Multiple, const uint32 _width = 1, const uint32 _span = 1) : widthType(type), width(_width), span(_span), maximumWidth(0), minimumWidth(-1) {} 
00143             };
00144 
00147             typedef Container::WithCopyConstructor<Row>::Array    RowArray;
00149             typedef Container::WithCopyConstructor<Column>::Array ColumnArray;
00150 
00151 
00152             // Members
00153         private:
00155             Cell ***        cellMap;
00157             uint32          cellMapWidth;
00159             uint32          cellMapHeight;
00160 
00162             RowArray        rowArray;
00164             ColumnArray     columnArray;
00165 
00166         public:
00168             uint32          maximumWidth;
00170             uint32          minimumWidth;
00171 
00172             // Helpers
00173         private:
00176             inline const uint32 typedRowCount(const Row::RowType type) const 
00177             {
00178                 uint32 count = 0;
00179                 for (uint32 i = 0; i < rowArray.getSize(); i++)
00180                     count += rowArray[i].getRowType() == type;
00181                 return count;
00182             }
00183             
00185             inline void cleanCellMap() 
00186             {
00187                 if (cellMap) { for (uint32 i = 0; i < cellMapHeight; i++) delete[] cellMap[i]; }
00188                 delete[] cellMap; cellMap = 0;
00189                 cellMapWidth = cellMapHeight = 0;
00190             }
00191 
00222             inline bool createCellMap()
00223             {
00224                 cleanCellMap();
00225                 cellMap = new Cell ** [rowArray.getSize()];
00226                 if (!cellMap) return false;
00227                 
00228                 cellMapHeight = rowArray.getSize();
00229                 cellMapWidth  = realColumnCount();
00230                 uint32 i = 0;
00231                 for (; i < cellMapHeight; i++)
00232                 {
00233                     cellMap[i] = new Cell* [cellMapWidth];
00234                     if (!cellMap[i]) { cleanCellMap(); return false; }
00235                     memset(cellMap[i], 0, sizeof(cellMap[i][0]) * cellMapWidth);
00236                 }
00237 
00238                 for (i = 0; i < cellMapHeight; i++)
00239                 {
00240                     Row & row = rowArray[i];
00241                     uint32 j = 0; uint32 index = 0;
00242                     while (j < cellMapWidth && index < row.cellCount())
00243                     {   
00244                         Cell & cell = row[index++];
00245                         uint32 z = 0, t = 0;
00246                         // If some previous row spanned on us, skip them
00247                         while (cellMap[i][j] && j < cellMapWidth) j+=cellMap[i][j]->horizontalSpan;
00248                         for (; z < cell.verticalSpan && (i+z) < cellMapHeight; z++)  
00249                         {   // Fill the grid vertically
00250                             for (t = 0; t < cell.horizontalSpan && (j+t) < cellMapWidth; t++) 
00251                             {
00252                                 // Fill horizontally 
00253                                 if (!cellMap[i+z][j+t]) cellMap[i+z][j+t] = &cell;
00254                             }
00255                         }
00256 
00257                         j += cell.horizontalSpan;
00258                     }
00259                 }
00260                 return true;
00261             }
00262 
00263             // Interface
00264         public:
00266             inline Row & operator[](const uint32 index) { return rowArray[index]; } 
00269             inline const uint32 dataRowCount() const { return typedRowCount(Row::Data); }
00272             inline const uint32 headerRowCount() const { return typedRowCount(Row::Header); }
00275             inline const uint32 footerRowCount() const { return typedRowCount(Row::Footer); }
00278             inline const uint32 rowCount() const { return rowArray.getSize(); }
00279 
00281             inline const uint32 realColumnCount() const 
00282             {
00283                 uint32 count = 0;
00284                 for (uint32 i = 0; i < columnArray.getSize(); i++) { count += columnArray[i].span; } 
00285                 return count; 
00286             }
00287 
00291             inline void appendColumn(const Column & col) 
00292             { 
00293                 columnArray.Append(col); 
00294 //                uint32 columnCount = realColumnCount();
00295 //                for (uint32 i = 0; i < rowArray.getSize(); i++)
00296 //                    rowArray[i].ensureSize(columnCount);
00297                 cleanCellMap();
00298             }
00299 
00304             inline void appendMultipleColumns(uint32 count, const Column & col) 
00305             { 
00306                 while (count--) columnArray.Append(col); 
00307 //                uint32 columnCount = realColumnCount();
00308 //                for (uint32 i = 0; i < rowArray.getSize(); i++)
00309 //                    rowArray[i].ensureSize(columnCount);
00310                 cleanCellMap();
00311             }
00312 
00313 
00319             inline void updateRowAt(const uint32 index, const Row & row)
00320             {
00321                 if (index < rowCount()) { rowArray[index] = row; }
00322                 else if (index == rowCount()) { rowArray.Append(row); cleanCellMap(); }
00323             }
00324 
00328             inline Column * columnAt(const uint32 index) { if (index < realColumnCount()) return &columnArray[index]; return 0; }
00333             inline Column & unsafeColumnAt(const uint32 index) { return columnArray[index]; }
00334 
00340             inline Cell * findCell(const void * data, const bool findFirstData = true)
00341             {
00342                 for (uint32 i = 0; i < rowArray.getSize(); i++)
00343                 {
00344                     Row & row = rowArray[i];
00345                     for (uint32 j = 0; j < row.cellCount(); j++)
00346                     {
00347                         if ((findFirstData && row[j].userData == data) || (!findFirstData && row[j].userData2 == data) ) return &row[j];
00348                     }
00349                 }
00350                 return 0;
00351             }
00352 
00359             inline Cell * findCellAt(const uint32 rowIndex, const uint32 colIndex)
00360             {
00361                 // Check out-of-bound indexes
00362                 uint32 maxColumnCount = realColumnCount();
00363                 if (rowIndex >= rowArray.getSize() || colIndex >= maxColumnCount) return 0;
00364                 if (!cellMap) 
00365                     if (!createCellMap()) return 0;
00366                 return cellMap[rowIndex][colIndex];
00367             }
00368             
00369             // Construction and destruction
00370         public:
00372             TableLayout() : cellMap(0) {}
00374             ~TableLayout() { cleanCellMap(); }
00375         };
00376 
00377 
00378     }
00379 }
00380 
00381 #endif

(C) An X-Ryl669 project 2007

This document describes Unlimited Zooming Interface source code. UZI stands for Unlimited Zooming Interface, and source code license is