]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/toolbar.cpp
default button on older systems was not shown with OK, but empty, resulting in wxID_C...
[wxWidgets.git] / src / mac / carbon / toolbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/toolbar.cpp
3 // Purpose: wxToolBar
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #if wxUSE_TOOLBAR
15
16 #include "wx/wx.h"
17 #include "wx/bitmap.h"
18 #include "wx/toolbar.h"
19
20 #include "wx/mac/uma.h"
21 #include "wx/geometry.h"
22
23
24 #ifdef __WXMAC_OSX__
25 const short kwxMacToolBarToolDefaultWidth = 16;
26 const short kwxMacToolBarToolDefaultHeight = 16;
27 const short kwxMacToolBarTopMargin = 4;
28 const short kwxMacToolBarLeftMargin = 4;
29 const short kwxMacToolBorder = 0;
30 const short kwxMacToolSpacing = 6;
31 #else
32 const short kwxMacToolBarToolDefaultWidth = 24;
33 const short kwxMacToolBarToolDefaultHeight = 22;
34 const short kwxMacToolBarTopMargin = 2;
35 const short kwxMacToolBarLeftMargin = 2;
36 const short kwxMacToolBorder = 4;
37 const short kwxMacToolSpacing = 0;
38 #endif
39
40
41 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
42
43 BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
44 EVT_PAINT( wxToolBar::OnPaint )
45 END_EVENT_TABLE()
46
47
48 #pragma mark -
49 #pragma mark Tool Implementation
50
51
52 // ----------------------------------------------------------------------------
53 // private classes
54 // ----------------------------------------------------------------------------
55
56 // We have a dual implementation for each tool, ControlRef and HIToolbarItemRef
57
58 class wxToolBarTool : public wxToolBarToolBase
59 {
60 public:
61 wxToolBarTool(
62 wxToolBar *tbar,
63 int id,
64 const wxString& label,
65 const wxBitmap& bmpNormal,
66 const wxBitmap& bmpDisabled,
67 wxItemKind kind,
68 wxObject *clientData,
69 const wxString& shortHelp,
70 const wxString& longHelp );
71
72 wxToolBarTool(wxToolBar *tbar, wxControl *control)
73 : wxToolBarToolBase(tbar, control)
74 {
75 Init();
76 if (control != NULL)
77 SetControlHandle( (ControlRef) control->GetHandle() );
78 }
79
80 ~wxToolBarTool()
81 {
82 ClearControl();
83
84 #if wxMAC_USE_NATIVE_TOOLBAR
85 if ( m_toolbarItemRef )
86 CFRelease( m_toolbarItemRef );
87 #endif
88 }
89
90 WXWidget GetControlHandle()
91 {
92 return (WXWidget) m_controlHandle;
93 }
94
95 void SetControlHandle( ControlRef handle )
96 {
97 m_controlHandle = handle;
98 }
99
100 void SetPosition( const wxPoint& position );
101
102 void ClearControl()
103 {
104 m_control = NULL;
105 if ( m_controlHandle )
106 {
107 DisposeControl( m_controlHandle );
108 m_controlHandle = NULL ;
109 }
110
111 #if wxMAC_USE_NATIVE_TOOLBAR
112 m_toolbarItemRef = NULL;
113 #endif
114 }
115
116 wxSize GetSize() const
117 {
118 wxSize curSize;
119
120 if ( IsControl() )
121 {
122 curSize = GetControl()->GetSize();
123 }
124 else if ( IsButton() )
125 {
126 curSize = GetToolBar()->GetToolSize();
127 }
128 else
129 {
130 // separator size
131 curSize = GetToolBar()->GetToolSize();
132 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
133 curSize.y /= 4;
134 else
135 curSize.x /= 4;
136 }
137
138 return curSize;
139 }
140
141 wxPoint GetPosition() const
142 {
143 return wxPoint( m_x, m_y );
144 }
145
146 bool DoEnable( bool enable );
147
148 void UpdateToggleImage( bool toggle );
149
150 #if wxMAC_USE_NATIVE_TOOLBAR
151 void SetToolbarItemRef( HIToolbarItemRef ref )
152 {
153 if ( m_controlHandle )
154 HideControl( m_controlHandle );
155 if ( m_toolbarItemRef )
156 CFRelease( m_toolbarItemRef );
157
158 m_toolbarItemRef = ref;
159 if ( m_toolbarItemRef )
160 {
161 HIToolbarItemSetHelpText(
162 m_toolbarItemRef,
163 wxMacCFStringHolder( GetShortHelp(), GetToolBar()->GetFont().GetEncoding() ),
164 wxMacCFStringHolder( GetLongHelp(), GetToolBar()->GetFont().GetEncoding() ) );
165 }
166 }
167
168 HIToolbarItemRef GetToolbarItemRef() const
169 {
170 return m_toolbarItemRef;
171 }
172
173 void SetIndex( CFIndex idx )
174 {
175 m_index = idx;
176 }
177
178 CFIndex GetIndex() const
179 {
180 return m_index;
181 }
182 #endif
183
184 private:
185 void Init()
186 {
187 m_controlHandle = NULL;
188
189 #if wxMAC_USE_NATIVE_TOOLBAR
190 m_toolbarItemRef = NULL;
191 m_index = -1;
192 #endif
193 }
194
195 ControlRef m_controlHandle;
196 wxCoord m_x;
197 wxCoord m_y;
198
199 #if wxMAC_USE_NATIVE_TOOLBAR
200 HIToolbarItemRef m_toolbarItemRef;
201 // position in its toolbar, -1 means not inserted
202 CFIndex m_index;
203 #endif
204 };
205
206 static const EventTypeSpec eventList[] =
207 {
208 { kEventClassControl, kEventControlHit },
209 #ifdef __WXMAC_OSX__
210 { kEventClassControl, kEventControlHitTest },
211 #endif
212 };
213
214 static pascal OSStatus wxMacToolBarToolControlEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
215 {
216 OSStatus result = eventNotHandledErr;
217 ControlRef controlRef;
218 wxMacCarbonEvent cEvent( event );
219
220 cEvent.GetParameter( kEventParamDirectObject, &controlRef );
221
222 switch ( GetEventKind( event ) )
223 {
224 case kEventControlHit:
225 {
226 wxToolBarTool *tbartool = (wxToolBarTool*)data;
227 wxToolBar *tbar = tbartool != NULL ? (wxToolBar*) (tbartool->GetToolBar()) : NULL;
228 if ((tbartool != NULL) && tbartool->CanBeToggled())
229 {
230 bool shouldToggle;
231
232 #ifdef __WXMAC_OSX__
233 shouldToggle = !tbartool->IsToggled();
234 #else
235 shouldToggle = (GetControl32BitValue( (ControlRef)(tbartool->GetControlHandle()) ) != 0);
236 #endif
237
238 tbar->ToggleTool( tbartool->GetId(), shouldToggle );
239 }
240
241 if (tbartool != NULL)
242 tbar->OnLeftClick( tbartool->GetId(), tbartool->IsToggled() );
243 result = noErr;
244 }
245 break;
246
247 #ifdef __WXMAC_OSX__
248 case kEventControlHitTest:
249 {
250 HIPoint pt = cEvent.GetParameter<HIPoint>(kEventParamMouseLocation);
251 HIRect rect;
252 HIViewGetBounds( controlRef, &rect );
253
254 ControlPartCode pc = kControlNoPart;
255 if ( CGRectContainsPoint( rect, pt ) )
256 pc = kControlIconPart;
257 cEvent.SetParameter( kEventParamControlPart, typeControlPartCode, pc );
258 result = noErr;
259 }
260 break;
261 #endif
262
263 default:
264 break;
265 }
266
267 return result;
268 }
269
270 static pascal OSStatus wxMacToolBarToolEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
271 {
272 OSStatus result = eventNotHandledErr;
273
274 switch ( GetEventClass( event ) )
275 {
276 case kEventClassControl:
277 result = wxMacToolBarToolControlEventHandler( handler, event, data );
278 break;
279
280 default:
281 break;
282 }
283
284 return result;
285 }
286
287 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacToolBarToolEventHandler )
288
289 #if wxMAC_USE_NATIVE_TOOLBAR
290
291 static const EventTypeSpec toolBarEventList[] =
292 {
293 { kEventClassToolbarItem, kEventToolbarItemPerformAction },
294 };
295
296 static pascal OSStatus wxMacToolBarCommandEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
297 {
298 OSStatus result = eventNotHandledErr;
299
300 switch ( GetEventKind( event ) )
301 {
302 case kEventToolbarItemPerformAction:
303 {
304 wxToolBarTool* tbartool = (wxToolBarTool*) data;
305 if ( tbartool != NULL )
306 {
307 wxToolBar *tbar = (wxToolBar*)(tbartool->GetToolBar());
308 int toolID = tbartool->GetId();
309
310 if ( tbartool->CanBeToggled() )
311 {
312 if ( tbar != NULL )
313 tbar->ToggleTool(toolID, !tbartool->IsToggled() );
314 }
315
316 if ( tbar != NULL )
317 tbar->OnLeftClick( toolID, tbartool->IsToggled() );
318 result = noErr;
319 }
320 }
321 break;
322
323 default:
324 break;
325 }
326
327 return result;
328 }
329
330 static pascal OSStatus wxMacToolBarEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
331 {
332 OSStatus result = eventNotHandledErr;
333
334 switch ( GetEventClass( event ) )
335 {
336 case kEventClassToolbarItem:
337 result = wxMacToolBarCommandEventHandler( handler, event, data );
338 break;
339
340 default:
341 break;
342 }
343
344 return result;
345 }
346
347 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacToolBarEventHandler )
348
349 #endif
350
351 bool wxToolBarTool::DoEnable( bool enable )
352 {
353 if ( IsControl() )
354 {
355 GetControl()->Enable( enable );
356 }
357 else if ( IsButton() )
358 {
359 #if wxMAC_USE_NATIVE_TOOLBAR
360 if ( m_toolbarItemRef != NULL )
361 HIToolbarItemSetEnabled( m_toolbarItemRef, enable );
362 #endif
363
364 if ( m_controlHandle != NULL )
365 {
366 #if TARGET_API_MAC_OSX
367 if ( enable )
368 EnableControl( m_controlHandle );
369 else
370 DisableControl( m_controlHandle );
371 #else
372 if ( enable )
373 ActivateControl( m_controlHandle );
374 else
375 DeactivateControl( m_controlHandle );
376 #endif
377 }
378 }
379
380 return true;
381 }
382
383 void wxToolBarTool::SetPosition( const wxPoint& position )
384 {
385 m_x = position.x;
386 m_y = position.y;
387
388 int x, y;
389 x = y = 0;
390 int mac_x = position.x;
391 int mac_y = position.y;
392
393 if ( ! GetToolBar()->MacGetTopLevelWindow()->MacUsesCompositing() )
394 {
395 GetToolBar()->MacWindowToRootWindow( &x, &y );
396 mac_x += x;
397 mac_y += y;
398 }
399
400 if ( IsButton() )
401 {
402 Rect contrlRect;
403 GetControlBounds( m_controlHandle, &contrlRect );
404 int former_mac_x = contrlRect.left;
405 int former_mac_y = contrlRect.top;
406 GetToolBar()->GetToolSize();
407
408 if ( mac_x != former_mac_x || mac_y != former_mac_y )
409 {
410 UMAMoveControl( m_controlHandle, mac_x, mac_y );
411 }
412 }
413 else if ( IsControl() )
414 {
415 GetControl()->Move( position );
416 }
417 else
418 {
419 // separator
420 #ifdef __WXMAC_OSX__
421 Rect contrlRect;
422 GetControlBounds( m_controlHandle, &contrlRect );
423 int former_mac_x = contrlRect.left;
424 int former_mac_y = contrlRect.top;
425
426 if ( mac_x != former_mac_x || mac_y != former_mac_y )
427 UMAMoveControl( m_controlHandle, mac_x, mac_y );
428 #endif
429 }
430 }
431
432 void wxToolBarTool::UpdateToggleImage( bool toggle )
433 {
434 #if wxMAC_USE_NATIVE_TOOLBAR
435
436 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
437 #define kHIToolbarItemSelected (1 << 7)
438 #endif
439
440 // FIXME: this should be a OSX v10.4 runtime check
441 if (m_toolbarItemRef != NULL)
442 {
443 OptionBits addAttrs, removeAttrs;
444 OSStatus result;
445
446 if (toggle)
447 {
448 addAttrs = kHIToolbarItemSelected;
449 removeAttrs = kHIToolbarItemNoAttributes;
450 }
451 else
452 {
453 addAttrs = kHIToolbarItemNoAttributes;
454 removeAttrs = kHIToolbarItemSelected;
455 }
456
457 result = HIToolbarItemChangeAttributes( m_toolbarItemRef, addAttrs, removeAttrs );
458 }
459 #endif
460
461 #ifdef __WXMAC_OSX__
462 if ( toggle )
463 {
464 int w = m_bmpNormal.GetWidth();
465 int h = m_bmpNormal.GetHeight();
466 wxBitmap bmp( w, h );
467 wxMemoryDC dc;
468
469 dc.SelectObject( bmp );
470 dc.SetPen( wxNullPen );
471 dc.SetBackground( *wxWHITE );
472 dc.DrawRectangle( 0, 0, w, h );
473 dc.DrawBitmap( m_bmpNormal, 0, 0, true );
474 dc.SelectObject( wxNullBitmap );
475 ControlButtonContentInfo info;
476 wxMacCreateBitmapButton( &info, bmp );
477 SetControlData( m_controlHandle, 0, kControlIconContentTag, sizeof(info), (Ptr)&info );
478 wxMacReleaseBitmapButton( &info );
479 }
480 else
481 {
482 ControlButtonContentInfo info;
483 wxMacCreateBitmapButton( &info, m_bmpNormal );
484 SetControlData( m_controlHandle, 0, kControlIconContentTag, sizeof(info), (Ptr)&info );
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 #else
495 ::SetControl32BitValue( m_controlHandle, toggle );
496 #endif
497 }
498
499 wxToolBarTool::wxToolBarTool(
500 wxToolBar *tbar,
501 int id,
502 const wxString& label,
503 const wxBitmap& bmpNormal,
504 const wxBitmap& bmpDisabled,
505 wxItemKind kind,
506 wxObject *clientData,
507 const wxString& shortHelp,
508 const wxString& longHelp )
509 :
510 wxToolBarToolBase(
511 tbar, id, label, bmpNormal, bmpDisabled, kind,
512 clientData, shortHelp, longHelp )
513 {
514 Init();
515 }
516
517 #pragma mark -
518 #pragma mark Toolbar Implementation
519
520 wxToolBarToolBase *wxToolBar::CreateTool(
521 int id,
522 const wxString& label,
523 const wxBitmap& bmpNormal,
524 const wxBitmap& bmpDisabled,
525 wxItemKind kind,
526 wxObject *clientData,
527 const wxString& shortHelp,
528 const wxString& longHelp )
529 {
530 return new wxToolBarTool(
531 this, id, label, bmpNormal, bmpDisabled, kind,
532 clientData, shortHelp, longHelp );
533 }
534
535 wxToolBarToolBase * wxToolBar::CreateTool( wxControl *control )
536 {
537 return new wxToolBarTool( this, control );
538 }
539
540 void wxToolBar::Init()
541 {
542 m_maxWidth = -1;
543 m_maxHeight = -1;
544 m_defaultWidth = kwxMacToolBarToolDefaultWidth;
545 m_defaultHeight = kwxMacToolBarToolDefaultHeight;
546
547 #if wxMAC_USE_NATIVE_TOOLBAR
548 m_macHIToolbarRef = NULL;
549 m_macUsesNativeToolbar = false;
550 #endif
551 }
552
553 // also for the toolbar we have the dual implementation:
554 // only when MacInstallNativeToolbar is called is the native toolbar set as the window toolbar
555 //
556 bool wxToolBar::Create(
557 wxWindow *parent,
558 wxWindowID id,
559 const wxPoint& pos,
560 const wxSize& size,
561 long style,
562 const wxString& name )
563 {
564 if ( !wxToolBarBase::Create( parent, id, pos, size, style, wxDefaultValidator, name ) )
565 return false;
566
567 OSStatus err = noErr;
568
569 #if wxMAC_USE_NATIVE_TOOLBAR
570 wxString labelStr = wxString::Format( wxT("%xd"), (int)this );
571 err = HIToolbarCreate(
572 wxMacCFStringHolder( labelStr, wxFont::GetDefaultEncoding() ), 0,
573 (HIToolbarRef*) &m_macHIToolbarRef );
574
575 if (m_macHIToolbarRef != NULL)
576 {
577 HIToolbarDisplayMode mode = kHIToolbarDisplayModeDefault;
578 HIToolbarDisplaySize displaySize = kHIToolbarDisplaySizeSmall;
579
580 if ( style & wxTB_NOICONS )
581 mode = kHIToolbarDisplayModeLabelOnly;
582 else if ( style & wxTB_TEXT )
583 mode = kHIToolbarDisplayModeIconAndLabel;
584 else
585 mode = kHIToolbarDisplayModeIconOnly;
586
587 HIToolbarSetDisplayMode( (HIToolbarRef) m_macHIToolbarRef, mode );
588 HIToolbarSetDisplaySize( (HIToolbarRef) m_macHIToolbarRef, displaySize );
589 }
590 #endif
591
592 return (err == noErr);
593 }
594
595 wxToolBar::~wxToolBar()
596 {
597 #if wxMAC_USE_NATIVE_TOOLBAR
598 if (m_macHIToolbarRef != NULL)
599 {
600 // if this is the installed toolbar, then deinstall it
601 if (m_macUsesNativeToolbar)
602 MacInstallNativeToolbar( false );
603
604 CFRelease( (HIToolbarRef)m_macHIToolbarRef );
605 m_macHIToolbarRef = NULL;
606 }
607 #endif
608 }
609
610 bool wxToolBar::Show( bool show )
611 {
612 WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
613 bool bResult = (tlw != NULL);
614
615 if (bResult)
616 {
617 #if wxMAC_USE_NATIVE_TOOLBAR
618 bool ownToolbarInstalled = false;
619 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
620 if (ownToolbarInstalled)
621 {
622 bResult = (IsWindowToolbarVisible( tlw ) != show);
623 if ( bResult )
624 ShowHideWindowToolbar( tlw, show, false );
625 }
626 else
627 bResult = wxToolBarBase::Show( show );
628 #else
629
630 bResult = wxToolBarBase::Show( show );
631 #endif
632 }
633
634 return bResult;
635 }
636
637 bool wxToolBar::IsShown() const
638 {
639 bool bResult;
640
641 #if wxMAC_USE_NATIVE_TOOLBAR
642 bool ownToolbarInstalled;
643
644 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
645 if (ownToolbarInstalled)
646 {
647 WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
648 bResult = IsWindowToolbarVisible( tlw );
649 }
650 else
651 bResult = wxToolBarBase::IsShown();
652 #else
653
654 bResult = wxToolBarBase::IsShown();
655 #endif
656
657 return bResult;
658 }
659
660 void wxToolBar::DoGetSize( int *width, int *height ) const
661 {
662 #if wxMAC_USE_NATIVE_TOOLBAR
663 Rect boundsR;
664 bool ownToolbarInstalled;
665
666 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
667 if ( ownToolbarInstalled )
668 {
669 // TODO: is this really a control ?
670 GetControlBounds( (ControlRef) m_macHIToolbarRef, &boundsR );
671 if ( width != NULL )
672 *width = boundsR.right - boundsR.left;
673 if ( height != NULL )
674 *height = boundsR.bottom - boundsR.top;
675 }
676 else
677 wxToolBarBase::DoGetSize( width, height );
678
679 #else
680 wxToolBarBase::DoGetSize( width, height );
681 #endif
682 }
683
684 wxSize wxToolBar::DoGetBestSize() const
685 {
686 int width, height;
687
688 DoGetSize( &width, &height );
689
690 return wxSize( width, height );
691 }
692
693 void wxToolBar::SetWindowStyleFlag( long style )
694 {
695 wxToolBarBase::SetWindowStyleFlag( style );
696
697 #if wxMAC_USE_NATIVE_TOOLBAR
698 if (m_macHIToolbarRef != NULL)
699 {
700 HIToolbarDisplayMode mode = kHIToolbarDisplayModeDefault;
701
702 if ( style & wxTB_NOICONS )
703 mode = kHIToolbarDisplayModeLabelOnly;
704 else if ( style & wxTB_TEXT )
705 mode = kHIToolbarDisplayModeIconAndLabel;
706 else
707 mode = kHIToolbarDisplayModeIconOnly;
708
709 HIToolbarSetDisplayMode( (HIToolbarRef) m_macHIToolbarRef, mode );
710 }
711 #endif
712 }
713
714 #if wxMAC_USE_NATIVE_TOOLBAR
715 bool wxToolBar::MacWantsNativeToolbar()
716 {
717 return m_macUsesNativeToolbar;
718 }
719
720 bool wxToolBar::MacTopLevelHasNativeToolbar(bool *ownToolbarInstalled) const
721 {
722 bool bResultV = false;
723
724 if (ownToolbarInstalled != NULL)
725 *ownToolbarInstalled = false;
726
727 WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
728 if (tlw != NULL)
729 {
730 HIToolbarRef curToolbarRef = NULL;
731 OSStatus err = GetWindowToolbar( tlw, &curToolbarRef );
732 bResultV = ((err == noErr) && (curToolbarRef != NULL));
733 if (bResultV && (ownToolbarInstalled != NULL))
734 *ownToolbarInstalled = (curToolbarRef == m_macHIToolbarRef);
735 }
736
737 return bResultV;
738 }
739
740 bool wxToolBar::MacInstallNativeToolbar(bool usesNative)
741 {
742 bool bResult = false;
743
744 if (usesNative && (m_macHIToolbarRef == NULL))
745 return bResult;
746
747 if (usesNative && ((GetWindowStyleFlag() & wxTB_VERTICAL) != 0))
748 return bResult;
749
750 WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
751 if (tlw == NULL)
752 return bResult;
753
754 // check the existing toolbar
755 HIToolbarRef curToolbarRef = NULL;
756 OSStatus err = GetWindowToolbar( tlw, &curToolbarRef );
757 if (err != noErr)
758 curToolbarRef = NULL;
759
760 m_macUsesNativeToolbar = usesNative;
761
762 if (m_macUsesNativeToolbar)
763 {
764 // only install toolbar if there isn't one installed already
765 if (curToolbarRef == NULL)
766 {
767 bResult = true;
768
769 SetWindowToolbar( tlw, (HIToolbarRef) m_macHIToolbarRef );
770 ShowHideWindowToolbar( tlw, true, false );
771 ChangeWindowAttributes( tlw, kWindowToolbarButtonAttribute, 0 );
772 SetAutomaticControlDragTrackingEnabledForWindow( tlw, true );
773
774 Rect r = { 0, 0, 0, 0 };
775 m_peer->SetRect( &r );
776 SetSize( wxSIZE_AUTO_WIDTH, 0 );
777 m_peer->SetVisibility( false, true );
778 wxToolBarBase::Show( false );
779 }
780 }
781 else
782 {
783 // only deinstall toolbar if this is the installed one
784 if (m_macHIToolbarRef == curToolbarRef)
785 {
786 bResult = true;
787
788 ShowHideWindowToolbar( tlw, false, false );
789 ChangeWindowAttributes( tlw, 0, kWindowToolbarButtonAttribute );
790 SetWindowToolbar( tlw, NULL );
791
792 m_peer->SetVisibility( true, true );
793 }
794 }
795
796 if (bResult)
797 InvalidateBestSize();
798
799 // wxLogDebug( wxT(" --> [%lx] - result [%s]"), (long)this, bResult ? wxT("T") : wxT("F") );
800 return bResult;
801 }
802 #endif
803
804 bool wxToolBar::Realize()
805 {
806 if (m_tools.GetCount() == 0)
807 return false;
808
809 int maxWidth = 0;
810 int maxHeight = 0;
811
812 int maxToolWidth = 0;
813 int maxToolHeight = 0;
814
815 int x = m_xMargin + kwxMacToolBarLeftMargin;
816 int y = m_yMargin + kwxMacToolBarTopMargin;
817
818 int tw, th;
819 GetSize( &tw, &th );
820
821 // find the maximum tool width and height
822 wxToolBarTool *tool;
823 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
824 while ( node != NULL )
825 {
826 tool = (wxToolBarTool *) node->GetData();
827 if ( tool != NULL )
828 {
829 wxSize sz = tool->GetSize();
830
831 if ( sz.x > maxToolWidth )
832 maxToolWidth = sz.x;
833 if ( sz.y > maxToolHeight )
834 maxToolHeight = sz.y;
835 }
836
837 node = node->GetNext();
838 }
839
840 bool lastIsRadio = false;
841 bool curIsRadio = false;
842 bool setChoiceInGroup = false;
843
844 #if wxMAC_USE_NATIVE_TOOLBAR
845 CFIndex currentPosition = 0;
846 bool insertAll = false;
847 #endif
848
849 node = m_tools.GetFirst();
850 while ( node != NULL )
851 {
852 tool = (wxToolBarTool*) node->GetData();
853 if ( tool == NULL )
854 {
855 node = node->GetNext();
856 continue;
857 }
858
859 // set tool position:
860 // for the moment just perform a single row/column alignment
861 wxSize cursize = tool->GetSize();
862 if ( x + cursize.x > maxWidth )
863 maxWidth = x + cursize.x;
864 if ( y + cursize.y > maxHeight )
865 maxHeight = y + cursize.y;
866
867 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
868 {
869 int x1 = x + ( maxToolWidth - cursize.x ) / 2;
870 tool->SetPosition( wxPoint(x1, y) );
871 }
872 else
873 {
874 int y1 = y + ( maxToolHeight - cursize.y ) / 2;
875 tool->SetPosition( wxPoint(x, y1) );
876 }
877
878 // update the item positioning state
879 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
880 y += cursize.y + kwxMacToolSpacing;
881 else
882 x += cursize.x + kwxMacToolSpacing;
883
884 #if wxMAC_USE_NATIVE_TOOLBAR
885 // install in native HIToolbar
886 if ( m_macHIToolbarRef != NULL )
887 {
888 HIToolbarItemRef hiItemRef = tool->GetToolbarItemRef();
889 if ( hiItemRef != NULL )
890 {
891 if ( insertAll || (tool->GetIndex() != currentPosition) )
892 {
893 OSStatus err = noErr;
894 if ( !insertAll )
895 {
896 insertAll = true;
897
898 // if this is the first tool that gets newly inserted or repositioned
899 // first remove all 'old' tools from here to the right, because of this
900 // all following tools will have to be reinserted (insertAll). i = 100 because there's
901 // no way to determine how many there are in a toolbar, so just a high number :-(
902 for ( CFIndex i = 100; i >= currentPosition; --i )
903 {
904 err = HIToolbarRemoveItemAtIndex( (HIToolbarRef) m_macHIToolbarRef, i );
905 }
906
907 if (err != noErr)
908 {
909 wxString errMsg = wxString::Format( wxT("HIToolbarRemoveItemAtIndex failed [%ld]"), (long)err );
910 wxASSERT_MSG( 0, errMsg.c_str() );
911 }
912 }
913
914 err = HIToolbarInsertItemAtIndex( (HIToolbarRef) m_macHIToolbarRef, hiItemRef, currentPosition );
915 if (err != noErr)
916 {
917 wxString errMsg = wxString::Format( wxT("HIToolbarInsertItemAtIndex failed [%ld]"), (long)err );
918 wxASSERT_MSG( 0, errMsg.c_str() );
919 }
920
921 tool->SetIndex( currentPosition );
922 }
923
924 currentPosition++;
925 }
926 }
927 #endif
928
929 // update radio button (and group) state
930 lastIsRadio = curIsRadio;
931 curIsRadio = ( tool->IsButton() && (tool->GetKind() == wxITEM_RADIO) );
932
933 if ( !curIsRadio )
934 {
935 if ( tool->IsToggled() )
936 DoToggleTool( tool, true );
937
938 setChoiceInGroup = false;
939 }
940 else
941 {
942 if ( !lastIsRadio )
943 {
944 if ( tool->Toggle( true ) )
945 {
946 DoToggleTool( tool, true );
947 setChoiceInGroup = true;
948 }
949 }
950 else if ( tool->IsToggled() )
951 {
952 if ( tool->IsToggled() )
953 DoToggleTool( tool, true );
954
955 wxToolBarToolsList::compatibility_iterator nodePrev = node->GetPrevious();
956 while ( nodePrev != NULL )
957 {
958 wxToolBarToolBase *toggleTool = nodePrev->GetData();
959 if ( (toggleTool == NULL) || !toggleTool->IsButton() || (toggleTool->GetKind() != wxITEM_RADIO) )
960 break;
961
962 if ( toggleTool->Toggle( false ) )
963 DoToggleTool( toggleTool, false );
964
965 nodePrev = nodePrev->GetPrevious();
966 }
967 }
968 }
969
970 node = node->GetNext();
971 }
972
973 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
974 {
975 // if not set yet, only one row
976 if ( m_maxRows <= 0 )
977 SetRows( 1 );
978
979 m_minWidth = maxWidth;
980 maxWidth = tw;
981 maxHeight += m_yMargin + kwxMacToolBarTopMargin;
982 m_minHeight = m_maxHeight = maxHeight;
983 }
984 else
985 {
986 // if not set yet, have one column
987 if ( (GetToolsCount() > 0) && (m_maxRows <= 0) )
988 SetRows( GetToolsCount() );
989
990 m_minHeight = maxHeight;
991 maxHeight = th;
992 maxWidth += m_xMargin + kwxMacToolBarLeftMargin;
993 m_minWidth = m_maxWidth = maxWidth;
994 }
995
996 #if 0
997 // FIXME: should this be OSX-only?
998 {
999 bool wantNativeToolbar, ownToolbarInstalled;
1000
1001 // attempt to install the native toolbar
1002 wantNativeToolbar = ((GetWindowStyleFlag() & wxTB_VERTICAL) == 0);
1003 MacInstallNativeToolbar( wantNativeToolbar );
1004 (void)MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
1005 if (!ownToolbarInstalled)
1006 {
1007 SetSize( maxWidth, maxHeight );
1008 InvalidateBestSize();
1009 }
1010 }
1011 #else
1012 SetSize( maxWidth, maxHeight );
1013 InvalidateBestSize();
1014 #endif
1015
1016 SetBestFittingSize();
1017
1018 return true;
1019 }
1020
1021 void wxToolBar::SetToolBitmapSize(const wxSize& size)
1022 {
1023 m_defaultWidth = size.x + kwxMacToolBorder;
1024 m_defaultHeight = size.y + kwxMacToolBorder;
1025
1026 #if wxMAC_USE_NATIVE_TOOLBAR
1027 if (m_macHIToolbarRef != NULL)
1028 {
1029 int maxs = wxMax( size.x, size.y );
1030 HIToolbarDisplaySize sizeSpec;
1031 if ( maxs > 32 )
1032 sizeSpec = kHIToolbarDisplaySizeNormal;
1033 else if ( maxs > 24 )
1034 sizeSpec = kHIToolbarDisplaySizeDefault;
1035 else
1036 sizeSpec = kHIToolbarDisplaySizeSmall;
1037
1038 HIToolbarSetDisplaySize( (HIToolbarRef) m_macHIToolbarRef, sizeSpec );
1039 }
1040 #endif
1041 }
1042
1043 // The button size is bigger than the bitmap size
1044 wxSize wxToolBar::GetToolSize() const
1045 {
1046 return wxSize(m_defaultWidth + kwxMacToolBorder, m_defaultHeight + kwxMacToolBorder);
1047 }
1048
1049 void wxToolBar::SetRows(int nRows)
1050 {
1051 // avoid resizing the frame uselessly
1052 if ( nRows != m_maxRows )
1053 m_maxRows = nRows;
1054 }
1055
1056 void wxToolBar::MacSuperChangedPosition()
1057 {
1058 wxWindow::MacSuperChangedPosition();
1059
1060 #if wxMAC_USE_NATIVE_TOOLBAR
1061 if (! m_macUsesNativeToolbar )
1062 Realize();
1063 #else
1064
1065 Realize();
1066 #endif
1067 }
1068
1069 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
1070 {
1071 wxToolBarTool *tool;
1072 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1073 while ( node != NULL )
1074 {
1075 tool = (wxToolBarTool *)node->GetData();
1076 if (tool != NULL)
1077 {
1078 wxRect2DInt r( tool->GetPosition(), tool->GetSize() );
1079 if ( r.Contains( wxPoint( x, y ) ) )
1080 return tool;
1081 }
1082
1083 node = node->GetNext();
1084 }
1085
1086 return (wxToolBarToolBase*)NULL;
1087 }
1088
1089 wxString wxToolBar::MacGetToolTipString( wxPoint &pt )
1090 {
1091 wxToolBarToolBase *tool = FindToolForPosition( pt.x, pt.y );
1092 if ( tool != NULL )
1093 return tool->GetShortHelp();
1094
1095 return wxEmptyString;
1096 }
1097
1098 void wxToolBar::DoEnableTool(wxToolBarToolBase *t, bool enable)
1099 {
1100 if ( t != NULL )
1101 ((wxToolBarTool*)t)->DoEnable( enable );
1102 }
1103
1104 void wxToolBar::DoToggleTool(wxToolBarToolBase *t, bool toggle)
1105 {
1106 wxToolBarTool *tool = (wxToolBarTool *)t;
1107 if ( ( tool != NULL ) && tool->IsButton() )
1108 tool->UpdateToggleImage( toggle );
1109 }
1110
1111 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
1112 {
1113 wxToolBarTool *tool = wx_static_cast( wxToolBarTool*, toolBase );
1114 if (tool == NULL)
1115 return false;
1116
1117 WindowRef window = (WindowRef) MacGetTopLevelWindowRef();
1118 wxSize toolSize = GetToolSize();
1119 Rect toolrect = { 0, 0, toolSize.y, toolSize.x };
1120 ControlRef controlHandle = NULL;
1121 OSStatus err = 0;
1122
1123 switch (tool->GetStyle())
1124 {
1125 case wxTOOL_STYLE_SEPARATOR:
1126 {
1127 wxASSERT( tool->GetControlHandle() == NULL );
1128 toolSize.x /= 4;
1129 toolSize.y /= 4;
1130 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1131 toolrect.bottom = toolSize.y;
1132 else
1133 toolrect.right = toolSize.x;
1134
1135 #ifdef __WXMAC_OSX__
1136 // in flat style we need a visual separator
1137 #if wxMAC_USE_NATIVE_TOOLBAR
1138 HIToolbarItemRef item;
1139 err = HIToolbarItemCreate(
1140 kHIToolbarSeparatorIdentifier,
1141 kHIToolbarItemCantBeRemoved | kHIToolbarItemIsSeparator | kHIToolbarItemAllowDuplicates,
1142 &item );
1143 if (err == noErr)
1144 tool->SetToolbarItemRef( item );
1145 #endif
1146
1147 CreateSeparatorControl( window, &toolrect, &controlHandle );
1148 tool->SetControlHandle( controlHandle );
1149 #endif
1150 }
1151 break;
1152
1153 case wxTOOL_STYLE_BUTTON:
1154 {
1155 wxASSERT( tool->GetControlHandle() == NULL );
1156 ControlButtonContentInfo info;
1157 wxMacCreateBitmapButton( &info, tool->GetNormalBitmap(), kControlContentIconRef );
1158
1159 if ( UMAGetSystemVersion() >= 0x1000)
1160 {
1161 CreateIconControl( window, &toolrect, &info, false, &controlHandle );
1162 }
1163 else
1164 {
1165 SInt16 behaviour = kControlBehaviorOffsetContents;
1166 if ( tool->CanBeToggled() )
1167 behaviour |= kControlBehaviorToggles;
1168 err = CreateBevelButtonControl( window,
1169 &toolrect, CFSTR(""), kControlBevelButtonNormalBevel,
1170 behaviour, &info, 0, 0, 0, &controlHandle );
1171 }
1172
1173 #if wxMAC_USE_NATIVE_TOOLBAR
1174 HIToolbarItemRef item;
1175 wxString labelStr = wxString::Format(wxT("%xd"), (int)tool);
1176 err = HIToolbarItemCreate(
1177 wxMacCFStringHolder(labelStr, wxFont::GetDefaultEncoding()),
1178 kHIToolbarItemCantBeRemoved | kHIToolbarItemAnchoredLeft | kHIToolbarItemAllowDuplicates, &item );
1179 if (err == noErr)
1180 {
1181 InstallEventHandler(
1182 HIObjectGetEventTarget(item), GetwxMacToolBarEventHandlerUPP(),
1183 GetEventTypeCount(toolBarEventList), toolBarEventList, tool, NULL );
1184 HIToolbarItemSetLabel( item, wxMacCFStringHolder(tool->GetLabel(), m_font.GetEncoding()) );
1185 HIToolbarItemSetIconRef( item, info.u.iconRef );
1186 HIToolbarItemSetCommandID( item, kHIToolbarCommandPressAction );
1187 tool->SetToolbarItemRef( item );
1188 }
1189 #endif
1190
1191 wxMacReleaseBitmapButton( &info );
1192
1193 #if 0
1194 SetBevelButtonTextPlacement( m_controlHandle, kControlBevelButtonPlaceBelowGraphic );
1195 UMASetControlTitle( m_controlHandle, label, wxFont::GetDefaultEncoding() );
1196 #endif
1197
1198 InstallControlEventHandler(
1199 (ControlRef) controlHandle, GetwxMacToolBarToolEventHandlerUPP(),
1200 GetEventTypeCount(eventList), eventList, tool, NULL );
1201
1202 tool->SetControlHandle( controlHandle );
1203 }
1204 break;
1205
1206 case wxTOOL_STYLE_CONTROL:
1207 wxASSERT( tool->GetControl() != NULL );
1208
1209 #if 0 // wxMAC_USE_NATIVE_TOOLBAR
1210 // FIXME: doesn't work yet...
1211 {
1212 HIToolbarItemRef item;
1213 wxString labelStr = wxString::Format( wxT("%xd"), (int)tool );
1214 result = HIToolbarItemCreate(
1215 wxMacCFStringHolder( labelStr, wxFont::GetDefaultEncoding() ),
1216 kHIToolbarItemCantBeRemoved | kHIToolbarItemAnchoredLeft | kHIToolbarItemAllowDuplicates,
1217 &item );
1218 if ( result == noErr )
1219 {
1220 HIToolbarItemSetLabel( item, wxMacCFStringHolder( tool->GetLabel(), m_font.GetEncoding() ) );
1221 HIToolbarItemSetCommandID( item, tool->GetId() );
1222 tool->SetToolbarItemRef( item );
1223
1224 controlHandle = ( ControlRef ) tool->GetControlHandle();
1225 wxASSERT_MSG( controlHandle != NULL, wxT("NULL tool control") );
1226
1227 // FIXME: is this necessary ??
1228 ::GetControlBounds( controlHandle, &toolrect );
1229 UMAMoveControl( controlHandle, -toolrect.left, -toolrect.top );
1230
1231 // FIXME: is this necessary ??
1232 InstallControlEventHandler(
1233 controlHandle, GetwxMacToolBarToolEventHandlerUPP(),
1234 GetEventTypeCount(eventList), eventList, tool, NULL );
1235 }
1236 }
1237
1238 #else
1239 // FIXME: right now there's nothing to do here
1240 #endif
1241 break;
1242
1243 default:
1244 break;
1245 }
1246
1247 if ( err == noErr )
1248 {
1249 if ( controlHandle )
1250 {
1251 ControlRef container = (ControlRef) GetHandle();
1252 wxASSERT_MSG( container != NULL, wxT("No valid Mac container control") );
1253
1254 UMAShowControl( controlHandle );
1255 ::EmbedControl( controlHandle, container );
1256 }
1257
1258 if ( tool->CanBeToggled() && tool->IsToggled() )
1259 tool->UpdateToggleImage( true );
1260
1261 // nothing special to do here - we relayout in Realize() later
1262 tool->Attach( this );
1263 InvalidateBestSize();
1264 }
1265 else
1266 {
1267 wxString errMsg = wxString::Format( wxT("wxToolBar::DoInsertTool - failure [%ld]"), (long)err );
1268 wxASSERT_MSG( false, errMsg.c_str() );
1269 }
1270
1271 return (err == noErr);
1272 }
1273
1274 void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
1275 {
1276 wxFAIL_MSG( wxT("not implemented") );
1277 }
1278
1279 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolbase)
1280 {
1281 wxToolBarTool* tool = wx_static_cast( wxToolBarTool*, toolbase );
1282 wxToolBarToolsList::compatibility_iterator node;
1283 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
1284 {
1285 wxToolBarToolBase *tool2 = node->GetData();
1286 if ( tool2 == tool )
1287 {
1288 // let node point to the next node in the list
1289 node = node->GetNext();
1290
1291 break;
1292 }
1293 }
1294
1295 wxSize sz = ((wxToolBarTool*)tool)->GetSize();
1296
1297 tool->Detach();
1298
1299 #if wxMAC_USE_NATIVE_TOOLBAR
1300 CFIndex removeIndex = tool->GetIndex();
1301 #endif
1302
1303 switch ( tool->GetStyle() )
1304 {
1305 case wxTOOL_STYLE_CONTROL:
1306 {
1307 tool->GetControl()->Destroy();
1308 tool->ClearControl();
1309 }
1310 break;
1311
1312 case wxTOOL_STYLE_BUTTON:
1313 case wxTOOL_STYLE_SEPARATOR:
1314 if ( tool->GetControlHandle() )
1315 {
1316 #if wxMAC_USE_NATIVE_TOOLBAR
1317 if ( removeIndex != -1 && m_macHIToolbarRef )
1318 {
1319 HIToolbarRemoveItemAtIndex( (HIToolbarRef) m_macHIToolbarRef, removeIndex );
1320 tool->SetIndex( -1 );
1321 }
1322 #endif
1323
1324 tool->ClearControl();
1325 }
1326 break;
1327
1328 default:
1329 break;
1330 }
1331
1332 // and finally reposition all the controls after this one
1333
1334 for ( /* node -> first after deleted */; node; node = node->GetNext() )
1335 {
1336 wxToolBarTool *tool2 = (wxToolBarTool*) node->GetData();
1337 wxPoint pt = tool2->GetPosition();
1338
1339 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1340 pt.y -= sz.y;
1341 else
1342 pt.x -= sz.x;
1343
1344 tool2->SetPosition( pt );
1345
1346 #if wxMAC_USE_NATIVE_TOOLBAR
1347 if ( removeIndex != -1 && tool2->GetIndex() > removeIndex )
1348 tool2->SetIndex( tool2->GetIndex() - 1 );
1349 #endif
1350 }
1351
1352 InvalidateBestSize();
1353
1354 return true;
1355 }
1356
1357 void wxToolBar::OnPaint(wxPaintEvent& event)
1358 {
1359 #if wxMAC_USE_NATIVE_TOOLBAR
1360 if ( m_macUsesNativeToolbar )
1361 {
1362 event.Skip(true);
1363 return;
1364 }
1365 #endif
1366
1367 wxPaintDC dc(this);
1368
1369 int w, h;
1370 GetSize( &w, &h );
1371
1372 bool drawMetalTheme = MacGetTopLevelWindow()->MacGetMetalAppearance();
1373 bool minimumUmaAvailable = (UMAGetSystemVersion() >= 0x1030);
1374
1375 #if wxMAC_USE_CORE_GRAPHICS && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
1376 if ( !drawMetalTheme && minimumUmaAvailable )
1377 {
1378 HIThemePlacardDrawInfo info;
1379 memset( &info, 0, sizeof(info) );
1380 info.version = 0;
1381 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive;
1382
1383 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef();
1384 HIRect rect = CGRectMake( 0, 0, w, h );
1385 HIThemeDrawPlacard( &rect, &info, cgContext, kHIThemeOrientationNormal );
1386 }
1387 else
1388 {
1389 // leave the background as it is (striped or metal)
1390 }
1391
1392 #else
1393
1394 const bool drawBorder = true;
1395
1396 if (drawBorder)
1397 {
1398 wxMacPortSetter helper( &dc );
1399
1400 if ( !drawMetalTheme || !minimumUmaAvailable )
1401 {
1402 Rect toolbarrect = { dc.YLOG2DEVMAC(0), dc.XLOG2DEVMAC(0),
1403 dc.YLOG2DEVMAC(h), dc.XLOG2DEVMAC(w) };
1404
1405 #if 0
1406 if ( toolbarrect.left < 0 )
1407 toolbarrect.left = 0;
1408 if ( toolbarrect.top < 0 )
1409 toolbarrect.top = 0;
1410 #endif
1411
1412 UMADrawThemePlacard( &toolbarrect, IsEnabled() ? kThemeStateActive : kThemeStateInactive );
1413 }
1414 else
1415 {
1416 #if TARGET_API_MAC_OSX
1417 HIRect hiToolbarrect = CGRectMake(
1418 dc.YLOG2DEVMAC(0), dc.XLOG2DEVMAC(0),
1419 dc.YLOG2DEVREL(h), dc.XLOG2DEVREL(w) );
1420 CGContextRef cgContext;
1421 Rect bounds;
1422
1423 GetPortBounds( (CGrafPtr) dc.m_macPort, &bounds );
1424 QDBeginCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
1425
1426 CGContextTranslateCTM( cgContext, 0, bounds.bottom - bounds.top );
1427 CGContextScaleCTM( cgContext, 1, -1 );
1428
1429 HIThemeBackgroundDrawInfo drawInfo;
1430 drawInfo.version = 0;
1431 drawInfo.state = kThemeStateActive;
1432 drawInfo.kind = kThemeBackgroundMetal;
1433 HIThemeApplyBackground( &hiToolbarrect, &drawInfo, cgContext, kHIThemeOrientationNormal );
1434
1435 QDEndCGContext( (CGrafPtr) dc.m_macPort, &cgContext );
1436 #endif
1437 }
1438 }
1439 #endif
1440
1441 event.Skip();
1442 }
1443
1444 #endif // wxUSE_TOOLBAR