1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: generic/htmllbox.cpp
3 // Purpose: implementation of wxHtmlListBox
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // License: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
28 #include "wx/dcclient.h"
31 #include "wx/htmllbox.h"
33 #include "wx/html/htmlcell.h"
34 #include "wx/html/winpars.h"
36 // this hack forces the linker to always link in m_* files
37 #include "wx/html/forcelnk.h"
38 FORCE_WXHTML_MODULES()
40 // ----------------------------------------------------------------------------
42 // ----------------------------------------------------------------------------
44 // this class is used by wxHtmlListBox to cache the parsed representation of
45 // the items to avoid doing it anew each time an item must be drawn
46 class wxHtmlListBoxCache
51 for ( size_t n
= 0; n
< SIZE
; n
++ )
53 m_items
[n
] = (size_t)-1;
62 for ( size_t n
= 0; n
< SIZE
; n
++ )
68 // completely invalidate the cache
71 for ( size_t n
= 0; n
< SIZE
; n
++ )
73 m_items
[n
] = (size_t)-1;
79 // return the cached cell for this index or NULL if none
80 wxHtmlCell
*Get(size_t item
) const
82 for ( size_t n
= 0; n
< SIZE
; n
++ )
84 if ( m_items
[n
] == item
)
91 // returns true if we already have this item cached
92 bool Has(size_t item
) const { return Get(item
) != NULL
; }
94 // ensure that the item is cached
95 void Store(size_t item
, wxHtmlCell
*cell
)
97 delete m_cells
[m_next
];
98 m_cells
[m_next
] = cell
;
99 m_items
[m_next
] = item
;
101 // advance to the next item wrapping around if there are no more
102 if ( ++m_next
== SIZE
)
107 // the max number of the items we cache
110 // the index of the LRU (oldest) cell
113 // the parsed representation of the cached item or NULL
114 wxHtmlCell
*m_cells
[SIZE
];
116 // the index of the currently cached item (only valid if m_cells != NULL)
117 size_t m_items
[SIZE
];
120 // ----------------------------------------------------------------------------
122 // ----------------------------------------------------------------------------
124 BEGIN_EVENT_TABLE(wxHtmlListBox
, wxVListBox
)
125 EVT_SIZE(wxHtmlListBox::OnSize
)
128 // ============================================================================
130 // ============================================================================
132 // ----------------------------------------------------------------------------
133 // wxHtmlListBox creation
134 // ----------------------------------------------------------------------------
136 void wxHtmlListBox::Init()
139 m_cache
= new wxHtmlListBoxCache
;
142 bool wxHtmlListBox::Create(wxWindow
*parent
,
148 const wxString
& name
)
150 return wxVListBox::Create(parent
, id
, pos
, size
, countItems
, style
, name
);
153 wxHtmlListBox::~wxHtmlListBox()
158 delete m_htmlParser
->GetDC();
163 // ----------------------------------------------------------------------------
164 // wxHtmlListBox items markup
165 // ----------------------------------------------------------------------------
167 wxString
wxHtmlListBox::OnGetItemMarkup(size_t n
) const
169 // we don't even need to wrap the value returned by OnGetItem() inside
170 // "<html><body>" and "</body></html>" because wxHTML can parse it even
171 // without these tags
175 // ----------------------------------------------------------------------------
176 // wxHtmlListBox cache handling
177 // ----------------------------------------------------------------------------
179 void wxHtmlListBox::CacheItem(size_t n
) const
181 if ( !m_cache
->Has(n
) )
185 wxHtmlListBox
*self
= wxConstCast(this, wxHtmlListBox
);
187 self
->m_htmlParser
= new wxHtmlWinParser
;
188 m_htmlParser
->SetDC(new wxClientDC(self
));
191 wxHtmlContainerCell
*cell
= (wxHtmlContainerCell
*)m_htmlParser
->
192 Parse(OnGetItemMarkup(n
));
193 wxCHECK_RET( cell
, _T("wxHtmlParser::Parse() returned NULL?") );
195 cell
->Layout(GetClientSize().x
- 2*GetMargins().x
);
197 m_cache
->Store(n
, cell
);
201 void wxHtmlListBox::OnSize(wxSizeEvent
& event
)
203 // we need to relayout all the cached cells
209 void wxHtmlListBox::RefreshAll()
213 wxVListBox::RefreshAll();
216 // ----------------------------------------------------------------------------
217 // wxHtmlListBox implementation of wxVListBox pure virtuals
218 // ----------------------------------------------------------------------------
220 void wxHtmlListBox::OnDrawItem(wxDC
& dc
, const wxRect
& rect
, size_t n
) const
224 wxHtmlCell
*cell
= m_cache
->Get(n
);
225 wxCHECK_RET( cell
, _T("this cell should be cached!") );
227 wxHtmlRenderingState htmlRendState
;
229 // draw the selected cell in selected state
232 wxHtmlSelection htmlSel
;
233 htmlSel
.Set(wxPoint(0, 0), cell
, wxPoint(INT_MAX
, INT_MAX
), cell
);
234 htmlRendState
.SetSelection(&htmlSel
);
235 htmlRendState
.SetSelectionState(wxHTML_SEL_IN
);
238 // note that we can't stop drawing exactly at the window boundary as then
239 // even the visible cells part could be not drawn, so always draw the
241 cell
->Draw(dc
, rect
.x
, rect
.y
, 0, INT_MAX
, htmlRendState
);
244 wxCoord
wxHtmlListBox::OnMeasureItem(size_t n
) const
248 wxHtmlCell
*cell
= m_cache
->Get(n
);
249 wxCHECK_MSG( cell
, 0, _T("this cell should be cached!") );
251 return cell
->GetHeight() + cell
->GetDescent();