+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 :
+ return result ;
+}
+
+#if wxMAC_USE_NATIVE_TOOLBAR
+static const EventTypeSpec kToolbarEvents[] =
+{
+ { kEventClassToolbar, kEventToolbarGetDefaultIdentifiers },
+ { kEventClassToolbar, kEventToolbarGetAllowedIdentifiers },
+ { kEventClassToolbar, kEventToolbarCreateItemWithIdentifier },
+};
+
+static OSStatus ToolbarDelegateHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
+{
+ OSStatus result = eventNotHandledErr;
+ // Not yet needed
+ // wxToolBar* toolbar = (wxToolBar*) inUserData ;
+ CFMutableArrayRef array;
+
+ switch ( GetEventKind( inEvent ) )
+ {
+ case kEventToolbarGetDefaultIdentifiers:
+ {
+ GetEventParameter( inEvent, kEventParamMutableArray, typeCFMutableArrayRef, NULL,
+ sizeof( CFMutableArrayRef ), NULL, &array );
+ // not implemented yet
+ // GetToolbarDefaultItems( array );
+ result = noErr;
+ }
+ break;
+
+ case kEventToolbarGetAllowedIdentifiers:
+ {
+ GetEventParameter( inEvent, kEventParamMutableArray, typeCFMutableArrayRef, NULL,
+ sizeof( CFMutableArrayRef ), NULL, &array );
+ // not implemented yet
+ // GetToolbarAllowedItems( array );
+ result = noErr;
+ }
+ break;
+ case kEventToolbarCreateItemWithIdentifier:
+ {
+ 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 );
+ if ( item )
+ {
+ SetEventParameter( inEvent, kEventParamToolbarItem, typeHIToolbarItemRef,
+ sizeof( HIToolbarItemRef ), &item );
+ result = noErr;
+ }
+ }
+
+ }
+ break;
+ }
+ return result ;
+}
+#endif // wxMAC_USE_NATIVE_TOOLBAR
+
+// also for the toolbar we have the dual implementation:
+// only when MacInstallNativeToolbar is called is the native toolbar set as the window toolbar
+
+bool wxToolBar::Create(
+ wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name )
+{
+ if ( !wxToolBarBase::Create( parent, id, pos, size, style, wxDefaultValidator, name ) )
+ return false;
+
+ FixupStyle();
+
+ 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)
+ {
+ InstallEventHandler( HIObjectGetEventTarget((HIToolbarRef)m_macHIToolbarRef ), ToolbarDelegateHandler,
+ GetEventTypeCount( kToolbarEvents ), kToolbarEvents, this, NULL );
+
+ 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 );
+ }
+#endif
+
+ return (err == noErr);
+}
+
+wxToolBar::~wxToolBar()
+{
+#if wxMAC_USE_NATIVE_TOOLBAR
+ if (m_macHIToolbarRef != NULL)
+ {
+ // if this is the installed toolbar, then deinstall it
+ if (m_macUsesNativeToolbar)
+ MacInstallNativeToolbar( false );
+
+ CFRelease( (HIToolbarRef)m_macHIToolbarRef );
+ m_macHIToolbarRef = NULL;
+ }
+#endif
+}
+
+bool wxToolBar::Show( bool show )
+{
+ WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
+ bool bResult = (tlw != NULL);
+
+ if (bResult)
+ {
+#if wxMAC_USE_NATIVE_TOOLBAR
+ bool ownToolbarInstalled = false;
+ MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
+ if (ownToolbarInstalled)
+ {
+ bResult = (IsWindowToolbarVisible( tlw ) != show);
+ if ( bResult )
+ ShowHideWindowToolbar( tlw, show, false );
+ }
+ else
+ bResult = wxToolBarBase::Show( show );
+#else
+
+ bResult = wxToolBarBase::Show( show );
+#endif
+ }
+
+ return bResult;
+}
+
+bool wxToolBar::IsShown() const
+{
+ bool bResult;
+
+#if wxMAC_USE_NATIVE_TOOLBAR
+ bool ownToolbarInstalled;
+
+ MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
+ if (ownToolbarInstalled)
+ {
+ WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
+ bResult = IsWindowToolbarVisible( tlw );
+ }
+ else
+ bResult = wxToolBarBase::IsShown();
+#else
+
+ bResult = wxToolBarBase::IsShown();
+#endif
+
+ return bResult;
+}
+
+void wxToolBar::DoGetSize( int *width, int *height ) const
+{
+#if wxMAC_USE_NATIVE_TOOLBAR
+ Rect boundsR;
+ bool ownToolbarInstalled;
+
+ MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
+ if ( ownToolbarInstalled )
+ {
+ // TODO: is this really a control ?
+ GetControlBounds( (ControlRef) m_macHIToolbarRef, &boundsR );
+ if ( width != NULL )
+ *width = boundsR.right - boundsR.left;
+ if ( height != NULL )
+ *height = boundsR.bottom - boundsR.top;
+ }
+ else
+ wxToolBarBase::DoGetSize( width, height );
+
+#else
+ wxToolBarBase::DoGetSize( width, height );
+#endif
+}
+
+wxSize wxToolBar::DoGetBestSize() const
+{
+ int width, height;
+
+ DoGetSize( &width, &height );
+
+ return wxSize( width, height );
+}
+
+void wxToolBar::SetWindowStyleFlag( long style )
+{
+ wxToolBarBase::SetWindowStyleFlag( style );
+
+#if wxMAC_USE_NATIVE_TOOLBAR
+ if (m_macHIToolbarRef != NULL)
+ {
+ HIToolbarDisplayMode mode = kHIToolbarDisplayModeDefault;
+
+ if ( style & wxTB_NOICONS )
+ mode = kHIToolbarDisplayModeLabelOnly;
+ else if ( style & wxTB_TEXT )
+ mode = kHIToolbarDisplayModeIconAndLabel;
+ else
+ mode = kHIToolbarDisplayModeIconOnly;
+
+ HIToolbarSetDisplayMode( (HIToolbarRef) m_macHIToolbarRef, mode );
+ }
+#endif
+}
+
+#if wxMAC_USE_NATIVE_TOOLBAR
+bool wxToolBar::MacWantsNativeToolbar()
+{
+ return m_macUsesNativeToolbar;
+}
+
+bool wxToolBar::MacTopLevelHasNativeToolbar(bool *ownToolbarInstalled) const
+{
+ bool bResultV = false;
+
+ if (ownToolbarInstalled != NULL)
+ *ownToolbarInstalled = false;
+
+ WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
+ if (tlw != NULL)
+ {
+ HIToolbarRef curToolbarRef = NULL;
+ OSStatus err = GetWindowToolbar( tlw, &curToolbarRef );
+ bResultV = ((err == noErr) && (curToolbarRef != NULL));
+ if (bResultV && (ownToolbarInstalled != NULL))
+ *ownToolbarInstalled = (curToolbarRef == m_macHIToolbarRef);
+ }
+
+ return bResultV;
+}
+
+bool wxToolBar::MacInstallNativeToolbar(bool usesNative)
+{
+ bool bResult = false;
+
+ if (usesNative && (m_macHIToolbarRef == NULL))
+ return bResult;
+
+ if (usesNative && ((GetWindowStyleFlag() & wxTB_VERTICAL) != 0))
+ return bResult;
+
+ WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
+ if (tlw == NULL)
+ return bResult;
+
+ // check the existing toolbar
+ HIToolbarRef curToolbarRef = NULL;
+ OSStatus err = GetWindowToolbar( tlw, &curToolbarRef );
+ if (err != noErr)
+ curToolbarRef = NULL;
+
+ m_macUsesNativeToolbar = usesNative;
+
+ if (m_macUsesNativeToolbar)
+ {
+ // only install toolbar if there isn't one installed already
+ if (curToolbarRef == NULL)
+ {
+ bResult = true;
+
+ SetWindowToolbar( tlw, (HIToolbarRef) m_macHIToolbarRef );
+ ShowHideWindowToolbar( tlw, true, false );
+ ChangeWindowAttributes( tlw, kWindowToolbarButtonAttribute, 0 );
+ SetAutomaticControlDragTrackingEnabledForWindow( tlw, true );
+
+ Rect r = { 0, 0, 0, 0 };
+ m_peer->SetRect( &r );
+ SetSize( wxSIZE_AUTO_WIDTH, 0 );
+ m_peer->SetVisibility( false, true );
+ wxToolBarBase::Show( false );
+ }
+ }
+ else
+ {
+ // only deinstall toolbar if this is the installed one
+ if (m_macHIToolbarRef == curToolbarRef)
+ {
+ bResult = true;
+
+ ShowHideWindowToolbar( tlw, false, false );
+ ChangeWindowAttributes( tlw, 0, kWindowToolbarButtonAttribute );
+ SetWindowToolbar( tlw, NULL );
+
+ m_peer->SetVisibility( true, true );
+ }
+ }
+
+ if (bResult)
+ InvalidateBestSize();
+
+// wxLogDebug( wxT(" --> [%lx] - result [%s]"), (long)this, bResult ? wxT("T") : wxT("F") );
+ return bResult;
+}
+#endif
+
+bool wxToolBar::Realize()
+{
+ if (m_tools.GetCount() == 0)
+ return false;
+
+ int maxWidth = 0;
+ int maxHeight = 0;
+
+ int maxToolWidth = 0;
+ int maxToolHeight = 0;
+
+ int x = m_xMargin + kwxMacToolBarLeftMargin;
+ int y = m_yMargin + kwxMacToolBarTopMargin;
+
+ int tw, th;
+ GetSize( &tw, &th );
+
+ // find the maximum tool width and height
+ wxToolBarTool *tool;
+ wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
+ while ( node != NULL )
+ {
+ tool = (wxToolBarTool *) node->GetData();
+ if ( tool != NULL )
+ {
+ wxSize sz = tool->GetSize();
+
+ if ( sz.x > maxToolWidth )
+ maxToolWidth = sz.x;
+ if ( sz.y > maxToolHeight )
+ maxToolHeight = sz.y;
+ }
+
+ node = node->GetNext();
+ }
+
+ bool lastIsRadio = false;
+ bool curIsRadio = false;
+
+#if wxMAC_USE_NATIVE_TOOLBAR
+ CFIndex currentPosition = 0;
+ bool insertAll = false;
+#endif
+
+ node = m_tools.GetFirst();
+ while ( node != NULL )
+ {
+ tool = (wxToolBarTool*) node->GetData();
+ if ( tool == NULL )
+ {
+ node = node->GetNext();
+ continue;
+ }
+
+ // set tool position:
+ // for the moment just perform a single row/column alignment
+ wxSize cursize = tool->GetSize();
+ if ( x + cursize.x > maxWidth )
+ maxWidth = x + cursize.x;
+ if ( y + cursize.y > maxHeight )
+ maxHeight = y + cursize.y;
+
+ if ( GetWindowStyleFlag() & wxTB_VERTICAL )
+ {
+ int x1 = x + ( maxToolWidth - cursize.x ) / 2;
+ tool->SetPosition( wxPoint(x1, y) );
+ }
+ else
+ {
+ int y1 = y + ( maxToolHeight - cursize.y ) / 2;
+ tool->SetPosition( wxPoint(x, y1) );
+ }
+
+ // update the item positioning state
+ if ( GetWindowStyleFlag() & wxTB_VERTICAL )
+ y += cursize.y + kwxMacToolSpacing;
+ else
+ x += cursize.x + kwxMacToolSpacing;
+
+#if wxMAC_USE_NATIVE_TOOLBAR
+ // install in native HIToolbar
+ if ( m_macHIToolbarRef != NULL )
+ {
+ HIToolbarItemRef hiItemRef = tool->GetToolbarItemRef();
+ if ( hiItemRef != NULL )
+ {
+ if ( insertAll || (tool->GetIndex() != currentPosition) )
+ {
+ OSStatus err = noErr;
+ if ( !insertAll )
+ {
+ insertAll = true;
+
+ // 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 )
+ {
+ err = HIToolbarRemoveItemAtIndex( (HIToolbarRef) m_macHIToolbarRef, i );
+ }
+
+ if (err != noErr)
+ {
+ wxString errMsg = wxString::Format( wxT("HIToolbarRemoveItemAtIndex failed [%ld]"), (long)err );
+ wxFAIL_MSG( errMsg.c_str() );
+ }
+ }
+
+ err = HIToolbarInsertItemAtIndex( (HIToolbarRef) m_macHIToolbarRef, hiItemRef, currentPosition );
+ if (err != noErr)
+ {
+ wxString errMsg = wxString::Format( wxT("HIToolbarInsertItemAtIndex failed [%ld]"), (long)err );
+ wxFAIL_MSG( errMsg.c_str() );
+ }
+
+ tool->SetIndex( currentPosition );
+ }
+
+ currentPosition++;
+ }
+ }
+#endif
+
+ // update radio button (and group) state
+ lastIsRadio = curIsRadio;
+ curIsRadio = ( tool->IsButton() && (tool->GetKind() == wxITEM_RADIO) );
+
+ if ( !curIsRadio )
+ {
+ if ( tool->IsToggled() )
+ DoToggleTool( tool, true );
+ }
+ else
+ {
+ if ( !lastIsRadio )
+ {
+ if ( tool->Toggle( true ) )
+ {
+ DoToggleTool( tool, true );
+ }
+ }
+ else if ( tool->IsToggled() )
+ {
+ if ( tool->IsToggled() )
+ DoToggleTool( tool, true );
+
+ wxToolBarToolsList::compatibility_iterator nodePrev = node->GetPrevious();
+ while ( nodePrev != NULL )
+ {
+ wxToolBarToolBase *toggleTool = nodePrev->GetData();
+ if ( (toggleTool == NULL) || !toggleTool->IsButton() || (toggleTool->GetKind() != wxITEM_RADIO) )
+ break;
+
+ if ( toggleTool->Toggle( false ) )
+ DoToggleTool( toggleTool, false );
+
+ nodePrev = nodePrev->GetPrevious();
+ }
+ }
+ }
+
+ node = node->GetNext();
+ }