]>
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
;
89 if (link
.GetHref() != wxEmptyString
)
90 m_Link
= new wxHtmlLinkInfo(link
);
95 void wxHtmlCell::Layout(int w
)
98 if (m_Next
) m_Next
-> Layout(w
);
102 void wxHtmlCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
104 if (m_Next
) m_Next
-> Draw(dc
, x
, y
, view_y1
, view_y2
);
109 void wxHtmlCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
111 if (m_Next
) m_Next
-> DrawInvisible(dc
, x
, y
);
116 const wxHtmlCell
* wxHtmlCell::Find(int condition
, const void* param
) const
118 if (m_Next
) return m_Next
-> Find(condition
, param
);
124 //-----------------------------------------------------------------------------
126 //-----------------------------------------------------------------------------
128 wxHtmlWordCell::wxHtmlWordCell(const wxString
& word
, wxDC
& dc
) : wxHtmlCell()
132 if (m_Word
.Find(wxT('&')) != -1)
134 #define ESCSEQ(escape, subst) \
135 { wxT("&"escape";"), wxT("&"escape" "), wxT(subst) }
136 static wxChar
* substitutions
[][3] =
138 ESCSEQ("quot", "\""),
143 ESCSEQ("iexcl", "!"),
147 ESCSEQ("brkbar", " "),
151 ESCSEQ("copy", "(c)"),
153 ESCSEQ("laquo", " "),
156 ESCSEQ("reg", "(r)"),
159 ESCSEQ("plusm", " "),
161 ESCSEQ("acute", " "),
162 ESCSEQ("micro", " "),
166 ESCSEQ("raquo", " "),
168 ESCSEQ("iquest", " "),
169 ESCSEQ("Agrave", "À"),
171 ESCSEQ("Acirc", "Â"),
172 ESCSEQ("Atilde", "Ã"),
174 ESCSEQ("Aring", " "),
175 ESCSEQ("AElig", " "),
176 ESCSEQ("Ccedil", "ç"),
177 ESCSEQ("Egrave", "È"),
178 ESCSEQ("Eacute", "É"),
179 ESCSEQ("Ecirc", "Ê"),
181 ESCSEQ("Igrave", "Ì"),
183 ESCSEQ("Icirc", "Î"),
186 ESCSEQ("Ntilde", "Ñ"),
187 ESCSEQ("Ograve", "Ò"),
189 ESCSEQ("Ocirc", "Ô"),
190 ESCSEQ("Otilde", "Õ"),
193 ESCSEQ("Oslash", " "),
194 ESCSEQ("Ugrave", "Ù"),
196 ESCSEQ("Ucirc", " "),
199 ESCSEQ("szlig", "§"),
200 ESCSEQ("agrave;","à"),
201 ESCSEQ("aacute", "á"),
202 ESCSEQ("acirc", "â"),
203 ESCSEQ("atilde", "ã"),
205 ESCSEQ("aring", "a"),
206 ESCSEQ("aelig", "ae"),
207 ESCSEQ("ccedil", "ç"),
208 ESCSEQ("egrave", "è"),
209 ESCSEQ("eacute", "é"),
210 ESCSEQ("ecirc", "ê"),
212 ESCSEQ("igrave", "ì"),
213 ESCSEQ("iacute", "í"),
214 ESCSEQ("icirc", " "),
217 ESCSEQ("ntilde", "ñ"),
218 ESCSEQ("ograve", "ò"),
219 ESCSEQ("oacute", "ó"),
220 ESCSEQ("ocirc", "ô"),
221 ESCSEQ("otilde", "õ"),
223 ESCSEQ("divide", " "),
224 ESCSEQ("oslash", " "),
225 ESCSEQ("ugrave", "ù"),
226 ESCSEQ("uacute", "ú"),
227 ESCSEQ("ucirc", "û"),
232 /* this one should ALWAYS stay the last one!!! */
238 for (int i
= 0; substitutions
[i
][0] != NULL
; i
++)
240 m_Word
.Replace(substitutions
[i
][0], substitutions
[i
][2], TRUE
);
241 m_Word
.Replace(substitutions
[i
][1], substitutions
[i
][2], TRUE
);
245 dc
.GetTextExtent(m_Word
, &m_Width
, &m_Height
, &m_Descent
);
246 SetCanLiveOnPagebreak(FALSE
);
251 void wxHtmlWordCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
253 dc
.DrawText(m_Word
, x
+ m_PosX
, y
+ m_PosY
);
254 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
259 //-----------------------------------------------------------------------------
260 // wxHtmlContainerCell
261 //-----------------------------------------------------------------------------
264 wxHtmlContainerCell::wxHtmlContainerCell(wxHtmlContainerCell
*parent
) : wxHtmlCell()
266 m_Cells
= m_LastCell
= NULL
;
268 if (m_Parent
) m_Parent
-> InsertCell(this);
269 m_AlignHor
= wxHTML_ALIGN_LEFT
;
270 m_AlignVer
= wxHTML_ALIGN_BOTTOM
;
271 m_IndentLeft
= m_IndentRight
= m_IndentTop
= m_IndentBottom
= 0;
272 m_WidthFloat
= 100; m_WidthFloatUnits
= wxHTML_UNITS_PERCENT
;
273 m_UseBkColour
= FALSE
;
276 m_MinHeightAlign
= wxHTML_ALIGN_TOP
;
280 wxHtmlContainerCell::~wxHtmlContainerCell()
282 if (m_Cells
) delete m_Cells
;
287 void wxHtmlContainerCell::SetIndent(int i
, int what
, int units
)
289 int val
= (units
== wxHTML_UNITS_PIXELS
) ? i
: -i
;
290 if (what
& wxHTML_INDENT_LEFT
) m_IndentLeft
= val
;
291 if (what
& wxHTML_INDENT_RIGHT
) m_IndentRight
= val
;
292 if (what
& wxHTML_INDENT_TOP
) m_IndentTop
= val
;
293 if (what
& wxHTML_INDENT_BOTTOM
) m_IndentBottom
= val
;
299 int wxHtmlContainerCell::GetIndent(int ind
) const
301 if (ind
& wxHTML_INDENT_LEFT
) return m_IndentLeft
;
302 else if (ind
& wxHTML_INDENT_RIGHT
) return m_IndentRight
;
303 else if (ind
& wxHTML_INDENT_TOP
) return m_IndentTop
;
304 else if (ind
& wxHTML_INDENT_BOTTOM
) return m_IndentBottom
;
305 else return -1; /* BUG! Should not be called... */
311 int wxHtmlContainerCell::GetIndentUnits(int ind
) const
314 if (ind
& wxHTML_INDENT_LEFT
) p
= m_IndentLeft
< 0;
315 else if (ind
& wxHTML_INDENT_RIGHT
) p
= m_IndentRight
< 0;
316 else if (ind
& wxHTML_INDENT_TOP
) p
= m_IndentTop
< 0;
317 else if (ind
& wxHTML_INDENT_BOTTOM
) p
= m_IndentBottom
< 0;
318 if (p
) return wxHTML_UNITS_PERCENT
;
319 else return wxHTML_UNITS_PIXELS
;
324 bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak
) const
326 if (!m_CanLiveOnPagebreak
)
327 return wxHtmlCell::AdjustPagebreak(pagebreak
);
330 wxHtmlCell
*c
= GetFirstCell();
332 int pbrk
= *pagebreak
- m_PosY
;
335 if (c
-> AdjustPagebreak(&pbrk
)) rt
= TRUE
;
338 if (rt
) *pagebreak
= pbrk
+ m_PosY
;
345 void wxHtmlContainerCell::Layout(int w
)
347 if (m_LastLayout
== w
) {
348 wxHtmlCell::Layout(w
);
352 wxHtmlCell
*cell
= m_Cells
, *line
= m_Cells
;
353 long xpos
= 0, ypos
= m_IndentTop
;
354 int xdelta
= 0, ybasicpos
= 0, ydiff
;
355 int s_width
, s_indent
;
356 int ysizeup
= 0, ysizedown
= 0;
357 int MaxLineWidth
= 0;
367 if (m_WidthFloatUnits
== wxHTML_UNITS_PERCENT
) {
368 if (m_WidthFloat
< 0) m_Width
= (100 + m_WidthFloat
) * w
/ 100;
369 else m_Width
= m_WidthFloat
* w
/ 100;
372 if (m_WidthFloat
< 0) m_Width
= w
+ m_WidthFloat
;
373 else m_Width
= m_WidthFloat
;
377 int l
= (m_IndentLeft
< 0) ? (-m_IndentLeft
* m_Width
/ 100) : m_IndentLeft
;
378 int r
= (m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
;
379 m_Cells
-> Layout(m_Width
- (l
+ r
));
388 // adjust indentation:
389 s_indent
= (m_IndentLeft
< 0) ? (-m_IndentLeft
* m_Width
/ 100) : m_IndentLeft
;
390 s_width
= m_Width
- s_indent
- ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
393 while (cell
!= NULL
) {
394 switch (m_AlignVer
) {
395 case wxHTML_ALIGN_TOP
: ybasicpos
= 0; break;
396 case wxHTML_ALIGN_BOTTOM
: ybasicpos
= - cell
-> GetHeight(); break;
397 case wxHTML_ALIGN_CENTER
: ybasicpos
= - cell
-> GetHeight() / 2; break;
399 ydiff
= cell
-> GetHeight() + ybasicpos
;
401 if (cell
-> GetDescent() + ydiff
> ysizedown
) ysizedown
= cell
-> GetDescent() + ydiff
;
402 if (ybasicpos
+ cell
-> GetDescent() < -ysizeup
) ysizeup
= - (ybasicpos
+ cell
-> GetDescent());
404 cell
-> SetPos(xpos
, ybasicpos
+ cell
-> GetDescent());
405 xpos
+= cell
-> GetWidth();
406 cell
= cell
-> GetNext();
409 // force new line if occured:
410 if ((cell
== NULL
) || (xpos
+ cell
-> GetWidth() > s_width
)) {
411 if (xpos
> MaxLineWidth
) MaxLineWidth
= xpos
;
412 if (ysizeup
< 0) ysizeup
= 0;
413 if (ysizedown
< 0) ysizedown
= 0;
414 switch (m_AlignHor
) {
415 case wxHTML_ALIGN_LEFT
:
416 case wxHTML_ALIGN_JUSTIFY
:
419 case wxHTML_ALIGN_RIGHT
:
420 xdelta
= 0 + (s_width
- xpos
);
422 case wxHTML_ALIGN_CENTER
:
423 xdelta
= 0 + (s_width
- xpos
) / 2;
426 if (xdelta
< 0) xdelta
= 0;
431 if (m_AlignHor
!= wxHTML_ALIGN_JUSTIFY
|| cell
== NULL
)
432 while (line
!= cell
) {
433 line
-> SetPos(line
-> GetPosX() + xdelta
,
434 ypos
+ line
-> GetPosY());
435 line
= line
-> GetNext();
440 int step
= (s_width
- xpos
);
441 if (step
< 0) step
= 0;
442 while (line
!= cell
) {
443 line
-> SetPos(line
-> GetPosX() + s_indent
+
444 (counter
++ * step
/ xcnt
),
445 ypos
+ line
-> GetPosY());
446 line
= line
-> GetNext();
452 ysizeup
= ysizedown
= 0;
457 // setup height & width, depending on container layout:
458 m_Height
= ypos
+ (ysizedown
+ ysizeup
) + m_IndentBottom
;
460 if (m_Height
< m_MinHeight
) {
461 if (m_MinHeightAlign
!= wxHTML_ALIGN_TOP
) {
462 int diff
= m_MinHeight
- m_Height
;
463 if (m_MinHeightAlign
== wxHTML_ALIGN_CENTER
) diff
/= 2;
466 cell
-> SetPos(cell
-> GetPosX(), cell
-> GetPosY() + diff
);
467 cell
= cell
-> GetNext();
470 m_Height
= m_MinHeight
;
473 MaxLineWidth
+= s_indent
+ ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
474 if (m_Width
< MaxLineWidth
) m_Width
= MaxLineWidth
;
478 wxHtmlCell::Layout(w
);
482 #define mMin(a, b) (((a) < (b)) ? (a) : (b))
483 #define mMax(a, b) (((a) < (b)) ? (b) : (a))
485 void wxHtmlContainerCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
487 // container visible, draw it:
488 if ((y
+ m_PosY
< view_y2
) && (y
+ m_PosY
+ m_Height
> view_y1
)) {
491 wxBrush myb
= wxBrush(m_BkColour
, wxSOLID
);
493 int real_y1
= mMax(y
+ m_PosY
, view_y1
);
494 int real_y2
= mMin(y
+ m_PosY
+ m_Height
- 1, view_y2
);
497 dc
.SetPen(*wxTRANSPARENT_PEN
);
498 dc
.DrawRectangle(x
+ m_PosX
, real_y1
, m_Width
, real_y2
- real_y1
+ 1);
502 wxPen
mypen1(m_BorderColour1
, 1, wxSOLID
);
503 wxPen
mypen2(m_BorderColour2
, 1, wxSOLID
);
506 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1);
507 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
);
509 dc
.DrawLine(x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
510 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
513 if (m_Cells
) m_Cells
-> Draw(dc
, x
+ m_PosX
, y
+ m_PosY
, view_y1
, view_y2
);
515 // container invisible, just proceed font+color changing:
517 if (m_Cells
) m_Cells
-> DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
520 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
525 void wxHtmlContainerCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
527 if (m_Cells
) m_Cells
-> DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
528 wxHtmlCell::DrawInvisible(dc
, x
, y
);
533 wxHtmlLinkInfo
*wxHtmlContainerCell::GetLink(int x
, int y
) const
535 wxHtmlCell
*c
= m_Cells
;
539 cx
= c
-> GetPosX(), cy
= c
-> GetPosY();
540 cw
= c
-> GetWidth(), ch
= c
-> GetHeight();
541 if ((x
>= cx
) && (x
< cx
+ cw
) && (y
>= cy
) && (y
< cy
+ ch
))
542 return c
-> GetLink(x
- cx
, y
- cy
);
550 void wxHtmlContainerCell::InsertCell(wxHtmlCell
*f
)
552 if (!m_Cells
) m_Cells
= m_LastCell
= f
;
554 m_LastCell
-> SetNext(f
);
556 if (m_LastCell
) while (m_LastCell
-> GetNext()) m_LastCell
= m_LastCell
-> GetNext();
558 f
-> SetParent(this);
564 void wxHtmlContainerCell::SetAlign(const wxHtmlTag
& tag
)
566 if (tag
.HasParam(wxT("ALIGN"))) {
567 wxString alg
= tag
.GetParam(wxT("ALIGN"));
569 if (alg
== wxT("CENTER"))
570 SetAlignHor(wxHTML_ALIGN_CENTER
);
571 else if (alg
== wxT("LEFT"))
572 SetAlignHor(wxHTML_ALIGN_LEFT
);
573 else if (alg
== wxT("JUSTIFY"))
574 SetAlignHor(wxHTML_ALIGN_JUSTIFY
);
575 else if (alg
== wxT("RIGHT"))
576 SetAlignHor(wxHTML_ALIGN_RIGHT
);
583 void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag
& tag
, double pixel_scale
)
585 if (tag
.HasParam(wxT("WIDTH"))) {
587 wxString wd
= tag
.GetParam(wxT("WIDTH"));
589 if (wd
[wd
.Length()-1] == wxT('%')) {
590 wxSscanf(wd
.c_str(), wxT("%i%%"), &wdi
);
591 SetWidthFloat(wdi
, wxHTML_UNITS_PERCENT
);
594 wxSscanf(wd
.c_str(), wxT("%i"), &wdi
);
595 SetWidthFloat((int)(pixel_scale
* (double)wdi
), wxHTML_UNITS_PIXELS
);
603 const wxHtmlCell
* wxHtmlContainerCell::Find(int condition
, const void* param
) const
605 const wxHtmlCell
*r
= NULL
;
608 r
= m_Cells
-> Find(condition
, param
);
612 return wxHtmlCell::Find(condition
, param
);
617 void wxHtmlContainerCell::OnMouseClick(wxWindow
*parent
, int x
, int y
, const wxMouseEvent
& event
)
620 wxHtmlCell
*c
= m_Cells
;
622 if ( (c
-> GetPosX() <= x
) &&
623 (c
-> GetPosY() <= y
) &&
624 (c
-> GetPosX() + c
-> GetWidth() > x
) &&
625 (c
-> GetPosY() + c
-> GetHeight() > y
)) {
626 c
-> OnMouseClick(parent
, x
- c
-> GetPosX(), y
- c
-> GetPosY(), event
);
638 //--------------------------------------------------------------------------------
640 //--------------------------------------------------------------------------------
642 void wxHtmlColourCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
644 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
645 dc
.SetTextForeground(m_Colour
);
646 if (m_Flags
& wxHTML_CLR_BACKGROUND
) {
647 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
648 dc
.SetTextBackground(m_Colour
);
650 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
653 void wxHtmlColourCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
655 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
656 dc
.SetTextForeground(m_Colour
);
657 if (m_Flags
& wxHTML_CLR_BACKGROUND
) {
658 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
659 dc
.SetTextBackground(m_Colour
);
661 wxHtmlCell::DrawInvisible(dc
, x
, y
);
667 //--------------------------------------------------------------------------------
669 //--------------------------------------------------------------------------------
671 void wxHtmlFontCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
674 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
677 void wxHtmlFontCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
680 wxHtmlCell::DrawInvisible(dc
, x
, y
);
690 //--------------------------------------------------------------------------------
692 //--------------------------------------------------------------------------------
694 wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow
*wnd
, int w
)
698 m_Wnd
-> GetSize(&sx
, &sy
);
699 m_Width
= sx
, m_Height
= sy
;
704 void wxHtmlWidgetCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
706 int absx
= 0, absy
= 0, stx
, sty
;
707 wxHtmlCell
*c
= this;
710 absx
+= c
-> GetPosX();
711 absy
+= c
-> GetPosY();
712 c
= c
-> GetParent();
715 ((wxScrolledWindow
*)(m_Wnd
-> GetParent())) -> ViewStart(&stx
, &sty
);
716 m_Wnd
-> SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
718 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
723 void wxHtmlWidgetCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
725 int absx
= 0, absy
= 0, stx
, sty
;
726 wxHtmlCell
*c
= this;
729 absx
+= c
-> GetPosX();
730 absy
+= c
-> GetPosY();
731 c
= c
-> GetParent();
734 ((wxScrolledWindow
*)(m_Wnd
-> GetParent())) -> ViewStart(&stx
, &sty
);
735 m_Wnd
-> SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
737 wxHtmlCell::DrawInvisible(dc
, x
, y
);
742 void wxHtmlWidgetCell::Layout(int w
)
744 if (m_WidthFloat
!= 0) {
745 m_Width
= (w
* m_WidthFloat
) / 100;
746 m_Wnd
-> SetSize(m_Width
, m_Height
);
749 wxHtmlCell::Layout(w
);