]> git.saurik.com Git - wxWidgets.git/blob - src/html/htmlcell.cpp
6979805f45fd302dc65e6dc5dad703716a108a75
[wxWidgets.git] / src / html / htmlcell.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: htmlcell.cpp
3 // Purpose: wxHtmlCell - basic element of HTML output
4 // Author: Vaclav Slavik
5 // RCS-ID: $Id$
6 // Copyright: (c) 1999 Vaclav Slavik
7 // Licence: wxWindows Licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation
12 #endif
13
14 #include "wx/wxprec.h"
15
16 #if wxUSE_HTML
17
18 #ifdef __BORDLANDC__
19 #pragma hdrstop
20 #endif
21
22 #ifndef WXPRECOMP
23 #include "wx/wx.h"
24 #endif
25
26 #include "wx/html/htmlcell.h"
27 #include "wx/html/htmlwin.h"
28 #include <stdlib.h>
29
30
31 //-----------------------------------------------------------------------------
32 // wxHtmlCell
33 //-----------------------------------------------------------------------------
34
35
36 void wxHtmlCell::OnMouseClick(wxWindow *parent, int x, int y,
37 bool WXUNUSED(left),
38 bool WXUNUSED(middle),
39 bool WXUNUSED(right))
40 {
41 wxString lnk = GetLink(x, y);
42 if (lnk != wxEmptyString)
43 ((wxHtmlWindow*)parent) -> OnLinkClicked(lnk);
44 // note : this overcasting is legal because parent is *always* wxHtmlWindow
45 }
46
47
48
49 bool wxHtmlCell::AdjustPagebreak(int *pagebreak)
50 {
51
52 if ((!m_CanLiveOnPagebreak) &&
53 m_PosY < *pagebreak && m_PosY + m_Height > *pagebreak) {
54 *pagebreak = m_PosY;
55 if (m_Next != NULL) m_Next -> AdjustPagebreak(pagebreak);
56 return TRUE;
57 }
58
59 else {
60 if (m_Next != NULL) return m_Next -> AdjustPagebreak(pagebreak);
61 else return FALSE;
62 }
63 }
64
65
66
67
68 //-----------------------------------------------------------------------------
69 // wxHtmlWordCell
70 //-----------------------------------------------------------------------------
71
72 wxHtmlWordCell::wxHtmlWordCell(const wxString& word, wxDC& dc) : wxHtmlCell()
73 {
74 m_Word = word;
75 m_Word.Replace("&nbsp;", " ", TRUE);
76 m_Word.Replace("&quot;", "\"", TRUE);
77 m_Word.Replace("&lt;", "<", TRUE);
78 m_Word.Replace("&gt;", ">", TRUE);
79 m_Word.Replace("&amp;", "&", TRUE);
80 dc.GetTextExtent(m_Word, &m_Width, &m_Height, &m_Descent);
81 SetCanLiveOnPagebreak(FALSE);
82 }
83
84
85
86 void wxHtmlWordCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
87 {
88 dc.DrawText(m_Word, x + m_PosX, y + m_PosY);
89 wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
90 }
91
92
93
94 //-----------------------------------------------------------------------------
95 // wxHtmlContainerCell
96 //-----------------------------------------------------------------------------
97
98
99 wxHtmlContainerCell::wxHtmlContainerCell(wxHtmlContainerCell *parent) : wxHtmlCell()
100 {
101 m_Cells = m_LastCell = NULL;
102 m_Parent = parent;
103 if (m_Parent) m_Parent -> InsertCell(this);
104 m_AlignHor = wxHTML_ALIGN_LEFT;
105 m_AlignVer = wxHTML_ALIGN_BOTTOM;
106 m_IndentLeft = m_IndentRight = m_IndentTop = m_IndentBottom = 0;
107 m_WidthFloat = 100; m_WidthFloatUnits = wxHTML_UNITS_PERCENT;
108 m_UseBkColour = FALSE;
109 m_UseBorder = FALSE;
110 m_MinHeight = m_MaxLineWidth = 0;
111 m_MinHeightAlign = wxHTML_ALIGN_TOP;
112 }
113
114
115
116 void wxHtmlContainerCell::SetIndent(int i, int what, int units)
117 {
118 int val = (units == wxHTML_UNITS_PIXELS) ? i : -i;
119 if (what & wxHTML_INDENT_LEFT) m_IndentLeft = val;
120 if (what & wxHTML_INDENT_RIGHT) m_IndentRight = val;
121 if (what & wxHTML_INDENT_TOP) m_IndentTop = val;
122 if (what & wxHTML_INDENT_BOTTOM) m_IndentBottom = val;
123 }
124
125
126
127 int wxHtmlContainerCell::GetIndent(int ind) const
128 {
129 if (ind & wxHTML_INDENT_LEFT) return m_IndentLeft;
130 else if (ind & wxHTML_INDENT_RIGHT) return m_IndentRight;
131 else if (ind & wxHTML_INDENT_TOP) return m_IndentTop;
132 else if (ind & wxHTML_INDENT_BOTTOM) return m_IndentBottom;
133 else return -1; /* BUG! Should not be called... */
134 }
135
136
137
138
139 int wxHtmlContainerCell::GetIndentUnits(int ind) const
140 {
141 bool p = FALSE;
142 if (ind & wxHTML_INDENT_LEFT) p = m_IndentLeft < 0;
143 else if (ind & wxHTML_INDENT_RIGHT) p = m_IndentRight < 0;
144 else if (ind & wxHTML_INDENT_TOP) p = m_IndentTop < 0;
145 else if (ind & wxHTML_INDENT_BOTTOM) p = m_IndentBottom < 0;
146 if (p) return wxHTML_UNITS_PERCENT;
147 else return wxHTML_UNITS_PIXELS;
148 }
149
150
151
152 bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak)
153 {
154 if (!m_CanLiveOnPagebreak)
155 return wxHtmlCell::AdjustPagebreak(pagebreak);
156
157 else {
158 wxHtmlCell *c = GetFirstCell();
159 bool rt = FALSE;
160 int pbrk = *pagebreak - m_PosY;
161
162 while (c) {
163 if (c -> AdjustPagebreak(&pbrk)) rt = TRUE;
164 c = c -> GetNext();
165 }
166 if (rt) *pagebreak = pbrk + m_PosY;
167 return rt;
168 }
169 }
170
171
172
173 void wxHtmlContainerCell::Layout(int w)
174 {
175 wxHtmlCell *cell = m_Cells, *line = m_Cells;
176 long xpos = 0, ypos = m_IndentTop;
177 int xdelta = 0, ybasicpos = 0, ydiff;
178 int s_width, s_indent;
179 int ysizeup = 0, ysizedown = 0;
180
181 /*
182
183 WIDTH ADJUSTING :
184
185 */
186
187 if (m_WidthFloatUnits == wxHTML_UNITS_PERCENT) {
188 if (m_WidthFloat < 0) m_Width = (100 + m_WidthFloat) * w / 100;
189 else m_Width = m_WidthFloat * w / 100;
190 }
191 else {
192 if (m_WidthFloat < 0) m_Width = w + m_WidthFloat;
193 else m_Width = m_WidthFloat;
194 }
195
196 if (m_Cells) {
197 int l = (m_IndentLeft < 0) ? (-m_IndentLeft * m_Width / 100) : m_IndentLeft;
198 int r = (m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight;
199 m_Cells -> Layout(m_Width - (l + r));
200 }
201
202 /*
203
204 LAYOUTING :
205
206 */
207
208 // adjust indentation:
209 s_indent = (m_IndentLeft < 0) ? (-m_IndentLeft * m_Width / 100) : m_IndentLeft;
210 s_width = m_Width - s_indent - ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
211
212 m_MaxLineWidth = 0;
213
214 // my own layouting:
215 while (cell != NULL) {
216 switch (m_AlignVer) {
217 case wxHTML_ALIGN_TOP : ybasicpos = 0; break;
218 case wxHTML_ALIGN_BOTTOM : ybasicpos = - cell -> GetHeight(); break;
219 case wxHTML_ALIGN_CENTER : ybasicpos = - cell -> GetHeight() / 2; break;
220 }
221 ydiff = cell -> GetHeight() + ybasicpos;
222
223 if (cell -> GetDescent() + ydiff > ysizedown) ysizedown = cell -> GetDescent() + ydiff;
224 if (ybasicpos + cell -> GetDescent() < -ysizeup) ysizeup = - (ybasicpos + cell -> GetDescent());
225
226 cell -> SetPos(xpos, ybasicpos + cell -> GetDescent());
227 xpos += cell -> GetWidth();
228 cell = cell -> GetNext();
229
230 // force new line if occured:
231 if ((cell == NULL) || (xpos + cell -> GetWidth() > s_width)) {
232 if (xpos > m_MaxLineWidth) m_MaxLineWidth = xpos;
233 if (ysizeup < 0) ysizeup = 0;
234 if (ysizedown < 0) ysizedown = 0;
235 switch (m_AlignHor) {
236 case wxHTML_ALIGN_LEFT : xdelta = 0; break;
237 case wxHTML_ALIGN_RIGHT : xdelta = 0 + (s_width - xpos); break;
238 case wxHTML_ALIGN_CENTER : xdelta = 0 + (s_width - xpos) / 2; break;
239 }
240 if (xdelta < 0) xdelta = 0;
241 xdelta += s_indent;
242
243 ypos += ysizeup;
244 while (line != cell) {
245 line -> SetPos(line -> GetPosX() + xdelta, ypos + line -> GetPosY());
246 line = line -> GetNext();
247 }
248
249 ypos += ysizedown;
250 xpos = 0;
251 ysizeup = ysizedown = 0;
252 line = cell;
253 }
254 }
255
256 // setup height & width, depending on container layout:
257 m_Height = ypos + (ysizedown + ysizeup) + m_IndentBottom;
258
259 if (m_Height < m_MinHeight) {
260 if (m_MinHeightAlign != wxHTML_ALIGN_TOP) {
261 int diff = m_MinHeight - m_Height;
262 if (m_MinHeightAlign == wxHTML_ALIGN_CENTER) diff /= 2;
263 cell = m_Cells;
264 while (cell) {
265 cell -> SetPos(cell -> GetPosX(), cell -> GetPosY() + diff);
266 cell = cell -> GetNext();
267 }
268 }
269 m_Height = m_MinHeight;
270 }
271
272 m_MaxLineWidth += s_indent + ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
273 if (m_Width < m_MaxLineWidth) m_Width = m_MaxLineWidth;
274
275 wxHtmlCell::Layout(w);
276 }
277
278
279 #define mMin(a, b) (((a) < (b)) ? (a) : (b))
280 #define mMax(a, b) (((a) < (b)) ? (b) : (a))
281
282 void wxHtmlContainerCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
283 {
284 // container visible, draw it:
285 if ((y + m_PosY < view_y2) && (y + m_PosY + m_Height > view_y1)) {
286
287 if (m_UseBkColour) {
288 wxBrush myb = wxBrush(m_BkColour, wxSOLID);
289
290 int real_y1 = mMax(y + m_PosY, view_y1);
291 int real_y2 = mMin(y + m_PosY + m_Height - 1, view_y2);
292
293 dc.SetBrush(myb);
294 dc.SetPen(*wxTRANSPARENT_PEN);
295 dc.DrawRectangle(x + m_PosX, real_y1, m_Width, real_y2 - real_y1 + 1);
296 }
297
298 if (m_UseBorder) {
299 wxPen mypen1(m_BorderColour1, 1, wxSOLID);
300 wxPen mypen2(m_BorderColour2, 1, wxSOLID);
301
302 dc.SetPen(mypen1);
303 dc.DrawLine(x + m_PosX, y + m_PosY, x + m_PosX, y + m_PosY + m_Height - 1);
304 dc.DrawLine(x + m_PosX, y + m_PosY, x + m_PosX + m_Width - 1, y + m_PosY);
305 dc.SetPen(mypen2);
306 dc.DrawLine(x + m_PosX + m_Width - 1, y + m_PosY, x + m_PosX + m_Width - 1, y + m_PosY + m_Height - 1);
307 dc.DrawLine(x + m_PosX, y + m_PosY + m_Height - 1, x + m_PosX + m_Width - 1, y + m_PosY + m_Height - 1);
308 }
309
310 if (m_Cells) m_Cells -> Draw(dc, x + m_PosX, y + m_PosY, view_y1, view_y2);
311 }
312 // container invisible, just proceed font+color changing:
313 else {
314 if (m_Cells) m_Cells -> DrawInvisible(dc, x + m_PosX, y + m_PosY);
315 }
316
317 wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
318 }
319
320
321
322 void wxHtmlContainerCell::DrawInvisible(wxDC& dc, int x, int y)
323 {
324 if (m_Cells) m_Cells -> DrawInvisible(dc, x + m_PosX, y + m_PosY);
325 wxHtmlCell::DrawInvisible(dc, x, y);
326 }
327
328
329
330 wxString wxHtmlContainerCell::GetLink(int x, int y) const
331 {
332 wxHtmlCell *c = m_Cells;
333 int cx, cy, cw, ch;
334
335 while (c) {
336 cx = c -> GetPosX(), cy = c -> GetPosY();
337 cw = c -> GetWidth(), ch = c -> GetHeight();
338 if ((x >= cx) && (x < cx + cw) && (y >= cy) && (y < cy + ch))
339 return c -> GetLink(x - cx, y - cy);
340 c = c -> GetNext();
341 }
342 return wxEmptyString;
343 }
344
345
346
347 void wxHtmlContainerCell::InsertCell(wxHtmlCell *f)
348 {
349 if (!m_Cells) m_Cells = m_LastCell = f;
350 else {
351 m_LastCell -> SetNext(f);
352 m_LastCell = f;
353 if (m_LastCell) while (m_LastCell -> GetNext()) m_LastCell = m_LastCell -> GetNext();
354 }
355 f -> SetParent(this);
356 }
357
358
359
360 void wxHtmlContainerCell::SetAlign(const wxHtmlTag& tag)
361 {
362 if (tag.HasParam("ALIGN")) {
363 wxString alg = tag.GetParam("ALIGN");
364 alg.MakeUpper();
365 if (alg == "CENTER")
366 SetAlignHor(wxHTML_ALIGN_CENTER);
367 else if (alg == "LEFT")
368 SetAlignHor(wxHTML_ALIGN_LEFT);
369 else if (alg == "RIGHT")
370 SetAlignHor(wxHTML_ALIGN_RIGHT);
371 }
372 }
373
374
375
376 void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag& tag)
377 {
378 if (tag.HasParam("WIDTH")) {
379 int wdi;
380 wxString wd = tag.GetParam("WIDTH");
381
382 if (wd[wd.Length()-1] == '%') {
383 sscanf(wd.c_str(), "%i%%", &wdi);
384 SetWidthFloat(wdi, wxHTML_UNITS_PERCENT);
385 }
386 else {
387 sscanf(wd.c_str(), "%i", &wdi);
388 SetWidthFloat(wdi, wxHTML_UNITS_PIXELS);
389 }
390 }
391 }
392
393
394
395 const wxHtmlCell* wxHtmlContainerCell::Find(int condition, const void* param) const
396 {
397 const wxHtmlCell *r = NULL;
398
399 if (m_Cells) {
400 r = m_Cells -> Find(condition, param);
401 if (r) return r;
402 }
403
404 return wxHtmlCell::Find(condition, param);
405 }
406
407
408
409 void wxHtmlContainerCell::OnMouseClick(wxWindow *parent, int x, int y, bool left, bool middle, bool right)
410 {
411 if (m_Cells) {
412 wxHtmlCell *c = m_Cells;
413 while (c) {
414 if ( (c -> GetPosX() <= x) &&
415 (c -> GetPosY() <= y) &&
416 (c -> GetPosX() + c -> GetWidth() > x) &&
417 (c -> GetPosY() + c -> GetHeight() > y)) {
418 c -> OnMouseClick(parent, x - c -> GetPosX(), y - c -> GetPosY(), left, middle, right);
419 break;
420 }
421 c = c -> GetNext();
422 }
423 }
424 }
425
426
427
428
429
430 //--------------------------------------------------------------------------------
431 // wxHtmlColourCell
432 //--------------------------------------------------------------------------------
433
434 void wxHtmlColourCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
435 {
436 if (m_Flags & wxHTML_CLR_FOREGROUND)
437 dc.SetTextForeground(m_Colour);
438 if (m_Flags & wxHTML_CLR_BACKGROUND) {
439 dc.SetBackground(wxBrush(m_Colour, wxSOLID));
440 dc.SetTextBackground(m_Colour);
441 }
442 wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
443 }
444
445 void wxHtmlColourCell::DrawInvisible(wxDC& dc, int x, int y)
446 {
447 if (m_Flags & wxHTML_CLR_FOREGROUND)
448 dc.SetTextForeground(m_Colour);
449 if (m_Flags & wxHTML_CLR_BACKGROUND) {
450 dc.SetBackground(wxBrush(m_Colour, wxSOLID));
451 dc.SetTextBackground(m_Colour);
452 }
453 wxHtmlCell::DrawInvisible(dc, x, y);
454 }
455
456
457
458
459 //--------------------------------------------------------------------------------
460 // wxHtmlFontCell
461 //--------------------------------------------------------------------------------
462
463 void wxHtmlFontCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
464 {
465 dc.SetFont(*m_Font);
466 wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
467 }
468
469 void wxHtmlFontCell::DrawInvisible(wxDC& dc, int x, int y)
470 {
471 dc.SetFont(*m_Font);
472 wxHtmlCell::DrawInvisible(dc, x, y);
473 }
474
475
476
477
478
479
480
481
482 //--------------------------------------------------------------------------------
483 // wxHtmlWidgetCell
484 //--------------------------------------------------------------------------------
485
486 wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow *wnd, int w)
487 {
488 int sx, sy;
489 m_Wnd = wnd;
490 m_Wnd -> GetSize(&sx, &sy);
491 m_Width = sx, m_Height = sy;
492 m_WidthFloat = w;
493 }
494
495
496 void wxHtmlWidgetCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
497 {
498 int absx = 0, absy = 0, stx, sty;
499 wxHtmlCell *c = this;
500
501 while (c) {
502 absx += c -> GetPosX();
503 absy += c -> GetPosY();
504 c = c -> GetParent();
505 }
506
507 ((wxScrolledWindow*)(m_Wnd -> GetParent())) -> ViewStart(&stx, &sty);
508 m_Wnd -> SetSize(absx - wxHTML_SCROLL_STEP * stx, absy - wxHTML_SCROLL_STEP * sty, m_Width, m_Height);
509
510 wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
511 }
512
513
514
515 void wxHtmlWidgetCell::DrawInvisible(wxDC& dc, int x, int y)
516 {
517 int absx = 0, absy = 0, stx, sty;
518 wxHtmlCell *c = this;
519
520 while (c) {
521 absx += c -> GetPosX();
522 absy += c -> GetPosY();
523 c = c -> GetParent();
524 }
525
526 ((wxScrolledWindow*)(m_Wnd -> GetParent())) -> ViewStart(&stx, &sty);
527 m_Wnd -> SetSize(absx - wxHTML_SCROLL_STEP * stx, absy - wxHTML_SCROLL_STEP * sty, m_Width, m_Height);
528
529 wxHtmlCell::DrawInvisible(dc, x, y);
530 }
531
532
533
534 void wxHtmlWidgetCell::Layout(int w)
535 {
536 if (m_WidthFloat != 0) {
537 m_Width = (w * m_WidthFloat) / 100;
538 m_Wnd -> SetSize(m_Width, m_Height);
539 }
540
541 wxHtmlCell::Layout(w);
542 }
543
544 #endif