]> git.saurik.com Git - wxWidgets.git/blob - src/generic/htmllbox.cpp
fixed the channel order for Mac (alpha comes first)
[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 #include "wx/htmllbox.h"
32
33 #include "wx/html/htmlcell.h"
34 #include "wx/html/winpars.h"
35
36 // this hack forces the linker to always link in m_* files
37 #include "wx/html/forcelnk.h"
38 FORCE_WXHTML_MODULES()
39
40 // ----------------------------------------------------------------------------
41 // private classes
42 // ----------------------------------------------------------------------------
43
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
47 {
48 public:
49 wxHtmlListBoxCache()
50 {
51 for ( size_t n = 0; n < SIZE; n++ )
52 {
53 m_items[n] = (size_t)-1;
54 m_cells[n] = NULL;
55 }
56
57 m_next = 0;
58 }
59
60 ~wxHtmlListBoxCache()
61 {
62 for ( size_t n = 0; n < SIZE; n++ )
63 {
64 delete m_cells[n];
65 }
66 }
67
68 // completely invalidate the cache
69 void Clear()
70 {
71 for ( size_t n = 0; n < SIZE; n++ )
72 {
73 m_items[n] = (size_t)-1;
74 delete m_cells[n];
75 m_cells[n] = NULL;
76 }
77 }
78
79 // return the cached cell for this index or NULL if none
80 wxHtmlCell *Get(size_t item) const
81 {
82 for ( size_t n = 0; n < SIZE; n++ )
83 {
84 if ( m_items[n] == item )
85 return m_cells[n];
86 }
87
88 return NULL;
89 }
90
91 // returns true if we already have this item cached
92 bool Has(size_t item) const { return Get(item) != NULL; }
93
94 // ensure that the item is cached
95 void Store(size_t item, wxHtmlCell *cell)
96 {
97 delete m_cells[m_next];
98 m_cells[m_next] = cell;
99 m_items[m_next] = item;
100
101 // advance to the next item wrapping around if there are no more
102 if ( ++m_next == SIZE )
103 m_next = 0;
104 }
105
106 private:
107 // the max number of the items we cache
108 enum { SIZE = 50 };
109
110 // the index of the LRU (oldest) cell
111 size_t m_next;
112
113 // the parsed representation of the cached item or NULL
114 wxHtmlCell *m_cells[SIZE];
115
116 // the index of the currently cached item (only valid if m_cells != NULL)
117 size_t m_items[SIZE];
118 };
119
120 // ----------------------------------------------------------------------------
121 // event tables
122 // ----------------------------------------------------------------------------
123
124 BEGIN_EVENT_TABLE(wxHtmlListBox, wxVListBox)
125 EVT_SIZE(wxHtmlListBox::OnSize)
126 END_EVENT_TABLE()
127
128 // ============================================================================
129 // implementation
130 // ============================================================================
131
132 // ----------------------------------------------------------------------------
133 // wxHtmlListBox creation
134 // ----------------------------------------------------------------------------
135
136 void wxHtmlListBox::Init()
137 {
138 m_htmlParser = NULL;
139 m_cache = new wxHtmlListBoxCache;
140 }
141
142 bool wxHtmlListBox::Create(wxWindow *parent,
143 wxWindowID id,
144 const wxPoint& pos,
145 const wxSize& size,
146 size_t countItems,
147 long style,
148 const wxString& name)
149 {
150 return wxVListBox::Create(parent, id, pos, size, countItems, style, name);
151 }
152
153 wxHtmlListBox::~wxHtmlListBox()
154 {
155 delete m_cache;
156 if ( m_htmlParser )
157 {
158 delete m_htmlParser->GetDC();
159 delete m_htmlParser;
160 }
161 }
162
163 // ----------------------------------------------------------------------------
164 // wxHtmlListBox items markup
165 // ----------------------------------------------------------------------------
166
167 wxString wxHtmlListBox::OnGetItemMarkup(size_t n) const
168 {
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
172 return OnGetItem(n);
173 }
174
175 // ----------------------------------------------------------------------------
176 // wxHtmlListBox cache handling
177 // ----------------------------------------------------------------------------
178
179 void wxHtmlListBox::CacheItem(size_t n) const
180 {
181 if ( !m_cache->Has(n) )
182 {
183 if ( !m_htmlParser )
184 {
185 wxHtmlListBox *self = wxConstCast(this, wxHtmlListBox);
186
187 self->m_htmlParser = new wxHtmlWinParser;
188 m_htmlParser->SetDC(new wxClientDC(self));
189 }
190
191 wxHtmlContainerCell *cell = (wxHtmlContainerCell *)m_htmlParser->
192 Parse(OnGetItemMarkup(n));
193 wxCHECK_RET( cell, _T("wxHtmlParser::Parse() returned NULL?") );
194
195 cell->Layout(GetClientSize().x - 2*GetMargins().x);
196
197 m_cache->Store(n, cell);
198 }
199 }
200
201 void wxHtmlListBox::OnSize(wxSizeEvent& event)
202 {
203 // we need to relayout all the cached cells
204 m_cache->Clear();
205
206 event.Skip();
207 }
208
209 void wxHtmlListBox::RefreshAll()
210 {
211 m_cache->Clear();
212
213 wxVListBox::RefreshAll();
214 }
215
216 // ----------------------------------------------------------------------------
217 // wxHtmlListBox implementation of wxVListBox pure virtuals
218 // ----------------------------------------------------------------------------
219
220 void wxHtmlListBox::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const
221 {
222 CacheItem(n);
223
224 wxHtmlCell *cell = m_cache->Get(n);
225 wxCHECK_RET( cell, _T("this cell should be cached!") );
226
227 wxHtmlRenderingState htmlRendState;
228
229 // draw the selected cell in selected state
230 if ( IsSelected(n) )
231 {
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);
236 }
237
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
240 // entire cell
241 cell->Draw(dc, rect.x, rect.y, 0, INT_MAX, htmlRendState);
242 }
243
244 wxCoord wxHtmlListBox::OnMeasureItem(size_t n) const
245 {
246 CacheItem(n);
247
248 wxHtmlCell *cell = m_cache->Get(n);
249 wxCHECK_MSG( cell, 0, _T("this cell should be cached!") );
250
251 return cell->GetHeight() + cell->GetDescent();
252 }
253