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