]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/toolbar.cpp
Test for wxUSE_UXTHEME
[wxWidgets.git] / src / mac / carbon / toolbar.cpp
index d3fcb494ac348e4fe6b75c7a637d64274324ede0..1b7cef3e5fb4b7c46745456281eee54b4acd9136 100644 (file)
     #include "wx/wx.h"
 #endif
 
+#include "wx/app.h"
 #include "wx/mac/uma.h"
 #include "wx/geometry.h"
+#include "wx/sysopt.h"
 
 
 #ifdef __WXMAC_OSX__
@@ -57,6 +59,17 @@ END_EVENT_TABLE()
 
 // We have a dual implementation for each tool, ControlRef and HIToolbarItemRef
 
+// when embedding native controls in the native toolbar we must make sure the
+// control does not get deleted behind our backs, so the retain count gets increased
+// (after creation it is 1), first be the creation of the custom HIToolbarItem wrapper 
+// object, and second by the code 'creating' the custom HIView (which is the same as the
+// already existing native control, therefore we just increase the ref count)
+// when this view is removed from the native toolbar its count gets decremented again
+// and when the HITooolbarItem wrapper object gets destroyed it is decremented as well
+// so in the end the control lives with a refcount of one and can be disposed of by the
+// wxControl code. For embedded controls on a non-native toolbar this ref count is less
+// so we can only test against a range, not a specific value of the refcount.
+
 class wxToolBarTool : public wxToolBarToolBase
 {
 public:
@@ -71,8 +84,8 @@ public:
         const wxString& shortHelp,
         const wxString& longHelp );
 
-    wxToolBarTool(wxToolBar *tbar, wxControl *control)
-        : wxToolBarToolBase(tbar, control)
+    wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
+        : wxToolBarToolBase(tbar, control, label)
     {
         Init();
         if (control != NULL)
@@ -98,24 +111,27 @@ public:
 
     void ClearControl()
     {
-        m_control = NULL;
         if ( m_controlHandle )
         {
             if ( !IsControl() )
                 DisposeControl( m_controlHandle );
             else
             {
-                // the embedded control is not under the responsibility of the tool
+                // the embedded control is not under the responsibility of the tool, it will be disposed of in the
+                // proper wxControl destructor
+                wxASSERT( IsValidControlHandle(GetControl()->GetPeer()->GetControlRef() )) ;
             }
             m_controlHandle = NULL ;
         }
+        m_control = NULL;
 
 #if wxMAC_USE_NATIVE_TOOLBAR
         if ( m_toolbarItemRef )
         {
             CFIndex count = CFGetRetainCount( m_toolbarItemRef ) ;
             wxASSERT_MSG( count == 1 , wxT("Reference Count of native tool was not 1 in wxToolBarTool destructor") );
-            CFRelease( m_toolbarItemRef );
+            wxTheApp->MacAddToAutorelease(m_toolbarItemRef);
+            CFRelease(m_toolbarItemRef);
             m_toolbarItemRef = NULL;
         }
 #endif
@@ -166,10 +182,19 @@ public:
         m_toolbarItemRef = ref;
         if ( m_toolbarItemRef )
         {
+            wxFont f;
+            wxFontEncoding enc;
+            if ( GetToolBar() )
+                f = GetToolBar()->GetFont();
+            if ( f.IsOk() )
+                enc = f.GetEncoding();
+            else
+                enc = wxFont::GetDefaultEncoding();
+
             HIToolbarItemSetHelpText(
                 m_toolbarItemRef,
-                wxMacCFStringHolder( GetShortHelp(), GetToolBar()->GetFont().GetEncoding() ),
-                wxMacCFStringHolder( GetLongHelp(), GetToolBar()->GetFont().GetEncoding() ) );
+                wxMacCFStringHolder( GetShortHelp(), enc ),
+                wxMacCFStringHolder( GetLongHelp(), enc ) );
         }
     }
 
@@ -451,7 +476,7 @@ void wxToolBarTool::UpdateToggleImage( bool toggle )
         dc.DrawBitmap( m_bmpNormal, 0, 0, true );
         dc.SelectObject( wxNullBitmap );
         ControlButtonContentInfo info;
-        wxMacCreateBitmapButton( &info, bmp );
+        wxMacCreateBitmapButton( &info, bmp, kControlContentIconRef );
         SetControlData( m_controlHandle, 0, kControlIconContentTag, sizeof(info), (Ptr)&info );
 #if wxMAC_USE_NATIVE_TOOLBAR
         if (m_toolbarItemRef != NULL)
@@ -464,7 +489,7 @@ void wxToolBarTool::UpdateToggleImage( bool toggle )
     else
     {
         ControlButtonContentInfo info;
-        wxMacCreateBitmapButton( &info, m_bmpNormal );
+        wxMacCreateBitmapButton( &info, m_bmpNormal, kControlContentIconRef );
         SetControlData( m_controlHandle, 0, kControlIconContentTag, sizeof(info), (Ptr)&info );
 #if wxMAC_USE_NATIVE_TOOLBAR
         if (m_toolbarItemRef != NULL)
@@ -522,9 +547,10 @@ wxToolBarToolBase *wxToolBar::CreateTool(
         clientData, shortHelp, longHelp );
 }
 
-wxToolBarToolBase * wxToolBar::CreateTool( wxControl *control )
+wxToolBarToolBase *
+wxToolBar::CreateTool(wxControl *control, const wxString& label)
 {
-    return new wxToolBarTool( this, control );
+    return new wxToolBarTool(this, control, label);
 }
 
 void wxToolBar::Init()
@@ -542,26 +568,26 @@ void wxToolBar::Init()
 
 #define kControlToolbarItemClassID      CFSTR( "org.wxwidgets.controltoolbaritem" )
 
-const EventTypeSpec kEvents[] = 
+const EventTypeSpec kEvents[] =
 {
     { kEventClassHIObject, kEventHIObjectConstruct },
     { kEventClassHIObject, kEventHIObjectInitialize },
     { kEventClassHIObject, kEventHIObjectDestruct },
-    
+
     { kEventClassToolbarItem, kEventToolbarItemCreateCustomView }
 };
 
-const EventTypeSpec kViewEvents[] = 
-{ 
-    { kEventClassControl, kEventControlGetSizeConstraints } 
+const EventTypeSpec kViewEvents[] =
+{
+    { kEventClassControl, kEventControlGetSizeConstraints }
 };
 
-struct ControlToolbarItem 
-{ 
-    HIToolbarItemRef    toolbarItem; 
+struct ControlToolbarItem
+{
+    HIToolbarItemRef    toolbarItem;
     HIViewRef           viewRef;
     wxSize              lastValidSize ;
-}; 
+};
 
 static pascal OSStatus ControlToolbarItemHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
 {
@@ -577,20 +603,21 @@ static pascal OSStatus ControlToolbarItemHandler( EventHandlerCallRef inCallRef,
                     {
                         HIObjectRef         toolbarItem;
                         ControlToolbarItem* item;
-                        
+
                         GetEventParameter( inEvent, kEventParamHIObjectInstance, typeHIObjectRef, NULL,
                             sizeof( HIObjectRef ), NULL, &toolbarItem );
-                        
+
                         item = (ControlToolbarItem*) malloc(sizeof(ControlToolbarItem)) ;
                         item->toolbarItem = toolbarItem ;
+                        item->lastValidSize = wxSize(-1,-1);
                         item->viewRef = NULL ;
-                        
+
                         SetEventParameter( inEvent, kEventParamHIObjectInstance, typeVoidPtr, sizeof( void * ), &item );
-                        
+
                         result = noErr ;
                     }
                     break;
+
                 case kEventHIObjectInitialize:
                     result = CallNextEventHandler( inCallRef, inEvent );
                     if ( result == noErr )
@@ -598,26 +625,33 @@ static pascal OSStatus ControlToolbarItemHandler( EventHandlerCallRef inCallRef,
                         CFDataRef           data;
                         GetEventParameter( inEvent, kEventParamToolbarItemConfigData, typeCFTypeRef, NULL,
                             sizeof( CFTypeRef ), NULL, &data );
-                    
+
                         HIViewRef viewRef ;
-                        
+
                         wxASSERT_MSG( CFDataGetLength( data ) == sizeof( viewRef ) , wxT("Illegal Data passed") ) ;
                         memcpy( &viewRef , CFDataGetBytePtr( data ) , sizeof( viewRef ) ) ;
-                    
+
                         object->viewRef = (HIViewRef) viewRef ;
+                        // make sure we keep that control during our lifetime
+                        CFRetain( object->viewRef ) ;
 
+                        verify_noerr(InstallEventHandler( GetControlEventTarget( viewRef ), ControlToolbarItemHandler,
+                                            GetEventTypeCount( kViewEvents ), kViewEvents, object, NULL ));
                         result = noErr ;
                     }
                     break;
 
                 case kEventHIObjectDestruct:
                     {
-                        // we've increased the ref count when creating this, so we decrease manually again in case
-                        // it was never really installed and deinstalled
                         HIViewRef viewRef = object->viewRef ;
-                        if( viewRef && CFGetRetainCount( viewRef ) > 1 )
+                        if( viewRef && IsValidControlHandle( viewRef)  )
                         {
-                            CFRelease( viewRef ) ;
+                            // depending whether the wxControl corresponding to this HIView has already been destroyed or
+                            // not, ref counts differ, so we cannot assert a special value
+                            CFIndex count =  CFGetRetainCount( viewRef ) ;
+                            wxASSERT_MSG( count >=1 , wxT("Reference Count of native tool was illegal before removal") );
+                            if ( count >= 1 )
+                                CFRelease( viewRef ) ;
                         }
                            free( object ) ;
                        result = noErr;
@@ -625,25 +659,22 @@ static pascal OSStatus ControlToolbarItemHandler( EventHandlerCallRef inCallRef,
                     break;
             }
             break;
-        
+
         case kEventClassToolbarItem:
             switch ( GetEventKind( inEvent ) )
-            {               
+            {
                 case kEventToolbarItemCreateCustomView:
                 {
                     HIViewRef viewRef = object->viewRef ;
-
                     HIViewRemoveFromSuperview( viewRef ) ;
                     HIViewSetVisible(viewRef, true) ;
-                    InstallEventHandler( GetControlEventTarget( viewRef ), ControlToolbarItemHandler,
-                                            GetEventTypeCount( kViewEvents ), kViewEvents, object, NULL );
-                    
+                    CFRetain( viewRef ) ;
                     result = SetEventParameter( inEvent, kEventParamControlRef, typeControlRef, sizeof( HIViewRef ), &viewRef );
                 }
                 break;
             }
             break;
-        
+
         case kEventClassControl:
             switch ( GetEventKind( inEvent ) )
             {
@@ -652,24 +683,32 @@ static pascal OSStatus ControlToolbarItemHandler( EventHandlerCallRef inCallRef,
                     wxWindow* wxwindow = wxFindControlFromMacControl(object->viewRef ) ;
                     if ( wxwindow )
                     {
-                        wxSize sz = wxwindow->GetSize() ;
-                        sz.x -= wxwindow->MacGetLeftBorderSize() + wxwindow->MacGetRightBorderSize();
-                        sz.y -= wxwindow->MacGetTopBorderSize() + wxwindow->MacGetBottomBorderSize();
-                        // during toolbar layout the native window sometimes gets negative sizes
-                        // so we always keep the last valid size here, to make sure we survive the
-                        // shuffle ...
-                        if ( sz.x > 0 && sz.y > 0 )
-                            object->lastValidSize = sz ;
-                        else
-                            sz = object->lastValidSize ;
-                            
+                        // during toolbar layout the native window sometimes gets negative sizes,
+                        // sometimes it just gets shrunk behind our back, so in order to avoid
+                        // ever shrinking more, once a valid size is captured, we keep it
+
+                        wxSize sz = object->lastValidSize;
+                        if ( sz.x <= 0 || sz.y <= 0 )
+                        {
+                            sz = wxwindow->GetSize() ;
+                            sz.x -= wxwindow->MacGetLeftBorderSize() + wxwindow->MacGetRightBorderSize();
+                            sz.y -= wxwindow->MacGetTopBorderSize() + wxwindow->MacGetBottomBorderSize();
+                            if ( sz.x > 0 && sz.y > 0 )
+                                object->lastValidSize = sz ;
+                            else
+                                sz = wxSize(0,0) ;
+                        }
+
+                        // Extra width to avoid edge of combobox being cut off
+                        sz.x += 3;
+                        
                         HISize min, max;
                         min.width = max.width = sz.x ;
                         min.height = max.height = sz.y ;
-                        
+
                         result = SetEventParameter( inEvent, kEventParamMinimumSize, typeHISize,
                                                         sizeof( HISize ), &min );
-                        
+
                         result = SetEventParameter( inEvent, kEventParamMaximumSize, typeHISize,
                                                         sizeof( HISize ), &max );
                         result = noErr ;
@@ -679,19 +718,19 @@ static pascal OSStatus ControlToolbarItemHandler( EventHandlerCallRef inCallRef,
             }
             break;
     }
-    
+
     return result;
 }
 
 void RegisterControlToolbarItemClass()
 {
     static bool sRegistered;
-    
+
     if ( !sRegistered )
     {
         HIObjectRegisterSubclass( kControlToolbarItemClassID, kHIToolbarItemClassID, 0,
                 ControlToolbarItemHandler, GetEventTypeCount( kEvents ), kEvents, 0, NULL );
-        
+
         sRegistered = true;
     }
 }
@@ -699,26 +738,26 @@ void RegisterControlToolbarItemClass()
 HIToolbarItemRef CreateControlToolbarItem(CFStringRef inIdentifier, CFTypeRef inConfigData)
 {
     RegisterControlToolbarItemClass();
-    
+
     OSStatus            err;
     EventRef            event;
     UInt32              options = kHIToolbarItemAllowDuplicates;
     HIToolbarItemRef    result = NULL;
-    
+
     err = CreateEvent( NULL, kEventClassHIObject, kEventHIObjectInitialize, GetCurrentEventTime(), 0, &event );
     require_noerr( err, CantCreateEvent );
-    
+
     SetEventParameter( event, kEventParamAttributes, typeUInt32, sizeof( UInt32 ), &options );
     SetEventParameter( event, kEventParamToolbarItemIdentifier, typeCFStringRef, sizeof( CFStringRef ), &inIdentifier );
-    
+
     if ( inConfigData )
         SetEventParameter( event, kEventParamToolbarItemConfigData, typeCFTypeRef, sizeof( CFTypeRef ), &inConfigData );
-    
+
     err = HIObjectCreate( kControlToolbarItemClassID, event, (HIObjectRef*)&result );
     check_noerr( err );
-    
+
     ReleaseEvent( event );
-CantCreateEvent :   
+CantCreateEvent :
     return result ;
 }
 
@@ -748,7 +787,7 @@ static OSStatus ToolbarDelegateHandler( EventHandlerCallRef inCallRef, EventRef
                 result = noErr;
             }
             break;
-            
+
         case kEventToolbarGetAllowedIdentifiers:
             {
                 GetEventParameter( inEvent, kEventParamMutableArray, typeCFMutableArrayRef, NULL,
@@ -763,13 +802,13 @@ static OSStatus ToolbarDelegateHandler( EventHandlerCallRef inCallRef, EventRef
                 HIToolbarItemRef        item = NULL;
                 CFTypeRef               data = NULL;
                 CFStringRef             identifier = NULL ;
-                
+
                 GetEventParameter( inEvent, kEventParamToolbarItemIdentifier, typeCFStringRef, NULL,
                         sizeof( CFStringRef ), NULL, &identifier );
-                
+
                 GetEventParameter( inEvent, kEventParamToolbarItemConfigData, typeCFTypeRef, NULL,
                         sizeof( CFTypeRef ), NULL, &data );
-                    
+
                 if ( CFStringCompare( kControlToolbarItemClassID, identifier, kCFCompareBackwards ) == kCFCompareEqualTo )
                 {
                     item = CreateControlToolbarItem( kControlToolbarItemClassID, data );
@@ -780,7 +819,7 @@ static OSStatus ToolbarDelegateHandler( EventHandlerCallRef inCallRef, EventRef
                         result = noErr;
                     }
                 }
-                
+
             }
             break;
     }
@@ -807,30 +846,33 @@ bool wxToolBar::Create(
     OSStatus err = noErr;
 
 #if wxMAC_USE_NATIVE_TOOLBAR
-    wxString labelStr = wxString::Format( wxT("%xd"), (int)this );
-    err = HIToolbarCreate(
-        wxMacCFStringHolder( labelStr, wxFont::GetDefaultEncoding() ), 0,
-        (HIToolbarRef*) &m_macHIToolbarRef );
-
-    if (m_macHIToolbarRef != NULL)
+    if (parent->IsKindOf(CLASSINFO(wxFrame)) && wxSystemOptions::GetOptionInt(wxT("mac.toolbar.no-native")) != 1)
     {
-        InstallEventHandler( HIObjectGetEventTarget((HIToolbarRef)m_macHIToolbarRef ), ToolbarDelegateHandler,
-                GetEventTypeCount( kToolbarEvents ), kToolbarEvents, this, NULL );
+        wxString labelStr = wxString::Format( wxT("%xd"), (int)this );
+        err = HIToolbarCreate(
+          wxMacCFStringHolder( labelStr, wxFont::GetDefaultEncoding() ), 0,
+          (HIToolbarRef*) &m_macHIToolbarRef );
 
-        HIToolbarDisplayMode mode = kHIToolbarDisplayModeDefault;
-        HIToolbarDisplaySize displaySize = kHIToolbarDisplaySizeSmall;
+        if (m_macHIToolbarRef != NULL)
+        {
+            InstallEventHandler( HIObjectGetEventTarget((HIToolbarRef)m_macHIToolbarRef ), ToolbarDelegateHandler,
+                    GetEventTypeCount( kToolbarEvents ), kToolbarEvents, this, NULL );
 
-        if ( style & wxTB_NOICONS )
-            mode = kHIToolbarDisplayModeLabelOnly;
-        else if ( style & wxTB_TEXT )
-            mode = kHIToolbarDisplayModeIconAndLabel;
-        else
-            mode = kHIToolbarDisplayModeIconOnly;
+            HIToolbarDisplayMode mode = kHIToolbarDisplayModeDefault;
+            HIToolbarDisplaySize displaySize = kHIToolbarDisplaySizeSmall;
+
+            if ( style & wxTB_NOICONS )
+                mode = kHIToolbarDisplayModeLabelOnly;
+            else if ( style & wxTB_TEXT )
+                mode = kHIToolbarDisplayModeIconAndLabel;
+            else
+                mode = kHIToolbarDisplayModeIconOnly;
 
-        HIToolbarSetDisplayMode( (HIToolbarRef) m_macHIToolbarRef, mode );
-        HIToolbarSetDisplaySize( (HIToolbarRef) m_macHIToolbarRef, displaySize );
+            HIToolbarSetDisplayMode( (HIToolbarRef) m_macHIToolbarRef, mode );
+          HIToolbarSetDisplaySize( (HIToolbarRef) m_macHIToolbarRef, displaySize );
+       }
     }
-#endif
+#endif // wxMAC_USE_NATIVE_TOOLBAR
 
     return (err == noErr);
 }
@@ -1067,7 +1109,7 @@ bool wxToolBar::Realize()
     // find the maximum tool width and height
     wxToolBarTool *tool;
     wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
-    while ( node != NULL )
+    while ( node )
     {
         tool = (wxToolBarTool *) node->GetData();
         if ( tool != NULL )
@@ -1089,10 +1131,12 @@ bool wxToolBar::Realize()
 #if wxMAC_USE_NATIVE_TOOLBAR
     CFIndex currentPosition = 0;
     bool insertAll = false;
+
+    HIToolbarRef refTB = (HIToolbarRef)m_macHIToolbarRef;
 #endif
 
     node = m_tools.GetFirst();
-    while ( node != NULL )
+    while ( node )
     {
         tool = (wxToolBarTool*) node->GetData();
         if ( tool == NULL )
@@ -1128,9 +1172,9 @@ bool wxToolBar::Realize()
 
 #if wxMAC_USE_NATIVE_TOOLBAR
         // install in native HIToolbar
-        if ( m_macHIToolbarRef != NULL )
+        if ( refTB )
         {
-            HIToolbarItemRef    hiItemRef = tool->GetToolbarItemRef();
+            HIToolbarItemRef hiItemRef = tool->GetToolbarItemRef();
             if ( hiItemRef != NULL )
             {
                 if ( insertAll || (tool->GetIndex() != currentPosition) )
@@ -1142,28 +1186,53 @@ bool wxToolBar::Realize()
 
                         // if this is the first tool that gets newly inserted or repositioned
                         // first remove all 'old' tools from here to the right, because of this
-                        // all following tools will have to be reinserted (insertAll). i = 100 because there's
-                        // no way to determine how many there are in a toolbar, so just a high number :-(
-                        for ( CFIndex i = 100; i >= currentPosition; --i )
+                        // all following tools will have to be reinserted (insertAll).
+                        for ( wxToolBarToolsList::compatibility_iterator node2 = m_tools.GetLast();
+                              node2 != node;
+                              node2 = node2->GetPrevious() )
                         {
-                            err = HIToolbarRemoveItemAtIndex( (HIToolbarRef) m_macHIToolbarRef, i );
-                        }
-
-                        if (err != noErr)
-                        {
-                            wxString errMsg = wxString::Format( wxT("HIToolbarRemoveItemAtIndex failed [%ld]"), (long)err );
-                            wxFAIL_MSG( errMsg.c_str() );
+                            wxToolBarTool *tool2 = (wxToolBarTool*) node2->GetData();
+
+                            const long idx = tool2->GetIndex();
+                            if ( idx != -1 )
+                            {
+                                if ( tool2->IsControl() )
+                                {
+                                    CFIndex count = CFGetRetainCount( tool2->GetControl()->GetPeer()->GetControlRef() ) ;
+                                    wxASSERT_MSG( count == 3 || count == 2 , wxT("Reference Count of native tool was illegal before removal") );
+                                    wxASSERT( IsValidControlHandle(tool2->GetControl()->GetPeer()->GetControlRef() )) ;
+                                }
+                                err = HIToolbarRemoveItemAtIndex(refTB, idx);
+                                if ( err != noErr )
+                                {
+                                    wxLogDebug(wxT("HIToolbarRemoveItemAtIndex(%ld) failed [%ld]"),
+                                               idx, (long)err);
+                                }
+                                if ( tool2->IsControl() )
+                                {
+                                    CFIndex count = CFGetRetainCount( tool2->GetControl()->GetPeer()->GetControlRef() ) ;
+                                    wxASSERT_MSG( count == 2 , wxT("Reference Count of native tool was not 2 after removal") );
+                                    wxASSERT( IsValidControlHandle(tool2->GetControl()->GetPeer()->GetControlRef() )) ;
+                                }
+
+                                tool2->SetIndex(-1);
+                            }
                         }
                     }
 
-                    err = HIToolbarInsertItemAtIndex( (HIToolbarRef) m_macHIToolbarRef, hiItemRef, currentPosition );
+                    err = HIToolbarInsertItemAtIndex( refTB, hiItemRef, currentPosition );
                     if (err != noErr)
                     {
-                        wxString errMsg = wxString::Format( wxT("HIToolbarInsertItemAtIndex failed [%ld]"), (long)err );
-                        wxFAIL_MSG( errMsg.c_str() );
+                        wxLogDebug( wxT("HIToolbarInsertItemAtIndex failed [%ld]"), (long)err );
                     }
 
                     tool->SetIndex( currentPosition );
+                    if ( tool->IsControl() )
+                    {
+                        CFIndex count = CFGetRetainCount( tool->GetControl()->GetPeer()->GetControlRef() ) ;
+                        wxASSERT_MSG( count == 3 || count == 2, wxT("Reference Count of native tool was illegal after insertion") );
+                        wxASSERT( IsValidControlHandle(tool->GetControl()->GetPeer()->GetControlRef() )) ;
+                    }
                 }
 
                 currentPosition++;
@@ -1195,7 +1264,7 @@ bool wxToolBar::Realize()
                     DoToggleTool( tool, true );
 
                 wxToolBarToolsList::compatibility_iterator  nodePrev = node->GetPrevious();
-                while ( nodePrev != NULL )
+                while ( nodePrev )
                 {
                     wxToolBarToolBase   *toggleTool = nodePrev->GetData();
                     if ( (toggleTool == NULL) || !toggleTool->IsButton() || (toggleTool->GetKind() != wxITEM_RADIO) )
@@ -1308,11 +1377,38 @@ void wxToolBar::MacSuperChangedPosition()
 #endif
 }
 
+void wxToolBar::SetToolNormalBitmap( int id, const wxBitmap& bitmap )
+{
+    wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
+    if ( tool )
+    {
+        wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
+
+        tool->SetNormalBitmap(bitmap);
+
+        // a side-effect of the UpdateToggleImage function is that it always changes the bitmap used on the button.
+        tool->UpdateToggleImage( tool->CanBeToggled() && tool->IsToggled() );
+    }
+}
+
+void wxToolBar::SetToolDisabledBitmap( int id, const wxBitmap& bitmap )
+{
+    wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
+    if ( tool )
+    {
+        wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
+
+        tool->SetDisabledBitmap(bitmap);
+
+        // TODO:  what to do for this one?
+    }
+}
+
 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
 {
     wxToolBarTool *tool;
     wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
-    while ( node != NULL )
+    while ( node )
     {
         tool = (wxToolBarTool *)node->GetData();
         if (tool != NULL)
@@ -1361,6 +1457,11 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
     Rect toolrect = { 0, 0, toolSize.y, toolSize.x };
     ControlRef controlHandle = NULL;
     OSStatus err = 0;
+    tool->Attach( this );
+
+#if wxMAC_USE_NATIVE_TOOLBAR
+    HIToolbarItemRef item;
+#endif
 
     switch (tool->GetStyle())
     {
@@ -1374,21 +1475,23 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
                 else
                     toolrect.right = toolSize.x;
 
-#ifdef __WXMAC_OSX__
                 // in flat style we need a visual separator
 #if wxMAC_USE_NATIVE_TOOLBAR
-                HIToolbarItemRef item;
-                err = HIToolbarItemCreate(
-                    kHIToolbarSeparatorIdentifier,
-                    kHIToolbarItemCantBeRemoved | kHIToolbarItemIsSeparator | kHIToolbarItemAllowDuplicates,
-                    &item );
-                if (err == noErr)
-                    tool->SetToolbarItemRef( item );
-#endif
+                if (m_macHIToolbarRef != NULL)
+                {
+                    err = HIToolbarItemCreate(
+                        kHIToolbarSeparatorIdentifier,
+                        kHIToolbarItemCantBeRemoved | kHIToolbarItemIsSeparator | kHIToolbarItemAllowDuplicates,
+                        &item );
+                    if (err == noErr)
+                        tool->SetToolbarItemRef( item );
+                }
+                else
+                    err = noErr;
+#endif // wxMAC_USE_NATIVE_TOOLBAR
 
                 CreateSeparatorControl( window, &toolrect, &controlHandle );
                 tool->SetControlHandle( controlHandle );
-#endif
             }
             break;
 
@@ -1413,22 +1516,26 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
                 }
 
 #if wxMAC_USE_NATIVE_TOOLBAR
-                HIToolbarItemRef item;
-                wxString labelStr = wxString::Format(wxT("%xd"), (int)tool);
-                err = HIToolbarItemCreate(
-                    wxMacCFStringHolder(labelStr, wxFont::GetDefaultEncoding()),
-                    kHIToolbarItemCantBeRemoved | kHIToolbarItemAnchoredLeft | kHIToolbarItemAllowDuplicates, &item );
-                if (err  == noErr)
+                if (m_macHIToolbarRef != NULL)
                 {
-                    InstallEventHandler(
-                        HIObjectGetEventTarget(item), GetwxMacToolBarEventHandlerUPP(),
-                        GetEventTypeCount(toolBarEventList), toolBarEventList, tool, NULL );
-                    HIToolbarItemSetLabel( item, wxMacCFStringHolder(tool->GetLabel(), m_font.GetEncoding()) );
-                    HIToolbarItemSetIconRef( item, info.u.iconRef );
-                    HIToolbarItemSetCommandID( item, kHIToolbarCommandPressAction );
-                    tool->SetToolbarItemRef( item );
+                    wxString labelStr = wxString::Format(wxT("%xd"), (int)tool);
+                    err = HIToolbarItemCreate(
+                        wxMacCFStringHolder(labelStr, wxFont::GetDefaultEncoding()),
+                        kHIToolbarItemCantBeRemoved | kHIToolbarItemAnchoredLeft | kHIToolbarItemAllowDuplicates, &item );
+                    if (err  == noErr)
+                    {
+                        InstallEventHandler(
+                            HIObjectGetEventTarget(item), GetwxMacToolBarEventHandlerUPP(),
+                            GetEventTypeCount(toolBarEventList), toolBarEventList, tool, NULL );
+
+                        HIToolbarItemSetIconRef( item, info.u.iconRef );
+                        HIToolbarItemSetCommandID( item, kHIToolbarCommandPressAction );
+                        tool->SetToolbarItemRef( item );
+                    }
                 }
-#endif
+                else
+                    err = noErr;
+#endif // wxMAC_USE_NATIVE_TOOLBAR
 
                 wxMacReleaseBitmapButton( &info );
 
@@ -1448,16 +1555,14 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
         case wxTOOL_STYLE_CONTROL:
 
 #if wxMAC_USE_NATIVE_TOOLBAR
+            if (m_macHIToolbarRef != NULL)
             {
-                wxASSERT( tool->GetControl() != NULL );
-                HIToolbarItemRef    item;
+                wxCHECK_MSG( tool->GetControl(), false, _T("control must be non-NULL") );
+
                 HIViewRef viewRef = (HIViewRef) tool->GetControl()->GetHandle() ;
-                // as this control now is part of both the wxToolBar children and the native toolbar, we have to increase the
-                // reference count to make sure we are not dealing with zombie controls after the native toolbar has released its views
-                CFRetain( viewRef ) ;
                 CFDataRef data = CFDataCreate( kCFAllocatorDefault , (UInt8*) &viewRef , sizeof(viewRef) ) ;
-                 err = HIToolbarCreateItemWithIdentifier((HIToolbarRef) m_macHIToolbarRef,kControlToolbarItemClassID,
-                   data , &item ) ;
+                err = HIToolbarCreateItemWithIdentifier((HIToolbarRef) m_macHIToolbarRef,kControlToolbarItemClassID,
+                    data , &item ) ;
 
                 if (err  == noErr)
                 {
@@ -1465,7 +1570,11 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
                 }
                 CFRelease( data ) ;
            }
-
+           else
+           {
+               err = noErr;
+               break;
+           }
 #else
                 // right now there's nothing to do here
 #endif
@@ -1475,6 +1584,19 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
             break;
     }
 
+#if wxMAC_USE_NATIVE_TOOLBAR
+    wxString label = tool->GetLabel();
+    if (m_macHIToolbarRef && !label.empty() )
+    {
+        // strip mnemonics from the label for compatibility
+        // with the usual labels in wxStaticText sense
+        label = wxStripMenuCodes(label);
+
+        HIToolbarItemSetLabel(item,
+                              wxMacCFStringHolder(label, m_font.GetEncoding()));
+    }
+#endif // wxMAC_USE_NATIVE_TOOLBAR
+
     if ( err == noErr )
     {
         if ( controlHandle )
@@ -1490,13 +1612,11 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
             tool->UpdateToggleImage( true );
 
         // nothing special to do here - we relayout in Realize() later
-        tool->Attach( this );
         InvalidateBestSize();
     }
     else
     {
-        wxString errMsg = wxString::Format( wxT("wxToolBar::DoInsertTool - failure [%ld]"), (long)err );
-        wxFAIL_MSG( errMsg.c_str() );
+        wxFAIL_MSG( wxString::Format( wxT("wxToolBar::DoInsertTool - failure [%ld]"), (long)err ) );
     }
 
     return (err == noErr);
@@ -1532,10 +1652,13 @@ bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolbase)
 #endif
 
 #if wxMAC_USE_NATIVE_TOOLBAR
-    if ( removeIndex != -1 && m_macHIToolbarRef )
+    if (m_macHIToolbarRef != NULL)
     {
-        HIToolbarRemoveItemAtIndex( (HIToolbarRef) m_macHIToolbarRef, removeIndex );
-        tool->SetIndex( -1 );
+        if ( removeIndex != -1 && m_macHIToolbarRef )
+        {
+            HIToolbarRemoveItemAtIndex( (HIToolbarRef) m_macHIToolbarRef, removeIndex );
+            tool->SetIndex( -1 );
+        }
     }
 #endif
     switch ( tool->GetStyle() )
@@ -1570,8 +1693,11 @@ bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolbase)
         tool2->SetPosition( pt );
 
 #if wxMAC_USE_NATIVE_TOOLBAR
-        if ( removeIndex != -1 && tool2->GetIndex() > removeIndex )
-            tool2->SetIndex( tool2->GetIndex() - 1 );
+        if (m_macHIToolbarRef != NULL)
+        {
+            if ( removeIndex != -1 && tool2->GetIndex() > removeIndex )
+                tool2->SetIndex( tool2->GetIndex() - 1 );
+        }
 #endif
     }