]> git.saurik.com Git - wxWidgets.git/blob - src/generic/htmllbox.cpp
don't call CopyBeforeWrite when returning non-const interator if the string is empty...
[wxWidgets.git] / src / generic / htmllbox.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: generic/htmllbox.cpp
3 // Purpose: implementation of wxHtmlListBox
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 31.05.03
7 // RCS-ID: $Id$
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // License: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/dcclient.h"
29 #endif //WX_PRECOMP
30
31 #if wxUSE_HTML
32
33 #include "wx/htmllbox.h"
34
35 #include "wx/html/htmlcell.h"
36 #include "wx/html/winpars.h"
37
38 // this hack forces the linker to always link in m_* files
39 #include "wx/html/forcelnk.h"
40 FORCE_WXHTML_MODULES()
41
42 // ============================================================================
43 // private classes
44 // ============================================================================
45
46 // ----------------------------------------------------------------------------
47 // wxHtmlListBoxCache
48 // ----------------------------------------------------------------------------
49
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
53 {
54 public:
55 wxHtmlListBoxCache()
56 {
57 for ( size_t n = 0; n < SIZE; n++ )
58 {
59 m_items[n] = (size_t)-1;
60 m_cells[n] = NULL;
61 }
62
63 m_next = 0;
64 }
65
66 ~wxHtmlListBoxCache()
67 {
68 for ( size_t n = 0; n < SIZE; n++ )
69 {
70 delete m_cells[n];
71 }
72 }
73
74 // completely invalidate the cache
75 void Clear()
76 {
77 for ( size_t n = 0; n < SIZE; n++ )
78 {
79 m_items[n] = (size_t)-1;
80 delete m_cells[n];
81 m_cells[n] = NULL;
82 }
83 }
84
85 // return the cached cell for this index or NULL if none
86 wxHtmlCell *Get(size_t item) const
87 {
88 for ( size_t n = 0; n < SIZE; n++ )
89 {
90 if ( m_items[n] == item )
91 return m_cells[n];
92 }
93
94 return NULL;
95 }
96
97 // returns true if we already have this item cached
98 bool Has(size_t item) const { return Get(item) != NULL; }
99
100 // ensure that the item is cached
101 void Store(size_t item, wxHtmlCell *cell)
102 {
103 delete m_cells[m_next];
104 m_cells[m_next] = cell;
105 m_items[m_next] = item;
106
107 // advance to the next item wrapping around if there are no more
108 if ( ++m_next == SIZE )
109 m_next = 0;
110 }
111
112 private:
113 // the max number of the items we cache
114 enum { SIZE = 50 };
115
116 // the index of the LRU (oldest) cell
117 size_t m_next;
118
119 // the parsed representation of the cached item or NULL
120 wxHtmlCell *m_cells[SIZE];
121
122 // the index of the currently cached item (only valid if m_cells != NULL)
123 size_t m_items[SIZE];
124 };
125
126 // ----------------------------------------------------------------------------
127 // wxHtmlListBoxStyle
128 // ----------------------------------------------------------------------------
129
130 // just forward wxDefaultHtmlRenderingStyle callbacks to the main class so that
131 // they could be overridden by the user code
132 class wxHtmlListBoxStyle : public wxDefaultHtmlRenderingStyle
133 {
134 public:
135 wxHtmlListBoxStyle(wxHtmlListBox& hlbox) : m_hlbox(hlbox) { }
136
137 virtual wxColour GetSelectedTextColour(const wxColour& colFg)
138 {
139 return m_hlbox.GetSelectedTextColour(colFg);
140 }
141
142 virtual wxColour GetSelectedTextBgColour(const wxColour& colBg)
143 {
144 return m_hlbox.GetSelectedTextBgColour(colBg);
145 }
146
147 private:
148 const wxHtmlListBox& m_hlbox;
149
150 DECLARE_NO_COPY_CLASS(wxHtmlListBoxStyle)
151 };
152
153
154 // ----------------------------------------------------------------------------
155 // event tables
156 // ----------------------------------------------------------------------------
157
158 BEGIN_EVENT_TABLE(wxHtmlListBox, wxVListBox)
159 EVT_SIZE(wxHtmlListBox::OnSize)
160 END_EVENT_TABLE()
161
162 // ============================================================================
163 // implementation
164 // ============================================================================
165
166 IMPLEMENT_ABSTRACT_CLASS(wxHtmlListBox, wxVListBox)
167
168
169 // ----------------------------------------------------------------------------
170 // wxHtmlListBox creation
171 // ----------------------------------------------------------------------------
172
173 void wxHtmlListBox::Init()
174 {
175 m_htmlParser = NULL;
176 m_htmlRendStyle = new wxHtmlListBoxStyle(*this);
177 m_cache = new wxHtmlListBoxCache;
178 }
179
180 bool wxHtmlListBox::Create(wxWindow *parent,
181 wxWindowID id,
182 const wxPoint& pos,
183 const wxSize& size,
184 long style,
185 const wxString& name)
186 {
187 return wxVListBox::Create(parent, id, pos, size, style, name);
188 }
189
190 wxHtmlListBox::~wxHtmlListBox()
191 {
192 delete m_cache;
193
194 if ( m_htmlParser )
195 {
196 delete m_htmlParser->GetDC();
197 delete m_htmlParser;
198 }
199
200 delete m_htmlRendStyle;
201 }
202
203 // ----------------------------------------------------------------------------
204 // wxHtmlListBox appearance
205 // ----------------------------------------------------------------------------
206
207 wxColour wxHtmlListBox::GetSelectedTextColour(const wxColour& colFg) const
208 {
209 return m_htmlRendStyle->
210 wxDefaultHtmlRenderingStyle::GetSelectedTextColour(colFg);
211 }
212
213 wxColour
214 wxHtmlListBox::GetSelectedTextBgColour(const wxColour& WXUNUSED(colBg)) const
215 {
216 return GetSelectionBackground();
217 }
218
219 // ----------------------------------------------------------------------------
220 // wxHtmlListBox items markup
221 // ----------------------------------------------------------------------------
222
223 wxString wxHtmlListBox::OnGetItemMarkup(size_t n) const
224 {
225 // we don't even need to wrap the value returned by OnGetItem() inside
226 // "<html><body>" and "</body></html>" because wxHTML can parse it even
227 // without these tags
228 return OnGetItem(n);
229 }
230
231 // ----------------------------------------------------------------------------
232 // wxHtmlListBox cache handling
233 // ----------------------------------------------------------------------------
234
235 void wxHtmlListBox::CacheItem(size_t n) const
236 {
237 if ( !m_cache->Has(n) )
238 {
239 if ( !m_htmlParser )
240 {
241 wxHtmlListBox *self = wxConstCast(this, wxHtmlListBox);
242
243 self->m_htmlParser = new wxHtmlWinParser;
244 m_htmlParser->SetDC(new wxClientDC(self));
245 m_htmlParser->SetFS(&self->m_filesystem);
246 }
247
248 wxHtmlContainerCell *cell = (wxHtmlContainerCell *)m_htmlParser->
249 Parse(OnGetItemMarkup(n));
250 wxCHECK_RET( cell, _T("wxHtmlParser::Parse() returned NULL?") );
251
252 cell->Layout(GetClientSize().x - 2*GetMargins().x);
253
254 m_cache->Store(n, cell);
255 }
256 }
257
258 void wxHtmlListBox::OnSize(wxSizeEvent& event)
259 {
260 // we need to relayout all the cached cells
261 m_cache->Clear();
262
263 event.Skip();
264 }
265
266 void wxHtmlListBox::RefreshAll()
267 {
268 m_cache->Clear();
269
270 wxVListBox::RefreshAll();
271 }
272
273 void wxHtmlListBox::SetItemCount(size_t count)
274 {
275 // the items are going to change, forget the old ones
276 m_cache->Clear();
277
278 wxVListBox::SetItemCount(count);
279 }
280
281 // ----------------------------------------------------------------------------
282 // wxHtmlListBox implementation of wxVListBox pure virtuals
283 // ----------------------------------------------------------------------------
284
285 void wxHtmlListBox::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const
286 {
287 CacheItem(n);
288
289 wxHtmlCell *cell = m_cache->Get(n);
290 wxCHECK_RET( cell, _T("this cell should be cached!") );
291
292 wxHtmlRenderingInfo htmlRendInfo;
293
294 // draw the selected cell in selected state
295 if ( IsSelected(n) )
296 {
297 wxHtmlSelection htmlSel;
298 htmlSel.Set(wxPoint(0, 0), cell, wxPoint(INT_MAX, INT_MAX), cell);
299 htmlRendInfo.SetSelection(&htmlSel);
300 if ( m_htmlRendStyle )
301 htmlRendInfo.SetStyle(m_htmlRendStyle);
302 htmlRendInfo.GetState().SetSelectionState(wxHTML_SEL_IN);
303 }
304
305 // note that we can't stop drawing exactly at the window boundary as then
306 // even the visible cells part could be not drawn, so always draw the
307 // entire cell
308 cell->Draw(dc, rect.x+2, rect.y+2, 0, INT_MAX, htmlRendInfo);
309 }
310
311 wxCoord wxHtmlListBox::OnMeasureItem(size_t n) const
312 {
313 CacheItem(n);
314
315 wxHtmlCell *cell = m_cache->Get(n);
316 wxCHECK_MSG( cell, 0, _T("this cell should be cached!") );
317
318 return cell->GetHeight() + cell->GetDescent() + 4;
319 }
320
321 #endif