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