]>
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
;
244 m_MinHeight
= m_MaxLineWidth
= 0;
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;
328 if (m_WidthFloatUnits
== wxHTML_UNITS_PERCENT
) {
329 if (m_WidthFloat
< 0) m_Width
= (100 + m_WidthFloat
) * w
/ 100;
330 else m_Width
= m_WidthFloat
* w
/ 100;
333 if (m_WidthFloat
< 0) m_Width
= w
+ m_WidthFloat
;
334 else m_Width
= m_WidthFloat
;
338 int l
= (m_IndentLeft
< 0) ? (-m_IndentLeft
* m_Width
/ 100) : m_IndentLeft
;
339 int r
= (m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
;
340 m_Cells
-> Layout(m_Width
- (l
+ r
));
349 // adjust indentation:
350 s_indent
= (m_IndentLeft
< 0) ? (-m_IndentLeft
* m_Width
/ 100) : m_IndentLeft
;
351 s_width
= m_Width
- s_indent
- ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
356 while (cell
!= NULL
) {
357 switch (m_AlignVer
) {
358 case wxHTML_ALIGN_TOP
: ybasicpos
= 0; break;
359 case wxHTML_ALIGN_BOTTOM
: ybasicpos
= - cell
-> GetHeight(); break;
360 case wxHTML_ALIGN_CENTER
: ybasicpos
= - cell
-> GetHeight() / 2; break;
362 ydiff
= cell
-> GetHeight() + ybasicpos
;
364 if (cell
-> GetDescent() + ydiff
> ysizedown
) ysizedown
= cell
-> GetDescent() + ydiff
;
365 if (ybasicpos
+ cell
-> GetDescent() < -ysizeup
) ysizeup
= - (ybasicpos
+ cell
-> GetDescent());
367 cell
-> SetPos(xpos
, ybasicpos
+ cell
-> GetDescent());
368 xpos
+= cell
-> GetWidth();
369 cell
= cell
-> GetNext();
371 // force new line if occured:
372 if ((cell
== NULL
) || (xpos
+ cell
-> GetWidth() > s_width
)) {
373 if (xpos
> m_MaxLineWidth
) m_MaxLineWidth
= xpos
;
374 if (ysizeup
< 0) ysizeup
= 0;
375 if (ysizedown
< 0) ysizedown
= 0;
376 switch (m_AlignHor
) {
377 case wxHTML_ALIGN_LEFT
: xdelta
= 0; break;
378 case wxHTML_ALIGN_RIGHT
: xdelta
= 0 + (s_width
- xpos
); break;
379 case wxHTML_ALIGN_CENTER
: xdelta
= 0 + (s_width
- xpos
) / 2; break;
381 if (xdelta
< 0) xdelta
= 0;
385 while (line
!= cell
) {
386 line
-> SetPos(line
-> GetPosX() + xdelta
, ypos
+ line
-> GetPosY());
387 line
= line
-> GetNext();
392 ysizeup
= ysizedown
= 0;
397 // setup height & width, depending on container layout:
398 m_Height
= ypos
+ (ysizedown
+ ysizeup
) + m_IndentBottom
;
400 if (m_Height
< m_MinHeight
) {
401 if (m_MinHeightAlign
!= wxHTML_ALIGN_TOP
) {
402 int diff
= m_MinHeight
- m_Height
;
403 if (m_MinHeightAlign
== wxHTML_ALIGN_CENTER
) diff
/= 2;
406 cell
-> SetPos(cell
-> GetPosX(), cell
-> GetPosY() + diff
);
407 cell
= cell
-> GetNext();
410 m_Height
= m_MinHeight
;
413 m_MaxLineWidth
+= s_indent
+ ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
414 if (m_Width
< m_MaxLineWidth
) m_Width
= m_MaxLineWidth
;
418 wxHtmlCell::Layout(w
);
422 #define mMin(a, b) (((a) < (b)) ? (a) : (b))
423 #define mMax(a, b) (((a) < (b)) ? (b) : (a))
425 void wxHtmlContainerCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
427 // container visible, draw it:
428 if ((y
+ m_PosY
< view_y2
) && (y
+ m_PosY
+ m_Height
> view_y1
)) {
431 wxBrush myb
= wxBrush(m_BkColour
, wxSOLID
);
433 int real_y1
= mMax(y
+ m_PosY
, view_y1
);
434 int real_y2
= mMin(y
+ m_PosY
+ m_Height
- 1, view_y2
);
437 dc
.SetPen(*wxTRANSPARENT_PEN
);
438 dc
.DrawRectangle(x
+ m_PosX
, real_y1
, m_Width
, real_y2
- real_y1
+ 1);
442 wxPen
mypen1(m_BorderColour1
, 1, wxSOLID
);
443 wxPen
mypen2(m_BorderColour2
, 1, wxSOLID
);
446 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1);
447 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
);
449 dc
.DrawLine(x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
450 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
453 if (m_Cells
) m_Cells
-> Draw(dc
, x
+ m_PosX
, y
+ m_PosY
, view_y1
, view_y2
);
455 // container invisible, just proceed font+color changing:
457 if (m_Cells
) m_Cells
-> DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
460 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
465 void wxHtmlContainerCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
467 if (m_Cells
) m_Cells
-> DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
468 wxHtmlCell::DrawInvisible(dc
, x
, y
);
473 wxHtmlLinkInfo
*wxHtmlContainerCell::GetLink(int x
, int y
) const
475 wxHtmlCell
*c
= m_Cells
;
479 cx
= c
-> GetPosX(), cy
= c
-> GetPosY();
480 cw
= c
-> GetWidth(), ch
= c
-> GetHeight();
481 if ((x
>= cx
) && (x
< cx
+ cw
) && (y
>= cy
) && (y
< cy
+ ch
))
482 return c
-> GetLink(x
- cx
, y
- cy
);
490 void wxHtmlContainerCell::InsertCell(wxHtmlCell
*f
)
492 if (!m_Cells
) m_Cells
= m_LastCell
= f
;
494 m_LastCell
-> SetNext(f
);
496 if (m_LastCell
) while (m_LastCell
-> GetNext()) m_LastCell
= m_LastCell
-> GetNext();
498 f
-> SetParent(this);
504 void wxHtmlContainerCell::SetAlign(const wxHtmlTag
& tag
)
506 if (tag
.HasParam(wxT("ALIGN"))) {
507 wxString alg
= tag
.GetParam(wxT("ALIGN"));
509 if (alg
== wxT("CENTER"))
510 SetAlignHor(wxHTML_ALIGN_CENTER
);
511 else if (alg
== wxT("LEFT"))
512 SetAlignHor(wxHTML_ALIGN_LEFT
);
513 else if (alg
== wxT("RIGHT"))
514 SetAlignHor(wxHTML_ALIGN_RIGHT
);
521 void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag
& tag
, double pixel_scale
)
523 if (tag
.HasParam(wxT("WIDTH"))) {
525 wxString wd
= tag
.GetParam(wxT("WIDTH"));
527 if (wd
[wd
.Length()-1] == wxT('%')) {
528 wxSscanf(wd
.c_str(), wxT("%i%%"), &wdi
);
529 SetWidthFloat(wdi
, wxHTML_UNITS_PERCENT
);
532 wxSscanf(wd
.c_str(), wxT("%i"), &wdi
);
533 SetWidthFloat((int)(pixel_scale
* (double)wdi
), wxHTML_UNITS_PIXELS
);
541 const wxHtmlCell
* wxHtmlContainerCell::Find(int condition
, const void* param
) const
543 const wxHtmlCell
*r
= NULL
;
546 r
= m_Cells
-> Find(condition
, param
);
550 return wxHtmlCell::Find(condition
, param
);
555 void wxHtmlContainerCell::OnMouseClick(wxWindow
*parent
, int x
, int y
, const wxMouseEvent
& event
)
558 wxHtmlCell
*c
= m_Cells
;
560 if ( (c
-> GetPosX() <= x
) &&
561 (c
-> GetPosY() <= y
) &&
562 (c
-> GetPosX() + c
-> GetWidth() > x
) &&
563 (c
-> GetPosY() + c
-> GetHeight() > y
)) {
564 c
-> OnMouseClick(parent
, x
- c
-> GetPosX(), y
- c
-> GetPosY(), event
);
576 //--------------------------------------------------------------------------------
578 //--------------------------------------------------------------------------------
580 void wxHtmlColourCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
582 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
583 dc
.SetTextForeground(m_Colour
);
584 if (m_Flags
& wxHTML_CLR_BACKGROUND
) {
585 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
586 dc
.SetTextBackground(m_Colour
);
588 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
591 void wxHtmlColourCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
593 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
594 dc
.SetTextForeground(m_Colour
);
595 if (m_Flags
& wxHTML_CLR_BACKGROUND
) {
596 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
597 dc
.SetTextBackground(m_Colour
);
599 wxHtmlCell::DrawInvisible(dc
, x
, y
);
605 //--------------------------------------------------------------------------------
607 //--------------------------------------------------------------------------------
609 void wxHtmlFontCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
612 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
615 void wxHtmlFontCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
618 wxHtmlCell::DrawInvisible(dc
, x
, y
);
628 //--------------------------------------------------------------------------------
630 //--------------------------------------------------------------------------------
632 wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow
*wnd
, int w
)
636 m_Wnd
-> GetSize(&sx
, &sy
);
637 m_Width
= sx
, m_Height
= sy
;
642 void wxHtmlWidgetCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
644 int absx
= 0, absy
= 0, stx
, sty
;
645 wxHtmlCell
*c
= this;
648 absx
+= c
-> GetPosX();
649 absy
+= c
-> GetPosY();
650 c
= c
-> GetParent();
653 ((wxScrolledWindow
*)(m_Wnd
-> GetParent())) -> ViewStart(&stx
, &sty
);
654 m_Wnd
-> SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
656 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
661 void wxHtmlWidgetCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
663 int absx
= 0, absy
= 0, stx
, sty
;
664 wxHtmlCell
*c
= this;
667 absx
+= c
-> GetPosX();
668 absy
+= c
-> GetPosY();
669 c
= c
-> GetParent();
672 ((wxScrolledWindow
*)(m_Wnd
-> GetParent())) -> ViewStart(&stx
, &sty
);
673 m_Wnd
-> SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
675 wxHtmlCell::DrawInvisible(dc
, x
, y
);
680 void wxHtmlWidgetCell::Layout(int w
)
682 if (m_WidthFloat
!= 0) {
683 m_Width
= (w
* m_WidthFloat
) / 100;
684 m_Wnd
-> SetSize(m_Width
, m_Height
);
687 wxHtmlCell::Layout(w
);