]>
Commit | Line | Data |
---|---|---|
e9576ca5 | 1 | /////////////////////////////////////////////////////////////////////////////// |
c18353e5 | 2 | // Name: src/mac/carbon/checklst.cpp |
e9576ca5 | 3 | // Purpose: implementation of wxCheckListBox class |
a31a5f85 | 4 | // Author: Stefan Csomor |
3dee36ae | 5 | // Modified by: |
a31a5f85 | 6 | // Created: 1998-01-01 |
e9576ca5 | 7 | // RCS-ID: $Id$ |
a31a5f85 | 8 | // Copyright: (c) Stefan Csomor |
65571936 | 9 | // Licence: wxWindows licence |
e9576ca5 | 10 | /////////////////////////////////////////////////////////////////////////////// |
c18353e5 DS |
11 | // |
12 | // new DataBrowser-based version | |
e9576ca5 | 13 | |
e9576ca5 | 14 | |
a8e9860d | 15 | #include "wx/wxprec.h" |
e9576ca5 | 16 | |
55d60746 GD |
17 | #if wxUSE_CHECKLISTBOX |
18 | ||
b698c8e9 | 19 | #include "wx/checklst.h" |
584ad2a3 | 20 | #include "wx/arrstr.h" |
b698c8e9 | 21 | |
dbfc5b97 | 22 | #include "wx/mac/uma.h" |
c18353e5 | 23 | |
768c6e8b | 24 | #ifndef __DARWIN__ |
7f0c3a63 | 25 | #include <Appearance.h> |
768c6e8b | 26 | #endif |
dbfc5b97 | 27 | |
dbfc5b97 SC |
28 | IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox) |
29 | ||
d058c153 SC |
30 | BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox) |
31 | END_EVENT_TABLE() | |
dbfc5b97 | 32 | |
c18353e5 DS |
33 | const short kTextColumnId = 1024; |
34 | const short kCheckboxColumnId = 1025; | |
dbfc5b97 | 35 | |
dbfc5b97 SC |
36 | |
37 | void wxCheckListBox::Init() | |
38 | { | |
39 | } | |
40 | ||
c18353e5 DS |
41 | bool wxCheckListBox::Create( |
42 | wxWindow *parent, | |
43 | wxWindowID id, | |
44 | const wxPoint &pos, | |
45 | const wxSize &size, | |
46 | const wxArrayString& choices, | |
47 | long style, | |
48 | const wxValidator& validator, | |
49 | const wxString &name ) | |
584ad2a3 | 50 | { |
c18353e5 | 51 | wxCArrayString chs( choices ); |
584ad2a3 | 52 | |
c18353e5 | 53 | return Create( parent, id, pos, size, chs.GetCount(), chs.GetStrings(), style, validator, name ); |
584ad2a3 MB |
54 | } |
55 | ||
d058c153 | 56 | #if TARGET_API_MAC_OSX |
c18353e5 DS |
57 | static pascal void DataBrowserItemNotificationProc( |
58 | ControlRef browser, | |
59 | DataBrowserItemID itemID, | |
60 | DataBrowserItemNotification message, | |
61 | DataBrowserItemDataRef itemData ) | |
d058c153 | 62 | #else |
c18353e5 DS |
63 | static pascal void DataBrowserItemNotificationProc( |
64 | ControlRef browser, | |
65 | DataBrowserItemID itemID, | |
66 | DataBrowserItemNotification message ) | |
d058c153 SC |
67 | #endif |
68 | { | |
c18353e5 DS |
69 | long ref = GetControlReference( browser ); |
70 | if (ref != 0) | |
d058c153 | 71 | { |
c18353e5 DS |
72 | wxCheckListBox* list = wxDynamicCast( (wxObject*)ref, wxCheckListBox ); |
73 | int i = itemID - 1; | |
74 | if ((i >= 0) && (i < (int)list->GetCount())) | |
683e36bc | 75 | { |
c18353e5 DS |
76 | bool trigger = false; |
77 | wxCommandEvent event( wxEVT_COMMAND_LISTBOX_SELECTED, list->GetId() ); | |
78 | switch ( message ) | |
d058c153 | 79 | { |
c18353e5 | 80 | case kDataBrowserItemDeselected: |
683e36bc | 81 | if ( list->HasMultipleSelection() ) |
c18353e5 DS |
82 | trigger = true; |
83 | break; | |
84 | ||
85 | case kDataBrowserItemSelected: | |
86 | trigger = true; | |
87 | break; | |
88 | ||
89 | case kDataBrowserItemDoubleClicked: | |
90 | event.SetEventType( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED ); | |
91 | trigger = true; | |
92 | break; | |
93 | ||
94 | default: | |
95 | break; | |
d058c153 | 96 | } |
683e36bc SC |
97 | |
98 | if ( trigger ) | |
99 | { | |
100 | event.SetEventObject( list ); | |
101 | if ( list->HasClientObjectData() ) | |
c18353e5 | 102 | event.SetClientObject( list->GetClientObject( i ) ); |
683e36bc | 103 | else if ( list->HasClientUntypedData() ) |
c18353e5 DS |
104 | event.SetClientData( list->GetClientData( i ) ); |
105 | event.SetString( list->GetString( i ) ); | |
106 | event.SetInt( i ); | |
107 | event.SetExtraLong( list->HasMultipleSelection() ? message == kDataBrowserItemSelected : true ); | |
108 | wxPostEvent( list->GetEventHandler(), event ); | |
109 | ||
110 | // direct notification is not always having the listbox GetSelection() having in sync with event | |
111 | // list->GetEventHandler()->ProcessEvent( event ); | |
3dee36ae | 112 | } |
683e36bc | 113 | } |
d058c153 SC |
114 | } |
115 | } | |
116 | ||
c18353e5 DS |
117 | static pascal OSStatus ListBoxGetSetItemData( |
118 | ControlRef browser, | |
119 | DataBrowserItemID itemID, | |
120 | DataBrowserPropertyID property, | |
121 | DataBrowserItemDataRef itemData, | |
122 | Boolean changeValue ) | |
d058c153 | 123 | { |
3dee36ae WS |
124 | OSStatus err = errDataBrowserPropertyNotSupported; |
125 | ||
c18353e5 | 126 | if ( !changeValue ) |
3dee36ae WS |
127 | { |
128 | switch (property) | |
129 | { | |
3dee36ae WS |
130 | case kTextColumnId: |
131 | { | |
c18353e5 DS |
132 | long ref = GetControlReference( browser ); |
133 | if (ref != 0) | |
3dee36ae | 134 | { |
c18353e5 DS |
135 | wxCheckListBox* list = wxDynamicCast( (wxObject*) ref, wxCheckListBox ); |
136 | int i = itemID - 1; | |
137 | if ((i >= 0) && (i < (int)list->GetCount())) | |
3dee36ae | 138 | { |
c18353e5 DS |
139 | wxMacCFStringHolder cf( list->GetString( i ), list->GetFont().GetEncoding() ); |
140 | verify_noerr( ::SetDataBrowserItemDataText( itemData, cf ) ); | |
141 | err = noErr; | |
3dee36ae WS |
142 | } |
143 | } | |
144 | } | |
145 | break; | |
c18353e5 DS |
146 | |
147 | case kCheckboxColumnId: | |
3dee36ae | 148 | { |
c18353e5 DS |
149 | long ref = GetControlReference( browser ); |
150 | if (ref != 0) | |
3dee36ae | 151 | { |
c18353e5 DS |
152 | wxCheckListBox* list = wxDynamicCast( (wxObject*)ref, wxCheckListBox ); |
153 | int i = itemID - 1; | |
154 | if ((i >= 0) && (i < (int)list->GetCount())) | |
3dee36ae | 155 | { |
aa61d352 | 156 | verify_noerr( ::SetDataBrowserItemDataButtonValue( itemData, list->IsChecked(i) ? kThemeButtonOn : kThemeButtonOff ) ); |
c18353e5 | 157 | err = noErr; |
3dee36ae WS |
158 | } |
159 | } | |
160 | } | |
c18353e5 DS |
161 | break; |
162 | ||
3dee36ae WS |
163 | case kDataBrowserItemIsEditableProperty: |
164 | { | |
c18353e5 | 165 | err = ::SetDataBrowserItemDataBooleanValue( itemData, true ); |
3dee36ae WS |
166 | } |
167 | break; | |
168 | ||
169 | default: | |
170 | break; | |
171 | } | |
172 | } | |
173 | else | |
174 | { | |
c18353e5 | 175 | switch ( property ) |
3dee36ae | 176 | { |
c18353e5 | 177 | case kCheckboxColumnId: |
3dee36ae | 178 | { |
c18353e5 DS |
179 | long ref = GetControlReference( browser ); |
180 | if (ref != 0) | |
3dee36ae | 181 | { |
c18353e5 DS |
182 | wxCheckListBox* list = wxDynamicCast( (wxObject*) ref, wxCheckListBox ); |
183 | int i = itemID - 1; | |
184 | if ((i >= 0) && (i < (int)list->GetCount())) | |
3dee36ae WS |
185 | { |
186 | // we have to change this behind the back, since Check() would be triggering another update round | |
aa61d352 | 187 | bool newVal = !list->IsChecked(i); |
c18353e5 DS |
188 | verify_noerr( ::SetDataBrowserItemDataButtonValue( itemData, newVal ? kThemeButtonOn : kThemeButtonOff ) ); |
189 | err = noErr; | |
190 | list->m_checks[i] = newVal; | |
683e36bc SC |
191 | |
192 | wxCommandEvent event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, list->GetId()); | |
c18353e5 DS |
193 | event.SetInt( i ); |
194 | event.SetEventObject( list ); | |
195 | list->GetEventHandler()->ProcessEvent( event ); | |
3dee36ae WS |
196 | } |
197 | } | |
3dee36ae | 198 | } |
c18353e5 | 199 | break; |
3dee36ae | 200 | |
c18353e5 DS |
201 | default: |
202 | break; | |
3dee36ae WS |
203 | } |
204 | } | |
205 | ||
206 | return err; | |
d058c153 | 207 | } |
c18353e5 DS |
208 | |
209 | bool wxCheckListBox::Create( | |
210 | wxWindow *parent, | |
211 | wxWindowID id, | |
212 | const wxPoint& pos, | |
213 | const wxSize& size, | |
214 | int n, | |
215 | const wxString choices[], | |
216 | long style, | |
217 | const wxValidator& validator, | |
218 | const wxString& name ) | |
dbfc5b97 | 219 | { |
c18353e5 | 220 | m_macIsUserPane = false; |
d058c153 SC |
221 | |
222 | wxASSERT_MSG( !(style & wxLB_MULTIPLE) || !(style & wxLB_EXTENDED), | |
c18353e5 | 223 | wxT("only one of listbox selection modes can be specified") ); |
3dee36ae | 224 | |
c18353e5 | 225 | if ( !wxListBoxBase::Create( parent, id, pos, size, style & ~(wxHSCROLL | wxVSCROLL), validator, name ) ) |
b45ed7a2 VZ |
226 | return false; |
227 | ||
c18353e5 DS |
228 | // this will be increased by our Append command |
229 | m_noItems = 0; | |
dbfc5b97 | 230 | m_selected = 0; |
facd6764 | 231 | |
c18353e5 | 232 | Rect bounds = wxMacGetBoundsForControl( this, pos, size ); |
dbfc5b97 | 233 | |
c18353e5 DS |
234 | m_peer = new wxMacControl( this ); |
235 | OSStatus err = ::CreateDataBrowserControl( | |
236 | MAC_WXHWND(parent->MacGetTopLevelWindowRef()), | |
237 | &bounds, kDataBrowserListView, m_peer->GetControlRefAddr() ); | |
238 | verify_noerr( err ); | |
3dee36ae | 239 | |
c18353e5 | 240 | DataBrowserSelectionFlags options = kDataBrowserDragSelect; |
dbfc5b97 SC |
241 | if ( style & wxLB_MULTIPLE ) |
242 | { | |
c18353e5 | 243 | options |= kDataBrowserAlwaysExtendSelection | kDataBrowserCmdTogglesSelection; |
dbfc5b97 SC |
244 | } |
245 | else if ( style & wxLB_EXTENDED ) | |
246 | { | |
d058c153 | 247 | // default behaviour |
dbfc5b97 SC |
248 | } |
249 | else | |
250 | { | |
c18353e5 | 251 | options |= kDataBrowserSelectOnlyOne; |
dbfc5b97 | 252 | } |
d058c153 | 253 | |
c18353e5 DS |
254 | err = m_peer->SetSelectionFlags( options ); |
255 | verify_noerr( err ); | |
256 | ||
257 | DataBrowserListViewColumnDesc columnDesc; | |
d058c153 | 258 | columnDesc.headerBtnDesc.titleOffset = 0; |
3dee36ae WS |
259 | columnDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc; |
260 | ||
261 | columnDesc.headerBtnDesc.btnFontStyle.flags = | |
262 | kControlUseFontMask | kControlUseJustMask; | |
263 | ||
264 | columnDesc.headerBtnDesc.btnContentInfo.contentType = kControlNoContent; | |
265 | columnDesc.headerBtnDesc.btnFontStyle.just = teFlushDefault; | |
266 | columnDesc.headerBtnDesc.btnFontStyle.font = kControlFontViewSystemFont; | |
267 | columnDesc.headerBtnDesc.btnFontStyle.style = normal; | |
c18353e5 | 268 | columnDesc.headerBtnDesc.titleString = NULL; // CFSTR( "" ); |
d058c153 SC |
269 | |
270 | // check column | |
271 | ||
c18353e5 | 272 | columnDesc.headerBtnDesc.minimumWidth = 30; |
3dee36ae | 273 | columnDesc.headerBtnDesc.maximumWidth = 30; |
d058c153 | 274 | |
3dee36ae WS |
275 | columnDesc.propertyDesc.propertyID = kCheckboxColumnId; |
276 | columnDesc.propertyDesc.propertyType = kDataBrowserCheckboxType; | |
c18353e5 DS |
277 | columnDesc.propertyDesc.propertyFlags = |
278 | kDataBrowserPropertyIsMutable | |
279 | | kDataBrowserTableViewSelectionColumn | |
280 | | kDataBrowserDefaultPropertyFlags; | |
281 | err = m_peer->AddListViewColumn( &columnDesc, kDataBrowserListViewAppendColumn ); | |
282 | verify_noerr( err ); | |
d058c153 SC |
283 | |
284 | // text column | |
285 | ||
3dee36ae WS |
286 | columnDesc.headerBtnDesc.minimumWidth = 0; |
287 | columnDesc.headerBtnDesc.maximumWidth = 10000; | |
d058c153 | 288 | |
3dee36ae WS |
289 | columnDesc.propertyDesc.propertyID = kTextColumnId; |
290 | columnDesc.propertyDesc.propertyType = kDataBrowserTextType; | |
291 | columnDesc.propertyDesc.propertyFlags = kDataBrowserTableViewSelectionColumn | |
d058c153 | 292 | #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 |
3dee36ae | 293 | | kDataBrowserListViewTypeSelectColumn |
d058c153 | 294 | #endif |
3dee36ae WS |
295 | ; |
296 | ||
c18353e5 | 297 | verify_noerr( m_peer->AddListViewColumn( &columnDesc, kDataBrowserListViewAppendColumn ) ); |
d058c153 | 298 | |
c18353e5 DS |
299 | verify_noerr( m_peer->AutoSizeListViewColumns() ); |
300 | verify_noerr( m_peer->SetHasScrollBars( false, true ) ); | |
301 | verify_noerr( m_peer->SetTableViewHiliteStyle( kDataBrowserTableViewFillHilite ) ); | |
302 | verify_noerr( m_peer->SetListViewHeaderBtnHeight( 0 ) ); | |
d058c153 | 303 | |
c18353e5 | 304 | DataBrowserCallbacks callbacks; |
d058c153 | 305 | callbacks.version = kDataBrowserLatestCallbacks; |
c18353e5 DS |
306 | InitDataBrowserCallbacks( &callbacks ); |
307 | callbacks.u.v1.itemDataCallback = NewDataBrowserItemDataUPP( &ListBoxGetSetItemData ); | |
3dee36ae | 308 | callbacks.u.v1.itemNotificationCallback = |
d058c153 | 309 | #if TARGET_API_MAC_OSX |
c18353e5 | 310 | (DataBrowserItemNotificationUPP) NewDataBrowserItemNotificationWithItemUPP( &DataBrowserItemNotificationProc ); |
d058c153 | 311 | #else |
c18353e5 | 312 | NewDataBrowserItemNotificationUPP( &DataBrowserItemNotificationProc ); |
d058c153 | 313 | #endif |
c18353e5 | 314 | m_peer->SetCallbacks( &callbacks ); |
d058c153 | 315 | |
789ae0cf SC |
316 | #if 0 |
317 | // shouldn't be necessary anymore under 10.2 | |
c18353e5 DS |
318 | m_peer->SetData( kControlNoPart, kControlDataBrowserIncludesFrameAndFocusTag, (Boolean)false ); |
319 | m_peer->SetNeedsFocusRect( true ); | |
789ae0cf SC |
320 | #endif |
321 | ||
c18353e5 | 322 | MacPostControlCreate( pos, size ); |
d058c153 | 323 | |
c18353e5 | 324 | for ( int i = 0; i < n; i++ ) |
dbfc5b97 | 325 | { |
c18353e5 | 326 | Append( choices[i] ); |
dbfc5b97 | 327 | } |
dbfc5b97 | 328 | |
c18353e5 DS |
329 | // Needed because it is a wxControlWithItems |
330 | SetBestSize( size ); | |
3dee36ae WS |
331 | |
332 | return true; | |
dbfc5b97 | 333 | } |
e9576ca5 SC |
334 | |
335 | // ---------------------------------------------------------------------------- | |
dbfc5b97 | 336 | // wxCheckListBox functions |
e9576ca5 SC |
337 | // ---------------------------------------------------------------------------- |
338 | ||
aa61d352 | 339 | bool wxCheckListBox::IsChecked(unsigned int item) const |
dbfc5b97 | 340 | { |
aa61d352 | 341 | wxCHECK_MSG( IsValid(item), false, |
c18353e5 | 342 | wxT("invalid index in wxCheckListBox::IsChecked") ); |
dbfc5b97 SC |
343 | |
344 | return m_checks[item] != 0; | |
345 | } | |
346 | ||
aa61d352 | 347 | void wxCheckListBox::Check(unsigned int item, bool check) |
dbfc5b97 | 348 | { |
aa61d352 | 349 | wxCHECK_RET( IsValid(item), |
c18353e5 | 350 | wxT("invalid index in wxCheckListBox::Check") ); |
dbfc5b97 | 351 | |
dbfc5b97 SC |
352 | bool isChecked = m_checks[item] != 0; |
353 | if ( check != isChecked ) | |
354 | { | |
355 | m_checks[item] = check; | |
c18353e5 DS |
356 | UInt32 id = item + 1; |
357 | OSStatus err = m_peer->UpdateItems( | |
358 | kDataBrowserNoItem, 1, &id, | |
359 | kDataBrowserItemNoProperty, kDataBrowserItemNoProperty ); | |
360 | verify_noerr( err ); | |
dbfc5b97 SC |
361 | } |
362 | } | |
363 | ||
364 | // ---------------------------------------------------------------------------- | |
d058c153 | 365 | // methods forwarded to wxCheckListBox |
dbfc5b97 SC |
366 | // ---------------------------------------------------------------------------- |
367 | ||
aa61d352 | 368 | void wxCheckListBox::Delete(unsigned int n) |
dbfc5b97 | 369 | { |
aa61d352 | 370 | wxCHECK_RET( IsValid(n), wxT("invalid index in wxCheckListBox::Delete") ); |
e9576ca5 | 371 | |
c18353e5 DS |
372 | wxListBox::Delete( n ); |
373 | m_checks.RemoveAt( n ); | |
dbfc5b97 SC |
374 | } |
375 | ||
376 | int wxCheckListBox::DoAppend(const wxString& item) | |
e9576ca5 | 377 | { |
c18353e5 | 378 | int pos = wxListBox::DoAppend( item ); |
dbfc5b97 SC |
379 | |
380 | // the item is initially unchecked | |
c18353e5 | 381 | m_checks.Insert( false, pos ); |
dbfc5b97 SC |
382 | |
383 | return pos; | |
e9576ca5 SC |
384 | } |
385 | ||
aa61d352 | 386 | void wxCheckListBox::DoInsertItems(const wxArrayString& items, unsigned int pos) |
e9576ca5 | 387 | { |
c18353e5 | 388 | wxListBox::DoInsertItems( items, pos ); |
dbfc5b97 | 389 | |
aa61d352 VZ |
390 | unsigned int count = items.GetCount(); |
391 | for ( unsigned int n = 0; n < count; n++ ) | |
dbfc5b97 | 392 | { |
c18353e5 | 393 | m_checks.Insert( false, pos + n ); |
dbfc5b97 | 394 | } |
e9576ca5 SC |
395 | } |
396 | ||
dbfc5b97 SC |
397 | void wxCheckListBox::DoSetItems(const wxArrayString& items, void **clientData) |
398 | { | |
399 | // call it first as it does DoClear() | |
c18353e5 | 400 | wxListBox::DoSetItems( items, clientData ); |
dbfc5b97 | 401 | |
aa61d352 VZ |
402 | unsigned int count = items.GetCount(); |
403 | for ( unsigned int n = 0; n < count; n++ ) | |
dbfc5b97 | 404 | { |
c18353e5 | 405 | m_checks.Add( false ); |
dbfc5b97 SC |
406 | } |
407 | } | |
e9576ca5 | 408 | |
dbfc5b97 | 409 | void wxCheckListBox::DoClear() |
e9576ca5 | 410 | { |
dbfc5b97 | 411 | m_checks.Empty(); |
e9576ca5 SC |
412 | } |
413 | ||
dbfc5b97 | 414 | #endif // wxUSE_CHECKLISTBOX |