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