]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/toolbar.cpp
Fixed uninstalled toolbars in native toolbar mode, with a method for
[wxWidgets.git] / src / mac / carbon / toolbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/toolbar.cpp
3 // Purpose: wxToolBar
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #if wxUSE_TOOLBAR
15
16 #include "wx/toolbar.h"
17
18 #ifndef WX_PRECOMP
19 #include "wx/wx.h"
20 #endif
21
22 #include "wx/app.h"
23 #include "wx/mac/uma.h"
24 #include "wx/geometry.h"
25 #include "wx/sysopt.h"
26
27
28 #ifdef __WXMAC_OSX__
29 const short kwxMacToolBarToolDefaultWidth = 16;
30 const short kwxMacToolBarToolDefaultHeight = 16;
31 const short kwxMacToolBarTopMargin = 4;
32 const short kwxMacToolBarLeftMargin = 4;
33 const short kwxMacToolBorder = 0;
34 const short kwxMacToolSpacing = 6;
35 #else
36 const short kwxMacToolBarToolDefaultWidth = 24;
37 const short kwxMacToolBarToolDefaultHeight = 22;
38 const short kwxMacToolBarTopMargin = 2;
39 const short kwxMacToolBarLeftMargin = 2;
40 const short kwxMacToolBorder = 4;
41 const short kwxMacToolSpacing = 0;
42 #endif
43
44
45 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
46
47 BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
48 EVT_PAINT( wxToolBar::OnPaint )
49 END_EVENT_TABLE()
50
51
52 #pragma mark -
53 #pragma mark Tool Implementation
54
55
56 // ----------------------------------------------------------------------------
57 // private classes
58 // ----------------------------------------------------------------------------
59
60 // We have a dual implementation for each tool, ControlRef and HIToolbarItemRef
61
62 // when embedding native controls in the native toolbar we must make sure the
63 // control does not get deleted behind our backs, so the retain count gets increased
64 // (after creation it is 1), first be the creation of the custom HIToolbarItem wrapper
65 // object, and second by the code 'creating' the custom HIView (which is the same as the
66 // already existing native control, therefore we just increase the ref count)
67 // when this view is removed from the native toolbar its count gets decremented again
68 // and when the HITooolbarItem wrapper object gets destroyed it is decremented as well
69 // so in the end the control lives with a refcount of one and can be disposed of by the
70 // wxControl code. For embedded controls on a non-native toolbar this ref count is less
71 // so we can only test against a range, not a specific value of the refcount.
72
73 class wxToolBarTool : public wxToolBarToolBase
74 {
75 public:
76 wxToolBarTool(
77 wxToolBar *tbar,
78 int id,
79 const wxString& label,
80 const wxBitmap& bmpNormal,
81 const wxBitmap& bmpDisabled,
82 wxItemKind kind,
83 wxObject *clientData,
84 const wxString& shortHelp,
85 const wxString& longHelp );
86
87 wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
88 : wxToolBarToolBase(tbar, control, label)
89 {
90 Init();
91 if (control != NULL)
92 SetControlHandle( (ControlRef) control->GetHandle() );
93 }
94
95 virtual ~wxToolBarTool()
96 {
97 ClearControl();
98 }
99
100 WXWidget GetControlHandle()
101 {
102 return (WXWidget) m_controlHandle;
103 }
104
105 void SetControlHandle( ControlRef handle )
106 {
107 m_controlHandle = handle;
108 }
109
110 void SetPosition( const wxPoint& position );
111
112 void ClearControl()
113 {
114 if ( m_controlHandle )
115 {
116 if ( !IsControl() )
117 DisposeControl( m_controlHandle );
118 else
119 {
120 // the embedded control is not under the responsibility of the tool, it will be disposed of in the
121 // proper wxControl destructor
122 wxASSERT( IsValidControlHandle(GetControl()->GetPeer()->GetControlRef() )) ;
123 }
124 m_controlHandle = NULL ;
125 }
126 m_control = NULL;
127
128 #if wxMAC_USE_NATIVE_TOOLBAR
129 if ( m_toolbarItemRef )
130 {
131 CFIndex count = CFGetRetainCount( m_toolbarItemRef ) ;
132 wxASSERT_MSG( count == 1 , wxT("Reference Count of native tool was not 1 in wxToolBarTool destructor") );
133 wxTheApp->MacAddToAutorelease(m_toolbarItemRef);
134 CFRelease(m_toolbarItemRef);
135 m_toolbarItemRef = NULL;
136 }
137 #endif
138 }
139
140 wxSize GetSize() const
141 {
142 wxSize curSize;
143
144 if ( IsControl() )
145 {
146 curSize = GetControl()->GetSize();
147 }
148 else if ( IsButton() )
149 {
150 curSize = GetToolBar()->GetToolSize();
151 }
152 else
153 {
154 // separator size
155 curSize = GetToolBar()->GetToolSize();
156 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
157 curSize.y /= 4;
158 else
159 curSize.x /= 4;
160 }
161
162 return curSize;
163 }
164
165 wxPoint GetPosition() const
166 {
167 return wxPoint( m_x, m_y );
168 }
169
170 bool DoEnable( bool enable );
171
172 void UpdateToggleImage( bool toggle );
173
174 #if wxMAC_USE_NATIVE_TOOLBAR
175 void SetToolbarItemRef( HIToolbarItemRef ref )
176 {
177 if ( m_controlHandle )
178 HideControl( m_controlHandle );
179 if ( m_toolbarItemRef )
180 CFRelease( m_toolbarItemRef );
181
182 m_toolbarItemRef = ref;
183 if ( m_toolbarItemRef )
184 {
185 wxFont f;
186 wxFontEncoding enc;
187 if ( GetToolBar() )
188 f = GetToolBar()->GetFont();
189 if ( f.IsOk() )
190 enc = f.GetEncoding();
191 else
192 enc = wxFont::GetDefaultEncoding();
193
194 HIToolbarItemSetHelpText(
195 m_toolbarItemRef,
196 wxMacCFStringHolder( GetShortHelp(), enc ),
197 wxMacCFStringHolder( GetLongHelp(), enc ) );
198 }
199 }
200
201 HIToolbarItemRef GetToolbarItemRef() const
202 {
203 return m_toolbarItemRef;
204 }
205
206 void SetIndex( CFIndex idx )
207 {
208 m_index = idx;
209 }
210
211 CFIndex GetIndex() const
212 {
213 return m_index;
214 }
215 #endif
216
217 private:
218 void Init()
219 {
220 m_controlHandle = NULL;
221
222 #if wxMAC_USE_NATIVE_TOOLBAR
223 m_toolbarItemRef = NULL;
224 m_index = -1;
225 #endif
226 }
227
228 ControlRef m_controlHandle;
229 wxCoord m_x;
230 wxCoord m_y;
231
232 #if wxMAC_USE_NATIVE_TOOLBAR
233 HIToolbarItemRef m_toolbarItemRef;
234 // position in its toolbar, -1 means not inserted
235 CFIndex m_index;
236 #endif
237 };
238
239 static const EventTypeSpec eventList[] =
240 {
241 { kEventClassControl, kEventControlHit },
242 #ifdef __WXMAC_OSX__
243 { kEventClassControl, kEventControlHitTest },
244 #endif
245 };
246
247 static pascal OSStatus wxMacToolBarToolControlEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
248 {
249 OSStatus result = eventNotHandledErr;
250 ControlRef controlRef;
251 wxMacCarbonEvent cEvent( event );
252
253 cEvent.GetParameter( kEventParamDirectObject, &controlRef );
254
255 switch ( GetEventKind( event ) )
256 {
257 case kEventControlHit:
258 {
259 wxToolBarTool *tbartool = (wxToolBarTool*)data;
260 wxToolBar *tbar = tbartool != NULL ? (wxToolBar*) (tbartool->GetToolBar()) : NULL;
261 if ((tbartool != NULL) && tbartool->CanBeToggled())
262 {
263 bool shouldToggle;
264
265 #ifdef __WXMAC_OSX__
266 shouldToggle = !tbartool->IsToggled();
267 #else
268 shouldToggle = (GetControl32BitValue( (ControlRef)(tbartool->GetControlHandle()) ) != 0);
269 #endif
270
271 tbar->ToggleTool( tbartool->GetId(), shouldToggle );
272 }
273
274 if (tbartool != NULL)
275 tbar->OnLeftClick( tbartool->GetId(), tbartool->IsToggled() );
276 result = noErr;
277 }
278 break;
279
280 #ifdef __WXMAC_OSX__
281 case kEventControlHitTest:
282 {
283 HIPoint pt = cEvent.GetParameter<HIPoint>(kEventParamMouseLocation);
284 HIRect rect;
285 HIViewGetBounds( controlRef, &rect );
286
287 ControlPartCode pc = kControlNoPart;
288 if ( CGRectContainsPoint( rect, pt ) )
289 pc = kControlIconPart;
290 cEvent.SetParameter( kEventParamControlPart, typeControlPartCode, pc );
291 result = noErr;
292 }
293 break;
294 #endif
295
296 default:
297 break;
298 }
299
300 return result;
301 }
302
303 static pascal OSStatus wxMacToolBarToolEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
304 {
305 OSStatus result = eventNotHandledErr;
306
307 switch ( GetEventClass( event ) )
308 {
309 case kEventClassControl:
310 result = wxMacToolBarToolControlEventHandler( handler, event, data );
311 break;
312
313 default:
314 break;
315 }
316
317 return result;
318 }
319
320 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacToolBarToolEventHandler )
321
322 #if wxMAC_USE_NATIVE_TOOLBAR
323
324 static const EventTypeSpec toolBarEventList[] =
325 {
326 { kEventClassToolbarItem, kEventToolbarItemPerformAction },
327 };
328
329 static pascal OSStatus wxMacToolBarCommandEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
330 {
331 OSStatus result = eventNotHandledErr;
332
333 switch ( GetEventKind( event ) )
334 {
335 case kEventToolbarItemPerformAction:
336 {
337 wxToolBarTool* tbartool = (wxToolBarTool*) data;
338 if ( tbartool != NULL )
339 {
340 wxToolBar *tbar = (wxToolBar*)(tbartool->GetToolBar());
341 int toolID = tbartool->GetId();
342
343 if ( tbartool->CanBeToggled() )
344 {
345 if ( tbar != NULL )
346 tbar->ToggleTool(toolID, !tbartool->IsToggled() );
347 }
348
349 if ( tbar != NULL )
350 tbar->OnLeftClick( toolID, tbartool->IsToggled() );
351 result = noErr;
352 }
353 }
354 break;
355
356 default:
357 break;
358 }
359
360 return result;
361 }
362
363 static pascal OSStatus wxMacToolBarEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
364 {
365 OSStatus result = eventNotHandledErr;
366
367 switch ( GetEventClass( event ) )
368 {
369 case kEventClassToolbarItem:
370 result = wxMacToolBarCommandEventHandler( handler, event, data );
371 break;
372
373 default:
374 break;
375 }
376
377 return result;
378 }
379
380 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacToolBarEventHandler )
381
382 #endif
383
384 bool wxToolBarTool::DoEnable( bool enable )
385 {
386 if ( IsControl() )
387 {
388 GetControl()->Enable( enable );
389 }
390 else if ( IsButton() )
391 {
392 #if wxMAC_USE_NATIVE_TOOLBAR
393 if ( m_toolbarItemRef != NULL )
394 HIToolbarItemSetEnabled( m_toolbarItemRef, enable );
395 #endif
396
397 if ( m_controlHandle != NULL )
398 {
399 #if TARGET_API_MAC_OSX
400 if ( enable )
401 EnableControl( m_controlHandle );
402 else
403 DisableControl( m_controlHandle );
404 #else
405 if ( enable )
406 ActivateControl( m_controlHandle );
407 else
408 DeactivateControl( m_controlHandle );
409 #endif
410 }
411 }
412
413 return true;
414 }
415
416 void wxToolBarTool::SetPosition( const wxPoint& position )
417 {
418 m_x = position.x;
419 m_y = position.y;
420
421 int mac_x = position.x;
422 int mac_y = position.y;
423
424 if ( IsButton() )
425 {
426 Rect contrlRect;
427 GetControlBounds( m_controlHandle, &contrlRect );
428 int former_mac_x = contrlRect.left;
429 int former_mac_y = contrlRect.top;
430 GetToolBar()->GetToolSize();
431
432 if ( mac_x != former_mac_x || mac_y != former_mac_y )
433 {
434 UMAMoveControl( m_controlHandle, mac_x, mac_y );
435 }
436 }
437 else if ( IsControl() )
438 {
439 // embedded native controls are moved by the OS
440 #if wxMAC_USE_NATIVE_TOOLBAR
441 if ( ((wxToolBar*)GetToolBar())->MacWantsNativeToolbar() == false )
442 #endif
443 {
444 GetControl()->Move( position );
445 }
446 }
447 else
448 {
449 // separator
450 #ifdef __WXMAC_OSX__
451 Rect contrlRect;
452 GetControlBounds( m_controlHandle, &contrlRect );
453 int former_mac_x = contrlRect.left;
454 int former_mac_y = contrlRect.top;
455
456 if ( mac_x != former_mac_x || mac_y != former_mac_y )
457 UMAMoveControl( m_controlHandle, mac_x, mac_y );
458 #endif
459 }
460 }
461
462 void wxToolBarTool::UpdateToggleImage( bool toggle )
463 {
464 #ifdef __WXMAC_OSX__
465 if ( toggle )
466 {
467 int w = m_bmpNormal.GetWidth();
468 int h = m_bmpNormal.GetHeight();
469 wxBitmap bmp( w, h );
470 wxMemoryDC dc;
471
472 dc.SelectObject( bmp );
473 dc.SetPen( wxPen(*wxBLACK) );
474 dc.SetBrush( wxBrush( *wxLIGHT_GREY ));
475 dc.DrawRectangle( 0, 0, w, h );
476 dc.DrawBitmap( m_bmpNormal, 0, 0, true );
477 dc.SelectObject( wxNullBitmap );
478 ControlButtonContentInfo info;
479 wxMacCreateBitmapButton( &info, bmp, kControlContentIconRef );
480 SetControlData( m_controlHandle, 0, kControlIconContentTag, sizeof(info), (Ptr)&info );
481 #if wxMAC_USE_NATIVE_TOOLBAR
482 if (m_toolbarItemRef != NULL)
483 {
484 HIToolbarItemSetIconRef( m_toolbarItemRef, info.u.iconRef );
485 }
486 #endif
487 wxMacReleaseBitmapButton( &info );
488 }
489 else
490 {
491 ControlButtonContentInfo info;
492 wxMacCreateBitmapButton( &info, m_bmpNormal, kControlContentIconRef );
493 SetControlData( m_controlHandle, 0, kControlIconContentTag, sizeof(info), (Ptr)&info );
494 #if wxMAC_USE_NATIVE_TOOLBAR
495 if (m_toolbarItemRef != NULL)
496 {
497 HIToolbarItemSetIconRef( m_toolbarItemRef, info.u.iconRef );
498 }
499 #endif
500 wxMacReleaseBitmapButton( &info );
501 }
502
503 IconTransformType transform = toggle ? kTransformSelected : kTransformNone;
504 SetControlData(
505 m_controlHandle, 0, kControlIconTransformTag,
506 sizeof(transform), (Ptr)&transform );
507 HIViewSetNeedsDisplay( m_controlHandle, true );
508
509 #else
510 ::SetControl32BitValue( m_controlHandle, toggle );
511 #endif
512 }
513
514 wxToolBarTool::wxToolBarTool(
515 wxToolBar *tbar,
516 int id,
517 const wxString& label,
518 const wxBitmap& bmpNormal,
519 const wxBitmap& bmpDisabled,
520 wxItemKind kind,
521 wxObject *clientData,
522 const wxString& shortHelp,
523 const wxString& longHelp )
524 :
525 wxToolBarToolBase(
526 tbar, id, label, bmpNormal, bmpDisabled, kind,
527 clientData, shortHelp, longHelp )
528 {
529 Init();
530 }
531
532 #pragma mark -
533 #pragma mark Toolbar Implementation
534
535 wxToolBarToolBase *wxToolBar::CreateTool(
536 int id,
537 const wxString& label,
538 const wxBitmap& bmpNormal,
539 const wxBitmap& bmpDisabled,
540 wxItemKind kind,
541 wxObject *clientData,
542 const wxString& shortHelp,
543 const wxString& longHelp )
544 {
545 return new wxToolBarTool(
546 this, id, label, bmpNormal, bmpDisabled, kind,
547 clientData, shortHelp, longHelp );
548 }
549
550 wxToolBarToolBase *
551 wxToolBar::CreateTool(wxControl *control, const wxString& label)
552 {
553 return new wxToolBarTool(this, control, label);
554 }
555
556 void wxToolBar::Init()
557 {
558 m_maxWidth = -1;
559 m_maxHeight = -1;
560 m_defaultWidth = kwxMacToolBarToolDefaultWidth;
561 m_defaultHeight = kwxMacToolBarToolDefaultHeight;
562
563 #if wxMAC_USE_NATIVE_TOOLBAR
564 m_macHIToolbarRef = NULL;
565 m_macUsesNativeToolbar = false;
566 #endif
567 }
568
569 #define kControlToolbarItemClassID CFSTR( "org.wxwidgets.controltoolbaritem" )
570
571 const EventTypeSpec kEvents[] =
572 {
573 { kEventClassHIObject, kEventHIObjectConstruct },
574 { kEventClassHIObject, kEventHIObjectInitialize },
575 { kEventClassHIObject, kEventHIObjectDestruct },
576
577 { kEventClassToolbarItem, kEventToolbarItemCreateCustomView }
578 };
579
580 const EventTypeSpec kViewEvents[] =
581 {
582 { kEventClassControl, kEventControlGetSizeConstraints }
583 };
584
585 struct ControlToolbarItem
586 {
587 HIToolbarItemRef toolbarItem;
588 HIViewRef viewRef;
589 wxSize lastValidSize ;
590 };
591
592 static pascal OSStatus ControlToolbarItemHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
593 {
594 OSStatus result = eventNotHandledErr;
595 ControlToolbarItem* object = (ControlToolbarItem*)inUserData;
596
597 switch ( GetEventClass( inEvent ) )
598 {
599 case kEventClassHIObject:
600 switch ( GetEventKind( inEvent ) )
601 {
602 case kEventHIObjectConstruct:
603 {
604 HIObjectRef toolbarItem;
605 ControlToolbarItem* item;
606
607 GetEventParameter( inEvent, kEventParamHIObjectInstance, typeHIObjectRef, NULL,
608 sizeof( HIObjectRef ), NULL, &toolbarItem );
609
610 item = (ControlToolbarItem*) malloc(sizeof(ControlToolbarItem)) ;
611 item->toolbarItem = toolbarItem ;
612 item->lastValidSize = wxSize(-1,-1);
613 item->viewRef = NULL ;
614
615 SetEventParameter( inEvent, kEventParamHIObjectInstance, typeVoidPtr, sizeof( void * ), &item );
616
617 result = noErr ;
618 }
619 break;
620
621 case kEventHIObjectInitialize:
622 result = CallNextEventHandler( inCallRef, inEvent );
623 if ( result == noErr )
624 {
625 CFDataRef data;
626 GetEventParameter( inEvent, kEventParamToolbarItemConfigData, typeCFTypeRef, NULL,
627 sizeof( CFTypeRef ), NULL, &data );
628
629 HIViewRef viewRef ;
630
631 wxASSERT_MSG( CFDataGetLength( data ) == sizeof( viewRef ) , wxT("Illegal Data passed") ) ;
632 memcpy( &viewRef , CFDataGetBytePtr( data ) , sizeof( viewRef ) ) ;
633
634 object->viewRef = (HIViewRef) viewRef ;
635 // make sure we keep that control during our lifetime
636 CFRetain( object->viewRef ) ;
637
638 verify_noerr(InstallEventHandler( GetControlEventTarget( viewRef ), ControlToolbarItemHandler,
639 GetEventTypeCount( kViewEvents ), kViewEvents, object, NULL ));
640 result = noErr ;
641 }
642 break;
643
644 case kEventHIObjectDestruct:
645 {
646 HIViewRef viewRef = object->viewRef ;
647 if( viewRef && IsValidControlHandle( viewRef) )
648 {
649 // depending whether the wxControl corresponding to this HIView has already been destroyed or
650 // not, ref counts differ, so we cannot assert a special value
651 CFIndex count = CFGetRetainCount( viewRef ) ;
652 wxASSERT_MSG( count >=1 , wxT("Reference Count of native tool was illegal before removal") );
653 if ( count >= 1 )
654 CFRelease( viewRef ) ;
655 }
656 free( object ) ;
657 result = noErr;
658 }
659 break;
660 }
661 break;
662
663 case kEventClassToolbarItem:
664 switch ( GetEventKind( inEvent ) )
665 {
666 case kEventToolbarItemCreateCustomView:
667 {
668 HIViewRef viewRef = object->viewRef ;
669 HIViewRemoveFromSuperview( viewRef ) ;
670 HIViewSetVisible(viewRef, true) ;
671 CFRetain( viewRef ) ;
672 result = SetEventParameter( inEvent, kEventParamControlRef, typeControlRef, sizeof( HIViewRef ), &viewRef );
673 }
674 break;
675 }
676 break;
677
678 case kEventClassControl:
679 switch ( GetEventKind( inEvent ) )
680 {
681 case kEventControlGetSizeConstraints:
682 {
683 wxWindow* wxwindow = wxFindControlFromMacControl(object->viewRef ) ;
684 if ( wxwindow )
685 {
686 // during toolbar layout the native window sometimes gets negative sizes,
687 // sometimes it just gets shrunk behind our back, so in order to avoid
688 // ever shrinking more, once a valid size is captured, we keep it
689
690 wxSize sz = object->lastValidSize;
691 if ( sz.x <= 0 || sz.y <= 0 )
692 {
693 sz = wxwindow->GetSize() ;
694 sz.x -= wxwindow->MacGetLeftBorderSize() + wxwindow->MacGetRightBorderSize();
695 sz.y -= wxwindow->MacGetTopBorderSize() + wxwindow->MacGetBottomBorderSize();
696 if ( sz.x > 0 && sz.y > 0 )
697 object->lastValidSize = sz ;
698 else
699 sz = wxSize(0,0) ;
700 }
701
702 HISize min, max;
703 min.width = max.width = sz.x ;
704 min.height = max.height = sz.y ;
705
706 result = SetEventParameter( inEvent, kEventParamMinimumSize, typeHISize,
707 sizeof( HISize ), &min );
708
709 result = SetEventParameter( inEvent, kEventParamMaximumSize, typeHISize,
710 sizeof( HISize ), &max );
711 result = noErr ;
712 }
713 }
714 break;
715 }
716 break;
717 }
718
719 return result;
720 }
721
722 void RegisterControlToolbarItemClass()
723 {
724 static bool sRegistered;
725
726 if ( !sRegistered )
727 {
728 HIObjectRegisterSubclass( kControlToolbarItemClassID, kHIToolbarItemClassID, 0,
729 ControlToolbarItemHandler, GetEventTypeCount( kEvents ), kEvents, 0, NULL );
730
731 sRegistered = true;
732 }
733 }
734
735 HIToolbarItemRef CreateControlToolbarItem(CFStringRef inIdentifier, CFTypeRef inConfigData)
736 {
737 RegisterControlToolbarItemClass();
738
739 OSStatus err;
740 EventRef event;
741 UInt32 options = kHIToolbarItemAllowDuplicates;
742 HIToolbarItemRef result = NULL;
743
744 err = CreateEvent( NULL, kEventClassHIObject, kEventHIObjectInitialize, GetCurrentEventTime(), 0, &event );
745 require_noerr( err, CantCreateEvent );
746
747 SetEventParameter( event, kEventParamAttributes, typeUInt32, sizeof( UInt32 ), &options );
748 SetEventParameter( event, kEventParamToolbarItemIdentifier, typeCFStringRef, sizeof( CFStringRef ), &inIdentifier );
749
750 if ( inConfigData )
751 SetEventParameter( event, kEventParamToolbarItemConfigData, typeCFTypeRef, sizeof( CFTypeRef ), &inConfigData );
752
753 err = HIObjectCreate( kControlToolbarItemClassID, event, (HIObjectRef*)&result );
754 check_noerr( err );
755
756 ReleaseEvent( event );
757 CantCreateEvent :
758 return result ;
759 }
760
761 #if wxMAC_USE_NATIVE_TOOLBAR
762 static const EventTypeSpec kToolbarEvents[] =
763 {
764 { kEventClassToolbar, kEventToolbarGetDefaultIdentifiers },
765 { kEventClassToolbar, kEventToolbarGetAllowedIdentifiers },
766 { kEventClassToolbar, kEventToolbarCreateItemWithIdentifier },
767 };
768
769 static OSStatus ToolbarDelegateHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
770 {
771 OSStatus result = eventNotHandledErr;
772 // Not yet needed
773 // wxToolBar* toolbar = (wxToolBar*) inUserData ;
774 CFMutableArrayRef array;
775
776 switch ( GetEventKind( inEvent ) )
777 {
778 case kEventToolbarGetDefaultIdentifiers:
779 {
780 GetEventParameter( inEvent, kEventParamMutableArray, typeCFMutableArrayRef, NULL,
781 sizeof( CFMutableArrayRef ), NULL, &array );
782 // not implemented yet
783 // GetToolbarDefaultItems( array );
784 result = noErr;
785 }
786 break;
787
788 case kEventToolbarGetAllowedIdentifiers:
789 {
790 GetEventParameter( inEvent, kEventParamMutableArray, typeCFMutableArrayRef, NULL,
791 sizeof( CFMutableArrayRef ), NULL, &array );
792 // not implemented yet
793 // GetToolbarAllowedItems( array );
794 result = noErr;
795 }
796 break;
797 case kEventToolbarCreateItemWithIdentifier:
798 {
799 HIToolbarItemRef item = NULL;
800 CFTypeRef data = NULL;
801 CFStringRef identifier = NULL ;
802
803 GetEventParameter( inEvent, kEventParamToolbarItemIdentifier, typeCFStringRef, NULL,
804 sizeof( CFStringRef ), NULL, &identifier );
805
806 GetEventParameter( inEvent, kEventParamToolbarItemConfigData, typeCFTypeRef, NULL,
807 sizeof( CFTypeRef ), NULL, &data );
808
809 if ( CFStringCompare( kControlToolbarItemClassID, identifier, kCFCompareBackwards ) == kCFCompareEqualTo )
810 {
811 item = CreateControlToolbarItem( kControlToolbarItemClassID, data );
812 if ( item )
813 {
814 SetEventParameter( inEvent, kEventParamToolbarItem, typeHIToolbarItemRef,
815 sizeof( HIToolbarItemRef ), &item );
816 result = noErr;
817 }
818 }
819
820 }
821 break;
822 }
823 return result ;
824 }
825 #endif // wxMAC_USE_NATIVE_TOOLBAR
826
827 // also for the toolbar we have the dual implementation:
828 // only when MacInstallNativeToolbar is called is the native toolbar set as the window toolbar
829
830 bool wxToolBar::Create(
831 wxWindow *parent,
832 wxWindowID id,
833 const wxPoint& pos,
834 const wxSize& size,
835 long style,
836 const wxString& name )
837 {
838 if ( !wxToolBarBase::Create( parent, id, pos, size, style, wxDefaultValidator, name ) )
839 return false;
840
841 FixupStyle();
842
843 OSStatus err = noErr;
844
845 #if wxMAC_USE_NATIVE_TOOLBAR
846 if (parent->IsKindOf(CLASSINFO(wxFrame)) && wxSystemOptions::GetOptionInt(wxT("mac.toolbar.no-native")) != 1)
847 {
848 wxString labelStr = wxString::Format( wxT("%xd"), (int)this );
849 err = HIToolbarCreate(
850 wxMacCFStringHolder( labelStr, wxFont::GetDefaultEncoding() ), 0,
851 (HIToolbarRef*) &m_macHIToolbarRef );
852
853 if (m_macHIToolbarRef != NULL)
854 {
855 InstallEventHandler( HIObjectGetEventTarget((HIToolbarRef)m_macHIToolbarRef ), ToolbarDelegateHandler,
856 GetEventTypeCount( kToolbarEvents ), kToolbarEvents, this, NULL );
857
858 HIToolbarDisplayMode mode = kHIToolbarDisplayModeDefault;
859 HIToolbarDisplaySize displaySize = kHIToolbarDisplaySizeSmall;
860
861 if ( style & wxTB_NOICONS )
862 mode = kHIToolbarDisplayModeLabelOnly;
863 else if ( style & wxTB_TEXT )
864 mode = kHIToolbarDisplayModeIconAndLabel;
865 else
866 mode = kHIToolbarDisplayModeIconOnly;
867
868 HIToolbarSetDisplayMode( (HIToolbarRef) m_macHIToolbarRef, mode );
869 HIToolbarSetDisplaySize( (HIToolbarRef) m_macHIToolbarRef, displaySize );
870 }
871 }
872 #endif // wxMAC_USE_NATIVE_TOOLBAR
873
874 return (err == noErr);
875 }
876
877 wxToolBar::~wxToolBar()
878 {
879 #if wxMAC_USE_NATIVE_TOOLBAR
880 if (m_macHIToolbarRef != NULL)
881 {
882 // if this is the installed toolbar, then deinstall it
883 if (m_macUsesNativeToolbar)
884 MacInstallNativeToolbar( false );
885
886 CFIndex count = CFGetRetainCount( m_macHIToolbarRef ) ;
887 wxASSERT_MSG( count == 1 , wxT("Reference Count of native control was not 1 in wxToolBar destructor") );
888
889 CFRelease( (HIToolbarRef)m_macHIToolbarRef );
890 m_macHIToolbarRef = NULL;
891 }
892 #endif
893 }
894
895 bool wxToolBar::Show( bool show )
896 {
897 WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
898 bool bResult = (tlw != NULL);
899
900 if (bResult)
901 {
902 #if wxMAC_USE_NATIVE_TOOLBAR
903 bool ownToolbarInstalled = false;
904 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
905 if (ownToolbarInstalled)
906 {
907 bResult = (IsWindowToolbarVisible( tlw ) != show);
908 if ( bResult )
909 ShowHideWindowToolbar( tlw, show, false );
910 }
911 else
912 bResult = wxToolBarBase::Show( show );
913 #else
914
915 bResult = wxToolBarBase::Show( show );
916 #endif
917 }
918
919 return bResult;
920 }
921
922 bool wxToolBar::IsShown() const
923 {
924 bool bResult;
925
926 #if wxMAC_USE_NATIVE_TOOLBAR
927 bool ownToolbarInstalled;
928
929 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
930 if (ownToolbarInstalled)
931 {
932 WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
933 bResult = IsWindowToolbarVisible( tlw );
934 }
935 else
936 bResult = wxToolBarBase::IsShown();
937 #else
938
939 bResult = wxToolBarBase::IsShown();
940 #endif
941
942 return bResult;
943 }
944
945 void wxToolBar::DoGetSize( int *width, int *height ) const
946 {
947 #if wxMAC_USE_NATIVE_TOOLBAR
948 Rect boundsR;
949 bool ownToolbarInstalled;
950
951 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
952 if ( ownToolbarInstalled )
953 {
954 // TODO: is this really a control ?
955 GetControlBounds( (ControlRef) m_macHIToolbarRef, &boundsR );
956 if ( width != NULL )
957 *width = boundsR.right - boundsR.left;
958 if ( height != NULL )
959 *height = boundsR.bottom - boundsR.top;
960 }
961 else
962 wxToolBarBase::DoGetSize( width, height );
963
964 #else
965 wxToolBarBase::DoGetSize( width, height );
966 #endif
967 }
968
969 wxSize wxToolBar::DoGetBestSize() const
970 {
971 int width, height;
972
973 DoGetSize( &width, &height );
974
975 return wxSize( width, height );
976 }
977
978 void wxToolBar::SetWindowStyleFlag( long style )
979 {
980 wxToolBarBase::SetWindowStyleFlag( style );
981
982 #if wxMAC_USE_NATIVE_TOOLBAR
983 if (m_macHIToolbarRef != NULL)
984 {
985 HIToolbarDisplayMode mode = kHIToolbarDisplayModeDefault;
986
987 if ( style & wxTB_NOICONS )
988 mode = kHIToolbarDisplayModeLabelOnly;
989 else if ( style & wxTB_TEXT )
990 mode = kHIToolbarDisplayModeIconAndLabel;
991 else
992 mode = kHIToolbarDisplayModeIconOnly;
993
994 HIToolbarSetDisplayMode( (HIToolbarRef) m_macHIToolbarRef, mode );
995 }
996 #endif
997 }
998
999 #if wxMAC_USE_NATIVE_TOOLBAR
1000 bool wxToolBar::MacWantsNativeToolbar()
1001 {
1002 return m_macUsesNativeToolbar;
1003 }
1004
1005 bool wxToolBar::MacTopLevelHasNativeToolbar(bool *ownToolbarInstalled) const
1006 {
1007 bool bResultV = false;
1008
1009 if (ownToolbarInstalled != NULL)
1010 *ownToolbarInstalled = false;
1011
1012 WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
1013 if (tlw != NULL)
1014 {
1015 HIToolbarRef curToolbarRef = NULL;
1016 OSStatus err = GetWindowToolbar( tlw, &curToolbarRef );
1017 bResultV = ((err == noErr) && (curToolbarRef != NULL));
1018 if (bResultV && (ownToolbarInstalled != NULL))
1019 *ownToolbarInstalled = (curToolbarRef == m_macHIToolbarRef);
1020 }
1021
1022 return bResultV;
1023 }
1024
1025 bool wxToolBar::MacInstallNativeToolbar(bool usesNative)
1026 {
1027 bool bResult = false;
1028
1029 if (usesNative && (m_macHIToolbarRef == NULL))
1030 return bResult;
1031
1032 if (usesNative && ((GetWindowStyleFlag() & wxTB_VERTICAL) != 0))
1033 return bResult;
1034
1035 WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
1036 if (tlw == NULL)
1037 return bResult;
1038
1039 // check the existing toolbar
1040 HIToolbarRef curToolbarRef = NULL;
1041 OSStatus err = GetWindowToolbar( tlw, &curToolbarRef );
1042 if (err != noErr)
1043 curToolbarRef = NULL;
1044
1045 m_macUsesNativeToolbar = usesNative;
1046
1047 if (m_macUsesNativeToolbar)
1048 {
1049 // only install toolbar if there isn't one installed already
1050 if (curToolbarRef == NULL)
1051 {
1052 bResult = true;
1053
1054 SetWindowToolbar( tlw, (HIToolbarRef) m_macHIToolbarRef );
1055 ShowHideWindowToolbar( tlw, true, false );
1056 ChangeWindowAttributes( tlw, kWindowToolbarButtonAttribute, 0 );
1057 SetAutomaticControlDragTrackingEnabledForWindow( tlw, true );
1058
1059 Rect r = { 0, 0, 0, 0 };
1060 m_peer->SetRect( &r );
1061 SetSize( wxSIZE_AUTO_WIDTH, 0 );
1062 m_peer->SetVisibility( false, true );
1063 wxToolBarBase::Show( false );
1064 }
1065 }
1066 else
1067 {
1068 // only deinstall toolbar if this is the installed one
1069 if (m_macHIToolbarRef == curToolbarRef)
1070 {
1071 bResult = true;
1072
1073 ShowHideWindowToolbar( tlw, false, false );
1074 ChangeWindowAttributes( tlw, 0, kWindowToolbarButtonAttribute );
1075 SetWindowToolbar( tlw, NULL );
1076
1077 m_peer->SetVisibility( true, true );
1078 }
1079 }
1080
1081 if (bResult)
1082 InvalidateBestSize();
1083
1084 // wxLogDebug( wxT(" --> [%lx] - result [%s]"), (long)this, bResult ? wxT("T") : wxT("F") );
1085 return bResult;
1086 }
1087 #endif
1088
1089 bool wxToolBar::Realize()
1090 {
1091 if (m_tools.GetCount() == 0)
1092 return false;
1093
1094 int maxWidth = 0;
1095 int maxHeight = 0;
1096
1097 int maxToolWidth = 0;
1098 int maxToolHeight = 0;
1099
1100 int x = m_xMargin + kwxMacToolBarLeftMargin;
1101 int y = m_yMargin + kwxMacToolBarTopMargin;
1102
1103 int tw, th;
1104 GetSize( &tw, &th );
1105
1106 // find the maximum tool width and height
1107 wxToolBarTool *tool;
1108 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1109 while ( node )
1110 {
1111 tool = (wxToolBarTool *) node->GetData();
1112 if ( tool != NULL )
1113 {
1114 wxSize sz = tool->GetSize();
1115
1116 if ( sz.x > maxToolWidth )
1117 maxToolWidth = sz.x;
1118 if ( sz.y > maxToolHeight )
1119 maxToolHeight = sz.y;
1120 }
1121
1122 node = node->GetNext();
1123 }
1124
1125 bool lastIsRadio = false;
1126 bool curIsRadio = false;
1127
1128 #if wxMAC_USE_NATIVE_TOOLBAR
1129 CFIndex currentPosition = 0;
1130 bool insertAll = false;
1131
1132 HIToolbarRef refTB = (HIToolbarRef)m_macHIToolbarRef;
1133 #endif
1134
1135 node = m_tools.GetFirst();
1136 while ( node )
1137 {
1138 tool = (wxToolBarTool*) node->GetData();
1139 if ( tool == NULL )
1140 {
1141 node = node->GetNext();
1142 continue;
1143 }
1144
1145 // set tool position:
1146 // for the moment just perform a single row/column alignment
1147 wxSize cursize = tool->GetSize();
1148 if ( x + cursize.x > maxWidth )
1149 maxWidth = x + cursize.x;
1150 if ( y + cursize.y > maxHeight )
1151 maxHeight = y + cursize.y;
1152
1153 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1154 {
1155 int x1 = x + ( maxToolWidth - cursize.x ) / 2;
1156 tool->SetPosition( wxPoint(x1, y) );
1157 }
1158 else
1159 {
1160 int y1 = y + ( maxToolHeight - cursize.y ) / 2;
1161 tool->SetPosition( wxPoint(x, y1) );
1162 }
1163
1164 // update the item positioning state
1165 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1166 y += cursize.y + kwxMacToolSpacing;
1167 else
1168 x += cursize.x + kwxMacToolSpacing;
1169
1170 #if wxMAC_USE_NATIVE_TOOLBAR
1171 // install in native HIToolbar
1172 if ( refTB )
1173 {
1174 HIToolbarItemRef hiItemRef = tool->GetToolbarItemRef();
1175 if ( hiItemRef != NULL )
1176 {
1177 if ( insertAll || (tool->GetIndex() != currentPosition) )
1178 {
1179 OSStatus err = noErr;
1180 if ( !insertAll )
1181 {
1182 insertAll = true;
1183
1184 // if this is the first tool that gets newly inserted or repositioned
1185 // first remove all 'old' tools from here to the right, because of this
1186 // all following tools will have to be reinserted (insertAll).
1187 for ( wxToolBarToolsList::compatibility_iterator node2 = m_tools.GetLast();
1188 node2 != node;
1189 node2 = node2->GetPrevious() )
1190 {
1191 wxToolBarTool *tool2 = (wxToolBarTool*) node2->GetData();
1192
1193 const long idx = tool2->GetIndex();
1194 if ( idx != -1 )
1195 {
1196 if ( tool2->IsControl() )
1197 {
1198 CFIndex count = CFGetRetainCount( tool2->GetControl()->GetPeer()->GetControlRef() ) ;
1199 wxASSERT_MSG( count == 3 || count == 2 , wxT("Reference Count of native tool was illegal before removal") );
1200 wxASSERT( IsValidControlHandle(tool2->GetControl()->GetPeer()->GetControlRef() )) ;
1201 }
1202 err = HIToolbarRemoveItemAtIndex(refTB, idx);
1203 if ( err != noErr )
1204 {
1205 wxLogDebug(wxT("HIToolbarRemoveItemAtIndex(%ld) failed [%ld]"),
1206 idx, (long)err);
1207 }
1208 if ( tool2->IsControl() )
1209 {
1210 CFIndex count = CFGetRetainCount( tool2->GetControl()->GetPeer()->GetControlRef() ) ;
1211 wxASSERT_MSG( count == 2 , wxT("Reference Count of native tool was not 2 after removal") );
1212 wxASSERT( IsValidControlHandle(tool2->GetControl()->GetPeer()->GetControlRef() )) ;
1213 }
1214
1215 tool2->SetIndex(-1);
1216 }
1217 }
1218 }
1219
1220 err = HIToolbarInsertItemAtIndex( refTB, hiItemRef, currentPosition );
1221 if (err != noErr)
1222 {
1223 wxLogDebug( wxT("HIToolbarInsertItemAtIndex failed [%ld]"), (long)err );
1224 }
1225
1226 tool->SetIndex( currentPosition );
1227 if ( tool->IsControl() )
1228 {
1229 CFIndex count = CFGetRetainCount( tool->GetControl()->GetPeer()->GetControlRef() ) ;
1230 wxASSERT_MSG( count == 3 || count == 2, wxT("Reference Count of native tool was illegal after insertion") );
1231 wxASSERT( IsValidControlHandle(tool->GetControl()->GetPeer()->GetControlRef() )) ;
1232 }
1233 }
1234
1235 currentPosition++;
1236 }
1237 }
1238 #endif
1239
1240 // update radio button (and group) state
1241 lastIsRadio = curIsRadio;
1242 curIsRadio = ( tool->IsButton() && (tool->GetKind() == wxITEM_RADIO) );
1243
1244 if ( !curIsRadio )
1245 {
1246 if ( tool->IsToggled() )
1247 DoToggleTool( tool, true );
1248 }
1249 else
1250 {
1251 if ( !lastIsRadio )
1252 {
1253 if ( tool->Toggle( true ) )
1254 {
1255 DoToggleTool( tool, true );
1256 }
1257 }
1258 else if ( tool->IsToggled() )
1259 {
1260 if ( tool->IsToggled() )
1261 DoToggleTool( tool, true );
1262
1263 wxToolBarToolsList::compatibility_iterator nodePrev = node->GetPrevious();
1264 while ( nodePrev )
1265 {
1266 wxToolBarToolBase *toggleTool = nodePrev->GetData();
1267 if ( (toggleTool == NULL) || !toggleTool->IsButton() || (toggleTool->GetKind() != wxITEM_RADIO) )
1268 break;
1269
1270 if ( toggleTool->Toggle( false ) )
1271 DoToggleTool( toggleTool, false );
1272
1273 nodePrev = nodePrev->GetPrevious();
1274 }
1275 }
1276 }
1277
1278 node = node->GetNext();
1279 }
1280
1281 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
1282 {
1283 // if not set yet, only one row
1284 if ( m_maxRows <= 0 )
1285 SetRows( 1 );
1286
1287 m_minWidth = maxWidth;
1288 maxWidth = tw;
1289 maxHeight += m_yMargin + kwxMacToolBarTopMargin;
1290 m_minHeight = m_maxHeight = maxHeight;
1291 }
1292 else
1293 {
1294 // if not set yet, have one column
1295 if ( (GetToolsCount() > 0) && (m_maxRows <= 0) )
1296 SetRows( GetToolsCount() );
1297
1298 m_minHeight = maxHeight;
1299 maxHeight = th;
1300 maxWidth += m_xMargin + kwxMacToolBarLeftMargin;
1301 m_minWidth = m_maxWidth = maxWidth;
1302 }
1303
1304 #if 0
1305 // FIXME: should this be OSX-only?
1306 {
1307 bool wantNativeToolbar, ownToolbarInstalled;
1308
1309 // attempt to install the native toolbar
1310 wantNativeToolbar = ((GetWindowStyleFlag() & wxTB_VERTICAL) == 0);
1311 MacInstallNativeToolbar( wantNativeToolbar );
1312 (void)MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
1313 if (!ownToolbarInstalled)
1314 {
1315 SetSize( maxWidth, maxHeight );
1316 InvalidateBestSize();
1317 }
1318 }
1319 #else
1320 SetSize( maxWidth, maxHeight );
1321 InvalidateBestSize();
1322 #endif
1323
1324 SetInitialSize();
1325
1326 return true;
1327 }
1328
1329 void wxToolBar::SetToolBitmapSize(const wxSize& size)
1330 {
1331 m_defaultWidth = size.x + kwxMacToolBorder;
1332 m_defaultHeight = size.y + kwxMacToolBorder;
1333
1334 #if wxMAC_USE_NATIVE_TOOLBAR
1335 if (m_macHIToolbarRef != NULL)
1336 {
1337 int maxs = wxMax( size.x, size.y );
1338 HIToolbarDisplaySize sizeSpec;
1339 if ( maxs > 32 )
1340 sizeSpec = kHIToolbarDisplaySizeNormal;
1341 else if ( maxs > 24 )
1342 sizeSpec = kHIToolbarDisplaySizeDefault;
1343 else
1344 sizeSpec = kHIToolbarDisplaySizeSmall;
1345
1346 HIToolbarSetDisplaySize( (HIToolbarRef) m_macHIToolbarRef, sizeSpec );
1347 }
1348 #endif
1349 }
1350
1351 // The button size is bigger than the bitmap size
1352 wxSize wxToolBar::GetToolSize() const
1353 {
1354 return wxSize(m_defaultWidth + kwxMacToolBorder, m_defaultHeight + kwxMacToolBorder);
1355 }
1356
1357 void wxToolBar::SetRows(int nRows)
1358 {
1359 // avoid resizing the frame uselessly
1360 if ( nRows != m_maxRows )
1361 m_maxRows = nRows;
1362 }
1363
1364 void wxToolBar::MacSuperChangedPosition()
1365 {
1366 wxWindow::MacSuperChangedPosition();
1367
1368 #if wxMAC_USE_NATIVE_TOOLBAR
1369 if (! m_macUsesNativeToolbar )
1370 Realize();
1371 #else
1372
1373 Realize();
1374 #endif
1375 }
1376
1377 void wxToolBar::SetToolNormalBitmap( int id, const wxBitmap& bitmap )
1378 {
1379 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
1380 if ( tool )
1381 {
1382 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
1383
1384 tool->SetNormalBitmap(bitmap);
1385
1386 // a side-effect of the UpdateToggleImage function is that it always changes the bitmap used on the button.
1387 tool->UpdateToggleImage( tool->CanBeToggled() && tool->IsToggled() );
1388 }
1389 }
1390
1391 void wxToolBar::SetToolDisabledBitmap( int id, const wxBitmap& bitmap )
1392 {
1393 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
1394 if ( tool )
1395 {
1396 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
1397
1398 tool->SetDisabledBitmap(bitmap);
1399
1400 // TODO: what to do for this one?
1401 }
1402 }
1403
1404 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
1405 {
1406 wxToolBarTool *tool;
1407 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1408 while ( node )
1409 {
1410 tool = (wxToolBarTool *)node->GetData();
1411 if (tool != NULL)
1412 {
1413 wxRect2DInt r( tool->GetPosition(), tool->GetSize() );
1414 if ( r.Contains( wxPoint( x, y ) ) )
1415 return tool;
1416 }
1417
1418 node = node->GetNext();
1419 }
1420
1421 return (wxToolBarToolBase*)NULL;
1422 }
1423
1424 wxString wxToolBar::MacGetToolTipString( wxPoint &pt )
1425 {
1426 wxToolBarToolBase *tool = FindToolForPosition( pt.x, pt.y );
1427 if ( tool != NULL )
1428 return tool->GetShortHelp();
1429
1430 return wxEmptyString;
1431 }
1432
1433 void wxToolBar::DoEnableTool(wxToolBarToolBase *t, bool enable)
1434 {
1435 if ( t != NULL )
1436 ((wxToolBarTool*)t)->DoEnable( enable );
1437 }
1438
1439 void wxToolBar::DoToggleTool(wxToolBarToolBase *t, bool toggle)
1440 {
1441 wxToolBarTool *tool = (wxToolBarTool *)t;
1442 if ( ( tool != NULL ) && tool->IsButton() )
1443 tool->UpdateToggleImage( toggle );
1444 }
1445
1446 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
1447 {
1448 wxToolBarTool *tool = wx_static_cast( wxToolBarTool*, toolBase );
1449 if (tool == NULL)
1450 return false;
1451
1452 WindowRef window = (WindowRef) MacGetTopLevelWindowRef();
1453 wxSize toolSize = GetToolSize();
1454 Rect toolrect = { 0, 0, toolSize.y, toolSize.x };
1455 ControlRef controlHandle = NULL;
1456 OSStatus err = 0;
1457 tool->Attach( this );
1458
1459 #if wxMAC_USE_NATIVE_TOOLBAR
1460 HIToolbarItemRef item;
1461 #endif
1462
1463 switch (tool->GetStyle())
1464 {
1465 case wxTOOL_STYLE_SEPARATOR:
1466 {
1467 wxASSERT( tool->GetControlHandle() == NULL );
1468 toolSize.x /= 4;
1469 toolSize.y /= 4;
1470 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1471 toolrect.bottom = toolSize.y;
1472 else
1473 toolrect.right = toolSize.x;
1474
1475 // in flat style we need a visual separator
1476 #if wxMAC_USE_NATIVE_TOOLBAR
1477 if (m_macHIToolbarRef != NULL)
1478 {
1479 err = HIToolbarItemCreate(
1480 kHIToolbarSeparatorIdentifier,
1481 kHIToolbarItemCantBeRemoved | kHIToolbarItemIsSeparator | kHIToolbarItemAllowDuplicates,
1482 &item );
1483 if (err == noErr)
1484 tool->SetToolbarItemRef( item );
1485 }
1486 else
1487 err = noErr;
1488 #endif // wxMAC_USE_NATIVE_TOOLBAR
1489
1490 CreateSeparatorControl( window, &toolrect, &controlHandle );
1491 tool->SetControlHandle( controlHandle );
1492 }
1493 break;
1494
1495 case wxTOOL_STYLE_BUTTON:
1496 {
1497 wxASSERT( tool->GetControlHandle() == NULL );
1498 ControlButtonContentInfo info;
1499 wxMacCreateBitmapButton( &info, tool->GetNormalBitmap(), kControlContentIconRef );
1500
1501 if ( UMAGetSystemVersion() >= 0x1000)
1502 {
1503 CreateIconControl( window, &toolrect, &info, false, &controlHandle );
1504 }
1505 else
1506 {
1507 SInt16 behaviour = kControlBehaviorOffsetContents;
1508 if ( tool->CanBeToggled() )
1509 behaviour |= kControlBehaviorToggles;
1510 err = CreateBevelButtonControl( window,
1511 &toolrect, CFSTR(""), kControlBevelButtonNormalBevel,
1512 behaviour, &info, 0, 0, 0, &controlHandle );
1513 }
1514
1515 #if wxMAC_USE_NATIVE_TOOLBAR
1516 if (m_macHIToolbarRef != NULL)
1517 {
1518 wxString labelStr = wxString::Format(wxT("%xd"), (int)tool);
1519 err = HIToolbarItemCreate(
1520 wxMacCFStringHolder(labelStr, wxFont::GetDefaultEncoding()),
1521 kHIToolbarItemCantBeRemoved | kHIToolbarItemAnchoredLeft | kHIToolbarItemAllowDuplicates, &item );
1522 if (err == noErr)
1523 {
1524 InstallEventHandler(
1525 HIObjectGetEventTarget(item), GetwxMacToolBarEventHandlerUPP(),
1526 GetEventTypeCount(toolBarEventList), toolBarEventList, tool, NULL );
1527
1528 HIToolbarItemSetIconRef( item, info.u.iconRef );
1529 HIToolbarItemSetCommandID( item, kHIToolbarCommandPressAction );
1530 tool->SetToolbarItemRef( item );
1531 }
1532 }
1533 else
1534 err = noErr;
1535 #endif // wxMAC_USE_NATIVE_TOOLBAR
1536
1537 wxMacReleaseBitmapButton( &info );
1538
1539 #if 0
1540 SetBevelButtonTextPlacement( m_controlHandle, kControlBevelButtonPlaceBelowGraphic );
1541 UMASetControlTitle( m_controlHandle, label, wxFont::GetDefaultEncoding() );
1542 #endif
1543
1544 InstallControlEventHandler(
1545 (ControlRef) controlHandle, GetwxMacToolBarToolEventHandlerUPP(),
1546 GetEventTypeCount(eventList), eventList, tool, NULL );
1547
1548 tool->SetControlHandle( controlHandle );
1549 }
1550 break;
1551
1552 case wxTOOL_STYLE_CONTROL:
1553
1554 #if wxMAC_USE_NATIVE_TOOLBAR
1555 if (m_macHIToolbarRef != NULL)
1556 {
1557 wxCHECK_MSG( tool->GetControl(), false, _T("control must be non-NULL") );
1558
1559 HIViewRef viewRef = (HIViewRef) tool->GetControl()->GetHandle() ;
1560 CFDataRef data = CFDataCreate( kCFAllocatorDefault , (UInt8*) &viewRef , sizeof(viewRef) ) ;
1561 err = HIToolbarCreateItemWithIdentifier((HIToolbarRef) m_macHIToolbarRef,kControlToolbarItemClassID,
1562 data , &item ) ;
1563
1564 if (err == noErr)
1565 {
1566 tool->SetToolbarItemRef( item );
1567 }
1568 CFRelease( data ) ;
1569 }
1570 else
1571 {
1572 err = noErr;
1573 break;
1574 }
1575 #else
1576 // right now there's nothing to do here
1577 #endif
1578 break;
1579
1580 default:
1581 break;
1582 }
1583
1584 #if wxMAC_USE_NATIVE_TOOLBAR
1585 wxString label = tool->GetLabel();
1586 if (m_macHIToolbarRef && !label.empty() )
1587 {
1588 // strip mnemonics from the label for compatibility
1589 // with the usual labels in wxStaticText sense
1590 label = wxStripMenuCodes(label);
1591
1592 HIToolbarItemSetLabel(item,
1593 wxMacCFStringHolder(label, m_font.GetEncoding()));
1594 }
1595 #endif // wxMAC_USE_NATIVE_TOOLBAR
1596
1597 if ( err == noErr )
1598 {
1599 if ( controlHandle )
1600 {
1601 ControlRef container = (ControlRef) GetHandle();
1602 wxASSERT_MSG( container != NULL, wxT("No valid Mac container control") );
1603
1604 UMAShowControl( controlHandle );
1605 ::EmbedControl( controlHandle, container );
1606 }
1607
1608 if ( tool->CanBeToggled() && tool->IsToggled() )
1609 tool->UpdateToggleImage( true );
1610
1611 // nothing special to do here - we relayout in Realize() later
1612 InvalidateBestSize();
1613 }
1614 else
1615 {
1616 wxFAIL_MSG( wxString::Format( wxT("wxToolBar::DoInsertTool - failure [%ld]"), (long)err ) );
1617 }
1618
1619 return (err == noErr);
1620 }
1621
1622 void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
1623 {
1624 wxFAIL_MSG( wxT("not implemented") );
1625 }
1626
1627 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolbase)
1628 {
1629 wxToolBarTool* tool = wx_static_cast( wxToolBarTool*, toolbase );
1630 wxToolBarToolsList::compatibility_iterator node;
1631 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
1632 {
1633 wxToolBarToolBase *tool2 = node->GetData();
1634 if ( tool2 == tool )
1635 {
1636 // let node point to the next node in the list
1637 node = node->GetNext();
1638
1639 break;
1640 }
1641 }
1642
1643 wxSize sz = ((wxToolBarTool*)tool)->GetSize();
1644
1645 tool->Detach();
1646
1647 #if wxMAC_USE_NATIVE_TOOLBAR
1648 CFIndex removeIndex = tool->GetIndex();
1649 #endif
1650
1651 #if wxMAC_USE_NATIVE_TOOLBAR
1652 if (m_macHIToolbarRef != NULL)
1653 {
1654 if ( removeIndex != -1 && m_macHIToolbarRef )
1655 {
1656 HIToolbarRemoveItemAtIndex( (HIToolbarRef) m_macHIToolbarRef, removeIndex );
1657 tool->SetIndex( -1 );
1658 }
1659 }
1660 #endif
1661 switch ( tool->GetStyle() )
1662 {
1663 case wxTOOL_STYLE_CONTROL:
1664 if ( tool->GetControl() )
1665 tool->GetControl()->Destroy();
1666 break;
1667
1668 case wxTOOL_STYLE_BUTTON:
1669 case wxTOOL_STYLE_SEPARATOR:
1670 // nothing special
1671 break;
1672
1673 default:
1674 break;
1675 }
1676 tool->ClearControl();
1677
1678 // and finally reposition all the controls after this one
1679
1680 for ( /* node -> first after deleted */; node; node = node->GetNext() )
1681 {
1682 wxToolBarTool *tool2 = (wxToolBarTool*) node->GetData();
1683 wxPoint pt = tool2->GetPosition();
1684
1685 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1686 pt.y -= sz.y;
1687 else
1688 pt.x -= sz.x;
1689
1690 tool2->SetPosition( pt );
1691
1692 #if wxMAC_USE_NATIVE_TOOLBAR
1693 if (m_macHIToolbarRef != NULL)
1694 {
1695 if ( removeIndex != -1 && tool2->GetIndex() > removeIndex )
1696 tool2->SetIndex( tool2->GetIndex() - 1 );
1697 }
1698 #endif
1699 }
1700
1701 InvalidateBestSize();
1702
1703 return true;
1704 }
1705
1706 void wxToolBar::OnPaint(wxPaintEvent& event)
1707 {
1708 #if wxMAC_USE_NATIVE_TOOLBAR
1709 if ( m_macUsesNativeToolbar )
1710 {
1711 event.Skip(true);
1712 return;
1713 }
1714 #endif
1715
1716 wxPaintDC dc(this);
1717
1718 int w, h;
1719 GetSize( &w, &h );
1720
1721 bool drawMetalTheme = MacGetTopLevelWindow()->MacGetMetalAppearance();
1722 bool minimumUmaAvailable = (UMAGetSystemVersion() >= 0x1030);
1723
1724 #if wxMAC_USE_CORE_GRAPHICS && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
1725 if ( !drawMetalTheme && minimumUmaAvailable )
1726 {
1727 HIThemePlacardDrawInfo info;
1728 memset( &info, 0, sizeof(info) );
1729 info.version = 0;
1730 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive;
1731
1732 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef();
1733 HIRect rect = CGRectMake( 0, 0, w, h );
1734 HIThemeDrawPlacard( &rect, &info, cgContext, kHIThemeOrientationNormal );
1735 }
1736 else
1737 {
1738 // leave the background as it is (striped or metal)
1739 }
1740
1741 #else
1742
1743 const bool drawBorder = true;
1744
1745 if (drawBorder)
1746 {
1747 wxMacPortSetter helper( &dc );
1748
1749 if ( !drawMetalTheme || !minimumUmaAvailable )
1750 {
1751 Rect toolbarrect = { dc.YLOG2DEVMAC(0), dc.XLOG2DEVMAC(0),
1752 dc.YLOG2DEVMAC(h), dc.XLOG2DEVMAC(w) };
1753
1754 #if 0
1755 if ( toolbarrect.left < 0 )
1756 toolbarrect.left = 0;
1757 if ( toolbarrect.top < 0 )
1758 toolbarrect.top = 0;
1759 #endif
1760
1761 UMADrawThemePlacard( &toolbarrect, IsEnabled() ? kThemeStateActive : kThemeStateInactive );
1762 }
1763 else
1764 {
1765 #if TARGET_API_MAC_OSX
1766 HIRect hiToolbarrect = CGRectMake(
1767 dc.YLOG2DEVMAC(0), dc.XLOG2DEVMAC(0),
1768 dc.YLOG2DEVREL(h), dc.XLOG2DEVREL(w) );
1769 CGContextRef cgContext;
1770 Rect bounds;
1771
1772 GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
1773 QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
1774
1775 CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
1776 CGContextScaleCTM( cgContext, 1, -1 );
1777
1778 HIThemeBackgroundDrawInfo drawInfo;
1779 drawInfo.version = 0;
1780 drawInfo.state = kThemeStateActive;
1781 drawInfo.kind = kThemeBackgroundMetal;
1782 HIThemeApplyBackground( &hiToolbarrect, &drawInfo, cgContext, kHIThemeOrientationNormal );
1783
1784 #ifndef __LP64__
1785 QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
1786 #endif
1787 #endif
1788 }
1789 }
1790 #endif
1791
1792 event.Skip();
1793 }
1794
1795 #endif // wxUSE_TOOLBAR