]>
git.saurik.com Git - wxWidgets.git/blob - src/html/htmlcell.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxHtmlCell - basic element of HTML output
4 // Author: Vaclav Slavik
6 // Copyright: (c) 1999 Vaclav Slavik
7 // Licence: wxWindows Licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation
14 #include "wx/wxprec.h"
18 #if wxUSE_HTML && wxUSE_STREAMS
28 #include "wx/html/htmlcell.h"
29 #include "wx/html/htmlwin.h"
33 //-----------------------------------------------------------------------------
35 //-----------------------------------------------------------------------------
37 wxHtmlCell::wxHtmlCell() : wxObject()
41 m_Width
= m_Height
= m_Descent
= 0;
42 m_CanLiveOnPagebreak
= TRUE
;
46 wxHtmlCell::~wxHtmlCell()
48 if (m_Link
) delete m_Link
;
49 if (m_Next
) delete m_Next
;
53 void wxHtmlCell::OnMouseClick(wxWindow
*parent
, int x
, int y
,
54 const wxMouseEvent
& event
)
56 wxHtmlLinkInfo
*lnk
= GetLink(x
, y
);
59 wxHtmlLinkInfo
lnk2(*lnk
);
60 lnk2
.SetEvent(&event
);
61 lnk2
.SetHtmlCell(this);
62 ((wxHtmlWindow
*)parent
) -> OnLinkClicked(lnk2
);
63 // note : this overcasting is legal because parent is *always* wxHtmlWindow
69 bool wxHtmlCell::AdjustPagebreak(int *pagebreak
) const
71 if ((!m_CanLiveOnPagebreak
) &&
72 m_PosY
< *pagebreak
&& m_PosY
+ m_Height
> *pagebreak
) {
74 if (m_Next
!= NULL
) m_Next
-> AdjustPagebreak(pagebreak
);
79 if (m_Next
!= NULL
) return m_Next
-> AdjustPagebreak(pagebreak
);
86 void wxHtmlCell::SetLink(const wxHtmlLinkInfo
& link
)
88 if (m_Link
) delete m_Link
;
90 if (link
.GetHref() != wxEmptyString
)
91 m_Link
= new wxHtmlLinkInfo(link
);
96 void wxHtmlCell::Layout(int w
)
99 if (m_Next
) m_Next
-> Layout(w
);
103 void wxHtmlCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
105 if (m_Next
) m_Next
-> Draw(dc
, x
, y
, view_y1
, view_y2
);
110 void wxHtmlCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
112 if (m_Next
) m_Next
-> DrawInvisible(dc
, x
, y
);
117 const wxHtmlCell
* wxHtmlCell::Find(int condition
, const void* param
) const
119 if (m_Next
) return m_Next
-> Find(condition
, param
);
125 //-----------------------------------------------------------------------------
127 //-----------------------------------------------------------------------------
129 wxHtmlWordCell::wxHtmlWordCell(const wxString
& word
, wxDC
& dc
) : wxHtmlCell()
133 if (m_Word
.Find(wxT('&')) != -1)
135 #define ESCSEQ(escape, subst) \
136 { _T("&") _T(escape) _T(";"), _T("&") _T(escape) _T(" "), _T(subst) }
137 static wxChar
* substitutions
[][3] =
139 ESCSEQ("quot", "\""),
144 ESCSEQ("iexcl", "!"),
148 ESCSEQ("brkbar", " "),
152 ESCSEQ("copy", "(c)"),
154 ESCSEQ("laquo", " "),
157 ESCSEQ("reg", "(r)"),
160 ESCSEQ("plusm", " "),
162 ESCSEQ("acute", " "),
163 ESCSEQ("micro", " "),
167 ESCSEQ("raquo", " "),
169 ESCSEQ("iquest", " "),
170 ESCSEQ("Agrave", "À"),
172 ESCSEQ("Acirc", "Â"),
173 ESCSEQ("Atilde", "Ã"),
175 ESCSEQ("Aring", " "),
176 ESCSEQ("AElig", " "),
177 ESCSEQ("Ccedil", "ç"),
178 ESCSEQ("Egrave", "È"),
179 ESCSEQ("Eacute", "É"),
180 ESCSEQ("Ecirc", "Ê"),
182 ESCSEQ("Igrave", "Ì"),
184 ESCSEQ("Icirc", "Î"),
187 ESCSEQ("Ntilde", "Ñ"),
188 ESCSEQ("Ograve", "Ò"),
190 ESCSEQ("Ocirc", "Ô"),
191 ESCSEQ("Otilde", "Õ"),
194 ESCSEQ("Oslash", " "),
195 ESCSEQ("Ugrave", "Ù"),
197 ESCSEQ("Ucirc", " "),
200 ESCSEQ("szlig", "§"),
201 ESCSEQ("agrave;","à"),
202 ESCSEQ("aacute", "á"),
203 ESCSEQ("acirc", "â"),
204 ESCSEQ("atilde", "ã"),
206 ESCSEQ("aring", "a"),
207 ESCSEQ("aelig", "ae"),
208 ESCSEQ("ccedil", "ç"),
209 ESCSEQ("egrave", "è"),
210 ESCSEQ("eacute", "é"),
211 ESCSEQ("ecirc", "ê"),
213 ESCSEQ("igrave", "ì"),
214 ESCSEQ("iacute", "í"),
215 ESCSEQ("icirc", " "),
218 ESCSEQ("ntilde", "ñ"),
219 ESCSEQ("ograve", "ò"),
220 ESCSEQ("oacute", "ó"),
221 ESCSEQ("ocirc", "ô"),
222 ESCSEQ("otilde", "õ"),
224 ESCSEQ("divide", " "),
225 ESCSEQ("oslash", " "),
226 ESCSEQ("ugrave", "ù"),
227 ESCSEQ("uacute", "ú"),
228 ESCSEQ("ucirc", "û"),
233 /* this one should ALWAYS stay the last one!!! */
239 for (int i
= 0; substitutions
[i
][0] != NULL
; i
++)
241 m_Word
.Replace(substitutions
[i
][0], substitutions
[i
][2], TRUE
);
242 m_Word
.Replace(substitutions
[i
][1], substitutions
[i
][2], TRUE
);
246 dc
.GetTextExtent(m_Word
, &m_Width
, &m_Height
, &m_Descent
);
247 SetCanLiveOnPagebreak(FALSE
);
252 void wxHtmlWordCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
254 dc
.DrawText(m_Word
, x
+ m_PosX
, y
+ m_PosY
);
255 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
260 //-----------------------------------------------------------------------------
261 // wxHtmlContainerCell
262 //-----------------------------------------------------------------------------
265 wxHtmlContainerCell::wxHtmlContainerCell(wxHtmlContainerCell
*parent
) : wxHtmlCell()
267 m_Cells
= m_LastCell
= NULL
;
269 if (m_Parent
) m_Parent
-> InsertCell(this);
270 m_AlignHor
= wxHTML_ALIGN_LEFT
;
271 m_AlignVer
= wxHTML_ALIGN_BOTTOM
;
272 m_IndentLeft
= m_IndentRight
= m_IndentTop
= m_IndentBottom
= 0;
273 m_WidthFloat
= 100; m_WidthFloatUnits
= wxHTML_UNITS_PERCENT
;
274 m_UseBkColour
= FALSE
;
277 m_MinHeightAlign
= wxHTML_ALIGN_TOP
;
281 wxHtmlContainerCell::~wxHtmlContainerCell()
283 if (m_Cells
) delete m_Cells
;
288 void wxHtmlContainerCell::SetIndent(int i
, int what
, int units
)
290 int val
= (units
== wxHTML_UNITS_PIXELS
) ? i
: -i
;
291 if (what
& wxHTML_INDENT_LEFT
) m_IndentLeft
= val
;
292 if (what
& wxHTML_INDENT_RIGHT
) m_IndentRight
= val
;
293 if (what
& wxHTML_INDENT_TOP
) m_IndentTop
= val
;
294 if (what
& wxHTML_INDENT_BOTTOM
) m_IndentBottom
= val
;
300 int wxHtmlContainerCell::GetIndent(int ind
) const
302 if (ind
& wxHTML_INDENT_LEFT
) return m_IndentLeft
;
303 else if (ind
& wxHTML_INDENT_RIGHT
) return m_IndentRight
;
304 else if (ind
& wxHTML_INDENT_TOP
) return m_IndentTop
;
305 else if (ind
& wxHTML_INDENT_BOTTOM
) return m_IndentBottom
;
306 else return -1; /* BUG! Should not be called... */
312 int wxHtmlContainerCell::GetIndentUnits(int ind
) const
315 if (ind
& wxHTML_INDENT_LEFT
) p
= m_IndentLeft
< 0;
316 else if (ind
& wxHTML_INDENT_RIGHT
) p
= m_IndentRight
< 0;
317 else if (ind
& wxHTML_INDENT_TOP
) p
= m_IndentTop
< 0;
318 else if (ind
& wxHTML_INDENT_BOTTOM
) p
= m_IndentBottom
< 0;
319 if (p
) return wxHTML_UNITS_PERCENT
;
320 else return wxHTML_UNITS_PIXELS
;
325 bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak
) const
327 if (!m_CanLiveOnPagebreak
)
328 return wxHtmlCell::AdjustPagebreak(pagebreak
);
331 wxHtmlCell
*c
= GetFirstCell();
333 int pbrk
= *pagebreak
- m_PosY
;
336 if (c
-> AdjustPagebreak(&pbrk
)) rt
= TRUE
;
339 if (rt
) *pagebreak
= pbrk
+ m_PosY
;
346 void wxHtmlContainerCell::Layout(int w
)
348 if (m_LastLayout
== w
) {
349 wxHtmlCell::Layout(w
);
353 wxHtmlCell
*cell
= m_Cells
, *line
= m_Cells
;
354 long xpos
= 0, ypos
= m_IndentTop
;
355 int xdelta
= 0, ybasicpos
= 0, ydiff
;
356 int s_width
, s_indent
;
357 int ysizeup
= 0, ysizedown
= 0;
358 int MaxLineWidth
= 0;
368 if (m_WidthFloatUnits
== wxHTML_UNITS_PERCENT
) {
369 if (m_WidthFloat
< 0) m_Width
= (100 + m_WidthFloat
) * w
/ 100;
370 else m_Width
= m_WidthFloat
* w
/ 100;
373 if (m_WidthFloat
< 0) m_Width
= w
+ m_WidthFloat
;
374 else m_Width
= m_WidthFloat
;
378 int l
= (m_IndentLeft
< 0) ? (-m_IndentLeft
* m_Width
/ 100) : m_IndentLeft
;
379 int r
= (m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
;
380 m_Cells
-> Layout(m_Width
- (l
+ r
));
389 // adjust indentation:
390 s_indent
= (m_IndentLeft
< 0) ? (-m_IndentLeft
* m_Width
/ 100) : m_IndentLeft
;
391 s_width
= m_Width
- s_indent
- ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
394 while (cell
!= NULL
) {
395 switch (m_AlignVer
) {
396 case wxHTML_ALIGN_TOP
: ybasicpos
= 0; break;
397 case wxHTML_ALIGN_BOTTOM
: ybasicpos
= - cell
-> GetHeight(); break;
398 case wxHTML_ALIGN_CENTER
: ybasicpos
= - cell
-> GetHeight() / 2; break;
400 ydiff
= cell
-> GetHeight() + ybasicpos
;
402 if (cell
-> GetDescent() + ydiff
> ysizedown
) ysizedown
= cell
-> GetDescent() + ydiff
;
403 if (ybasicpos
+ cell
-> GetDescent() < -ysizeup
) ysizeup
= - (ybasicpos
+ cell
-> GetDescent());
405 cell
-> SetPos(xpos
, ybasicpos
+ cell
-> GetDescent());
406 xpos
+= cell
-> GetWidth();
407 cell
= cell
-> GetNext();
410 // force new line if occured:
411 if ((cell
== NULL
) || (xpos
+ cell
-> GetWidth() > s_width
)) {
412 if (xpos
> MaxLineWidth
) MaxLineWidth
= xpos
;
413 if (ysizeup
< 0) ysizeup
= 0;
414 if (ysizedown
< 0) ysizedown
= 0;
415 switch (m_AlignHor
) {
416 case wxHTML_ALIGN_LEFT
:
417 case wxHTML_ALIGN_JUSTIFY
:
420 case wxHTML_ALIGN_RIGHT
:
421 xdelta
= 0 + (s_width
- xpos
);
423 case wxHTML_ALIGN_CENTER
:
424 xdelta
= 0 + (s_width
- xpos
) / 2;
427 if (xdelta
< 0) xdelta
= 0;
432 if (m_AlignHor
!= wxHTML_ALIGN_JUSTIFY
|| cell
== NULL
)
433 while (line
!= cell
) {
434 line
-> SetPos(line
-> GetPosX() + xdelta
,
435 ypos
+ line
-> GetPosY());
436 line
= line
-> GetNext();
441 int step
= (s_width
- xpos
);
442 if (step
< 0) step
= 0;
444 if (xcnt
> 0) while (line
!= cell
) {
445 line
-> SetPos(line
-> GetPosX() + s_indent
+
446 (counter
++ * step
/ xcnt
),
447 ypos
+ line
-> GetPosY());
448 line
= line
-> GetNext();
455 ysizeup
= ysizedown
= 0;
460 // setup height & width, depending on container layout:
461 m_Height
= ypos
+ (ysizedown
+ ysizeup
) + m_IndentBottom
;
463 if (m_Height
< m_MinHeight
) {
464 if (m_MinHeightAlign
!= wxHTML_ALIGN_TOP
) {
465 int diff
= m_MinHeight
- m_Height
;
466 if (m_MinHeightAlign
== wxHTML_ALIGN_CENTER
) diff
/= 2;
469 cell
-> SetPos(cell
-> GetPosX(), cell
-> GetPosY() + diff
);
470 cell
= cell
-> GetNext();
473 m_Height
= m_MinHeight
;
476 MaxLineWidth
+= s_indent
+ ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
477 if (m_Width
< MaxLineWidth
) m_Width
= MaxLineWidth
;
481 wxHtmlCell::Layout(w
);
485 #define mMin(a, b) (((a) < (b)) ? (a) : (b))
486 #define mMax(a, b) (((a) < (b)) ? (b) : (a))
488 void wxHtmlContainerCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
490 // container visible, draw it:
491 if ((y
+ m_PosY
< view_y2
) && (y
+ m_PosY
+ m_Height
> view_y1
)) {
494 wxBrush myb
= wxBrush(m_BkColour
, wxSOLID
);
496 int real_y1
= mMax(y
+ m_PosY
, view_y1
);
497 int real_y2
= mMin(y
+ m_PosY
+ m_Height
- 1, view_y2
);
500 dc
.SetPen(*wxTRANSPARENT_PEN
);
501 dc
.DrawRectangle(x
+ m_PosX
, real_y1
, m_Width
, real_y2
- real_y1
+ 1);
505 wxPen
mypen1(m_BorderColour1
, 1, wxSOLID
);
506 wxPen
mypen2(m_BorderColour2
, 1, wxSOLID
);
509 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1);
510 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
);
512 dc
.DrawLine(x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
513 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
516 if (m_Cells
) m_Cells
-> Draw(dc
, x
+ m_PosX
, y
+ m_PosY
, view_y1
, view_y2
);
518 // container invisible, just proceed font+color changing:
520 if (m_Cells
) m_Cells
-> DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
523 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
528 void wxHtmlContainerCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
530 if (m_Cells
) m_Cells
-> DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
531 wxHtmlCell::DrawInvisible(dc
, x
, y
);
536 wxHtmlLinkInfo
*wxHtmlContainerCell::GetLink(int x
, int y
) const
538 wxHtmlCell
*c
= m_Cells
;
542 cx
= c
-> GetPosX(), cy
= c
-> GetPosY();
543 cw
= c
-> GetWidth(), ch
= c
-> GetHeight();
544 if ((x
>= cx
) && (x
< cx
+ cw
) && (y
>= cy
) && (y
< cy
+ ch
))
545 return c
-> GetLink(x
- cx
, y
- cy
);
553 void wxHtmlContainerCell::InsertCell(wxHtmlCell
*f
)
555 if (!m_Cells
) m_Cells
= m_LastCell
= f
;
557 m_LastCell
-> SetNext(f
);
559 if (m_LastCell
) while (m_LastCell
-> GetNext()) m_LastCell
= m_LastCell
-> GetNext();
561 f
-> SetParent(this);
567 void wxHtmlContainerCell::SetAlign(const wxHtmlTag
& tag
)
569 if (tag
.HasParam(wxT("ALIGN"))) {
570 wxString alg
= tag
.GetParam(wxT("ALIGN"));
572 if (alg
== wxT("CENTER"))
573 SetAlignHor(wxHTML_ALIGN_CENTER
);
574 else if (alg
== wxT("LEFT"))
575 SetAlignHor(wxHTML_ALIGN_LEFT
);
576 else if (alg
== wxT("JUSTIFY"))
577 SetAlignHor(wxHTML_ALIGN_JUSTIFY
);
578 else if (alg
== wxT("RIGHT"))
579 SetAlignHor(wxHTML_ALIGN_RIGHT
);
586 void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag
& tag
, double pixel_scale
)
588 if (tag
.HasParam(wxT("WIDTH"))) {
590 wxString wd
= tag
.GetParam(wxT("WIDTH"));
592 if (wd
[wd
.Length()-1] == wxT('%')) {
593 wxSscanf(wd
.c_str(), wxT("%i%%"), &wdi
);
594 SetWidthFloat(wdi
, wxHTML_UNITS_PERCENT
);
597 wxSscanf(wd
.c_str(), wxT("%i"), &wdi
);
598 SetWidthFloat((int)(pixel_scale
* (double)wdi
), wxHTML_UNITS_PIXELS
);
606 const wxHtmlCell
* wxHtmlContainerCell::Find(int condition
, const void* param
) const
608 const wxHtmlCell
*r
= NULL
;
611 r
= m_Cells
-> Find(condition
, param
);
615 return wxHtmlCell::Find(condition
, param
);
620 void wxHtmlContainerCell::OnMouseClick(wxWindow
*parent
, int x
, int y
, const wxMouseEvent
& event
)
623 wxHtmlCell
*c
= m_Cells
;
625 if ( (c
-> GetPosX() <= x
) &&
626 (c
-> GetPosY() <= y
) &&
627 (c
-> GetPosX() + c
-> GetWidth() > x
) &&
628 (c
-> GetPosY() + c
-> GetHeight() > y
)) {
629 c
-> OnMouseClick(parent
, x
- c
-> GetPosX(), y
- c
-> GetPosY(), event
);
641 //--------------------------------------------------------------------------------
643 //--------------------------------------------------------------------------------
645 void wxHtmlColourCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
647 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
648 dc
.SetTextForeground(m_Colour
);
649 if (m_Flags
& wxHTML_CLR_BACKGROUND
) {
650 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
651 dc
.SetTextBackground(m_Colour
);
653 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
656 void wxHtmlColourCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
658 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
659 dc
.SetTextForeground(m_Colour
);
660 if (m_Flags
& wxHTML_CLR_BACKGROUND
) {
661 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
662 dc
.SetTextBackground(m_Colour
);
664 wxHtmlCell::DrawInvisible(dc
, x
, y
);
670 //--------------------------------------------------------------------------------
672 //--------------------------------------------------------------------------------
674 void wxHtmlFontCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
677 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
680 void wxHtmlFontCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
683 wxHtmlCell::DrawInvisible(dc
, x
, y
);
693 //--------------------------------------------------------------------------------
695 //--------------------------------------------------------------------------------
697 wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow
*wnd
, int w
)
701 m_Wnd
-> GetSize(&sx
, &sy
);
702 m_Width
= sx
, m_Height
= sy
;
707 void wxHtmlWidgetCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
709 int absx
= 0, absy
= 0, stx
, sty
;
710 wxHtmlCell
*c
= this;
713 absx
+= c
-> GetPosX();
714 absy
+= c
-> GetPosY();
715 c
= c
-> GetParent();
718 ((wxScrolledWindow
*)(m_Wnd
-> GetParent())) -> ViewStart(&stx
, &sty
);
719 m_Wnd
-> SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
721 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
726 void wxHtmlWidgetCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
728 int absx
= 0, absy
= 0, stx
, sty
;
729 wxHtmlCell
*c
= this;
732 absx
+= c
-> GetPosX();
733 absy
+= c
-> GetPosY();
734 c
= c
-> GetParent();
737 ((wxScrolledWindow
*)(m_Wnd
-> GetParent())) -> ViewStart(&stx
, &sty
);
738 m_Wnd
-> SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
740 wxHtmlCell::DrawInvisible(dc
, x
, y
);
745 void wxHtmlWidgetCell::Layout(int w
)
747 if (m_WidthFloat
!= 0) {
748 m_Width
= (w
* m_WidthFloat
) / 100;
749 m_Wnd
-> SetSize(m_Width
, m_Height
);
752 wxHtmlCell::Layout(w
);