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