]>
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 
  26     #include "wx/colour.h" 
  30 #include "wx/html/htmlcell.h" 
  31 #include "wx/html/htmlwin.h" 
  35 //----------------------------------------------------------------------------- 
  37 //----------------------------------------------------------------------------- 
  39 wxHtmlCell::wxHtmlCell() : wxObject() 
  43     m_Width 
= m_Height 
= m_Descent 
= 0; 
  44     m_CanLiveOnPagebreak 
= TRUE
; 
  48 wxHtmlCell::~wxHtmlCell() 
  54 void wxHtmlCell::OnMouseClick(wxWindow 
*parent
, int x
, int y
, 
  55                               const wxMouseEvent
& event
) 
  57     wxHtmlLinkInfo 
*lnk 
= GetLink(x
, y
); 
  60         wxHtmlLinkInfo 
lnk2(*lnk
); 
  61         lnk2
.SetEvent(&event
); 
  62         lnk2
.SetHtmlCell(this); 
  64         // note : this cast is legal because parent is *always* wxHtmlWindow 
  65         wxStaticCast(parent
, wxHtmlWindow
)->OnLinkClicked(lnk2
); 
  71 bool wxHtmlCell::AdjustPagebreak(int *pagebreak
) const 
  73     if ((!m_CanLiveOnPagebreak
) && 
  74                 m_PosY 
< *pagebreak 
&& m_PosY 
+ m_Height 
> *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 WXUNUSED(w
)) 
 102 void wxHtmlCell::GetHorizontalConstraints(int *left
, int *right
) const 
 107         *right 
= m_PosX 
+ m_Width
; 
 112 const wxHtmlCell
* wxHtmlCell::Find(int WXUNUSED(condition
), const void* WXUNUSED(param
)) const 
 118 wxHtmlCell 
*wxHtmlCell::FindCellByPos(wxCoord x
, wxCoord y
) const 
 120     if ( x 
>= 0 && x 
< m_Width 
&& y 
>= 0 && y 
< m_Height 
) 
 121         return wxConstCast(this, wxHtmlCell
); 
 127 //----------------------------------------------------------------------------- 
 129 //----------------------------------------------------------------------------- 
 131 wxHtmlWordCell::wxHtmlWordCell(const wxString
& word
, wxDC
& dc
) : wxHtmlCell() 
 134     dc
.GetTextExtent(m_Word
, &m_Width
, &m_Height
, &m_Descent
); 
 135     SetCanLiveOnPagebreak(FALSE
); 
 140 void wxHtmlWordCell::Draw(wxDC
& dc
, int x
, int y
, int WXUNUSED(view_y1
), int WXUNUSED(view_y2
)) 
 142     dc
.DrawText(m_Word
, x 
+ m_PosX
, y 
+ m_PosY
); 
 147 //----------------------------------------------------------------------------- 
 148 // wxHtmlContainerCell 
 149 //----------------------------------------------------------------------------- 
 152 wxHtmlContainerCell::wxHtmlContainerCell(wxHtmlContainerCell 
*parent
) : wxHtmlCell() 
 154     m_Cells 
= m_LastCell 
= NULL
; 
 156     if (m_Parent
) m_Parent
->InsertCell(this); 
 157     m_AlignHor 
= wxHTML_ALIGN_LEFT
; 
 158     m_AlignVer 
= wxHTML_ALIGN_BOTTOM
; 
 159     m_IndentLeft 
= m_IndentRight 
= m_IndentTop 
= m_IndentBottom 
= 0; 
 160     m_WidthFloat 
= 100; m_WidthFloatUnits 
= wxHTML_UNITS_PERCENT
; 
 161     m_UseBkColour 
= FALSE
; 
 164     m_MinHeightAlign 
= wxHTML_ALIGN_TOP
; 
 168 wxHtmlContainerCell::~wxHtmlContainerCell() 
 170     wxHtmlCell 
*cell 
= m_Cells
; 
 173         wxHtmlCell 
*cellNext 
= cell
->GetNext(); 
 181 void wxHtmlContainerCell::SetIndent(int i
, int what
, int units
) 
 183     int val 
= (units 
== wxHTML_UNITS_PIXELS
) ? i 
: -i
; 
 184     if (what 
& wxHTML_INDENT_LEFT
) m_IndentLeft 
= val
; 
 185     if (what 
& wxHTML_INDENT_RIGHT
) m_IndentRight 
= val
; 
 186     if (what 
& wxHTML_INDENT_TOP
) m_IndentTop 
= val
; 
 187     if (what 
& wxHTML_INDENT_BOTTOM
) m_IndentBottom 
= val
; 
 193 int wxHtmlContainerCell::GetIndent(int ind
) const 
 195     if (ind 
& wxHTML_INDENT_LEFT
) return m_IndentLeft
; 
 196     else if (ind 
& wxHTML_INDENT_RIGHT
) return m_IndentRight
; 
 197     else if (ind 
& wxHTML_INDENT_TOP
) return m_IndentTop
; 
 198     else if (ind 
& wxHTML_INDENT_BOTTOM
) return m_IndentBottom
; 
 199     else return -1; /* BUG! Should not be called... */ 
 205 int wxHtmlContainerCell::GetIndentUnits(int ind
) const 
 208     if (ind 
& wxHTML_INDENT_LEFT
) p 
= m_IndentLeft 
< 0; 
 209     else if (ind 
& wxHTML_INDENT_RIGHT
) p 
= m_IndentRight 
< 0; 
 210     else if (ind 
& wxHTML_INDENT_TOP
) p 
= m_IndentTop 
< 0; 
 211     else if (ind 
& wxHTML_INDENT_BOTTOM
) p 
= m_IndentBottom 
< 0; 
 212     if (p
) return wxHTML_UNITS_PERCENT
; 
 213     else return wxHTML_UNITS_PIXELS
; 
 218 bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak
) const 
 220     if (!m_CanLiveOnPagebreak
) 
 221         return wxHtmlCell::AdjustPagebreak(pagebreak
); 
 225         wxHtmlCell 
*c 
= GetFirstCell(); 
 227         int pbrk 
= *pagebreak 
- m_PosY
; 
 231             if (c
->AdjustPagebreak(&pbrk
)) 
 236             *pagebreak 
= pbrk 
+ m_PosY
; 
 243 void wxHtmlContainerCell::Layout(int w
) 
 245     wxHtmlCell::Layout(w
); 
 247     if (m_LastLayout 
== w
) return; 
 249     // VS: Any attempt to layout with negative or zero width leads to hell, 
 250     // but we can't ignore such attempts completely, since it sometimes 
 251     // happen (e.g. when trying how small a table can be). The best thing we 
 252     // can do is to set the width of child cells to zero 
 256        for (wxHtmlCell 
*cell 
= m_Cells
; cell
; cell 
= cell
->GetNext()) 
 258             // this does two things: it recursively calls this code on all child 
 259             // contrainers and resets children's position to (0,0) 
 263     wxHtmlCell 
*cell 
= m_Cells
, *line 
= m_Cells
; 
 264     long xpos 
= 0, ypos 
= m_IndentTop
; 
 265     int xdelta 
= 0, ybasicpos 
= 0, ydiff
; 
 266     int s_width
, s_indent
; 
 267     int ysizeup 
= 0, ysizedown 
= 0; 
 268     int MaxLineWidth 
= 0; 
 278     if (m_WidthFloatUnits 
== wxHTML_UNITS_PERCENT
) 
 280         if (m_WidthFloat 
< 0) m_Width 
= (100 + m_WidthFloat
) * w 
/ 100; 
 281         else m_Width 
= m_WidthFloat 
* w 
/ 100; 
 285         if (m_WidthFloat 
< 0) m_Width 
= w 
+ m_WidthFloat
; 
 286         else m_Width 
= m_WidthFloat
; 
 291         int l 
= (m_IndentLeft 
< 0) ? (-m_IndentLeft 
* m_Width 
/ 100) : m_IndentLeft
; 
 292         int r 
= (m_IndentRight 
< 0) ? (-m_IndentRight 
* m_Width 
/ 100) : m_IndentRight
; 
 293         for (wxHtmlCell 
*cell 
= m_Cells
; cell
; cell 
= cell
->GetNext()) 
 294             cell
->Layout(m_Width 
- (l 
+ r
)); 
 303     // adjust indentation: 
 304     s_indent 
= (m_IndentLeft 
< 0) ? (-m_IndentLeft 
* m_Width 
/ 100) : m_IndentLeft
; 
 305     s_width 
= m_Width 
- s_indent 
- ((m_IndentRight 
< 0) ? (-m_IndentRight 
* m_Width 
/ 100) : m_IndentRight
); 
 312             case wxHTML_ALIGN_TOP 
:      ybasicpos 
= 0; break; 
 313             case wxHTML_ALIGN_BOTTOM 
:   ybasicpos 
= - cell
->GetHeight(); break; 
 314             case wxHTML_ALIGN_CENTER 
:   ybasicpos 
= - cell
->GetHeight() / 2; break; 
 316         ydiff 
= cell
->GetHeight() + ybasicpos
; 
 318         if (cell
->GetDescent() + ydiff 
> ysizedown
) ysizedown 
= cell
->GetDescent() + ydiff
; 
 319         if (ybasicpos 
+ cell
->GetDescent() < -ysizeup
) ysizeup 
= - (ybasicpos 
+ cell
->GetDescent()); 
 321         cell
->SetPos(xpos
, ybasicpos 
+ cell
->GetDescent()); 
 322         xpos 
+= cell
->GetWidth(); 
 323         cell 
= cell
->GetNext(); 
 326         // force new line if occured: 
 327         if ((cell 
== NULL
) || (xpos 
+ cell
->GetWidth() > s_width
)) 
 329             if (xpos 
> MaxLineWidth
) MaxLineWidth 
= xpos
; 
 330             if (ysizeup 
< 0) ysizeup 
= 0; 
 331             if (ysizedown 
< 0) ysizedown 
= 0; 
 332             switch (m_AlignHor
) { 
 333                 case wxHTML_ALIGN_LEFT 
: 
 334                 case wxHTML_ALIGN_JUSTIFY 
: 
 337                 case wxHTML_ALIGN_RIGHT 
: 
 338                          xdelta 
= 0 + (s_width 
- xpos
); 
 340                 case wxHTML_ALIGN_CENTER 
: 
 341                          xdelta 
= 0 + (s_width 
- xpos
) / 2; 
 344             if (xdelta 
< 0) xdelta 
= 0; 
 349             if (m_AlignHor 
!= wxHTML_ALIGN_JUSTIFY 
|| cell 
== NULL
) 
 352                     line
->SetPos(line
->GetPosX() + xdelta
, 
 353                                    ypos 
+ line
->GetPosY()); 
 354                     line 
= line
->GetNext(); 
 359                 int step 
= (s_width 
- xpos
); 
 360                 if (step 
< 0) step 
= 0; 
 362                 if (xcnt 
> 0) while (line 
!= cell
) 
 364                     line
->SetPos(line
->GetPosX() + s_indent 
+ 
 365                                    (counter
++ * step 
/ xcnt
), 
 366                                    ypos 
+ line
->GetPosY()); 
 367                     line 
= line
->GetNext(); 
 374             ysizeup 
= ysizedown 
= 0; 
 379     // setup height & width, depending on container layout: 
 380     m_Height 
= ypos 
+ (ysizedown 
+ ysizeup
) + m_IndentBottom
; 
 382     if (m_Height 
< m_MinHeight
) 
 384         if (m_MinHeightAlign 
!= wxHTML_ALIGN_TOP
) 
 386             int diff 
= m_MinHeight 
- m_Height
; 
 387             if (m_MinHeightAlign 
== wxHTML_ALIGN_CENTER
) diff 
/= 2; 
 391                 cell
->SetPos(cell
->GetPosX(), cell
->GetPosY() + diff
); 
 392                 cell 
= cell
->GetNext(); 
 395         m_Height 
= m_MinHeight
; 
 398     MaxLineWidth 
+= s_indent 
+ ((m_IndentRight 
< 0) ? (-m_IndentRight 
* m_Width 
/ 100) : m_IndentRight
); 
 399     if (m_Width 
< MaxLineWidth
) m_Width 
= MaxLineWidth
; 
 405 #define mMin(a, b) (((a) < (b)) ? (a) : (b)) 
 406 #define mMax(a, b) (((a) < (b)) ? (b) : (a)) 
 408 void wxHtmlContainerCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
) 
 410     // container visible, draw it: 
 411     if ((y 
+ m_PosY 
< view_y2
) && (y 
+ m_PosY 
+ m_Height 
> view_y1
)) 
 416             wxBrush myb 
= wxBrush(m_BkColour
, wxSOLID
); 
 418             int real_y1 
= mMax(y 
+ m_PosY
, view_y1
); 
 419             int real_y2 
= mMin(y 
+ m_PosY 
+ m_Height 
- 1, view_y2
); 
 422             dc
.SetPen(*wxTRANSPARENT_PEN
); 
 423             dc
.DrawRectangle(x 
+ m_PosX
, real_y1
, m_Width
, real_y2 
- real_y1 
+ 1); 
 428             wxPen 
mypen1(m_BorderColour1
, 1, wxSOLID
); 
 429             wxPen 
mypen2(m_BorderColour2
, 1, wxSOLID
); 
 432             dc
.DrawLine(x 
+ m_PosX
, y 
+ m_PosY
, x 
+ m_PosX
, y 
+ m_PosY 
+ m_Height 
- 1); 
 433             dc
.DrawLine(x 
+ m_PosX
, y 
+ m_PosY
, x 
+ m_PosX 
+ m_Width 
- 1, y 
+ m_PosY
); 
 435             dc
.DrawLine(x 
+ m_PosX 
+ m_Width 
- 1, y 
+ m_PosY
, x 
+ m_PosX 
+  m_Width 
- 1, y 
+ m_PosY 
+ m_Height 
- 1); 
 436             dc
.DrawLine(x 
+ m_PosX
, y 
+ m_PosY 
+ m_Height 
- 1, x 
+ m_PosX 
+ m_Width 
- 1, y 
+ m_PosY 
+ m_Height 
- 1); 
 441             for (wxHtmlCell 
*cell 
= m_Cells
; cell
; cell 
= cell
->GetNext()) 
 442                 cell
->Draw(dc
, x 
+ m_PosX
, y 
+ m_PosY
, view_y1
, view_y2
); 
 445     // container invisible, just proceed font+color changing: 
 450             for (wxHtmlCell 
*cell 
= m_Cells
; cell
; cell 
= cell
->GetNext()) 
 451                 cell
->DrawInvisible(dc
, x 
+ m_PosX
, y 
+ m_PosY
); 
 458 void wxHtmlContainerCell::DrawInvisible(wxDC
& dc
, int x
, int y
) 
 462         for (wxHtmlCell 
*cell 
= m_Cells
; cell
; cell 
= cell
->GetNext()) 
 463             cell
->DrawInvisible(dc
, x 
+ m_PosX
, y 
+ m_PosY
); 
 469 wxHtmlLinkInfo 
*wxHtmlContainerCell::GetLink(int x
, int y
) const 
 471     wxHtmlCell 
*cell 
= FindCellByPos(x
, y
); 
 473     // VZ: I don't know if we should pass absolute or relative coords to 
 474     //     wxHtmlCell::GetLink()? As the base class version just ignores them 
 475     //     anyhow, it hardly matters right now but should still be clarified 
 476     return cell 
? cell
->GetLink(x
, y
) : NULL
; 
 481 void wxHtmlContainerCell::InsertCell(wxHtmlCell 
*f
) 
 483     if (!m_Cells
) m_Cells 
= m_LastCell 
= f
; 
 486         m_LastCell
->SetNext(f
); 
 488         if (m_LastCell
) while (m_LastCell
->GetNext()) m_LastCell 
= m_LastCell
->GetNext(); 
 496 void wxHtmlContainerCell::SetAlign(const wxHtmlTag
& tag
) 
 498     if (tag
.HasParam(wxT("ALIGN"))) 
 500         wxString alg 
= tag
.GetParam(wxT("ALIGN")); 
 502         if (alg 
== wxT("CENTER")) 
 503             SetAlignHor(wxHTML_ALIGN_CENTER
); 
 504         else if (alg 
== wxT("LEFT")) 
 505             SetAlignHor(wxHTML_ALIGN_LEFT
); 
 506         else if (alg 
== wxT("JUSTIFY")) 
 507             SetAlignHor(wxHTML_ALIGN_JUSTIFY
); 
 508         else if (alg 
== wxT("RIGHT")) 
 509             SetAlignHor(wxHTML_ALIGN_RIGHT
); 
 516 void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag
& tag
, double pixel_scale
) 
 518     if (tag
.HasParam(wxT("WIDTH"))) 
 521         wxString wd 
= tag
.GetParam(wxT("WIDTH")); 
 523         if (wd
[wd
.Length()-1] == wxT('%')) 
 525             wxSscanf(wd
.c_str(), wxT("%i%%"), &wdi
); 
 526             SetWidthFloat(wdi
, wxHTML_UNITS_PERCENT
); 
 530             wxSscanf(wd
.c_str(), wxT("%i"), &wdi
); 
 531             SetWidthFloat((int)(pixel_scale 
* (double)wdi
), wxHTML_UNITS_PIXELS
); 
 539 const wxHtmlCell
* wxHtmlContainerCell::Find(int condition
, const void* param
) const 
 543         const wxHtmlCell 
*r 
= NULL
; 
 545         for (wxHtmlCell 
*cell 
= m_Cells
; cell
; cell 
= cell
->GetNext()) 
 547             r 
= cell
->Find(condition
, param
); 
 555 wxHtmlCell 
*wxHtmlContainerCell::FindCellByPos(wxCoord x
, wxCoord y
) const 
 557     for ( const wxHtmlCell 
*cell 
= m_Cells
; cell
; cell 
= cell
->GetNext() ) 
 559         int cx 
= cell
->GetPosX(), 
 560             cy 
= cell
->GetPosY(); 
 562         if ( (cx 
<= x
) && (cx 
+ cell
->GetWidth() > x
) && 
 563              (cy 
<= y
) && (cy 
+ cell
->GetHeight() > y
) ) 
 565             return cell
->FindCellByPos(x 
- cx
, y 
- cy
); 
 573 void wxHtmlContainerCell::OnMouseClick(wxWindow 
*parent
, int x
, int y
, const wxMouseEvent
& event
) 
 575     wxHtmlCell 
*cell 
= FindCellByPos(x
, y
); 
 577         cell
->OnMouseClick(parent
, x
, y
, event
); 
 582 void wxHtmlContainerCell::GetHorizontalConstraints(int *left
, int *right
) const 
 584     int cleft 
= m_PosX 
+ m_Width
, cright 
= m_PosX
; // worst case 
 587     for (wxHtmlCell 
*cell 
= m_Cells
; cell
; cell 
= cell
->GetNext()) 
 589         cell
->GetHorizontalConstraints(&l
, &r
); 
 596     cleft 
-= (m_IndentLeft 
< 0) ? (-m_IndentLeft 
* m_Width 
/ 100) : m_IndentLeft
; 
 597     cright 
+= (m_IndentRight 
< 0) ? (-m_IndentRight 
* m_Width 
/ 100) : m_IndentRight
; 
 609 //-------------------------------------------------------------------------------- 
 611 //-------------------------------------------------------------------------------- 
 613 void wxHtmlColourCell::Draw(wxDC
& dc
, int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(view_y1
), int WXUNUSED(view_y2
)) 
 615     if (m_Flags 
& wxHTML_CLR_FOREGROUND
) 
 616         dc
.SetTextForeground(m_Colour
); 
 617     if (m_Flags 
& wxHTML_CLR_BACKGROUND
) 
 619         dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
)); 
 620         dc
.SetTextBackground(m_Colour
); 
 624 void wxHtmlColourCell::DrawInvisible(wxDC
& dc
, int WXUNUSED(x
), int WXUNUSED(y
)) 
 626     if (m_Flags 
& wxHTML_CLR_FOREGROUND
) 
 627         dc
.SetTextForeground(m_Colour
); 
 628     if (m_Flags 
& wxHTML_CLR_BACKGROUND
) 
 630         dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
)); 
 631         dc
.SetTextBackground(m_Colour
); 
 638 //-------------------------------------------------------------------------------- 
 640 //-------------------------------------------------------------------------------- 
 642 void wxHtmlFontCell::Draw(wxDC
& dc
, int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(view_y1
), int WXUNUSED(view_y2
)) 
 647 void wxHtmlFontCell::DrawInvisible(wxDC
& dc
, int WXUNUSED(x
), int WXUNUSED(y
)) 
 659 //-------------------------------------------------------------------------------- 
 661 //-------------------------------------------------------------------------------- 
 663 wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow 
*wnd
, int w
) 
 667     m_Wnd
->GetSize(&sx
, &sy
); 
 668     m_Width 
= sx
, m_Height 
= sy
; 
 673 void wxHtmlWidgetCell::Draw(wxDC
& WXUNUSED(dc
), int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(view_y1
), int WXUNUSED(view_y2
)) 
 675     int absx 
= 0, absy 
= 0, stx
, sty
; 
 676     wxHtmlCell 
*c 
= this; 
 680         absx 
+= c
->GetPosX(); 
 681         absy 
+= c
->GetPosY(); 
 685     ((wxScrolledWindow
*)(m_Wnd
->GetParent()))->GetViewStart(&stx
, &sty
); 
 686     m_Wnd
->SetSize(absx 
- wxHTML_SCROLL_STEP 
* stx
, absy  
- wxHTML_SCROLL_STEP 
* sty
, m_Width
, m_Height
); 
 691 void wxHtmlWidgetCell::DrawInvisible(wxDC
& WXUNUSED(dc
), int WXUNUSED(x
), int WXUNUSED(y
)) 
 693     int absx 
= 0, absy 
= 0, stx
, sty
; 
 694     wxHtmlCell 
*c 
= this; 
 698         absx 
+= c
->GetPosX(); 
 699         absy 
+= c
->GetPosY(); 
 703     ((wxScrolledWindow
*)(m_Wnd
->GetParent()))->GetViewStart(&stx
, &sty
); 
 704     m_Wnd
->SetSize(absx 
- wxHTML_SCROLL_STEP 
* stx
, absy  
- wxHTML_SCROLL_STEP 
* sty
, m_Width
, m_Height
); 
 709 void wxHtmlWidgetCell::Layout(int w
) 
 711     if (m_WidthFloat 
!= 0) 
 713         m_Width 
= (w 
* m_WidthFloat
) / 100; 
 714         m_Wnd
->SetSize(m_Width
, m_Height
); 
 717     wxHtmlCell::Layout(w
);