]>
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"
27 #include "wx/html/htmlcell.h"
28 #include "wx/html/htmlwin.h"
32 //-----------------------------------------------------------------------------
34 //-----------------------------------------------------------------------------
36 wxHtmlCell::wxHtmlCell() : wxObject()
40 m_Width
= m_Height
= m_Descent
= 0;
41 m_CanLiveOnPagebreak
= TRUE
;
45 wxHtmlCell::~wxHtmlCell()
47 if (m_Link
) delete m_Link
;
48 if (m_Next
) delete m_Next
;
52 void wxHtmlCell::OnMouseClick(wxWindow
*parent
, int x
, int y
,
53 const wxMouseEvent
& event
)
55 wxHtmlLinkInfo
*lnk
= GetLink(x
, y
);
58 wxHtmlLinkInfo
lnk2(*lnk
);
59 lnk2
.SetEvent(&event
);
60 lnk2
.SetHtmlCell(this);
61 ((wxHtmlWindow
*)parent
) -> OnLinkClicked(lnk2
);
62 // note : this overcasting is legal because parent is *always* wxHtmlWindow
68 bool wxHtmlCell::AdjustPagebreak(int *pagebreak
) const
70 if ((!m_CanLiveOnPagebreak
) &&
71 m_PosY
< *pagebreak
&& m_PosY
+ m_Height
> *pagebreak
) {
73 if (m_Next
!= NULL
) m_Next
-> AdjustPagebreak(pagebreak
);
78 if (m_Next
!= NULL
) return m_Next
-> AdjustPagebreak(pagebreak
);
85 void wxHtmlCell::SetLink(const wxHtmlLinkInfo
& link
)
87 if (m_Link
) delete m_Link
;
88 m_Link
= new wxHtmlLinkInfo(link
);
93 //-----------------------------------------------------------------------------
95 //-----------------------------------------------------------------------------
97 wxHtmlWordCell::wxHtmlWordCell(const wxString
& word
, wxDC
& dc
) : wxHtmlCell()
101 if (m_Word
.Find(wxT('&')) != -1)
103 #define ESCSEQ(escape, subst) \
104 { wxT("&"escape";"), wxT("&"escape" "), wxT(subst) }
105 static wxChar
* substitutions
[][3] =
107 ESCSEQ("quot", "\""),
112 ESCSEQ("iexcl", "!"),
116 ESCSEQ("brkbar", " "),
120 ESCSEQ("copy", "(c)"),
122 ESCSEQ("laquo", " "),
125 ESCSEQ("reg", "(r)"),
128 ESCSEQ("plusm", " "),
130 ESCSEQ("acute", " "),
131 ESCSEQ("micro", " "),
135 ESCSEQ("raquo", " "),
137 ESCSEQ("iquest", " "),
138 ESCSEQ("Agrave", "À"),
140 ESCSEQ("Acirc", "Â"),
141 ESCSEQ("Atilde", "Ã"),
143 ESCSEQ("Aring", " "),
144 ESCSEQ("AElig", " "),
145 ESCSEQ("Ccedil", "ç"),
146 ESCSEQ("Egrave", "È"),
147 ESCSEQ("Eacute", "É"),
148 ESCSEQ("Ecirc", "Ê"),
150 ESCSEQ("Igrave", "Ì"),
152 ESCSEQ("Icirc", "Î"),
155 ESCSEQ("Ntilde", "Ñ"),
156 ESCSEQ("Ograve", "Ò"),
158 ESCSEQ("Ocirc", "Ô"),
159 ESCSEQ("Otilde", "Õ"),
162 ESCSEQ("Oslash", " "),
163 ESCSEQ("Ugrave", "Ù"),
165 ESCSEQ("Ucirc", " "),
168 ESCSEQ("szlig", "§"),
169 ESCSEQ("agrave;","à"),
170 ESCSEQ("aacute", "á"),
171 ESCSEQ("acirc", "â"),
172 ESCSEQ("atilde", "ã"),
174 ESCSEQ("aring", "a"),
175 ESCSEQ("aelig", "ae"),
176 ESCSEQ("ccedil", "ç"),
177 ESCSEQ("egrave", "è"),
178 ESCSEQ("eacute", "é"),
179 ESCSEQ("ecirc", "ê"),
181 ESCSEQ("igrave", "ì"),
182 ESCSEQ("iacute", "í"),
183 ESCSEQ("icirc", " "),
186 ESCSEQ("ntilde", "ñ"),
187 ESCSEQ("ograve", "ò"),
188 ESCSEQ("oacute", "ó"),
189 ESCSEQ("ocirc", "ô"),
190 ESCSEQ("otilde", "õ"),
192 ESCSEQ("divide", " "),
193 ESCSEQ("oslash", " "),
194 ESCSEQ("ugrave", "ù"),
195 ESCSEQ("uacute", "ú"),
196 ESCSEQ("ucirc", "û"),
201 /* this one should ALWAYS stay the last one!!! */
207 for (int i
= 0; substitutions
[i
][0] != NULL
; i
++)
209 m_Word
.Replace(substitutions
[i
][0], substitutions
[i
][2], TRUE
);
210 m_Word
.Replace(substitutions
[i
][1], substitutions
[i
][2], TRUE
);
214 dc
.GetTextExtent(m_Word
, &m_Width
, &m_Height
, &m_Descent
);
215 SetCanLiveOnPagebreak(FALSE
);
220 void wxHtmlWordCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
222 dc
.DrawText(m_Word
, x
+ m_PosX
, y
+ m_PosY
);
223 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
228 //-----------------------------------------------------------------------------
229 // wxHtmlContainerCell
230 //-----------------------------------------------------------------------------
233 wxHtmlContainerCell::wxHtmlContainerCell(wxHtmlContainerCell
*parent
) : wxHtmlCell()
235 m_Cells
= m_LastCell
= NULL
;
237 if (m_Parent
) m_Parent
-> InsertCell(this);
238 m_AlignHor
= wxHTML_ALIGN_LEFT
;
239 m_AlignVer
= wxHTML_ALIGN_BOTTOM
;
240 m_IndentLeft
= m_IndentRight
= m_IndentTop
= m_IndentBottom
= 0;
241 m_WidthFloat
= 100; m_WidthFloatUnits
= wxHTML_UNITS_PERCENT
;
242 m_UseBkColour
= FALSE
;
245 m_MinHeightAlign
= wxHTML_ALIGN_TOP
;
251 void wxHtmlContainerCell::SetIndent(int i
, int what
, int units
)
253 int val
= (units
== wxHTML_UNITS_PIXELS
) ? i
: -i
;
254 if (what
& wxHTML_INDENT_LEFT
) m_IndentLeft
= val
;
255 if (what
& wxHTML_INDENT_RIGHT
) m_IndentRight
= val
;
256 if (what
& wxHTML_INDENT_TOP
) m_IndentTop
= val
;
257 if (what
& wxHTML_INDENT_BOTTOM
) m_IndentBottom
= val
;
263 int wxHtmlContainerCell::GetIndent(int ind
) const
265 if (ind
& wxHTML_INDENT_LEFT
) return m_IndentLeft
;
266 else if (ind
& wxHTML_INDENT_RIGHT
) return m_IndentRight
;
267 else if (ind
& wxHTML_INDENT_TOP
) return m_IndentTop
;
268 else if (ind
& wxHTML_INDENT_BOTTOM
) return m_IndentBottom
;
269 else return -1; /* BUG! Should not be called... */
275 int wxHtmlContainerCell::GetIndentUnits(int ind
) const
278 if (ind
& wxHTML_INDENT_LEFT
) p
= m_IndentLeft
< 0;
279 else if (ind
& wxHTML_INDENT_RIGHT
) p
= m_IndentRight
< 0;
280 else if (ind
& wxHTML_INDENT_TOP
) p
= m_IndentTop
< 0;
281 else if (ind
& wxHTML_INDENT_BOTTOM
) p
= m_IndentBottom
< 0;
282 if (p
) return wxHTML_UNITS_PERCENT
;
283 else return wxHTML_UNITS_PIXELS
;
288 bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak
) const
290 if (!m_CanLiveOnPagebreak
)
291 return wxHtmlCell::AdjustPagebreak(pagebreak
);
294 wxHtmlCell
*c
= GetFirstCell();
296 int pbrk
= *pagebreak
- m_PosY
;
299 if (c
-> AdjustPagebreak(&pbrk
)) rt
= TRUE
;
302 if (rt
) *pagebreak
= pbrk
+ m_PosY
;
309 void wxHtmlContainerCell::Layout(int w
)
311 if (m_LastLayout
== w
) {
312 wxHtmlCell::Layout(w
);
316 wxHtmlCell
*cell
= m_Cells
, *line
= m_Cells
;
317 long xpos
= 0, ypos
= m_IndentTop
;
318 int xdelta
= 0, ybasicpos
= 0, ydiff
;
319 int s_width
, s_indent
;
320 int ysizeup
= 0, ysizedown
= 0;
321 int MaxLineWidth
= 0;
331 if (m_WidthFloatUnits
== wxHTML_UNITS_PERCENT
) {
332 if (m_WidthFloat
< 0) m_Width
= (100 + m_WidthFloat
) * w
/ 100;
333 else m_Width
= m_WidthFloat
* w
/ 100;
336 if (m_WidthFloat
< 0) m_Width
= w
+ m_WidthFloat
;
337 else m_Width
= m_WidthFloat
;
341 int l
= (m_IndentLeft
< 0) ? (-m_IndentLeft
* m_Width
/ 100) : m_IndentLeft
;
342 int r
= (m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
;
343 m_Cells
-> Layout(m_Width
- (l
+ r
));
352 // adjust indentation:
353 s_indent
= (m_IndentLeft
< 0) ? (-m_IndentLeft
* m_Width
/ 100) : m_IndentLeft
;
354 s_width
= m_Width
- s_indent
- ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
357 while (cell
!= NULL
) {
358 switch (m_AlignVer
) {
359 case wxHTML_ALIGN_TOP
: ybasicpos
= 0; break;
360 case wxHTML_ALIGN_BOTTOM
: ybasicpos
= - cell
-> GetHeight(); break;
361 case wxHTML_ALIGN_CENTER
: ybasicpos
= - cell
-> GetHeight() / 2; break;
363 ydiff
= cell
-> GetHeight() + ybasicpos
;
365 if (cell
-> GetDescent() + ydiff
> ysizedown
) ysizedown
= cell
-> GetDescent() + ydiff
;
366 if (ybasicpos
+ cell
-> GetDescent() < -ysizeup
) ysizeup
= - (ybasicpos
+ cell
-> GetDescent());
368 cell
-> SetPos(xpos
, ybasicpos
+ cell
-> GetDescent());
369 xpos
+= cell
-> GetWidth();
370 cell
= cell
-> GetNext();
373 // force new line if occured:
374 if ((cell
== NULL
) || (xpos
+ cell
-> GetWidth() > s_width
)) {
375 if (xpos
> MaxLineWidth
) MaxLineWidth
= xpos
;
376 if (ysizeup
< 0) ysizeup
= 0;
377 if (ysizedown
< 0) ysizedown
= 0;
378 switch (m_AlignHor
) {
379 case wxHTML_ALIGN_LEFT
:
380 case wxHTML_ALIGN_JUSTIFY
:
383 case wxHTML_ALIGN_RIGHT
:
384 xdelta
= 0 + (s_width
- xpos
);
386 case wxHTML_ALIGN_CENTER
:
387 xdelta
= 0 + (s_width
- xpos
) / 2;
390 if (xdelta
< 0) xdelta
= 0;
395 if (m_AlignHor
!= wxHTML_ALIGN_JUSTIFY
|| cell
== NULL
)
396 while (line
!= cell
) {
397 line
-> SetPos(line
-> GetPosX() + xdelta
,
398 ypos
+ line
-> GetPosY());
399 line
= line
-> GetNext();
404 int step
= (s_width
- xpos
);
405 if (step
< 0) step
= 0;
406 while (line
!= cell
) {
407 line
-> SetPos(line
-> GetPosX() + s_indent
+
408 (counter
++ * step
/ xcnt
),
409 ypos
+ line
-> GetPosY());
410 line
= line
-> GetNext();
416 ysizeup
= ysizedown
= 0;
421 // setup height & width, depending on container layout:
422 m_Height
= ypos
+ (ysizedown
+ ysizeup
) + m_IndentBottom
;
424 if (m_Height
< m_MinHeight
) {
425 if (m_MinHeightAlign
!= wxHTML_ALIGN_TOP
) {
426 int diff
= m_MinHeight
- m_Height
;
427 if (m_MinHeightAlign
== wxHTML_ALIGN_CENTER
) diff
/= 2;
430 cell
-> SetPos(cell
-> GetPosX(), cell
-> GetPosY() + diff
);
431 cell
= cell
-> GetNext();
434 m_Height
= m_MinHeight
;
437 MaxLineWidth
+= s_indent
+ ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
438 if (m_Width
< MaxLineWidth
) m_Width
= MaxLineWidth
;
442 wxHtmlCell::Layout(w
);
446 #define mMin(a, b) (((a) < (b)) ? (a) : (b))
447 #define mMax(a, b) (((a) < (b)) ? (b) : (a))
449 void wxHtmlContainerCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
451 // container visible, draw it:
452 if ((y
+ m_PosY
< view_y2
) && (y
+ m_PosY
+ m_Height
> view_y1
)) {
455 wxBrush myb
= wxBrush(m_BkColour
, wxSOLID
);
457 int real_y1
= mMax(y
+ m_PosY
, view_y1
);
458 int real_y2
= mMin(y
+ m_PosY
+ m_Height
- 1, view_y2
);
461 dc
.SetPen(*wxTRANSPARENT_PEN
);
462 dc
.DrawRectangle(x
+ m_PosX
, real_y1
, m_Width
, real_y2
- real_y1
+ 1);
466 wxPen
mypen1(m_BorderColour1
, 1, wxSOLID
);
467 wxPen
mypen2(m_BorderColour2
, 1, wxSOLID
);
470 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1);
471 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
);
473 dc
.DrawLine(x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
474 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
477 if (m_Cells
) m_Cells
-> Draw(dc
, x
+ m_PosX
, y
+ m_PosY
, view_y1
, view_y2
);
479 // container invisible, just proceed font+color changing:
481 if (m_Cells
) m_Cells
-> DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
484 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
489 void wxHtmlContainerCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
491 if (m_Cells
) m_Cells
-> DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
492 wxHtmlCell::DrawInvisible(dc
, x
, y
);
497 wxHtmlLinkInfo
*wxHtmlContainerCell::GetLink(int x
, int y
) const
499 wxHtmlCell
*c
= m_Cells
;
503 cx
= c
-> GetPosX(), cy
= c
-> GetPosY();
504 cw
= c
-> GetWidth(), ch
= c
-> GetHeight();
505 if ((x
>= cx
) && (x
< cx
+ cw
) && (y
>= cy
) && (y
< cy
+ ch
))
506 return c
-> GetLink(x
- cx
, y
- cy
);
514 void wxHtmlContainerCell::InsertCell(wxHtmlCell
*f
)
516 if (!m_Cells
) m_Cells
= m_LastCell
= f
;
518 m_LastCell
-> SetNext(f
);
520 if (m_LastCell
) while (m_LastCell
-> GetNext()) m_LastCell
= m_LastCell
-> GetNext();
522 f
-> SetParent(this);
528 void wxHtmlContainerCell::SetAlign(const wxHtmlTag
& tag
)
530 if (tag
.HasParam(wxT("ALIGN"))) {
531 wxString alg
= tag
.GetParam(wxT("ALIGN"));
533 if (alg
== wxT("CENTER"))
534 SetAlignHor(wxHTML_ALIGN_CENTER
);
535 else if (alg
== wxT("LEFT"))
536 SetAlignHor(wxHTML_ALIGN_LEFT
);
537 else if (alg
== wxT("JUSTIFY"))
538 SetAlignHor(wxHTML_ALIGN_JUSTIFY
);
539 else if (alg
== wxT("RIGHT"))
540 SetAlignHor(wxHTML_ALIGN_RIGHT
);
547 void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag
& tag
, double pixel_scale
)
549 if (tag
.HasParam(wxT("WIDTH"))) {
551 wxString wd
= tag
.GetParam(wxT("WIDTH"));
553 if (wd
[wd
.Length()-1] == wxT('%')) {
554 wxSscanf(wd
.c_str(), wxT("%i%%"), &wdi
);
555 SetWidthFloat(wdi
, wxHTML_UNITS_PERCENT
);
558 wxSscanf(wd
.c_str(), wxT("%i"), &wdi
);
559 SetWidthFloat((int)(pixel_scale
* (double)wdi
), wxHTML_UNITS_PIXELS
);
567 const wxHtmlCell
* wxHtmlContainerCell::Find(int condition
, const void* param
) const
569 const wxHtmlCell
*r
= NULL
;
572 r
= m_Cells
-> Find(condition
, param
);
576 return wxHtmlCell::Find(condition
, param
);
581 void wxHtmlContainerCell::OnMouseClick(wxWindow
*parent
, int x
, int y
, const wxMouseEvent
& event
)
584 wxHtmlCell
*c
= m_Cells
;
586 if ( (c
-> GetPosX() <= x
) &&
587 (c
-> GetPosY() <= y
) &&
588 (c
-> GetPosX() + c
-> GetWidth() > x
) &&
589 (c
-> GetPosY() + c
-> GetHeight() > y
)) {
590 c
-> OnMouseClick(parent
, x
- c
-> GetPosX(), y
- c
-> GetPosY(), event
);
602 //--------------------------------------------------------------------------------
604 //--------------------------------------------------------------------------------
606 void wxHtmlColourCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
608 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
609 dc
.SetTextForeground(m_Colour
);
610 if (m_Flags
& wxHTML_CLR_BACKGROUND
) {
611 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
612 dc
.SetTextBackground(m_Colour
);
614 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
617 void wxHtmlColourCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
619 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
620 dc
.SetTextForeground(m_Colour
);
621 if (m_Flags
& wxHTML_CLR_BACKGROUND
) {
622 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
623 dc
.SetTextBackground(m_Colour
);
625 wxHtmlCell::DrawInvisible(dc
, x
, y
);
631 //--------------------------------------------------------------------------------
633 //--------------------------------------------------------------------------------
635 void wxHtmlFontCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
638 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
641 void wxHtmlFontCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
644 wxHtmlCell::DrawInvisible(dc
, x
, y
);
654 //--------------------------------------------------------------------------------
656 //--------------------------------------------------------------------------------
658 wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow
*wnd
, int w
)
662 m_Wnd
-> GetSize(&sx
, &sy
);
663 m_Width
= sx
, m_Height
= sy
;
668 void wxHtmlWidgetCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
670 int absx
= 0, absy
= 0, stx
, sty
;
671 wxHtmlCell
*c
= this;
674 absx
+= c
-> GetPosX();
675 absy
+= c
-> GetPosY();
676 c
= c
-> GetParent();
679 ((wxScrolledWindow
*)(m_Wnd
-> GetParent())) -> ViewStart(&stx
, &sty
);
680 m_Wnd
-> SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
682 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
687 void wxHtmlWidgetCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
689 int absx
= 0, absy
= 0, stx
, sty
;
690 wxHtmlCell
*c
= this;
693 absx
+= c
-> GetPosX();
694 absy
+= c
-> GetPosY();
695 c
= c
-> GetParent();
698 ((wxScrolledWindow
*)(m_Wnd
-> GetParent())) -> ViewStart(&stx
, &sty
);
699 m_Wnd
-> SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
701 wxHtmlCell::DrawInvisible(dc
, x
, y
);
706 void wxHtmlWidgetCell::Layout(int w
)
708 if (m_WidthFloat
!= 0) {
709 m_Width
= (w
* m_WidthFloat
) / 100;
710 m_Wnd
-> SetSize(m_Width
, m_Height
);
713 wxHtmlCell::Layout(w
);