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