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
)
39 : wxMacControl( 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
63 { return (wxListBox
*)m_peer
; }
67 // In case we have to replace data browser ...
68 // custom HIView-based implementation
70 class wxMacCustomHIViewListControl
: public wxMacListControl
73 wxMacCustomHIViewListControl( wxListBox
*peer
, const wxPoint
& pos
, const wxSize
& size
, long style
);
74 ~wxMacCustomHIViewListControl();
76 void MacDelete( int n
);
77 void MacInsert( int n
, const wxString
& item
);
78 void MacInsert( int n
, const wxArrayString
& items
);
79 void MacAppend( const wxString
& item
);
80 void MacSet( int n
, const wxString
& item
);
82 void MacDeselectAll();
83 void MacSetSelection( int n
, bool select
);
84 int MacGetSelection() const;
85 int MacGetSelections( wxArrayInt
& aSelections
) const;
86 bool MacIsSelected( int n
) const;
87 void MacScrollTo( int n
);
91 // DataBrowser-based implementation
93 class wxMacDataBrowserListControl
: public wxMacListControl
96 wxMacDataBrowserListControl( wxListBox
*peer
, const wxPoint
& pos
, const wxSize
& size
, long style
);
97 ~wxMacDataBrowserListControl();
99 void UpdateLine( int n
);
101 void MacDelete( int n
);
102 void MacInsert( int n
, const wxString
& item
);
103 void MacInsert( int n
, const wxArrayString
& items
);
104 void MacAppend( const wxString
& item
);
105 void MacSet( int n
, const wxString
& item
);
107 void MacDeselectAll();
108 void MacSetSelection( int n
, bool select
);
109 int MacGetSelection() const;
110 int MacGetSelections( wxArrayInt
& aSelections
) const;
111 bool MacIsSelected( int n
) const;
112 void MacScrollTo( int n
);
114 virtual OSStatus
SetSelectionFlags( DataBrowserSelectionFlags
);
115 virtual OSStatus
AddListViewColumn( DataBrowserListViewColumnDesc
*columnDesc
,
116 DataBrowserTableViewColumnIndex position
);
117 virtual OSStatus
AutoSizeListViewColumns();
118 virtual OSStatus
SetHasScrollBars( bool horiz
, bool vert
);
119 virtual OSStatus
SetTableViewHiliteStyle( DataBrowserTableViewHiliteStyle hiliteStyle
);
120 virtual OSStatus
SetListViewHeaderBtnHeight( UInt16 height
);
121 virtual OSStatus
SetCallbacks( const DataBrowserCallbacks
*callbacks
);
122 virtual OSStatus
UpdateItems( DataBrowserItemID container
, UInt32 numItems
,
123 const DataBrowserItemID
*items
,
124 DataBrowserPropertyID preSortProperty
,
125 DataBrowserPropertyID propertyID
);
126 virtual OSStatus
AddItems( DataBrowserItemID container
, UInt32 numItems
,
127 const DataBrowserItemID
*items
,
128 DataBrowserPropertyID preSortProperty
);
129 virtual OSStatus
RemoveItems( DataBrowserItemID container
, UInt32 numItems
,
130 const DataBrowserItemID
*items
,
131 DataBrowserPropertyID preSortProperty
);
132 virtual OSStatus
RevealItem( DataBrowserItemID item
,
133 DataBrowserPropertyID propertyID
,
134 DataBrowserRevealOptions options
);
135 virtual OSStatus
GetSelectionAnchor( DataBrowserItemID
*first
, DataBrowserItemID
*last
) const;
136 virtual bool IsItemSelected( DataBrowserItemID item
) const;
137 virtual OSStatus
SetSelectedItems( UInt32 numItems
,
138 const DataBrowserItemID
*items
,
139 DataBrowserSetOption operation
);
142 // as we are getting the same events for human and API selection we have to suppress
143 // events in the latter case
144 bool MacSuppressSelection( bool suppress
);
145 bool MacIsSelectionSuppressed() const { return m_suppressSelection
; }
147 bool m_suppressSelection
;
149 #if TARGET_API_MAC_OSX
150 static pascal void DataBrowserItemNotificationProc(
152 DataBrowserItemID itemID
,
153 DataBrowserItemNotification message
,
154 DataBrowserItemDataRef itemData
);
156 static pascal void DataBrowserItemNotificationProc(
158 DataBrowserItemID itemID
,
159 DataBrowserItemNotification message
);
163 // ============================================================================
164 // data browser based implementation
165 // ============================================================================
167 const short kTextColumnId
= 1024;
168 const short kCheckboxColumnId
= 1025;
170 // new DataBrowser-based version
171 // because of the limited insert
172 // functionality of DataBrowser,
173 // we just introduce IDs corresponding
174 // to the line number
176 DataBrowserItemDataUPP gDataBrowserItemDataUPP
= NULL
;
177 DataBrowserItemNotificationUPP gDataBrowserItemNotificationUPP
= NULL
;
179 #if TARGET_API_MAC_OSX
180 pascal void wxMacDataBrowserListControl::DataBrowserItemNotificationProc(
182 DataBrowserItemID itemID
,
183 DataBrowserItemNotification message
,
184 DataBrowserItemDataRef itemData
)
186 pascal void wxMacDataBrowserListControl::DataBrowserItemNotificationProc(
188 DataBrowserItemID itemID
,
189 DataBrowserItemNotification message
)
192 long ref
= GetControlReference( browser
);
195 wxListBox
*list
= wxDynamicCast( (wxObject
*)ref
, wxListBox
);
196 wxMacDataBrowserListControl
*peer
= (wxMacDataBrowserListControl
*) list
->GetPeer();
199 if (i
>= 0 && i
< (int)list
->GetCount())
201 bool trigger
= false;
202 wxCommandEvent
event( wxEVT_COMMAND_LISTBOX_SELECTED
, list
->GetId() );
205 case kDataBrowserItemDeselected
:
206 if ( list
->HasMultipleSelection() )
207 trigger
= !peer
->MacIsSelectionSuppressed();
210 case kDataBrowserItemSelected
:
211 trigger
= !peer
->MacIsSelectionSuppressed();
214 case kDataBrowserItemDoubleClicked
:
215 event
.SetEventType( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
);
225 event
.SetEventObject( list
);
226 if ( list
->HasClientObjectData() )
227 event
.SetClientObject( list
->GetClientObject( i
) );
228 else if ( list
->HasClientUntypedData() )
229 event
.SetClientData( list
->GetClientData( i
) );
230 event
.SetString( list
->GetString( i
) );
232 event
.SetExtraLong( list
->HasMultipleSelection() ? message
== kDataBrowserItemSelected
: true );
233 wxPostEvent( list
->GetEventHandler(), event
);
235 // direct notification is not always having the listbox GetSelection() having in synch with event
236 // list->GetEventHandler()->ProcessEvent(event);
242 static pascal OSStatus
ListBoxGetSetItemData(
244 DataBrowserItemID itemID
,
245 DataBrowserPropertyID property
,
246 DataBrowserItemDataRef itemData
,
247 Boolean changeValue
)
249 OSStatus err
= errDataBrowserPropertyNotSupported
;
251 long ref
= GetControlReference( browser
);
255 wxListBox
*list
= wxDynamicCast( (wxObject
*)ref
, wxListBox
);
256 bool isCheckList
= false;
258 isCheckList
= list
->IsKindOf( CLASSINFO(wxCheckListBox
) );
266 if (i
>= 0 && i
< (int)list
->GetCount())
268 wxMacCFStringHolder
cf( list
->GetString( i
), list
->GetFont().GetEncoding() );
269 err
= ::SetDataBrowserItemDataText( itemData
, cf
);
276 case kCheckboxColumnId
:
279 wxCheckListBox
*list
= wxDynamicCast( (wxObject
*)ref
, wxCheckListBox
);
281 if (i
>= 0 && (unsigned int) i
< list
->GetCount())
283 err
= ::SetDataBrowserItemDataButtonValue( itemData
, list
->IsChecked( i
) ? kThemeButtonOn
: kThemeButtonOff
);
290 case kDataBrowserItemIsEditableProperty
:
292 err
= ::SetDataBrowserItemDataBooleanValue( itemData
, true );
303 case kCheckboxColumnId
:
306 wxCheckListBox
*list
= wxDynamicCast( (wxObject
*)ref
, wxCheckListBox
);
308 if (i
>= 0 && (unsigned int)i
< list
->GetCount())
310 // we have to change this behind the back, since Check() would be triggering another update round
311 bool newVal
= !list
->IsChecked( i
);
312 err
= ::SetDataBrowserItemDataButtonValue( itemData
, newVal
? kThemeButtonOn
: kThemeButtonOff
);
315 list
->m_checks
[i
] = newVal
;
317 wxCommandEvent
event( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, list
->GetId() );
319 event
.SetEventObject( list
);
320 list
->GetEventHandler()->ProcessEvent( event
);
333 wxMacDataBrowserListControl::wxMacDataBrowserListControl( wxListBox
*peer
, const wxPoint
& pos
, const wxSize
& size
, long style
)
334 : wxMacListControl( peer
)
336 bool isCheckList
= peer
->IsKindOf( CLASSINFO(wxCheckListBox
));
338 m_suppressSelection
= false;
339 Rect bounds
= wxMacGetBoundsForControl( peer
, pos
, size
);
340 OSStatus err
= ::CreateDataBrowserControl(
341 MAC_WXHWND(peer
->MacGetTopLevelWindowRef()),
342 &bounds
, kDataBrowserListView
, &m_controlRef
);
345 DataBrowserSelectionFlags options
= kDataBrowserDragSelect
;
346 if ( style
& wxLB_MULTIPLE
)
348 options
|= kDataBrowserAlwaysExtendSelection
| kDataBrowserCmdTogglesSelection
;
350 else if ( style
& wxLB_EXTENDED
)
356 options
|= kDataBrowserSelectOnlyOne
;
358 err
= SetSelectionFlags( options
);
361 if ( gDataBrowserItemDataUPP
== NULL
)
362 gDataBrowserItemDataUPP
= NewDataBrowserItemDataUPP(ListBoxGetSetItemData
);
363 if ( gDataBrowserItemNotificationUPP
== NULL
)
365 gDataBrowserItemNotificationUPP
=
366 #if TARGET_API_MAC_OSX
367 (DataBrowserItemNotificationUPP
) NewDataBrowserItemNotificationWithItemUPP(DataBrowserItemNotificationProc
);
369 NewDataBrowserItemNotificationUPP(DataBrowserItemNotificationProc
);
373 DataBrowserCallbacks callbacks
;
374 InitializeDataBrowserCallbacks( &callbacks
, kDataBrowserLatestCallbacks
);
376 callbacks
.u
.v1
.itemDataCallback
= gDataBrowserItemDataUPP
;
377 callbacks
.u
.v1
.itemNotificationCallback
= gDataBrowserItemNotificationUPP
;
378 SetCallbacks( &callbacks
);
380 DataBrowserListViewColumnDesc columnDesc
;
381 columnDesc
.headerBtnDesc
.titleOffset
= 0;
382 columnDesc
.headerBtnDesc
.version
= kDataBrowserListViewLatestHeaderDesc
;
384 columnDesc
.headerBtnDesc
.btnFontStyle
.flags
=
385 kControlUseFontMask
| kControlUseJustMask
;
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
;
395 columnDesc
.headerBtnDesc
.minimumWidth
= 30;
396 columnDesc
.headerBtnDesc
.maximumWidth
= 30;
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
);
408 columnDesc
.headerBtnDesc
.minimumWidth
= 0;
409 columnDesc
.headerBtnDesc
.maximumWidth
= 10000;
411 columnDesc
.propertyDesc
.propertyID
= kTextColumnId
;
412 columnDesc
.propertyDesc
.propertyType
= kDataBrowserTextType
;
413 columnDesc
.propertyDesc
.propertyFlags
= kDataBrowserTableViewSelectionColumn
;
414 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
415 columnDesc
.propertyDesc
.propertyFlags
|= kDataBrowserListViewTypeSelectColumn
;
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 ) );
425 // shouldn't be necessary anymore under 10.2
426 m_peer
->SetData( kControlNoPart
, kControlDataBrowserIncludesFrameAndFocusTag
, (Boolean
)false );
427 m_peer
->SetNeedsFocusRect( true );
431 wxMacDataBrowserListControl::~wxMacDataBrowserListControl()
435 void wxMacDataBrowserListControl::MacDelete( int n
)
437 wxArrayInt selectionBefore
;
438 MacGetSelections( selectionBefore
);
440 UInt32 id
= GetPeer()->GetCount() + 1;
442 OSStatus err
= RemoveItems( kDataBrowserNoItem
, 1, (UInt32
*) &id
, kDataBrowserItemNoProperty
);
445 for ( size_t i
= 0; i
< selectionBefore
.GetCount(); ++i
)
447 int current
= selectionBefore
[i
];
450 // selection was deleted
451 MacSetSelection( current
, false );
453 else if ( current
> n
)
455 // something behind the deleted item was selected -> move up
456 MacSetSelection( current
- 1, true );
457 MacSetSelection( current
, false );
463 kDataBrowserNoItem
, 1, (UInt32
*)kDataBrowserNoItem
,
464 kDataBrowserItemNoProperty
, kDataBrowserItemNoProperty
);
468 void wxMacDataBrowserListControl::MacInsert( int n
, const wxString
& text
)
470 wxArrayInt selectionBefore
;
471 MacGetSelections( selectionBefore
);
473 UInt32 id
= GetPeer()->GetCount(); // this has already been increased
474 OSStatus err
= AddItems( kDataBrowserNoItem
, 1, (UInt32
*) &id
, kDataBrowserItemNoProperty
);
477 for ( int i
= selectionBefore
.GetCount() - 1; i
>= 0; --i
)
479 int current
= selectionBefore
[i
];
482 MacSetSelection( current
+ 1, true );
483 MacSetSelection( current
, false );
489 kDataBrowserNoItem
, 1, (UInt32
*)kDataBrowserNoItem
,
490 kDataBrowserItemNoProperty
, kDataBrowserItemNoProperty
);
494 void wxMacDataBrowserListControl::MacInsert( int n
, const wxArrayString
& items
)
496 wxArrayInt selectionBefore
;
497 MacGetSelections( selectionBefore
);
498 size_t itemsCount
= items
.GetCount();
500 UInt32
*ids
= new UInt32
[itemsCount
];
501 for ( unsigned int i
= 0; i
< itemsCount
; ++i
)
502 ids
[i
] = GetPeer()->GetCount() - itemsCount
+ i
+ 1;
504 OSStatus err
= AddItems( kDataBrowserNoItem
, itemsCount
, ids
, kDataBrowserItemNoProperty
);
508 for ( int i
= selectionBefore
.GetCount() - 1; i
>= 0; --i
)
510 int current
= selectionBefore
[i
];
513 MacSetSelection( current
+ 1, true );
514 MacSetSelection( current
, false );
520 kDataBrowserNoItem
, 1, (UInt32
*)kDataBrowserNoItem
,
521 kDataBrowserItemNoProperty
, kDataBrowserItemNoProperty
);
525 void wxMacDataBrowserListControl::MacAppend( const wxString
& text
)
527 UInt32 id
= GetPeer()->GetCount(); // this has already been increased
528 verify_noerr( AddItems( kDataBrowserNoItem
, 1, (UInt32
*) &id
, kDataBrowserItemNoProperty
) );
529 // no need to deal with selections nor refreshed, as we have appended
532 void wxMacDataBrowserListControl::MacClear()
534 verify_noerr( RemoveItems( kDataBrowserNoItem
, 0, NULL
, kDataBrowserItemNoProperty
) );
537 void wxMacDataBrowserListControl::MacDeselectAll()
539 bool former
= MacSuppressSelection( true );
540 verify_noerr(SetSelectedItems( 0, NULL
, kDataBrowserItemsRemove
) );
541 MacSuppressSelection( former
);
544 void wxMacDataBrowserListControl::MacSetSelection( int n
, bool select
)
547 bool former
= MacSuppressSelection( true );
549 if ( IsItemSelected( id
) != select
)
554 err
= SetSelectedItems( 1, &id
, GetPeer()->HasMultipleSelection() ? kDataBrowserItemsAdd
: kDataBrowserItemsAssign
);
556 err
= SetSelectedItems( 1, &id
, kDataBrowserItemsRemove
);
562 MacSuppressSelection( former
);
565 bool wxMacDataBrowserListControl::MacSuppressSelection( bool suppress
)
567 bool former
= m_suppressSelection
;
568 m_suppressSelection
= suppress
;
573 bool wxMacDataBrowserListControl::MacIsSelected( int n
) const
575 return IsItemSelected( n
+ 1 );
578 int wxMacDataBrowserListControl::MacGetSelection() const
580 for ( unsigned int i
= 0; i
< GetPeer()->GetCount(); ++i
)
582 if ( IsItemSelected( i
+ 1 ) )
591 int wxMacDataBrowserListControl::MacGetSelections( wxArrayInt
& aSelections
) const
598 GetSelectionAnchor( &first
, &last
);
599 if ( first
!= kDataBrowserNoItem
)
601 for ( size_t i
= first
; i
<= last
; ++i
)
603 if ( IsItemSelected( i
) )
605 aSelections
.Add( i
- 1 );
614 void wxMacDataBrowserListControl::MacSet( int n
, const wxString
& text
)
616 // as we don't store the strings we only have to issue a redraw
618 verify_noerr( UpdateItems( kDataBrowserNoItem
, 1, &id
, kDataBrowserItemNoProperty
, kDataBrowserItemNoProperty
) );
621 void wxMacDataBrowserListControl::MacScrollTo( int n
)
624 verify_noerr( RevealItem( id
, kTextColumnId
, kDataBrowserRevealWithoutSelecting
) );
627 void wxMacDataBrowserListControl::UpdateLine( int n
)
630 verify_noerr( UpdateItems(kDataBrowserNoItem
, 1, &id
, kDataBrowserItemNoProperty
, kDataBrowserItemNoProperty
) );
637 OSStatus
wxMacDataBrowserListControl::SetSelectionFlags( DataBrowserSelectionFlags options
)
639 return SetDataBrowserSelectionFlags( m_controlRef
, options
);
642 OSStatus
wxMacDataBrowserListControl::AddListViewColumn( DataBrowserListViewColumnDesc
*columnDesc
,
643 DataBrowserTableViewColumnIndex position
)
645 return AddDataBrowserListViewColumn( m_controlRef
, columnDesc
, position
);
648 OSStatus
wxMacDataBrowserListControl::AutoSizeListViewColumns()
650 return AutoSizeDataBrowserListViewColumns(m_controlRef
);
653 OSStatus
wxMacDataBrowserListControl::SetHasScrollBars( bool horiz
, bool vert
)
655 return SetDataBrowserHasScrollBars( m_controlRef
, horiz
, vert
);
658 OSStatus
wxMacDataBrowserListControl::SetTableViewHiliteStyle( DataBrowserTableViewHiliteStyle hiliteStyle
)
660 return SetDataBrowserTableViewHiliteStyle( m_controlRef
, hiliteStyle
);
663 OSStatus
wxMacDataBrowserListControl::SetListViewHeaderBtnHeight(UInt16 height
)
665 return SetDataBrowserListViewHeaderBtnHeight( m_controlRef
, height
);
668 OSStatus
wxMacDataBrowserListControl::SetCallbacks(const DataBrowserCallbacks
*callbacks
)
670 return SetDataBrowserCallbacks( m_controlRef
, callbacks
);
673 OSStatus
wxMacDataBrowserListControl::UpdateItems(
674 DataBrowserItemID container
,
676 const DataBrowserItemID
*items
,
677 DataBrowserPropertyID preSortProperty
,
678 DataBrowserPropertyID propertyID
)
680 return UpdateDataBrowserItems( m_controlRef
, container
, numItems
, items
, preSortProperty
, propertyID
);
683 bool wxMacDataBrowserListControl::IsItemSelected( DataBrowserItemID item
) const
685 return IsDataBrowserItemSelected( m_controlRef
, item
);
688 OSStatus
wxMacDataBrowserListControl::AddItems(
689 DataBrowserItemID container
,
691 const DataBrowserItemID
*items
,
692 DataBrowserPropertyID preSortProperty
)
694 return AddDataBrowserItems( m_controlRef
, container
, numItems
, items
, preSortProperty
);
697 OSStatus
wxMacDataBrowserListControl::RemoveItems(
698 DataBrowserItemID container
,
700 const DataBrowserItemID
*items
,
701 DataBrowserPropertyID preSortProperty
)
703 return RemoveDataBrowserItems( m_controlRef
, container
, numItems
, items
, preSortProperty
);
706 OSStatus
wxMacDataBrowserListControl::RevealItem(
707 DataBrowserItemID item
,
708 DataBrowserPropertyID propertyID
,
709 DataBrowserRevealOptions options
)
711 return RevealDataBrowserItem( m_controlRef
, item
, propertyID
, options
);
714 OSStatus
wxMacDataBrowserListControl::SetSelectedItems(
716 const DataBrowserItemID
*items
,
717 DataBrowserSetOption operation
)
719 return SetDataBrowserSelectedItems( m_controlRef
, numItems
, items
, operation
);
722 OSStatus
wxMacDataBrowserListControl::GetSelectionAnchor( DataBrowserItemID
*first
, DataBrowserItemID
*last
) const
724 return GetDataBrowserSelectionAnchor( m_controlRef
, first
, last
);
729 // in case we need that one day
731 // ============================================================================
732 // HIView owner-draw-based implementation
733 // ============================================================================
735 static pascal void ListBoxDrawProc(
736 ControlRef browser
, DataBrowserItemID item
, DataBrowserPropertyID property
,
737 DataBrowserItemState itemState
, const Rect
*itemRect
, SInt16 depth
, Boolean isColorDevice
)
739 CFStringRef cfString
;
740 ThemeDrawingState themeState
;
743 GetThemeDrawingState( &themeState
);
744 cfString
= CFStringCreateWithFormat( NULL
, NULL
, CFSTR("Row %d"), item
);
746 // In this sample we handle the "selected" state; all others fall through to our "active" state
747 if ( itemState
== kDataBrowserItemIsSelected
)
749 ThemeBrush colorBrushID
;
751 // TODO: switch over to wxSystemSettingsNative::GetColour() when kThemeBrushSecondaryHighlightColor
752 // is incorporated Panther DB starts using kThemeBrushSecondaryHighlightColor
753 // for inactive browser highlighting
754 Gestalt( gestaltSystemVersion
, &systemVersion
);
755 if ( (systemVersion
>= 0x00001030) && !IsControlActive( browser
) )
756 colorBrushID
= kThemeBrushSecondaryHighlightColor
;
758 colorBrushID
= kThemeBrushPrimaryHighlightColor
;
760 // First paint the hilite rect, then the text on top
761 SetThemePen( colorBrushID
, 32, true );
762 PaintRect( itemRect
);
763 SetThemeDrawingState( themeState
, false );
766 DrawThemeTextBox( cfString
, kThemeApplicationFont
, kThemeStateActive
, true, itemRect
, teFlushDefault
, NULL
);
767 SetThemeDrawingState( themeState
, true );
769 if ( cfString
!= NULL
)
770 CFRelease( cfString
);
774 // ============================================================================
775 // list box control implementation
776 // ============================================================================
778 wxListBox::wxListBox()
783 bool wxListBox::Create(
788 const wxArrayString
& choices
,
790 const wxValidator
& validator
,
791 const wxString
& name
)
793 wxCArrayString
chs(choices
);
796 parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(),
797 style
, validator
, name
);
800 bool wxListBox::Create(
806 const wxString choices
[],
808 const wxValidator
& validator
,
809 const wxString
& name
)
811 m_macIsUserPane
= false;
813 wxASSERT_MSG( !(style
& wxLB_MULTIPLE
) || !(style
& wxLB_EXTENDED
),
814 wxT("only a single listbox selection mode can be specified") );
816 if ( !wxListBoxBase::Create( parent
, id
, pos
, size
, style
& ~(wxHSCROLL
| wxVSCROLL
), validator
, name
) )
819 // this will be increased by our append command
822 m_peer
= CreateMacListControl( pos
, size
, style
);
824 MacPostControlCreate( pos
, size
);
826 InsertItems( n
, choices
, 0 );
828 // Needed because it is a wxControlWithItems
834 wxListBox::~wxListBox()
836 m_peer
->SetReference( 0 );
840 wxMacListControl
* wxListBox::CreateMacListControl(const wxPoint
& pos
, const wxSize
& size
, long style
)
842 return new wxMacDataBrowserListControl( this, pos
, size
, style
);
845 void wxListBox::FreeData()
847 #if wxUSE_OWNER_DRAWN
848 if ( m_windowStyle
& wxLB_OWNERDRAW
)
850 size_t uiCount
= m_aItems
.Count();
851 while ( uiCount
!= 0 )
854 delete m_aItems
[uiCount
];
855 m_aItems
[uiCount
] = NULL
;
862 if ( HasClientObjectData() )
864 for ( unsigned int n
= 0; n
< m_noItems
; n
++ )
866 delete GetClientObject( n
);
871 void wxListBox::DoSetSize(int x
, int y
,
872 int width
, int height
,
875 wxControl::DoSetSize( x
, y
, width
, height
, sizeFlags
);
878 void wxListBox::DoSetFirstItem(int n
)
880 GetPeer()->MacScrollTo( n
);
883 void wxListBox::Delete(unsigned int n
)
885 wxCHECK_RET( IsValid(n
), wxT("invalid index in wxListBox::Delete") );
887 #if wxUSE_OWNER_DRAWN
889 m_aItems
.RemoveAt(n
);
891 if ( HasClientObjectData() )
893 delete GetClientObject(n
);
897 m_stringArray
.RemoveAt( n
);
898 m_dataArray
.RemoveAt( n
);
901 GetPeer()->MacDelete( n
);
904 int wxListBox::DoAppend(const wxString
& item
)
906 InvalidateBestSize();
908 unsigned int index
= m_noItems
;
909 m_stringArray
.Add( item
);
910 m_dataArray
.Add( NULL
);
912 DoSetItemClientData( index
, NULL
);
913 GetPeer()->MacAppend( item
);
918 void wxListBox::DoSetItems(const wxArrayString
& choices
, void** clientData
)
921 unsigned int n
= choices
.GetCount();
923 for ( size_t i
= 0; i
< n
; ++i
)
927 #if wxUSE_OWNER_DRAWN
928 wxASSERT_MSG(clientData
[i
] == NULL
,
929 wxT("Cannot use client data with owner-drawn listboxes"));
931 Append( choices
[i
], clientData
[i
] );
935 Append( choices
[i
] );
938 #if wxUSE_OWNER_DRAWN
939 if ( m_windowStyle
& wxLB_OWNERDRAW
)
941 // first delete old items
942 size_t ui
= m_aItems
.Count();
952 // then create new ones
953 for ( ui
= 0; ui
< (size_t)m_noItems
; ui
++ )
955 wxOwnerDrawn
*pNewItem
= CreateItem(ui
);
956 pNewItem
->SetName(choices
[ui
]);
957 m_aItems
.Add(pNewItem
);
963 int wxListBox::FindString(const wxString
& s
, bool bCase
) const
965 for ( size_t i
= 0; i
< m_noItems
; ++ i
)
967 if (s
.IsSameAs( GetString( i
), bCase
) )
974 void wxListBox::Clear()
978 m_stringArray
.Empty();
980 GetPeer()->MacClear();
983 void wxListBox::DoSetSelection(int n
, bool select
)
985 wxCHECK_RET( n
== wxNOT_FOUND
|| IsValid(n
),
986 wxT("invalid index in wxListBox::SetSelection") );
988 if ( n
== wxNOT_FOUND
)
989 GetPeer()->MacDeselectAll();
991 GetPeer()->MacSetSelection( n
, select
);
994 bool wxListBox::IsSelected(int n
) const
996 wxCHECK_MSG( IsValid(n
), false, wxT("invalid index in wxListBox::Selected") );
998 return GetPeer()->MacIsSelected( n
);
1001 void *wxListBox::DoGetItemClientData(unsigned int n
) const
1003 wxCHECK_MSG( IsValid(n
), NULL
, wxT("invalid index in wxListBox::GetClientData"));
1005 wxASSERT_MSG( m_dataArray
.GetCount() >= (unsigned int)n
, wxT("invalid client_data array") );
1007 return (void*)m_dataArray
[n
];
1010 wxClientData
*wxListBox::DoGetItemClientObject(unsigned int n
) const
1012 return (wxClientData
*)DoGetItemClientData( n
);
1015 void wxListBox::DoSetItemClientData(unsigned int n
, void *clientData
)
1017 wxCHECK_RET( IsValid(n
), wxT("invalid index in wxListBox::SetClientData") );
1019 #if wxUSE_OWNER_DRAWN
1020 if ( m_windowStyle
& wxLB_OWNERDRAW
)
1022 // client data must be pointer to wxOwnerDrawn, otherwise we would crash
1023 // in OnMeasure/OnDraw.
1024 wxFAIL_MSG(wxT("Cannot use client data with owner-drawn listboxes"));
1028 wxASSERT_MSG( m_dataArray
.GetCount() >= (unsigned int)n
, wxT("invalid client_data array") );
1030 if ( m_dataArray
.GetCount() > (unsigned int)n
)
1031 m_dataArray
[n
] = (char*)clientData
;
1033 m_dataArray
.Add( (char*)clientData
);
1036 void wxListBox::DoSetItemClientObject(unsigned int n
, wxClientData
* clientData
)
1038 DoSetItemClientData(n
, clientData
);
1041 // Return number of selections and an array of selected integers
1042 int wxListBox::GetSelections(wxArrayInt
& aSelections
) const
1044 return GetPeer()->MacGetSelections( aSelections
);
1047 // Get single selection, for single choice list items
1048 int wxListBox::GetSelection() const
1050 return GetPeer()->MacGetSelection();
1053 // Find string for position
1054 wxString
wxListBox::GetString(unsigned int n
) const
1056 wxCHECK_MSG( IsValid(n
), wxEmptyString
, wxT("invalid index in wxListBox::GetString") );
1058 return m_stringArray
[n
];
1061 void wxListBox::DoInsertItems(const wxArrayString
& items
, unsigned int pos
)
1063 wxCHECK_RET( IsValidInsert(pos
), wxT("invalid index in wxListBox::InsertItems") );
1065 InvalidateBestSize();
1067 unsigned int nItems
= items
.GetCount();
1069 for ( unsigned int i
= 0; i
< nItems
; i
++ )
1070 m_stringArray
.Insert( items
[i
], pos
+ i
);
1071 m_dataArray
.Insert( NULL
, pos
, nItems
);
1072 m_noItems
+= nItems
;
1073 GetPeer()->MacInsert( pos
, items
);
1076 void wxListBox::SetString(unsigned int n
, const wxString
& s
)
1078 m_stringArray
[n
] = s
;
1079 GetPeer()->MacSet( n
, s
);
1082 wxSize
wxListBox::DoGetBestSize() const
1084 int lbWidth
= 100; // some defaults
1089 wxMacPortStateHelper
st( UMAGetWindowPort( (WindowRef
)MacGetTopLevelWindowRef() ) );
1091 // TODO: clean this up
1094 ::TextFont( m_font
.MacGetFontNum() );
1095 ::TextSize( m_font
.MacGetFontSize() );
1096 ::TextFace( m_font
.MacGetFontStyle() );
1100 ::TextFont( kFontIDMonaco
);
1105 // Find the widest line
1106 for (unsigned int i
= 0; i
< GetCount(); i
++)
1108 wxString
str( GetString( i
) );
1111 Point bounds
= {0, 0};
1114 // NB: what if m_font.Ok() == false ???
1115 ::GetThemeTextDimensions(
1116 wxMacCFStringHolder( str
, m_font
.GetEncoding() ),
1117 kThemeCurrentPortFont
,
1124 wLine
= ::TextWidth( str
.c_str(), 0, str
.length() );
1127 lbWidth
= wxMax( lbWidth
, wLine
);
1130 // Add room for the scrollbar
1131 lbWidth
+= wxSystemSettings::GetMetric( wxSYS_VSCROLL_X
);
1133 // And just a bit more
1135 int cx
= ::TextWidth( "X", 0, 1 );
1138 // don't make the listbox too tall (limit height to around 10 items)
1139 // but don't make it too small neither
1140 lbHeight
= wxMax( (cy
+ 4) * wxMin( wxMax( GetCount(), 3 ), 10 ), 70 );
1143 return wxSize( lbWidth
, lbHeight
);
1146 unsigned int wxListBox::GetCount() const
1151 void wxListBox::Refresh(bool eraseBack
, const wxRect
*rect
)
1153 wxControl::Refresh( eraseBack
, rect
);
1156 void wxListBox::MacUpdateLine(int n
)
1158 GetPeer()->UpdateLine(n
);
1161 #if wxUSE_OWNER_DRAWN
1163 class wxListBoxItem
: public wxOwnerDrawn
1166 wxListBoxItem(const wxString
& str
= "");
1169 wxListBoxItem::wxListBoxItem(const wxString
& str
)
1170 : wxOwnerDrawn(str
, false)
1172 // no bitmaps/checkmarks
1173 SetMarginWidth( 0 );
1176 wxOwnerDrawn
*wxListBox::CreateItem(size_t n
)
1178 return new wxListBoxItem();
1181 #endif // USE_OWNER_DRAWN
1184 // Some custom controls depend on this
1185 /* static */ wxVisualAttributes
1186 wxListBox::GetClassDefaultAttributes(wxWindowVariant
WXUNUSED(variant
))
1188 wxVisualAttributes attr
;
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
);
1197 int wxListBox::DoListHitTest(const wxPoint
& inpoint
) const
1201 // There are few reasons why this is complicated:
1202 // 1) There is no native HitTest function for Mac
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
1209 wxPoint point
= inpoint
;
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
);
1217 // get column property ID (req. for call to itempartbounds)
1218 DataBrowserTableViewColumnID colId
= 0;
1219 err
= GetDataBrowserTableViewColumnProperty(m_peer
->GetControlRef(), 0, &colId
);
1220 wxCHECK_MSG(err
== noErr
, wxNOT_FOUND
, wxT("Unexpected error from GetDataBrowserTableViewColumnProperty"));
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"));
1232 err
= GetDataBrowserTableViewRowHeight(m_peer
->GetControlRef(), &height
);
1233 wxCHECK_MSG(err
== noErr
, wxNOT_FOUND
, wxT("Unexpected error from GetDataBrowserTableViewRowHeight"));
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;
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
)
1246 err
= GetDataBrowserItemPartBounds(
1247 m_peer
->GetControlRef(), low
+ 1, colId
,
1248 kDataBrowserPropertyEnclosingPart
,
1249 &bounds
); // note +1 to translate to Mac ID
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") );
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
)
1265 int mid
= (low
+ high
) / 2;
1268 err
= GetDataBrowserItemPartBounds(
1269 m_peer
->GetControlRef(), mid
+ 1, colId
,
1270 kDataBrowserPropertyEnclosingPart
,
1271 &bounds
); //note +1 to trans to mac id
1272 wxCHECK_MSG( err
== noErr
|| err
== errDataBrowserItemNotFound
,
1274 wxT("Unexpected error from GetDataBrowserItemPartBounds") );
1276 if ( err
== errDataBrowserItemNotFound
)
1278 // item not visible, attempt to find a visible one
1282 else // visible item, do actual hitttest
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
1287 if ((point
.x
>= bounds
.left
&& point
.x
<= bounds
.right
) &&
1288 (point
.y
>= bounds
.top
&& point
.y
<= bounds
.bottom
) )
1294 if ( point
.y
< bounds
.top
)
1295 // index(bounds) greater then key(point)
1298 // index(bounds) less then key(point)