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