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