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"
33 #include "wx/htmllbox.h"
35 #include "wx/html/htmlcell.h"
36 #include "wx/html/winpars.h"
38 // this hack forces the linker to always link in m_* files
39 #include "wx/html/forcelnk.h"
40 FORCE_WXHTML_MODULES()
42 // ============================================================================
44 // ============================================================================
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 // this class is used by wxHtmlListBox to cache the parsed representation of
51 // the items to avoid doing it anew each time an item must be drawn
52 class wxHtmlListBoxCache
55 // invalidate a single item, used by Clear() and InvalidateRange()
56 void InvalidateItem(size_t n
)
58 m_items
[n
] = (size_t)-1;
66 for ( size_t n
= 0; n
< SIZE
; n
++ )
68 m_items
[n
] = (size_t)-1;
77 for ( size_t n
= 0; n
< SIZE
; n
++ )
83 // completely invalidate the cache
86 for ( size_t n
= 0; n
< SIZE
; n
++ )
92 // return the cached cell for this index or NULL if none
93 wxHtmlCell
*Get(size_t item
) const
95 for ( size_t n
= 0; n
< SIZE
; n
++ )
97 if ( m_items
[n
] == item
)
104 // returns true if we already have this item cached
105 bool Has(size_t item
) const { return Get(item
) != NULL
; }
107 // ensure that the item is cached
108 void Store(size_t item
, wxHtmlCell
*cell
)
110 delete m_cells
[m_next
];
111 m_cells
[m_next
] = cell
;
112 m_items
[m_next
] = item
;
114 // advance to the next item wrapping around if there are no more
115 if ( ++m_next
== SIZE
)
119 // forget the cached value of the item(s) between the given ones (inclusive)
120 void InvalidateRange(size_t from
, size_t to
)
122 for ( size_t n
= 0; n
< SIZE
; n
++ )
124 if ( m_items
[n
] >= from
&& m_items
[n
] <= to
)
132 // the max number of the items we cache
135 // the index of the LRU (oldest) cell
138 // the parsed representation of the cached item or NULL
139 wxHtmlCell
*m_cells
[SIZE
];
141 // the index of the currently cached item (only valid if m_cells != NULL)
142 size_t m_items
[SIZE
];
145 // ----------------------------------------------------------------------------
146 // wxHtmlListBoxStyle
147 // ----------------------------------------------------------------------------
149 // just forward wxDefaultHtmlRenderingStyle callbacks to the main class so that
150 // they could be overridden by the user code
151 class wxHtmlListBoxStyle
: public wxDefaultHtmlRenderingStyle
154 wxHtmlListBoxStyle(wxHtmlListBox
& hlbox
) : m_hlbox(hlbox
) { }
156 virtual wxColour
GetSelectedTextColour(const wxColour
& colFg
)
158 return m_hlbox
.GetSelectedTextColour(colFg
);
161 virtual wxColour
GetSelectedTextBgColour(const wxColour
& colBg
)
163 return m_hlbox
.GetSelectedTextBgColour(colBg
);
167 const wxHtmlListBox
& m_hlbox
;
169 DECLARE_NO_COPY_CLASS(wxHtmlListBoxStyle
)
173 // ----------------------------------------------------------------------------
175 // ----------------------------------------------------------------------------
177 BEGIN_EVENT_TABLE(wxHtmlListBox
, wxVListBox
)
178 EVT_SIZE(wxHtmlListBox::OnSize
)
181 // ============================================================================
183 // ============================================================================
185 IMPLEMENT_ABSTRACT_CLASS(wxHtmlListBox
, wxVListBox
)
188 // ----------------------------------------------------------------------------
189 // wxHtmlListBox creation
190 // ----------------------------------------------------------------------------
192 void wxHtmlListBox::Init()
195 m_htmlRendStyle
= new wxHtmlListBoxStyle(*this);
196 m_cache
= new wxHtmlListBoxCache
;
199 bool wxHtmlListBox::Create(wxWindow
*parent
,
204 const wxString
& name
)
206 return wxVListBox::Create(parent
, id
, pos
, size
, style
, name
);
209 wxHtmlListBox::~wxHtmlListBox()
215 delete m_htmlParser
->GetDC();
219 delete m_htmlRendStyle
;
222 // ----------------------------------------------------------------------------
223 // wxHtmlListBox appearance
224 // ----------------------------------------------------------------------------
226 wxColour
wxHtmlListBox::GetSelectedTextColour(const wxColour
& colFg
) const
228 return m_htmlRendStyle
->
229 wxDefaultHtmlRenderingStyle::GetSelectedTextColour(colFg
);
233 wxHtmlListBox::GetSelectedTextBgColour(const wxColour
& WXUNUSED(colBg
)) const
235 return GetSelectionBackground();
238 // ----------------------------------------------------------------------------
239 // wxHtmlListBox items markup
240 // ----------------------------------------------------------------------------
242 wxString
wxHtmlListBox::OnGetItemMarkup(size_t n
) const
244 // we don't even need to wrap the value returned by OnGetItem() inside
245 // "<html><body>" and "</body></html>" because wxHTML can parse it even
246 // without these tags
250 // ----------------------------------------------------------------------------
251 // wxHtmlListBox cache handling
252 // ----------------------------------------------------------------------------
254 void wxHtmlListBox::CacheItem(size_t n
) const
256 if ( !m_cache
->Has(n
) )
260 wxHtmlListBox
*self
= wxConstCast(this, wxHtmlListBox
);
262 self
->m_htmlParser
= new wxHtmlWinParser
;
263 m_htmlParser
->SetDC(new wxClientDC(self
));
264 m_htmlParser
->SetFS(&self
->m_filesystem
);
266 // use system's default GUI font by default:
267 m_htmlParser
->SetStandardFonts();
270 wxHtmlContainerCell
*cell
= (wxHtmlContainerCell
*)m_htmlParser
->
271 Parse(OnGetItemMarkup(n
));
272 wxCHECK_RET( cell
, _T("wxHtmlParser::Parse() returned NULL?") );
274 cell
->Layout(GetClientSize().x
- 2*GetMargins().x
);
276 m_cache
->Store(n
, cell
);
280 void wxHtmlListBox::OnSize(wxSizeEvent
& event
)
282 // we need to relayout all the cached cells
288 void wxHtmlListBox::RefreshLine(size_t line
)
290 m_cache
->InvalidateRange(line
, line
);
292 wxVListBox::RefreshLine(line
);
295 void wxHtmlListBox::RefreshLines(size_t from
, size_t to
)
297 m_cache
->InvalidateRange(from
, to
);
299 wxVListBox::RefreshLines(from
, to
);
302 void wxHtmlListBox::RefreshAll()
306 wxVListBox::RefreshAll();
309 void wxHtmlListBox::SetItemCount(size_t count
)
311 // the items are going to change, forget the old ones
314 wxVListBox::SetItemCount(count
);
317 // ----------------------------------------------------------------------------
318 // wxHtmlListBox implementation of wxVListBox pure virtuals
319 // ----------------------------------------------------------------------------
321 void wxHtmlListBox::OnDrawItem(wxDC
& dc
, const wxRect
& rect
, size_t n
) const
325 wxHtmlCell
*cell
= m_cache
->Get(n
);
326 wxCHECK_RET( cell
, _T("this cell should be cached!") );
328 wxHtmlRenderingInfo htmlRendInfo
;
330 // draw the selected cell in selected state
333 wxHtmlSelection htmlSel
;
334 htmlSel
.Set(wxPoint(), cell
, wxPoint(INT_MAX
, INT_MAX
), cell
);
335 htmlRendInfo
.SetSelection(&htmlSel
);
336 if ( m_htmlRendStyle
)
337 htmlRendInfo
.SetStyle(m_htmlRendStyle
);
338 htmlRendInfo
.GetState().SetSelectionState(wxHTML_SEL_IN
);
341 // note that we can't stop drawing exactly at the window boundary as then
342 // even the visible cells part could be not drawn, so always draw the
344 cell
->Draw(dc
, rect
.x
+2, rect
.y
+2, 0, INT_MAX
, htmlRendInfo
);
347 wxCoord
wxHtmlListBox::OnMeasureItem(size_t n
) const
351 wxHtmlCell
*cell
= m_cache
->Get(n
);
352 wxCHECK_MSG( cell
, 0, _T("this cell should be cached!") );
354 return cell
->GetHeight() + cell
->GetDescent() + 4;