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