+
+#include "wx/mac/uma.h"
+#include "wx/geometry.h"
+
+#ifdef __WXMAC_OSX__
+const short kwxMacToolBarToolDefaultWidth = 16 ;
+const short kwxMacToolBarToolDefaultHeight = 16 ;
+const short kwxMacToolBarTopMargin = 4 ; // 1 ; // used to be 4
+const short kwxMacToolBarLeftMargin = 4 ; //1 ; // used to be 4
+const short kwxMacToolBorder = 0 ; // used to be 0
+const short kwxMacToolSpacing = 6 ; // 2 ; // used to be 6
+#else
+const short kwxMacToolBarToolDefaultWidth = 24 ;
+const short kwxMacToolBarToolDefaultHeight = 22 ;
+const short kwxMacToolBarTopMargin = 2 ;
+const short kwxMacToolBarLeftMargin = 2 ;
+const short kwxMacToolBorder = 4 ;
+const short kwxMacToolSpacing = 0 ;
+#endif
+
+#pragma mark -
+#pragma mark Tool Implementation
+
+
+// ----------------------------------------------------------------------------
+// private classes
+// ----------------------------------------------------------------------------
+
+// We have a dual implementation for each tool, ControlRef and HIToolbarItemRef
+
+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)
+ : wxToolBarToolBase(tbar, control)
+ {
+ Init() ;
+ if (control != NULL)
+ SetControlHandle( (ControlRef) control->GetHandle() ) ;
+ }
+
+ ~wxToolBarTool()
+ {
+ ClearControl() ;
+ if ( m_controlHandle )
+ DisposeControl( m_controlHandle ) ;
+#if wxMAC_USE_NATIVE_TOOLBAR
+ if ( m_toolbarItemRef )
+ CFRelease( m_toolbarItemRef ) ;
+#endif
+ }
+
+ WXWidget GetControlHandle()
+ {
+ return (WXWidget) m_controlHandle ;
+ }
+
+ void SetControlHandle( ControlRef handle )
+ {
+ m_controlHandle = handle ;
+ }
+
+ void SetPosition( const wxPoint& position ) ;
+
+ void ClearControl()
+ {
+ m_control = NULL ;
+#if wxMAC_USE_NATIVE_TOOLBAR
+ m_toolbarItemRef = NULL ;
+#endif
+ }
+
+ wxSize GetSize() const
+ {
+ if ( IsControl() )
+ {
+ return GetControl()->GetSize() ;
+ }
+ else if ( IsButton() )
+ {
+ return GetToolBar()->GetToolSize() ;
+ }
+ else
+ {
+ // separator size
+ wxSize sz = GetToolBar()->GetToolSize() ;
+ if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
+ sz.y /= 4 ;
+ else
+ sz.x /= 4 ;
+ return sz ;
+ }
+ }
+ wxPoint GetPosition() const
+ {
+ return wxPoint(m_x, m_y);
+ }
+ bool DoEnable( bool enable ) ;
+
+ void UpdateToggleImage( bool toggle ) ;
+
+#if wxMAC_USE_NATIVE_TOOLBAR
+ void SetToolbarItemRef( HIToolbarItemRef ref )
+ {
+ if ( m_controlHandle )
+ HideControl( m_controlHandle ) ;
+ if ( m_toolbarItemRef )
+ CFRelease( m_toolbarItemRef ) ;
+ m_toolbarItemRef = ref ;
+ if ( m_toolbarItemRef )
+ {
+ HIToolbarItemSetHelpText(
+ m_toolbarItemRef, wxMacCFStringHolder( GetShortHelp() , GetToolBar()->GetFont().GetEncoding() ) ,
+ wxMacCFStringHolder( GetLongHelp() , GetToolBar()->GetFont().GetEncoding() ) ) ;
+ }
+ }
+ HIToolbarItemRef GetToolbarItemRef() const
+ {
+ return m_toolbarItemRef ;
+ }
+
+ void SetIndex( CFIndex idx )
+ {
+ m_index = idx ;
+ }
+
+ CFIndex GetIndex() const
+ {
+ return m_index ;
+ }
+#endif
+
+private :
+ void Init()
+ {
+ m_controlHandle = NULL ;
+#if wxMAC_USE_NATIVE_TOOLBAR
+ m_toolbarItemRef = NULL ;
+ m_index = -1 ;
+#endif
+ }
+ ControlRef m_controlHandle ;
+#if wxMAC_USE_NATIVE_TOOLBAR
+ HIToolbarItemRef m_toolbarItemRef ;
+ // position in its toolbar, -1 means not inserted
+ CFIndex m_index ;
+#endif
+ wxCoord m_x;
+ wxCoord m_y;
+};
+
+static const EventTypeSpec eventList[] =
+{
+ { kEventClassControl , kEventControlHit } ,
+#ifdef __WXMAC_OSX__
+ { kEventClassControl , kEventControlHitTest } ,
+#endif
+} ;
+
+static pascal OSStatus wxMacToolBarToolControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
+{
+ OSStatus result = eventNotHandledErr ;
+
+ wxMacCarbonEvent cEvent( event ) ;
+
+ ControlRef controlRef ;
+
+ 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;
+#ifdef __WXMAC_OSX__
+ shouldToggle = !tbartool->IsToggled();
+#else
+ shouldToggle = ( GetControl32BitValue((ControlRef) tbartool->GetControlHandle()) != 0 );
+#endif
+ tbar->ToggleTool( tbartool->GetId(), shouldToggle );
+ }
+ if (tbartool != NULL)
+ tbar->OnLeftClick( tbartool->GetId(), tbartool->IsToggled() );
+ result = noErr;
+ }
+ break ;
+
+#ifdef __WXMAC_OSX__
+ case kEventControlHitTest :
+ {
+ HIPoint pt = cEvent.GetParameter<HIPoint>(kEventParamMouseLocation) ;
+ HIRect rect ;
+ HIViewGetBounds( controlRef , &rect ) ;
+
+ ControlPartCode pc = kControlNoPart ;
+ if ( CGRectContainsPoint( rect , pt ) )
+ pc = kControlIconPart ;
+ cEvent.SetParameter( kEventParamControlPart , typeControlPartCode, pc ) ;
+ result = noErr ;
+ }
+ break ;
+#endif
+
+ 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 wxMAC_USE_NATIVE_TOOLBAR
+
+//
+// native toolbar
+//
+
+static const EventTypeSpec toolBarEventList[] =
+{
+ { kEventClassToolbarItem , kEventToolbarItemPerformAction } ,
+} ;
+
+static pascal OSStatus wxMacToolBarCommandEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
+{
+ OSStatus result = eventNotHandledErr ;
+
+ switch( GetEventKind( event ) )
+ {
+ case kEventToolbarItemPerformAction :
+ {
+ wxToolBarTool* tbartool = (wxToolBarTool*) data ;
+ if ( tbartool != NULL )
+ {
+ int toolID = tbartool->GetId();
+ wxToolBar *tbar = ( wxToolBar * ) ( tbartool->GetToolBar() );
+ if ( tbartool->CanBeToggled() )
+ {
+ if ( tbar )
+ tbar->ToggleTool(toolID, !tbartool->IsToggled() );
+ }
+ if ( tbar )
+ 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
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxToolBarTool
+// ----------------------------------------------------------------------------
+
+bool wxToolBarTool::DoEnable(bool enable)
+{
+ if ( IsControl() )
+ {
+ GetControl()->Enable( enable ) ;
+ }
+ else if ( IsButton() )
+ {
+#if wxMAC_USE_NATIVE_TOOLBAR
+ if ( m_toolbarItemRef )
+ HIToolbarItemSetEnabled( m_toolbarItemRef , enable ) ;
+#endif
+
+ if ( m_controlHandle )
+ {
+#if TARGET_API_MAC_OSX
+ if ( enable )
+ EnableControl( m_controlHandle ) ;
+ else
+ DisableControl( m_controlHandle ) ;
+#else
+ if ( enable )
+ ActivateControl( m_controlHandle ) ;
+ else
+ DeactivateControl( m_controlHandle ) ;
+#endif
+ }
+ }
+ return true ;
+}
+
+void wxToolBarTool::SetPosition(const wxPoint& position)
+{
+ m_x = position.x;
+ m_y = position.y;
+
+ int x , y ;
+ x = y = 0 ;
+ int mac_x = position.x ;
+ int mac_y = position.y ;
+
+ if ( ! GetToolBar()->MacGetTopLevelWindow()->MacUsesCompositing() )
+ {
+ GetToolBar()->MacWindowToRootWindow( &x , &y ) ;
+ mac_x += x;
+ mac_y += 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 )
+ {
+ UMAMoveControl( m_controlHandle , mac_x , mac_y ) ;
+ }
+ }
+ else if ( IsControl() )
+ {
+ GetControl()->Move( position ) ;
+ }
+ else
+ {
+ // separator
+#ifdef __WXMAC_OSX__
+ 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 )
+ {
+ UMAMoveControl( m_controlHandle , mac_x , mac_y ) ;
+ }
+#endif
+ }
+}
+
+void wxToolBarTool::UpdateToggleImage( bool toggle )
+{
+#if wxMAC_USE_NATIVE_TOOLBAR
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
+#define kHIToolbarItemSelected (1 << 7)
+#endif
+
+ // FIXME: this should be a OSX v10.4 runtime check
+ if (m_toolbarItemRef != NULL)
+ {
+ OptionBits addAttrs, removeAttrs;
+ OSStatus result;
+
+ if (toggle)
+ {
+ addAttrs = kHIToolbarItemSelected;
+ removeAttrs = kHIToolbarItemNoAttributes;
+ }
+ else
+ {
+ addAttrs = kHIToolbarItemNoAttributes;
+ removeAttrs = kHIToolbarItemSelected;
+ }
+
+ result = HIToolbarItemChangeAttributes( m_toolbarItemRef, addAttrs, removeAttrs );
+ }