]>
git.saurik.com Git - wxWidgets.git/blob - src/html/htmlcell.cpp
a3d20ab2c0be9ac8535ea042393ea32462cba8ed
   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 //----------------------------------------------------------------------------- 
  37 void wxHtmlCell::OnMouseClick(wxWindow 
*parent
, int x
, int y
, 
  39                               bool WXUNUSED(middle
), 
  42     wxString lnk 
= GetLink(x
, y
); 
  43     if (lnk 
!= wxEmptyString
) 
  44         ((wxHtmlWindow
*)parent
) -> OnLinkClicked(lnk
); 
  45         // note : this overcasting is legal because parent is *always* wxHtmlWindow 
  50 bool wxHtmlCell::AdjustPagebreak(int *pagebreak
) 
  53     if ((!m_CanLiveOnPagebreak
) &&  
  54                 m_PosY 
< *pagebreak 
&& m_PosY 
+ m_Height 
> *pagebreak
) { 
  56         if (m_Next 
!= NULL
) m_Next 
-> AdjustPagebreak(pagebreak
); 
  61         if (m_Next 
!= NULL
) return m_Next 
-> AdjustPagebreak(pagebreak
); 
  69 //----------------------------------------------------------------------------- 
  71 //----------------------------------------------------------------------------- 
  73 wxHtmlWordCell::wxHtmlWordCell(const wxString
& word
, wxDC
& dc
) : wxHtmlCell() 
  77     if (m_Word
.Find(wxT('&')) != -1)  
  79         static wxChar
* substitutions
[][3] =  
  81                     { wxT(" "), wxT("  "), wxT(" ") }, 
  82                     { wxT("©"), wxT("© "), wxT("(c)") }, 
  83                     { wxT("""), wxT("" "), wxT("\"") }, 
  84                     { wxT("<"), wxT("< "), wxT("<") }, 
  85                     { wxT(">"), wxT("> "), wxT(">") }, 
  86                     { wxT("&"), wxT("& "), wxT("&")  /*this one should be last one*/ }, 
  90         for (int i 
= 0; substitutions
[i
][0] != NULL
; i
++)  
  92             m_Word
.Replace(substitutions
[i
][0], substitutions
[i
][2], TRUE
); 
  93             m_Word
.Replace(substitutions
[i
][1], substitutions
[i
][2], TRUE
); 
  97     dc
.GetTextExtent(m_Word
, &m_Width
, &m_Height
, &m_Descent
); 
  98     SetCanLiveOnPagebreak(FALSE
); 
 103 void wxHtmlWordCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
) 
 105     dc
.DrawText(m_Word
, x 
+ m_PosX
, y 
+ m_PosY
); 
 106     wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
); 
 111 //----------------------------------------------------------------------------- 
 112 // wxHtmlContainerCell 
 113 //----------------------------------------------------------------------------- 
 116 wxHtmlContainerCell::wxHtmlContainerCell(wxHtmlContainerCell 
*parent
) : wxHtmlCell() 
 118     m_Cells 
= m_LastCell 
= NULL
; 
 120     if (m_Parent
) m_Parent 
-> InsertCell(this); 
 121     m_AlignHor 
= wxHTML_ALIGN_LEFT
; 
 122     m_AlignVer 
= wxHTML_ALIGN_BOTTOM
; 
 123     m_IndentLeft 
= m_IndentRight 
= m_IndentTop 
= m_IndentBottom 
= 0; 
 124     m_WidthFloat 
= 100; m_WidthFloatUnits 
= wxHTML_UNITS_PERCENT
; 
 125     m_UseBkColour 
= FALSE
; 
 127     m_MinHeight 
= m_MaxLineWidth 
= 0; 
 128     m_MinHeightAlign 
= wxHTML_ALIGN_TOP
; 
 133 void wxHtmlContainerCell::SetIndent(int i
, int what
, int units
) 
 135     int val 
= (units 
== wxHTML_UNITS_PIXELS
) ? i 
: -i
; 
 136     if (what 
& wxHTML_INDENT_LEFT
) m_IndentLeft 
= val
; 
 137     if (what 
& wxHTML_INDENT_RIGHT
) m_IndentRight 
= val
; 
 138     if (what 
& wxHTML_INDENT_TOP
) m_IndentTop 
= val
; 
 139     if (what 
& wxHTML_INDENT_BOTTOM
) m_IndentBottom 
= val
; 
 144 int wxHtmlContainerCell::GetIndent(int ind
) const 
 146     if (ind 
& wxHTML_INDENT_LEFT
) return m_IndentLeft
; 
 147     else if (ind 
& wxHTML_INDENT_RIGHT
) return m_IndentRight
; 
 148     else if (ind 
& wxHTML_INDENT_TOP
) return m_IndentTop
; 
 149     else if (ind 
& wxHTML_INDENT_BOTTOM
) return m_IndentBottom
; 
 150     else return -1; /* BUG! Should not be called... */ 
 156 int wxHtmlContainerCell::GetIndentUnits(int ind
) const 
 159     if (ind 
& wxHTML_INDENT_LEFT
) p 
= m_IndentLeft 
< 0; 
 160     else if (ind 
& wxHTML_INDENT_RIGHT
) p 
= m_IndentRight 
< 0; 
 161     else if (ind 
& wxHTML_INDENT_TOP
) p 
= m_IndentTop 
< 0; 
 162     else if (ind 
& wxHTML_INDENT_BOTTOM
) p 
= m_IndentBottom 
< 0; 
 163     if (p
) return wxHTML_UNITS_PERCENT
; 
 164     else return wxHTML_UNITS_PIXELS
; 
 169 bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak
) 
 171     if (!m_CanLiveOnPagebreak
)  
 172         return wxHtmlCell::AdjustPagebreak(pagebreak
); 
 175         wxHtmlCell 
*c 
= GetFirstCell(); 
 177         int pbrk 
= *pagebreak 
- m_PosY
; 
 180             if (c 
-> AdjustPagebreak(&pbrk
)) rt 
= TRUE
; 
 183         if (rt
) *pagebreak 
= pbrk 
+ m_PosY
; 
 190 void wxHtmlContainerCell::Layout(int w
) 
 192     wxHtmlCell 
*cell 
= m_Cells
, *line 
= m_Cells
; 
 193     long xpos 
= 0, ypos 
= m_IndentTop
; 
 194     int xdelta 
= 0, ybasicpos 
= 0, ydiff
; 
 195     int s_width
, s_indent
; 
 196     int ysizeup 
= 0, ysizedown 
= 0; 
 204     if (m_WidthFloatUnits 
== wxHTML_UNITS_PERCENT
) { 
 205         if (m_WidthFloat 
< 0) m_Width 
= (100 + m_WidthFloat
) * w 
/ 100; 
 206         else m_Width 
= m_WidthFloat 
* w 
/ 100; 
 209         if (m_WidthFloat 
< 0) m_Width 
= w 
+ m_WidthFloat
; 
 210         else m_Width 
= m_WidthFloat
; 
 214         int l 
= (m_IndentLeft 
< 0) ? (-m_IndentLeft 
* m_Width 
/ 100) : m_IndentLeft
; 
 215         int r 
= (m_IndentRight 
< 0) ? (-m_IndentRight 
* m_Width 
/ 100) : m_IndentRight
; 
 216         m_Cells 
-> Layout(m_Width 
- (l 
+ r
)); 
 225     // adjust indentation: 
 226     s_indent 
= (m_IndentLeft 
< 0) ? (-m_IndentLeft 
* m_Width 
/ 100) : m_IndentLeft
; 
 227     s_width 
= m_Width 
- s_indent 
- ((m_IndentRight 
< 0) ? (-m_IndentRight 
* m_Width 
/ 100) : m_IndentRight
); 
 232     while (cell 
!= NULL
) { 
 233         switch (m_AlignVer
) { 
 234             case wxHTML_ALIGN_TOP 
:      ybasicpos 
= 0; break; 
 235             case wxHTML_ALIGN_BOTTOM 
:   ybasicpos 
= - cell 
-> GetHeight(); break; 
 236             case wxHTML_ALIGN_CENTER 
:   ybasicpos 
= - cell 
-> GetHeight() / 2; break; 
 238         ydiff 
= cell 
-> GetHeight() + ybasicpos
; 
 240         if (cell 
-> GetDescent() + ydiff 
> ysizedown
) ysizedown 
= cell 
-> GetDescent() + ydiff
; 
 241         if (ybasicpos 
+ cell 
-> GetDescent() < -ysizeup
) ysizeup 
= - (ybasicpos 
+ cell 
-> GetDescent()); 
 243         cell 
-> SetPos(xpos
, ybasicpos 
+ cell 
-> GetDescent()); 
 244         xpos 
+= cell 
-> GetWidth(); 
 245         cell 
= cell 
-> GetNext(); 
 247         // force new line if occured: 
 248         if ((cell 
== NULL
) || (xpos 
+ cell 
-> GetWidth() > s_width
)) { 
 249             if (xpos 
> m_MaxLineWidth
) m_MaxLineWidth 
= xpos
; 
 250             if (ysizeup 
< 0) ysizeup 
= 0; 
 251             if (ysizedown 
< 0) ysizedown 
= 0; 
 252             switch (m_AlignHor
) { 
 253                 case wxHTML_ALIGN_LEFT 
: xdelta 
= 0; break; 
 254                 case wxHTML_ALIGN_RIGHT 
: xdelta 
= 0 + (s_width 
- xpos
); break; 
 255                 case wxHTML_ALIGN_CENTER 
: xdelta 
= 0 + (s_width 
- xpos
) / 2; break; 
 257             if (xdelta 
< 0) xdelta 
= 0; 
 261             while (line 
!= cell
) { 
 262                 line 
-> SetPos(line 
-> GetPosX() + xdelta
, ypos 
+ line 
-> GetPosY()); 
 263                 line 
= line 
-> GetNext(); 
 268             ysizeup 
= ysizedown 
= 0; 
 273     // setup height & width, depending on container layout: 
 274     m_Height 
= ypos 
+ (ysizedown 
+ ysizeup
) + m_IndentBottom
; 
 276     if (m_Height 
< m_MinHeight
) { 
 277         if (m_MinHeightAlign 
!= wxHTML_ALIGN_TOP
) { 
 278             int diff 
= m_MinHeight 
- m_Height
; 
 279             if (m_MinHeightAlign 
== wxHTML_ALIGN_CENTER
) diff 
/= 2; 
 282                 cell 
-> SetPos(cell 
-> GetPosX(), cell 
-> GetPosY() + diff
); 
 283                 cell 
= cell 
-> GetNext(); 
 286         m_Height 
= m_MinHeight
; 
 289     m_MaxLineWidth 
+= s_indent 
+ ((m_IndentRight 
< 0) ? (-m_IndentRight 
* m_Width 
/ 100) : m_IndentRight
); 
 290     if (m_Width 
< m_MaxLineWidth
) m_Width 
= m_MaxLineWidth
; 
 292     wxHtmlCell::Layout(w
); 
 296 #define mMin(a, b) (((a) < (b)) ? (a) : (b)) 
 297 #define mMax(a, b) (((a) < (b)) ? (b) : (a)) 
 299 void wxHtmlContainerCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
) 
 301     // container visible, draw it: 
 302     if ((y 
+ m_PosY 
< view_y2
) && (y 
+ m_PosY 
+ m_Height 
> view_y1
)) { 
 305             wxBrush myb 
= wxBrush(m_BkColour
, wxSOLID
); 
 307             int real_y1 
= mMax(y 
+ m_PosY
, view_y1
); 
 308             int real_y2 
= mMin(y 
+ m_PosY 
+ m_Height 
- 1, view_y2
); 
 311             dc
.SetPen(*wxTRANSPARENT_PEN
); 
 312             dc
.DrawRectangle(x 
+ m_PosX
, real_y1
, m_Width
, real_y2 
- real_y1 
+ 1); 
 316             wxPen 
mypen1(m_BorderColour1
, 1, wxSOLID
); 
 317             wxPen 
mypen2(m_BorderColour2
, 1, wxSOLID
); 
 320             dc
.DrawLine(x 
+ m_PosX
, y 
+ m_PosY
, x 
+ m_PosX
, y 
+ m_PosY 
+ m_Height 
- 1); 
 321             dc
.DrawLine(x 
+ m_PosX
, y 
+ m_PosY
, x 
+ m_PosX 
+ m_Width 
- 1, y 
+ m_PosY
); 
 323             dc
.DrawLine(x 
+ m_PosX 
+ m_Width 
- 1, y 
+ m_PosY
, x 
+ m_PosX 
+  m_Width 
- 1, y 
+ m_PosY 
+ m_Height 
- 1); 
 324             dc
.DrawLine(x 
+ m_PosX
, y 
+ m_PosY 
+ m_Height 
- 1, x 
+ m_PosX 
+ m_Width 
- 1, y 
+ m_PosY 
+ m_Height 
- 1); 
 327         if (m_Cells
) m_Cells 
-> Draw(dc
, x 
+ m_PosX
, y 
+ m_PosY
, view_y1
, view_y2
); 
 329     // container invisible, just proceed font+color changing: 
 331         if (m_Cells
) m_Cells 
-> DrawInvisible(dc
, x 
+ m_PosX
, y 
+ m_PosY
); 
 334     wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
); 
 339 void wxHtmlContainerCell::DrawInvisible(wxDC
& dc
, int x
, int y
) 
 341     if (m_Cells
) m_Cells 
-> DrawInvisible(dc
, x 
+ m_PosX
, y 
+ m_PosY
); 
 342     wxHtmlCell::DrawInvisible(dc
, x
, y
); 
 347 wxString 
wxHtmlContainerCell::GetLink(int x
, int y
) const 
 349     wxHtmlCell 
*c 
= m_Cells
; 
 353         cx 
= c 
-> GetPosX(), cy 
= c 
-> GetPosY(); 
 354         cw 
= c 
-> GetWidth(), ch 
= c 
-> GetHeight(); 
 355         if ((x 
>= cx
) && (x 
< cx 
+ cw
) && (y 
>= cy
) && (y 
< cy 
+ ch
)) 
 356             return c 
-> GetLink(x 
- cx
, y 
- cy
); 
 359     return wxEmptyString
; 
 364 void wxHtmlContainerCell::InsertCell(wxHtmlCell 
*f
) 
 366     if (!m_Cells
) m_Cells 
= m_LastCell 
= f
; 
 368         m_LastCell 
-> SetNext(f
); 
 370         if (m_LastCell
) while (m_LastCell 
-> GetNext()) m_LastCell 
= m_LastCell 
-> GetNext(); 
 372     f 
-> SetParent(this); 
 377 void wxHtmlContainerCell::SetAlign(const wxHtmlTag
& tag
) 
 379     if (tag
.HasParam("ALIGN")) { 
 380         wxString alg 
= tag
.GetParam("ALIGN"); 
 383             SetAlignHor(wxHTML_ALIGN_CENTER
); 
 384         else if (alg 
== "LEFT") 
 385             SetAlignHor(wxHTML_ALIGN_LEFT
); 
 386         else if (alg 
== "RIGHT") 
 387             SetAlignHor(wxHTML_ALIGN_RIGHT
); 
 393 void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag
& tag
, double pixel_scale
) 
 395     if (tag
.HasParam("WIDTH")) { 
 397         wxString wd 
= tag
.GetParam("WIDTH"); 
 399         if (wd
[wd
.Length()-1] == '%') { 
 400             wxSscanf(wd
.c_str(), wxT("%i%%"), &wdi
); 
 401             SetWidthFloat(wdi
, wxHTML_UNITS_PERCENT
); 
 404             wxSscanf(wd
.c_str(), wxT("%i"), &wdi
); 
 405             SetWidthFloat((int)(pixel_scale 
* (double)wdi
), wxHTML_UNITS_PIXELS
); 
 412 const wxHtmlCell
* wxHtmlContainerCell::Find(int condition
, const void* param
) const 
 414     const wxHtmlCell 
*r 
= NULL
; 
 417         r 
= m_Cells 
-> Find(condition
, param
); 
 421     return wxHtmlCell::Find(condition
, param
); 
 426 void wxHtmlContainerCell::OnMouseClick(wxWindow 
*parent
, int x
, int y
, bool left
, bool middle
, bool right
) 
 429         wxHtmlCell 
*c 
= m_Cells
; 
 431             if (    (c 
-> GetPosX() <= x
) && 
 432                     (c 
-> GetPosY() <= y
) && 
 433                     (c 
-> GetPosX() + c 
-> GetWidth() > x
) && 
 434                     (c 
-> GetPosY() + c 
-> GetHeight() > y
)) { 
 435                 c 
-> OnMouseClick(parent
, x 
- c 
-> GetPosX(), y 
- c 
-> GetPosY(), left
, middle
, right
); 
 447 //-------------------------------------------------------------------------------- 
 449 //-------------------------------------------------------------------------------- 
 451 void wxHtmlColourCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
) 
 453     if (m_Flags 
& wxHTML_CLR_FOREGROUND
) 
 454         dc
.SetTextForeground(m_Colour
); 
 455     if (m_Flags 
& wxHTML_CLR_BACKGROUND
) { 
 456         dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
)); 
 457         dc
.SetTextBackground(m_Colour
); 
 459     wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
); 
 462 void wxHtmlColourCell::DrawInvisible(wxDC
& dc
, int x
, int y
) 
 464     if (m_Flags 
& wxHTML_CLR_FOREGROUND
) 
 465         dc
.SetTextForeground(m_Colour
); 
 466     if (m_Flags 
& wxHTML_CLR_BACKGROUND
) { 
 467         dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
)); 
 468         dc
.SetTextBackground(m_Colour
); 
 470     wxHtmlCell::DrawInvisible(dc
, x
, y
); 
 476 //-------------------------------------------------------------------------------- 
 478 //-------------------------------------------------------------------------------- 
 480 void wxHtmlFontCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
) 
 483     wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
); 
 486 void wxHtmlFontCell::DrawInvisible(wxDC
& dc
, int x
, int y
) 
 489     wxHtmlCell::DrawInvisible(dc
, x
, y
); 
 499 //-------------------------------------------------------------------------------- 
 501 //-------------------------------------------------------------------------------- 
 503 wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow 
*wnd
, int w
) 
 507     m_Wnd 
-> GetSize(&sx
, &sy
); 
 508     m_Width 
= sx
, m_Height 
= sy
; 
 513 void wxHtmlWidgetCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
) 
 515     int absx 
= 0, absy 
= 0, stx
, sty
; 
 516     wxHtmlCell 
*c 
= this; 
 519         absx 
+= c 
-> GetPosX(); 
 520         absy 
+= c 
-> GetPosY(); 
 521         c 
= c 
-> GetParent(); 
 524     ((wxScrolledWindow
*)(m_Wnd 
-> GetParent())) -> ViewStart(&stx
, &sty
); 
 525     m_Wnd 
-> SetSize(absx 
- wxHTML_SCROLL_STEP 
* stx
, absy  
- wxHTML_SCROLL_STEP 
* sty
, m_Width
, m_Height
); 
 527     wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
); 
 532 void wxHtmlWidgetCell::DrawInvisible(wxDC
& dc
, int x
, int y
) 
 534     int absx 
= 0, absy 
= 0, stx
, sty
; 
 535     wxHtmlCell 
*c 
= this; 
 538         absx 
+= c 
-> GetPosX(); 
 539         absy 
+= c 
-> GetPosY(); 
 540         c 
= c 
-> GetParent(); 
 543     ((wxScrolledWindow
*)(m_Wnd 
-> GetParent())) -> ViewStart(&stx
, &sty
); 
 544     m_Wnd 
-> SetSize(absx 
- wxHTML_SCROLL_STEP 
* stx
, absy  
- wxHTML_SCROLL_STEP 
* sty
, m_Width
, m_Height
); 
 546     wxHtmlCell::DrawInvisible(dc
, x
, y
); 
 551 void wxHtmlWidgetCell::Layout(int w
) 
 553     if (m_WidthFloat 
!= 0) { 
 554         m_Width 
= (w 
* m_WidthFloat
) / 100; 
 555         m_Wnd 
-> SetSize(m_Width
, m_Height
); 
 558     wxHtmlCell::Layout(w
);