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