]>
git.saurik.com Git - wxWidgets.git/blob - src/html/m_tables.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mod_tables.cpp
3 // Purpose: wxHtml module for tables
4 // Author: Vaclav Slavik
6 // Copyright: (c) 1999 Vaclav Slavik
7 // Licence: wxWindows Licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation
14 #include <wx/wxprec.h>
28 1. This version of mod_tables doesn't support auto-layout algorithm.
29 This means that all columns are of same width unless explicitly specified.
33 #include "wx/html/forcelnk.h"
34 #include "wx/html/m_templ.h"
36 #include "wx/html/htmlcell.h"
38 FORCE_LINK_ME(mod_tables
)
41 #define TABLE_BORDER_CLR_1 wxColour(0xC5, 0xC2, 0xC5)
42 #define TABLE_BORDER_CLR_2 wxColour(0x62, 0x61, 0x62)
45 //-----------------------------------------------------------------------------
47 //-----------------------------------------------------------------------------
51 int width
, units
; // universal
52 int leftpos
, pixwidth
, maxrealwidth
; // temporary (depends on width of table)
62 wxHtmlContainerCell
*cont
;
64 int minheight
, valign
;
69 class wxHtmlTableCell
: public wxHtmlContainerCell
72 /* These are real attributes: */
74 // should we draw borders or not?
75 int m_NumCols
, m_NumRows
;
76 // number of columns; rows
77 colStruct
*m_ColsInfo
;
78 // array of column information
79 cellStruct
**m_CellInfo
;
80 // 2D array of all cells in the table : m_CellInfo[row][column]
82 // spaces between cells
84 // cells internal indentation
87 /* ...and these are valid only during parsing of table: */
88 int m_ActualCol
, m_ActualRow
;
89 // number of actual column (ranging from 0..m_NumCols)
91 // default values (for table and row):
93 wxString m_tValign
, m_rValign
;
97 wxHtmlTableCell(wxHtmlContainerCell
*parent
, const wxHtmlTag
& tag
);
99 virtual void Layout(int w
);
101 void AddRow(const wxHtmlTag
& tag
);
102 void AddCell(wxHtmlContainerCell
*cell
, const wxHtmlTag
& tag
);
104 void ReallocCols(int cols
);
105 void ReallocRows(int rows
);
106 // reallocates memory to given number of cols/rows
107 // and changes m_NumCols/m_NumRows value to reflect this change
108 // NOTE! You CAN'T change m_NumCols/m_NumRows before calling this!!
113 wxHtmlTableCell::wxHtmlTableCell(wxHtmlContainerCell
*parent
, const wxHtmlTag
& tag
)
114 : wxHtmlContainerCell(parent
)
116 m_HasBorders
= tag
.HasParam("BORDER");
118 m_NumCols
= m_NumRows
= 0;
120 m_ActualCol
= m_ActualRow
= -1;
123 m_tBkg
= m_rBkg
= -1;
124 if (tag
.HasParam("BGCOLOR")) tag
.ScanParam("BGCOLOR", "#%lX", &m_tBkg
);
125 if (tag
.HasParam("VALIGN")) m_tValign
= tag
.GetParam("VALIGN"); else m_tValign
= wxEmptyString
;
126 if (tag
.HasParam("CELLSPACING") && tag
.ScanParam("CELLSPACING", "%i", &m_Spacing
) == 1) {} else m_Spacing
= 2;
127 if (tag
.HasParam("CELLPADDING") && tag
.ScanParam("CELLPADDING", "%i", &m_Padding
) == 1) {} else m_Padding
= 3;
130 SetBorder(TABLE_BORDER_CLR_1
, TABLE_BORDER_CLR_2
);
135 wxHtmlTableCell::~wxHtmlTableCell()
137 if (m_ColsInfo
) free(m_ColsInfo
);
139 for (int i
= 0; i
< m_NumRows
; i
++)
147 void wxHtmlTableCell::ReallocCols(int cols
)
151 for (i
= 0; i
< m_NumRows
; i
++) {
152 m_CellInfo
[i
] = (cellStruct
*) realloc(m_CellInfo
[i
], sizeof(cellStruct
) * cols
);
153 for (j
= m_NumCols
; j
< cols
; j
++)
154 m_CellInfo
[i
][j
].flag
= cellFree
;
157 m_ColsInfo
= (colStruct
*) realloc(m_ColsInfo
, sizeof(colStruct
) * cols
);
158 for (j
= m_NumCols
; j
< cols
; j
++) {
159 m_ColsInfo
[j
].width
= 0;
160 m_ColsInfo
[j
].units
= HTML_UNITS_PERCENT
;
168 void wxHtmlTableCell::ReallocRows(int rows
)
170 m_CellInfo
= (cellStruct
**) realloc(m_CellInfo
, sizeof(cellStruct
*) * rows
);
171 if (m_NumCols
!= 0) {
173 m_CellInfo
[x
] = (cellStruct
*) malloc(sizeof(cellStruct
) * m_NumCols
);
174 for (int i
= 0; i
< m_NumCols
; i
++)
175 m_CellInfo
[x
][i
].flag
= cellFree
;
178 m_CellInfo
[rows
- 1] = NULL
;
184 void wxHtmlTableCell::AddRow(const wxHtmlTag
& tag
)
186 if (m_ActualRow
+ 1 > m_NumRows
- 1)
187 ReallocRows(m_ActualRow
+ 2);
193 if (tag
.HasParam("BGCOLOR")) tag
.ScanParam("BGCOLOR", "#%lX", &m_rBkg
);
194 if (tag
.HasParam("VALIGN")) m_rValign
= tag
.GetParam("VALIGN"); else m_rValign
= m_tValign
;
199 void wxHtmlTableCell::AddCell(wxHtmlContainerCell
*cell
, const wxHtmlTag
& tag
)
203 } while ((m_ActualCol
< m_NumCols
) && (m_CellInfo
[m_ActualRow
][m_ActualCol
].flag
!= cellFree
));
204 if (m_ActualCol
> m_NumCols
- 1)
205 ReallocCols(m_ActualCol
+ 1);
207 int r
= m_ActualRow
, c
= m_ActualCol
;
209 m_CellInfo
[r
][c
].cont
= cell
;
210 m_CellInfo
[r
][c
].colspan
= 1;
211 m_CellInfo
[r
][c
].rowspan
= 1;
212 m_CellInfo
[r
][c
].flag
= cellUsed
;
213 m_CellInfo
[r
][c
].minheight
= 0;
214 m_CellInfo
[r
][c
].valign
= HTML_ALIGN_TOP
;
216 /* scan for parameters: */
220 if (tag
.HasParam("WIDTH")) {
221 wxString wd
= tag
.GetParam("WIDTH");
223 if (wd
[wd
.Length()-1] == '%') {
224 sscanf(wd
.c_str(), "%i%%", &m_ColsInfo
[c
].width
);
225 m_ColsInfo
[c
].units
= HTML_UNITS_PERCENT
;
228 sscanf(wd
.c_str(), "%i", &m_ColsInfo
[c
].width
);
229 m_ColsInfo
[c
].units
= HTML_UNITS_PIXELS
;
237 if (tag
.HasParam("COLSPAN")) tag
.ScanParam("COLSPAN", "%i", &m_CellInfo
[r
][c
].colspan
);
238 if (tag
.HasParam("ROWSPAN")) tag
.ScanParam("ROWSPAN", "%i", &m_CellInfo
[r
][c
].rowspan
);
239 if ((m_CellInfo
[r
][c
].colspan
!= 1) || (m_CellInfo
[r
][c
].rowspan
!= 1)) {
242 if (r
+ m_CellInfo
[r
][c
].rowspan
> m_NumRows
) ReallocRows(r
+ m_CellInfo
[r
][c
].rowspan
);
243 if (c
+ m_CellInfo
[r
][c
].colspan
> m_NumCols
) ReallocCols(c
+ m_CellInfo
[r
][c
].colspan
);
244 for (i
= r
; i
< r
+ m_CellInfo
[r
][c
].rowspan
; i
++)
245 for (j
= c
; j
< c
+ m_CellInfo
[r
][c
].colspan
; j
++)
246 m_CellInfo
[i
][j
].flag
= cellSpan
;
247 m_CellInfo
[r
][c
].flag
= cellUsed
;
254 if (tag
.HasParam("BGCOLOR")) tag
.ScanParam("BGCOLOR", "#%lX", &bk
);
256 wxColour clr
= wxColour((bk
& 0xFF0000) >> 16 , (bk
& 0x00FF00) >> 8, (bk
& 0x0000FF));
257 cell
-> SetBackgroundColour(clr
);
261 cell
-> SetBorder(TABLE_BORDER_CLR_2
, TABLE_BORDER_CLR_1
);
263 // vertical alignment:
266 if (tag
.HasParam("VALIGN")) valign
= tag
.GetParam("VALIGN"); else valign
= m_tValign
;
268 if (valign
== "TOP") m_CellInfo
[r
][c
].valign
= HTML_ALIGN_TOP
;
269 else if (valign
== "BOTTOM") m_CellInfo
[r
][c
].valign
= HTML_ALIGN_BOTTOM
;
270 else m_CellInfo
[r
][c
].valign
= HTML_ALIGN_CENTER
;
273 cell
-> SetIndent(m_Padding
, HTML_INDENT_ALL
, HTML_UNITS_PIXELS
);
280 void wxHtmlTableCell::Layout(int w
)
288 if (m_WidthFloatUnits
== HTML_UNITS_PERCENT
) {
289 if (m_WidthFloat
< 0) m_Width
= (100 + m_WidthFloat
) * w
/ 100;
290 else m_Width
= m_WidthFloat
* w
/ 100;
293 if (m_WidthFloat
< 0) m_Width
= w
+ m_WidthFloat
;
294 else m_Width
= m_WidthFloat
;
304 /* 1. setup columns widths: */
306 int wpix
= m_Width
- (m_NumCols
+ 1) * m_Spacing
;
310 // 1a. setup fixed-width columns:
311 for (i
= 0; i
< m_NumCols
; i
++)
312 if (m_ColsInfo
[i
].units
== HTML_UNITS_PIXELS
)
313 wpix
-= (m_ColsInfo
[i
].pixwidth
= m_ColsInfo
[i
].width
);
315 // 1b. setup floating-width columns:
316 for (i
= 0; i
< m_NumCols
; i
++)
317 if ((m_ColsInfo
[i
].units
== HTML_UNITS_PERCENT
) && (m_ColsInfo
[i
].width
!= 0))
318 wtemp
+= (m_ColsInfo
[i
].pixwidth
= m_ColsInfo
[i
].width
* wpix
/ 100);
321 // 1c. setup defalut columns (no width specification supplied):
322 // NOTE! This algorithm doesn't conform to HTML standard : it assigns equal widths
323 // instead of optimal
324 for (i
= j
= 0; i
< m_NumCols
; i
++)
325 if (m_ColsInfo
[i
].width
== 0) j
++;
326 for (i
= 0; i
< m_NumCols
; i
++)
327 if (m_ColsInfo
[i
].width
== 0)
328 m_ColsInfo
[i
].pixwidth
= wpix
/ j
;
331 /* 2. compute positions of columns: */
333 int wpos
= m_Spacing
;
334 for (int i
= 0; i
< m_NumCols
; i
++) {
335 m_ColsInfo
[i
].leftpos
= wpos
;
336 wpos
+= m_ColsInfo
[i
].pixwidth
+ m_Spacing
;
340 /* 3. sub-layout all cells: */
342 int *ypos
= new int[m_NumRows
+ 1];
346 wxHtmlContainerCell
*actcell
;
348 for (actrow
= 0; actrow
<= m_NumRows
; actrow
++) ypos
[actrow
] = m_Spacing
;
350 for (actrow
= 0; actrow
< m_NumRows
; actrow
++) {
352 // 3a. sub-layout and detect max height:
354 for (actcol
= 0; actcol
< m_NumCols
; actcol
++) {
355 if (m_CellInfo
[actrow
][actcol
].flag
!= cellUsed
) continue;
356 actcell
= m_CellInfo
[actrow
][actcol
].cont
;
358 for (int i
= actcol
; i
< m_CellInfo
[actrow
][actcol
].colspan
+ actcol
; i
++)
359 fullwid
+= m_ColsInfo
[i
].pixwidth
;
360 actcell
-> SetMinHeight(m_CellInfo
[actrow
][actcol
].minheight
, m_CellInfo
[actrow
][actcol
].valign
);
361 actcell
-> Layout(fullwid
);
363 if (ypos
[actrow
] + actcell
-> GetHeight() + m_CellInfo
[actrow
][actcol
].rowspan
* m_Spacing
> ypos
[actrow
+ m_CellInfo
[actrow
][actcol
].rowspan
])
364 ypos
[actrow
+ m_CellInfo
[actrow
][actcol
].rowspan
] =
365 ypos
[actrow
] + actcell
-> GetHeight() + m_CellInfo
[actrow
][actcol
].rowspan
* m_Spacing
;
370 for (actrow
= 0; actrow
< m_NumRows
; actrow
++) {
372 // 3b. place cells in row & let'em all have same height:
374 for (actcol
= 0; actcol
< m_NumCols
; actcol
++) {
375 if (m_CellInfo
[actrow
][actcol
].flag
!= cellUsed
) continue;
376 actcell
= m_CellInfo
[actrow
][actcol
].cont
;
377 actcell
-> SetMinHeight(
378 ypos
[actrow
+ m_CellInfo
[actrow
][actcol
].rowspan
] - ypos
[actrow
] - m_CellInfo
[actrow
][actcol
].rowspan
* m_Spacing
,
379 m_CellInfo
[actrow
][actcol
].valign
);
381 for (int i
= actcol
; i
< m_CellInfo
[actrow
][actcol
].colspan
+ actcol
; i
++)
382 fullwid
+= m_ColsInfo
[i
].pixwidth
;
383 actcell
-> Layout(fullwid
);
384 actcell
-> SetPos(m_ColsInfo
[actcol
].leftpos
, ypos
[actrow
]);
388 m_Height
= ypos
[m_NumRows
];
398 //-----------------------------------------------------------------------------
399 // The tables handler:
400 //-----------------------------------------------------------------------------
403 TAG_HANDLER_BEGIN(TABLE
, "TABLE,TR,TD,TH")
406 wxHtmlTableCell
* m_Table
;
407 wxString m_tAlign
, m_rAlign
;
410 TAG_HANDLER_CONSTR(TABLE
)
413 m_tAlign
= m_rAlign
= wxEmptyString
;
414 m_OldAlign
= HTML_ALIGN_LEFT
;
418 TAG_HANDLER_PROC(tag
)
420 wxHtmlContainerCell
*c
;
422 // new table started, backup upper-level table (if any) and create new:
423 if (tag
.GetName() == "TABLE") {
424 wxHtmlTableCell
*oldt
= m_Table
;
425 wxHtmlContainerCell
*oldcont
;
428 oldcont
= c
= m_WParser
-> OpenContainer();
430 c
-> SetWidthFloat(tag
);
431 m_Table
= new wxHtmlTableCell(c
, tag
);
432 m_OldAlign
= m_WParser
-> GetAlign();
433 m_tAlign
= wxEmptyString
;
434 if (tag
.HasParam("ALIGN")) m_tAlign
= tag
.GetParam("ALIGN");
438 m_WParser
-> SetAlign(m_OldAlign
);
439 m_WParser
-> SetContainer(oldcont
);
440 m_WParser
-> CloseContainer();
446 else if (m_Table
&& !tag
.IsEnding()) {
448 if (tag
.GetName() == "TR") {
449 m_Table
-> AddRow(tag
);
451 if (tag
.HasParam("ALIGN")) m_rAlign
= tag
.GetParam("ALIGN");
456 m_WParser
-> SetAlign(m_OldAlign
);
457 c
= m_WParser
-> SetContainer(new wxHtmlContainerCell(m_Table
));
458 m_Table
-> AddCell(c
, tag
);
460 m_WParser
-> OpenContainer();
462 if (tag
.GetName() == "TH") /*header style*/ {
463 m_WParser
-> SetAlign(HTML_ALIGN_CENTER
);
470 if (tag
.HasParam("ALIGN")) als
= tag
.GetParam("ALIGN");
472 if (als
== "RIGHT(") m_WParser
-> SetAlign(HTML_ALIGN_RIGHT
);
473 else if (als
== "CENTER") m_WParser
-> SetAlign(HTML_ALIGN_CENTER
);
475 m_WParser
-> OpenContainer();
481 TAG_HANDLER_END(TABLE
)
487 TAGS_MODULE_BEGIN(Tables
)
489 TAGS_MODULE_ADD(TABLE
)
491 TAGS_MODULE_END(Tables
)