]>
Commit | Line | Data |
---|---|---|
e9576ca5 | 1 | /////////////////////////////////////////////////////////////////////////////// |
11e62fe6 | 2 | // Name: src/mac/carbon/listbox.cpp |
e9576ca5 | 3 | // Purpose: wxListBox |
a31a5f85 | 4 | // Author: Stefan Csomor |
e9576ca5 | 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 SC |
10 | /////////////////////////////////////////////////////////////////////////////// |
11 | ||
3d1a4878 SC |
12 | #include "wx/wxprec.h" |
13 | ||
179e085f RN |
14 | #if wxUSE_LISTBOX |
15 | ||
03e11df5 | 16 | #include "wx/app.h" |
e9576ca5 | 17 | #include "wx/listbox.h" |
b4726a58 | 18 | #include "wx/checklst.h" |
dc0ace7c | 19 | #include "wx/button.h" |
e9576ca5 | 20 | #include "wx/settings.h" |
422644a3 | 21 | #include "wx/toplevel.h" |
e9576ca5 SC |
22 | #include "wx/dynarray.h" |
23 | #include "wx/log.h" | |
24 | ||
519cb848 | 25 | #include "wx/utils.h" |
519cb848 | 26 | |
b4726a58 SC |
27 | IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl) |
28 | ||
29 | BEGIN_EVENT_TABLE(wxListBox, wxControl) | |
30 | END_EVENT_TABLE() | |
31 | ||
fdd4e6cc DS |
32 | #include "wx/mac/uma.h" |
33 | ||
b4726a58 SC |
34 | // common interface for all implementations |
35 | class wxMacListControl : public wxMacControl | |
36 | { | |
cee24bf7 | 37 | public: |
520b09fc DS |
38 | wxMacListControl( wxListBox *peer ) |
39 | : wxMacControl( peer ) | |
b4726a58 SC |
40 | { |
41 | } | |
cee24bf7 DS |
42 | |
43 | ~wxMacListControl() | |
b4726a58 | 44 | { |
b4726a58 | 45 | } |
fdd4e6cc | 46 | |
b4726a58 | 47 | virtual void UpdateLine( int n ) = 0; |
cee24bf7 | 48 | |
b4726a58 | 49 | virtual void MacDelete( int n ) = 0; |
520b09fc DS |
50 | virtual void MacInsert( int n, const wxString& item ) = 0; |
51 | virtual void MacInsert( int n, const wxArrayString& items ) = 0; | |
52 | virtual void MacAppend( const wxString& item ) = 0; | |
cee24bf7 DS |
53 | virtual void MacSet( int n, const wxString& item ) = 0; |
54 | virtual void MacClear() = 0; | |
55 | virtual void MacDeselectAll() = 0; | |
56 | virtual void MacSetSelection( int n, bool select ) = 0; | |
57 | virtual int MacGetSelection() const = 0; | |
520b09fc DS |
58 | virtual int MacGetSelections( wxArrayInt& aSelections ) const = 0; |
59 | virtual bool MacIsSelected( int n ) const = 0; | |
cee24bf7 | 60 | virtual void MacScrollTo( int n ) = 0; |
b4726a58 | 61 | |
cee24bf7 | 62 | wxListBox * GetPeer() const |
520b09fc | 63 | { return (wxListBox*)m_peer; } |
b4726a58 | 64 | }; |
fdd4e6cc | 65 | |
cee24bf7 | 66 | #if 0 |
b4726a58 | 67 | // In case we have to replace data browser ... |
cee24bf7 | 68 | // custom HIView-based implementation |
fdd4e6cc | 69 | |
b4726a58 SC |
70 | class wxMacCustomHIViewListControl : public wxMacListControl |
71 | { | |
cee24bf7 DS |
72 | public: |
73 | wxMacCustomHIViewListControl( wxListBox *peer, const wxPoint& pos, const wxSize& size, long style ); | |
b4726a58 SC |
74 | ~wxMacCustomHIViewListControl(); |
75 | ||
76 | void MacDelete( int n ); | |
520b09fc DS |
77 | void MacInsert( int n, const wxString& item ); |
78 | void MacInsert( int n, const wxArrayString& items ); | |
79 | void MacAppend( const wxString& item ); | |
cee24bf7 | 80 | void MacSet( int n, const wxString& item ); |
b4726a58 SC |
81 | void MacClear(); |
82 | void MacDeselectAll(); | |
cee24bf7 | 83 | void MacSetSelection( int n, bool select ); |
b4726a58 | 84 | int MacGetSelection() const; |
520b09fc | 85 | int MacGetSelections( wxArrayInt& aSelections ) const; |
b4726a58 SC |
86 | bool MacIsSelected( int n ) const; |
87 | void MacScrollTo( int n ); | |
88 | }; | |
89 | #endif | |
519cb848 | 90 | |
cee24bf7 | 91 | // DataBrowser-based implementation |
b4726a58 SC |
92 | |
93 | class wxMacDataBrowserListControl : public wxMacListControl | |
94 | { | |
cee24bf7 DS |
95 | public: |
96 | wxMacDataBrowserListControl( wxListBox *peer, const wxPoint& pos, const wxSize& size, long style ); | |
b4726a58 SC |
97 | ~wxMacDataBrowserListControl(); |
98 | ||
99 | void UpdateLine( int n ); | |
100 | ||
101 | void MacDelete( int n ); | |
520b09fc DS |
102 | void MacInsert( int n, const wxString& item ); |
103 | void MacInsert( int n, const wxArrayString& items ); | |
104 | void MacAppend( const wxString& item ); | |
cee24bf7 | 105 | void MacSet( int n, const wxString& item ); |
b4726a58 SC |
106 | void MacClear(); |
107 | void MacDeselectAll(); | |
cee24bf7 | 108 | void MacSetSelection( int n, bool select ); |
b4726a58 | 109 | int MacGetSelection() const; |
520b09fc | 110 | int MacGetSelections( wxArrayInt& aSelections ) const; |
b4726a58 SC |
111 | bool MacIsSelected( int n ) const; |
112 | void MacScrollTo( int n ); | |
113 | ||
114 | virtual OSStatus SetSelectionFlags( DataBrowserSelectionFlags ); | |
115 | virtual OSStatus AddListViewColumn( DataBrowserListViewColumnDesc *columnDesc, | |
116 | DataBrowserTableViewColumnIndex position ); | |
117 | virtual OSStatus AutoSizeListViewColumns(); | |
cee24bf7 | 118 | virtual OSStatus SetHasScrollBars( bool horiz, bool vert ); |
b4726a58 | 119 | virtual OSStatus SetTableViewHiliteStyle( DataBrowserTableViewHiliteStyle hiliteStyle ); |
520b09fc DS |
120 | virtual OSStatus SetListViewHeaderBtnHeight( UInt16 height ); |
121 | virtual OSStatus SetCallbacks( const DataBrowserCallbacks *callbacks ); | |
b4726a58 | 122 | virtual OSStatus UpdateItems( DataBrowserItemID container, UInt32 numItems, |
cee24bf7 | 123 | const DataBrowserItemID *items, |
b4726a58 SC |
124 | DataBrowserPropertyID preSortProperty, |
125 | DataBrowserPropertyID propertyID ); | |
126 | virtual OSStatus AddItems( DataBrowserItemID container, UInt32 numItems, | |
cee24bf7 | 127 | const DataBrowserItemID *items, |
b4726a58 SC |
128 | DataBrowserPropertyID preSortProperty ); |
129 | virtual OSStatus RemoveItems( DataBrowserItemID container, UInt32 numItems, | |
cee24bf7 | 130 | const DataBrowserItemID *items, |
b4726a58 SC |
131 | DataBrowserPropertyID preSortProperty ); |
132 | virtual OSStatus RevealItem( DataBrowserItemID item, | |
133 | DataBrowserPropertyID propertyID, | |
134 | DataBrowserRevealOptions options ); | |
cee24bf7 | 135 | virtual OSStatus GetSelectionAnchor( DataBrowserItemID *first, DataBrowserItemID *last ) const; |
b4726a58 | 136 | virtual bool IsItemSelected( DataBrowserItemID item ) const; |
520b09fc | 137 | virtual OSStatus SetSelectedItems( UInt32 numItems, |
cee24bf7 | 138 | const DataBrowserItemID *items, |
b4726a58 SC |
139 | DataBrowserSetOption operation ); |
140 | ||
cee24bf7 | 141 | private: |
b4726a58 SC |
142 | // as we are getting the same events for human and API selection we have to suppress |
143 | // events in the latter case | |
cee24bf7 DS |
144 | bool MacSuppressSelection( bool suppress ); |
145 | bool MacIsSelectionSuppressed() const { return m_suppressSelection; } | |
146 | ||
147 | bool m_suppressSelection; | |
b4726a58 SC |
148 | |
149 | #if TARGET_API_MAC_OSX | |
cee24bf7 DS |
150 | static pascal void DataBrowserItemNotificationProc( |
151 | ControlRef browser, | |
152 | DataBrowserItemID itemID, | |
153 | DataBrowserItemNotification message, | |
154 | DataBrowserItemDataRef itemData ); | |
b4726a58 | 155 | #else |
cee24bf7 DS |
156 | static pascal void DataBrowserItemNotificationProc( |
157 | ControlRef browser, | |
158 | DataBrowserItemID itemID, | |
159 | DataBrowserItemNotification message ); | |
facd6764 | 160 | #endif |
b4726a58 SC |
161 | }; |
162 | ||
163 | // ============================================================================ | |
164 | // data browser based implementation | |
165 | // ============================================================================ | |
e9576ca5 | 166 | |
b4726a58 SC |
167 | const short kTextColumnId = 1024; |
168 | const short kCheckboxColumnId = 1025; | |
facd6764 | 169 | |
520b09fc | 170 | // new DataBrowser-based version |
b4726a58 SC |
171 | // because of the limited insert |
172 | // functionality of DataBrowser, | |
520b09fc | 173 | // we just introduce IDs corresponding |
b4726a58 | 174 | // to the line number |
789ae0cf | 175 | |
b4726a58 SC |
176 | DataBrowserItemDataUPP gDataBrowserItemDataUPP = NULL; |
177 | DataBrowserItemNotificationUPP gDataBrowserItemNotificationUPP = NULL; | |
fdd4e6cc | 178 | |
83ce5634 | 179 | #if TARGET_API_MAC_OSX |
cee24bf7 DS |
180 | pascal void wxMacDataBrowserListControl::DataBrowserItemNotificationProc( |
181 | ControlRef browser, | |
182 | DataBrowserItemID itemID, | |
183 | DataBrowserItemNotification message, | |
520b09fc | 184 | DataBrowserItemDataRef itemData ) |
83ce5634 | 185 | #else |
cee24bf7 DS |
186 | pascal void wxMacDataBrowserListControl::DataBrowserItemNotificationProc( |
187 | ControlRef browser, | |
188 | DataBrowserItemID itemID, | |
520b09fc | 189 | DataBrowserItemNotification message ) |
83ce5634 SC |
190 | #endif |
191 | { | |
b4726a58 | 192 | long ref = GetControlReference( browser ); |
cee24bf7 | 193 | if ( ref != 0 ) |
83ce5634 | 194 | { |
cee24bf7 | 195 | wxListBox *list = wxDynamicCast( (wxObject*)ref, wxListBox ); |
520b09fc | 196 | wxMacDataBrowserListControl *peer = (wxMacDataBrowserListControl*) list->GetPeer(); |
cee24bf7 | 197 | |
b4726a58 | 198 | int i = itemID - 1; |
cee24bf7 | 199 | if (i >= 0 && i < (int)list->GetCount()) |
8e0f22c0 | 200 | { |
b4726a58 | 201 | bool trigger = false; |
fdd4e6cc | 202 | wxCommandEvent event( wxEVT_COMMAND_LISTBOX_SELECTED, list->GetId() ); |
cee24bf7 | 203 | switch (message) |
83ce5634 | 204 | { |
cee24bf7 | 205 | case kDataBrowserItemDeselected: |
8e0f22c0 | 206 | if ( list->HasMultipleSelection() ) |
b4726a58 SC |
207 | trigger = !peer->MacIsSelectionSuppressed(); |
208 | break; | |
fdd4e6cc | 209 | |
cee24bf7 | 210 | case kDataBrowserItemSelected: |
b4726a58 SC |
211 | trigger = !peer->MacIsSelectionSuppressed(); |
212 | break; | |
fdd4e6cc | 213 | |
cee24bf7 | 214 | case kDataBrowserItemDoubleClicked: |
b4726a58 SC |
215 | event.SetEventType( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED ); |
216 | trigger = true; | |
217 | break; | |
fdd4e6cc | 218 | |
cee24bf7 | 219 | default: |
b4726a58 | 220 | break; |
83ce5634 | 221 | } |
fdd4e6cc | 222 | |
8e0f22c0 SC |
223 | if ( trigger ) |
224 | { | |
225 | event.SetEventObject( list ); | |
226 | if ( list->HasClientObjectData() ) | |
fdd4e6cc | 227 | event.SetClientObject( list->GetClientObject( i ) ); |
8e0f22c0 | 228 | else if ( list->HasClientUntypedData() ) |
fdd4e6cc DS |
229 | event.SetClientData( list->GetClientData( i ) ); |
230 | event.SetString( list->GetString( i ) ); | |
b4726a58 | 231 | event.SetInt( i ); |
fdd4e6cc | 232 | event.SetExtraLong( list->HasMultipleSelection() ? message == kDataBrowserItemSelected : true ); |
cee24bf7 | 233 | wxPostEvent( list->GetEventHandler(), event ); |
520b09fc | 234 | |
8e0f22c0 | 235 | // direct notification is not always having the listbox GetSelection() having in synch with event |
b4726a58 | 236 | // list->GetEventHandler()->ProcessEvent(event); |
c6179a84 | 237 | } |
8e0f22c0 | 238 | } |
83ce5634 SC |
239 | } |
240 | } | |
241 | ||
520b09fc DS |
242 | static pascal OSStatus ListBoxGetSetItemData( |
243 | ControlRef browser, | |
244 | DataBrowserItemID itemID, | |
245 | DataBrowserPropertyID property, | |
246 | DataBrowserItemDataRef itemData, | |
247 | Boolean changeValue ) | |
facd6764 | 248 | { |
de1b0aeb VZ |
249 | OSStatus err = errDataBrowserPropertyNotSupported; |
250 | ||
cee24bf7 DS |
251 | long ref = GetControlReference( browser ); |
252 | ||
520b09fc | 253 | if ( !changeValue ) |
de1b0aeb | 254 | { |
520b09fc | 255 | wxListBox *list = wxDynamicCast( (wxObject*)ref, wxListBox ); |
b4726a58 | 256 | bool isCheckList = false; |
cee24bf7 DS |
257 | if (list) |
258 | isCheckList = list->IsKindOf( CLASSINFO(wxCheckListBox) ); | |
259 | ||
de1b0aeb VZ |
260 | switch (property) |
261 | { | |
de1b0aeb | 262 | case kTextColumnId: |
520b09fc | 263 | if ( ref != 0 ) |
de1b0aeb | 264 | { |
b4726a58 | 265 | int i = itemID - 1; |
520b09fc | 266 | if (i >= 0 && i < (int)list->GetCount()) |
de1b0aeb | 267 | { |
cee24bf7 | 268 | wxMacCFStringHolder cf( list->GetString( i ), list->GetFont().GetEncoding() ); |
520b09fc DS |
269 | err = ::SetDataBrowserItemDataText( itemData, cf ); |
270 | verify_noerr( err ); | |
b4726a58 | 271 | err = noErr; |
de1b0aeb VZ |
272 | } |
273 | } | |
fdd4e6cc | 274 | break; |
cee24bf7 DS |
275 | |
276 | case kCheckboxColumnId: | |
520b09fc | 277 | if ( ref != 0 ) |
cee24bf7 | 278 | { |
520b09fc | 279 | wxCheckListBox *list = wxDynamicCast( (wxObject*)ref, wxCheckListBox ); |
b4726a58 | 280 | int i = itemID - 1; |
cee24bf7 DS |
281 | if (i >= 0 && (unsigned int) i < list->GetCount()) |
282 | { | |
520b09fc DS |
283 | err = ::SetDataBrowserItemDataButtonValue( itemData, list->IsChecked( i ) ? kThemeButtonOn : kThemeButtonOff ); |
284 | verify_noerr( err ); | |
cee24bf7 DS |
285 | err = noErr; |
286 | } | |
287 | } | |
288 | break; | |
289 | ||
290 | case kDataBrowserItemIsEditableProperty: | |
291 | if ( isCheckList ) | |
520b09fc | 292 | err = ::SetDataBrowserItemDataBooleanValue( itemData, true ); |
cee24bf7 | 293 | break; |
c6179a84 | 294 | |
de1b0aeb | 295 | default: |
fdd4e6cc | 296 | break; |
de1b0aeb VZ |
297 | } |
298 | } | |
cee24bf7 DS |
299 | else |
300 | { | |
301 | switch (property) | |
302 | { | |
303 | case kCheckboxColumnId: | |
520b09fc | 304 | if ( ref != 0 ) |
cee24bf7 | 305 | { |
520b09fc | 306 | wxCheckListBox *list = wxDynamicCast( (wxObject*)ref, wxCheckListBox ); |
cee24bf7 | 307 | int i = itemID - 1; |
520b09fc | 308 | if (i >= 0 && (unsigned int)i < list->GetCount()) |
cee24bf7 DS |
309 | { |
310 | // we have to change this behind the back, since Check() would be triggering another update round | |
311 | bool newVal = !list->IsChecked( i ); | |
520b09fc DS |
312 | err = ::SetDataBrowserItemDataButtonValue( itemData, newVal ? kThemeButtonOn : kThemeButtonOff ); |
313 | verify_noerr( err ); | |
cee24bf7 DS |
314 | err = noErr; |
315 | list->m_checks[i] = newVal; | |
316 | ||
520b09fc DS |
317 | wxCommandEvent event( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, list->GetId() ); |
318 | event.SetInt( i ); | |
319 | event.SetEventObject( list ); | |
320 | list->GetEventHandler()->ProcessEvent( event ); | |
cee24bf7 DS |
321 | } |
322 | } | |
323 | break; | |
324 | ||
325 | default: | |
326 | break; | |
327 | } | |
328 | } | |
c6179a84 | 329 | |
de1b0aeb | 330 | return err; |
facd6764 | 331 | } |
fe3dc505 | 332 | |
cee24bf7 DS |
333 | wxMacDataBrowserListControl::wxMacDataBrowserListControl( wxListBox *peer, const wxPoint& pos, const wxSize& size, long style) |
334 | : wxMacListControl( peer ) | |
b4726a58 SC |
335 | { |
336 | bool isCheckList = peer->IsKindOf( CLASSINFO(wxCheckListBox)); | |
cee24bf7 | 337 | |
b4726a58 | 338 | m_suppressSelection = false; |
cee24bf7 DS |
339 | Rect bounds = wxMacGetBoundsForControl( peer, pos, size ); |
340 | OSStatus err = ::CreateDataBrowserControl( | |
341 | MAC_WXHWND(peer->MacGetTopLevelWindowRef()), | |
342 | &bounds, kDataBrowserListView, &m_controlRef ); | |
343 | verify_noerr( err ); | |
b4726a58 SC |
344 | |
345 | DataBrowserSelectionFlags options = kDataBrowserDragSelect; | |
346 | if ( style & wxLB_MULTIPLE ) | |
347 | { | |
cee24bf7 | 348 | options |= kDataBrowserAlwaysExtendSelection | kDataBrowserCmdTogglesSelection; |
b4726a58 SC |
349 | } |
350 | else if ( style & wxLB_EXTENDED ) | |
351 | { | |
352 | // default behaviour | |
353 | } | |
354 | else | |
355 | { | |
cee24bf7 | 356 | options |= kDataBrowserSelectOnlyOne; |
b4726a58 | 357 | } |
cee24bf7 DS |
358 | err = SetSelectionFlags( options ); |
359 | verify_noerr( err ); | |
360 | ||
361 | if ( gDataBrowserItemDataUPP == NULL ) | |
362 | gDataBrowserItemDataUPP = NewDataBrowserItemDataUPP(ListBoxGetSetItemData); | |
b4726a58 | 363 | if ( gDataBrowserItemNotificationUPP == NULL ) |
cee24bf7 DS |
364 | { |
365 | gDataBrowserItemNotificationUPP = | |
b4726a58 | 366 | #if TARGET_API_MAC_OSX |
cee24bf7 | 367 | (DataBrowserItemNotificationUPP) NewDataBrowserItemNotificationWithItemUPP(DataBrowserItemNotificationProc); |
b4726a58 | 368 | #else |
cee24bf7 | 369 | NewDataBrowserItemNotificationUPP(DataBrowserItemNotificationProc); |
b4726a58 | 370 | #endif |
cee24bf7 | 371 | } |
b4726a58 SC |
372 | |
373 | DataBrowserCallbacks callbacks; | |
cee24bf7 | 374 | InitializeDataBrowserCallbacks( &callbacks, kDataBrowserLatestCallbacks ); |
b4726a58 SC |
375 | |
376 | callbacks.u.v1.itemDataCallback = gDataBrowserItemDataUPP; | |
cee24bf7 DS |
377 | callbacks.u.v1.itemNotificationCallback = gDataBrowserItemNotificationUPP; |
378 | SetCallbacks( &callbacks ); | |
379 | ||
b4726a58 SC |
380 | DataBrowserListViewColumnDesc columnDesc; |
381 | columnDesc.headerBtnDesc.titleOffset = 0; | |
cee24bf7 | 382 | columnDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc; |
b4726a58 | 383 | |
cee24bf7 DS |
384 | columnDesc.headerBtnDesc.btnFontStyle.flags = |
385 | kControlUseFontMask | kControlUseJustMask; | |
b4726a58 | 386 | |
cee24bf7 DS |
387 | columnDesc.headerBtnDesc.btnContentInfo.contentType = kControlNoContent; |
388 | columnDesc.headerBtnDesc.btnFontStyle.just = teFlushDefault; | |
389 | columnDesc.headerBtnDesc.btnFontStyle.font = kControlFontViewSystemFont; | |
390 | columnDesc.headerBtnDesc.btnFontStyle.style = normal; | |
391 | columnDesc.headerBtnDesc.titleString = NULL; | |
b4726a58 | 392 | |
cee24bf7 | 393 | if ( isCheckList ) |
b4726a58 | 394 | { |
cee24bf7 DS |
395 | columnDesc.headerBtnDesc.minimumWidth = 30; |
396 | columnDesc.headerBtnDesc.maximumWidth = 30; | |
397 | ||
398 | columnDesc.propertyDesc.propertyID = kCheckboxColumnId; | |
399 | columnDesc.propertyDesc.propertyType = kDataBrowserCheckboxType; | |
400 | columnDesc.propertyDesc.propertyFlags = | |
401 | kDataBrowserPropertyIsMutable | |
402 | | kDataBrowserTableViewSelectionColumn | |
403 | | kDataBrowserDefaultPropertyFlags; | |
404 | err = AddListViewColumn( &columnDesc, kDataBrowserListViewAppendColumn ); | |
405 | verify_noerr( err ); | |
b4726a58 | 406 | } |
cee24bf7 DS |
407 | |
408 | columnDesc.headerBtnDesc.minimumWidth = 0; | |
409 | columnDesc.headerBtnDesc.maximumWidth = 10000; | |
b4726a58 | 410 | |
cee24bf7 DS |
411 | columnDesc.propertyDesc.propertyID = kTextColumnId; |
412 | columnDesc.propertyDesc.propertyType = kDataBrowserTextType; | |
413 | columnDesc.propertyDesc.propertyFlags = kDataBrowserTableViewSelectionColumn; | |
b4726a58 | 414 | #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 |
cee24bf7 | 415 | columnDesc.propertyDesc.propertyFlags |= kDataBrowserListViewTypeSelectColumn; |
b4726a58 | 416 | #endif |
b4726a58 | 417 | |
cee24bf7 DS |
418 | verify_noerr( AddListViewColumn( &columnDesc, kDataBrowserListViewAppendColumn ) ); |
419 | verify_noerr( AutoSizeListViewColumns() ); | |
420 | verify_noerr( SetHasScrollBars( false, true ) ); | |
421 | verify_noerr( SetTableViewHiliteStyle(kDataBrowserTableViewFillHilite ) ); | |
422 | verify_noerr( SetListViewHeaderBtnHeight( 0 ) ); | |
b4726a58 SC |
423 | |
424 | #if 0 | |
425 | // shouldn't be necessary anymore under 10.2 | |
cee24bf7 | 426 | m_peer->SetData( kControlNoPart, kControlDataBrowserIncludesFrameAndFocusTag, (Boolean)false ); |
b4726a58 SC |
427 | m_peer->SetNeedsFocusRect( true ); |
428 | #endif | |
429 | } | |
cee24bf7 DS |
430 | |
431 | wxMacDataBrowserListControl::~wxMacDataBrowserListControl() | |
b4726a58 | 432 | { |
b4726a58 SC |
433 | } |
434 | ||
435 | void wxMacDataBrowserListControl::MacDelete( int n ) | |
436 | { | |
437 | wxArrayInt selectionBefore; | |
438 | MacGetSelections( selectionBefore ); | |
439 | ||
cee24bf7 DS |
440 | UInt32 id = GetPeer()->GetCount() + 1; |
441 | ||
442 | OSStatus err = RemoveItems( kDataBrowserNoItem, 1, (UInt32*) &id, kDataBrowserItemNoProperty ); | |
443 | verify_noerr( err ); | |
444 | ||
b4726a58 SC |
445 | for ( size_t i = 0; i < selectionBefore.GetCount(); ++i ) |
446 | { | |
447 | int current = selectionBefore[i]; | |
448 | if ( current == n ) | |
449 | { | |
450 | // selection was deleted | |
cee24bf7 | 451 | MacSetSelection( current, false ); |
b4726a58 SC |
452 | } |
453 | else if ( current > n ) | |
454 | { | |
455 | // something behind the deleted item was selected -> move up | |
cee24bf7 DS |
456 | MacSetSelection( current - 1, true ); |
457 | MacSetSelection( current, false ); | |
b4726a58 SC |
458 | } |
459 | } | |
cee24bf7 | 460 | |
b4726a58 | 461 | // refresh all |
cee24bf7 DS |
462 | err = UpdateItems( |
463 | kDataBrowserNoItem, 1, (UInt32*)kDataBrowserNoItem, | |
464 | kDataBrowserItemNoProperty, kDataBrowserItemNoProperty ); | |
465 | verify_noerr( err ); | |
b4726a58 SC |
466 | } |
467 | ||
cee24bf7 | 468 | void wxMacDataBrowserListControl::MacInsert( int n, const wxString& text) |
b4726a58 SC |
469 | { |
470 | wxArrayInt selectionBefore; | |
471 | MacGetSelections( selectionBefore ); | |
472 | ||
473 | UInt32 id = GetPeer()->GetCount(); // this has already been increased | |
cee24bf7 DS |
474 | OSStatus err = AddItems( kDataBrowserNoItem, 1, (UInt32*) &id, kDataBrowserItemNoProperty ); |
475 | verify_noerr( err ); | |
b4726a58 | 476 | |
cee24bf7 | 477 | for ( int i = selectionBefore.GetCount() - 1; i >= 0; --i ) |
b4726a58 SC |
478 | { |
479 | int current = selectionBefore[i]; | |
480 | if ( current >= n ) | |
481 | { | |
cee24bf7 DS |
482 | MacSetSelection( current + 1, true ); |
483 | MacSetSelection( current, false ); | |
b4726a58 SC |
484 | } |
485 | } | |
486 | ||
487 | // refresh all | |
cee24bf7 DS |
488 | err = UpdateItems( |
489 | kDataBrowserNoItem, 1, (UInt32*)kDataBrowserNoItem, | |
490 | kDataBrowserItemNoProperty, kDataBrowserItemNoProperty ); | |
491 | verify_noerr( err ); | |
b4726a58 SC |
492 | } |
493 | ||
cee24bf7 | 494 | void wxMacDataBrowserListControl::MacInsert( int n, const wxArrayString& items) |
b4726a58 SC |
495 | { |
496 | wxArrayInt selectionBefore; | |
497 | MacGetSelections( selectionBefore ); | |
498 | size_t itemsCount = items.GetCount(); | |
499 | ||
cee24bf7 DS |
500 | UInt32 *ids = new UInt32[itemsCount]; |
501 | for ( unsigned int i = 0; i < itemsCount; ++i ) | |
502 | ids[i] = GetPeer()->GetCount() - itemsCount + i + 1; | |
b4726a58 | 503 | |
cee24bf7 DS |
504 | OSStatus err = AddItems( kDataBrowserNoItem, itemsCount, ids, kDataBrowserItemNoProperty ); |
505 | verify_noerr( err ); | |
506 | delete [] ids; | |
b4726a58 | 507 | |
cee24bf7 | 508 | for ( int i = selectionBefore.GetCount() - 1; i >= 0; --i ) |
b4726a58 SC |
509 | { |
510 | int current = selectionBefore[i]; | |
511 | if ( current >= n ) | |
512 | { | |
cee24bf7 DS |
513 | MacSetSelection( current + 1, true ); |
514 | MacSetSelection( current, false ); | |
b4726a58 SC |
515 | } |
516 | } | |
cee24bf7 | 517 | |
b4726a58 | 518 | // refresh all |
cee24bf7 DS |
519 | err = UpdateItems( |
520 | kDataBrowserNoItem, 1, (UInt32*)kDataBrowserNoItem, | |
521 | kDataBrowserItemNoProperty, kDataBrowserItemNoProperty ); | |
522 | verify_noerr( err ); | |
b4726a58 SC |
523 | } |
524 | ||
525 | void wxMacDataBrowserListControl::MacAppend( const wxString& text) | |
526 | { | |
527 | UInt32 id = GetPeer()->GetCount(); // this has already been increased | |
cee24bf7 | 528 | verify_noerr( AddItems( kDataBrowserNoItem, 1, (UInt32*) &id, kDataBrowserItemNoProperty ) ); |
b4726a58 SC |
529 | // no need to deal with selections nor refreshed, as we have appended |
530 | } | |
531 | ||
532 | void wxMacDataBrowserListControl::MacClear() | |
533 | { | |
cee24bf7 | 534 | verify_noerr( RemoveItems( kDataBrowserNoItem, 0, NULL, kDataBrowserItemNoProperty ) ); |
b4726a58 SC |
535 | } |
536 | ||
537 | void wxMacDataBrowserListControl::MacDeselectAll() | |
538 | { | |
539 | bool former = MacSuppressSelection( true ); | |
cee24bf7 | 540 | verify_noerr(SetSelectedItems( 0, NULL, kDataBrowserItemsRemove ) ); |
b4726a58 SC |
541 | MacSuppressSelection( former ); |
542 | } | |
543 | ||
cee24bf7 | 544 | void wxMacDataBrowserListControl::MacSetSelection( int n, bool select ) |
b4726a58 | 545 | { |
b4726a58 | 546 | UInt32 id = n + 1; |
cee24bf7 | 547 | bool former = MacSuppressSelection( true ); |
b4726a58 SC |
548 | |
549 | if ( IsItemSelected( id ) != select ) | |
550 | { | |
cee24bf7 DS |
551 | OSStatus err; |
552 | ||
b4726a58 | 553 | if ( select ) |
cee24bf7 | 554 | err = SetSelectedItems( 1, &id, GetPeer()->HasMultipleSelection() ? kDataBrowserItemsAdd : kDataBrowserItemsAssign ); |
b4726a58 | 555 | else |
cee24bf7 DS |
556 | err = SetSelectedItems( 1, &id, kDataBrowserItemsRemove ); |
557 | ||
558 | verify_noerr( err ); | |
b4726a58 | 559 | } |
cee24bf7 | 560 | |
b4726a58 SC |
561 | MacScrollTo( n ); |
562 | MacSuppressSelection( former ); | |
563 | } | |
564 | ||
565 | bool wxMacDataBrowserListControl::MacSuppressSelection( bool suppress ) | |
566 | { | |
cee24bf7 DS |
567 | bool former = m_suppressSelection; |
568 | m_suppressSelection = suppress; | |
569 | ||
570 | return former; | |
b4726a58 SC |
571 | } |
572 | ||
573 | bool wxMacDataBrowserListControl::MacIsSelected( int n ) const | |
574 | { | |
575 | return IsItemSelected( n + 1 ); | |
576 | } | |
577 | ||
578 | int wxMacDataBrowserListControl::MacGetSelection() const | |
579 | { | |
580 | for ( unsigned int i = 0; i < GetPeer()->GetCount(); ++i ) | |
581 | { | |
582 | if ( IsItemSelected( i + 1 ) ) | |
583 | { | |
584 | return i; | |
585 | } | |
586 | } | |
cee24bf7 | 587 | |
b4726a58 SC |
588 | return -1; |
589 | } | |
590 | ||
591 | int wxMacDataBrowserListControl::MacGetSelections( wxArrayInt& aSelections ) const | |
592 | { | |
593 | int no_sel = 0; | |
594 | ||
595 | aSelections.Empty(); | |
596 | ||
cee24bf7 DS |
597 | UInt32 first, last; |
598 | GetSelectionAnchor( &first, &last ); | |
b4726a58 SC |
599 | if ( first != kDataBrowserNoItem ) |
600 | { | |
601 | for ( size_t i = first; i <= last; ++i ) | |
602 | { | |
603 | if ( IsItemSelected( i ) ) | |
604 | { | |
605 | aSelections.Add( i - 1 ); | |
606 | no_sel++; | |
607 | } | |
608 | } | |
609 | } | |
cee24bf7 | 610 | |
b4726a58 SC |
611 | return no_sel; |
612 | } | |
613 | ||
cee24bf7 | 614 | void wxMacDataBrowserListControl::MacSet( int n, const wxString& text ) |
b4726a58 SC |
615 | { |
616 | // as we don't store the strings we only have to issue a redraw | |
617 | UInt32 id = n + 1; | |
cee24bf7 | 618 | verify_noerr( UpdateItems( kDataBrowserNoItem, 1, &id, kDataBrowserItemNoProperty, kDataBrowserItemNoProperty ) ); |
b4726a58 SC |
619 | } |
620 | ||
621 | void wxMacDataBrowserListControl::MacScrollTo( int n ) | |
622 | { | |
623 | UInt32 id = n + 1; | |
cee24bf7 | 624 | verify_noerr( RevealItem( id, kTextColumnId, kDataBrowserRevealWithoutSelecting ) ); |
b4726a58 SC |
625 | } |
626 | ||
627 | void wxMacDataBrowserListControl::UpdateLine( int n ) | |
628 | { | |
629 | UInt32 id = n + 1; | |
cee24bf7 | 630 | verify_noerr( UpdateItems(kDataBrowserNoItem, 1, &id, kDataBrowserItemNoProperty, kDataBrowserItemNoProperty ) ); |
b4726a58 SC |
631 | } |
632 | ||
633 | // | |
634 | // Databrowser | |
635 | // | |
636 | ||
637 | OSStatus wxMacDataBrowserListControl::SetSelectionFlags( DataBrowserSelectionFlags options ) | |
638 | { | |
cee24bf7 | 639 | return SetDataBrowserSelectionFlags( m_controlRef, options ); |
b4726a58 SC |
640 | } |
641 | ||
642 | OSStatus wxMacDataBrowserListControl::AddListViewColumn( DataBrowserListViewColumnDesc *columnDesc, | |
643 | DataBrowserTableViewColumnIndex position ) | |
644 | { | |
cee24bf7 | 645 | return AddDataBrowserListViewColumn( m_controlRef, columnDesc, position ); |
b4726a58 SC |
646 | } |
647 | ||
648 | OSStatus wxMacDataBrowserListControl::AutoSizeListViewColumns() | |
649 | { | |
650 | return AutoSizeDataBrowserListViewColumns(m_controlRef); | |
651 | } | |
652 | ||
cee24bf7 | 653 | OSStatus wxMacDataBrowserListControl::SetHasScrollBars( bool horiz, bool vert ) |
b4726a58 | 654 | { |
cee24bf7 | 655 | return SetDataBrowserHasScrollBars( m_controlRef, horiz, vert ); |
b4726a58 SC |
656 | } |
657 | ||
658 | OSStatus wxMacDataBrowserListControl::SetTableViewHiliteStyle( DataBrowserTableViewHiliteStyle hiliteStyle ) | |
659 | { | |
cee24bf7 | 660 | return SetDataBrowserTableViewHiliteStyle( m_controlRef, hiliteStyle ); |
b4726a58 SC |
661 | } |
662 | ||
663 | OSStatus wxMacDataBrowserListControl::SetListViewHeaderBtnHeight(UInt16 height) | |
664 | { | |
cee24bf7 | 665 | return SetDataBrowserListViewHeaderBtnHeight( m_controlRef, height ); |
b4726a58 SC |
666 | } |
667 | ||
cee24bf7 | 668 | OSStatus wxMacDataBrowserListControl::SetCallbacks(const DataBrowserCallbacks *callbacks) |
b4726a58 | 669 | { |
cee24bf7 | 670 | return SetDataBrowserCallbacks( m_controlRef, callbacks ); |
b4726a58 SC |
671 | } |
672 | ||
cee24bf7 DS |
673 | OSStatus wxMacDataBrowserListControl::UpdateItems( |
674 | DataBrowserItemID container, | |
675 | UInt32 numItems, | |
676 | const DataBrowserItemID *items, | |
677 | DataBrowserPropertyID preSortProperty, | |
678 | DataBrowserPropertyID propertyID ) | |
b4726a58 | 679 | { |
cee24bf7 | 680 | return UpdateDataBrowserItems( m_controlRef, container, numItems, items, preSortProperty, propertyID ); |
b4726a58 SC |
681 | } |
682 | ||
683 | bool wxMacDataBrowserListControl::IsItemSelected( DataBrowserItemID item ) const | |
684 | { | |
cee24bf7 | 685 | return IsDataBrowserItemSelected( m_controlRef, item ); |
b4726a58 SC |
686 | } |
687 | ||
cee24bf7 DS |
688 | OSStatus wxMacDataBrowserListControl::AddItems( |
689 | DataBrowserItemID container, | |
690 | UInt32 numItems, | |
691 | const DataBrowserItemID *items, | |
692 | DataBrowserPropertyID preSortProperty ) | |
b4726a58 | 693 | { |
cee24bf7 | 694 | return AddDataBrowserItems( m_controlRef, container, numItems, items, preSortProperty ); |
b4726a58 SC |
695 | } |
696 | ||
cee24bf7 DS |
697 | OSStatus wxMacDataBrowserListControl::RemoveItems( |
698 | DataBrowserItemID container, | |
699 | UInt32 numItems, | |
700 | const DataBrowserItemID *items, | |
701 | DataBrowserPropertyID preSortProperty ) | |
b4726a58 | 702 | { |
cee24bf7 | 703 | return RemoveDataBrowserItems( m_controlRef, container, numItems, items, preSortProperty ); |
b4726a58 SC |
704 | } |
705 | ||
cee24bf7 DS |
706 | OSStatus wxMacDataBrowserListControl::RevealItem( |
707 | DataBrowserItemID item, | |
708 | DataBrowserPropertyID propertyID, | |
709 | DataBrowserRevealOptions options ) | |
b4726a58 | 710 | { |
cee24bf7 | 711 | return RevealDataBrowserItem( m_controlRef, item, propertyID, options ); |
b4726a58 SC |
712 | } |
713 | ||
cee24bf7 DS |
714 | OSStatus wxMacDataBrowserListControl::SetSelectedItems( |
715 | UInt32 numItems, | |
716 | const DataBrowserItemID *items, | |
717 | DataBrowserSetOption operation ) | |
b4726a58 | 718 | { |
cee24bf7 | 719 | return SetDataBrowserSelectedItems( m_controlRef, numItems, items, operation ); |
b4726a58 SC |
720 | } |
721 | ||
cee24bf7 | 722 | OSStatus wxMacDataBrowserListControl::GetSelectionAnchor( DataBrowserItemID *first, DataBrowserItemID *last ) const |
b4726a58 | 723 | { |
cee24bf7 | 724 | return GetDataBrowserSelectionAnchor( m_controlRef, first, last ); |
b4726a58 SC |
725 | } |
726 | ||
727 | #if 0 | |
728 | ||
729 | // in case we need that one day | |
730 | ||
731 | // ============================================================================ | |
cee24bf7 | 732 | // HIView owner-draw-based implementation |
b4726a58 SC |
733 | // ============================================================================ |
734 | ||
cee24bf7 DS |
735 | static pascal void ListBoxDrawProc( |
736 | ControlRef browser, DataBrowserItemID item, DataBrowserPropertyID property, | |
737 | DataBrowserItemState itemState, const Rect *itemRect, SInt16 depth, Boolean isColorDevice ) | |
789ae0cf | 738 | { |
cee24bf7 | 739 | CFStringRef cfString; |
b4726a58 | 740 | ThemeDrawingState themeState; |
cee24bf7 | 741 | long systemVersion; |
789ae0cf | 742 | |
b4726a58 | 743 | GetThemeDrawingState( &themeState ); |
fdd4e6cc | 744 | cfString = CFStringCreateWithFormat( NULL, NULL, CFSTR("Row %d"), item ); |
de1b0aeb | 745 | |
fdd4e6cc DS |
746 | // In this sample we handle the "selected" state; all others fall through to our "active" state |
747 | if ( itemState == kDataBrowserItemIsSelected ) | |
789ae0cf | 748 | { |
fdd4e6cc DS |
749 | ThemeBrush colorBrushID; |
750 | ||
cee24bf7 DS |
751 | // TODO: switch over to wxSystemSettingsNative::GetColour() when kThemeBrushSecondaryHighlightColor |
752 | // is incorporated Panther DB starts using kThemeBrushSecondaryHighlightColor | |
753 | // for inactive browser highlighting | |
789ae0cf | 754 | Gestalt( gestaltSystemVersion, &systemVersion ); |
fdd4e6cc DS |
755 | if ( (systemVersion >= 0x00001030) && !IsControlActive( browser ) ) |
756 | colorBrushID = kThemeBrushSecondaryHighlightColor; | |
789ae0cf | 757 | else |
fdd4e6cc | 758 | colorBrushID = kThemeBrushPrimaryHighlightColor; |
789ae0cf | 759 | |
fdd4e6cc DS |
760 | // First paint the hilite rect, then the text on top |
761 | SetThemePen( colorBrushID, 32, true ); | |
762 | PaintRect( itemRect ); | |
cee24bf7 | 763 | SetThemeDrawingState( themeState, false ); |
789ae0cf | 764 | } |
fdd4e6cc | 765 | |
789ae0cf | 766 | DrawThemeTextBox( cfString, kThemeApplicationFont, kThemeStateActive, true, itemRect, teFlushDefault, NULL ); |
cee24bf7 | 767 | SetThemeDrawingState( themeState, true ); |
fdd4e6cc | 768 | |
de1b0aeb | 769 | if ( cfString != NULL ) |
789ae0cf | 770 | CFRelease( cfString ); |
789ae0cf | 771 | } |
b4726a58 SC |
772 | #endif |
773 | ||
b4726a58 SC |
774 | // ============================================================================ |
775 | // list box control implementation | |
776 | // ============================================================================ | |
fe3dc505 | 777 | |
fe3dc505 SC |
778 | wxListBox::wxListBox() |
779 | { | |
520b09fc | 780 | m_noItems = 0; |
fe3dc505 SC |
781 | } |
782 | ||
520b09fc DS |
783 | bool wxListBox::Create( |
784 | wxWindow *parent, | |
fdd4e6cc DS |
785 | wxWindowID id, |
786 | const wxPoint& pos, | |
787 | const wxSize& size, | |
788 | const wxArrayString& choices, | |
789 | long style, | |
790 | const wxValidator& validator, | |
520b09fc | 791 | const wxString& name ) |
fe3dc505 SC |
792 | { |
793 | wxCArrayString chs(choices); | |
794 | ||
cee24bf7 DS |
795 | return Create( |
796 | parent, id, pos, size, chs.GetCount(), chs.GetStrings(), | |
520b09fc | 797 | style, validator, name ); |
fe3dc505 SC |
798 | } |
799 | ||
520b09fc DS |
800 | bool wxListBox::Create( |
801 | wxWindow *parent, | |
fdd4e6cc DS |
802 | wxWindowID id, |
803 | const wxPoint& pos, | |
804 | const wxSize& size, | |
805 | int n, | |
806 | const wxString choices[], | |
807 | long style, | |
808 | const wxValidator& validator, | |
520b09fc | 809 | const wxString& name ) |
facd6764 | 810 | { |
b4726a58 | 811 | m_macIsUserPane = false; |
5e6f42cd SC |
812 | |
813 | wxASSERT_MSG( !(style & wxLB_MULTIPLE) || !(style & wxLB_EXTENDED), | |
520b09fc | 814 | wxT("only a single listbox selection mode can be specified") ); |
c6179a84 | 815 | |
520b09fc | 816 | if ( !wxListBoxBase::Create( parent, id, pos, size, style & ~(wxHSCROLL | wxVSCROLL), validator, name ) ) |
facd6764 SC |
817 | return false; |
818 | ||
cee24bf7 DS |
819 | // this will be increased by our append command |
820 | m_noItems = 0; | |
789ae0cf | 821 | |
cee24bf7 | 822 | m_peer = CreateMacListControl( pos, size, style ); |
de1b0aeb | 823 | |
cee24bf7 | 824 | MacPostControlCreate( pos, size ); |
c6179a84 | 825 | |
cee24bf7 | 826 | InsertItems( n, choices, 0 ); |
facd6764 | 827 | |
cee24bf7 DS |
828 | // Needed because it is a wxControlWithItems |
829 | SetBestSize( size ); | |
fdd4e6cc | 830 | |
cee24bf7 | 831 | return true; |
facd6764 SC |
832 | } |
833 | ||
834 | wxListBox::~wxListBox() | |
835 | { | |
b4726a58 SC |
836 | m_peer->SetReference( 0 ); |
837 | FreeData(); | |
838 | } | |
fdd4e6cc | 839 | |
cee24bf7 | 840 | wxMacListControl * wxListBox::CreateMacListControl(const wxPoint& pos, const wxSize& size, long style) |
b4726a58 | 841 | { |
cee24bf7 | 842 | return new wxMacDataBrowserListControl( this, pos, size, style ); |
facd6764 SC |
843 | } |
844 | ||
845 | void wxListBox::FreeData() | |
846 | { | |
b4726a58 SC |
847 | #if wxUSE_OWNER_DRAWN |
848 | if ( m_windowStyle & wxLB_OWNERDRAW ) | |
849 | { | |
850 | size_t uiCount = m_aItems.Count(); | |
cee24bf7 DS |
851 | while ( uiCount != 0 ) |
852 | { | |
853 | uiCount--; | |
b4726a58 SC |
854 | delete m_aItems[uiCount]; |
855 | m_aItems[uiCount] = NULL; | |
856 | } | |
857 | ||
858 | m_aItems.Clear(); | |
859 | } | |
860 | else | |
cee24bf7 | 861 | #endif |
facd6764 SC |
862 | if ( HasClientObjectData() ) |
863 | { | |
aa61d352 | 864 | for ( unsigned int n = 0; n < m_noItems; n++ ) |
facd6764 | 865 | { |
fdd4e6cc | 866 | delete GetClientObject( n ); |
facd6764 SC |
867 | } |
868 | } | |
869 | } | |
870 | ||
871 | void wxListBox::DoSetSize(int x, int y, | |
872 | int width, int height, | |
873 | int sizeFlags ) | |
874 | { | |
cee24bf7 | 875 | wxControl::DoSetSize( x, y, width, height, sizeFlags ); |
facd6764 SC |
876 | } |
877 | ||
fdd4e6cc | 878 | void wxListBox::DoSetFirstItem(int n) |
facd6764 | 879 | { |
b4726a58 | 880 | GetPeer()->MacScrollTo( n ); |
facd6764 SC |
881 | } |
882 | ||
aa61d352 | 883 | void wxListBox::Delete(unsigned int n) |
facd6764 | 884 | { |
cee24bf7 | 885 | wxCHECK_RET( IsValid(n), wxT("invalid index in wxListBox::Delete") ); |
facd6764 | 886 | |
b4726a58 SC |
887 | #if wxUSE_OWNER_DRAWN |
888 | delete m_aItems[n]; | |
889 | m_aItems.RemoveAt(n); | |
cee24bf7 | 890 | #else |
facd6764 | 891 | if ( HasClientObjectData() ) |
b4726a58 SC |
892 | { |
893 | delete GetClientObject(n); | |
894 | } | |
cee24bf7 DS |
895 | #endif |
896 | ||
b4726a58 SC |
897 | m_stringArray.RemoveAt( n ); |
898 | m_dataArray.RemoveAt( n ); | |
cee24bf7 | 899 | m_noItems--; |
facd6764 | 900 | |
b4726a58 | 901 | GetPeer()->MacDelete( n ); |
facd6764 SC |
902 | } |
903 | ||
904 | int wxListBox::DoAppend(const wxString& item) | |
905 | { | |
9f884528 RD |
906 | InvalidateBestSize(); |
907 | ||
b4726a58 SC |
908 | unsigned int index = m_noItems; |
909 | m_stringArray.Add( item ); | |
facd6764 | 910 | m_dataArray.Add( NULL ); |
fdd4e6cc | 911 | m_noItems++; |
cee24bf7 | 912 | DoSetItemClientData( index, NULL ); |
b4726a58 | 913 | GetPeer()->MacAppend( item ); |
facd6764 | 914 | |
b4726a58 | 915 | return index; |
facd6764 SC |
916 | } |
917 | ||
918 | void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData) | |
919 | { | |
b4726a58 | 920 | Clear(); |
aa61d352 | 921 | unsigned int n = choices.GetCount(); |
c6179a84 | 922 | |
b4726a58 | 923 | for ( size_t i = 0; i < n; ++i ) |
facd6764 SC |
924 | { |
925 | if ( clientData ) | |
b4726a58 SC |
926 | { |
927 | #if wxUSE_OWNER_DRAWN | |
928 | wxASSERT_MSG(clientData[i] == NULL, | |
520b09fc | 929 | wxT("Cannot use client data with owner-drawn listboxes")); |
cee24bf7 DS |
930 | #else |
931 | Append( choices[i], clientData[i] ); | |
b4726a58 SC |
932 | #endif |
933 | } | |
facd6764 | 934 | else |
b4726a58 | 935 | Append( choices[i] ); |
facd6764 | 936 | } |
b4726a58 SC |
937 | |
938 | #if wxUSE_OWNER_DRAWN | |
cee24bf7 DS |
939 | if ( m_windowStyle & wxLB_OWNERDRAW ) |
940 | { | |
b4726a58 SC |
941 | // first delete old items |
942 | size_t ui = m_aItems.Count(); | |
cee24bf7 DS |
943 | while ( ui != 0 ) |
944 | { | |
945 | ui--; | |
b4726a58 SC |
946 | delete m_aItems[ui]; |
947 | m_aItems[ui] = NULL; | |
948 | } | |
cee24bf7 | 949 | |
b4726a58 SC |
950 | m_aItems.Empty(); |
951 | ||
952 | // then create new ones | |
cee24bf7 DS |
953 | for ( ui = 0; ui < (size_t)m_noItems; ui++ ) |
954 | { | |
b4726a58 SC |
955 | wxOwnerDrawn *pNewItem = CreateItem(ui); |
956 | pNewItem->SetName(choices[ui]); | |
957 | m_aItems.Add(pNewItem); | |
958 | } | |
959 | } | |
cee24bf7 | 960 | #endif |
facd6764 SC |
961 | } |
962 | ||
11e62fe6 | 963 | int wxListBox::FindString(const wxString& s, bool bCase) const |
facd6764 | 964 | { |
b4726a58 | 965 | for ( size_t i = 0; i < m_noItems; ++ i ) |
facd6764 | 966 | { |
520b09fc | 967 | if (s.IsSameAs( GetString( i ), bCase) ) |
b4726a58 | 968 | return (int)i; |
facd6764 | 969 | } |
fdd4e6cc | 970 | |
11e62fe6 | 971 | return wxNOT_FOUND; |
facd6764 SC |
972 | } |
973 | ||
974 | void wxListBox::Clear() | |
975 | { | |
976 | FreeData(); | |
977 | m_noItems = 0; | |
b4726a58 SC |
978 | m_stringArray.Empty(); |
979 | m_dataArray.Empty(); | |
980 | GetPeer()->MacClear(); | |
facd6764 SC |
981 | } |
982 | ||
fdd4e6cc | 983 | void wxListBox::DoSetSelection(int n, bool select) |
facd6764 | 984 | { |
cee24bf7 | 985 | wxCHECK_RET( n == wxNOT_FOUND || IsValid(n), |
facd6764 | 986 | wxT("invalid index in wxListBox::SetSelection") ); |
c6179a84 | 987 | |
fdd4e6cc | 988 | if ( n == wxNOT_FOUND ) |
b4726a58 | 989 | GetPeer()->MacDeselectAll(); |
fe3dc505 | 990 | else |
cee24bf7 | 991 | GetPeer()->MacSetSelection( n, select ); |
facd6764 SC |
992 | } |
993 | ||
fdd4e6cc | 994 | bool wxListBox::IsSelected(int n) const |
facd6764 | 995 | { |
cee24bf7 | 996 | wxCHECK_MSG( IsValid(n), false, wxT("invalid index in wxListBox::Selected") ); |
c6179a84 | 997 | |
b4726a58 | 998 | return GetPeer()->MacIsSelected( n ); |
facd6764 SC |
999 | } |
1000 | ||
aa61d352 | 1001 | void *wxListBox::DoGetItemClientData(unsigned int n) const |
facd6764 | 1002 | { |
8228b893 WS |
1003 | wxCHECK_MSG( IsValid(n), NULL, wxT("invalid index in wxListBox::GetClientData")); |
1004 | ||
520b09fc | 1005 | wxASSERT_MSG( m_dataArray.GetCount() >= (unsigned int)n, wxT("invalid client_data array") ); |
c6179a84 | 1006 | |
520b09fc | 1007 | return (void*)m_dataArray[n]; |
facd6764 SC |
1008 | } |
1009 | ||
aa61d352 | 1010 | wxClientData *wxListBox::DoGetItemClientObject(unsigned int n) const |
facd6764 | 1011 | { |
520b09fc | 1012 | return (wxClientData*)DoGetItemClientData( n ); |
facd6764 SC |
1013 | } |
1014 | ||
aa61d352 | 1015 | void wxListBox::DoSetItemClientData(unsigned int n, void *clientData) |
facd6764 | 1016 | { |
8228b893 | 1017 | wxCHECK_RET( IsValid(n), wxT("invalid index in wxListBox::SetClientData") ); |
c6179a84 | 1018 | |
b4726a58 SC |
1019 | #if wxUSE_OWNER_DRAWN |
1020 | if ( m_windowStyle & wxLB_OWNERDRAW ) | |
1021 | { | |
1022 | // client data must be pointer to wxOwnerDrawn, otherwise we would crash | |
1023 | // in OnMeasure/OnDraw. | |
520b09fc | 1024 | wxFAIL_MSG(wxT("Cannot use client data with owner-drawn listboxes")); |
b4726a58 | 1025 | } |
cee24bf7 DS |
1026 | #endif |
1027 | ||
520b09fc | 1028 | wxASSERT_MSG( m_dataArray.GetCount() >= (unsigned int)n, wxT("invalid client_data array") ); |
c6179a84 | 1029 | |
520b09fc | 1030 | if ( m_dataArray.GetCount() > (unsigned int)n ) |
b4726a58 | 1031 | m_dataArray[n] = (char*)clientData; |
facd6764 | 1032 | else |
b4726a58 | 1033 | m_dataArray.Add( (char*)clientData ); |
facd6764 SC |
1034 | } |
1035 | ||
aa61d352 | 1036 | void wxListBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData) |
facd6764 SC |
1037 | { |
1038 | DoSetItemClientData(n, clientData); | |
1039 | } | |
1040 | ||
1041 | // Return number of selections and an array of selected integers | |
1042 | int wxListBox::GetSelections(wxArrayInt& aSelections) const | |
1043 | { | |
b4726a58 | 1044 | return GetPeer()->MacGetSelections( aSelections ); |
facd6764 SC |
1045 | } |
1046 | ||
1047 | // Get single selection, for single choice list items | |
1048 | int wxListBox::GetSelection() const | |
1049 | { | |
b4726a58 | 1050 | return GetPeer()->MacGetSelection(); |
facd6764 SC |
1051 | } |
1052 | ||
1053 | // Find string for position | |
aa61d352 | 1054 | wxString wxListBox::GetString(unsigned int n) const |
facd6764 | 1055 | { |
cee24bf7 | 1056 | wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("invalid index in wxListBox::GetString") ); |
55ae2833 | 1057 | |
cee24bf7 | 1058 | return m_stringArray[n]; |
facd6764 SC |
1059 | } |
1060 | ||
aa61d352 | 1061 | void wxListBox::DoInsertItems(const wxArrayString& items, unsigned int pos) |
facd6764 | 1062 | { |
cee24bf7 | 1063 | wxCHECK_RET( IsValidInsert(pos), wxT("invalid index in wxListBox::InsertItems") ); |
c6179a84 | 1064 | |
9f884528 RD |
1065 | InvalidateBestSize(); |
1066 | ||
aa61d352 | 1067 | unsigned int nItems = items.GetCount(); |
c6179a84 | 1068 | |
b4726a58 | 1069 | for ( unsigned int i = 0; i < nItems; i++ ) |
cee24bf7 DS |
1070 | m_stringArray.Insert( items[i], pos + i ); |
1071 | m_dataArray.Insert( NULL, pos, nItems ); | |
b4726a58 | 1072 | m_noItems += nItems; |
cee24bf7 | 1073 | GetPeer()->MacInsert( pos, items ); |
facd6764 SC |
1074 | } |
1075 | ||
aa61d352 | 1076 | void wxListBox::SetString(unsigned int n, const wxString& s) |
facd6764 | 1077 | { |
b4726a58 | 1078 | m_stringArray[n] = s; |
cee24bf7 | 1079 | GetPeer()->MacSet( n, s ); |
facd6764 SC |
1080 | } |
1081 | ||
1082 | wxSize wxListBox::DoGetBestSize() const | |
1083 | { | |
1084 | int lbWidth = 100; // some defaults | |
1085 | int lbHeight = 110; | |
1086 | int wLine; | |
1087 | ||
1088 | { | |
b4726a58 | 1089 | wxMacPortStateHelper st( UMAGetWindowPort( (WindowRef)MacGetTopLevelWindowRef() ) ); |
c6179a84 | 1090 | |
fdd4e6cc | 1091 | // TODO: clean this up |
facd6764 SC |
1092 | if ( m_font.Ok() ) |
1093 | { | |
b4726a58 SC |
1094 | ::TextFont( m_font.MacGetFontNum() ); |
1095 | ::TextSize( m_font.MacGetFontSize() ); | |
1096 | ::TextFace( m_font.MacGetFontStyle() ); | |
facd6764 SC |
1097 | } |
1098 | else | |
1099 | { | |
b4726a58 | 1100 | ::TextFont( kFontIDMonaco ); |
520b09fc | 1101 | ::TextSize( 9 ); |
b4726a58 | 1102 | ::TextFace( 0 ); |
facd6764 | 1103 | } |
c6179a84 | 1104 | |
facd6764 | 1105 | // Find the widest line |
aa61d352 | 1106 | for (unsigned int i = 0; i < GetCount(); i++) |
fdd4e6cc | 1107 | { |
520b09fc | 1108 | wxString str( GetString( i ) ); |
fdd4e6cc DS |
1109 | |
1110 | #if wxUSE_UNICODE | |
b4726a58 SC |
1111 | Point bounds = {0, 0}; |
1112 | SInt16 baseline; | |
fdd4e6cc DS |
1113 | |
1114 | // NB: what if m_font.Ok() == false ??? | |
1115 | ::GetThemeTextDimensions( | |
cee24bf7 | 1116 | wxMacCFStringHolder( str, m_font.GetEncoding() ), |
facd6764 SC |
1117 | kThemeCurrentPortFont, |
1118 | kThemeStateActive, | |
1119 | false, | |
1120 | &bounds, | |
1121 | &baseline ); | |
b4726a58 | 1122 | wLine = bounds.h; |
fdd4e6cc | 1123 | #else |
cee24bf7 | 1124 | wLine = ::TextWidth( str.c_str(), 0, str.length() ); |
fdd4e6cc DS |
1125 | #endif |
1126 | ||
1127 | lbWidth = wxMax( lbWidth, wLine ); | |
facd6764 | 1128 | } |
c6179a84 | 1129 | |
facd6764 | 1130 | // Add room for the scrollbar |
520b09fc | 1131 | lbWidth += wxSystemSettings::GetMetric( wxSYS_VSCROLL_X ); |
c6179a84 | 1132 | |
facd6764 | 1133 | // And just a bit more |
b4726a58 | 1134 | int cy = 12; |
cee24bf7 | 1135 | int cx = ::TextWidth( "X", 0, 1 ); |
b4726a58 | 1136 | lbWidth += cx; |
c6179a84 | 1137 | |
fdd4e6cc DS |
1138 | // don't make the listbox too tall (limit height to around 10 items) |
1139 | // but don't make it too small neither | |
9761ab43 | 1140 | lbHeight = wxMax( (cy + 4) * wxMin( wxMax( GetCount(), 3 ), 10 ), 70 ); |
facd6764 SC |
1141 | } |
1142 | ||
fdd4e6cc | 1143 | return wxSize( lbWidth, lbHeight ); |
facd6764 SC |
1144 | } |
1145 | ||
aa61d352 | 1146 | unsigned int wxListBox::GetCount() const |
facd6764 SC |
1147 | { |
1148 | return m_noItems; | |
1149 | } | |
1150 | ||
1151 | void wxListBox::Refresh(bool eraseBack, const wxRect *rect) | |
1152 | { | |
cee24bf7 | 1153 | wxControl::Refresh( eraseBack, rect ); |
facd6764 SC |
1154 | } |
1155 | ||
cee24bf7 | 1156 | void wxListBox::MacUpdateLine(int n) |
b6a20a20 | 1157 | { |
b4726a58 | 1158 | GetPeer()->UpdateLine(n); |
b6a20a20 RD |
1159 | } |
1160 | ||
b4726a58 | 1161 | #if wxUSE_OWNER_DRAWN |
facd6764 | 1162 | |
b4726a58 | 1163 | class wxListBoxItem : public wxOwnerDrawn |
facd6764 | 1164 | { |
b4726a58 SC |
1165 | public: |
1166 | wxListBoxItem(const wxString& str = ""); | |
1167 | }; | |
fdd4e6cc | 1168 | |
cee24bf7 DS |
1169 | wxListBoxItem::wxListBoxItem(const wxString& str) |
1170 | : wxOwnerDrawn(str, false) | |
facd6764 | 1171 | { |
b4726a58 | 1172 | // no bitmaps/checkmarks |
520b09fc | 1173 | SetMarginWidth( 0 ); |
facd6764 SC |
1174 | } |
1175 | ||
b4726a58 | 1176 | wxOwnerDrawn *wxListBox::CreateItem(size_t n) |
facd6764 | 1177 | { |
b4726a58 | 1178 | return new wxListBoxItem(); |
facd6764 SC |
1179 | } |
1180 | ||
cee24bf7 | 1181 | #endif // USE_OWNER_DRAWN |
fdd4e6cc | 1182 | |
facd6764 | 1183 | |
b4726a58 SC |
1184 | // Some custom controls depend on this |
1185 | /* static */ wxVisualAttributes | |
1186 | wxListBox::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant)) | |
facd6764 | 1187 | { |
b4726a58 | 1188 | wxVisualAttributes attr; |
519cb848 | 1189 | |
b4726a58 SC |
1190 | attr.colFg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ); |
1191 | attr.colBg = wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX ); | |
1192 | attr.font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); | |
e42e45a9 | 1193 | |
b4726a58 | 1194 | return attr; |
facd6764 SC |
1195 | } |
1196 | ||
443e2f09 VZ |
1197 | int wxListBox::DoListHitTest(const wxPoint& inpoint) const |
1198 | { | |
cee24bf7 | 1199 | OSStatus err; |
443e2f09 VZ |
1200 | |
1201 | // There are few reasons why this is complicated: | |
cee24bf7 | 1202 | // 1) There is no native HitTest function for Mac |
443e2f09 VZ |
1203 | // 2) GetDataBrowserItemPartBounds only works on visible items |
1204 | // 3) We can't do it through GetDataBrowserTableView[Item]RowHeight | |
1205 | // because what it returns is basically inaccurate in the context | |
1206 | // of the coordinates we want here, but we use this as a guess | |
1207 | // for where the first visible item lies | |
1208 | ||
1209 | wxPoint point = inpoint; | |
cee24bf7 | 1210 | |
443e2f09 VZ |
1211 | // interestingly enough 10.2 (and below?) have GetDataBrowserItemPartBounds |
1212 | // giving root window coordinates but 10.3 and above give client coordinates | |
1213 | // so we only compare using root window coordinates on 10.3 and up | |
1214 | if ( UMAGetSystemVersion() < 0x1030 ) | |
1215 | MacClientToRootWindow(&point.x, &point.y); | |
1216 | ||
cee24bf7 | 1217 | // get column property ID (req. for call to itempartbounds) |
c00fed0e | 1218 | DataBrowserTableViewColumnID colId = 0; |
443e2f09 VZ |
1219 | err = GetDataBrowserTableViewColumnProperty(m_peer->GetControlRef(), 0, &colId); |
1220 | wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserTableViewColumnProperty")); | |
1221 | ||
1222 | // OK, first we need to find the first visible item we have - | |
1223 | // this will be the "low" for our binary search. There is no real | |
1224 | // easy way around this, as we will need to do a SLOW linear search | |
1225 | // until we find a visible item, but we can do a cheap calculation | |
1226 | // via the row height to speed things up a bit | |
1227 | UInt32 scrollx, scrolly; | |
1228 | err = GetDataBrowserScrollPosition(m_peer->GetControlRef(), &scrollx, &scrolly); | |
1229 | wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserScrollPosition")); | |
1230 | ||
1231 | UInt16 height; | |
1232 | err = GetDataBrowserTableViewRowHeight(m_peer->GetControlRef(), &height); | |
1233 | wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserTableViewRowHeight")); | |
1234 | ||
1235 | // these indices are 0-based, as usual, so we need to add 1 to them when | |
1236 | // passing them to data browser functions which use 1-based indices | |
1237 | int low = scrolly / height, | |
1238 | high = GetCount() - 1; | |
1239 | ||
443e2f09 VZ |
1240 | // search for the first visible item (note that the scroll guess above |
1241 | // is the low bounds of where the item might lie so we only use that as a | |
1242 | // starting point - we should reach it within 1 or 2 iterations of the loop) | |
1243 | while ( low <= high ) | |
1244 | { | |
1245 | Rect bounds; | |
cee24bf7 DS |
1246 | err = GetDataBrowserItemPartBounds( |
1247 | m_peer->GetControlRef(), low + 1, colId, | |
1248 | kDataBrowserPropertyEnclosingPart, | |
1249 | &bounds); // note +1 to translate to Mac ID | |
443e2f09 VZ |
1250 | if ( err == noErr ) |
1251 | break; | |
1252 | ||
1253 | // errDataBrowserItemNotFound is expected as it simply means that the | |
1254 | // item is not currently visible -- but other errors are not | |
1255 | wxCHECK_MSG( err == errDataBrowserItemNotFound, wxNOT_FOUND, | |
1256 | wxT("Unexpected error from GetDataBrowserItemPartBounds") ); | |
1257 | ||
1258 | low++; | |
1259 | } | |
c00fed0e | 1260 | |
443e2f09 VZ |
1261 | // NOW do a binary search for where the item lies, searching low again if |
1262 | // we hit an item that isn't visible | |
1263 | while ( low <= high ) | |
c00fed0e | 1264 | { |
443e2f09 VZ |
1265 | int mid = (low + high) / 2; |
1266 | ||
c00fed0e | 1267 | Rect bounds; |
cee24bf7 DS |
1268 | err = GetDataBrowserItemPartBounds( |
1269 | m_peer->GetControlRef(), mid + 1, colId, | |
1270 | kDataBrowserPropertyEnclosingPart, | |
1271 | &bounds); //note +1 to trans to mac id | |
443e2f09 VZ |
1272 | wxCHECK_MSG( err == noErr || err == errDataBrowserItemNotFound, |
1273 | wxNOT_FOUND, | |
1274 | wxT("Unexpected error from GetDataBrowserItemPartBounds") ); | |
1275 | ||
1276 | if ( err == errDataBrowserItemNotFound ) | |
c00fed0e | 1277 | { |
443e2f09 | 1278 | // item not visible, attempt to find a visible one |
cee24bf7 DS |
1279 | // search lower |
1280 | high = mid - 1; | |
443e2f09 VZ |
1281 | } |
1282 | else // visible item, do actual hitttest | |
1283 | { | |
1284 | // if point is within the bounds, return this item (since we assume | |
1285 | // all x coords of items are equal we only test the x coord in | |
1286 | // equality) | |
cee24bf7 | 1287 | if ((point.x >= bounds.left && point.x <= bounds.right) && |
443e2f09 VZ |
1288 | (point.y >= bounds.top && point.y <= bounds.bottom) ) |
1289 | { | |
cee24bf7 DS |
1290 | // found! |
1291 | return mid; | |
443e2f09 VZ |
1292 | } |
1293 | ||
1294 | if ( point.y < bounds.top ) | |
cee24bf7 DS |
1295 | // index(bounds) greater then key(point) |
1296 | high = mid - 1; | |
443e2f09 | 1297 | else |
cee24bf7 DS |
1298 | // index(bounds) less then key(point) |
1299 | low = mid + 1; | |
c00fed0e VZ |
1300 | } |
1301 | } | |
443e2f09 | 1302 | |
c00fed0e VZ |
1303 | return wxNOT_FOUND; |
1304 | } | |
1305 | ||
179e085f | 1306 | #endif |