]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/toolbar.cpp
removed extra membersections (patch 1702329)
[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
70
71 class wxToolBarTool : public wxToolBarToolBase
72 {
73 public:
74 wxToolBarTool(
75 wxToolBar *tbar,
76 int id,
77 const wxString& label,
78 const wxBitmap& bmpNormal,
79 const wxBitmap& bmpDisabled,
80 wxItemKind kind,
81 wxObject *clientData,
82 const wxString& shortHelp,
83 const wxString& longHelp );
84
85 wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
86 : wxToolBarToolBase(tbar, control, label)
87 {
88 Init();
89 if (control != NULL)
90 SetControlHandle( (ControlRef) control->GetHandle() );
91 }
92
93 virtual ~wxToolBarTool()
94 {
95 ClearControl();
96 }
97
98 WXWidget GetControlHandle()
99 {
100 return (WXWidget) m_controlHandle;
101 }
102
103 void SetControlHandle( ControlRef handle )
104 {
105 m_controlHandle = handle;
106 }
107
108 void SetPosition( const wxPoint& position );
109
110 void ClearControl()
111 {
112 if ( m_controlHandle )
113 {
114 if ( !IsControl() )
115 DisposeControl( m_controlHandle );
116 else
117 {
118 // the embedded control is not under the responsibility of the tool, it will be disposed of in the
119 // proper wxControl destructor
120 wxASSERT( IsValidControlHandle(GetControl()->GetPeer()->GetControlRef() )) ;
121 }
122 m_controlHandle = NULL ;
123 }
124 m_control = NULL;
125
126 #if wxMAC_USE_NATIVE_TOOLBAR
127 if ( m_toolbarItemRef )
128 {
129 CFIndex count = CFGetRetainCount( m_toolbarItemRef ) ;
130 wxASSERT_MSG( count == 1 , wxT("Reference Count of native tool was not 1 in wxToolBarTool destructor") );
131 wxTheApp->MacAddToAutorelease(m_toolbarItemRef);
132 CFRelease(m_toolbarItemRef);
133 m_toolbarItemRef = NULL;
134 }
135 #endif
136 }
137
138 wxSize GetSize() const
139 {
140 wxSize curSize;
141
142 if ( IsControl() )
143 {
144 curSize = GetControl()->GetSize();
145 }
146 else if ( IsButton() )
147 {
148 curSize = GetToolBar()->GetToolSize();
149 }
150 else
151 {
152 // separator size
153 curSize = GetToolBar()->GetToolSize();
154 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
155 curSize.y /= 4;
156 else
157 curSize.x /= 4;
158 }
159
160 return curSize;
161 }
162
163 wxPoint GetPosition() const
164 {
165 return wxPoint( m_x, m_y );
166 }
167
168 bool DoEnable( bool enable );
169
170 void UpdateToggleImage( bool toggle );
171
172 #if wxMAC_USE_NATIVE_TOOLBAR
173 void SetToolbarItemRef( HIToolbarItemRef ref )
174 {
175 if ( m_controlHandle )
176 HideControl( m_controlHandle );
177 if ( m_toolbarItemRef )
178 CFRelease( m_toolbarItemRef );
179
180 m_toolbarItemRef = ref;
181 if ( m_toolbarItemRef )
182 {
183 wxFont f;
184 wxFontEncoding enc;
185 if ( GetToolBar() )
186 f = GetToolBar()->GetFont();
187 if ( f.IsOk() )
188 enc = f.GetEncoding();
189 else
190 enc = wxFont::GetDefaultEncoding();
191
192 HIToolbarItemSetHelpText(
193 m_toolbarItemRef,
194 wxMacCFStringHolder( GetShortHelp(), enc ),
195 wxMacCFStringHolder( GetLongHelp(), enc ) );
196 }
197 }
198
199 HIToolbarItemRef GetToolbarItemRef() const
200 {
201 return m_toolbarItemRef;
202 }
203
204 void SetIndex( CFIndex idx )
205 {
206 m_index = idx;
207 }
208
209 CFIndex GetIndex() const
210 {
211 return m_index;
212 }
213 #endif
214
215 private:
216 void Init()
217 {
218 m_controlHandle = NULL;
219
220 #if wxMAC_USE_NATIVE_TOOLBAR
221 m_toolbarItemRef = NULL;
222 m_index = -1;
223 #endif
224 }
225
226 ControlRef m_controlHandle;
227 wxCoord m_x;
228 wxCoord m_y;
229
230 #if wxMAC_USE_NATIVE_TOOLBAR
231 HIToolbarItemRef m_toolbarItemRef;
232 // position in its toolbar, -1 means not inserted
233 CFIndex m_index;
234 #endif
235 };
236
237 static const EventTypeSpec eventList[] =
238 {
239 { kEventClassControl, kEventControlHit },
240 #ifdef __WXMAC_OSX__
241 { kEventClassControl, kEventControlHitTest },
242 #endif
243 };
244
245 static pascal OSStatus wxMacToolBarToolControlEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
246 {
247 OSStatus result = eventNotHandledErr;
248 ControlRef controlRef;
249 wxMacCarbonEvent cEvent( event );
250
251 cEvent.GetParameter( kEventParamDirectObject, &controlRef );
252
253 switch ( GetEventKind( event ) )
254 {
255 case kEventControlHit:
256 {
257 wxToolBarTool *tbartool = (wxToolBarTool*)data;
258 wxToolBar *tbar = tbartool != NULL ? (wxToolBar*) (tbartool->GetToolBar()) : NULL;
259 if ((tbartool != NULL) && tbartool->CanBeToggled())
260 {
261 bool shouldToggle;
262
263 #ifdef __WXMAC_OSX__
264 shouldToggle = !tbartool->IsToggled();
265 #else
266 shouldToggle = (GetControl32BitValue( (ControlRef)(tbartool->GetControlHandle()) ) != 0);
267 #endif
268
269 tbar->ToggleTool( tbartool->GetId(), shouldToggle );
270 }
271
272 if (tbartool != NULL)
273 tbar->OnLeftClick( tbartool->GetId(), tbartool->IsToggled() );
274 result = noErr;
275 }
276 break;
277
278 #ifdef __WXMAC_OSX__
279 case kEventControlHitTest:
280 {
281 HIPoint pt = cEvent.GetParameter<HIPoint>(kEventParamMouseLocation);
282 HIRect rect;
283 HIViewGetBounds( controlRef, &rect );
284
285 ControlPartCode pc = kControlNoPart;
286 if ( CGRectContainsPoint( rect, pt ) )
287 pc = kControlIconPart;
288 cEvent.SetParameter( kEventParamControlPart, typeControlPartCode, pc );
289 result = noErr;
290 }
291 break;
292 #endif
293
294 default:
295 break;
296 }
297
298 return result;
299 }
300
301 static pascal OSStatus wxMacToolBarToolEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
302 {
303 OSStatus result = eventNotHandledErr;
304
305 switch ( GetEventClass( event ) )
306 {
307 case kEventClassControl:
308 result = wxMacToolBarToolControlEventHandler( handler, event, data );
309 break;
310
311 default:
312 break;
313 }
314
315 return result;
316 }
317
318 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacToolBarToolEventHandler )
319
320 #if wxMAC_USE_NATIVE_TOOLBAR
321
322 static const EventTypeSpec toolBarEventList[] =
323 {
324 { kEventClassToolbarItem, kEventToolbarItemPerformAction },
325 };
326
327 static pascal OSStatus wxMacToolBarCommandEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
328 {
329 OSStatus result = eventNotHandledErr;
330
331 switch ( GetEventKind( event ) )
332 {
333 case kEventToolbarItemPerformAction:
334 {
335 wxToolBarTool* tbartool = (wxToolBarTool*) data;
336 if ( tbartool != NULL )
337 {
338 wxToolBar *tbar = (wxToolBar*)(tbartool->GetToolBar());
339 int toolID = tbartool->GetId();
340
341 if ( tbartool->CanBeToggled() )
342 {
343 if ( tbar != NULL )
344 tbar->ToggleTool(toolID, !tbartool->IsToggled() );
345 }
346
347 if ( tbar != NULL )
348 tbar->OnLeftClick( toolID, tbartool->IsToggled() );
349 result = noErr;
350 }
351 }
352 break;
353
354 default:
355 break;
356 }
357
358 return result;
359 }
360
361 static pascal OSStatus wxMacToolBarEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
362 {
363 OSStatus result = eventNotHandledErr;
364
365 switch ( GetEventClass( event ) )
366 {
367 case kEventClassToolbarItem:
368 result = wxMacToolBarCommandEventHandler( handler, event, data );
369 break;
370
371 default:
372 break;
373 }
374
375 return result;
376 }
377
378 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacToolBarEventHandler )
379
380 #endif
381
382 bool wxToolBarTool::DoEnable( bool enable )
383 {
384 if ( IsControl() )
385 {
386 GetControl()->Enable( enable );
387 }
388 else if ( IsButton() )
389 {
390 #if wxMAC_USE_NATIVE_TOOLBAR
391 if ( m_toolbarItemRef != NULL )
392 HIToolbarItemSetEnabled( m_toolbarItemRef, enable );
393 #endif
394
395 if ( m_controlHandle != NULL )
396 {
397 #if TARGET_API_MAC_OSX
398 if ( enable )
399 EnableControl( m_controlHandle );
400 else
401 DisableControl( m_controlHandle );
402 #else
403 if ( enable )
404 ActivateControl( m_controlHandle );
405 else
406 DeactivateControl( m_controlHandle );
407 #endif
408 }
409 }
410
411 return true;
412 }
413
414 void wxToolBarTool::SetPosition( const wxPoint& position )
415 {
416 m_x = position.x;
417 m_y = position.y;
418
419 int mac_x = position.x;
420 int mac_y = position.y;
421
422 if ( IsButton() )
423 {
424 Rect contrlRect;
425 GetControlBounds( m_controlHandle, &contrlRect );
426 int former_mac_x = contrlRect.left;
427 int former_mac_y = contrlRect.top;
428 GetToolBar()->GetToolSize();
429
430 if ( mac_x != former_mac_x || mac_y != former_mac_y )
431 {
432 UMAMoveControl( m_controlHandle, mac_x, mac_y );
433 }
434 }
435 else if ( IsControl() )
436 {
437 // embedded native controls are moved by the OS
438 #if wxMAC_USE_NATIVE_TOOLBAR
439 if ( ((wxToolBar*)GetToolBar())->MacWantsNativeToolbar() == false )
440 #endif
441 {
442 GetControl()->Move( position );
443 }
444 }
445 else
446 {
447 // separator
448 #ifdef __WXMAC_OSX__
449 Rect contrlRect;
450 GetControlBounds( m_controlHandle, &contrlRect );
451 int former_mac_x = contrlRect.left;
452 int former_mac_y = contrlRect.top;
453
454 if ( mac_x != former_mac_x || mac_y != former_mac_y )
455 UMAMoveControl( m_controlHandle, mac_x, mac_y );
456 #endif
457 }
458 }
459
460 void wxToolBarTool::UpdateToggleImage( bool toggle )
461 {
462 #ifdef __WXMAC_OSX__
463 if ( toggle )
464 {
465 int w = m_bmpNormal.GetWidth();
466 int h = m_bmpNormal.GetHeight();
467 wxBitmap bmp( w, h );
468 wxMemoryDC dc;
469
470 dc.SelectObject( bmp );
471 dc.SetPen( wxPen(*wxBLACK) );
472 dc.SetBrush( wxBrush( *wxLIGHT_GREY ));
473 dc.DrawRectangle( 0, 0, w, h );
474 dc.DrawBitmap( m_bmpNormal, 0, 0, true );
475 dc.SelectObject( wxNullBitmap );
476 ControlButtonContentInfo info;
477 wxMacCreateBitmapButton( &info, bmp, kControlContentIconRef );
478 SetControlData( m_controlHandle, 0, kControlIconContentTag, sizeof(info), (Ptr)&info );
479 #if wxMAC_USE_NATIVE_TOOLBAR
480 if (m_toolbarItemRef != NULL)
481 {
482 HIToolbarItemSetIconRef( m_toolbarItemRef, info.u.iconRef );
483 }
484 #endif
485 wxMacReleaseBitmapButton( &info );
486 }
487 else
488 {
489 ControlButtonContentInfo info;
490 wxMacCreateBitmapButton( &info, m_bmpNormal, kControlContentIconRef );
491 SetControlData( m_controlHandle, 0, kControlIconContentTag, sizeof(info), (Ptr)&info );
492 #if wxMAC_USE_NATIVE_TOOLBAR
493 if (m_toolbarItemRef != NULL)
494 {
495 HIToolbarItemSetIconRef( m_toolbarItemRef, info.u.iconRef );
496 }
497 #endif
498 wxMacReleaseBitmapButton( &info );
499 }
500
501 IconTransformType transform = toggle ? kTransformSelected : kTransformNone;
502 SetControlData(
503 m_controlHandle, 0, kControlIconTransformTag,
504 sizeof(transform), (Ptr)&transform );
505 HIViewSetNeedsDisplay( m_controlHandle, true );
506
507 #else
508 ::SetControl32BitValue( m_controlHandle, toggle );
509 #endif
510 }
511
512 wxToolBarTool::wxToolBarTool(
513 wxToolBar *tbar,
514 int id,
515 const wxString& label,
516 const wxBitmap& bmpNormal,
517 const wxBitmap& bmpDisabled,
518 wxItemKind kind,
519 wxObject *clientData,
520 const wxString& shortHelp,
521 const wxString& longHelp )
522 :
523 wxToolBarToolBase(
524 tbar, id, label, bmpNormal, bmpDisabled, kind,
525 clientData, shortHelp, longHelp )
526 {
527 Init();
528 }
529
530 #pragma mark -
531 #pragma mark Toolbar Implementation
532
533 wxToolBarToolBase *wxToolBar::CreateTool(
534 int id,
535 const wxString& label,
536 const wxBitmap& bmpNormal,
537 const wxBitmap& bmpDisabled,
538 wxItemKind kind,
539 wxObject *clientData,
540 const wxString& shortHelp,
541 const wxString& longHelp )
542 {
543 return new wxToolBarTool(
544 this, id, label, bmpNormal, bmpDisabled, kind,
545 clientData, shortHelp, longHelp );
546 }
547
548 wxToolBarToolBase *
549 wxToolBar::CreateTool(wxControl *control, const wxString& label)
550 {
551 return new wxToolBarTool(this, control, label);
552 }
553
554 void wxToolBar::Init()
555 {
556 m_maxWidth = -1;
557 m_maxHeight = -1;
558 m_defaultWidth = kwxMacToolBarToolDefaultWidth;
559 m_defaultHeight = kwxMacToolBarToolDefaultHeight;
560
561 #if wxMAC_USE_NATIVE_TOOLBAR
562 m_macHIToolbarRef = NULL;
563 m_macUsesNativeToolbar = false;
564 #endif
565 }
566
567 #define kControlToolbarItemClassID CFSTR( "org.wxwidgets.controltoolbaritem" )
568
569 const EventTypeSpec kEvents[] =
570 {
571 { kEventClassHIObject, kEventHIObjectConstruct },
572 { kEventClassHIObject, kEventHIObjectInitialize },
573 { kEventClassHIObject, kEventHIObjectDestruct },
574
575 { kEventClassToolbarItem, kEventToolbarItemCreateCustomView }
576 };
577
578 const EventTypeSpec kViewEvents[] =
579 {
580 { kEventClassControl, kEventControlGetSizeConstraints }
581 };
582
583 struct ControlToolbarItem
584 {
585 HIToolbarItemRef toolbarItem;
586 HIViewRef viewRef;
587 wxSize lastValidSize ;
588 };
589
590 static pascal OSStatus ControlToolbarItemHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
591 {
592 OSStatus result = eventNotHandledErr;
593 ControlToolbarItem* object = (ControlToolbarItem*)inUserData;
594
595 switch ( GetEventClass( inEvent ) )
596 {
597 case kEventClassHIObject:
598 switch ( GetEventKind( inEvent ) )
599 {
600 case kEventHIObjectConstruct:
601 {
602 HIObjectRef toolbarItem;
603 ControlToolbarItem* item;
604
605 GetEventParameter( inEvent, kEventParamHIObjectInstance, typeHIObjectRef, NULL,
606 sizeof( HIObjectRef ), NULL, &toolbarItem );
607
608 item = (ControlToolbarItem*) malloc(sizeof(ControlToolbarItem)) ;
609 item->toolbarItem = toolbarItem ;
610 item->lastValidSize = wxSize(-1,-1);
611 item->viewRef = NULL ;
612
613 SetEventParameter( inEvent, kEventParamHIObjectInstance, typeVoidPtr, sizeof( void * ), &item );
614
615 result = noErr ;
616 }
617 break;
618
619 case kEventHIObjectInitialize:
620 result = CallNextEventHandler( inCallRef, inEvent );
621 if ( result == noErr )
622 {
623 CFDataRef data;
624 GetEventParameter( inEvent, kEventParamToolbarItemConfigData, typeCFTypeRef, NULL,
625 sizeof( CFTypeRef ), NULL, &data );
626
627 HIViewRef viewRef ;
628
629 wxASSERT_MSG( CFDataGetLength( data ) == sizeof( viewRef ) , wxT("Illegal Data passed") ) ;
630 memcpy( &viewRef , CFDataGetBytePtr( data ) , sizeof( viewRef ) ) ;
631
632 object->viewRef = (HIViewRef) viewRef ;
633 // make sure we keep that control during our lifetime
634 CFRetain( object->viewRef ) ;
635
636 verify_noerr(InstallEventHandler( GetControlEventTarget( viewRef ), ControlToolbarItemHandler,
637 GetEventTypeCount( kViewEvents ), kViewEvents, object, NULL ));
638 result = noErr ;
639 }
640 break;
641
642 case kEventHIObjectDestruct:
643 {
644 HIViewRef viewRef = object->viewRef ;
645 wxASSERT( IsValidControlHandle(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 != NULL )
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 != NULL )
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 , wxT("Reference Count of native tool was not 3 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 , wxT("Reference Count of native tool was not 3 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 != NULL )
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 != NULL )
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 wxString errMsg = wxString::Format( wxT("wxToolBar::DoInsertTool - failure [%ld]"), (long)err );
1598 wxFAIL_MSG( errMsg.c_str() );
1599 }
1600
1601 return (err == noErr);
1602 }
1603
1604 void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
1605 {
1606 wxFAIL_MSG( wxT("not implemented") );
1607 }
1608
1609 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolbase)
1610 {
1611 wxToolBarTool* tool = wx_static_cast( wxToolBarTool*, toolbase );
1612 wxToolBarToolsList::compatibility_iterator node;
1613 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
1614 {
1615 wxToolBarToolBase *tool2 = node->GetData();
1616 if ( tool2 == tool )
1617 {
1618 // let node point to the next node in the list
1619 node = node->GetNext();
1620
1621 break;
1622 }
1623 }
1624
1625 wxSize sz = ((wxToolBarTool*)tool)->GetSize();
1626
1627 tool->Detach();
1628
1629 #if wxMAC_USE_NATIVE_TOOLBAR
1630 CFIndex removeIndex = tool->GetIndex();
1631 #endif
1632
1633 #if wxMAC_USE_NATIVE_TOOLBAR
1634 if ( removeIndex != -1 && m_macHIToolbarRef )
1635 {
1636 HIToolbarRemoveItemAtIndex( (HIToolbarRef) m_macHIToolbarRef, removeIndex );
1637 tool->SetIndex( -1 );
1638 }
1639 #endif
1640 switch ( tool->GetStyle() )
1641 {
1642 case wxTOOL_STYLE_CONTROL:
1643 if ( tool->GetControl() )
1644 tool->GetControl()->Destroy();
1645 break;
1646
1647 case wxTOOL_STYLE_BUTTON:
1648 case wxTOOL_STYLE_SEPARATOR:
1649 // nothing special
1650 break;
1651
1652 default:
1653 break;
1654 }
1655 tool->ClearControl();
1656
1657 // and finally reposition all the controls after this one
1658
1659 for ( /* node -> first after deleted */; node; node = node->GetNext() )
1660 {
1661 wxToolBarTool *tool2 = (wxToolBarTool*) node->GetData();
1662 wxPoint pt = tool2->GetPosition();
1663
1664 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1665 pt.y -= sz.y;
1666 else
1667 pt.x -= sz.x;
1668
1669 tool2->SetPosition( pt );
1670
1671 #if wxMAC_USE_NATIVE_TOOLBAR
1672 if ( removeIndex != -1 && tool2->GetIndex() > removeIndex )
1673 tool2->SetIndex( tool2->GetIndex() - 1 );
1674 #endif
1675 }
1676
1677 InvalidateBestSize();
1678
1679 return true;
1680 }
1681
1682 void wxToolBar::OnPaint(wxPaintEvent& event)
1683 {
1684 #if wxMAC_USE_NATIVE_TOOLBAR
1685 if ( m_macUsesNativeToolbar )
1686 {
1687 event.Skip(true);
1688 return;
1689 }
1690 #endif
1691
1692 wxPaintDC dc(this);
1693
1694 int w, h;
1695 GetSize( &w, &h );
1696
1697 bool drawMetalTheme = MacGetTopLevelWindow()->MacGetMetalAppearance();
1698 bool minimumUmaAvailable = (UMAGetSystemVersion() >= 0x1030);
1699
1700 #if wxMAC_USE_CORE_GRAPHICS && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
1701 if ( !drawMetalTheme && minimumUmaAvailable )
1702 {
1703 HIThemePlacardDrawInfo info;
1704 memset( &info, 0, sizeof(info) );
1705 info.version = 0;
1706 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive;
1707
1708 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef();
1709 HIRect rect = CGRectMake( 0, 0, w, h );
1710 HIThemeDrawPlacard( &rect, &info, cgContext, kHIThemeOrientationNormal );
1711 }
1712 else
1713 {
1714 // leave the background as it is (striped or metal)
1715 }
1716
1717 #else
1718
1719 const bool drawBorder = true;
1720
1721 if (drawBorder)
1722 {
1723 wxMacPortSetter helper( &dc );
1724
1725 if ( !drawMetalTheme || !minimumUmaAvailable )
1726 {
1727 Rect toolbarrect = { dc.YLOG2DEVMAC(0), dc.XLOG2DEVMAC(0),
1728 dc.YLOG2DEVMAC(h), dc.XLOG2DEVMAC(w) };
1729
1730 #if 0
1731 if ( toolbarrect.left < 0 )
1732 toolbarrect.left = 0;
1733 if ( toolbarrect.top < 0 )
1734 toolbarrect.top = 0;
1735 #endif
1736
1737 UMADrawThemePlacard( &toolbarrect, IsEnabled() ? kThemeStateActive : kThemeStateInactive );
1738 }
1739 else
1740 {
1741 #if TARGET_API_MAC_OSX
1742 HIRect hiToolbarrect = CGRectMake(
1743 dc.YLOG2DEVMAC(0), dc.XLOG2DEVMAC(0),
1744 dc.YLOG2DEVREL(h), dc.XLOG2DEVREL(w) );
1745 CGContextRef cgContext;
1746 Rect bounds;
1747
1748 GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
1749 QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
1750
1751 CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
1752 CGContextScaleCTM( cgContext, 1, -1 );
1753
1754 HIThemeBackgroundDrawInfo drawInfo;
1755 drawInfo.version = 0;
1756 drawInfo.state = kThemeStateActive;
1757 drawInfo.kind = kThemeBackgroundMetal;
1758 HIThemeApplyBackground( &hiToolbarrect, &drawInfo, cgContext, kHIThemeOrientationNormal );
1759
1760 #ifndef __LP64__
1761 QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
1762 #endif
1763 #endif
1764 }
1765 }
1766 #endif
1767
1768 event.Skip();
1769 }
1770
1771 #endif // wxUSE_TOOLBAR