]>
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;
443 if (xcnt
> 0) while (line
!= cell
) {
444 line
-> SetPos(line
-> GetPosX() + s_indent
+
445 (counter
++ * step
/ xcnt
),
446 ypos
+ line
-> GetPosY());
447 line
= line
-> GetNext();
454 ysizeup
= ysizedown
= 0;
459 // setup height & width, depending on container layout:
460 m_Height
= ypos
+ (ysizedown
+ ysizeup
) + m_IndentBottom
;
462 if (m_Height
< m_MinHeight
) {
463 if (m_MinHeightAlign
!= wxHTML_ALIGN_TOP
) {
464 int diff
= m_MinHeight
- m_Height
;
465 if (m_MinHeightAlign
== wxHTML_ALIGN_CENTER
) diff
/= 2;
468 cell
-> SetPos(cell
-> GetPosX(), cell
-> GetPosY() + diff
);
469 cell
= cell
-> GetNext();
472 m_Height
= m_MinHeight
;
475 MaxLineWidth
+= s_indent
+ ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
476 if (m_Width
< MaxLineWidth
) m_Width
= MaxLineWidth
;
480 wxHtmlCell::Layout(w
);
484 #define mMin(a, b) (((a) < (b)) ? (a) : (b))
485 #define mMax(a, b) (((a) < (b)) ? (b) : (a))
487 void wxHtmlContainerCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
489 // container visible, draw it:
490 if ((y
+ m_PosY
< view_y2
) && (y
+ m_PosY
+ m_Height
> view_y1
)) {
493 wxBrush myb
= wxBrush(m_BkColour
, wxSOLID
);
495 int real_y1
= mMax(y
+ m_PosY
, view_y1
);
496 int real_y2
= mMin(y
+ m_PosY
+ m_Height
- 1, view_y2
);
499 dc
.SetPen(*wxTRANSPARENT_PEN
);
500 dc
.DrawRectangle(x
+ m_PosX
, real_y1
, m_Width
, real_y2
- real_y1
+ 1);
504 wxPen
mypen1(m_BorderColour1
, 1, wxSOLID
);
505 wxPen
mypen2(m_BorderColour2
, 1, wxSOLID
);
508 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1);
509 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
);
511 dc
.DrawLine(x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
512 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
515 if (m_Cells
) m_Cells
-> Draw(dc
, x
+ m_PosX
, y
+ m_PosY
, view_y1
, view_y2
);
517 // container invisible, just proceed font+color changing:
519 if (m_Cells
) m_Cells
-> DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
522 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
527 void wxHtmlContainerCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
529 if (m_Cells
) m_Cells
-> DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
530 wxHtmlCell::DrawInvisible(dc
, x
, y
);
535 wxHtmlLinkInfo
*wxHtmlContainerCell::GetLink(int x
, int y
) const
537 wxHtmlCell
*c
= m_Cells
;
541 cx
= c
-> GetPosX(), cy
= c
-> GetPosY();
542 cw
= c
-> GetWidth(), ch
= c
-> GetHeight();
543 if ((x
>= cx
) && (x
< cx
+ cw
) && (y
>= cy
) && (y
< cy
+ ch
))
544 return c
-> GetLink(x
- cx
, y
- cy
);
552 void wxHtmlContainerCell::InsertCell(wxHtmlCell
*f
)
554 if (!m_Cells
) m_Cells
= m_LastCell
= f
;
556 m_LastCell
-> SetNext(f
);
558 if (m_LastCell
) while (m_LastCell
-> GetNext()) m_LastCell
= m_LastCell
-> GetNext();
560 f
-> SetParent(this);
566 void wxHtmlContainerCell::SetAlign(const wxHtmlTag
& tag
)
568 if (tag
.HasParam(wxT("ALIGN"))) {
569 wxString alg
= tag
.GetParam(wxT("ALIGN"));
571 if (alg
== wxT("CENTER"))
572 SetAlignHor(wxHTML_ALIGN_CENTER
);
573 else if (alg
== wxT("LEFT"))
574 SetAlignHor(wxHTML_ALIGN_LEFT
);
575 else if (alg
== wxT("JUSTIFY"))
576 SetAlignHor(wxHTML_ALIGN_JUSTIFY
);
577 else if (alg
== wxT("RIGHT"))
578 SetAlignHor(wxHTML_ALIGN_RIGHT
);
585 void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag
& tag
, double pixel_scale
)
587 if (tag
.HasParam(wxT("WIDTH"))) {
589 wxString wd
= tag
.GetParam(wxT("WIDTH"));
591 if (wd
[wd
.Length()-1] == wxT('%')) {
592 wxSscanf(wd
.c_str(), wxT("%i%%"), &wdi
);
593 SetWidthFloat(wdi
, wxHTML_UNITS_PERCENT
);
596 wxSscanf(wd
.c_str(), wxT("%i"), &wdi
);
597 SetWidthFloat((int)(pixel_scale
* (double)wdi
), wxHTML_UNITS_PIXELS
);
605 const wxHtmlCell
* wxHtmlContainerCell::Find(int condition
, const void* param
) const
607 const wxHtmlCell
*r
= NULL
;
610 r
= m_Cells
-> Find(condition
, param
);
614 return wxHtmlCell::Find(condition
, param
);
619 void wxHtmlContainerCell::OnMouseClick(wxWindow
*parent
, int x
, int y
, const wxMouseEvent
& event
)
622 wxHtmlCell
*c
= m_Cells
;
624 if ( (c
-> GetPosX() <= x
) &&
625 (c
-> GetPosY() <= y
) &&
626 (c
-> GetPosX() + c
-> GetWidth() > x
) &&
627 (c
-> GetPosY() + c
-> GetHeight() > y
)) {
628 c
-> OnMouseClick(parent
, x
- c
-> GetPosX(), y
- c
-> GetPosY(), event
);
640 //--------------------------------------------------------------------------------
642 //--------------------------------------------------------------------------------
644 void wxHtmlColourCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
646 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
647 dc
.SetTextForeground(m_Colour
);
648 if (m_Flags
& wxHTML_CLR_BACKGROUND
) {
649 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
650 dc
.SetTextBackground(m_Colour
);
652 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
655 void wxHtmlColourCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
657 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
658 dc
.SetTextForeground(m_Colour
);
659 if (m_Flags
& wxHTML_CLR_BACKGROUND
) {
660 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
661 dc
.SetTextBackground(m_Colour
);
663 wxHtmlCell::DrawInvisible(dc
, x
, y
);
669 //--------------------------------------------------------------------------------
671 //--------------------------------------------------------------------------------
673 void wxHtmlFontCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
676 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
679 void wxHtmlFontCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
682 wxHtmlCell::DrawInvisible(dc
, x
, y
);
692 //--------------------------------------------------------------------------------
694 //--------------------------------------------------------------------------------
696 wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow
*wnd
, int w
)
700 m_Wnd
-> GetSize(&sx
, &sy
);
701 m_Width
= sx
, m_Height
= sy
;
706 void wxHtmlWidgetCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
708 int absx
= 0, absy
= 0, stx
, sty
;
709 wxHtmlCell
*c
= this;
712 absx
+= c
-> GetPosX();
713 absy
+= c
-> GetPosY();
714 c
= c
-> GetParent();
717 ((wxScrolledWindow
*)(m_Wnd
-> GetParent())) -> ViewStart(&stx
, &sty
);
718 m_Wnd
-> SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
720 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
725 void wxHtmlWidgetCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
727 int absx
= 0, absy
= 0, stx
, sty
;
728 wxHtmlCell
*c
= this;
731 absx
+= c
-> GetPosX();
732 absy
+= c
-> GetPosY();
733 c
= c
-> GetParent();
736 ((wxScrolledWindow
*)(m_Wnd
-> GetParent())) -> ViewStart(&stx
, &sty
);
737 m_Wnd
-> SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
739 wxHtmlCell::DrawInvisible(dc
, x
, y
);
744 void wxHtmlWidgetCell::Layout(int w
)
746 if (m_WidthFloat
!= 0) {
747 m_Width
= (w
* m_WidthFloat
) / 100;
748 m_Wnd
-> SetSize(m_Width
, m_Height
);
751 wxHtmlCell::Layout(w
);