1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/lboxcmn.cpp
3 // Purpose: wxListBox class methods common to all platforms
4 // Author: Vadim Zeitlin
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
29 #include "wx/listbox.h"
32 #include "wx/dynarray.h"
33 #include "wx/arrstr.h"
38 // ============================================================================
40 // ============================================================================
42 wxListBoxBase::~wxListBoxBase()
44 // this destructor is required for Darwin
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
51 bool wxListBoxBase::SetStringSelection(const wxString
& s
, bool select
)
53 const int sel
= FindString(s
);
54 if ( sel
== wxNOT_FOUND
)
57 SetSelection(sel
, select
);
62 void wxListBoxBase::SetSelection(int n
)
64 if ( !HasMultipleSelection() )
65 DoChangeSingleSelection(n
);
67 DoSetSelection(n
, true);
70 void wxListBoxBase::DeselectAll(int itemToLeaveSelected
)
72 if ( HasMultipleSelection() )
74 wxArrayInt selections
;
75 GetSelections(selections
);
77 size_t count
= selections
.GetCount();
78 for ( size_t n
= 0; n
< count
; n
++ )
80 int item
= selections
[n
];
81 if ( item
!= itemToLeaveSelected
)
85 else // single selection
87 int sel
= GetSelection();
88 if ( sel
!= wxNOT_FOUND
&& sel
!= itemToLeaveSelected
)
95 void wxListBoxBase::UpdateOldSelections()
97 // We need to remember the selection even in single-selection case on
98 // Windows, so that we don't send an event when the user clicks on an
99 // already selected item.
101 if (HasFlag(wxLB_MULTIPLE
) || HasFlag(wxLB_EXTENDED
))
104 GetSelections( m_oldSelections
);
108 bool wxListBoxBase::SendEvent(wxEventType evtType
, int item
, bool selected
)
110 wxCommandEvent
event(evtType
, GetId());
111 event
.SetEventObject(this);
114 event
.SetString(GetString(item
));
115 event
.SetExtraLong(selected
);
117 if ( HasClientObjectData() )
118 event
.SetClientObject(GetClientObject(item
));
119 else if ( HasClientUntypedData() )
120 event
.SetClientData(GetClientData(item
));
122 return HandleWindowEvent(event
);
125 bool wxListBoxBase::DoChangeSingleSelection(int item
)
127 // As we don't use m_oldSelections in single selection mode, we store the
128 // last item that we notified the user about in it in this case because we
129 // need to remember it to be able to filter out the dummy selection changes
130 // that we get when the user clicks on an already selected item.
131 if ( !m_oldSelections
.empty() && *m_oldSelections
.begin() == item
)
133 // Same item as the last time.
137 m_oldSelections
.clear();
138 m_oldSelections
.push_back(item
);
143 bool wxListBoxBase::CalcAndSendEvent()
145 wxArrayInt selections
;
146 GetSelections(selections
);
147 bool selected
= true;
149 if ( selections
.empty() && m_oldSelections
.empty() )
151 // nothing changed, just leave
155 const size_t countSel
= selections
.size(),
156 countSelOld
= m_oldSelections
.size();
157 if ( countSel
== countSelOld
)
159 bool changed
= false;
160 for ( size_t idx
= 0; idx
< countSel
; idx
++ )
162 if (selections
[idx
] != m_oldSelections
[idx
])
169 // nothing changed, just leave
174 int item
= wxNOT_FOUND
;
175 if ( selections
.empty() )
178 item
= m_oldSelections
[0];
180 else // we [still] have some selections
182 // Now test if any new item is selected
183 bool any_new_selected
= false;
184 for ( size_t idx
= 0; idx
< countSel
; idx
++ )
186 item
= selections
[idx
];
187 if ( m_oldSelections
.Index(item
) == wxNOT_FOUND
)
189 any_new_selected
= true;
194 if ( !any_new_selected
)
196 // No new items selected, now test if any new item is deselected
197 bool any_new_deselected
= false;
198 for ( size_t idx
= 0; idx
< countSelOld
; idx
++ )
200 item
= m_oldSelections
[idx
];
201 if ( selections
.Index(item
) == wxNOT_FOUND
)
203 any_new_deselected
= true;
208 if ( any_new_deselected
)
210 // indicate that this is a selection
215 item
= wxNOT_FOUND
; // this should be impossible
220 wxASSERT_MSG( item
!= wxNOT_FOUND
,
221 "Logic error in wxListBox selection event generation code" );
223 m_oldSelections
= selections
;
225 return SendEvent(wxEVT_COMMAND_LISTBOX_SELECTED
, item
, selected
);
228 // ----------------------------------------------------------------------------
230 // ----------------------------------------------------------------------------
232 void wxListBoxBase::Command(wxCommandEvent
& event
)
234 SetSelection(event
.GetInt(), event
.GetExtraLong() != 0);
235 (void)GetEventHandler()->ProcessEvent(event
);
238 // ----------------------------------------------------------------------------
239 // SetFirstItem() and such
240 // ----------------------------------------------------------------------------
242 void wxListBoxBase::SetFirstItem(const wxString
& s
)
244 int n
= FindString(s
);
246 wxCHECK_RET( n
!= wxNOT_FOUND
, wxT("invalid string in wxListBox::SetFirstItem") );
251 void wxListBoxBase::AppendAndEnsureVisible(const wxString
& s
)
254 EnsureVisible(GetCount() - 1);
257 void wxListBoxBase::EnsureVisible(int WXUNUSED(n
))
259 // the base class version does nothing (the only alternative would be to
260 // call SetFirstItem() but this is probably even more stupid)
263 #endif // wxUSE_LISTBOX