]> git.saurik.com Git - wxWidgets.git/blame - src/generic/vlbox.cpp
Remove duplicate wxEVT_COMMAND_TEXT_ENTER generation from wxOSX/Cocoa.
[wxWidgets.git] / src / generic / vlbox.cpp
CommitLineData
e0c6027b 1///////////////////////////////////////////////////////////////////////////////
e19ac18a 2// Name: src/generic/vlbox.cpp
e0c6027b
VZ
3// Purpose: implementation of wxVListBox
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>
526954c5 9// Licence: wxWindows licence
e0c6027b
VZ
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
179e085f
RN
27#if wxUSE_LISTBOX
28
2a673eb1
WS
29#include "wx/vlbox.h"
30
e0c6027b
VZ
31#ifndef WX_PRECOMP
32 #include "wx/settings.h"
bb178b29 33 #include "wx/dcclient.h"
2a673eb1 34 #include "wx/listbox.h"
e0c6027b
VZ
35#endif //WX_PRECOMP
36
0975a8a0 37#include "wx/dcbuffer.h"
be465555 38#include "wx/selstore.h"
04125489 39#include "wx/renderer.h"
e0c6027b
VZ
40
41// ----------------------------------------------------------------------------
42// event tables
43// ----------------------------------------------------------------------------
44
45BEGIN_EVENT_TABLE(wxVListBox, wxVScrolledWindow)
46 EVT_PAINT(wxVListBox::OnPaint)
47
48 EVT_KEY_DOWN(wxVListBox::OnKeyDown)
49 EVT_LEFT_DOWN(wxVListBox::OnLeftDown)
50 EVT_LEFT_DCLICK(wxVListBox::OnLeftDClick)
04125489
VZ
51
52 EVT_SET_FOCUS(wxVListBox::OnSetOrKillFocus)
53 EVT_KILL_FOCUS(wxVListBox::OnSetOrKillFocus)
858ad670
JS
54
55 EVT_SIZE(wxVListBox::OnSize)
e0c6027b
VZ
56END_EVENT_TABLE()
57
58// ============================================================================
59// implementation
60// ============================================================================
61
0c8392ca 62IMPLEMENT_ABSTRACT_CLASS(wxVListBox, wxVScrolledWindow)
a805142d 63const char wxVListBoxNameStr[] = "wxVListBox";
0c8392ca 64
e0c6027b
VZ
65// ----------------------------------------------------------------------------
66// wxVListBox creation
67// ----------------------------------------------------------------------------
68
69void wxVListBox::Init()
70{
970b97a2
VZ
71 m_current =
72 m_anchor = wxNOT_FOUND;
be465555 73 m_selStore = NULL;
e0c6027b
VZ
74}
75
76bool wxVListBox::Create(wxWindow *parent,
77 wxWindowID id,
78 const wxPoint& pos,
79 const wxSize& size,
e0c6027b
VZ
80 long style,
81 const wxString& name)
82{
a047aff2 83#ifdef __WXMSW__
9543d01c
VZ
84 if ( (style & wxBORDER_MASK) == wxDEFAULT )
85 style |= wxBORDER_THEME;
a047aff2
JS
86#endif
87
fef7400f 88 style |= wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE;
e0c6027b
VZ
89 if ( !wxVScrolledWindow::Create(parent, id, pos, size, style, name) )
90 return false;
91
be465555
VZ
92 if ( style & wxLB_MULTIPLE )
93 m_selStore = new wxSelectionStore;
e0c6027b 94
dc596072
RD
95 // make sure the native widget has the right colour since we do
96 // transparent drawing by default
97 SetBackgroundColour(GetBackgroundColour());
04125489
VZ
98
99 // leave m_colBgSel in an invalid state: it means for OnDrawBackground()
100 // to use wxRendererNative instead of painting selection bg ourselves
101 m_colBgSel = wxNullColour;
9a9b4940 102
0975a8a0
JS
103 // flicker-free drawing requires this
104 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
105
e0c6027b
VZ
106 return true;
107}
108
be465555
VZ
109wxVListBox::~wxVListBox()
110{
111 delete m_selStore;
112}
113
114void wxVListBox::SetItemCount(size_t count)
115{
9543d01c
VZ
116 // don't leave the current index invalid
117 if ( m_current != wxNOT_FOUND && (size_t)m_current >= count )
118 m_current = count - 1; // also ok when count == 0 as wxNOT_FOUND == -1
119
be465555
VZ
120 if ( m_selStore )
121 {
122 // tell the selection store that our number of items has changed
123 m_selStore->SetItemCount(count);
124 }
125
f18eaf26 126 SetRowCount(count);
be465555
VZ
127}
128
e0c6027b
VZ
129// ----------------------------------------------------------------------------
130// selection handling
131// ----------------------------------------------------------------------------
132
be465555
VZ
133bool wxVListBox::IsSelected(size_t line) const
134{
135 return m_selStore ? m_selStore->IsSelected(line) : (int)line == m_current;
136}
137
138bool wxVListBox::Select(size_t item, bool select)
139{
140 wxCHECK_MSG( m_selStore, false,
9a83f860 141 wxT("Select() may only be used with multiselection listbox") );
be465555
VZ
142
143 wxCHECK_MSG( item < GetItemCount(), false,
9a83f860 144 wxT("Select(): invalid item index") );
be465555
VZ
145
146 bool changed = m_selStore->SelectItem(item, select);
147 if ( changed )
148 {
149 // selection really changed
e02c72fa 150 RefreshRow(item);
be465555
VZ
151 }
152
153 DoSetCurrent(item);
154
155 return changed;
156}
157
158bool wxVListBox::SelectRange(size_t from, size_t to)
e0c6027b 159{
be465555 160 wxCHECK_MSG( m_selStore, false,
9a83f860 161 wxT("SelectRange() may only be used with multiselection listbox") );
be465555
VZ
162
163 // make sure items are in correct order
164 if ( from > to )
165 {
166 size_t tmp = from;
167 from = to;
168 to = tmp;
169 }
170
171 wxCHECK_MSG( to < GetItemCount(), false,
9a83f860 172 wxT("SelectRange(): invalid item index") );
be465555
VZ
173
174 wxArrayInt changed;
175 if ( !m_selStore->SelectRange(from, to, true, &changed) )
176 {
177 // too many items have changed, we didn't record them in changed array
178 // so we have no choice but to refresh everything between from and to
e02c72fa 179 RefreshRows(from, to);
be465555
VZ
180 }
181 else // we've got the indices of the changed items
182 {
183 const size_t count = changed.GetCount();
184 if ( !count )
185 {
186 // nothing changed
187 return false;
188 }
189
190 // refresh just the lines which have really changed
191 for ( size_t n = 0; n < count; n++ )
192 {
e02c72fa 193 RefreshRow(changed[n]);
be465555
VZ
194 }
195 }
196
197 // something changed
198 return true;
199}
200
201bool wxVListBox::DoSelectAll(bool select)
202{
203 wxCHECK_MSG( m_selStore, false,
9a83f860 204 wxT("SelectAll may only be used with multiselection listbox") );
be465555
VZ
205
206 size_t count = GetItemCount();
207 if ( count )
208 {
209 wxArrayInt changed;
210 if ( !m_selStore->SelectRange(0, count - 1, select) ||
211 !changed.IsEmpty() )
212 {
213 Refresh();
214
215 // something changed
216 return true;
217 }
218 }
219
220 return false;
221}
222
223bool wxVListBox::DoSetCurrent(int current)
224{
6c9210a7
VZ
225 wxASSERT_MSG( current == wxNOT_FOUND ||
226 (current >= 0 && (size_t)current < GetItemCount()),
9a83f860 227 wxT("wxVListBox::DoSetCurrent(): invalid item index") );
6c9210a7 228
be465555 229 if ( current == m_current )
e0c6027b
VZ
230 {
231 // nothing to do
be465555 232 return false;
e0c6027b
VZ
233 }
234
be465555 235 if ( m_current != wxNOT_FOUND )
e02c72fa 236 RefreshRow(m_current);
e0c6027b 237
be465555 238 m_current = current;
e0c6027b 239
be465555 240 if ( m_current != wxNOT_FOUND )
e0c6027b
VZ
241 {
242 // if the line is not visible at all, we scroll it into view but we
243 // don't need to refresh it -- it will be redrawn anyhow
be465555 244 if ( !IsVisible(m_current) )
e0c6027b 245 {
e02c72fa 246 ScrollToRow(m_current);
e0c6027b
VZ
247 }
248 else // line is at least partly visible
249 {
250 // it is, indeed, only partly visible, so scroll it into view to
251 // make it entirely visible
e02c72fa
VZ
252 while ( (size_t)m_current + 1 == GetVisibleRowsEnd() &&
253 ScrollToRow(GetVisibleBegin() + 1) ) ;
e0c6027b
VZ
254
255 // but in any case refresh it as even if it was only partly visible
256 // before we need to redraw it entirely as its background changed
e02c72fa 257 RefreshRow(m_current);
e0c6027b 258 }
be465555 259 }
e0c6027b 260
be465555
VZ
261 return true;
262}
e0c6027b 263
538483d8
FM
264void wxVListBox::InitEvent(wxCommandEvent& event, int n)
265{
266 event.SetEventObject(this);
267 event.SetInt(n);
268}
269
be465555
VZ
270void wxVListBox::SendSelectedEvent()
271{
272 wxASSERT_MSG( m_current != wxNOT_FOUND,
9a83f860 273 wxT("SendSelectedEvent() shouldn't be called") );
be465555
VZ
274
275 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, GetId());
538483d8 276 InitEvent(event, m_current);
be465555
VZ
277 (void)GetEventHandler()->ProcessEvent(event);
278}
279
280void wxVListBox::SetSelection(int selection)
281{
6c9210a7
VZ
282 wxCHECK_RET( selection == wxNOT_FOUND ||
283 (selection >= 0 && (size_t)selection < GetItemCount()),
9a83f860 284 wxT("wxVListBox::SetSelection(): invalid item index") );
6c9210a7 285
de5d3a20
VZ
286 if ( HasMultipleSelection() )
287 {
ad679137
VZ
288 if (selection != wxNOT_FOUND)
289 Select(selection);
290 else
291 DeselectAll();
de5d3a20
VZ
292 m_anchor = selection;
293 }
be465555
VZ
294
295 DoSetCurrent(selection);
296}
297
298size_t wxVListBox::GetSelectedCount() const
299{
300 return m_selStore ? m_selStore->GetSelectedCount()
301 : m_current == wxNOT_FOUND ? 0 : 1;
302}
303
304int wxVListBox::GetFirstSelected(unsigned long& cookie) const
305{
306 cookie = 0;
307
308 return GetNextSelected(cookie);
309}
310
311int wxVListBox::GetNextSelected(unsigned long& cookie) const
312{
313 wxCHECK_MSG( m_selStore, wxNOT_FOUND,
9a83f860 314 wxT("GetFirst/NextSelected() may only be used with multiselection listboxes") );
be465555
VZ
315
316 while ( cookie < GetItemCount() )
317 {
318 if ( IsSelected(cookie++) )
319 return cookie - 1;
e0c6027b 320 }
be465555
VZ
321
322 return wxNOT_FOUND;
e0c6027b
VZ
323}
324
04125489
VZ
325void wxVListBox::RefreshSelected()
326{
327 // only refresh those items which are currently visible and selected:
328 for ( size_t n = GetVisibleBegin(), end = GetVisibleEnd(); n < end; n++ )
329 {
330 if ( IsSelected(n) )
f18eaf26 331 RefreshRow(n);
04125489
VZ
332 }
333}
334
293b15f7
VZ
335wxRect wxVListBox::GetItemRect(size_t n) const
336{
337 wxRect itemrect;
338
339 // check that this item is visible
340 const size_t lineMax = GetVisibleEnd();
341 if ( n >= lineMax )
342 return itemrect;
343 size_t line = GetVisibleBegin();
344 if ( n < line )
345 return itemrect;
346
347 while ( line <= n )
348 {
349 itemrect.y += itemrect.height;
350 itemrect.height = OnGetRowHeight(line);
351
352 line++;
353 }
354
355 itemrect.width = GetClientSize().x;
356
357 return itemrect;
358}
359
e0c6027b 360// ----------------------------------------------------------------------------
9a9b4940 361// wxVListBox appearance parameters
e0c6027b
VZ
362// ----------------------------------------------------------------------------
363
364void wxVListBox::SetMargins(const wxPoint& pt)
365{
366 if ( pt != m_ptMargins )
367 {
368 m_ptMargins = pt;
369
370 Refresh();
371 }
372}
373
9a9b4940
VZ
374void wxVListBox::SetSelectionBackground(const wxColour& col)
375{
376 m_colBgSel = col;
377}
378
379// ----------------------------------------------------------------------------
380// wxVListBox painting
381// ----------------------------------------------------------------------------
382
e02c72fa 383wxCoord wxVListBox::OnGetRowHeight(size_t line) const
e0c6027b
VZ
384{
385 return OnMeasureItem(line) + 2*m_ptMargins.y;
386}
387
388void wxVListBox::OnDrawSeparator(wxDC& WXUNUSED(dc),
389 wxRect& WXUNUSED(rect),
390 size_t WXUNUSED(n)) const
391{
392}
393
c848185a
VZ
394bool
395wxVListBox::DoDrawSolidBackground(const wxColour& col,
396 wxDC& dc,
397 const wxRect& rect,
398 size_t n) const
27d0dcd0 399{
c848185a
VZ
400 if ( !col.IsOk() )
401 return false;
402
403 // we need to render selected and current items differently
404 const bool isSelected = IsSelected(n),
405 isCurrent = IsCurrent(n);
406 if ( isSelected || isCurrent )
27d0dcd0 407 {
c848185a 408 if ( isSelected )
27d0dcd0 409 {
04ee05f9 410 dc.SetBrush(wxBrush(col, wxBRUSHSTYLE_SOLID));
27d0dcd0 411 }
c848185a
VZ
412 else // !selected
413 {
414 dc.SetBrush(*wxTRANSPARENT_BRUSH);
415 }
416 dc.SetPen(*(isCurrent ? wxBLACK_PEN : wxTRANSPARENT_PEN));
417 dc.DrawRectangle(rect);
04125489 418 }
c848185a
VZ
419 //else: do nothing for the normal items
420
421 return true;
422}
423
424void wxVListBox::OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const
425{
426 // use wxRendererNative for more native look unless we use custom bg colour
427 if ( !DoDrawSolidBackground(m_colBgSel, dc, rect, n) )
04125489
VZ
428 {
429 int flags = 0;
430 if ( IsSelected(n) )
431 flags |= wxCONTROL_SELECTED;
432 if ( IsCurrent(n) )
433 flags |= wxCONTROL_CURRENT;
5c33522f 434 if ( wxWindow::FindFocus() == const_cast<wxVListBox*>(this) )
04125489
VZ
435 flags |= wxCONTROL_FOCUSED;
436
437 wxRendererNative::Get().DrawItemSelectionRect(
5c33522f 438 const_cast<wxVListBox *>(this), dc, rect, flags);
27d0dcd0 439 }
27d0dcd0
VZ
440}
441
442void wxVListBox::OnPaint(wxPaintEvent& WXUNUSED(event))
e0c6027b 443{
0975a8a0
JS
444 wxSize clientSize = GetClientSize();
445
2e992e06 446 wxAutoBufferedPaintDC dc(this);
e0c6027b
VZ
447
448 // the update rectangle
449 wxRect rectUpdate = GetUpdateClientRect();
450
959b1a33
VZ
451 // fill it with background colour
452 dc.SetBackground(GetBackgroundColour());
0975a8a0
JS
453 dc.Clear();
454
e0c6027b 455 // the bounding rectangle of the current line
e02c72fa
VZ
456 wxRect rectRow;
457 rectRow.width = clientSize.x;
e0c6027b
VZ
458
459 // iterate over all visible lines
b1b408af 460 const size_t lineMax = GetVisibleEnd();
e02c72fa 461 for ( size_t line = GetVisibleBegin(); line < lineMax; line++ )
e0c6027b 462 {
e02c72fa 463 const wxCoord hRow = OnGetRowHeight(line);
e0c6027b 464
e02c72fa 465 rectRow.height = hRow;
e0c6027b
VZ
466
467 // and draw the ones which intersect the update rect
e02c72fa 468 if ( rectRow.Intersects(rectUpdate) )
e0c6027b
VZ
469 {
470 // don't allow drawing outside of the lines rectangle
e02c72fa 471 wxDCClipper clip(dc, rectRow);
e0c6027b 472
e02c72fa 473 wxRect rect = rectRow;
27d0dcd0
VZ
474 OnDrawBackground(dc, rect, line);
475
e0c6027b
VZ
476 OnDrawSeparator(dc, rect, line);
477
478 rect.Deflate(m_ptMargins.x, m_ptMargins.y);
479 OnDrawItem(dc, rect, line);
480 }
481 else // no intersection
482 {
e02c72fa 483 if ( rectRow.GetTop() > rectUpdate.GetBottom() )
e0c6027b
VZ
484 {
485 // we are already below the update rect, no need to continue
486 // further
487 break;
488 }
489 //else: the next line may intersect the update rect
490 }
491
e02c72fa 492 rectRow.y += hRow;
e0c6027b
VZ
493 }
494}
495
04125489
VZ
496void wxVListBox::OnSetOrKillFocus(wxFocusEvent& WXUNUSED(event))
497{
498 // we need to repaint the selection when we get the focus since
499 // wxRendererNative in general draws the focused selection differently
500 // from the unfocused selection (see OnDrawItem):
501 RefreshSelected();
502}
503
858ad670
JS
504void wxVListBox::OnSize(wxSizeEvent& event)
505{
506 UpdateScrollbar();
507 event.Skip();
508}
04125489 509
be465555
VZ
510// ============================================================================
511// wxVListBox keyboard/mouse handling
512// ============================================================================
513
970b97a2 514void wxVListBox::DoHandleItemClick(int item, int flags)
be465555
VZ
515{
516 // has anything worth telling the client code about happened?
517 bool notify = false;
518
519 if ( HasMultipleSelection() )
520 {
521 // select the iteem clicked?
522 bool select = true;
523
524 // NB: the keyboard interface we implement here corresponds to
525 // wxLB_EXTENDED rather than wxLB_MULTIPLE but this one makes more
526 // sense IMHO
970b97a2 527 if ( flags & ItemClick_Shift )
be465555
VZ
528 {
529 if ( m_current != wxNOT_FOUND )
530 {
970b97a2
VZ
531 if ( m_anchor == wxNOT_FOUND )
532 m_anchor = m_current;
533
be465555
VZ
534 select = false;
535
970b97a2
VZ
536 // only the range from the selection anchor to new m_current
537 // must be selected
be465555
VZ
538 if ( DeselectAll() )
539 notify = true;
540
970b97a2 541 if ( SelectRange(m_anchor, item) )
be465555
VZ
542 notify = true;
543 }
544 //else: treat it as ordinary click/keypress
545 }
970b97a2 546 else // Shift not pressed
be465555 547 {
970b97a2 548 m_anchor = item;
be465555 549
970b97a2
VZ
550 if ( flags & ItemClick_Ctrl )
551 {
552 select = false;
be465555 553
970b97a2
VZ
554 if ( !(flags & ItemClick_Kbd) )
555 {
556 Toggle(item);
557
558 // the status of the item has definitely changed
559 notify = true;
560 }
561 //else: Ctrl-arrow pressed, don't change selection
562 }
563 //else: behave as in single selection case
be465555 564 }
be465555
VZ
565
566 if ( select )
567 {
568 // make the clicked item the only selection
569 if ( DeselectAll() )
570 notify = true;
571
572 if ( Select(item) )
573 notify = true;
574 }
575 }
576
577 // in any case the item should become the current one
578 if ( DoSetCurrent(item) )
579 {
580 if ( !HasMultipleSelection() )
581 {
582 // this has also changed the selection for single selection case
583 notify = true;
584 }
585 }
586
587 if ( notify )
588 {
589 // notify the user about the selection change
590 SendSelectedEvent();
591 }
592 //else: nothing changed at all
593}
594
e0c6027b 595// ----------------------------------------------------------------------------
be465555 596// keyboard handling
e0c6027b
VZ
597// ----------------------------------------------------------------------------
598
599void wxVListBox::OnKeyDown(wxKeyEvent& event)
600{
970b97a2
VZ
601 // flags for DoHandleItemClick()
602 int flags = ItemClick_Kbd;
603
999836aa 604 int current;
e0c6027b
VZ
605 switch ( event.GetKeyCode() )
606 {
607 case WXK_HOME:
293987e8 608 case WXK_NUMPAD_HOME:
be465555 609 current = 0;
e0c6027b
VZ
610 break;
611
612 case WXK_END:
293987e8 613 case WXK_NUMPAD_END:
e02c72fa 614 current = GetRowCount() - 1;
e0c6027b
VZ
615 break;
616
617 case WXK_DOWN:
293987e8 618 case WXK_NUMPAD_DOWN:
e02c72fa 619 if ( m_current == (int)GetRowCount() - 1 )
e0c6027b
VZ
620 return;
621
be465555 622 current = m_current + 1;
e0c6027b
VZ
623 break;
624
625 case WXK_UP:
293987e8 626 case WXK_NUMPAD_UP:
be465555 627 if ( m_current == wxNOT_FOUND )
e02c72fa 628 current = GetRowCount() - 1;
be465555
VZ
629 else if ( m_current != 0 )
630 current = m_current - 1;
631 else // m_current == 0
e0c6027b
VZ
632 return;
633 break;
634
635 case WXK_PAGEDOWN:
293987e8 636 case WXK_NUMPAD_PAGEDOWN:
e0c6027b 637 PageDown();
e02c72fa 638 current = GetVisibleBegin();
e0c6027b
VZ
639 break;
640
641 case WXK_PAGEUP:
293987e8 642 case WXK_NUMPAD_PAGEUP:
e02c72fa 643 if ( m_current == (int)GetVisibleBegin() )
e0c6027b
VZ
644 {
645 PageUp();
646 }
647
e02c72fa 648 current = GetVisibleBegin();
e0c6027b
VZ
649 break;
650
970b97a2
VZ
651 case WXK_SPACE:
652 // hack: pressing space should work like a mouse click rather than
653 // like a keyboard arrow press, so trick DoHandleItemClick() in
654 // thinking we were clicked
655 flags &= ~ItemClick_Kbd;
656 current = m_current;
657 break;
658
80c700cb
RD
659#ifdef __WXMSW__
660 case WXK_TAB:
661 // Since we are using wxWANTS_CHARS we need to send navigation
662 // events for the tabs on MSW
f029f1d1 663 HandleAsNavigationKey(event);
80c700cb
RD
664 // fall through to default
665#endif
e0c6027b
VZ
666 default:
667 event.Skip();
999836aa 668 current = 0; // just to silent the stupid compiler warnings
8703bc01 669 wxUnusedVar(current);
e0c6027b
VZ
670 return;
671 }
672
970b97a2
VZ
673 if ( event.ShiftDown() )
674 flags |= ItemClick_Shift;
675 if ( event.ControlDown() )
676 flags |= ItemClick_Ctrl;
677
678 DoHandleItemClick(current, flags);
e0c6027b
VZ
679}
680
681// ----------------------------------------------------------------------------
682// wxVListBox mouse handling
683// ----------------------------------------------------------------------------
684
685void wxVListBox::OnLeftDown(wxMouseEvent& event)
686{
c7778877 687 SetFocus();
4e115ed2 688
10368bff 689 int item = VirtualHitTest(event.GetPosition().y);
e0c6027b 690
6c9210a7
VZ
691 if ( item != wxNOT_FOUND )
692 {
970b97a2
VZ
693 int flags = 0;
694 if ( event.ShiftDown() )
695 flags |= ItemClick_Shift;
696
6c9210a7
VZ
697 // under Mac Apple-click is used in the same way as Ctrl-click
698 // elsewhere
be465555 699#ifdef __WXMAC__
970b97a2 700 if ( event.MetaDown() )
be465555 701#else
970b97a2 702 if ( event.ControlDown() )
be465555 703#endif
970b97a2
VZ
704 flags |= ItemClick_Ctrl;
705
706 DoHandleItemClick(item, flags);
6c9210a7 707 }
e0c6027b
VZ
708}
709
4e115ed2 710void wxVListBox::OnLeftDClick(wxMouseEvent& eventMouse)
e0c6027b 711{
10368bff 712 int item = VirtualHitTest(eventMouse.GetPosition().y);
be465555 713 if ( item != wxNOT_FOUND )
e0c6027b 714 {
e0c6027b 715
0975a8a0
JS
716 // if item double-clicked was not yet selected, then treat
717 // this event as a left-click instead
718 if ( item == m_current )
719 {
720 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, GetId());
538483d8 721 InitEvent(event, item);
0975a8a0
JS
722 (void)GetEventHandler()->ProcessEvent(event);
723 }
724 else
725 {
726 OnLeftDown(eventMouse);
727 }
e19ac18a 728
e0c6027b
VZ
729 }
730}
731
dc596072
RD
732
733// ----------------------------------------------------------------------------
734// use the same default attributes as wxListBox
735// ----------------------------------------------------------------------------
736
dc596072
RD
737//static
738wxVisualAttributes
739wxVListBox::GetClassDefaultAttributes(wxWindowVariant variant)
740{
741 return wxListBox::GetClassDefaultAttributes(variant);
742}
179e085f 743
8b939bc0 744#endif