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