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