]>
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
)
75 if (m_Next
!= NULL
) m_Next
->AdjustPagebreak(pagebreak
);
81 if (m_Next
!= NULL
) return m_Next
->AdjustPagebreak(pagebreak
);
88 void wxHtmlCell::SetLink(const wxHtmlLinkInfo
& link
)
90 if (m_Link
) delete m_Link
;
92 if (link
.GetHref() != wxEmptyString
)
93 m_Link
= new wxHtmlLinkInfo(link
);
98 void wxHtmlCell::Layout(int w
)
101 if (m_Next
) m_Next
->Layout(w
);
105 void wxHtmlCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
107 if (m_Next
) m_Next
->Draw(dc
, x
, y
, view_y1
, view_y2
);
112 void wxHtmlCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
114 if (m_Next
) m_Next
->DrawInvisible(dc
, x
, y
);
119 const wxHtmlCell
* wxHtmlCell::Find(int condition
, const void* param
) const
121 if (m_Next
) return m_Next
->Find(condition
, param
);
127 //-----------------------------------------------------------------------------
129 //-----------------------------------------------------------------------------
131 wxHtmlWordCell::wxHtmlWordCell(const wxString
& word
, wxDC
& dc
) : wxHtmlCell()
135 if (m_Word
.Find(wxT('&')) != -1)
137 #define ESCSEQ(escape, subst) \
138 { _T("&") _T(escape) _T(";"), _T("&") _T(escape) _T(" "), _T(subst) }
139 static wxChar
* substitutions
[][3] =
141 ESCSEQ("quot", "\""),
146 ESCSEQ("iexcl", "!"),
150 ESCSEQ("brkbar", " "),
154 ESCSEQ("copy", "(c)"),
156 ESCSEQ("laquo", " "),
159 ESCSEQ("reg", "(r)"),
162 ESCSEQ("plusm", " "),
164 ESCSEQ("acute", " "),
165 ESCSEQ("micro", " "),
169 ESCSEQ("raquo", " "),
171 ESCSEQ("iquest", " "),
172 ESCSEQ("Agrave", "À"),
174 ESCSEQ("Acirc", "Â"),
175 ESCSEQ("Atilde", "Ã"),
177 ESCSEQ("Aring", " "),
178 ESCSEQ("AElig", " "),
179 ESCSEQ("Ccedil", "ç"),
180 ESCSEQ("Egrave", "È"),
181 ESCSEQ("Eacute", "É"),
182 ESCSEQ("Ecirc", "Ê"),
184 ESCSEQ("Igrave", "Ì"),
186 ESCSEQ("Icirc", "Î"),
189 ESCSEQ("Ntilde", "Ñ"),
190 ESCSEQ("Ograve", "Ò"),
192 ESCSEQ("Ocirc", "Ô"),
193 ESCSEQ("Otilde", "Õ"),
196 ESCSEQ("Oslash", " "),
197 ESCSEQ("Ugrave", "Ù"),
199 ESCSEQ("Ucirc", " "),
202 ESCSEQ("szlig", "§"),
203 ESCSEQ("agrave;","à"),
204 ESCSEQ("aacute", "á"),
205 ESCSEQ("acirc", "â"),
206 ESCSEQ("atilde", "ã"),
208 ESCSEQ("aring", "a"),
209 ESCSEQ("aelig", "ae"),
210 ESCSEQ("ccedil", "ç"),
211 ESCSEQ("egrave", "è"),
212 ESCSEQ("eacute", "é"),
213 ESCSEQ("ecirc", "ê"),
215 ESCSEQ("igrave", "ì"),
216 ESCSEQ("iacute", "í"),
217 ESCSEQ("icirc", " "),
220 ESCSEQ("ntilde", "ñ"),
221 ESCSEQ("ograve", "ò"),
222 ESCSEQ("oacute", "ó"),
223 ESCSEQ("ocirc", "ô"),
224 ESCSEQ("otilde", "õ"),
226 ESCSEQ("divide", " "),
227 ESCSEQ("oslash", " "),
228 ESCSEQ("ugrave", "ù"),
229 ESCSEQ("uacute", "ú"),
230 ESCSEQ("ucirc", "û"),
235 /* this one should ALWAYS stay the last one!!! */
241 for (int i
= 0; substitutions
[i
][0] != NULL
; i
++)
243 m_Word
.Replace(substitutions
[i
][0], substitutions
[i
][2], TRUE
);
244 m_Word
.Replace(substitutions
[i
][1], substitutions
[i
][2], TRUE
);
248 dc
.GetTextExtent(m_Word
, &m_Width
, &m_Height
, &m_Descent
);
249 SetCanLiveOnPagebreak(FALSE
);
254 void wxHtmlWordCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
256 dc
.DrawText(m_Word
, x
+ m_PosX
, y
+ m_PosY
);
257 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
262 //-----------------------------------------------------------------------------
263 // wxHtmlContainerCell
264 //-----------------------------------------------------------------------------
267 wxHtmlContainerCell::wxHtmlContainerCell(wxHtmlContainerCell
*parent
) : wxHtmlCell()
269 m_Cells
= m_LastCell
= NULL
;
271 if (m_Parent
) m_Parent
->InsertCell(this);
272 m_AlignHor
= wxHTML_ALIGN_LEFT
;
273 m_AlignVer
= wxHTML_ALIGN_BOTTOM
;
274 m_IndentLeft
= m_IndentRight
= m_IndentTop
= m_IndentBottom
= 0;
275 m_WidthFloat
= 100; m_WidthFloatUnits
= wxHTML_UNITS_PERCENT
;
276 m_UseBkColour
= FALSE
;
279 m_MinHeightAlign
= wxHTML_ALIGN_TOP
;
283 wxHtmlContainerCell::~wxHtmlContainerCell()
285 if (m_Cells
) delete m_Cells
;
290 void wxHtmlContainerCell::SetIndent(int i
, int what
, int units
)
292 int val
= (units
== wxHTML_UNITS_PIXELS
) ? i
: -i
;
293 if (what
& wxHTML_INDENT_LEFT
) m_IndentLeft
= val
;
294 if (what
& wxHTML_INDENT_RIGHT
) m_IndentRight
= val
;
295 if (what
& wxHTML_INDENT_TOP
) m_IndentTop
= val
;
296 if (what
& wxHTML_INDENT_BOTTOM
) m_IndentBottom
= val
;
302 int wxHtmlContainerCell::GetIndent(int ind
) const
304 if (ind
& wxHTML_INDENT_LEFT
) return m_IndentLeft
;
305 else if (ind
& wxHTML_INDENT_RIGHT
) return m_IndentRight
;
306 else if (ind
& wxHTML_INDENT_TOP
) return m_IndentTop
;
307 else if (ind
& wxHTML_INDENT_BOTTOM
) return m_IndentBottom
;
308 else return -1; /* BUG! Should not be called... */
314 int wxHtmlContainerCell::GetIndentUnits(int ind
) const
317 if (ind
& wxHTML_INDENT_LEFT
) p
= m_IndentLeft
< 0;
318 else if (ind
& wxHTML_INDENT_RIGHT
) p
= m_IndentRight
< 0;
319 else if (ind
& wxHTML_INDENT_TOP
) p
= m_IndentTop
< 0;
320 else if (ind
& wxHTML_INDENT_BOTTOM
) p
= m_IndentBottom
< 0;
321 if (p
) return wxHTML_UNITS_PERCENT
;
322 else return wxHTML_UNITS_PIXELS
;
327 bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak
) const
329 if (!m_CanLiveOnPagebreak
)
330 return wxHtmlCell::AdjustPagebreak(pagebreak
);
334 wxHtmlCell
*c
= GetFirstCell();
336 int pbrk
= *pagebreak
- m_PosY
;
340 if (c
->AdjustPagebreak(&pbrk
)) rt
= TRUE
;
343 if (rt
) *pagebreak
= pbrk
+ m_PosY
;
350 void wxHtmlContainerCell::Layout(int w
)
352 if (m_LastLayout
== w
)
354 wxHtmlCell::Layout(w
);
358 wxHtmlCell
*cell
= m_Cells
, *line
= m_Cells
;
359 long xpos
= 0, ypos
= m_IndentTop
;
360 int xdelta
= 0, ybasicpos
= 0, ydiff
;
361 int s_width
, s_indent
;
362 int ysizeup
= 0, ysizedown
= 0;
363 int MaxLineWidth
= 0;
373 if (m_WidthFloatUnits
== wxHTML_UNITS_PERCENT
)
375 if (m_WidthFloat
< 0) m_Width
= (100 + m_WidthFloat
) * w
/ 100;
376 else m_Width
= m_WidthFloat
* w
/ 100;
380 if (m_WidthFloat
< 0) m_Width
= w
+ m_WidthFloat
;
381 else m_Width
= m_WidthFloat
;
386 int l
= (m_IndentLeft
< 0) ? (-m_IndentLeft
* m_Width
/ 100) : m_IndentLeft
;
387 int r
= (m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
;
388 m_Cells
->Layout(m_Width
- (l
+ r
));
397 // adjust indentation:
398 s_indent
= (m_IndentLeft
< 0) ? (-m_IndentLeft
* m_Width
/ 100) : m_IndentLeft
;
399 s_width
= m_Width
- s_indent
- ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
406 case wxHTML_ALIGN_TOP
: ybasicpos
= 0; break;
407 case wxHTML_ALIGN_BOTTOM
: ybasicpos
= - cell
->GetHeight(); break;
408 case wxHTML_ALIGN_CENTER
: ybasicpos
= - cell
->GetHeight() / 2; break;
410 ydiff
= cell
->GetHeight() + ybasicpos
;
412 if (cell
->GetDescent() + ydiff
> ysizedown
) ysizedown
= cell
->GetDescent() + ydiff
;
413 if (ybasicpos
+ cell
->GetDescent() < -ysizeup
) ysizeup
= - (ybasicpos
+ cell
->GetDescent());
415 cell
->SetPos(xpos
, ybasicpos
+ cell
->GetDescent());
416 xpos
+= cell
->GetWidth();
417 cell
= cell
->GetNext();
420 // force new line if occured:
421 if ((cell
== NULL
) || (xpos
+ cell
->GetWidth() > s_width
))
423 if (xpos
> MaxLineWidth
) MaxLineWidth
= xpos
;
424 if (ysizeup
< 0) ysizeup
= 0;
425 if (ysizedown
< 0) ysizedown
= 0;
426 switch (m_AlignHor
) {
427 case wxHTML_ALIGN_LEFT
:
428 case wxHTML_ALIGN_JUSTIFY
:
431 case wxHTML_ALIGN_RIGHT
:
432 xdelta
= 0 + (s_width
- xpos
);
434 case wxHTML_ALIGN_CENTER
:
435 xdelta
= 0 + (s_width
- xpos
) / 2;
438 if (xdelta
< 0) xdelta
= 0;
443 if (m_AlignHor
!= wxHTML_ALIGN_JUSTIFY
|| cell
== NULL
)
446 line
->SetPos(line
->GetPosX() + xdelta
,
447 ypos
+ line
->GetPosY());
448 line
= line
->GetNext();
453 int step
= (s_width
- xpos
);
454 if (step
< 0) step
= 0;
456 if (xcnt
> 0) while (line
!= cell
)
458 line
->SetPos(line
->GetPosX() + s_indent
+
459 (counter
++ * step
/ xcnt
),
460 ypos
+ line
->GetPosY());
461 line
= line
->GetNext();
468 ysizeup
= ysizedown
= 0;
473 // setup height & width, depending on container layout:
474 m_Height
= ypos
+ (ysizedown
+ ysizeup
) + m_IndentBottom
;
476 if (m_Height
< m_MinHeight
)
478 if (m_MinHeightAlign
!= wxHTML_ALIGN_TOP
)
480 int diff
= m_MinHeight
- m_Height
;
481 if (m_MinHeightAlign
== wxHTML_ALIGN_CENTER
) diff
/= 2;
485 cell
->SetPos(cell
->GetPosX(), cell
->GetPosY() + diff
);
486 cell
= cell
->GetNext();
489 m_Height
= m_MinHeight
;
492 MaxLineWidth
+= s_indent
+ ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
493 if (m_Width
< MaxLineWidth
) m_Width
= MaxLineWidth
;
497 wxHtmlCell::Layout(w
);
501 #define mMin(a, b) (((a) < (b)) ? (a) : (b))
502 #define mMax(a, b) (((a) < (b)) ? (b) : (a))
504 void wxHtmlContainerCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
506 // container visible, draw it:
507 if ((y
+ m_PosY
< view_y2
) && (y
+ m_PosY
+ m_Height
> view_y1
))
512 wxBrush myb
= wxBrush(m_BkColour
, wxSOLID
);
514 int real_y1
= mMax(y
+ m_PosY
, view_y1
);
515 int real_y2
= mMin(y
+ m_PosY
+ m_Height
- 1, view_y2
);
518 dc
.SetPen(*wxTRANSPARENT_PEN
);
519 dc
.DrawRectangle(x
+ m_PosX
, real_y1
, m_Width
, real_y2
- real_y1
+ 1);
524 wxPen
mypen1(m_BorderColour1
, 1, wxSOLID
);
525 wxPen
mypen2(m_BorderColour2
, 1, wxSOLID
);
528 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1);
529 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
);
531 dc
.DrawLine(x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
532 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
535 if (m_Cells
) m_Cells
->Draw(dc
, x
+ m_PosX
, y
+ m_PosY
, view_y1
, view_y2
);
537 // container invisible, just proceed font+color changing:
540 if (m_Cells
) m_Cells
->DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
543 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
548 void wxHtmlContainerCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
550 if (m_Cells
) m_Cells
->DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
551 wxHtmlCell::DrawInvisible(dc
, x
, y
);
556 wxHtmlLinkInfo
*wxHtmlContainerCell::GetLink(int x
, int y
) const
558 wxHtmlCell
*c
= m_Cells
;
563 cx
= c
->GetPosX(), cy
= c
->GetPosY();
564 cw
= c
->GetWidth(), ch
= c
->GetHeight();
565 if ((x
>= cx
) && (x
< cx
+ cw
) && (y
>= cy
) && (y
< cy
+ ch
))
566 return c
->GetLink(x
- cx
, y
- cy
);
574 void wxHtmlContainerCell::InsertCell(wxHtmlCell
*f
)
576 if (!m_Cells
) m_Cells
= m_LastCell
= f
;
579 m_LastCell
->SetNext(f
);
581 if (m_LastCell
) while (m_LastCell
->GetNext()) m_LastCell
= m_LastCell
->GetNext();
589 void wxHtmlContainerCell::SetAlign(const wxHtmlTag
& tag
)
591 if (tag
.HasParam(wxT("ALIGN")))
593 wxString alg
= tag
.GetParam(wxT("ALIGN"));
595 if (alg
== wxT("CENTER"))
596 SetAlignHor(wxHTML_ALIGN_CENTER
);
597 else if (alg
== wxT("LEFT"))
598 SetAlignHor(wxHTML_ALIGN_LEFT
);
599 else if (alg
== wxT("JUSTIFY"))
600 SetAlignHor(wxHTML_ALIGN_JUSTIFY
);
601 else if (alg
== wxT("RIGHT"))
602 SetAlignHor(wxHTML_ALIGN_RIGHT
);
609 void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag
& tag
, double pixel_scale
)
611 if (tag
.HasParam(wxT("WIDTH")))
614 wxString wd
= tag
.GetParam(wxT("WIDTH"));
616 if (wd
[wd
.Length()-1] == wxT('%'))
618 wxSscanf(wd
.c_str(), wxT("%i%%"), &wdi
);
619 SetWidthFloat(wdi
, wxHTML_UNITS_PERCENT
);
623 wxSscanf(wd
.c_str(), wxT("%i"), &wdi
);
624 SetWidthFloat((int)(pixel_scale
* (double)wdi
), wxHTML_UNITS_PIXELS
);
632 const wxHtmlCell
* wxHtmlContainerCell::Find(int condition
, const void* param
) const
634 const wxHtmlCell
*r
= NULL
;
638 r
= m_Cells
->Find(condition
, param
);
642 return wxHtmlCell::Find(condition
, param
);
647 void wxHtmlContainerCell::OnMouseClick(wxWindow
*parent
, int x
, int y
, const wxMouseEvent
& event
)
651 wxHtmlCell
*c
= m_Cells
;
654 if ( (c
->GetPosX() <= x
) &&
655 (c
->GetPosY() <= y
) &&
656 (c
->GetPosX() + c
->GetWidth() > x
) &&
657 (c
->GetPosY() + c
->GetHeight() > y
))
659 c
->OnMouseClick(parent
, x
- c
->GetPosX(), y
- c
->GetPosY(), event
);
671 //--------------------------------------------------------------------------------
673 //--------------------------------------------------------------------------------
675 void wxHtmlColourCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
677 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
678 dc
.SetTextForeground(m_Colour
);
679 if (m_Flags
& wxHTML_CLR_BACKGROUND
)
681 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
682 dc
.SetTextBackground(m_Colour
);
684 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
687 void wxHtmlColourCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
689 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
690 dc
.SetTextForeground(m_Colour
);
691 if (m_Flags
& wxHTML_CLR_BACKGROUND
)
693 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
694 dc
.SetTextBackground(m_Colour
);
696 wxHtmlCell::DrawInvisible(dc
, x
, y
);
702 //--------------------------------------------------------------------------------
704 //--------------------------------------------------------------------------------
706 void wxHtmlFontCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
709 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
712 void wxHtmlFontCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
715 wxHtmlCell::DrawInvisible(dc
, x
, y
);
725 //--------------------------------------------------------------------------------
727 //--------------------------------------------------------------------------------
729 wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow
*wnd
, int w
)
733 m_Wnd
->GetSize(&sx
, &sy
);
734 m_Width
= sx
, m_Height
= sy
;
739 void wxHtmlWidgetCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
741 int absx
= 0, absy
= 0, stx
, sty
;
742 wxHtmlCell
*c
= this;
746 absx
+= c
->GetPosX();
747 absy
+= c
->GetPosY();
751 ((wxScrolledWindow
*)(m_Wnd
->GetParent()))->ViewStart(&stx
, &sty
);
752 m_Wnd
->SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
754 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
759 void wxHtmlWidgetCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
761 int absx
= 0, absy
= 0, stx
, sty
;
762 wxHtmlCell
*c
= this;
766 absx
+= c
->GetPosX();
767 absy
+= c
->GetPosY();
771 ((wxScrolledWindow
*)(m_Wnd
->GetParent()))->ViewStart(&stx
, &sty
);
772 m_Wnd
->SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
774 wxHtmlCell::DrawInvisible(dc
, x
, y
);
779 void wxHtmlWidgetCell::Layout(int w
)
781 if (m_WidthFloat
!= 0)
783 m_Width
= (w
* m_WidthFloat
) / 100;
784 m_Wnd
->SetSize(m_Width
, m_Height
);
787 wxHtmlCell::Layout(w
);