///////////////////////////////////////////////////////////////////////////// // Name: src/osx/carbon/toolbar.cpp // Purpose: wxToolBar // Author: Stefan Csomor // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ // Copyright: (c) Stefan Csomor // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #include "wx/wxprec.h" #if wxUSE_TOOLBAR #include "wx/toolbar.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/app.h" #include "wx/osx/private.h" #include "wx/geometry.h" #include "wx/sysopt.h" const short kwxMacToolBarToolDefaultWidth = 16; const short kwxMacToolBarToolDefaultHeight = 16; const short kwxMacToolBarTopMargin = 4; const short kwxMacToolBarLeftMargin = 4; const short kwxMacToolBorder = 0; const short kwxMacToolSpacing = 6; BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase) EVT_PAINT( wxToolBar::OnPaint ) END_EVENT_TABLE() #pragma mark - #pragma mark Tool Implementation // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- // 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: wxToolBarTool( wxToolBar *tbar, int id, const wxString& label, const wxBitmap& bmpNormal, const wxBitmap& bmpDisabled, wxItemKind kind, wxObject *clientData, const wxString& shortHelp, const wxString& longHelp ); wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label) : wxToolBarToolBase(tbar, control, label) { Init(); if (control != NULL) SetControlHandle( (ControlRef) control->GetHandle() ); } virtual ~wxToolBarTool() { ClearControl(); } WXWidget GetControlHandle() { return (WXWidget) m_controlHandle; } void SetControlHandle( ControlRef handle ) { m_controlHandle = handle; } void SetPosition( const wxPoint& position ); void ClearControl() { if ( m_controlHandle ) { if ( !IsControl() ) DisposeControl( m_controlHandle ); else { // the embedded control is not under the responsibility of the tool, it gets disposed of in the // proper wxControl destructor } m_controlHandle = NULL ; } #if wxOSX_USE_NATIVE_TOOLBAR if ( m_toolbarItemRef ) { CFIndex count = CFGetRetainCount( m_toolbarItemRef ) ; // different behaviour under Leopard if ( UMAGetSystemVersion() < 0x1050 ) { if ( count != 1 ) { wxFAIL_MSG("Reference count of native tool was not 1 in wxToolBarTool destructor"); } } wxTheApp->MacAddToAutorelease(m_toolbarItemRef); CFRelease(m_toolbarItemRef); m_toolbarItemRef = NULL; } #endif // wxOSX_USE_NATIVE_TOOLBAR } wxSize GetSize() const { wxSize curSize; if ( IsControl() ) { curSize = GetControl()->GetSize(); } else if ( IsButton() ) { curSize = GetToolBar()->GetToolSize(); } else { // separator size curSize = GetToolBar()->GetToolSize(); if ( GetToolBar()->GetWindowStyleFlag() & (wxTB_LEFT|wxTB_RIGHT) ) curSize.y /= 4; else curSize.x /= 4; } return curSize; } wxPoint GetPosition() const { return wxPoint( m_x, m_y ); } virtual bool Enable( bool enable ); void UpdateToggleImage( bool toggle ); virtual bool Toggle(bool toggle) { if ( wxToolBarToolBase::Toggle( toggle ) == false ) return false; UpdateToggleImage(toggle); return true; } void UpdateHelpStrings() { #if wxOSX_USE_NATIVE_TOOLBAR if ( m_toolbarItemRef ) { wxFontEncoding enc = GetToolBarFontEncoding(); HIToolbarItemSetHelpText( m_toolbarItemRef, wxCFStringRef( GetShortHelp(), enc ), wxCFStringRef( GetLongHelp(), enc ) ); } #endif } virtual bool SetShortHelp(const wxString& help) { if ( wxToolBarToolBase::SetShortHelp( help ) == false ) return false; UpdateHelpStrings(); return true; } virtual bool SetLongHelp(const wxString& help) { if ( wxToolBarToolBase::SetLongHelp( help ) == false ) return false; UpdateHelpStrings(); return true; } virtual void SetNormalBitmap(const wxBitmap& bmp) { wxToolBarToolBase::SetNormalBitmap(bmp); UpdateToggleImage(CanBeToggled() && IsToggled()); } virtual void SetLabel(const wxString& label) { wxToolBarToolBase::SetLabel(label); #if wxOSX_USE_NATIVE_TOOLBAR if ( m_toolbarItemRef ) { // strip mnemonics from the label for compatibility with the usual // labels in wxStaticText sense wxString labelStr = wxStripMenuCodes(label); HIToolbarItemSetLabel( m_toolbarItemRef, wxCFStringRef(labelStr, GetToolBarFontEncoding()) ); } #endif } #if wxOSX_USE_NATIVE_TOOLBAR void SetToolbarItemRef( HIToolbarItemRef ref ) { if ( m_controlHandle ) HideControl( m_controlHandle ); if ( m_toolbarItemRef ) CFRelease( m_toolbarItemRef ); m_toolbarItemRef = ref; UpdateHelpStrings(); } HIToolbarItemRef GetToolbarItemRef() const { return m_toolbarItemRef; } void SetIndex( CFIndex idx ) { m_index = idx; } CFIndex GetIndex() const { return m_index; } #endif // wxOSX_USE_NATIVE_TOOLBAR private: #if wxOSX_USE_NATIVE_TOOLBAR wxFontEncoding GetToolBarFontEncoding() const { wxFont f; if ( GetToolBar() ) f = GetToolBar()->GetFont(); return f.IsOk() ? f.GetEncoding() : wxFont::GetDefaultEncoding(); } #endif // wxOSX_USE_NATIVE_TOOLBAR void Init() { m_controlHandle = NULL; #if wxOSX_USE_NATIVE_TOOLBAR m_toolbarItemRef = NULL; m_index = -1; #endif } ControlRef m_controlHandle; wxCoord m_x; wxCoord m_y; #if wxOSX_USE_NATIVE_TOOLBAR HIToolbarItemRef m_toolbarItemRef; // position in its toolbar, -1 means not inserted CFIndex m_index; #endif }; static const EventTypeSpec eventList[] = { { kEventClassControl, kEventControlHit }, { kEventClassControl, kEventControlHitTest }, }; static pascal OSStatus wxMacToolBarToolControlEventHandler( EventHandlerCallRef WXUNUSED(handler), EventRef event, void *data ) { OSStatus result = eventNotHandledErr; ControlRef controlRef; wxMacCarbonEvent cEvent( event ); cEvent.GetParameter( kEventParamDirectObject, &controlRef ); switch ( GetEventKind( event ) ) { case kEventControlHit: { wxToolBarTool *tbartool = (wxToolBarTool*)data; wxToolBar *tbar = tbartool != NULL ? (wxToolBar*) (tbartool->GetToolBar()) : NULL; if ((tbartool != NULL) && tbartool->CanBeToggled()) { bool shouldToggle; shouldToggle = !tbartool->IsToggled(); tbar->ToggleTool( tbartool->GetId(), shouldToggle ); } if (tbartool != NULL) tbar->OnLeftClick( tbartool->GetId(), tbartool->IsToggled() ); result = noErr; } break; case kEventControlHitTest: { HIPoint pt = cEvent.GetParameter(kEventParamMouseLocation); HIRect rect; HIViewGetBounds( controlRef, &rect ); ControlPartCode pc = kControlNoPart; if ( CGRectContainsPoint( rect, pt ) ) pc = kControlIconPart; cEvent.SetParameter( kEventParamControlPart, typeControlPartCode, pc ); result = noErr; } break; default: break; } return result; } static pascal OSStatus wxMacToolBarToolEventHandler( EventHandlerCallRef handler, EventRef event, void *data ) { OSStatus result = eventNotHandledErr; switch ( GetEventClass( event ) ) { case kEventClassControl: result = wxMacToolBarToolControlEventHandler( handler, event, data ); break; default: break; } return result; } DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacToolBarToolEventHandler ) #if wxOSX_USE_NATIVE_TOOLBAR static const EventTypeSpec toolBarEventList[] = { { kEventClassToolbarItem, kEventToolbarItemPerformAction }, }; static pascal OSStatus wxMacToolBarCommandEventHandler( EventHandlerCallRef WXUNUSED(handler), EventRef event, void *data ) { OSStatus result = eventNotHandledErr; switch ( GetEventKind( event ) ) { case kEventToolbarItemPerformAction: { wxToolBarTool* tbartool = (wxToolBarTool*) data; if ( tbartool != NULL ) { wxToolBar *tbar = (wxToolBar*)(tbartool->GetToolBar()); int toolID = tbartool->GetId(); if ( tbartool->CanBeToggled() ) { if ( tbar != NULL ) tbar->ToggleTool(toolID, !tbartool->IsToggled() ); } if ( tbar != NULL ) tbar->OnLeftClick( toolID, tbartool->IsToggled() ); result = noErr; } } break; default: break; } return result; } static pascal OSStatus wxMacToolBarEventHandler( EventHandlerCallRef handler, EventRef event, void *data ) { OSStatus result = eventNotHandledErr; switch ( GetEventClass( event ) ) { case kEventClassToolbarItem: result = wxMacToolBarCommandEventHandler( handler, event, data ); break; default: break; } return result; } DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacToolBarEventHandler ) #endif bool wxToolBarTool::Enable( bool enable ) { if ( wxToolBarToolBase::Enable( enable ) == false ) return false; if ( IsControl() ) { GetControl()->Enable( enable ); } else if ( IsButton() ) { #if wxOSX_USE_NATIVE_TOOLBAR if ( m_toolbarItemRef != NULL ) HIToolbarItemSetEnabled( m_toolbarItemRef, enable ); #endif if ( m_controlHandle != NULL ) { if ( enable ) EnableControl( m_controlHandle ); else DisableControl( m_controlHandle ); } } return true; } void wxToolBarTool::SetPosition( const wxPoint& position ) { m_x = position.x; m_y = position.y; int mac_x = position.x; int mac_y = position.y; if ( IsButton() ) { Rect contrlRect; GetControlBounds( m_controlHandle, &contrlRect ); int former_mac_x = contrlRect.left; int former_mac_y = contrlRect.top; GetToolBar()->GetToolSize(); if ( mac_x != former_mac_x || mac_y != former_mac_y ) { ::MoveControl( m_controlHandle, mac_x, mac_y ); } } else if ( IsControl() ) { // embedded native controls are moved by the OS #if wxOSX_USE_NATIVE_TOOLBAR if ( ((wxToolBar*)GetToolBar())->MacWantsNativeToolbar() == false ) #endif { GetControl()->Move( position ); } } else { // separator Rect contrlRect; GetControlBounds( m_controlHandle, &contrlRect ); int former_mac_x = contrlRect.left; int former_mac_y = contrlRect.top; if ( mac_x != former_mac_x || mac_y != former_mac_y ) ::MoveControl( m_controlHandle, mac_x, mac_y ); } } void wxToolBarTool::UpdateToggleImage( bool toggle ) { if ( toggle ) { int w = m_bmpNormal.GetWidth() + 6; int h = m_bmpNormal.GetHeight() + 6; wxBitmap bmp( w, h ); wxMemoryDC dc; dc.SelectObject( bmp ); wxColour mid_grey_75 = wxColour(128, 128, 128, 196); wxColour light_grey_75 = wxColour(196, 196, 196, 196); dc.GradientFillLinear( wxRect(1, 1, w - 1, h-1), light_grey_75, mid_grey_75, wxNORTH); wxColour black_50 = wxColour(0, 0, 0, 127); dc.SetPen( wxPen(black_50) ); dc.DrawRoundedRectangle( 0, 0, w, h, 1.5 ); dc.DrawBitmap( m_bmpNormal, 3, 3, true ); dc.SelectObject( wxNullBitmap ); ControlButtonContentInfo info; wxMacCreateBitmapButton( &info, bmp ); SetControlData( m_controlHandle, 0, kControlIconContentTag, sizeof(info), (Ptr)&info ); #if wxOSX_USE_NATIVE_TOOLBAR if (m_toolbarItemRef != NULL) { ControlButtonContentInfo info2; wxMacCreateBitmapButton( &info2, bmp, kControlContentCGImageRef); HIToolbarItemSetImage( m_toolbarItemRef, info2.u.imageRef ); wxMacReleaseBitmapButton( &info2 ); } #endif wxMacReleaseBitmapButton( &info ); } else { ControlButtonContentInfo info; wxMacCreateBitmapButton( &info, m_bmpNormal ); SetControlData( m_controlHandle, 0, kControlIconContentTag, sizeof(info), (Ptr)&info ); #if wxOSX_USE_NATIVE_TOOLBAR if (m_toolbarItemRef != NULL) { ControlButtonContentInfo info2; wxMacCreateBitmapButton( &info2, m_bmpNormal, kControlContentCGImageRef); HIToolbarItemSetImage( m_toolbarItemRef, info2.u.imageRef ); wxMacReleaseBitmapButton( &info2 ); } #endif wxMacReleaseBitmapButton( &info ); } IconTransformType transform = toggle ? kTransformSelected : kTransformNone; SetControlData( m_controlHandle, 0, kControlIconTransformTag, sizeof(transform), (Ptr)&transform ); HIViewSetNeedsDisplay( m_controlHandle, true ); } wxToolBarTool::wxToolBarTool( wxToolBar *tbar, int id, const wxString& label, const wxBitmap& bmpNormal, const wxBitmap& bmpDisabled, wxItemKind kind, wxObject *clientData, const wxString& shortHelp, const wxString& longHelp ) : wxToolBarToolBase( tbar, id, label, bmpNormal, bmpDisabled, kind, clientData, shortHelp, longHelp ) { Init(); } #pragma mark - #pragma mark Toolbar Implementation wxToolBarToolBase *wxToolBar::CreateTool( int id, const wxString& label, const wxBitmap& bmpNormal, const wxBitmap& bmpDisabled, wxItemKind kind, wxObject *clientData, const wxString& shortHelp, const wxString& longHelp ) { return new wxToolBarTool( this, id, label, bmpNormal, bmpDisabled, kind, clientData, shortHelp, longHelp ); } wxToolBarToolBase * wxToolBar::CreateTool(wxControl *control, const wxString& label) { return new wxToolBarTool(this, control, label); } void wxToolBar::Init() { m_maxWidth = -1; m_maxHeight = -1; m_defaultWidth = kwxMacToolBarToolDefaultWidth; m_defaultHeight = kwxMacToolBarToolDefaultHeight; #if wxOSX_USE_NATIVE_TOOLBAR m_macToolbar = NULL; m_macUsesNativeToolbar = false; #endif } #define kControlToolbarItemClassID CFSTR( "org.wxwidgets.controltoolbaritem" ) const EventTypeSpec kEvents[] = { { kEventClassHIObject, kEventHIObjectConstruct }, { kEventClassHIObject, kEventHIObjectInitialize }, { kEventClassHIObject, kEventHIObjectDestruct }, { kEventClassToolbarItem, kEventToolbarItemCreateCustomView } }; const EventTypeSpec kViewEvents[] = { { kEventClassControl, kEventControlGetSizeConstraints } }; struct ControlToolbarItem { HIToolbarItemRef toolbarItem; HIViewRef viewRef; wxSize lastValidSize ; }; static pascal OSStatus ControlToolbarItemHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ) { OSStatus result = eventNotHandledErr; ControlToolbarItem* object = (ControlToolbarItem*)inUserData; switch ( GetEventClass( inEvent ) ) { case kEventClassHIObject: switch ( GetEventKind( inEvent ) ) { case kEventHIObjectConstruct: { 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 ) { 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: { HIViewRef viewRef = object->viewRef ; if( viewRef && IsValidControlHandle( 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 ) ; if ( count >= 1 ) { CFRelease( viewRef ) ; } } free( object ) ; result = noErr; } break; } break; case kEventClassToolbarItem: switch ( GetEventKind( inEvent ) ) { case kEventToolbarItemCreateCustomView: { HIViewRef viewRef = object->viewRef ; HIViewRemoveFromSuperview( viewRef ) ; HIViewSetVisible(viewRef, true) ; CFRetain( viewRef ) ; result = SetEventParameter( inEvent, kEventParamControlRef, typeControlRef, sizeof( HIViewRef ), &viewRef ); } break; } break; case kEventClassControl: switch ( GetEventKind( inEvent ) ) { case kEventControlGetSizeConstraints: { wxWindow* wxwindow = wxFindWindowFromWXWidget( (WXWidget) object->viewRef ) ; if ( wxwindow ) { // 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 ; } } break; } break; } return result; } void RegisterControlToolbarItemClass() { static bool sRegistered; if ( !sRegistered ) { HIObjectRegisterSubclass( kControlToolbarItemClassID, kHIToolbarItemClassID, 0, ControlToolbarItemHandler, GetEventTypeCount( kEvents ), kEvents, 0, NULL ); sRegistered = true; } } 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 wxOSX_USE_NATIVE_TOOLBAR static const EventTypeSpec kToolbarEvents[] = { { kEventClassToolbar, kEventToolbarGetDefaultIdentifiers }, { kEventClassToolbar, kEventToolbarGetAllowedIdentifiers }, { kEventClassToolbar, kEventToolbarCreateItemWithIdentifier }, }; static OSStatus ToolbarDelegateHandler(EventHandlerCallRef WXUNUSED(inCallRef), EventRef inEvent, void* WXUNUSED(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 // wxOSX_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 wxOSX_USE_NATIVE_TOOLBAR if (parent->IsKindOf(CLASSINFO(wxFrame)) && wxSystemOptions::GetOptionInt(wxT("mac.toolbar.no-native")) != 1) { wxString labelStr = wxString::Format( wxT("%p"), this ); err = HIToolbarCreate( wxCFStringRef( labelStr, wxFont::GetDefaultEncoding() ), 0, (HIToolbarRef*) &m_macToolbar ); if (m_macToolbar != NULL) { InstallEventHandler( HIObjectGetEventTarget((HIToolbarRef)m_macToolbar ), 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_macToolbar, mode ); HIToolbarSetDisplaySize( (HIToolbarRef) m_macToolbar, displaySize ); } } #endif // wxOSX_USE_NATIVE_TOOLBAR return (err == noErr); } wxToolBar::~wxToolBar() { #if wxOSX_USE_NATIVE_TOOLBAR if (m_macToolbar != NULL) { // if this is the installed toolbar, then deinstall it if (m_macUsesNativeToolbar) MacInstallNativeToolbar( false ); CFIndex count = CFGetRetainCount( m_macToolbar ) ; // Leopard seems to have one refcount more, so we cannot check reliably at the moment if ( UMAGetSystemVersion() < 0x1050 ) { if ( count != 1 ) { wxFAIL_MSG("Reference count of native control was not 1 in wxToolBar destructor"); } } CFRelease( (HIToolbarRef)m_macToolbar ); m_macToolbar = NULL; } #endif } bool wxToolBar::Show( bool show ) { WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef()); bool bResult = (tlw != NULL); if (bResult) { #if wxOSX_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 wxOSX_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 wxOSX_USE_NATIVE_TOOLBAR Rect boundsR; bool ownToolbarInstalled; MacTopLevelHasNativeToolbar( &ownToolbarInstalled ); if ( ownToolbarInstalled ) { // TODO: is this really a control ? GetControlBounds( (ControlRef) m_macToolbar, &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 wxOSX_USE_NATIVE_TOOLBAR if (m_macToolbar != NULL) { HIToolbarDisplayMode mode = kHIToolbarDisplayModeDefault; if ( style & wxTB_NOICONS ) mode = kHIToolbarDisplayModeLabelOnly; else if ( style & wxTB_TEXT ) mode = kHIToolbarDisplayModeIconAndLabel; else mode = kHIToolbarDisplayModeIconOnly; HIToolbarSetDisplayMode( (HIToolbarRef) m_macToolbar, mode ); } #endif } #if wxOSX_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_macToolbar); } return bResultV; } bool wxToolBar::MacInstallNativeToolbar(bool usesNative) { bool bResult = false; if (usesNative && (m_macToolbar == NULL)) return bResult; if (usesNative && ((GetWindowStyleFlag() & (wxTB_LEFT|wxTB_RIGHT|wxTB_BOTTOM)) != 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_macToolbar ); // ShowHideWindowToolbar will make the wxFrame grow // which we don't want in this case wxSize sz = GetParent()->GetSize(); ShowHideWindowToolbar( tlw, true, false ); // Restore the orginal size GetParent()->SetSize( sz ); ChangeWindowAttributes( tlw, kWindowToolbarButtonAttribute, 0 ); SetAutomaticControlDragTrackingEnabledForWindow( tlw, true ); m_peer->Move(0,0,0,0 ); SetSize( wxSIZE_AUTO_WIDTH, 0 ); m_peer->SetVisibility( false ); wxToolBarBase::Show( false ); } } else { // only deinstall toolbar if this is the installed one if (m_macToolbar == curToolbarRef) { bResult = true; ShowHideWindowToolbar( tlw, false, false ); ChangeWindowAttributes( tlw, 0, kWindowToolbarButtonAttribute ); SetWindowToolbar( tlw, NULL ); m_peer->SetVisibility( 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; wxSize tlw_sz = GetParent()->GetSize(); 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 ) { 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 wxOSX_USE_NATIVE_TOOLBAR CFIndex currentPosition = 0; bool insertAll = false; HIToolbarRef refTB = (HIToolbarRef)m_macToolbar; wxFont f; wxFontEncoding enc; f = GetFont(); if ( f.IsOk() ) enc = f.GetEncoding(); else enc = wxFont::GetDefaultEncoding(); #endif node = m_tools.GetFirst(); while ( node ) { 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_LEFT|wxTB_RIGHT) ) { 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_LEFT|wxTB_RIGHT) ) y += cursize.y + kwxMacToolSpacing; else x += cursize.x + kwxMacToolSpacing; #if wxOSX_USE_NATIVE_TOOLBAR // install in native HIToolbar if ( refTB ) { HIToolbarItemRef hiItemRef = tool->GetToolbarItemRef(); if ( hiItemRef != NULL ) { // since setting the help texts is non-virtual we have to update // the strings now 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). for ( wxToolBarToolsList::compatibility_iterator node2 = m_tools.GetLast(); node2 != node; node2 = node2->GetPrevious() ) { wxToolBarTool *tool2 = (wxToolBarTool*) node2->GetData(); const long idx = tool2->GetIndex(); if ( idx != -1 ) { if ( tool2->IsControl() ) { CFIndex count = CFGetRetainCount( tool2->GetControl()->GetPeer()->GetControlRef() ) ; if ( count != 3 && count != 2 ) { wxFAIL_MSG("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() ) ; if ( count != 2 ) { wxFAIL_MSG("Reference count of native tool was not 2 after removal"); } wxASSERT( IsValidControlHandle(tool2->GetControl()->GetPeer()->GetControlRef() )) ; } tool2->SetIndex(-1); } } } err = HIToolbarInsertItemAtIndex( refTB, hiItemRef, currentPosition ); if (err != noErr) { wxLogDebug( wxT("HIToolbarInsertItemAtIndex failed [%ld]"), (long)err ); } tool->SetIndex( currentPosition ); if ( tool->IsControl() ) { CFIndex count = CFGetRetainCount( tool->GetControl()->GetPeer()->GetControlRef() ) ; if ( count != 3 && count != 2 ) { wxFAIL_MSG("Reference count of native tool was illegal before removal"); } wxASSERT( IsValidControlHandle(tool->GetControl()->GetPeer()->GetControlRef() )) ; } } 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 ) { 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(); } if (m_macUsesNativeToolbar) GetParent()->SetSize( tlw_sz ); if ( GetWindowStyleFlag() & (wxTB_TOP|wxTB_BOTTOM) ) { // if not set yet, only one row if ( m_maxRows <= 0 ) SetRows( 1 ); m_minWidth = maxWidth; maxHeight += m_yMargin + kwxMacToolBarTopMargin; m_minHeight = m_maxHeight = maxHeight; } else { // if not set yet, have one column if ( (GetToolsCount() > 0) && (m_maxRows <= 0) ) SetRows( GetToolsCount() ); m_minHeight = maxHeight; maxWidth += m_xMargin + kwxMacToolBarLeftMargin; m_minWidth = m_maxWidth = maxWidth; } #if 0 // FIXME: should this be OSX-only? { bool wantNativeToolbar, ownToolbarInstalled; // attempt to install the native toolbar wantNativeToolbar = ((GetWindowStyleFlag() & (wxTB_LEFT|wxTB_BOTTOM|wxTB_RIGHT)) == 0); MacInstallNativeToolbar( wantNativeToolbar ); (void)MacTopLevelHasNativeToolbar( &ownToolbarInstalled ); if (!ownToolbarInstalled) { SetSize( maxWidth, maxHeight ); InvalidateBestSize(); } } #else SetSize( maxWidth, maxHeight ); InvalidateBestSize(); #endif SetInitialSize(); return true; } void wxToolBar::SetToolBitmapSize(const wxSize& size) { m_defaultWidth = size.x + kwxMacToolBorder; m_defaultHeight = size.y + kwxMacToolBorder; #if wxOSX_USE_NATIVE_TOOLBAR if (m_macToolbar != NULL) { int maxs = wxMax( size.x, size.y ); HIToolbarDisplaySize sizeSpec; if ( maxs > 32 ) sizeSpec = kHIToolbarDisplaySizeNormal; else if ( maxs > 24 ) sizeSpec = kHIToolbarDisplaySizeDefault; else sizeSpec = kHIToolbarDisplaySizeSmall; HIToolbarSetDisplaySize( (HIToolbarRef) m_macToolbar, sizeSpec ); } #endif } // The button size is bigger than the bitmap size wxSize wxToolBar::GetToolSize() const { return wxSize(m_defaultWidth + kwxMacToolBorder, m_defaultHeight + kwxMacToolBorder); } void wxToolBar::SetRows(int nRows) { // avoid resizing the frame uselessly if ( nRows != m_maxRows ) m_maxRows = nRows; } void wxToolBar::MacSuperChangedPosition() { wxWindow::MacSuperChangedPosition(); #if wxOSX_USE_NATIVE_TOOLBAR if (! m_macUsesNativeToolbar ) Realize(); #else Realize(); #endif } void wxToolBar::SetToolNormalBitmap( int id, const wxBitmap& bitmap ) { wxToolBarTool* tool = static_cast(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 = static_cast(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 ) { tool = (wxToolBarTool *)node->GetData(); if (tool != NULL) { wxRect2DInt r( tool->GetPosition(), tool->GetSize() ); if ( r.Contains( wxPoint( x, y ) ) ) return tool; } node = node->GetNext(); } return NULL; } wxString wxToolBar::MacGetToolTipString( wxPoint &pt ) { wxToolBarToolBase *tool = FindToolForPosition( pt.x, pt.y ); if ( tool != NULL ) return tool->GetShortHelp(); return wxEmptyString; } void wxToolBar::DoEnableTool(wxToolBarToolBase *WXUNUSED(t), bool WXUNUSED(enable)) { // everything already done in the tool's implementation } void wxToolBar::DoToggleTool(wxToolBarToolBase *WXUNUSED(t), bool WXUNUSED(toggle)) { // everything already done in the tool's implementation } bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase) { wxToolBarTool *tool = static_cast< wxToolBarTool*>(toolBase ); if (tool == NULL) return false; WindowRef window = (WindowRef) MacGetTopLevelWindowRef(); wxSize toolSize = GetToolSize(); Rect toolrect = { 0, 0, toolSize.y, toolSize.x }; ControlRef controlHandle = NULL; OSStatus err = 0; #if wxOSX_USE_NATIVE_TOOLBAR wxString label = tool->GetLabel(); if (m_macToolbar && !label.empty() ) { // strip mnemonics from the label for compatibility // with the usual labels in wxStaticText sense label = wxStripMenuCodes(label); } #endif // wxOSX_USE_NATIVE_TOOLBAR switch (tool->GetStyle()) { case wxTOOL_STYLE_SEPARATOR: { wxASSERT( tool->GetControlHandle() == NULL ); toolSize.x /= 4; toolSize.y /= 4; if ( GetWindowStyleFlag() & (wxTB_LEFT|wxTB_RIGHT) ) toolrect.bottom = toolSize.y; else toolrect.right = toolSize.x; // in flat style we need a visual separator #if wxOSX_USE_NATIVE_TOOLBAR if (m_macToolbar != NULL) { HIToolbarItemRef item; err = HIToolbarItemCreate( kHIToolbarSeparatorIdentifier, kHIToolbarItemCantBeRemoved | kHIToolbarItemIsSeparator | kHIToolbarItemAllowDuplicates, &item ); if (err == noErr) tool->SetToolbarItemRef( item ); } else err = noErr; #endif // wxOSX_USE_NATIVE_TOOLBAR CreateSeparatorControl( window, &toolrect, &controlHandle ); tool->SetControlHandle( controlHandle ); } break; case wxTOOL_STYLE_BUTTON: { wxASSERT( tool->GetControlHandle() == NULL ); ControlButtonContentInfo info; wxMacCreateBitmapButton( &info, tool->GetNormalBitmap() ); if ( UMAGetSystemVersion() >= 0x1000) { // contrary to the docs this control only works with iconrefs ControlButtonContentInfo info; wxMacCreateBitmapButton( &info, tool->GetNormalBitmap(), kControlContentIconRef ); CreateIconControl( window, &toolrect, &info, false, &controlHandle ); wxMacReleaseBitmapButton( &info ); } else { SInt16 behaviour = kControlBehaviorOffsetContents; if ( tool->CanBeToggled() ) behaviour |= kControlBehaviorToggles; err = CreateBevelButtonControl( window, &toolrect, CFSTR(""), kControlBevelButtonNormalBevel, behaviour, &info, 0, 0, 0, &controlHandle ); } #if wxOSX_USE_NATIVE_TOOLBAR if (m_macToolbar != NULL) { HIToolbarItemRef item; wxString labelStr = wxString::Format(wxT("%p"), tool); err = HIToolbarItemCreate( wxCFStringRef(labelStr, wxFont::GetDefaultEncoding()), kHIToolbarItemCantBeRemoved | kHIToolbarItemAnchoredLeft | kHIToolbarItemAllowDuplicates, &item ); if (err == noErr) { ControlButtonContentInfo info2; wxMacCreateBitmapButton( &info2, tool->GetNormalBitmap(), kControlContentCGImageRef); InstallEventHandler( HIObjectGetEventTarget(item), GetwxMacToolBarEventHandlerUPP(), GetEventTypeCount(toolBarEventList), toolBarEventList, tool, NULL ); HIToolbarItemSetLabel( item, wxCFStringRef(label, GetFont().GetEncoding()) ); HIToolbarItemSetImage( item, info2.u.imageRef ); HIToolbarItemSetCommandID( item, kHIToolbarCommandPressAction ); tool->SetToolbarItemRef( item ); wxMacReleaseBitmapButton( &info2 ); } } else err = noErr; #endif // wxOSX_USE_NATIVE_TOOLBAR wxMacReleaseBitmapButton( &info ); #if 0 SetBevelButtonTextPlacement( m_controlHandle, kControlBevelButtonPlaceBelowGraphic ); SetControlTitleWithCFString( m_controlHandle , wxCFStringRef( label, wxFont::GetDefaultEncoding() ); #endif InstallControlEventHandler( (ControlRef) controlHandle, GetwxMacToolBarToolEventHandlerUPP(), GetEventTypeCount(eventList), eventList, tool, NULL ); tool->SetControlHandle( controlHandle ); } break; case wxTOOL_STYLE_CONTROL: #if wxOSX_USE_NATIVE_TOOLBAR if (m_macToolbar != NULL) { wxCHECK_MSG( tool->GetControl(), false, _T("control must be non-NULL") ); HIToolbarItemRef item; HIViewRef viewRef = (HIViewRef) tool->GetControl()->GetHandle() ; CFDataRef data = CFDataCreate( kCFAllocatorDefault , (UInt8*) &viewRef , sizeof(viewRef) ) ; err = HIToolbarCreateItemWithIdentifier((HIToolbarRef) m_macToolbar,kControlToolbarItemClassID, data , &item ) ; if (err == noErr) { tool->SetToolbarItemRef( item ); } CFRelease( data ) ; } else { err = noErr; break; } #else // right now there's nothing to do here #endif break; default: break; } if ( err == noErr ) { if ( controlHandle ) { ControlRef container = (ControlRef) GetHandle(); wxASSERT_MSG( container != NULL, wxT("No valid Mac container control") ); SetControlVisibility( controlHandle, true, true ); ::EmbedControl( controlHandle, container ); } if ( tool->CanBeToggled() && tool->IsToggled() ) tool->UpdateToggleImage( true ); // nothing special to do here - we relayout in Realize() later InvalidateBestSize(); } else { wxFAIL_MSG( wxString::Format( wxT("wxToolBar::DoInsertTool - failure [%ld]"), (long)err ) ); } return (err == noErr); } void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle)) { // nothing to do } bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolbase) { wxToolBarTool* tool = static_cast< wxToolBarTool*>(toolbase ); wxToolBarToolsList::compatibility_iterator node; for ( node = m_tools.GetFirst(); node; node = node->GetNext() ) { wxToolBarToolBase *tool2 = node->GetData(); if ( tool2 == tool ) { // let node point to the next node in the list node = node->GetNext(); break; } } wxSize sz = ((wxToolBarTool*)tool)->GetSize(); #if wxOSX_USE_NATIVE_TOOLBAR CFIndex removeIndex = tool->GetIndex(); #endif #if wxOSX_USE_NATIVE_TOOLBAR if (m_macToolbar != NULL) { if ( removeIndex != -1 && m_macToolbar ) { HIToolbarRemoveItemAtIndex( (HIToolbarRef) m_macToolbar, removeIndex ); tool->SetIndex( -1 ); } } #endif tool->ClearControl(); // and finally reposition all the controls after this one for ( /* node -> first after deleted */; node; node = node->GetNext() ) { wxToolBarTool *tool2 = (wxToolBarTool*) node->GetData(); wxPoint pt = tool2->GetPosition(); if ( GetWindowStyleFlag() & (wxTB_LEFT|wxTB_RIGHT) ) pt.y -= sz.y; else pt.x -= sz.x; tool2->SetPosition( pt ); #if wxOSX_USE_NATIVE_TOOLBAR if (m_macToolbar != NULL) { if ( removeIndex != -1 && tool2->GetIndex() > removeIndex ) tool2->SetIndex( tool2->GetIndex() - 1 ); } #endif } InvalidateBestSize(); return true; } void wxToolBar::OnPaint(wxPaintEvent& event) { #if wxOSX_USE_NATIVE_TOOLBAR if ( m_macUsesNativeToolbar ) { event.Skip(true); return; } #endif wxPaintDC dc(this); int w, h; GetSize( &w, &h ); bool drawMetalTheme = MacGetTopLevelWindow()->GetExtraStyle() & wxFRAME_EX_METAL; if ( !drawMetalTheme ) { HIThemePlacardDrawInfo info; memset( &info, 0, sizeof(info) ); info.version = 0; info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive; CGContextRef cgContext = (CGContextRef) MacGetCGContextRef(); HIRect rect = CGRectMake( 0, 0, w, h ); HIThemeDrawPlacard( &rect, &info, cgContext, kHIThemeOrientationNormal ); } else { // leave the background as it is (striped or metal) } event.Skip(); } #endif // wxUSE_TOOLBAR