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