]>
git.saurik.com Git - wxWidgets.git/blob - src/html/m_tables.cpp
1 /////////////////////////////////////////////////////////////////////////////
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"
29 1. This version of m_tables doesn't support auto-layout algorithm.
30 This means that all columns are of same width unless explicitly specified.
34 #include "wx/html/forcelnk.h"
35 #include "wx/html/m_templ.h"
37 #include "wx/html/htmlcell.h"
39 FORCE_LINK_ME(m_tables
)
42 #define TABLE_BORDER_CLR_1 wxColour(0xC5, 0xC2, 0xC5)
43 #define TABLE_BORDER_CLR_2 wxColour(0x62, 0x61, 0x62)
46 //-----------------------------------------------------------------------------
48 //-----------------------------------------------------------------------------
52 int width
, units
; // universal
53 int leftpos
, pixwidth
, maxrealwidth
; // temporary (depends on width of table)
63 wxHtmlContainerCell
*cont
;
65 int minheight
, valign
;
70 class wxHtmlTableCell
: public wxHtmlContainerCell
73 /* These are real attributes: */
75 // should we draw borders or not?
76 int m_NumCols
, m_NumRows
;
77 // number of columns; rows
78 colStruct
*m_ColsInfo
;
79 // array of column information
80 cellStruct
**m_CellInfo
;
81 // 2D array of all cells in the table : m_CellInfo[row][column]
83 // spaces between cells
85 // cells internal indentation
88 /* ...and these are valid only during parsing of table: */
89 int m_ActualCol
, m_ActualRow
;
90 // number of actual column (ranging from 0..m_NumCols)
92 // default values (for table and row):
94 wxString m_tValign
, m_rValign
;
100 wxHtmlTableCell(wxHtmlContainerCell
*parent
, const wxHtmlTag
& tag
, double pixel_scale
= 1.0);
102 virtual void Layout(int w
);
104 void AddRow(const wxHtmlTag
& tag
);
105 void AddCell(wxHtmlContainerCell
*cell
, const wxHtmlTag
& tag
);
107 void ReallocCols(int cols
);
108 void ReallocRows(int rows
);
109 // reallocates memory to given number of cols/rows
110 // and changes m_NumCols/m_NumRows value to reflect this change
111 // NOTE! You CAN'T change m_NumCols/m_NumRows before calling this!!
116 wxHtmlTableCell::wxHtmlTableCell(wxHtmlContainerCell
*parent
, const wxHtmlTag
& tag
, double pixel_scale
)
117 : wxHtmlContainerCell(parent
)
119 m_PixelScale
= pixel_scale
;
120 m_HasBorders
= (tag
.HasParam(wxT("BORDER")) && tag
.GetParam(wxT("BORDER")) != wxT("0"));
122 m_NumCols
= m_NumRows
= 0;
124 m_ActualCol
= m_ActualRow
= -1;
127 m_tBkg
= m_rBkg
= -1;
128 if (tag
.HasParam(wxT("BGCOLOR"))) tag
.ScanParam(wxT("BGCOLOR"), wxT("#%lX"), &m_tBkg
);
129 if (tag
.HasParam(wxT("VALIGN"))) m_tValign
= tag
.GetParam(wxT("VALIGN")); else m_tValign
= wxEmptyString
;
130 if (tag
.HasParam(wxT("CELLSPACING")) && tag
.ScanParam(wxT("CELLSPACING"), wxT("%i"), &m_Spacing
) == 1) {} else m_Spacing
= 2;
131 if (tag
.HasParam(wxT("CELLPADDING")) && tag
.ScanParam(wxT("CELLPADDING"), wxT("%i"), &m_Padding
) == 1) {} else m_Padding
= 3;
132 m_Spacing
= (int)(m_PixelScale
* (double)m_Spacing
);
133 m_Padding
= (int)(m_PixelScale
* (double)m_Padding
);
136 SetBorder(TABLE_BORDER_CLR_1
, TABLE_BORDER_CLR_2
);
141 wxHtmlTableCell::~wxHtmlTableCell()
143 if (m_ColsInfo
) free(m_ColsInfo
);
145 for (int i
= 0; i
< m_NumRows
; i
++)
153 void wxHtmlTableCell::ReallocCols(int cols
)
157 for (i
= 0; i
< m_NumRows
; i
++) {
158 m_CellInfo
[i
] = (cellStruct
*) realloc(m_CellInfo
[i
], sizeof(cellStruct
) * cols
);
159 for (j
= m_NumCols
; j
< cols
; j
++)
160 m_CellInfo
[i
][j
].flag
= cellFree
;
163 m_ColsInfo
= (colStruct
*) realloc(m_ColsInfo
, sizeof(colStruct
) * cols
);
164 for (j
= m_NumCols
; j
< cols
; j
++) {
165 m_ColsInfo
[j
].width
= 0;
166 m_ColsInfo
[j
].units
= wxHTML_UNITS_PERCENT
;
174 void wxHtmlTableCell::ReallocRows(int rows
)
176 m_CellInfo
= (cellStruct
**) realloc(m_CellInfo
, sizeof(cellStruct
*) * rows
);
177 for (int row
= m_NumRows
; row
< rows
; row
++)
180 m_CellInfo
[row
] = NULL
;
183 m_CellInfo
[row
] = (cellStruct
*) malloc(sizeof(cellStruct
) * m_NumCols
);
184 for (int col
= 0; col
< m_NumCols
; col
++)
185 m_CellInfo
[row
][col
].flag
= cellFree
;
192 void wxHtmlTableCell::AddRow(const wxHtmlTag
& tag
)
194 if (m_ActualRow
+ 1 > m_NumRows
- 1)
195 ReallocRows(m_ActualRow
+ 2);
201 if (tag
.HasParam(wxT("BGCOLOR"))) tag
.ScanParam(wxT("BGCOLOR"), wxT("#%lX"), &m_rBkg
);
202 if (tag
.HasParam(wxT("VALIGN"))) m_rValign
= tag
.GetParam(wxT("VALIGN")); else m_rValign
= m_tValign
;
207 void wxHtmlTableCell::AddCell(wxHtmlContainerCell
*cell
, const wxHtmlTag
& tag
)
211 } while ((m_ActualCol
< m_NumCols
) && (m_CellInfo
[m_ActualRow
][m_ActualCol
].flag
!= cellFree
));
212 if (m_ActualCol
> m_NumCols
- 1)
213 ReallocCols(m_ActualCol
+ 1);
215 int r
= m_ActualRow
, c
= m_ActualCol
;
217 m_CellInfo
[r
][c
].cont
= cell
;
218 m_CellInfo
[r
][c
].colspan
= 1;
219 m_CellInfo
[r
][c
].rowspan
= 1;
220 m_CellInfo
[r
][c
].flag
= cellUsed
;
221 m_CellInfo
[r
][c
].minheight
= 0;
222 m_CellInfo
[r
][c
].valign
= wxHTML_ALIGN_TOP
;
224 /* scan for parameters: */
228 if (tag
.HasParam("WIDTH")) {
229 wxString wd
= tag
.GetParam("WIDTH");
231 if (wd
[wd
.Length()-1] == '%') {
232 wxSscanf(wd
.c_str(), wxT("%i%%"), &m_ColsInfo
[c
].width
);
233 m_ColsInfo
[c
].units
= wxHTML_UNITS_PERCENT
;
236 wxSscanf(wd
.c_str(), wxT("%i"), &m_ColsInfo
[c
].width
);
237 m_ColsInfo
[c
].width
= (int)(m_PixelScale
* (double)m_ColsInfo
[c
].width
);
238 m_ColsInfo
[c
].units
= wxHTML_UNITS_PIXELS
;
246 if (tag
.HasParam(wxT("COLSPAN"))) tag
.ScanParam(wxT("COLSPAN"), wxT("%i"), &m_CellInfo
[r
][c
].colspan
);
247 if (tag
.HasParam(wxT("ROWSPAN"))) tag
.ScanParam(wxT("ROWSPAN"), wxT("%i"), &m_CellInfo
[r
][c
].rowspan
);
248 if ((m_CellInfo
[r
][c
].colspan
!= 1) || (m_CellInfo
[r
][c
].rowspan
!= 1)) {
251 if (r
+ m_CellInfo
[r
][c
].rowspan
> m_NumRows
) ReallocRows(r
+ m_CellInfo
[r
][c
].rowspan
);
252 if (c
+ m_CellInfo
[r
][c
].colspan
> m_NumCols
) ReallocCols(c
+ m_CellInfo
[r
][c
].colspan
);
253 for (i
= r
; i
< r
+ m_CellInfo
[r
][c
].rowspan
; i
++)
254 for (j
= c
; j
< c
+ m_CellInfo
[r
][c
].colspan
; j
++)
255 m_CellInfo
[i
][j
].flag
= cellSpan
;
256 m_CellInfo
[r
][c
].flag
= cellUsed
;
263 if (tag
.HasParam(wxT("BGCOLOR"))) tag
.ScanParam(wxT("BGCOLOR"), wxT("#%lX"), &bk
);
265 wxColour clr
= wxColour((bk
& 0xFF0000) >> 16 , (bk
& 0x00FF00) >> 8, (bk
& 0x0000FF));
266 cell
-> SetBackgroundColour(clr
);
270 cell
-> SetBorder(TABLE_BORDER_CLR_2
, TABLE_BORDER_CLR_1
);
272 // vertical alignment:
275 if (tag
.HasParam(wxT("VALIGN"))) valign
= tag
.GetParam(wxT("VALIGN")); else valign
= m_tValign
;
277 if (valign
== wxT("TOP")) m_CellInfo
[r
][c
].valign
= wxHTML_ALIGN_TOP
;
278 else if (valign
== wxT("BOTTOM")) m_CellInfo
[r
][c
].valign
= wxHTML_ALIGN_BOTTOM
;
279 else m_CellInfo
[r
][c
].valign
= wxHTML_ALIGN_CENTER
;
282 cell
-> SetIndent(m_Padding
, wxHTML_INDENT_ALL
, wxHTML_UNITS_PIXELS
);
289 void wxHtmlTableCell::Layout(int w
)
297 if (m_WidthFloatUnits
== wxHTML_UNITS_PERCENT
) {
298 if (m_WidthFloat
< 0) m_Width
= (100 + m_WidthFloat
) * w
/ 100;
299 else m_Width
= m_WidthFloat
* w
/ 100;
302 if (m_WidthFloat
< 0) m_Width
= w
+ m_WidthFloat
;
303 else m_Width
= m_WidthFloat
;
313 /* 1. setup columns widths: */
315 int wpix
= m_Width
- (m_NumCols
+ 1) * m_Spacing
;
319 // 1a. setup fixed-width columns:
320 for (i
= 0; i
< m_NumCols
; i
++)
321 if (m_ColsInfo
[i
].units
== wxHTML_UNITS_PIXELS
)
322 wpix
-= (m_ColsInfo
[i
].pixwidth
= m_ColsInfo
[i
].width
);
324 // 1b. setup floating-width columns:
325 for (i
= 0; i
< m_NumCols
; i
++)
326 if ((m_ColsInfo
[i
].units
== wxHTML_UNITS_PERCENT
) && (m_ColsInfo
[i
].width
!= 0))
327 wtemp
+= (m_ColsInfo
[i
].pixwidth
= m_ColsInfo
[i
].width
* wpix
/ 100);
330 // 1c. setup defalut columns (no width specification supplied):
331 // NOTE! This algorithm doesn't conform to HTML standard : it assigns equal widths
332 // instead of optimal
333 for (i
= j
= 0; i
< m_NumCols
; i
++)
334 if (m_ColsInfo
[i
].width
== 0) j
++;
335 for (i
= 0; i
< m_NumCols
; i
++)
336 if (m_ColsInfo
[i
].width
== 0)
337 m_ColsInfo
[i
].pixwidth
= wpix
/ j
;
340 /* 2. compute positions of columns: */
342 int wpos
= m_Spacing
;
343 for (int i
= 0; i
< m_NumCols
; i
++) {
344 m_ColsInfo
[i
].leftpos
= wpos
;
345 wpos
+= m_ColsInfo
[i
].pixwidth
+ m_Spacing
;
349 /* 3. sub-layout all cells: */
351 int *ypos
= new int[m_NumRows
+ 1];
355 wxHtmlContainerCell
*actcell
;
357 for (actrow
= 0; actrow
<= m_NumRows
; actrow
++) ypos
[actrow
] = m_Spacing
;
359 for (actrow
= 0; actrow
< m_NumRows
; actrow
++) {
361 // 3a. sub-layout and detect max height:
363 for (actcol
= 0; actcol
< m_NumCols
; actcol
++) {
364 if (m_CellInfo
[actrow
][actcol
].flag
!= cellUsed
) continue;
365 actcell
= m_CellInfo
[actrow
][actcol
].cont
;
367 for (int i
= actcol
; i
< m_CellInfo
[actrow
][actcol
].colspan
+ actcol
; i
++)
368 fullwid
+= m_ColsInfo
[i
].pixwidth
;
369 fullwid
+= (m_CellInfo
[actrow
][actcol
].colspan
- 1) * m_Spacing
;
370 actcell
-> SetMinHeight(m_CellInfo
[actrow
][actcol
].minheight
, m_CellInfo
[actrow
][actcol
].valign
);
371 actcell
-> Layout(fullwid
);
373 if (ypos
[actrow
] + actcell
-> GetHeight() + m_CellInfo
[actrow
][actcol
].rowspan
* m_Spacing
> ypos
[actrow
+ m_CellInfo
[actrow
][actcol
].rowspan
])
374 ypos
[actrow
+ m_CellInfo
[actrow
][actcol
].rowspan
] =
375 ypos
[actrow
] + actcell
-> GetHeight() + m_CellInfo
[actrow
][actcol
].rowspan
* m_Spacing
;
380 for (actrow
= 0; actrow
< m_NumRows
; actrow
++) {
382 // 3b. place cells in row & let'em all have same height:
384 for (actcol
= 0; actcol
< m_NumCols
; actcol
++) {
385 if (m_CellInfo
[actrow
][actcol
].flag
!= cellUsed
) continue;
386 actcell
= m_CellInfo
[actrow
][actcol
].cont
;
387 actcell
-> SetMinHeight(
388 ypos
[actrow
+ m_CellInfo
[actrow
][actcol
].rowspan
] - ypos
[actrow
] - m_Spacing
,
389 m_CellInfo
[actrow
][actcol
].valign
);
391 for (int i
= actcol
; i
< m_CellInfo
[actrow
][actcol
].colspan
+ actcol
; i
++)
392 fullwid
+= m_ColsInfo
[i
].pixwidth
;
393 fullwid
+= (m_CellInfo
[actrow
][actcol
].colspan
- 1) * m_Spacing
;
394 actcell
-> Layout(fullwid
);
395 actcell
-> SetPos(m_ColsInfo
[actcol
].leftpos
, ypos
[actrow
]);
399 m_Height
= ypos
[m_NumRows
];
409 //-----------------------------------------------------------------------------
410 // The tables handler:
411 //-----------------------------------------------------------------------------
414 TAG_HANDLER_BEGIN(TABLE
, "TABLE,TR,TD,TH")
417 wxHtmlTableCell
* m_Table
;
418 wxString m_tAlign
, m_rAlign
;
421 TAG_HANDLER_CONSTR(TABLE
)
424 m_tAlign
= m_rAlign
= wxEmptyString
;
425 m_OldAlign
= wxHTML_ALIGN_LEFT
;
429 TAG_HANDLER_PROC(tag
)
431 wxHtmlContainerCell
*c
;
433 // new table started, backup upper-level table (if any) and create new:
434 if (tag
.GetName() == wxT("TABLE")) {
435 wxHtmlTableCell
*oldt
= m_Table
;
436 wxHtmlContainerCell
*oldcont
;
439 oldcont
= c
= m_WParser
-> OpenContainer();
441 c
-> SetWidthFloat(tag
, m_WParser
-> GetPixelScale());
442 m_Table
= new wxHtmlTableCell(c
, tag
, m_WParser
-> GetPixelScale());
443 m_OldAlign
= m_WParser
-> GetAlign();
444 m_tAlign
= wxEmptyString
;
445 if (tag
.HasParam(wxT("ALIGN"))) m_tAlign
= tag
.GetParam(wxT("ALIGN"));
449 m_WParser
-> SetAlign(m_OldAlign
);
450 m_WParser
-> SetContainer(oldcont
);
451 m_WParser
-> CloseContainer();
457 else if (m_Table
&& !tag
.IsEnding()) {
459 if (tag
.GetName() == wxT("TR")) {
460 m_Table
-> AddRow(tag
);
462 if (tag
.HasParam(wxT("ALIGN"))) m_rAlign
= tag
.GetParam(wxT("ALIGN"));
467 m_WParser
-> SetAlign(m_OldAlign
);
468 c
= m_WParser
-> SetContainer(new wxHtmlContainerCell(m_Table
));
469 m_Table
-> AddCell(c
, tag
);
471 m_WParser
-> OpenContainer();
473 if (tag
.GetName() == wxT("TH")) /*header style*/ {
474 m_WParser
-> SetAlign(wxHTML_ALIGN_CENTER
);
481 if (tag
.HasParam(wxT("ALIGN"))) als
= tag
.GetParam(wxT("ALIGN"));
483 if (als
== wxT("RIGHT")) m_WParser
-> SetAlign(wxHTML_ALIGN_RIGHT
);
484 else if (als
== wxT("CENTER")) m_WParser
-> SetAlign(wxHTML_ALIGN_CENTER
);
486 m_WParser
-> OpenContainer();
492 TAG_HANDLER_END(TABLE
)
498 TAGS_MODULE_BEGIN(Tables
)
500 TAGS_MODULE_ADD(TABLE
)
502 TAGS_MODULE_END(Tables
)