1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/listbox.cpp
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
17 #include "wx/listbox.h"
18 #include "wx/checklst.h"
19 #include "wx/button.h"
20 #include "wx/settings.h"
21 #include "wx/toplevel.h"
22 #include "wx/dynarray.h"
27 IMPLEMENT_DYNAMIC_CLASS(wxListBox
, wxControl
)
29 BEGIN_EVENT_TABLE(wxListBox
, wxControl
)
32 #include "wx/mac/uma.h"
34 // common interface for all implementations
35 class wxMacListControl
: public wxMacControl
38 wxMacListControl( wxListBox
*peer
) :
47 virtual void UpdateLine( int n
) = 0;
49 virtual void MacDelete( int n
) = 0;
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;
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;
58 virtual int MacGetSelections(wxArrayInt
& aSelections
) const = 0;
59 virtual bool MacIsSelected( int n
) const= 0;
60 virtual void MacScrollTo( int n
) = 0;
62 wxListBox
* GetPeer() const
64 return (wxListBox
*)m_peer
;
69 // In case we have to replace data browser ...
70 // custom HIView-based implementation
72 class wxMacCustomHIViewListControl
: public wxMacListControl
75 wxMacCustomHIViewListControl( wxListBox
*peer
, const wxPoint
& pos
, const wxSize
& size
, long style
);
76 ~wxMacCustomHIViewListControl();
78 void MacDelete( int n
);
79 void MacInsert( int n
, const wxString
& item
);
80 void MacInsert( int n
, const wxArrayString
& items
);
81 void MacAppend( const wxString
& item
);
82 void MacSet( int n
, const wxString
& item
);
84 void MacDeselectAll();
85 void MacSetSelection( int n
, bool select
);
86 int MacGetSelection() const;
87 int MacGetSelections(wxArrayInt
& aSelections
) const;
88 bool MacIsSelected( int n
) const;
89 void MacScrollTo( int n
);
93 // DataBrowser-based implementation
95 class wxMacDataBrowserListControl
: public wxMacListControl
98 wxMacDataBrowserListControl( wxListBox
*peer
, const wxPoint
& pos
, const wxSize
& size
, long style
);
99 ~wxMacDataBrowserListControl();
101 void UpdateLine( int n
);
103 void MacDelete( int n
);
104 void MacInsert( int n
, const wxString
& item
);
105 void MacInsert( int n
, const wxArrayString
& items
);
106 void MacAppend( const wxString
& item
);
107 void MacSet( int n
, const wxString
& item
);
109 void MacDeselectAll();
110 void MacSetSelection( int n
, bool select
);
111 int MacGetSelection() const;
112 int MacGetSelections(wxArrayInt
& aSelections
) const;
113 bool MacIsSelected( int n
) const;
114 void MacScrollTo( int n
);
116 virtual OSStatus
SetSelectionFlags( DataBrowserSelectionFlags
);
117 virtual OSStatus
AddListViewColumn( DataBrowserListViewColumnDesc
*columnDesc
,
118 DataBrowserTableViewColumnIndex position
);
119 virtual OSStatus
AutoSizeListViewColumns();
120 virtual OSStatus
SetHasScrollBars( bool horiz
, bool vert
);
121 virtual OSStatus
SetTableViewHiliteStyle( DataBrowserTableViewHiliteStyle hiliteStyle
);
122 virtual OSStatus
SetListViewHeaderBtnHeight(UInt16 height
);
123 virtual OSStatus
SetCallbacks(const DataBrowserCallbacks
*callbacks
);
124 virtual OSStatus
UpdateItems( DataBrowserItemID container
, UInt32 numItems
,
125 const DataBrowserItemID
*items
,
126 DataBrowserPropertyID preSortProperty
,
127 DataBrowserPropertyID propertyID
);
128 virtual OSStatus
AddItems( DataBrowserItemID container
, UInt32 numItems
,
129 const DataBrowserItemID
*items
,
130 DataBrowserPropertyID preSortProperty
);
131 virtual OSStatus
RemoveItems( DataBrowserItemID container
, UInt32 numItems
,
132 const DataBrowserItemID
*items
,
133 DataBrowserPropertyID preSortProperty
);
134 virtual OSStatus
RevealItem( DataBrowserItemID item
,
135 DataBrowserPropertyID propertyID
,
136 DataBrowserRevealOptions options
);
137 virtual OSStatus
GetSelectionAnchor( DataBrowserItemID
*first
, DataBrowserItemID
*last
) const;
138 virtual bool IsItemSelected( DataBrowserItemID item
) const;
139 virtual OSStatus
SetSelectedItems(UInt32 numItems
,
140 const DataBrowserItemID
*items
,
141 DataBrowserSetOption operation
);
144 // as we are getting the same events for human and API selection we have to suppress
145 // events in the latter case
146 bool MacSuppressSelection( bool suppress
);
147 bool MacIsSelectionSuppressed() const { return m_suppressSelection
; }
149 bool m_suppressSelection
;
151 #if TARGET_API_MAC_OSX
152 static pascal void DataBrowserItemNotificationProc(
154 DataBrowserItemID itemID
,
155 DataBrowserItemNotification message
,
156 DataBrowserItemDataRef itemData
);
158 static pascal void DataBrowserItemNotificationProc(
160 DataBrowserItemID itemID
,
161 DataBrowserItemNotification message
);
165 // ============================================================================
166 // data browser based implementation
167 // ============================================================================
169 const short kTextColumnId
= 1024;
170 const short kCheckboxColumnId
= 1025;
172 // new databrowserbased version
173 // because of the limited insert
174 // functionality of DataBrowser,
175 // we just introduce id s corresponding
176 // to the line number
178 DataBrowserItemDataUPP gDataBrowserItemDataUPP
= NULL
;
179 DataBrowserItemNotificationUPP gDataBrowserItemNotificationUPP
= NULL
;
181 #if TARGET_API_MAC_OSX
182 pascal void wxMacDataBrowserListControl::DataBrowserItemNotificationProc(
184 DataBrowserItemID itemID
,
185 DataBrowserItemNotification message
,
186 DataBrowserItemDataRef itemData
)
188 pascal void wxMacDataBrowserListControl::DataBrowserItemNotificationProc(
190 DataBrowserItemID itemID
,
191 DataBrowserItemNotification message
)
194 long ref
= GetControlReference( browser
);
197 wxListBox
*list
= wxDynamicCast( (wxObject
*)ref
, wxListBox
);
198 wxMacDataBrowserListControl
* peer
= (wxMacDataBrowserListControl
*) list
->GetPeer();
201 if (i
>= 0 && i
< (int)list
->GetCount())
203 bool trigger
= false;
204 wxCommandEvent
event( wxEVT_COMMAND_LISTBOX_SELECTED
, list
->GetId() );
207 case kDataBrowserItemDeselected
:
208 if ( list
->HasMultipleSelection() )
209 trigger
= !peer
->MacIsSelectionSuppressed();
212 case kDataBrowserItemSelected
:
213 trigger
= !peer
->MacIsSelectionSuppressed();
216 case kDataBrowserItemDoubleClicked
:
217 event
.SetEventType( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
);
227 event
.SetEventObject( list
);
228 if ( list
->HasClientObjectData() )
229 event
.SetClientObject( list
->GetClientObject( i
) );
230 else if ( list
->HasClientUntypedData() )
231 event
.SetClientData( list
->GetClientData( i
) );
232 event
.SetString( list
->GetString( i
) );
234 event
.SetExtraLong( list
->HasMultipleSelection() ? message
== kDataBrowserItemSelected
: true );
235 wxPostEvent( list
->GetEventHandler(), event
);
236 // direct notification is not always having the listbox GetSelection() having in synch with event
237 // list->GetEventHandler()->ProcessEvent(event);
243 static pascal OSStatus
ListBoxGetSetItemData(ControlRef browser
,
244 DataBrowserItemID itemID
, DataBrowserPropertyID property
,
245 DataBrowserItemDataRef itemData
, Boolean changeValue
)
247 OSStatus err
= errDataBrowserPropertyNotSupported
;
249 long ref
= GetControlReference( browser
);
253 wxListBox
* list
= wxDynamicCast( (wxObject
*) ref
, wxListBox
);
254 bool isCheckList
= false;
256 isCheckList
= list
->IsKindOf( CLASSINFO(wxCheckListBox
) );
264 if (i
>= 0 && i
< (int)list
->GetCount() )
266 wxMacCFStringHolder
cf( list
->GetString( i
), list
->GetFont().GetEncoding() );
267 verify_noerr( ::SetDataBrowserItemDataText( itemData
, cf
) );
273 case kCheckboxColumnId
:
276 wxCheckListBox
* list
= wxDynamicCast( (wxObject
*) ref
, wxCheckListBox
);
278 if (i
>= 0 && (unsigned int) i
< list
->GetCount())
280 verify_noerr( ::SetDataBrowserItemDataButtonValue( itemData
, list
->IsChecked( i
) ? kThemeButtonOn
: kThemeButtonOff
) );
286 case kDataBrowserItemIsEditableProperty
:
288 err
= ::SetDataBrowserItemDataBooleanValue(itemData
, true);
299 case kCheckboxColumnId
:
302 wxCheckListBox
* list
= wxDynamicCast( (wxObject
*) ref
, wxCheckListBox
);
304 if (i
>= 0 && (unsigned int)i
< list
->GetCount() )
306 // we have to change this behind the back, since Check() would be triggering another update round
307 bool newVal
= !list
->IsChecked( i
);
308 verify_noerr( ::SetDataBrowserItemDataButtonValue( itemData
, newVal
? kThemeButtonOn
: kThemeButtonOff
) );
310 list
->m_checks
[i
] = newVal
;
312 wxCommandEvent
event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, list
->GetId());
314 event
.SetEventObject(list
);
315 list
->GetEventHandler()->ProcessEvent(event
);
328 wxMacDataBrowserListControl::wxMacDataBrowserListControl( wxListBox
*peer
, const wxPoint
& pos
, const wxSize
& size
, long style
)
329 : wxMacListControl( peer
)
331 bool isCheckList
= peer
->IsKindOf( CLASSINFO(wxCheckListBox
));
333 m_suppressSelection
= false;
334 Rect bounds
= wxMacGetBoundsForControl( peer
, pos
, size
);
335 OSStatus err
= ::CreateDataBrowserControl(
336 MAC_WXHWND(peer
->MacGetTopLevelWindowRef()),
337 &bounds
, kDataBrowserListView
, &m_controlRef
);
340 DataBrowserSelectionFlags options
= kDataBrowserDragSelect
;
341 if ( style
& wxLB_MULTIPLE
)
343 options
|= kDataBrowserAlwaysExtendSelection
| kDataBrowserCmdTogglesSelection
;
345 else if ( style
& wxLB_EXTENDED
)
351 options
|= kDataBrowserSelectOnlyOne
;
353 err
= SetSelectionFlags( options
);
356 if ( gDataBrowserItemDataUPP
== NULL
)
357 gDataBrowserItemDataUPP
= NewDataBrowserItemDataUPP(ListBoxGetSetItemData
);
358 if ( gDataBrowserItemNotificationUPP
== NULL
)
360 gDataBrowserItemNotificationUPP
=
361 #if TARGET_API_MAC_OSX
362 (DataBrowserItemNotificationUPP
) NewDataBrowserItemNotificationWithItemUPP(DataBrowserItemNotificationProc
);
364 NewDataBrowserItemNotificationUPP(DataBrowserItemNotificationProc
);
368 DataBrowserCallbacks callbacks
;
369 InitializeDataBrowserCallbacks( &callbacks
, kDataBrowserLatestCallbacks
);
371 callbacks
.u
.v1
.itemDataCallback
= gDataBrowserItemDataUPP
;
372 callbacks
.u
.v1
.itemNotificationCallback
= gDataBrowserItemNotificationUPP
;
373 SetCallbacks( &callbacks
);
375 DataBrowserListViewColumnDesc columnDesc
;
376 columnDesc
.headerBtnDesc
.titleOffset
= 0;
377 columnDesc
.headerBtnDesc
.version
= kDataBrowserListViewLatestHeaderDesc
;
379 columnDesc
.headerBtnDesc
.btnFontStyle
.flags
=
380 kControlUseFontMask
| kControlUseJustMask
;
382 columnDesc
.headerBtnDesc
.btnContentInfo
.contentType
= kControlNoContent
;
383 columnDesc
.headerBtnDesc
.btnFontStyle
.just
= teFlushDefault
;
384 columnDesc
.headerBtnDesc
.btnFontStyle
.font
= kControlFontViewSystemFont
;
385 columnDesc
.headerBtnDesc
.btnFontStyle
.style
= normal
;
386 columnDesc
.headerBtnDesc
.titleString
= NULL
;
390 columnDesc
.headerBtnDesc
.minimumWidth
= 30;
391 columnDesc
.headerBtnDesc
.maximumWidth
= 30;
393 columnDesc
.propertyDesc
.propertyID
= kCheckboxColumnId
;
394 columnDesc
.propertyDesc
.propertyType
= kDataBrowserCheckboxType
;
395 columnDesc
.propertyDesc
.propertyFlags
=
396 kDataBrowserPropertyIsMutable
397 | kDataBrowserTableViewSelectionColumn
398 | kDataBrowserDefaultPropertyFlags
;
399 err
= AddListViewColumn( &columnDesc
, kDataBrowserListViewAppendColumn
);
403 columnDesc
.headerBtnDesc
.minimumWidth
= 0;
404 columnDesc
.headerBtnDesc
.maximumWidth
= 10000;
407 columnDesc
.propertyDesc
.propertyID
= kTextColumnId
;
408 columnDesc
.propertyDesc
.propertyType
= kDataBrowserTextType
;
409 columnDesc
.propertyDesc
.propertyFlags
= kDataBrowserTableViewSelectionColumn
;
410 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
411 columnDesc
.propertyDesc
.propertyFlags
|= kDataBrowserListViewTypeSelectColumn
;
414 verify_noerr( AddListViewColumn( &columnDesc
, kDataBrowserListViewAppendColumn
) );
415 verify_noerr( AutoSizeListViewColumns() );
416 verify_noerr( SetHasScrollBars( false, true ) );
417 verify_noerr( SetTableViewHiliteStyle(kDataBrowserTableViewFillHilite
) );
418 verify_noerr( SetListViewHeaderBtnHeight( 0 ) );
421 // shouldn't be necessary anymore under 10.2
422 m_peer
->SetData( kControlNoPart
, kControlDataBrowserIncludesFrameAndFocusTag
, (Boolean
)false );
423 m_peer
->SetNeedsFocusRect( true );
427 wxMacDataBrowserListControl::~wxMacDataBrowserListControl()
431 void wxMacDataBrowserListControl::MacDelete( int n
)
433 wxArrayInt selectionBefore
;
434 MacGetSelections( selectionBefore
);
436 UInt32 id
= GetPeer()->GetCount() + 1;
438 OSStatus err
= RemoveItems( kDataBrowserNoItem
, 1, (UInt32
*) &id
, kDataBrowserItemNoProperty
);
441 for ( size_t i
= 0; i
< selectionBefore
.GetCount(); ++i
)
443 int current
= selectionBefore
[i
];
446 // selection was deleted
447 MacSetSelection( current
, false );
449 else if ( current
> n
)
451 // something behind the deleted item was selected -> move up
452 MacSetSelection( current
- 1, true );
453 MacSetSelection( current
, false );
459 kDataBrowserNoItem
, 1, (UInt32
*)kDataBrowserNoItem
,
460 kDataBrowserItemNoProperty
, kDataBrowserItemNoProperty
);
464 void wxMacDataBrowserListControl::MacInsert( int n
, const wxString
& text
)
466 wxArrayInt selectionBefore
;
467 MacGetSelections( selectionBefore
);
469 UInt32 id
= GetPeer()->GetCount(); // this has already been increased
470 OSStatus err
= AddItems( kDataBrowserNoItem
, 1, (UInt32
*) &id
, kDataBrowserItemNoProperty
);
473 for ( int i
= selectionBefore
.GetCount() - 1; i
>= 0; --i
)
475 int current
= selectionBefore
[i
];
478 MacSetSelection( current
+ 1, true );
479 MacSetSelection( current
, false );
485 kDataBrowserNoItem
, 1, (UInt32
*)kDataBrowserNoItem
,
486 kDataBrowserItemNoProperty
, kDataBrowserItemNoProperty
);
490 void wxMacDataBrowserListControl::MacInsert( int n
, const wxArrayString
& items
)
492 wxArrayInt selectionBefore
;
493 MacGetSelections( selectionBefore
);
494 size_t itemsCount
= items
.GetCount();
496 UInt32
*ids
= new UInt32
[itemsCount
];
497 for ( unsigned int i
= 0; i
< itemsCount
; ++i
)
498 ids
[i
] = GetPeer()->GetCount() - itemsCount
+ i
+ 1;
500 OSStatus err
= AddItems( kDataBrowserNoItem
, itemsCount
, ids
, kDataBrowserItemNoProperty
);
504 for ( int i
= selectionBefore
.GetCount() - 1; i
>= 0; --i
)
506 int current
= selectionBefore
[i
];
509 MacSetSelection( current
+ 1, true );
510 MacSetSelection( current
, false );
516 kDataBrowserNoItem
, 1, (UInt32
*)kDataBrowserNoItem
,
517 kDataBrowserItemNoProperty
, kDataBrowserItemNoProperty
);
521 void wxMacDataBrowserListControl::MacAppend( const wxString
& text
)
523 UInt32 id
= GetPeer()->GetCount(); // this has already been increased
524 verify_noerr( AddItems( kDataBrowserNoItem
, 1, (UInt32
*) &id
, kDataBrowserItemNoProperty
) );
525 // no need to deal with selections nor refreshed, as we have appended
528 void wxMacDataBrowserListControl::MacClear()
530 verify_noerr( RemoveItems( kDataBrowserNoItem
, 0, NULL
, kDataBrowserItemNoProperty
) );
533 void wxMacDataBrowserListControl::MacDeselectAll()
535 bool former
= MacSuppressSelection( true );
536 verify_noerr(SetSelectedItems( 0, NULL
, kDataBrowserItemsRemove
) );
537 MacSuppressSelection( former
);
540 void wxMacDataBrowserListControl::MacSetSelection( int n
, bool select
)
543 bool former
= MacSuppressSelection( true );
545 if ( IsItemSelected( id
) != select
)
550 err
= SetSelectedItems( 1, &id
, GetPeer()->HasMultipleSelection() ? kDataBrowserItemsAdd
: kDataBrowserItemsAssign
);
552 err
= SetSelectedItems( 1, &id
, kDataBrowserItemsRemove
);
558 MacSuppressSelection( former
);
561 bool wxMacDataBrowserListControl::MacSuppressSelection( bool suppress
)
563 bool former
= m_suppressSelection
;
564 m_suppressSelection
= suppress
;
569 bool wxMacDataBrowserListControl::MacIsSelected( int n
) const
571 return IsItemSelected( n
+ 1 );
574 int wxMacDataBrowserListControl::MacGetSelection() const
576 for ( unsigned int i
= 0; i
< GetPeer()->GetCount(); ++i
)
578 if ( IsItemSelected( i
+ 1 ) )
587 int wxMacDataBrowserListControl::MacGetSelections( wxArrayInt
& aSelections
) const
594 GetSelectionAnchor( &first
, &last
);
595 if ( first
!= kDataBrowserNoItem
)
597 for ( size_t i
= first
; i
<= last
; ++i
)
599 if ( IsItemSelected( i
) )
601 aSelections
.Add( i
- 1 );
610 void wxMacDataBrowserListControl::MacSet( int n
, const wxString
& text
)
612 // as we don't store the strings we only have to issue a redraw
614 verify_noerr( UpdateItems( kDataBrowserNoItem
, 1, &id
, kDataBrowserItemNoProperty
, kDataBrowserItemNoProperty
) );
617 void wxMacDataBrowserListControl::MacScrollTo( int n
)
620 verify_noerr( RevealItem( id
, kTextColumnId
, kDataBrowserRevealWithoutSelecting
) );
623 void wxMacDataBrowserListControl::UpdateLine( int n
)
626 verify_noerr( UpdateItems(kDataBrowserNoItem
, 1, &id
, kDataBrowserItemNoProperty
, kDataBrowserItemNoProperty
) );
633 OSStatus
wxMacDataBrowserListControl::SetSelectionFlags( DataBrowserSelectionFlags options
)
635 return SetDataBrowserSelectionFlags( m_controlRef
, options
);
638 OSStatus
wxMacDataBrowserListControl::AddListViewColumn( DataBrowserListViewColumnDesc
*columnDesc
,
639 DataBrowserTableViewColumnIndex position
)
641 return AddDataBrowserListViewColumn( m_controlRef
, columnDesc
, position
);
644 OSStatus
wxMacDataBrowserListControl::AutoSizeListViewColumns()
646 return AutoSizeDataBrowserListViewColumns(m_controlRef
);
649 OSStatus
wxMacDataBrowserListControl::SetHasScrollBars( bool horiz
, bool vert
)
651 return SetDataBrowserHasScrollBars( m_controlRef
, horiz
, vert
);
654 OSStatus
wxMacDataBrowserListControl::SetTableViewHiliteStyle( DataBrowserTableViewHiliteStyle hiliteStyle
)
656 return SetDataBrowserTableViewHiliteStyle( m_controlRef
, hiliteStyle
);
659 OSStatus
wxMacDataBrowserListControl::SetListViewHeaderBtnHeight(UInt16 height
)
661 return SetDataBrowserListViewHeaderBtnHeight( m_controlRef
, height
);
664 OSStatus
wxMacDataBrowserListControl::SetCallbacks(const DataBrowserCallbacks
*callbacks
)
666 return SetDataBrowserCallbacks( m_controlRef
, callbacks
);
669 OSStatus
wxMacDataBrowserListControl::UpdateItems(
670 DataBrowserItemID container
,
672 const DataBrowserItemID
*items
,
673 DataBrowserPropertyID preSortProperty
,
674 DataBrowserPropertyID propertyID
)
676 return UpdateDataBrowserItems( m_controlRef
, container
, numItems
, items
, preSortProperty
, propertyID
);
679 bool wxMacDataBrowserListControl::IsItemSelected( DataBrowserItemID item
) const
681 return IsDataBrowserItemSelected( m_controlRef
, item
);
684 OSStatus
wxMacDataBrowserListControl::AddItems(
685 DataBrowserItemID container
,
687 const DataBrowserItemID
*items
,
688 DataBrowserPropertyID preSortProperty
)
690 return AddDataBrowserItems( m_controlRef
, container
, numItems
, items
, preSortProperty
);
693 OSStatus
wxMacDataBrowserListControl::RemoveItems(
694 DataBrowserItemID container
,
696 const DataBrowserItemID
*items
,
697 DataBrowserPropertyID preSortProperty
)
699 return RemoveDataBrowserItems( m_controlRef
, container
, numItems
, items
, preSortProperty
);
702 OSStatus
wxMacDataBrowserListControl::RevealItem(
703 DataBrowserItemID item
,
704 DataBrowserPropertyID propertyID
,
705 DataBrowserRevealOptions options
)
707 return RevealDataBrowserItem( m_controlRef
, item
, propertyID
, options
);
710 OSStatus
wxMacDataBrowserListControl::SetSelectedItems(
712 const DataBrowserItemID
*items
,
713 DataBrowserSetOption operation
)
715 return SetDataBrowserSelectedItems( m_controlRef
, numItems
, items
, operation
);
718 OSStatus
wxMacDataBrowserListControl::GetSelectionAnchor( DataBrowserItemID
*first
, DataBrowserItemID
*last
) const
720 return GetDataBrowserSelectionAnchor( m_controlRef
, first
, last
);
725 // in case we need that one day
727 // ============================================================================
728 // HIView owner-draw-based implementation
729 // ============================================================================
731 static pascal void ListBoxDrawProc(
732 ControlRef browser
, DataBrowserItemID item
, DataBrowserPropertyID property
,
733 DataBrowserItemState itemState
, const Rect
*itemRect
, SInt16 depth
, Boolean isColorDevice
)
735 CFStringRef cfString
;
736 ThemeDrawingState themeState
;
739 GetThemeDrawingState( &themeState
);
740 cfString
= CFStringCreateWithFormat( NULL
, NULL
, CFSTR("Row %d"), item
);
742 // In this sample we handle the "selected" state; all others fall through to our "active" state
743 if ( itemState
== kDataBrowserItemIsSelected
)
745 ThemeBrush colorBrushID
;
747 // TODO: switch over to wxSystemSettingsNative::GetColour() when kThemeBrushSecondaryHighlightColor
748 // is incorporated Panther DB starts using kThemeBrushSecondaryHighlightColor
749 // for inactive browser highlighting
750 Gestalt( gestaltSystemVersion
, &systemVersion
);
751 if ( (systemVersion
>= 0x00001030) && !IsControlActive( browser
) )
752 colorBrushID
= kThemeBrushSecondaryHighlightColor
;
754 colorBrushID
= kThemeBrushPrimaryHighlightColor
;
756 // First paint the hilite rect, then the text on top
757 SetThemePen( colorBrushID
, 32, true );
758 PaintRect( itemRect
);
759 SetThemeDrawingState( themeState
, false );
762 DrawThemeTextBox( cfString
, kThemeApplicationFont
, kThemeStateActive
, true, itemRect
, teFlushDefault
, NULL
);
763 SetThemeDrawingState( themeState
, true );
765 if ( cfString
!= NULL
)
766 CFRelease( cfString
);
770 // ============================================================================
771 // list box control implementation
772 // ============================================================================
774 wxListBox::wxListBox()
779 bool wxListBox::Create(wxWindow
*parent
,
783 const wxArrayString
& choices
,
785 const wxValidator
& validator
,
786 const wxString
& name
)
788 wxCArrayString
chs(choices
);
791 parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(),
792 style
, validator
, name
);
795 bool wxListBox::Create(wxWindow
*parent
,
800 const wxString choices
[],
802 const wxValidator
& validator
,
803 const wxString
& name
)
805 m_macIsUserPane
= false;
807 wxASSERT_MSG( !(style
& wxLB_MULTIPLE
) || !(style
& wxLB_EXTENDED
),
808 _T("only one of listbox selection modes can be specified") );
810 if ( !wxListBoxBase::Create(parent
, id
, pos
, size
, style
& ~(wxHSCROLL
| wxVSCROLL
), validator
, name
) )
813 // this will be increased by our append command
816 m_peer
= CreateMacListControl( pos
, size
, style
);
818 MacPostControlCreate( pos
, size
);
820 InsertItems( n
, choices
, 0 );
822 // Needed because it is a wxControlWithItems
828 wxListBox::~wxListBox()
830 m_peer
->SetReference( 0 );
834 wxMacListControl
* wxListBox::CreateMacListControl(const wxPoint
& pos
, const wxSize
& size
, long style
)
836 return new wxMacDataBrowserListControl( this, pos
, size
, style
);
839 void wxListBox::FreeData()
841 #if wxUSE_OWNER_DRAWN
842 if ( m_windowStyle
& wxLB_OWNERDRAW
)
844 size_t uiCount
= m_aItems
.Count();
845 while ( uiCount
!= 0 )
848 delete m_aItems
[uiCount
];
849 m_aItems
[uiCount
] = NULL
;
856 if ( HasClientObjectData() )
858 for ( unsigned int n
= 0; n
< m_noItems
; n
++ )
860 delete GetClientObject( n
);
865 void wxListBox::DoSetSize(int x
, int y
,
866 int width
, int height
,
869 wxControl::DoSetSize( x
, y
, width
, height
, sizeFlags
);
872 void wxListBox::DoSetFirstItem(int n
)
874 GetPeer()->MacScrollTo( n
);
877 void wxListBox::Delete(unsigned int n
)
879 wxCHECK_RET( IsValid(n
), wxT("invalid index in wxListBox::Delete") );
881 #if wxUSE_OWNER_DRAWN
883 m_aItems
.RemoveAt(n
);
885 if ( HasClientObjectData() )
887 delete GetClientObject(n
);
891 m_stringArray
.RemoveAt( n
);
892 m_dataArray
.RemoveAt( n
);
895 GetPeer()->MacDelete( n
);
898 int wxListBox::DoAppend(const wxString
& item
)
900 InvalidateBestSize();
902 unsigned int index
= m_noItems
;
903 m_stringArray
.Add( item
);
904 m_dataArray
.Add( NULL
);
906 DoSetItemClientData( index
, NULL
);
907 GetPeer()->MacAppend( item
);
912 void wxListBox::DoSetItems(const wxArrayString
& choices
, void** clientData
)
915 unsigned int n
= choices
.GetCount();
917 for ( size_t i
= 0; i
< n
; ++i
)
921 #if wxUSE_OWNER_DRAWN
922 wxASSERT_MSG(clientData
[i
] == NULL
,
923 wxT("Can't use client data with owner-drawn listboxes"));
925 Append( choices
[i
], clientData
[i
] );
929 Append( choices
[i
] );
932 #if wxUSE_OWNER_DRAWN
933 if ( m_windowStyle
& wxLB_OWNERDRAW
)
935 // first delete old items
936 size_t ui
= m_aItems
.Count();
946 // then create new ones
947 for ( ui
= 0; ui
< (size_t)m_noItems
; ui
++ )
949 wxOwnerDrawn
*pNewItem
= CreateItem(ui
);
950 pNewItem
->SetName(choices
[ui
]);
951 m_aItems
.Add(pNewItem
);
957 int wxListBox::FindString(const wxString
& s
, bool bCase
) const
959 for ( size_t i
= 0; i
< m_noItems
; ++ i
)
961 if (s
.IsSameAs(GetString(i
), bCase
))
968 void wxListBox::Clear()
972 m_stringArray
.Empty();
974 GetPeer()->MacClear();
977 void wxListBox::DoSetSelection(int n
, bool select
)
979 wxCHECK_RET( n
== wxNOT_FOUND
|| IsValid(n
),
980 wxT("invalid index in wxListBox::SetSelection") );
982 if ( n
== wxNOT_FOUND
)
983 GetPeer()->MacDeselectAll();
985 GetPeer()->MacSetSelection( n
, select
);
988 bool wxListBox::IsSelected(int n
) const
990 wxCHECK_MSG( IsValid(n
), false, wxT("invalid index in wxListBox::Selected") );
992 return GetPeer()->MacIsSelected( n
);
995 void *wxListBox::DoGetItemClientData(unsigned int n
) const
997 wxCHECK_MSG( IsValid(n
), NULL
, wxT("invalid index in wxListBox::GetClientData"));
999 wxASSERT_MSG( m_dataArray
.GetCount() >= (unsigned int) n
, wxT("invalid client_data array") );
1001 return (void *)m_dataArray
[n
];
1004 wxClientData
*wxListBox::DoGetItemClientObject(unsigned int n
) const
1006 return (wxClientData
*) DoGetItemClientData( n
);
1009 void wxListBox::DoSetItemClientData(unsigned int n
, void *clientData
)
1011 wxCHECK_RET( IsValid(n
), wxT("invalid index in wxListBox::SetClientData") );
1013 #if wxUSE_OWNER_DRAWN
1014 if ( m_windowStyle
& wxLB_OWNERDRAW
)
1016 // client data must be pointer to wxOwnerDrawn, otherwise we would crash
1017 // in OnMeasure/OnDraw.
1018 wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes"));
1022 wxASSERT_MSG( m_dataArray
.GetCount() >= (unsigned int) n
, wxT("invalid client_data array") );
1024 if ( m_dataArray
.GetCount() > (unsigned int) n
)
1025 m_dataArray
[n
] = (char*)clientData
;
1027 m_dataArray
.Add( (char*)clientData
);
1030 void wxListBox::DoSetItemClientObject(unsigned int n
, wxClientData
* clientData
)
1032 DoSetItemClientData(n
, clientData
);
1035 // Return number of selections and an array of selected integers
1036 int wxListBox::GetSelections(wxArrayInt
& aSelections
) const
1038 return GetPeer()->MacGetSelections( aSelections
);
1041 // Get single selection, for single choice list items
1042 int wxListBox::GetSelection() const
1044 return GetPeer()->MacGetSelection();
1047 // Find string for position
1048 wxString
wxListBox::GetString(unsigned int n
) const
1050 wxCHECK_MSG( IsValid(n
), wxEmptyString
, wxT("invalid index in wxListBox::GetString") );
1052 return m_stringArray
[n
];
1055 void wxListBox::DoInsertItems(const wxArrayString
& items
, unsigned int pos
)
1057 wxCHECK_RET( IsValidInsert(pos
), wxT("invalid index in wxListBox::InsertItems") );
1059 InvalidateBestSize();
1061 unsigned int nItems
= items
.GetCount();
1063 for ( unsigned int i
= 0; i
< nItems
; i
++ )
1064 m_stringArray
.Insert( items
[i
], pos
+ i
);
1065 m_dataArray
.Insert( NULL
, pos
, nItems
);
1066 m_noItems
+= nItems
;
1067 GetPeer()->MacInsert( pos
, items
);
1070 void wxListBox::SetString(unsigned int n
, const wxString
& s
)
1072 m_stringArray
[n
] = s
;
1073 GetPeer()->MacSet( n
, s
);
1076 wxSize
wxListBox::DoGetBestSize() const
1078 int lbWidth
= 100; // some defaults
1083 wxMacPortStateHelper
st( UMAGetWindowPort( (WindowRef
)MacGetTopLevelWindowRef() ) );
1085 // TODO: clean this up
1088 ::TextFont( m_font
.MacGetFontNum() );
1089 ::TextSize( m_font
.MacGetFontSize() );
1090 ::TextFace( m_font
.MacGetFontStyle() );
1094 ::TextFont( kFontIDMonaco
);
1099 // Find the widest line
1100 for (unsigned int i
= 0; i
< GetCount(); i
++)
1102 wxString
str(GetString(i
));
1105 Point bounds
= {0, 0};
1108 // NB: what if m_font.Ok() == false ???
1109 ::GetThemeTextDimensions(
1110 wxMacCFStringHolder( str
, m_font
.GetEncoding() ),
1111 kThemeCurrentPortFont
,
1118 wLine
= ::TextWidth( str
.c_str(), 0, str
.length() );
1121 lbWidth
= wxMax( lbWidth
, wLine
);
1124 // Add room for the scrollbar
1125 lbWidth
+= wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
);
1127 // And just a bit more
1129 int cx
= ::TextWidth( "X", 0, 1 );
1132 // don't make the listbox too tall (limit height to around 10 items)
1133 // but don't make it too small neither
1134 lbHeight
= wxMax( (cy
+ 4) * wxMin( wxMax( GetCount(), 3 ), 10 ), 70 );
1137 return wxSize( lbWidth
, lbHeight
);
1140 unsigned int wxListBox::GetCount() const
1145 void wxListBox::Refresh(bool eraseBack
, const wxRect
*rect
)
1147 wxControl::Refresh( eraseBack
, rect
);
1150 void wxListBox::MacUpdateLine(int n
)
1152 GetPeer()->UpdateLine(n
);
1155 #if wxUSE_OWNER_DRAWN
1157 class wxListBoxItem
: public wxOwnerDrawn
1160 wxListBoxItem(const wxString
& str
= "");
1163 wxListBoxItem::wxListBoxItem(const wxString
& str
)
1164 : wxOwnerDrawn(str
, false)
1166 // no bitmaps/checkmarks
1170 wxOwnerDrawn
*wxListBox::CreateItem(size_t n
)
1172 return new wxListBoxItem();
1175 #endif // USE_OWNER_DRAWN
1178 // Some custom controls depend on this
1179 /* static */ wxVisualAttributes
1180 wxListBox::GetClassDefaultAttributes(wxWindowVariant
WXUNUSED(variant
))
1182 wxVisualAttributes attr
;
1184 attr
.colFg
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT
);
1185 attr
.colBg
= wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX
);
1186 attr
.font
= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
);
1191 int wxListBox::DoListHitTest(const wxPoint
& inpoint
) const
1195 // There are few reasons why this is complicated:
1196 // 1) There is no native HitTest function for Mac
1197 // 2) GetDataBrowserItemPartBounds only works on visible items
1198 // 3) We can't do it through GetDataBrowserTableView[Item]RowHeight
1199 // because what it returns is basically inaccurate in the context
1200 // of the coordinates we want here, but we use this as a guess
1201 // for where the first visible item lies
1203 wxPoint point
= inpoint
;
1205 // interestingly enough 10.2 (and below?) have GetDataBrowserItemPartBounds
1206 // giving root window coordinates but 10.3 and above give client coordinates
1207 // so we only compare using root window coordinates on 10.3 and up
1208 if ( UMAGetSystemVersion() < 0x1030 )
1209 MacClientToRootWindow(&point
.x
, &point
.y
);
1211 // get column property ID (req. for call to itempartbounds)
1212 DataBrowserTableViewColumnID colId
= 0;
1213 err
= GetDataBrowserTableViewColumnProperty(m_peer
->GetControlRef(), 0, &colId
);
1214 wxCHECK_MSG(err
== noErr
, wxNOT_FOUND
, wxT("Unexpected error from GetDataBrowserTableViewColumnProperty"));
1216 // OK, first we need to find the first visible item we have -
1217 // this will be the "low" for our binary search. There is no real
1218 // easy way around this, as we will need to do a SLOW linear search
1219 // until we find a visible item, but we can do a cheap calculation
1220 // via the row height to speed things up a bit
1221 UInt32 scrollx
, scrolly
;
1222 err
= GetDataBrowserScrollPosition(m_peer
->GetControlRef(), &scrollx
, &scrolly
);
1223 wxCHECK_MSG(err
== noErr
, wxNOT_FOUND
, wxT("Unexpected error from GetDataBrowserScrollPosition"));
1226 err
= GetDataBrowserTableViewRowHeight(m_peer
->GetControlRef(), &height
);
1227 wxCHECK_MSG(err
== noErr
, wxNOT_FOUND
, wxT("Unexpected error from GetDataBrowserTableViewRowHeight"));
1229 // these indices are 0-based, as usual, so we need to add 1 to them when
1230 // passing them to data browser functions which use 1-based indices
1231 int low
= scrolly
/ height
,
1232 high
= GetCount() - 1;
1234 // search for the first visible item (note that the scroll guess above
1235 // is the low bounds of where the item might lie so we only use that as a
1236 // starting point - we should reach it within 1 or 2 iterations of the loop)
1237 while ( low
<= high
)
1240 err
= GetDataBrowserItemPartBounds(
1241 m_peer
->GetControlRef(), low
+ 1, colId
,
1242 kDataBrowserPropertyEnclosingPart
,
1243 &bounds
); // note +1 to translate to Mac ID
1247 // errDataBrowserItemNotFound is expected as it simply means that the
1248 // item is not currently visible -- but other errors are not
1249 wxCHECK_MSG( err
== errDataBrowserItemNotFound
, wxNOT_FOUND
,
1250 wxT("Unexpected error from GetDataBrowserItemPartBounds") );
1255 // NOW do a binary search for where the item lies, searching low again if
1256 // we hit an item that isn't visible
1257 while ( low
<= high
)
1259 int mid
= (low
+ high
) / 2;
1262 err
= GetDataBrowserItemPartBounds(
1263 m_peer
->GetControlRef(), mid
+ 1, colId
,
1264 kDataBrowserPropertyEnclosingPart
,
1265 &bounds
); //note +1 to trans to mac id
1266 wxCHECK_MSG( err
== noErr
|| err
== errDataBrowserItemNotFound
,
1268 wxT("Unexpected error from GetDataBrowserItemPartBounds") );
1270 if ( err
== errDataBrowserItemNotFound
)
1272 // item not visible, attempt to find a visible one
1276 else // visible item, do actual hitttest
1278 // if point is within the bounds, return this item (since we assume
1279 // all x coords of items are equal we only test the x coord in
1281 if ((point
.x
>= bounds
.left
&& point
.x
<= bounds
.right
) &&
1282 (point
.y
>= bounds
.top
&& point
.y
<= bounds
.bottom
) )
1288 if ( point
.y
< bounds
.top
)
1289 // index(bounds) greater then key(point)
1292 // index(bounds) less then key(point)