1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/generic/htmllbox.cpp
3 // Purpose:     implementation of wxHtmlListBox
4 // Author:      Vadim Zeitlin
5 // Modified by:
6 // Created:     31.05.03
7 // Copyright:   (c) 2003 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21 
22 
23 #ifndef WX_PRECOMP
24     #include "wx/dcclient.h"
25 #endif //WX_PRECOMP
26 
27 #if wxUSE_HTML
28 
29 #include "wx/htmllbox.h"
30 
31 #include "wx/html/htmlcell.h"
32 #include "wx/html/winpars.h"
33 
34 // this hack forces the linker to always link in m_* files
35 #include "wx/html/forcelnk.h"
36 FORCE_WXHTML_MODULES()
37 
38 // ----------------------------------------------------------------------------
39 // constants
40 // ----------------------------------------------------------------------------
41 
42 // small border always added to the cells:
43 static const wxCoord CELL_BORDER = 2;
44 
45 const char wxHtmlListBoxNameStr[] = "htmlListBox";
46 const char wxSimpleHtmlListBoxNameStr[] = "simpleHtmlListBox";
47 
48 // ============================================================================
49 // private classes
50 // ============================================================================
51 
52 // ----------------------------------------------------------------------------
53 // wxHtmlListBoxCache
54 // ----------------------------------------------------------------------------
55 
56 // this class is used by wxHtmlListBox to cache the parsed representation of
57 // the items to avoid doing it anew each time an item must be drawn
58 class wxHtmlListBoxCache
59 {
60 private:
61     // invalidate a single item, used by Clear() and InvalidateRange()
InvalidateItem(size_t n)62     void InvalidateItem(size_t n)
63     {
64         m_items[n] = (size_t)-1;
65         wxDELETE(m_cells[n]);
66     }
67 
68 public:
wxHtmlListBoxCache()69     wxHtmlListBoxCache()
70     {
71         for ( size_t n = 0; n < SIZE; n++ )
72         {
73             m_items[n] = (size_t)-1;
74             m_cells[n] = NULL;
75         }
76 
77         m_next = 0;
78     }
79 
~wxHtmlListBoxCache()80     ~wxHtmlListBoxCache()
81     {
82         for ( size_t n = 0; n < SIZE; n++ )
83         {
84             delete m_cells[n];
85         }
86     }
87 
88     // completely invalidate the cache
Clear()89     void Clear()
90     {
91         for ( size_t n = 0; n < SIZE; n++ )
92         {
93             InvalidateItem(n);
94         }
95     }
96 
97     // return the cached cell for this index or NULL if none
Get(size_t item) const98     wxHtmlCell *Get(size_t item) const
99     {
100         for ( size_t n = 0; n < SIZE; n++ )
101         {
102             if ( m_items[n] == item )
103                 return m_cells[n];
104         }
105 
106         return NULL;
107     }
108 
109     // returns true if we already have this item cached
Has(size_t item) const110     bool Has(size_t item) const { return Get(item) != NULL; }
111 
112     // ensure that the item is cached
Store(size_t item,wxHtmlCell * cell)113     void Store(size_t item, wxHtmlCell *cell)
114     {
115         delete m_cells[m_next];
116         m_cells[m_next] = cell;
117         m_items[m_next] = item;
118 
119         // advance to the next item wrapping around if there are no more
120         if ( ++m_next == SIZE )
121             m_next = 0;
122     }
123 
124     // forget the cached value of the item(s) between the given ones (inclusive)
InvalidateRange(size_t from,size_t to)125     void InvalidateRange(size_t from, size_t to)
126     {
127         for ( size_t n = 0; n < SIZE; n++ )
128         {
129             if ( m_items[n] >= from && m_items[n] <= to )
130             {
131                 InvalidateItem(n);
132             }
133         }
134     }
135 
136 private:
137     // the max number of the items we cache
138     enum { SIZE = 50 };
139 
140     // the index of the LRU (oldest) cell
141     size_t m_next;
142 
143     // the parsed representation of the cached item or NULL
144     wxHtmlCell *m_cells[SIZE];
145 
146     // the index of the currently cached item (only valid if m_cells != NULL)
147     size_t m_items[SIZE];
148 };
149 
150 // ----------------------------------------------------------------------------
151 // wxHtmlListBoxStyle
152 // ----------------------------------------------------------------------------
153 
154 // just forward wxDefaultHtmlRenderingStyle callbacks to the main class so that
155 // they could be overridden by the user code
156 class wxHtmlListBoxStyle : public wxDefaultHtmlRenderingStyle
157 {
158 public:
wxHtmlListBoxStyle(const wxHtmlListBox & hlbox)159     wxHtmlListBoxStyle(const wxHtmlListBox& hlbox)
160         : wxDefaultHtmlRenderingStyle(&hlbox), m_hlbox(hlbox)
161     { }
162 
GetSelectedTextColour(const wxColour & colFg)163     virtual wxColour GetSelectedTextColour(const wxColour& colFg) wxOVERRIDE
164     {
165         // by default wxHtmlListBox doesn't implement GetSelectedTextColour()
166         // and returns wxNullColour from it, so use the default HTML colour for
167         // selection
168         wxColour col = m_hlbox.GetSelectedTextColour(colFg);
169         if ( !col.IsOk() )
170         {
171             col = wxDefaultHtmlRenderingStyle::GetSelectedTextColour(colFg);
172         }
173 
174         return col;
175     }
176 
GetSelectedTextBgColour(const wxColour & colBg)177     virtual wxColour GetSelectedTextBgColour(const wxColour& colBg) wxOVERRIDE
178     {
179         wxColour col = m_hlbox.GetSelectedTextBgColour(colBg);
180         if ( !col.IsOk() )
181         {
182             col = wxDefaultHtmlRenderingStyle::GetSelectedTextBgColour(colBg);
183         }
184 
185         return col;
186     }
187 
188 private:
189     const wxHtmlListBox& m_hlbox;
190 
191     wxDECLARE_NO_COPY_CLASS(wxHtmlListBoxStyle);
192 };
193 
194 // ----------------------------------------------------------------------------
195 // event tables
196 // ----------------------------------------------------------------------------
197 
198 wxBEGIN_EVENT_TABLE(wxHtmlListBox, wxVListBox)
199     EVT_SIZE(wxHtmlListBox::OnSize)
200     EVT_MOTION(wxHtmlListBox::OnMouseMove)
201     EVT_LEFT_DOWN(wxHtmlListBox::OnLeftDown)
202 wxEND_EVENT_TABLE()
203 
204 // ============================================================================
205 // implementation
206 // ============================================================================
207 
208 wxIMPLEMENT_ABSTRACT_CLASS(wxHtmlListBox, wxVListBox);
209 
210 
211 // ----------------------------------------------------------------------------
212 // wxHtmlListBox creation
213 // ----------------------------------------------------------------------------
214 
wxHtmlListBox()215 wxHtmlListBox::wxHtmlListBox()
216     : wxHtmlWindowMouseHelper(this)
217 {
218     Init();
219 }
220 
221 // normal constructor which calls Create() internally
wxHtmlListBox(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)222 wxHtmlListBox::wxHtmlListBox(wxWindow *parent,
223                              wxWindowID id,
224                              const wxPoint& pos,
225                              const wxSize& size,
226                              long style,
227                              const wxString& name)
228     : wxHtmlWindowMouseHelper(this)
229 {
230     Init();
231 
232     (void)Create(parent, id, pos, size, style, name);
233 }
234 
Init()235 void wxHtmlListBox::Init()
236 {
237     m_htmlParser = NULL;
238     m_htmlRendStyle = new wxHtmlListBoxStyle(*this);
239     m_cache = new wxHtmlListBoxCache;
240 }
241 
Create(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)242 bool wxHtmlListBox::Create(wxWindow *parent,
243                            wxWindowID id,
244                            const wxPoint& pos,
245                            const wxSize& size,
246                            long style,
247                            const wxString& name)
248 {
249     return wxVListBox::Create(parent, id, pos, size, style, name);
250 }
251 
~wxHtmlListBox()252 wxHtmlListBox::~wxHtmlListBox()
253 {
254     delete m_cache;
255 
256     if ( m_htmlParser )
257     {
258         delete m_htmlParser->GetDC();
259         delete m_htmlParser;
260     }
261 
262     delete m_htmlRendStyle;
263 }
264 
265 // ----------------------------------------------------------------------------
266 // wxHtmlListBox appearance
267 // ----------------------------------------------------------------------------
268 
269 wxColour
GetSelectedTextColour(const wxColour & WXUNUSED (colFg)) const270 wxHtmlListBox::GetSelectedTextColour(const wxColour& WXUNUSED(colFg)) const
271 {
272     return wxNullColour;
273 }
274 
275 wxColour
GetSelectedTextBgColour(const wxColour & WXUNUSED (colBg)) const276 wxHtmlListBox::GetSelectedTextBgColour(const wxColour& WXUNUSED(colBg)) const
277 {
278     return GetSelectionBackground();
279 }
280 
281 // ----------------------------------------------------------------------------
282 // wxHtmlListBox items markup
283 // ----------------------------------------------------------------------------
284 
OnGetItemMarkup(size_t n) const285 wxString wxHtmlListBox::OnGetItemMarkup(size_t n) const
286 {
287     // we don't even need to wrap the value returned by OnGetItem() inside
288     // "<html><body>" and "</body></html>" because wxHTML can parse it even
289     // without these tags
290     return OnGetItem(n);
291 }
292 
293 // ----------------------------------------------------------------------------
294 // wxHtmlListBox cache handling
295 // ----------------------------------------------------------------------------
296 
CreateCellForItem(size_t n) const297 wxHtmlCell* wxHtmlListBox::CreateCellForItem(size_t n) const
298 {
299     if ( !m_htmlParser )
300     {
301         wxHtmlListBox *self = wxConstCast(this, wxHtmlListBox);
302 
303         self->m_htmlParser = new wxHtmlWinParser(self);
304         m_htmlParser->SetDC(new wxClientDC(self));
305         m_htmlParser->SetFS(&self->m_filesystem);
306 #if !wxUSE_UNICODE
307         if (GetFont().IsOk())
308             m_htmlParser->SetInputEncoding(GetFont().GetEncoding());
309 #endif
310         // use system's default GUI font by default:
311         m_htmlParser->SetStandardFonts();
312     }
313 
314     wxHtmlContainerCell *cell = (wxHtmlContainerCell *)m_htmlParser->
315             Parse(OnGetItemMarkup(n));
316     wxCHECK_MSG( cell, NULL, wxT("wxHtmlParser::Parse() returned NULL?") );
317 
318     // set the cell's ID to item's index so that CellCoordsToPhysical()
319     // can quickly find the item:
320     cell->SetId(wxString::Format(wxT("%lu"), (unsigned long)n));
321 
322     cell->Layout(GetClientSize().x - 2*GetMargins().x);
323 
324     return cell;
325 }
326 
CacheItem(size_t n) const327 void wxHtmlListBox::CacheItem(size_t n) const
328 {
329     if ( !m_cache->Has(n) )
330         m_cache->Store(n, CreateCellForItem(n));
331 }
332 
OnSize(wxSizeEvent & event)333 void wxHtmlListBox::OnSize(wxSizeEvent& event)
334 {
335     // we need to relayout all the cached cells
336     m_cache->Clear();
337 
338     event.Skip();
339 }
340 
RefreshRow(size_t line)341 void wxHtmlListBox::RefreshRow(size_t line)
342 {
343     m_cache->InvalidateRange(line, line);
344 
345     wxVListBox::RefreshRow(line);
346 }
347 
RefreshRows(size_t from,size_t to)348 void wxHtmlListBox::RefreshRows(size_t from, size_t to)
349 {
350     m_cache->InvalidateRange(from, to);
351 
352     wxVListBox::RefreshRows(from, to);
353 }
354 
RefreshAll()355 void wxHtmlListBox::RefreshAll()
356 {
357     m_cache->Clear();
358 
359     wxVListBox::RefreshAll();
360 }
361 
SetItemCount(size_t count)362 void wxHtmlListBox::SetItemCount(size_t count)
363 {
364     // the items are going to change, forget the old ones
365     m_cache->Clear();
366 
367     wxVListBox::SetItemCount(count);
368 }
369 
370 // ----------------------------------------------------------------------------
371 // wxHtmlListBox implementation of wxVListBox pure virtuals
372 // ----------------------------------------------------------------------------
373 
374 void
OnDrawBackground(wxDC & dc,const wxRect & rect,size_t n) const375 wxHtmlListBox::OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const
376 {
377     if ( IsSelected(n) )
378     {
379         if ( DoDrawSolidBackground
380              (
381                 GetSelectedTextBgColour(GetBackgroundColour()),
382                 dc,
383                 rect,
384                 n
385              ) )
386         {
387             return;
388         }
389         //else: no custom selection background colour, use base class version
390     }
391 
392     wxVListBox::OnDrawBackground(dc, rect, n);
393 }
394 
OnDrawItem(wxDC & dc,const wxRect & rect,size_t n) const395 void wxHtmlListBox::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const
396 {
397     CacheItem(n);
398 
399     wxHtmlCell *cell = m_cache->Get(n);
400     wxCHECK_RET( cell, wxT("this cell should be cached!") );
401 
402     wxHtmlRenderingInfo htmlRendInfo;
403 
404     // draw the selected cell in selected state ourselves if we're using custom
405     // colours (to test for this, check the callbacks by passing them any dummy
406     // (but valid, to avoid asserts) colour):
407     if ( IsSelected(n) &&
408             (GetSelectedTextColour(*wxBLACK).IsOk() ||
409              GetSelectedTextBgColour(*wxWHITE).IsOk()) )
410     {
411         wxHtmlSelection htmlSel;
412         htmlSel.Set(wxPoint(0,0), cell, wxPoint(INT_MAX, INT_MAX), cell);
413         htmlRendInfo.SetSelection(&htmlSel);
414         htmlRendInfo.SetStyle(m_htmlRendStyle);
415         htmlRendInfo.GetState().SetSelectionState(wxHTML_SEL_IN);
416     }
417     //else: normal item or selected item with default colours, its background
418     //      was already taken care of in the base class
419 
420     // note that we can't stop drawing exactly at the window boundary as then
421     // even the visible cells part could be not drawn, so always draw the
422     // entire cell
423     cell->Draw(dc,
424                rect.x + CELL_BORDER, rect.y + CELL_BORDER,
425                0, INT_MAX, htmlRendInfo);
426 }
427 
OnMeasureItem(size_t n) const428 wxCoord wxHtmlListBox::OnMeasureItem(size_t n) const
429 {
430     // Notice that we can't cache the cell here because we could be called from
431     // some code updating an existing cell which could be displaced from the
432     // cache if we called CacheItem() and destroyed -- resulting in a crash
433     // when we return to its method from here, see #16651.
434     wxHtmlCell * const cell = CreateCellForItem(n);
435     if ( !cell )
436         return 0;
437 
438     const wxCoord h = cell->GetHeight() + cell->GetDescent() + 4;
439     delete cell;
440 
441     return h;
442 }
443 
444 // ----------------------------------------------------------------------------
445 // wxHtmlListBox implementation of wxHtmlListBoxWinInterface
446 // ----------------------------------------------------------------------------
447 
SetHTMLWindowTitle(const wxString & WXUNUSED (title))448 void wxHtmlListBox::SetHTMLWindowTitle(const wxString& WXUNUSED(title))
449 {
450     // nothing to do
451 }
452 
OnHTMLLinkClicked(const wxHtmlLinkInfo & link)453 void wxHtmlListBox::OnHTMLLinkClicked(const wxHtmlLinkInfo& link)
454 {
455     OnLinkClicked(GetItemForCell(link.GetHtmlCell()), link);
456 }
457 
OnLinkClicked(size_t WXUNUSED (n),const wxHtmlLinkInfo & link)458 void wxHtmlListBox::OnLinkClicked(size_t WXUNUSED(n),
459                                   const wxHtmlLinkInfo& link)
460 {
461     wxHtmlLinkEvent event(GetId(), link);
462     GetEventHandler()->ProcessEvent(event);
463 }
464 
465 wxHtmlOpeningStatus
OnHTMLOpeningURL(wxHtmlURLType WXUNUSED (type),const wxString & WXUNUSED (url),wxString * WXUNUSED (redirect)) const466 wxHtmlListBox::OnHTMLOpeningURL(wxHtmlURLType WXUNUSED(type),
467                                 const wxString& WXUNUSED(url),
468                                 wxString *WXUNUSED(redirect)) const
469 {
470     return wxHTML_OPEN;
471 }
472 
HTMLCoordsToWindow(wxHtmlCell * cell,const wxPoint & pos) const473 wxPoint wxHtmlListBox::HTMLCoordsToWindow(wxHtmlCell *cell,
474                                           const wxPoint& pos) const
475 {
476     return CellCoordsToPhysical(pos, cell);
477 }
478 
GetHTMLWindow()479 wxWindow* wxHtmlListBox::GetHTMLWindow() { return this; }
480 
GetHTMLBackgroundColour() const481 wxColour wxHtmlListBox::GetHTMLBackgroundColour() const
482 {
483     return GetBackgroundColour();
484 }
485 
SetHTMLBackgroundColour(const wxColour & WXUNUSED (clr))486 void wxHtmlListBox::SetHTMLBackgroundColour(const wxColour& WXUNUSED(clr))
487 {
488     // nothing to do
489 }
490 
SetHTMLBackgroundImage(const wxBitmap & WXUNUSED (bmpBg))491 void wxHtmlListBox::SetHTMLBackgroundImage(const wxBitmap& WXUNUSED(bmpBg))
492 {
493     // nothing to do
494 }
495 
SetHTMLStatusText(const wxString & WXUNUSED (text))496 void wxHtmlListBox::SetHTMLStatusText(const wxString& WXUNUSED(text))
497 {
498     // nothing to do
499 }
500 
GetHTMLCursor(HTMLCursor type) const501 wxCursor wxHtmlListBox::GetHTMLCursor(HTMLCursor type) const
502 {
503     // we don't want to show text selection cursor in listboxes
504     if (type == HTMLCursor_Text)
505         return wxHtmlWindow::GetDefaultHTMLCursor(HTMLCursor_Default);
506 
507     // in all other cases, use the same cursor as wxHtmlWindow:
508     return wxHtmlWindow::GetDefaultHTMLCursor(type);
509 }
510 
511 // ----------------------------------------------------------------------------
512 // wxHtmlListBox handling of HTML links
513 // ----------------------------------------------------------------------------
514 
GetRootCellCoords(size_t n) const515 wxPoint wxHtmlListBox::GetRootCellCoords(size_t n) const
516 {
517     wxPoint pos(CELL_BORDER, CELL_BORDER);
518     pos += GetMargins();
519     pos.y += GetRowsHeight(GetVisibleBegin(), n);
520     return pos;
521 }
522 
PhysicalCoordsToCell(wxPoint & pos,wxHtmlCell * & cell) const523 bool wxHtmlListBox::PhysicalCoordsToCell(wxPoint& pos, wxHtmlCell*& cell) const
524 {
525     int n = VirtualHitTest(pos.y);
526     if ( n == wxNOT_FOUND )
527         return false;
528 
529     // convert mouse coordinates to coords relative to item's wxHtmlCell:
530     pos -= GetRootCellCoords(n);
531 
532     CacheItem(n);
533     cell = m_cache->Get(n);
534 
535     return true;
536 }
537 
GetItemForCell(const wxHtmlCell * cell) const538 size_t wxHtmlListBox::GetItemForCell(const wxHtmlCell *cell) const
539 {
540     wxCHECK_MSG( cell, 0, wxT("no cell") );
541 
542     cell = cell->GetRootCell();
543 
544     wxCHECK_MSG( cell, 0, wxT("no root cell") );
545 
546     // the cell's ID contains item index, see CacheItem():
547     unsigned long n;
548     if ( !cell->GetId().ToULong(&n) )
549     {
550         wxFAIL_MSG( wxT("unexpected root cell's ID") );
551         return 0;
552     }
553 
554     return n;
555 }
556 
557 wxPoint
CellCoordsToPhysical(const wxPoint & pos,wxHtmlCell * cell) const558 wxHtmlListBox::CellCoordsToPhysical(const wxPoint& pos, wxHtmlCell *cell) const
559 {
560     return pos + GetRootCellCoords(GetItemForCell(cell));
561 }
562 
OnInternalIdle()563 void wxHtmlListBox::OnInternalIdle()
564 {
565     wxVListBox::OnInternalIdle();
566 
567     if ( wxHtmlWindowMouseHelper::DidMouseMove() )
568     {
569         wxPoint pos = ScreenToClient(wxGetMousePosition());
570         wxHtmlCell *cell;
571 
572         if ( !PhysicalCoordsToCell(pos, cell) )
573             return;
574 
575         wxHtmlWindowMouseHelper::HandleIdle(cell, pos);
576     }
577 }
578 
OnMouseMove(wxMouseEvent & event)579 void wxHtmlListBox::OnMouseMove(wxMouseEvent& event)
580 {
581     wxHtmlWindowMouseHelper::HandleMouseMoved();
582     event.Skip();
583 }
584 
OnLeftDown(wxMouseEvent & event)585 void wxHtmlListBox::OnLeftDown(wxMouseEvent& event)
586 {
587     wxPoint pos = event.GetPosition();
588     wxHtmlCell *cell;
589 
590     if ( !PhysicalCoordsToCell(pos, cell) )
591     {
592         event.Skip();
593         return;
594     }
595 
596     if ( !wxHtmlWindowMouseHelper::HandleMouseClick(cell, pos, event) )
597     {
598         // no link was clicked, so let the listbox code handle the click (e.g.
599         // by selecting another item in the list):
600         event.Skip();
601     }
602 }
603 
604 
605 // ----------------------------------------------------------------------------
606 // wxSimpleHtmlListBox
607 // ----------------------------------------------------------------------------
608 
609 wxIMPLEMENT_ABSTRACT_CLASS(wxSimpleHtmlListBox, wxHtmlListBox);
610 
611 
Create(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,int n,const wxString choices[],long style,const wxValidator & wxVALIDATOR_PARAM (validator),const wxString & name)612 bool wxSimpleHtmlListBox::Create(wxWindow *parent, wxWindowID id,
613                                  const wxPoint& pos,
614                                  const wxSize& size,
615                                  int n, const wxString choices[],
616                                  long style,
617                                  const wxValidator& wxVALIDATOR_PARAM(validator),
618                                  const wxString& name)
619 {
620     if (!wxHtmlListBox::Create(parent, id, pos, size, style, name))
621         return false;
622 
623 #if wxUSE_VALIDATORS
624     SetValidator(validator);
625 #endif
626 
627     Append(n, choices);
628 
629     return true;
630 }
631 
Create(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,const wxArrayString & choices,long style,const wxValidator & wxVALIDATOR_PARAM (validator),const wxString & name)632 bool wxSimpleHtmlListBox::Create(wxWindow *parent, wxWindowID id,
633                                  const wxPoint& pos,
634                                  const wxSize& size,
635                                  const wxArrayString& choices,
636                                  long style,
637                                  const wxValidator& wxVALIDATOR_PARAM(validator),
638                                  const wxString& name)
639 {
640     if (!wxHtmlListBox::Create(parent, id, pos, size, style, name))
641         return false;
642 
643 #if wxUSE_VALIDATORS
644     SetValidator(validator);
645 #endif
646 
647     Append(choices);
648 
649     return true;
650 }
651 
~wxSimpleHtmlListBox()652 wxSimpleHtmlListBox::~wxSimpleHtmlListBox()
653 {
654     wxItemContainer::Clear();
655 }
656 
DoClear()657 void wxSimpleHtmlListBox::DoClear()
658 {
659     wxASSERT(m_items.GetCount() == m_HTMLclientData.GetCount());
660 
661     m_items.Clear();
662     m_HTMLclientData.Clear();
663 
664     UpdateCount();
665 }
666 
Clear()667 void wxSimpleHtmlListBox::Clear()
668 {
669     DoClear();
670 }
671 
DoDeleteOneItem(unsigned int n)672 void wxSimpleHtmlListBox::DoDeleteOneItem(unsigned int n)
673 {
674     // For consistency with the other wxItemContainer-derived classes, deselect
675     // the currently selected item if it, or any item before it, is being
676     // deleted, from a single-selection control.
677     if ( !HasMultipleSelection() )
678     {
679         const int sel = GetSelection();
680         if ( sel != wxNOT_FOUND && static_cast<unsigned>(sel) >= n )
681         {
682             SetSelection(wxNOT_FOUND);
683         }
684     }
685 
686     m_items.RemoveAt(n);
687 
688     m_HTMLclientData.RemoveAt(n);
689 
690     UpdateCount();
691 }
692 
DoInsertItems(const wxArrayStringsAdapter & items,unsigned int pos,void ** clientData,wxClientDataType type)693 int wxSimpleHtmlListBox::DoInsertItems(const wxArrayStringsAdapter& items,
694                                        unsigned int pos,
695                                        void **clientData,
696                                        wxClientDataType type)
697 {
698     const unsigned int count = items.GetCount();
699 
700     m_items.Insert(wxEmptyString, pos, count);
701     m_HTMLclientData.Insert(NULL, pos, count);
702 
703     for ( unsigned int i = 0; i < count; ++i, ++pos )
704     {
705         m_items[pos] = items[i];
706         AssignNewItemClientData(pos, clientData, i, type);
707     }
708 
709     UpdateCount();
710 
711     return pos - 1;
712 }
713 
SetString(unsigned int n,const wxString & s)714 void wxSimpleHtmlListBox::SetString(unsigned int n, const wxString& s)
715 {
716     wxCHECK_RET( IsValid(n),
717                  wxT("invalid index in wxSimpleHtmlListBox::SetString") );
718 
719     m_items[n]=s;
720     RefreshRow(n);
721 }
722 
GetString(unsigned int n) const723 wxString wxSimpleHtmlListBox::GetString(unsigned int n) const
724 {
725     wxCHECK_MSG( IsValid(n), wxEmptyString,
726                  wxT("invalid index in wxSimpleHtmlListBox::GetString") );
727 
728     return m_items[n];
729 }
730 
UpdateCount()731 void wxSimpleHtmlListBox::UpdateCount()
732 {
733     wxASSERT(m_items.GetCount() == m_HTMLclientData.GetCount());
734     wxHtmlListBox::SetItemCount(m_items.GetCount());
735 
736     // very small optimization: if you need to add lot of items to
737     // a wxSimpleHtmlListBox be sure to use the
738     // wxSimpleHtmlListBox::Append(const wxArrayString&) method instead!
739     if (!this->IsFrozen())
740         RefreshAll();
741 }
742 
743 #endif // wxUSE_HTML
744