added wxVListBox using wxVScrolledWindow and wxHtmlListBox using it
[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 #endif //WX_PRECOMP
29
30 #include "wx/htmllbox.h"
31
32 #include "wx/html/htmlcell.h"
33 #include "wx/html/winpars.h"
34
35 // ----------------------------------------------------------------------------
36 // private classes
37 // ----------------------------------------------------------------------------
38
39 // this class is used by wxHtmlListBox to cache the parsed representation of
40 // the items to avoid doing it anew each time an item must be drawn
41 //
42 // TODO: extend the class to cache more than item
43 class wxHtmlListBoxCache
44 {
45 public:
46 wxHtmlListBoxCache() { m_cell = NULL; }
47 ~wxHtmlListBoxCache() { delete m_cell; }
48
49 // returns true if we already have this item cached
50 bool Has(size_t n) const { return m_cell && n == m_item; }
51
52 // ensure that the item is cached
53 void Store(size_t n, wxHtmlCell *cell)
54 {
55 m_item = n;
56
57 delete m_cell;
58 m_cell = cell;
59 }
60
61 // return the cached cell for this index or NULL if none
62 wxHtmlCell *Get(size_t n) const
63 {
64 // we could be reading uninitialized m_item here but the code is still
65 // correct
66 return n == m_item ? m_cell : NULL;
67 }
68
69 private:
70 // the parsed representation of the cached item or NULL
71 wxHtmlCell *m_cell;
72
73 // the index of the currently cached item (only valid if m_cell != NULL)
74 size_t m_item;
75 };
76
77 // ============================================================================
78 // implementation
79 // ============================================================================
80
81 // ----------------------------------------------------------------------------
82 // wxHtmlListBox creation
83 // ----------------------------------------------------------------------------
84
85 void wxHtmlListBox::Init()
86 {
87 m_htmlParser = NULL;
88 m_cache = new wxHtmlListBoxCache;
89 }
90
91 bool wxHtmlListBox::Create(wxWindow *parent,
92 wxWindowID id,
93 const wxPoint& pos,
94 const wxSize& size,
95 size_t countItems,
96 long style,
97 const wxString& name)
98 {
99 return wxVListBox::Create(parent, id, pos, size, countItems, style, name);
100 }
101
102 wxHtmlListBox::~wxHtmlListBox()
103 {
104 delete m_cache;
105 if ( m_htmlParser )
106 {
107 delete m_htmlParser->GetDC();
108 delete m_htmlParser;
109 }
110 }
111
112 // ----------------------------------------------------------------------------
113 // wxHtmlListBox items markup
114 // ----------------------------------------------------------------------------
115
116 wxString wxHtmlListBox::OnGetItemMarkup(size_t n) const
117 {
118 // we don't even need to wrap the value returned by OnGetItem() inside
119 // "<html><body>" and "</body></html>" because wxHTML can parse it even
120 // without these tags
121 return OnGetItem(n);
122 }
123
124 void wxHtmlListBox::CacheItem(size_t n) const
125 {
126 if ( !m_cache->Has(n) )
127 {
128 if ( !m_htmlParser )
129 {
130 wxHtmlListBox *self = wxConstCast(this, wxHtmlListBox);
131
132 self->m_htmlParser = new wxHtmlWinParser;
133 m_htmlParser->SetDC(new wxClientDC(self));
134 }
135
136 wxHtmlContainerCell *cell = (wxHtmlContainerCell *)m_htmlParser->
137 Parse(OnGetItemMarkup(n));
138 wxCHECK_RET( cell, _T("wxHtmlParser::Parse() returned NULL?") );
139
140 cell->Layout(GetClientSize().x);
141
142 m_cache->Store(n, cell);
143 }
144 }
145
146 // ----------------------------------------------------------------------------
147 // wxHtmlListBox implementation of wxVListBox pure virtuals
148 // ----------------------------------------------------------------------------
149
150 void wxHtmlListBox::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const
151 {
152 CacheItem(n);
153
154 wxHtmlCell *cell = m_cache->Get(n);
155 wxCHECK_RET( cell, _T("this cell should be cached!") );
156
157 // draw the selected cell in selected state
158 if ( IsSelected(n) )
159 {
160 wxHtmlSelection htmlSel;
161 htmlSel.Set(wxPoint(0, 0), cell, wxPoint(INT_MAX, INT_MAX), cell);
162 wxHtmlRenderingState htmlRendState(&htmlSel);
163 htmlRendState.SetSelectionState(wxHTML_SEL_IN);
164 cell->Draw(dc, rect.x, rect.y, 0, INT_MAX, htmlRendState);
165 }
166 else
167 {
168 // note that we can't stop drawing exactly at the window boundary as then
169 // even the visible cells part could be not drawn, so always draw the
170 // entire cell
171 wxHtmlRenderingState htmlRendState(NULL);
172 cell->Draw(dc, rect.x, rect.y, 0, INT_MAX, htmlRendState);
173 }
174 }
175
176 wxCoord wxHtmlListBox::OnMeasureItem(size_t n) const
177 {
178 CacheItem(n);
179
180 wxHtmlCell *cell = m_cache->Get(n);
181 wxCHECK_MSG( cell, 0, _T("this cell should be cached!") );
182
183 return cell->GetHeight() + cell->GetDescent();
184 }
185