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