]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/toolbar.cpp
Added missing URL attribute testing
[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 // Extra width to avoid edge of combobox being cut off
703 sz.x += 3;
704
705 HISize min, max;
706 min.width = max.width = sz.x ;
707 min.height = max.height = sz.y ;
708
709 result = SetEventParameter( inEvent, kEventParamMinimumSize, typeHISize,
710 sizeof( HISize ), &min );
711
712 result = SetEventParameter( inEvent, kEventParamMaximumSize, typeHISize,
713 sizeof( HISize ), &max );
714 result = noErr ;
715 }
716 }
717 break;
718 }
719 break;
720 }
721
722 return result;
723 }
724
725 void RegisterControlToolbarItemClass()
726 {
727 static bool sRegistered;
728
729 if ( !sRegistered )
730 {
731 HIObjectRegisterSubclass( kControlToolbarItemClassID, kHIToolbarItemClassID, 0,
732 ControlToolbarItemHandler, GetEventTypeCount( kEvents ), kEvents, 0, NULL );
733
734 sRegistered = true;
735 }
736 }
737
738 HIToolbarItemRef CreateControlToolbarItem(CFStringRef inIdentifier, CFTypeRef inConfigData)
739 {
740 RegisterControlToolbarItemClass();
741
742 OSStatus err;
743 EventRef event;
744 UInt32 options = kHIToolbarItemAllowDuplicates;
745 HIToolbarItemRef result = NULL;
746
747 err = CreateEvent( NULL, kEventClassHIObject, kEventHIObjectInitialize, GetCurrentEventTime(), 0, &event );
748 require_noerr( err, CantCreateEvent );
749
750 SetEventParameter( event, kEventParamAttributes, typeUInt32, sizeof( UInt32 ), &options );
751 SetEventParameter( event, kEventParamToolbarItemIdentifier, typeCFStringRef, sizeof( CFStringRef ), &inIdentifier );
752
753 if ( inConfigData )
754 SetEventParameter( event, kEventParamToolbarItemConfigData, typeCFTypeRef, sizeof( CFTypeRef ), &inConfigData );
755
756 err = HIObjectCreate( kControlToolbarItemClassID, event, (HIObjectRef*)&result );
757 check_noerr( err );
758
759 ReleaseEvent( event );
760 CantCreateEvent :
761 return result ;
762 }
763
764 #if wxMAC_USE_NATIVE_TOOLBAR
765 static const EventTypeSpec kToolbarEvents[] =
766 {
767 { kEventClassToolbar, kEventToolbarGetDefaultIdentifiers },
768 { kEventClassToolbar, kEventToolbarGetAllowedIdentifiers },
769 { kEventClassToolbar, kEventToolbarCreateItemWithIdentifier },
770 };
771
772 static OSStatus ToolbarDelegateHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
773 {
774 OSStatus result = eventNotHandledErr;
775 // Not yet needed
776 // wxToolBar* toolbar = (wxToolBar*) inUserData ;
777 CFMutableArrayRef array;
778
779 switch ( GetEventKind( inEvent ) )
780 {
781 case kEventToolbarGetDefaultIdentifiers:
782 {
783 GetEventParameter( inEvent, kEventParamMutableArray, typeCFMutableArrayRef, NULL,
784 sizeof( CFMutableArrayRef ), NULL, &array );
785 // not implemented yet
786 // GetToolbarDefaultItems( array );
787 result = noErr;
788 }
789 break;
790
791 case kEventToolbarGetAllowedIdentifiers:
792 {
793 GetEventParameter( inEvent, kEventParamMutableArray, typeCFMutableArrayRef, NULL,
794 sizeof( CFMutableArrayRef ), NULL, &array );
795 // not implemented yet
796 // GetToolbarAllowedItems( array );
797 result = noErr;
798 }
799 break;
800 case kEventToolbarCreateItemWithIdentifier:
801 {
802 HIToolbarItemRef item = NULL;
803 CFTypeRef data = NULL;
804 CFStringRef identifier = NULL ;
805
806 GetEventParameter( inEvent, kEventParamToolbarItemIdentifier, typeCFStringRef, NULL,
807 sizeof( CFStringRef ), NULL, &identifier );
808
809 GetEventParameter( inEvent, kEventParamToolbarItemConfigData, typeCFTypeRef, NULL,
810 sizeof( CFTypeRef ), NULL, &data );
811
812 if ( CFStringCompare( kControlToolbarItemClassID, identifier, kCFCompareBackwards ) == kCFCompareEqualTo )
813 {
814 item = CreateControlToolbarItem( kControlToolbarItemClassID, data );
815 if ( item )
816 {
817 SetEventParameter( inEvent, kEventParamToolbarItem, typeHIToolbarItemRef,
818 sizeof( HIToolbarItemRef ), &item );
819 result = noErr;
820 }
821 }
822
823 }
824 break;
825 }
826 return result ;
827 }
828 #endif // wxMAC_USE_NATIVE_TOOLBAR
829
830 // also for the toolbar we have the dual implementation:
831 // only when MacInstallNativeToolbar is called is the native toolbar set as the window toolbar
832
833 bool wxToolBar::Create(
834 wxWindow *parent,
835 wxWindowID id,
836 const wxPoint& pos,
837 const wxSize& size,
838 long style,
839 const wxString& name )
840 {
841 if ( !wxToolBarBase::Create( parent, id, pos, size, style, wxDefaultValidator, name ) )
842 return false;
843
844 FixupStyle();
845
846 OSStatus err = noErr;
847
848 #if wxMAC_USE_NATIVE_TOOLBAR
849 if (parent->IsKindOf(CLASSINFO(wxFrame)) && wxSystemOptions::GetOptionInt(wxT("mac.toolbar.no-native")) != 1)
850 {
851 wxString labelStr = wxString::Format( wxT("%xd"), (int)this );
852 err = HIToolbarCreate(
853 wxMacCFStringHolder( labelStr, wxFont::GetDefaultEncoding() ), 0,
854 (HIToolbarRef*) &m_macHIToolbarRef );
855
856 if (m_macHIToolbarRef != NULL)
857 {
858 InstallEventHandler( HIObjectGetEventTarget((HIToolbarRef)m_macHIToolbarRef ), ToolbarDelegateHandler,
859 GetEventTypeCount( kToolbarEvents ), kToolbarEvents, this, NULL );
860
861 HIToolbarDisplayMode mode = kHIToolbarDisplayModeDefault;
862 HIToolbarDisplaySize displaySize = kHIToolbarDisplaySizeSmall;
863
864 if ( style & wxTB_NOICONS )
865 mode = kHIToolbarDisplayModeLabelOnly;
866 else if ( style & wxTB_TEXT )
867 mode = kHIToolbarDisplayModeIconAndLabel;
868 else
869 mode = kHIToolbarDisplayModeIconOnly;
870
871 HIToolbarSetDisplayMode( (HIToolbarRef) m_macHIToolbarRef, mode );
872 HIToolbarSetDisplaySize( (HIToolbarRef) m_macHIToolbarRef, displaySize );
873 }
874 }
875 #endif // wxMAC_USE_NATIVE_TOOLBAR
876
877 return (err == noErr);
878 }
879
880 wxToolBar::~wxToolBar()
881 {
882 #if wxMAC_USE_NATIVE_TOOLBAR
883 if (m_macHIToolbarRef != NULL)
884 {
885 // if this is the installed toolbar, then deinstall it
886 if (m_macUsesNativeToolbar)
887 MacInstallNativeToolbar( false );
888
889 CFIndex count = CFGetRetainCount( m_macHIToolbarRef ) ;
890 wxASSERT_MSG( count == 1 , wxT("Reference Count of native control was not 1 in wxToolBar destructor") );
891
892 CFRelease( (HIToolbarRef)m_macHIToolbarRef );
893 m_macHIToolbarRef = NULL;
894 }
895 #endif
896 }
897
898 bool wxToolBar::Show( bool show )
899 {
900 WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
901 bool bResult = (tlw != NULL);
902
903 if (bResult)
904 {
905 #if wxMAC_USE_NATIVE_TOOLBAR
906 bool ownToolbarInstalled = false;
907 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
908 if (ownToolbarInstalled)
909 {
910 bResult = (IsWindowToolbarVisible( tlw ) != show);
911 if ( bResult )
912 ShowHideWindowToolbar( tlw, show, false );
913 }
914 else
915 bResult = wxToolBarBase::Show( show );
916 #else
917
918 bResult = wxToolBarBase::Show( show );
919 #endif
920 }
921
922 return bResult;
923 }
924
925 bool wxToolBar::IsShown() const
926 {
927 bool bResult;
928
929 #if wxMAC_USE_NATIVE_TOOLBAR
930 bool ownToolbarInstalled;
931
932 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
933 if (ownToolbarInstalled)
934 {
935 WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
936 bResult = IsWindowToolbarVisible( tlw );
937 }
938 else
939 bResult = wxToolBarBase::IsShown();
940 #else
941
942 bResult = wxToolBarBase::IsShown();
943 #endif
944
945 return bResult;
946 }
947
948 void wxToolBar::DoGetSize( int *width, int *height ) const
949 {
950 #if wxMAC_USE_NATIVE_TOOLBAR
951 Rect boundsR;
952 bool ownToolbarInstalled;
953
954 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
955 if ( ownToolbarInstalled )
956 {
957 // TODO: is this really a control ?
958 GetControlBounds( (ControlRef) m_macHIToolbarRef, &boundsR );
959 if ( width != NULL )
960 *width = boundsR.right - boundsR.left;
961 if ( height != NULL )
962 *height = boundsR.bottom - boundsR.top;
963 }
964 else
965 wxToolBarBase::DoGetSize( width, height );
966
967 #else
968 wxToolBarBase::DoGetSize( width, height );
969 #endif
970 }
971
972 wxSize wxToolBar::DoGetBestSize() const
973 {
974 int width, height;
975
976 DoGetSize( &width, &height );
977
978 return wxSize( width, height );
979 }
980
981 void wxToolBar::SetWindowStyleFlag( long style )
982 {
983 wxToolBarBase::SetWindowStyleFlag( style );
984
985 #if wxMAC_USE_NATIVE_TOOLBAR
986 if (m_macHIToolbarRef != NULL)
987 {
988 HIToolbarDisplayMode mode = kHIToolbarDisplayModeDefault;
989
990 if ( style & wxTB_NOICONS )
991 mode = kHIToolbarDisplayModeLabelOnly;
992 else if ( style & wxTB_TEXT )
993 mode = kHIToolbarDisplayModeIconAndLabel;
994 else
995 mode = kHIToolbarDisplayModeIconOnly;
996
997 HIToolbarSetDisplayMode( (HIToolbarRef) m_macHIToolbarRef, mode );
998 }
999 #endif
1000 }
1001
1002 #if wxMAC_USE_NATIVE_TOOLBAR
1003 bool wxToolBar::MacWantsNativeToolbar()
1004 {
1005 return m_macUsesNativeToolbar;
1006 }
1007
1008 bool wxToolBar::MacTopLevelHasNativeToolbar(bool *ownToolbarInstalled) const
1009 {
1010 bool bResultV = false;
1011
1012 if (ownToolbarInstalled != NULL)
1013 *ownToolbarInstalled = false;
1014
1015 WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
1016 if (tlw != NULL)
1017 {
1018 HIToolbarRef curToolbarRef = NULL;
1019 OSStatus err = GetWindowToolbar( tlw, &curToolbarRef );
1020 bResultV = ((err == noErr) && (curToolbarRef != NULL));
1021 if (bResultV && (ownToolbarInstalled != NULL))
1022 *ownToolbarInstalled = (curToolbarRef == m_macHIToolbarRef);
1023 }
1024
1025 return bResultV;
1026 }
1027
1028 bool wxToolBar::MacInstallNativeToolbar(bool usesNative)
1029 {
1030 bool bResult = false;
1031
1032 if (usesNative && (m_macHIToolbarRef == NULL))
1033 return bResult;
1034
1035 if (usesNative && ((GetWindowStyleFlag() & wxTB_VERTICAL) != 0))
1036 return bResult;
1037
1038 WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
1039 if (tlw == NULL)
1040 return bResult;
1041
1042 // check the existing toolbar
1043 HIToolbarRef curToolbarRef = NULL;
1044 OSStatus err = GetWindowToolbar( tlw, &curToolbarRef );
1045 if (err != noErr)
1046 curToolbarRef = NULL;
1047
1048 m_macUsesNativeToolbar = usesNative;
1049
1050 if (m_macUsesNativeToolbar)
1051 {
1052 // only install toolbar if there isn't one installed already
1053 if (curToolbarRef == NULL)
1054 {
1055 bResult = true;
1056
1057 SetWindowToolbar( tlw, (HIToolbarRef) m_macHIToolbarRef );
1058 ShowHideWindowToolbar( tlw, true, false );
1059 ChangeWindowAttributes( tlw, kWindowToolbarButtonAttribute, 0 );
1060 SetAutomaticControlDragTrackingEnabledForWindow( tlw, true );
1061
1062 Rect r = { 0, 0, 0, 0 };
1063 m_peer->SetRect( &r );
1064 SetSize( wxSIZE_AUTO_WIDTH, 0 );
1065 m_peer->SetVisibility( false, true );
1066 wxToolBarBase::Show( false );
1067 }
1068 }
1069 else
1070 {
1071 // only deinstall toolbar if this is the installed one
1072 if (m_macHIToolbarRef == curToolbarRef)
1073 {
1074 bResult = true;
1075
1076 ShowHideWindowToolbar( tlw, false, false );
1077 ChangeWindowAttributes( tlw, 0, kWindowToolbarButtonAttribute );
1078 SetWindowToolbar( tlw, NULL );
1079
1080 m_peer->SetVisibility( true, true );
1081 }
1082 }
1083
1084 if (bResult)
1085 InvalidateBestSize();
1086
1087 // wxLogDebug( wxT(" --> [%lx] - result [%s]"), (long)this, bResult ? wxT("T") : wxT("F") );
1088 return bResult;
1089 }
1090 #endif
1091
1092 bool wxToolBar::Realize()
1093 {
1094 if (m_tools.GetCount() == 0)
1095 return false;
1096
1097 int maxWidth = 0;
1098 int maxHeight = 0;
1099
1100 int maxToolWidth = 0;
1101 int maxToolHeight = 0;
1102
1103 int x = m_xMargin + kwxMacToolBarLeftMargin;
1104 int y = m_yMargin + kwxMacToolBarTopMargin;
1105
1106 int tw, th;
1107 GetSize( &tw, &th );
1108
1109 // find the maximum tool width and height
1110 wxToolBarTool *tool;
1111 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1112 while ( node )
1113 {
1114 tool = (wxToolBarTool *) node->GetData();
1115 if ( tool != NULL )
1116 {
1117 wxSize sz = tool->GetSize();
1118
1119 if ( sz.x > maxToolWidth )
1120 maxToolWidth = sz.x;
1121 if ( sz.y > maxToolHeight )
1122 maxToolHeight = sz.y;
1123 }
1124
1125 node = node->GetNext();
1126 }
1127
1128 bool lastIsRadio = false;
1129 bool curIsRadio = false;
1130
1131 #if wxMAC_USE_NATIVE_TOOLBAR
1132 CFIndex currentPosition = 0;
1133 bool insertAll = false;
1134
1135 HIToolbarRef refTB = (HIToolbarRef)m_macHIToolbarRef;
1136 #endif
1137
1138 node = m_tools.GetFirst();
1139 while ( node )
1140 {
1141 tool = (wxToolBarTool*) node->GetData();
1142 if ( tool == NULL )
1143 {
1144 node = node->GetNext();
1145 continue;
1146 }
1147
1148 // set tool position:
1149 // for the moment just perform a single row/column alignment
1150 wxSize cursize = tool->GetSize();
1151 if ( x + cursize.x > maxWidth )
1152 maxWidth = x + cursize.x;
1153 if ( y + cursize.y > maxHeight )
1154 maxHeight = y + cursize.y;
1155
1156 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1157 {
1158 int x1 = x + ( maxToolWidth - cursize.x ) / 2;
1159 tool->SetPosition( wxPoint(x1, y) );
1160 }
1161 else
1162 {
1163 int y1 = y + ( maxToolHeight - cursize.y ) / 2;
1164 tool->SetPosition( wxPoint(x, y1) );
1165 }
1166
1167 // update the item positioning state
1168 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1169 y += cursize.y + kwxMacToolSpacing;
1170 else
1171 x += cursize.x + kwxMacToolSpacing;
1172
1173 #if wxMAC_USE_NATIVE_TOOLBAR
1174 // install in native HIToolbar
1175 if ( refTB )
1176 {
1177 HIToolbarItemRef hiItemRef = tool->GetToolbarItemRef();
1178 if ( hiItemRef != NULL )
1179 {
1180 if ( insertAll || (tool->GetIndex() != currentPosition) )
1181 {
1182 OSStatus err = noErr;
1183 if ( !insertAll )
1184 {
1185 insertAll = true;
1186
1187 // if this is the first tool that gets newly inserted or repositioned
1188 // first remove all 'old' tools from here to the right, because of this
1189 // all following tools will have to be reinserted (insertAll).
1190 for ( wxToolBarToolsList::compatibility_iterator node2 = m_tools.GetLast();
1191 node2 != node;
1192 node2 = node2->GetPrevious() )
1193 {
1194 wxToolBarTool *tool2 = (wxToolBarTool*) node2->GetData();
1195
1196 const long idx = tool2->GetIndex();
1197 if ( idx != -1 )
1198 {
1199 if ( tool2->IsControl() )
1200 {
1201 CFIndex count = CFGetRetainCount( tool2->GetControl()->GetPeer()->GetControlRef() ) ;
1202 wxASSERT_MSG( count == 3 || count == 2 , wxT("Reference Count of native tool was illegal before removal") );
1203 wxASSERT( IsValidControlHandle(tool2->GetControl()->GetPeer()->GetControlRef() )) ;
1204 }
1205 err = HIToolbarRemoveItemAtIndex(refTB, idx);
1206 if ( err != noErr )
1207 {
1208 wxLogDebug(wxT("HIToolbarRemoveItemAtIndex(%ld) failed [%ld]"),
1209 idx, (long)err);
1210 }
1211 if ( tool2->IsControl() )
1212 {
1213 CFIndex count = CFGetRetainCount( tool2->GetControl()->GetPeer()->GetControlRef() ) ;
1214 wxASSERT_MSG( count == 2 , wxT("Reference Count of native tool was not 2 after removal") );
1215 wxASSERT( IsValidControlHandle(tool2->GetControl()->GetPeer()->GetControlRef() )) ;
1216 }
1217
1218 tool2->SetIndex(-1);
1219 }
1220 }
1221 }
1222
1223 err = HIToolbarInsertItemAtIndex( refTB, hiItemRef, currentPosition );
1224 if (err != noErr)
1225 {
1226 wxLogDebug( wxT("HIToolbarInsertItemAtIndex failed [%ld]"), (long)err );
1227 }
1228
1229 tool->SetIndex( currentPosition );
1230 if ( tool->IsControl() )
1231 {
1232 CFIndex count = CFGetRetainCount( tool->GetControl()->GetPeer()->GetControlRef() ) ;
1233 wxASSERT_MSG( count == 3 || count == 2, wxT("Reference Count of native tool was illegal after insertion") );
1234 wxASSERT( IsValidControlHandle(tool->GetControl()->GetPeer()->GetControlRef() )) ;
1235 }
1236 }
1237
1238 currentPosition++;
1239 }
1240 }
1241 #endif
1242
1243 // update radio button (and group) state
1244 lastIsRadio = curIsRadio;
1245 curIsRadio = ( tool->IsButton() && (tool->GetKind() == wxITEM_RADIO) );
1246
1247 if ( !curIsRadio )
1248 {
1249 if ( tool->IsToggled() )
1250 DoToggleTool( tool, true );
1251 }
1252 else
1253 {
1254 if ( !lastIsRadio )
1255 {
1256 if ( tool->Toggle( true ) )
1257 {
1258 DoToggleTool( tool, true );
1259 }
1260 }
1261 else if ( tool->IsToggled() )
1262 {
1263 if ( tool->IsToggled() )
1264 DoToggleTool( tool, true );
1265
1266 wxToolBarToolsList::compatibility_iterator nodePrev = node->GetPrevious();
1267 while ( nodePrev )
1268 {
1269 wxToolBarToolBase *toggleTool = nodePrev->GetData();
1270 if ( (toggleTool == NULL) || !toggleTool->IsButton() || (toggleTool->GetKind() != wxITEM_RADIO) )
1271 break;
1272
1273 if ( toggleTool->Toggle( false ) )
1274 DoToggleTool( toggleTool, false );
1275
1276 nodePrev = nodePrev->GetPrevious();
1277 }
1278 }
1279 }
1280
1281 node = node->GetNext();
1282 }
1283
1284 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
1285 {
1286 // if not set yet, only one row
1287 if ( m_maxRows <= 0 )
1288 SetRows( 1 );
1289
1290 m_minWidth = maxWidth;
1291 maxWidth = tw;
1292 maxHeight += m_yMargin + kwxMacToolBarTopMargin;
1293 m_minHeight = m_maxHeight = maxHeight;
1294 }
1295 else
1296 {
1297 // if not set yet, have one column
1298 if ( (GetToolsCount() > 0) && (m_maxRows <= 0) )
1299 SetRows( GetToolsCount() );
1300
1301 m_minHeight = maxHeight;
1302 maxHeight = th;
1303 maxWidth += m_xMargin + kwxMacToolBarLeftMargin;
1304 m_minWidth = m_maxWidth = maxWidth;
1305 }
1306
1307 #if 0
1308 // FIXME: should this be OSX-only?
1309 {
1310 bool wantNativeToolbar, ownToolbarInstalled;
1311
1312 // attempt to install the native toolbar
1313 wantNativeToolbar = ((GetWindowStyleFlag() & wxTB_VERTICAL) == 0);
1314 MacInstallNativeToolbar( wantNativeToolbar );
1315 (void)MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
1316 if (!ownToolbarInstalled)
1317 {
1318 SetSize( maxWidth, maxHeight );
1319 InvalidateBestSize();
1320 }
1321 }
1322 #else
1323 SetSize( maxWidth, maxHeight );
1324 InvalidateBestSize();
1325 #endif
1326
1327 SetInitialSize();
1328
1329 return true;
1330 }
1331
1332 void wxToolBar::SetToolBitmapSize(const wxSize& size)
1333 {
1334 m_defaultWidth = size.x + kwxMacToolBorder;
1335 m_defaultHeight = size.y + kwxMacToolBorder;
1336
1337 #if wxMAC_USE_NATIVE_TOOLBAR
1338 if (m_macHIToolbarRef != NULL)
1339 {
1340 int maxs = wxMax( size.x, size.y );
1341 HIToolbarDisplaySize sizeSpec;
1342 if ( maxs > 32 )
1343 sizeSpec = kHIToolbarDisplaySizeNormal;
1344 else if ( maxs > 24 )
1345 sizeSpec = kHIToolbarDisplaySizeDefault;
1346 else
1347 sizeSpec = kHIToolbarDisplaySizeSmall;
1348
1349 HIToolbarSetDisplaySize( (HIToolbarRef) m_macHIToolbarRef, sizeSpec );
1350 }
1351 #endif
1352 }
1353
1354 // The button size is bigger than the bitmap size
1355 wxSize wxToolBar::GetToolSize() const
1356 {
1357 return wxSize(m_defaultWidth + kwxMacToolBorder, m_defaultHeight + kwxMacToolBorder);
1358 }
1359
1360 void wxToolBar::SetRows(int nRows)
1361 {
1362 // avoid resizing the frame uselessly
1363 if ( nRows != m_maxRows )
1364 m_maxRows = nRows;
1365 }
1366
1367 void wxToolBar::MacSuperChangedPosition()
1368 {
1369 wxWindow::MacSuperChangedPosition();
1370
1371 #if wxMAC_USE_NATIVE_TOOLBAR
1372 if (! m_macUsesNativeToolbar )
1373 Realize();
1374 #else
1375
1376 Realize();
1377 #endif
1378 }
1379
1380 void wxToolBar::SetToolNormalBitmap( int id, const wxBitmap& bitmap )
1381 {
1382 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
1383 if ( tool )
1384 {
1385 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
1386
1387 tool->SetNormalBitmap(bitmap);
1388
1389 // a side-effect of the UpdateToggleImage function is that it always changes the bitmap used on the button.
1390 tool->UpdateToggleImage( tool->CanBeToggled() && tool->IsToggled() );
1391 }
1392 }
1393
1394 void wxToolBar::SetToolDisabledBitmap( int id, const wxBitmap& bitmap )
1395 {
1396 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
1397 if ( tool )
1398 {
1399 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
1400
1401 tool->SetDisabledBitmap(bitmap);
1402
1403 // TODO: what to do for this one?
1404 }
1405 }
1406
1407 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
1408 {
1409 wxToolBarTool *tool;
1410 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1411 while ( node )
1412 {
1413 tool = (wxToolBarTool *)node->GetData();
1414 if (tool != NULL)
1415 {
1416 wxRect2DInt r( tool->GetPosition(), tool->GetSize() );
1417 if ( r.Contains( wxPoint( x, y ) ) )
1418 return tool;
1419 }
1420
1421 node = node->GetNext();
1422 }
1423
1424 return (wxToolBarToolBase*)NULL;
1425 }
1426
1427 wxString wxToolBar::MacGetToolTipString( wxPoint &pt )
1428 {
1429 wxToolBarToolBase *tool = FindToolForPosition( pt.x, pt.y );
1430 if ( tool != NULL )
1431 return tool->GetShortHelp();
1432
1433 return wxEmptyString;
1434 }
1435
1436 void wxToolBar::DoEnableTool(wxToolBarToolBase *t, bool enable)
1437 {
1438 if ( t != NULL )
1439 ((wxToolBarTool*)t)->DoEnable( enable );
1440 }
1441
1442 void wxToolBar::DoToggleTool(wxToolBarToolBase *t, bool toggle)
1443 {
1444 wxToolBarTool *tool = (wxToolBarTool *)t;
1445 if ( ( tool != NULL ) && tool->IsButton() )
1446 tool->UpdateToggleImage( toggle );
1447 }
1448
1449 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
1450 {
1451 wxToolBarTool *tool = wx_static_cast( wxToolBarTool*, toolBase );
1452 if (tool == NULL)
1453 return false;
1454
1455 WindowRef window = (WindowRef) MacGetTopLevelWindowRef();
1456 wxSize toolSize = GetToolSize();
1457 Rect toolrect = { 0, 0, toolSize.y, toolSize.x };
1458 ControlRef controlHandle = NULL;
1459 OSStatus err = 0;
1460 tool->Attach( this );
1461
1462 #if wxMAC_USE_NATIVE_TOOLBAR
1463 HIToolbarItemRef item;
1464 #endif
1465
1466 switch (tool->GetStyle())
1467 {
1468 case wxTOOL_STYLE_SEPARATOR:
1469 {
1470 wxASSERT( tool->GetControlHandle() == NULL );
1471 toolSize.x /= 4;
1472 toolSize.y /= 4;
1473 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1474 toolrect.bottom = toolSize.y;
1475 else
1476 toolrect.right = toolSize.x;
1477
1478 // in flat style we need a visual separator
1479 #if wxMAC_USE_NATIVE_TOOLBAR
1480 if (m_macHIToolbarRef != NULL)
1481 {
1482 err = HIToolbarItemCreate(
1483 kHIToolbarSeparatorIdentifier,
1484 kHIToolbarItemCantBeRemoved | kHIToolbarItemIsSeparator | kHIToolbarItemAllowDuplicates,
1485 &item );
1486 if (err == noErr)
1487 tool->SetToolbarItemRef( item );
1488 }
1489 else
1490 err = noErr;
1491 #endif // wxMAC_USE_NATIVE_TOOLBAR
1492
1493 CreateSeparatorControl( window, &toolrect, &controlHandle );
1494 tool->SetControlHandle( controlHandle );
1495 }
1496 break;
1497
1498 case wxTOOL_STYLE_BUTTON:
1499 {
1500 wxASSERT( tool->GetControlHandle() == NULL );
1501 ControlButtonContentInfo info;
1502 wxMacCreateBitmapButton( &info, tool->GetNormalBitmap(), kControlContentIconRef );
1503
1504 if ( UMAGetSystemVersion() >= 0x1000)
1505 {
1506 CreateIconControl( window, &toolrect, &info, false, &controlHandle );
1507 }
1508 else
1509 {
1510 SInt16 behaviour = kControlBehaviorOffsetContents;
1511 if ( tool->CanBeToggled() )
1512 behaviour |= kControlBehaviorToggles;
1513 err = CreateBevelButtonControl( window,
1514 &toolrect, CFSTR(""), kControlBevelButtonNormalBevel,
1515 behaviour, &info, 0, 0, 0, &controlHandle );
1516 }
1517
1518 #if wxMAC_USE_NATIVE_TOOLBAR
1519 if (m_macHIToolbarRef != NULL)
1520 {
1521 wxString labelStr = wxString::Format(wxT("%xd"), (int)tool);
1522 err = HIToolbarItemCreate(
1523 wxMacCFStringHolder(labelStr, wxFont::GetDefaultEncoding()),
1524 kHIToolbarItemCantBeRemoved | kHIToolbarItemAnchoredLeft | kHIToolbarItemAllowDuplicates, &item );
1525 if (err == noErr)
1526 {
1527 InstallEventHandler(
1528 HIObjectGetEventTarget(item), GetwxMacToolBarEventHandlerUPP(),
1529 GetEventTypeCount(toolBarEventList), toolBarEventList, tool, NULL );
1530
1531 HIToolbarItemSetIconRef( item, info.u.iconRef );
1532 HIToolbarItemSetCommandID( item, kHIToolbarCommandPressAction );
1533 tool->SetToolbarItemRef( item );
1534 }
1535 }
1536 else
1537 err = noErr;
1538 #endif // wxMAC_USE_NATIVE_TOOLBAR
1539
1540 wxMacReleaseBitmapButton( &info );
1541
1542 #if 0
1543 SetBevelButtonTextPlacement( m_controlHandle, kControlBevelButtonPlaceBelowGraphic );
1544 UMASetControlTitle( m_controlHandle, label, wxFont::GetDefaultEncoding() );
1545 #endif
1546
1547 InstallControlEventHandler(
1548 (ControlRef) controlHandle, GetwxMacToolBarToolEventHandlerUPP(),
1549 GetEventTypeCount(eventList), eventList, tool, NULL );
1550
1551 tool->SetControlHandle( controlHandle );
1552 }
1553 break;
1554
1555 case wxTOOL_STYLE_CONTROL:
1556
1557 #if wxMAC_USE_NATIVE_TOOLBAR
1558 if (m_macHIToolbarRef != NULL)
1559 {
1560 wxCHECK_MSG( tool->GetControl(), false, _T("control must be non-NULL") );
1561
1562 HIViewRef viewRef = (HIViewRef) tool->GetControl()->GetHandle() ;
1563 CFDataRef data = CFDataCreate( kCFAllocatorDefault , (UInt8*) &viewRef , sizeof(viewRef) ) ;
1564 err = HIToolbarCreateItemWithIdentifier((HIToolbarRef) m_macHIToolbarRef,kControlToolbarItemClassID,
1565 data , &item ) ;
1566
1567 if (err == noErr)
1568 {
1569 tool->SetToolbarItemRef( item );
1570 }
1571 CFRelease( data ) ;
1572 }
1573 else
1574 {
1575 err = noErr;
1576 break;
1577 }
1578 #else
1579 // right now there's nothing to do here
1580 #endif
1581 break;
1582
1583 default:
1584 break;
1585 }
1586
1587 #if wxMAC_USE_NATIVE_TOOLBAR
1588 wxString label = tool->GetLabel();
1589 if (m_macHIToolbarRef && !label.empty() )
1590 {
1591 // strip mnemonics from the label for compatibility
1592 // with the usual labels in wxStaticText sense
1593 label = wxStripMenuCodes(label);
1594
1595 HIToolbarItemSetLabel(item,
1596 wxMacCFStringHolder(label, m_font.GetEncoding()));
1597 }
1598 #endif // wxMAC_USE_NATIVE_TOOLBAR
1599
1600 if ( err == noErr )
1601 {
1602 if ( controlHandle )
1603 {
1604 ControlRef container = (ControlRef) GetHandle();
1605 wxASSERT_MSG( container != NULL, wxT("No valid Mac container control") );
1606
1607 UMAShowControl( controlHandle );
1608 ::EmbedControl( controlHandle, container );
1609 }
1610
1611 if ( tool->CanBeToggled() && tool->IsToggled() )
1612 tool->UpdateToggleImage( true );
1613
1614 // nothing special to do here - we relayout in Realize() later
1615 InvalidateBestSize();
1616 }
1617 else
1618 {
1619 wxFAIL_MSG( wxString::Format( wxT("wxToolBar::DoInsertTool - failure [%ld]"), (long)err ) );
1620 }
1621
1622 return (err == noErr);
1623 }
1624
1625 void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
1626 {
1627 wxFAIL_MSG( wxT("not implemented") );
1628 }
1629
1630 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolbase)
1631 {
1632 wxToolBarTool* tool = wx_static_cast( wxToolBarTool*, toolbase );
1633 wxToolBarToolsList::compatibility_iterator node;
1634 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
1635 {
1636 wxToolBarToolBase *tool2 = node->GetData();
1637 if ( tool2 == tool )
1638 {
1639 // let node point to the next node in the list
1640 node = node->GetNext();
1641
1642 break;
1643 }
1644 }
1645
1646 wxSize sz = ((wxToolBarTool*)tool)->GetSize();
1647
1648 tool->Detach();
1649
1650 #if wxMAC_USE_NATIVE_TOOLBAR
1651 CFIndex removeIndex = tool->GetIndex();
1652 #endif
1653
1654 #if wxMAC_USE_NATIVE_TOOLBAR
1655 if (m_macHIToolbarRef != NULL)
1656 {
1657 if ( removeIndex != -1 && m_macHIToolbarRef )
1658 {
1659 HIToolbarRemoveItemAtIndex( (HIToolbarRef) m_macHIToolbarRef, removeIndex );
1660 tool->SetIndex( -1 );
1661 }
1662 }
1663 #endif
1664 switch ( tool->GetStyle() )
1665 {
1666 case wxTOOL_STYLE_CONTROL:
1667 if ( tool->GetControl() )
1668 tool->GetControl()->Destroy();
1669 break;
1670
1671 case wxTOOL_STYLE_BUTTON:
1672 case wxTOOL_STYLE_SEPARATOR:
1673 // nothing special
1674 break;
1675
1676 default:
1677 break;
1678 }
1679 tool->ClearControl();
1680
1681 // and finally reposition all the controls after this one
1682
1683 for ( /* node -> first after deleted */; node; node = node->GetNext() )
1684 {
1685 wxToolBarTool *tool2 = (wxToolBarTool*) node->GetData();
1686 wxPoint pt = tool2->GetPosition();
1687
1688 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1689 pt.y -= sz.y;
1690 else
1691 pt.x -= sz.x;
1692
1693 tool2->SetPosition( pt );
1694
1695 #if wxMAC_USE_NATIVE_TOOLBAR
1696 if (m_macHIToolbarRef != NULL)
1697 {
1698 if ( removeIndex != -1 && tool2->GetIndex() > removeIndex )
1699 tool2->SetIndex( tool2->GetIndex() - 1 );
1700 }
1701 #endif
1702 }
1703
1704 InvalidateBestSize();
1705
1706 return true;
1707 }
1708
1709 void wxToolBar::OnPaint(wxPaintEvent& event)
1710 {
1711 #if wxMAC_USE_NATIVE_TOOLBAR
1712 if ( m_macUsesNativeToolbar )
1713 {
1714 event.Skip(true);
1715 return;
1716 }
1717 #endif
1718
1719 wxPaintDC dc(this);
1720
1721 int w, h;
1722 GetSize( &w, &h );
1723
1724 bool drawMetalTheme = MacGetTopLevelWindow()->MacGetMetalAppearance();
1725 bool minimumUmaAvailable = (UMAGetSystemVersion() >= 0x1030);
1726
1727 #if wxMAC_USE_CORE_GRAPHICS && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
1728 if ( !drawMetalTheme && minimumUmaAvailable )
1729 {
1730 HIThemePlacardDrawInfo info;
1731 memset( &info, 0, sizeof(info) );
1732 info.version = 0;
1733 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive;
1734
1735 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef();
1736 HIRect rect = CGRectMake( 0, 0, w, h );
1737 HIThemeDrawPlacard( &rect, &info, cgContext, kHIThemeOrientationNormal );
1738 }
1739 else
1740 {
1741 // leave the background as it is (striped or metal)
1742 }
1743
1744 #else
1745
1746 const bool drawBorder = true;
1747
1748 if (drawBorder)
1749 {
1750 wxMacPortSetter helper( &dc );
1751
1752 if ( !drawMetalTheme || !minimumUmaAvailable )
1753 {
1754 Rect toolbarrect = { dc.YLOG2DEVMAC(0), dc.XLOG2DEVMAC(0),
1755 dc.YLOG2DEVMAC(h), dc.XLOG2DEVMAC(w) };
1756
1757 #if 0
1758 if ( toolbarrect.left < 0 )
1759 toolbarrect.left = 0;
1760 if ( toolbarrect.top < 0 )
1761 toolbarrect.top = 0;
1762 #endif
1763
1764 UMADrawThemePlacard( &toolbarrect, IsEnabled() ? kThemeStateActive : kThemeStateInactive );
1765 }
1766 else
1767 {
1768 #if TARGET_API_MAC_OSX
1769 HIRect hiToolbarrect = CGRectMake(
1770 dc.YLOG2DEVMAC(0), dc.XLOG2DEVMAC(0),
1771 dc.YLOG2DEVREL(h), dc.XLOG2DEVREL(w) );
1772 CGContextRef cgContext;
1773 Rect bounds;
1774
1775 GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
1776 QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
1777
1778 CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
1779 CGContextScaleCTM( cgContext, 1, -1 );
1780
1781 HIThemeBackgroundDrawInfo drawInfo;
1782 drawInfo.version = 0;
1783 drawInfo.state = kThemeStateActive;
1784 drawInfo.kind = kThemeBackgroundMetal;
1785 HIThemeApplyBackground( &hiToolbarrect, &drawInfo, cgContext, kHIThemeOrientationNormal );
1786
1787 #ifndef __LP64__
1788 QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
1789 #endif
1790 #endif
1791 }
1792 }
1793 #endif
1794
1795 event.Skip();
1796 }
1797
1798 #endif // wxUSE_TOOLBAR