]> git.saurik.com Git - wxWidgets.git/blame - src/generic/htmllbox.cpp
implemented multiple selection
[wxWidgets.git] / src / generic / htmllbox.cpp
CommitLineData
e0c6027b
VZ
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
bb178b29 28 #include "wx/dcclient.h"
e0c6027b
VZ
29#endif //WX_PRECOMP
30
31#include "wx/htmllbox.h"
32
33#include "wx/html/htmlcell.h"
34#include "wx/html/winpars.h"
35
5ecdc7ab
VZ
36// this hack forces the linker to always link in m_* files
37#include "wx/html/forcelnk.h"
38FORCE_WXHTML_MODULES()
39
e0c6027b
VZ
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
e0c6027b
VZ
46class wxHtmlListBoxCache
47{
48public:
5ecdc7ab
VZ
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 }
e0c6027b 56
5ecdc7ab
VZ
57 m_next = 0;
58 }
e0c6027b 59
5ecdc7ab 60 ~wxHtmlListBoxCache()
e0c6027b 61 {
5ecdc7ab
VZ
62 for ( size_t n = 0; n < SIZE; n++ )
63 {
64 delete m_cells[n];
65 }
66 }
e0c6027b 67
5ecdc7ab
VZ
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 }
e0c6027b
VZ
77 }
78
79 // return the cached cell for this index or NULL if none
5ecdc7ab
VZ
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)
e0c6027b 96 {
5ecdc7ab
VZ
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;
e0c6027b
VZ
104 }
105
106private:
5ecdc7ab
VZ
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
e0c6027b 113 // the parsed representation of the cached item or NULL
5ecdc7ab 114 wxHtmlCell *m_cells[SIZE];
e0c6027b 115
5ecdc7ab
VZ
116 // the index of the currently cached item (only valid if m_cells != NULL)
117 size_t m_items[SIZE];
e0c6027b
VZ
118};
119
5ecdc7ab
VZ
120// ----------------------------------------------------------------------------
121// event tables
122// ----------------------------------------------------------------------------
123
124BEGIN_EVENT_TABLE(wxHtmlListBox, wxVListBox)
125 EVT_SIZE(wxHtmlListBox::OnSize)
126END_EVENT_TABLE()
127
e0c6027b
VZ
128// ============================================================================
129// implementation
130// ============================================================================
131
132// ----------------------------------------------------------------------------
133// wxHtmlListBox creation
134// ----------------------------------------------------------------------------
135
136void wxHtmlListBox::Init()
137{
138 m_htmlParser = NULL;
139 m_cache = new wxHtmlListBoxCache;
140}
141
142bool 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
153wxHtmlListBox::~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
167wxString 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
5ecdc7ab
VZ
175// ----------------------------------------------------------------------------
176// wxHtmlListBox cache handling
177// ----------------------------------------------------------------------------
178
e0c6027b
VZ
179void 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
5ecdc7ab 195 cell->Layout(GetClientSize().x - 2*GetMargins().x);
e0c6027b
VZ
196
197 m_cache->Store(n, cell);
198 }
199}
200
5ecdc7ab
VZ
201void wxHtmlListBox::OnSize(wxSizeEvent& event)
202{
203 // we need to relayout all the cached cells
204 m_cache->Clear();
205
206 event.Skip();
207}
208
209void wxHtmlListBox::RefreshAll()
210{
211 m_cache->Clear();
212
213 wxVListBox::RefreshAll();
214}
215
e0c6027b
VZ
216// ----------------------------------------------------------------------------
217// wxHtmlListBox implementation of wxVListBox pure virtuals
218// ----------------------------------------------------------------------------
219
220void 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
901b583c 227 wxHtmlRenderingInfo htmlRendInfo;
5ecdc7ab 228
e0c6027b
VZ
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);
901b583c
VZ
234 htmlRendInfo.SetSelection(&htmlSel);
235 //htmlRendInfo.SetSelectionState(wxHTML_SEL_IN);
e0c6027b 236 }
5ecdc7ab
VZ
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
901b583c 241 cell->Draw(dc, rect.x, rect.y, 0, INT_MAX, htmlRendInfo);
e0c6027b
VZ
242}
243
244wxCoord 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