]>
git.saurik.com Git - wxWidgets.git/blob - src/html/mod_tables.cpp
3707b8026d37c41f445ac5089ae4e418ba5d79fa
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        mod_tables.cpp 
   3 // Purpose:     wxHtml module for tables 
   4 // Author:      Vaclav Slavik 
   5 // Copyright:   (c) 1999 Vaclav Slavik 
   6 // Licence:     wxWindows Licence 
   7 ///////////////////////////////////////////////////////////////////////////// 
  10 #pragma implementation 
  13 #include <wx/wxprec.h> 
  27     1. This version of mod_tables doesn't support auto-layout algorithm. 
  28        This means that all columns are of same width unless explicitly specified. 
  32 #include <wx/html/forcelink.h> 
  33 #include <wx/html/mod_templ.h> 
  35 #include <wx/html/htmlcell.h> 
  37 FORCE_LINK_ME(mod_tables
) 
  40 #define TABLE_BORDER_CLR_1  wxColour(0xC5, 0xC2, 0xC5) 
  41 #define TABLE_BORDER_CLR_2  wxColour(0x62, 0x61, 0x62) 
  44 //----------------------------------------------------------------------------- 
  46 //----------------------------------------------------------------------------- 
  50         int width
, units
;                      // universal 
  51         int leftpos
, pixwidth
, maxrealwidth
;   // temporary (depends on width of table) 
  61         wxHtmlContainerCell 
*cont
; 
  63         int minheight
, valign
; 
  68 class wxHtmlTableCell 
: public wxHtmlContainerCell
 
  71         /* These are real attributes: */ 
  73                 // should we draw borders or not? 
  74         int m_NumCols
, m_NumRows
; 
  75                 // number of columns; rows 
  76         colStruct 
*m_ColsInfo
; 
  77                 // array of column information 
  78         cellStruct 
**m_CellInfo
; 
  79                 // 2D array of all cells in the table : m_CellInfo[row][column] 
  81                 // spaces between cells 
  83                 // cells internal indentation 
  86         /* ...and these are valid only during parsing of table: */ 
  87         int m_ActualCol
, m_ActualRow
; 
  88                 // number of actual column (ranging from 0..m_NumCols) 
  90         // default values (for table and row): 
  92         wxString m_tValign
, m_rValign
; 
  96         wxHtmlTableCell(wxHtmlContainerCell 
*parent
, const wxHtmlTag
& tag
); 
  98         virtual void Layout(int w
); 
 100         void AddRow(const wxHtmlTag
& tag
); 
 101         void AddCell(wxHtmlContainerCell 
*cell
, const wxHtmlTag
& tag
); 
 103         void ReallocCols(int cols
); 
 104         void ReallocRows(int rows
); 
 105                 // reallocates memory to given number of cols/rows 
 106                 // and changes m_NumCols/m_NumRows value to reflect this change 
 107                 // NOTE! You CAN'T change m_NumCols/m_NumRows before calling this!! 
 112 wxHtmlTableCell::wxHtmlTableCell(wxHtmlContainerCell 
*parent
, const wxHtmlTag
& tag
) 
 113  : wxHtmlContainerCell(parent
) 
 115     m_HasBorders 
= tag
.HasParam("BORDER"); 
 117     m_NumCols 
= m_NumRows 
= 0; 
 119     m_ActualCol 
= m_ActualRow 
= -1; 
 122     m_tBkg 
= m_rBkg 
= -1; 
 123     if (tag
.HasParam("BGCOLOR")) tag
.ScanParam("BGCOLOR", "#%lX", &m_tBkg
); 
 124     if (tag
.HasParam("VALIGN")) m_tValign 
= tag
.GetParam("VALIGN"); else m_tValign 
= wxEmptyString
; 
 125     if (tag
.HasParam("CELLSPACING")) tag
.ScanParam("CELLSPACING", "%i", &m_Spacing
); else m_Spacing 
= 2; 
 126     if (tag
.HasParam("CELLPADDING")) tag
.ScanParam("CELLPADDING", "%i", &m_Padding
); else m_Padding 
= 3; 
 129         SetBorder(TABLE_BORDER_CLR_1
, TABLE_BORDER_CLR_2
); 
 134 wxHtmlTableCell::~wxHtmlTableCell() 
 136     if (m_ColsInfo
) free(m_ColsInfo
); 
 138         for (int i 
= 0; i 
< m_NumRows
; i
++) 
 146 void wxHtmlTableCell::ReallocCols(int cols
) 
 150     for (i 
= 0; i 
< m_NumRows
; i
++) { 
 151         m_CellInfo
[i
] = (cellStruct
*) realloc(m_CellInfo
[i
], sizeof(cellStruct
) * cols
); 
 152         for (j 
= m_NumCols
; j 
< cols
; j
++) 
 153             m_CellInfo
[i
][j
].flag 
= cellFree
; 
 156     m_ColsInfo 
= (colStruct
*) realloc(m_ColsInfo
, sizeof(colStruct
) * cols
); 
 157     for (j 
= m_NumCols
; j 
< cols
; j
++) { 
 158            m_ColsInfo
[j
].width 
= 0; 
 159            m_ColsInfo
[j
].units 
= HTML_UNITS_PERCENT
; 
 167 void wxHtmlTableCell::ReallocRows(int rows
) 
 169     m_CellInfo 
= (cellStruct
**) realloc(m_CellInfo
, sizeof(cellStruct
*) * rows
); 
 170     if (m_NumCols 
!= 0) { 
 172         m_CellInfo
[x
] = (cellStruct
*) malloc(sizeof(cellStruct
) * m_NumCols
); 
 173         for (int i 
= 0; i 
< m_NumCols
; i
++) 
 174             m_CellInfo
[x
][i
].flag 
= cellFree
; 
 177         m_CellInfo
[rows 
- 1] = NULL
; 
 183 void wxHtmlTableCell::AddRow(const wxHtmlTag
& tag
) 
 185     if (m_ActualRow 
+ 1 > m_NumRows 
- 1) 
 186         ReallocRows(m_ActualRow 
+ 2); 
 192     if (tag
.HasParam("BGCOLOR")) tag
.ScanParam("BGCOLOR", "#%lX", &m_rBkg
); 
 193     if (tag
.HasParam("VALIGN")) m_rValign 
= tag
.GetParam("VALIGN"); else m_rValign 
= m_tValign
; 
 198 void wxHtmlTableCell::AddCell(wxHtmlContainerCell 
*cell
, const wxHtmlTag
& tag
) 
 202     } while ((m_ActualCol 
< m_NumCols
) && (m_CellInfo
[m_ActualRow
][m_ActualCol
].flag 
!= cellFree
)); 
 203     if (m_ActualCol 
> m_NumCols 
- 1) 
 204         ReallocCols(m_ActualCol 
+ 1); 
 206     int r 
= m_ActualRow
, c 
= m_ActualCol
; 
 208     m_CellInfo
[r
][c
].cont 
= cell
; 
 209     m_CellInfo
[r
][c
].colspan 
= 1; 
 210     m_CellInfo
[r
][c
].rowspan 
= 1; 
 211     m_CellInfo
[r
][c
].flag 
= cellUsed
; 
 212     m_CellInfo
[r
][c
].minheight 
= 0; 
 213     m_CellInfo
[r
][c
].valign 
= HTML_ALIGN_TOP
; 
 215     /* scan for parameters: */ 
 219         if (tag
.HasParam("WIDTH")) { 
 220             wxString wd 
= tag
.GetParam("WIDTH"); 
 222             if (wd
[wd
.Length()-1] == '%') { 
 223                 sscanf(wd
.c_str(), "%i%%", &m_ColsInfo
[c
].width
); 
 224                 m_ColsInfo
[c
].units 
= HTML_UNITS_PERCENT
; 
 227                 sscanf(wd
.c_str(), "%i", &m_ColsInfo
[c
].width
); 
 228                 m_ColsInfo
[c
].units 
= HTML_UNITS_PIXELS
; 
 236         if (tag
.HasParam("COLSPAN")) tag
.ScanParam("COLSPAN", "%i", &m_CellInfo
[r
][c
].colspan
); 
 237         if (tag
.HasParam("ROWSPAN")) tag
.ScanParam("ROWSPAN", "%i", &m_CellInfo
[r
][c
].rowspan
); 
 238         if ((m_CellInfo
[r
][c
].colspan 
!= 1) || (m_CellInfo
[r
][c
].rowspan 
!= 1)) { 
 241             if (r 
+ m_CellInfo
[r
][c
].rowspan 
> m_NumRows
) ReallocRows(r 
+ m_CellInfo
[r
][c
].rowspan
); 
 242             if (c 
+ m_CellInfo
[r
][c
].colspan 
> m_NumCols
) ReallocCols(c 
+ m_CellInfo
[r
][c
].colspan
); 
 243             for (i 
= r
; i 
< r 
+ m_CellInfo
[r
][c
].rowspan
; i
++) 
 244                 for (j 
= c
; j 
< c 
+ m_CellInfo
[r
][c
].colspan
; j
++) 
 245                     m_CellInfo
[i
][j
].flag 
= cellSpan
; 
 246             m_CellInfo
[r
][c
].flag 
= cellUsed
; 
 253         if (tag
.HasParam("BGCOLOR")) tag
.ScanParam("BGCOLOR", "#%lX", &bk
); 
 255             wxColour clr 
= wxColour((bk 
& 0xFF0000) >> 16 , (bk 
& 0x00FF00) >> 8, (bk 
& 0x0000FF)); 
 256             cell 
-> SetBackgroundColour(clr
); 
 260         cell 
-> SetBorder(TABLE_BORDER_CLR_2
, TABLE_BORDER_CLR_1
); 
 262     // vertical alignment: 
 265         if (tag
.HasParam("VALIGN")) valign 
= tag
.GetParam("VALIGN"); else valign 
= m_tValign
; 
 267         if (valign 
== "TOP") m_CellInfo
[r
][c
].valign 
= HTML_ALIGN_TOP
; 
 268         else if (valign 
== "BOTTOM") m_CellInfo
[r
][c
].valign 
= HTML_ALIGN_BOTTOM
; 
 269         else m_CellInfo
[r
][c
].valign 
= HTML_ALIGN_CENTER
; 
 272     cell 
-> SetIndent(m_Padding
, HTML_INDENT_ALL
, HTML_UNITS_PIXELS
); 
 279 void wxHtmlTableCell::Layout(int w
) 
 287     if (m_WidthFloatUnits 
== HTML_UNITS_PERCENT
) { 
 288         if (m_WidthFloat 
< 0) m_Width 
= (100 + m_WidthFloat
) * w 
/ 100; 
 289         else m_Width 
= m_WidthFloat 
* w 
/ 100; 
 292         if (m_WidthFloat 
< 0) m_Width 
= w 
+ m_WidthFloat
; 
 293         else m_Width 
= m_WidthFloat
; 
 303     /* 1.  setup columns widths: */ 
 305         int wpix 
= m_Width 
- (m_NumCols 
+ 1) * m_Spacing
; 
 309         // 1a. setup fixed-width columns: 
 310         for (i 
= 0; i 
< m_NumCols
; i
++) 
 311             if (m_ColsInfo
[i
].units 
== HTML_UNITS_PIXELS
) 
 312                 wpix 
-= (m_ColsInfo
[i
].pixwidth 
= m_ColsInfo
[i
].width
); 
 314         // 1b. setup floating-width columns: 
 315         for (i 
= 0; i 
< m_NumCols
; i
++) 
 316             if ((m_ColsInfo
[i
].units 
== HTML_UNITS_PERCENT
) && (m_ColsInfo
[i
].width 
!= 0)) 
 317                 wtemp 
+= (m_ColsInfo
[i
].pixwidth 
= m_ColsInfo
[i
].width 
* wpix 
/ 100); 
 320         // 1c. setup defalut columns (no width specification supplied): 
 321         // NOTE! This algorithm doesn't conform to HTML standard : it assigns equal widths 
 322         // instead of optimal 
 323         for (i 
= j 
= 0; i 
< m_NumCols
; i
++) 
 324             if (m_ColsInfo
[i
].width 
== 0) j
++; 
 325         for (i 
= 0; i 
< m_NumCols
; i
++) 
 326             if (m_ColsInfo
[i
].width 
== 0) 
 327                 m_ColsInfo
[i
].pixwidth 
= wpix 
/ j
; 
 330     /* 2.  compute positions of columns: */ 
 332         int wpos 
= m_Spacing
; 
 333         for (int i 
= 0; i 
< m_NumCols
; i
++) { 
 334             m_ColsInfo
[i
].leftpos 
= wpos
; 
 335             wpos 
+= m_ColsInfo
[i
].pixwidth 
+ m_Spacing
; 
 339     /* 3.  sub-layout all cells: */ 
 341         int *ypos 
= (int*) malloc(sizeof(int) * (m_NumRows 
+ 1)); 
 345         wxHtmlContainerCell 
*actcell
; 
 347         for (actrow 
= 0; actrow 
<= m_NumRows
; actrow
++) ypos
[actrow
] = m_Spacing
; 
 349         for (actrow 
= 0; actrow 
< m_NumRows
; actrow
++) { 
 351             // 3a. sub-layout and detect max height: 
 353             for (actcol 
= 0; actcol 
< m_NumCols
; actcol
++) { 
 354                 if (m_CellInfo
[actrow
][actcol
].flag 
!= cellUsed
) continue; 
 355                 actcell 
= m_CellInfo
[actrow
][actcol
].cont
; 
 357                 for (int i 
= actcol
; i 
< m_CellInfo
[actrow
][actcol
].colspan 
+ actcol
; i
++) 
 358                     fullwid 
+= m_ColsInfo
[i
].pixwidth
; 
 359                 actcell 
-> SetMinHeight(m_CellInfo
[actrow
][actcol
].minheight
, m_CellInfo
[actrow
][actcol
].valign
); 
 360                 actcell 
-> Layout(fullwid
); 
 362                 if (ypos
[actrow
] + actcell 
-> GetHeight() + m_CellInfo
[actrow
][actcol
].rowspan 
* m_Spacing 
> ypos
[actrow 
+ m_CellInfo
[actrow
][actcol
].rowspan
]) 
 363                     ypos
[actrow 
+ m_CellInfo
[actrow
][actcol
].rowspan
] = 
 364                             ypos
[actrow
] + actcell 
-> GetHeight() + m_CellInfo
[actrow
][actcol
].rowspan 
* m_Spacing
; 
 369         for (actrow 
= 0; actrow 
< m_NumRows
; actrow
++) { 
 371             // 3b. place cells in row & let'em all have same height: 
 373             for (actcol 
= 0; actcol 
< m_NumCols
; actcol
++) { 
 374                 if (m_CellInfo
[actrow
][actcol
].flag 
!= cellUsed
) continue; 
 375                 actcell 
= m_CellInfo
[actrow
][actcol
].cont
; 
 376                 actcell 
-> SetMinHeight( 
 377                                  ypos
[actrow 
+ m_CellInfo
[actrow
][actcol
].rowspan
] - ypos
[actrow
] - m_CellInfo
[actrow
][actcol
].rowspan 
* m_Spacing
, 
 378                                  m_CellInfo
[actrow
][actcol
].valign
); 
 380                 for (int i 
= actcol
; i 
< m_CellInfo
[actrow
][actcol
].colspan 
+ actcol
; i
++) 
 381                     fullwid 
+= m_ColsInfo
[i
].pixwidth
; 
 382                 actcell 
-> Layout(fullwid
); 
 383                 actcell 
-> SetPos(m_ColsInfo
[actcol
].leftpos
, ypos
[actrow
]); 
 387         m_Height 
= ypos
[m_NumRows
]; 
 397 //----------------------------------------------------------------------------- 
 398 // The tables handler: 
 399 //----------------------------------------------------------------------------- 
 402 TAG_HANDLER_BEGIN(TABLE
, "TABLE,TR,TD,TH") 
 405         wxHtmlTableCell
* m_Table
; 
 406         wxString m_tAlign
, m_rAlign
; 
 409     TAG_HANDLER_CONSTR(TABLE
) 
 412     m_tAlign 
= m_rAlign 
= wxEmptyString
; 
 413     m_OldAlign 
= HTML_ALIGN_LEFT
; 
 417     TAG_HANDLER_PROC(tag
) 
 419         wxHtmlContainerCell 
*c
; 
 421         // new table started, backup upper-level table (if any) and create new: 
 422         if (tag
.GetName() == "TABLE") { 
 423             wxHtmlTableCell 
*oldt 
= m_Table
; 
 424             wxHtmlContainerCell 
*oldcont
; 
 427             oldcont 
= c 
= m_WParser 
-> OpenContainer(); 
 429             c 
-> SetWidthFloat(tag
); 
 430             m_Table 
= new wxHtmlTableCell(c
, tag
); 
 431             m_OldAlign 
= m_WParser 
-> GetAlign(); 
 432             m_tAlign 
= wxEmptyString
; 
 433             if (tag
.HasParam("ALIGN")) m_tAlign 
= tag
.GetParam("ALIGN"); 
 437             m_WParser 
-> SetAlign(m_OldAlign
); 
 438             m_WParser 
-> SetContainer(oldcont
); 
 439             m_WParser 
-> CloseContainer(); 
 445         else if (m_Table 
&& !tag
.IsEnding()) { 
 447             if (tag
.GetName() == "TR") { 
 448                 m_Table 
-> AddRow(tag
); 
 450                 if (tag
.HasParam("ALIGN")) m_rAlign 
= tag
.GetParam("ALIGN"); 
 455                 m_WParser 
-> SetAlign(m_OldAlign
); 
 456                 c 
= m_WParser 
-> SetContainer(new wxHtmlContainerCell(m_Table
)); 
 457                 m_Table 
-> AddCell(c
, tag
); 
 459                 m_WParser 
-> OpenContainer(); 
 461                 if (tag
.GetName() == "TH") /*header style*/ { 
 462                     m_WParser 
-> SetAlign(HTML_ALIGN_CENTER
); 
 469                     if (tag
.HasParam("ALIGN")) als 
= tag
.GetParam("ALIGN"); 
 471                     if (als 
== "RIGHT") m_WParser 
-> SetAlign(HTML_ALIGN_RIGHT
); 
 472                     else if (als 
== "CENTER") m_WParser 
-> SetAlign(HTML_ALIGN_CENTER
); 
 474                 m_WParser 
-> OpenContainer(); 
 480 TAG_HANDLER_END(TABLE
) 
 486 TAGS_MODULE_BEGIN(Tables
) 
 488     TAGS_MODULE_ADD(TABLE
) 
 490 TAGS_MODULE_END(Tables
)