1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:     The wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  13 #pragma implementation "toolbar.h" 
  16 #include "wx/wxprec.h" 
  21 #include "wx/toolbar.h" 
  22 #include "wx/notebook.h" 
  23 #include "wx/tabctrl.h" 
  24 #include "wx/bitmap.h" 
  26 #if !USE_SHARED_LIBRARY 
  27 IMPLEMENT_DYNAMIC_CLASS(wxToolBar
, wxControl
) 
  29 BEGIN_EVENT_TABLE(wxToolBar
, wxToolBarBase
) 
  30     EVT_PAINT( wxToolBar::OnPaint 
)  
  34 #include "wx/mac/uma.h" 
  35 #include "wx/geometry.h" 
  38 const short kwxMacToolBarToolDefaultWidth 
= 24 ; 
  39 const short kwxMacToolBarToolDefaultHeight 
= 24 ; 
  40 const short kwxMacToolBarTopMargin 
= 4 ; 
  41 const short kwxMacToolBarLeftMargin 
= 4 ; 
  42 const short kwxMacToolBorder 
= 0 ; 
  43 const short kwxMacToolSpacing 
= 6 ; 
  45 const short kwxMacToolBarToolDefaultWidth 
= 24 ; 
  46 const short kwxMacToolBarToolDefaultHeight 
= 22 ; 
  47 const short kwxMacToolBarTopMargin 
= 2 ; 
  48 const short kwxMacToolBarLeftMargin 
= 2 ; 
  49 const short kwxMacToolBorder 
= 4 ; 
  50 const short kwxMacToolSpacing 
= 0 ; 
  53 // ---------------------------------------------------------------------------- 
  55 // ---------------------------------------------------------------------------- 
  57 class wxToolBarTool 
: public wxToolBarToolBase
 
  60     wxToolBarTool(wxToolBar 
*tbar
, 
  62                   const wxString
& label
, 
  63                   const wxBitmap
& bmpNormal
, 
  64                   const wxBitmap
& bmpDisabled
, 
  67                   const wxString
& shortHelp
, 
  68                   const wxString
& longHelp
) ; 
  70     wxToolBarTool(wxToolBar 
*tbar
, wxControl 
*control
) 
  71         : wxToolBarToolBase(tbar
, control
) 
  78         if ( m_controlHandle 
) 
  79             DisposeControl( m_controlHandle 
) ; 
  82     WXWidget 
GetControlHandle() { return (WXWidget
) m_controlHandle 
; } 
  83     void SetControlHandle( ControlRef handle 
) { m_controlHandle 
= handle 
; } 
  85     void SetSize(const wxSize
& size
) ; 
  86     void SetPosition( const wxPoint
& position 
) ; 
  88     wxSize 
GetSize() const 
  92             return GetControl()->GetSize() ; 
  94         else if ( IsButton() ) 
  96             return GetToolBar()->GetToolSize() ; 
 101             wxSize sz 
= GetToolBar()->GetToolSize() ; 
 107     wxPoint 
GetPosition() const 
 109         return wxPoint(m_x
, m_y
); 
 111     bool DoEnable( bool enable 
) ; 
 113     void UpdateToggleImage( bool toggle 
) ; 
 117         m_controlHandle 
= NULL 
; 
 119     ControlRef m_controlHandle 
; 
 125 static const EventTypeSpec eventList
[] = 
 127         { kEventClassControl 
, kEventControlHit 
} , 
 129         { kEventClassControl 
, kEventControlHitTest 
} , 
 133 static pascal OSStatus 
wxMacToolBarToolControlEventHandler( EventHandlerCallRef handler 
, EventRef event 
, void *data 
) 
 135     OSStatus result 
= eventNotHandledErr 
; 
 137     wxMacCarbonEvent 
cEvent( event 
) ; 
 139     ControlRef controlRef 
; 
 141     cEvent
.GetParameter( kEventParamDirectObject 
, &controlRef 
) ; 
 143     switch( GetEventKind( event 
) ) 
 145         case kEventControlHit 
: 
 147                 wxToolBarTool
* tbartool 
= (wxToolBarTool
*)data 
; 
 148                 if ( tbartool
->CanBeToggled() ) 
 150                     ((wxToolBar
*)tbartool
->GetToolBar())->ToggleTool(tbartool
->GetId(), GetControl32BitValue((ControlRef
)tbartool
->GetControlHandle())); 
 152                 ((wxToolBar
*)tbartool
->GetToolBar())->OnLeftClick( tbartool
->GetId() , tbartool 
-> IsToggled() ) ; 
 157         case kEventControlHitTest 
: 
 159                 HIPoint pt 
= cEvent
.GetParameter
<HIPoint
>(kEventParamMouseLocation
) ; 
 161                 HIViewGetBounds( controlRef 
, &rect 
) ; 
 163                 ControlPartCode pc 
= kControlNoPart 
; 
 164                 if ( CGRectContainsPoint( rect 
, pt 
) ) 
 165                     pc 
= kControlButtonPart 
; 
 166                 cEvent
.SetParameter( kEventParamControlPart 
, typeControlPartCode
, pc 
) ; 
 177 pascal OSStatus 
wxMacToolBarToolEventHandler( EventHandlerCallRef handler 
, EventRef event 
, void *data 
) 
 179     OSStatus result 
= eventNotHandledErr 
; 
 181     switch ( GetEventClass( event 
) ) 
 183         case kEventClassControl 
: 
 184             result 
= wxMacToolBarToolControlEventHandler( handler
, event
, data 
) ; 
 192 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacToolBarToolEventHandler 
) 
 194 // ============================================================================ 
 196 // ============================================================================ 
 198 // ---------------------------------------------------------------------------- 
 200 // ---------------------------------------------------------------------------- 
 202 bool wxToolBarTool::DoEnable(bool enable
) 
 206         GetControl()->Enable( enable 
) ; 
 208     else if ( IsButton() ) 
 210 #if TARGET_API_MAC_OSX 
 212             EnableControl( m_controlHandle 
) ; 
 214             DisableControl( m_controlHandle 
) ; 
 217             ActivateControl( m_controlHandle 
) ; 
 219             DeactivateControl( m_controlHandle 
) ; 
 224 void wxToolBarTool::SetSize(const wxSize
& size
) 
 228         GetControl()->SetSize( size 
) ; 
 232 void wxToolBarTool::SetPosition(const wxPoint
& position
) 
 241         int mac_x 
= position
.x 
; 
 242         int mac_y 
= position
.y 
; 
 244         // already correctly set up 
 246         WindowRef rootwindow 
= (WindowRef
) GetToolBar()->MacGetTopLevelWindowRef() ;     
 247         GetToolBar()->MacWindowToRootWindow( &x 
, &y 
) ; 
 252         GetControlBounds( m_controlHandle 
, &contrlRect 
) ;  
 253         int former_mac_x 
= contrlRect
.left 
; 
 254         int former_mac_y 
= contrlRect
.top 
; 
 255         GetToolBar()->GetToolSize() ; 
 257         if ( mac_x 
!= former_mac_x 
|| mac_y 
!= former_mac_y 
) 
 259             UMAMoveControl( m_controlHandle 
, mac_x 
, mac_y 
) ; 
 262     else if ( IsControl() ) 
 264         GetControl()->Move( position 
) ; 
 272         int mac_x 
= position
.x 
; 
 273         int mac_y 
= position
.y 
; 
 276         GetControlBounds( m_controlHandle 
, &contrlRect 
) ;  
 277         int former_mac_x 
= contrlRect
.left 
; 
 278         int former_mac_y 
= contrlRect
.top 
; 
 280         if ( mac_x 
!= former_mac_x 
|| mac_y 
!= former_mac_y 
) 
 282             UMAMoveControl( m_controlHandle 
, mac_x 
, mac_y 
) ; 
 288 void wxToolBarTool::UpdateToggleImage( bool toggle 
)  
 293         int w 
= m_bmpNormal
.GetWidth() ; 
 294         int h 
= m_bmpNormal
.GetHeight() ; 
 295         wxBitmap 
bmp( w 
, h 
) ; 
 297         dc
.SelectObject( bmp 
) ; 
 298         dc
.SetPen( wxNullPen 
) ; 
 299         dc
.SetBackground( *wxWHITE 
) ; 
 300         dc
.DrawRectangle( 0 , 0 , w 
, h 
) ; 
 301         dc
.DrawBitmap( m_bmpNormal 
, 0 , 0 , true) ; 
 302         dc
.SelectObject( wxNullBitmap 
) ; 
 303         ControlButtonContentInfo info 
; 
 304         wxMacCreateBitmapButton( &info 
, bmp 
) ; 
 305         SetControlData( m_controlHandle 
, 0, kControlIconContentTag
, sizeof( info 
), 
 307         wxMacReleaseBitmapButton( &info 
) ; 
 311         ControlButtonContentInfo info 
; 
 312         wxMacCreateBitmapButton( &info 
, m_bmpNormal 
) ; 
 313         SetControlData( m_controlHandle 
, 0, kControlIconContentTag
, sizeof( info 
), 
 315         wxMacReleaseBitmapButton( &info 
) ; 
 318     IconTransformType transform 
= toggle 
? kTransformSelected 
: kTransformNone 
; 
 319         SetControlData( m_controlHandle
, 0, kControlIconTransformTag
, sizeof( transform 
), 
 321     HIViewSetNeedsDisplay( m_controlHandle 
, true ) ; 
 324     ::SetControl32BitValue( m_controlHandle 
, toggle 
) ; 
 328 wxToolBarTool::wxToolBarTool(wxToolBar 
*tbar
, 
 330   const wxString
& label
, 
 331   const wxBitmap
& bmpNormal
, 
 332   const wxBitmap
& bmpDisabled
, 
 334   wxObject 
*clientData
, 
 335   const wxString
& shortHelp
, 
 336   const wxString
& longHelp
) 
 337         : wxToolBarToolBase(tbar
, id
, label
, bmpNormal
, bmpDisabled
, kind
, 
 338                             clientData
, shortHelp
, longHelp
) 
 342     WindowRef window 
= (WindowRef
) tbar
->MacGetTopLevelWindowRef() ;     
 343     wxSize toolSize 
= tbar
->GetToolSize() ;     
 344     Rect toolrect 
= { 0, 0 , toolSize
.y 
, toolSize
.x 
} ; 
 346     if ( id 
== wxID_SEPARATOR 
) 
 350         if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL 
) 
 352             toolrect
.bottom 
= toolSize
.y 
; 
 356             toolrect
.right 
= toolSize
.x 
; 
 359         // in flat style we need a visual separator 
 360         CreateSeparatorControl( window 
, &toolrect 
, &m_controlHandle 
) ; 
 365         ControlButtonContentInfo info 
; 
 366         wxMacCreateBitmapButton( &info 
, GetNormalBitmap() ) ; 
 369         CreateIconControl( window 
, &toolrect 
, &info 
, false , &m_controlHandle 
) ; 
 371         SInt16 behaviour 
= kControlBehaviorOffsetContents 
; 
 372         if ( CanBeToggled() ) 
 373             behaviour 
+= kControlBehaviorToggles 
; 
 374         CreateBevelButtonControl( window 
, &toolrect 
, CFSTR("") , kControlBevelButtonNormalBevel 
, behaviour 
, &info 
,  
 375             0 , 0 , 0 , &m_controlHandle 
) ; 
 378         wxMacReleaseBitmapButton( &info 
) ; 
 380         SetBevelButtonTextPlacement( m_controlHandle , kControlBevelButtonPlaceBelowGraphic ) ; 
 381         UMASetControlTitle(  m_controlHandle , label , wxFont::GetDefaultEncoding() ) ; 
 384         InstallControlEventHandler( (ControlRef
) m_controlHandle
, GetwxMacToolBarToolEventHandlerUPP(), 
 385             GetEventTypeCount(eventList
), eventList
, this,NULL
);           
 388     ControlRef container 
= (ControlRef
) tbar
->GetHandle() ; 
 389     wxASSERT_MSG( container 
!= NULL 
, wxT("No valid mac container control") ) ; 
 390     if ( m_controlHandle 
) 
 392         UMAShowControl( m_controlHandle 
) ; 
 393         ::EmbedControl( m_controlHandle 
, container 
) ; 
 395     if ( CanBeToggled() && IsToggled() ) 
 397         UpdateToggleImage( true ) ; 
 402 wxToolBarToolBase 
*wxToolBar::CreateTool(int id
, 
 403                                          const wxString
& label
, 
 404                                          const wxBitmap
& bmpNormal
, 
 405                                          const wxBitmap
& bmpDisabled
, 
 407                                          wxObject 
*clientData
, 
 408                                          const wxString
& shortHelp
, 
 409                                          const wxString
& longHelp
) 
 411     return new wxToolBarTool(this, id
, label
, bmpNormal
, bmpDisabled
, kind
, 
 412                              clientData
, shortHelp
, longHelp
); 
 415 wxToolBarToolBase 
*wxToolBar::CreateTool(wxControl 
*control
) 
 417     return new wxToolBarTool(this, control
); 
 420 void wxToolBar::Init() 
 424     m_defaultWidth 
= kwxMacToolBarToolDefaultWidth
; 
 425     m_defaultHeight 
= kwxMacToolBarToolDefaultHeight
; 
 428 bool wxToolBar::Create(wxWindow 
*parent
, wxWindowID id
, const wxPoint
& pos
, const wxSize
& size
, 
 429             long style
, const wxString
& name
) 
 432     if ( !wxToolBarBase::Create( parent 
, id 
, pos 
, size 
, style 
) ) 
 438 wxToolBar::~wxToolBar() 
 440     // we must refresh the frame size when the toolbar is deleted but the frame 
 441     // is not - otherwise toolbar leaves a hole in the place it used to occupy 
 444 bool wxToolBar::Realize() 
 446     if (m_tools
.GetCount() == 0) 
 449     int x 
= m_xMargin 
+ kwxMacToolBarLeftMargin 
; 
 450     int y 
= m_yMargin 
+ kwxMacToolBarTopMargin 
; 
 458     int maxToolWidth 
= 0; 
 459     int maxToolHeight 
= 0; 
 461     // Find the maximum tool width and height 
 462     wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 465         wxToolBarTool 
*tool 
= (wxToolBarTool 
*)node
->GetData(); 
 466         wxSize sz 
= tool
->GetSize() ; 
 468         if ( sz
.x 
> maxToolWidth 
) 
 469             maxToolWidth 
= sz
.x 
; 
 470         if (sz
.y
> maxToolHeight
) 
 471             maxToolHeight 
= sz
.y
; 
 473         node 
= node
->GetNext(); 
 476     bool lastWasRadio 
= FALSE
; 
 477     node 
= m_tools
.GetFirst(); 
 480         wxToolBarTool 
*tool 
= (wxToolBarTool 
*)node
->GetData(); 
 481         wxSize cursize 
= tool
->GetSize() ; 
 483         bool isRadio 
= FALSE
; 
 485         if ( tool
->IsButton() && tool
->GetKind() == wxITEM_RADIO 
) 
 489                 if (tool
->Toggle(true)) 
 491                     DoToggleTool(tool
, true); 
 500         lastWasRadio 
= isRadio
; 
 502         // for the moment we just do a single row/column alignement 
 503         if ( x 
+ cursize
.x 
> maxWidth 
) 
 504             maxWidth 
= x 
+ cursize
.x 
; 
 505         if ( y 
+ cursize
.y 
> maxHeight 
) 
 506             maxHeight 
= y 
+ cursize
.y 
; 
 508         if ( GetWindowStyleFlag() & wxTB_VERTICAL 
) 
 510             int x1 
= x 
+ (maxToolWidth 
- cursize
.x
)/2 ; 
 511             tool
->SetPosition( wxPoint( x1 
, y 
) ) ; 
 515             int y1 
= y 
+ (maxToolHeight 
- cursize
.y
)/2 ; 
 516             tool
->SetPosition( wxPoint( x 
, y1 
) ) ; 
 518         if ( GetWindowStyleFlag() & wxTB_VERTICAL 
) 
 521             y 
+= kwxMacToolSpacing 
; 
 526             x 
+= kwxMacToolSpacing 
; 
 529         node 
= node
->GetNext(); 
 532     if ( GetWindowStyleFlag() & wxTB_HORIZONTAL 
) 
 534         if ( m_maxRows 
== 0 ) 
 536             // if not set yet, only one row 
 539         m_minWidth 
= maxWidth
; 
 541         maxHeight 
+= m_yMargin 
+ kwxMacToolBarTopMargin
; 
 542         m_minHeight 
= m_maxHeight 
= maxHeight 
; 
 546         if ( GetToolsCount() > 0 && m_maxRows 
== 0 ) 
 548             // if not set yet, have one column 
 549             SetRows(GetToolsCount()); 
 551         m_minHeight 
= maxHeight
; 
 553         maxWidth 
+= m_xMargin 
+ kwxMacToolBarLeftMargin
; 
 554         m_minWidth 
= m_maxWidth 
= maxWidth 
; 
 557     SetSize( maxWidth
, maxHeight 
); 
 558     InvalidateBestSize(); 
 563 void wxToolBar::SetToolBitmapSize(const wxSize
& size
) 
 565     m_defaultWidth 
= size
.x
+kwxMacToolBorder
; m_defaultHeight 
= size
.y
+kwxMacToolBorder
; 
 568 // The button size is bigger than the bitmap size 
 569 wxSize 
wxToolBar::GetToolSize() const 
 571     return wxSize(m_defaultWidth 
+ kwxMacToolBorder
, m_defaultHeight 
+ kwxMacToolBorder
); 
 574 void wxToolBar::SetRows(int nRows
) 
 576     if ( nRows 
== m_maxRows 
) 
 578         // avoid resizing the frame uselessly 
 585 void wxToolBar::MacSuperChangedPosition()  
 587     wxWindow::MacSuperChangedPosition() ; 
 591 wxToolBarToolBase 
*wxToolBar::FindToolForPosition(wxCoord x
, wxCoord y
) const 
 593     wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 596         wxToolBarTool 
*tool 
= (wxToolBarTool 
*)node
->GetData() ; 
 597         wxRect2DInt 
r( tool
->GetPosition() , tool
->GetSize() ) ; 
 598         if ( r
.Contains( wxPoint( x 
, y 
) ) ) 
 603         node 
= node
->GetNext(); 
 606     return (wxToolBarToolBase 
*)NULL
; 
 609 wxString 
wxToolBar::MacGetToolTipString( wxPoint 
&pt 
) 
 611     wxToolBarToolBase
* tool 
= FindToolForPosition( pt
.x 
, pt
.y 
) ; 
 614         return tool
->GetShortHelp() ; 
 616     return wxEmptyString 
; 
 619 void wxToolBar::DoEnableTool(wxToolBarToolBase 
*t
, bool enable
) 
 621     ((wxToolBarTool
*)t
)->DoEnable( enable 
) ; 
 624 void wxToolBar::DoToggleTool(wxToolBarToolBase 
*t
, bool toggle
) 
 626     wxToolBarTool 
*tool 
= (wxToolBarTool 
*)t
; 
 627     if ( tool
->IsButton() ) 
 629         tool
->UpdateToggleImage( toggle 
) ; 
 633 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos
), 
 634                              wxToolBarToolBase 
*tool
) 
 636     // nothing special to do here - we relayout in Realize() later 
 638     InvalidateBestSize(); 
 643 void wxToolBar::DoSetToggle(wxToolBarToolBase 
*WXUNUSED(tool
), bool WXUNUSED(toggle
)) 
 645     wxFAIL_MSG( _T("not implemented") ); 
 648 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos
), wxToolBarToolBase 
*tool
) 
 650     wxToolBarToolsList::compatibility_iterator node
; 
 651     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 653         wxToolBarToolBase 
*tool2 
= node
->GetData(); 
 656             // let node point to the next node in the list 
 657             node 
= node
->GetNext(); 
 663     wxSize sz 
= ((wxToolBarTool
*)tool
)->GetSize() ; 
 667     // and finally reposition all the controls after this one 
 669     for ( /* node -> first after deleted */ ; node
; node 
= node
->GetNext() ) 
 671         wxToolBarTool 
*tool2 
= (wxToolBarTool
*) node
->GetData(); 
 672         wxPoint pt 
= tool2
->GetPosition() ; 
 674         if ( GetWindowStyleFlag() & wxTB_VERTICAL 
) 
 682         tool2
->SetPosition( pt 
) ; 
 685     InvalidateBestSize(); 
 689 void wxToolBar::OnPaint(wxPaintEvent
& event
) 
 692 #if wxMAC_USE_CORE_GRAPHICS 
 693     // leave the background as it is (striped or metal) 
 695     wxMacPortSetter 
helper(&dc
) ; 
 699     Rect toolbarrect 
= { dc
.YLOG2DEVMAC(0) , dc
.XLOG2DEVMAC(0) ,  
 700         dc
.YLOG2DEVMAC(h
) , dc
.XLOG2DEVMAC(w
) } ; 
 702     if( toolbarrect.left < 0 ) 
 703         toolbarrect.left = 0 ; 
 704     if ( toolbarrect.top < 0 ) 
 705         toolbarrect.top = 0 ; 
 707     if ( !MacGetTopLevelWindow()->MacGetMetalAppearance() ) 
 709         UMADrawThemePlacard( &toolbarrect 
, IsEnabled() ? kThemeStateActive 
: kThemeStateInactive
) ; 
 713 #if TARGET_API_MAC_OSX 
 714 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 
 715         if ( UMAGetSystemVersion() >= 0x1030 ) 
 717             HIRect hiToolbarrect 
= CGRectMake( dc
.YLOG2DEVMAC(0) , dc
.XLOG2DEVMAC(0) ,  
 718             dc
.YLOG2DEVREL(h
) , dc
.XLOG2DEVREL(w
) ); 
 719             CGContextRef cgContext 
; 
 721             GetPortBounds( (CGrafPtr
) dc
.m_macPort 
, &bounds 
) ; 
 722             QDBeginCGContext( (CGrafPtr
) dc
.m_macPort 
, &cgContext 
) ; 
 723             CGContextTranslateCTM( cgContext 
, 0 , bounds
.bottom 
- bounds
.top 
) ; 
 724             CGContextScaleCTM( cgContext 
, 1 , -1 ) ; 
 727                 HIThemeBackgroundDrawInfo drawInfo 
; 
 728                 drawInfo
.version 
= 0 ; 
 729                 drawInfo
.state 
= kThemeStateActive 
; 
 730                 drawInfo
.kind 
= kThemeBackgroundMetal 
; 
 731                 HIThemeApplyBackground( &hiToolbarrect
, &drawInfo 
, cgContext
,kHIThemeOrientationNormal
) ; 
 733             QDEndCGContext( (CGrafPtr
) dc
.m_macPort 
, &cgContext 
) ; 
 738             UMADrawThemePlacard( &toolbarrect 
, IsEnabled() ? kThemeStateActive 
: kThemeStateInactive
) ; 
 747 #endif // wxUSE_TOOLBAR