1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/cocoa/toolbar.mm
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
16 #include "wx/toolbar.h"
23 #include "wx/osx/private.h"
24 #include "wx/geometry.h"
25 #include "wx/sysopt.h"
27 const short kwxMacToolBarToolDefaultWidth = 16;
28 const short kwxMacToolBarToolDefaultHeight = 16;
29 const short kwxMacToolBarTopMargin = 4;
30 const short kwxMacToolBarLeftMargin = 4;
31 const short kwxMacToolBorder = 0;
32 const short kwxMacToolSpacing = 6;
34 BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
35 EVT_PAINT( wxToolBar::OnPaint )
40 #pragma mark Tool Implementation
42 // ----------------------------------------------------------------------------
44 // ----------------------------------------------------------------------------
48 @interface wxNSToolBarButton : NSButton
53 - (id)initWithFrame:(NSRect)frame;
54 - (void) clickedAction: (id) sender;
55 - (void)setImplementation: (wxToolBarTool *) theImplementation;
56 - (wxToolBarTool*) implementation;
61 // We have a dual implementation for each tool, WXWidget and NSToolbarItem*
63 // when embedding native controls in the native toolbar we must make sure the
64 // control does not get deleted behind our backs, so the retain count gets increased
65 // (after creation it is 1), first be the creation of the custom NSToolbarItem wrapper
66 // object, and second by the code 'creating' the custom HIView (which is the same as the
67 // already existing native control, therefore we just increase the ref count)
68 // when this view is removed from the native toolbar its count gets decremented again
69 // and when the HITooolbarItem wrapper object gets destroyed it is decremented as well
70 // so in the end the control lives with a refcount of one and can be disposed of by the
71 // wxControl code. For embedded controls on a non-native toolbar this ref count is less
72 // so we can only test against a range, not a specific value of the refcount.
74 class wxToolBarTool : public wxToolBarToolBase
80 const wxString& label,
81 const wxBitmap& bmpNormal,
82 const wxBitmap& bmpDisabled,
85 const wxString& shortHelp,
86 const wxString& longHelp );
88 wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
89 : wxToolBarToolBase(tbar, control, label)
93 SetControlHandle( (WXWidget) control->GetHandle() );
96 virtual ~wxToolBarTool()
101 WXWidget GetControlHandle()
103 return (WXWidget) m_controlHandle;
106 void SetControlHandle( WXWidget handle )
108 m_controlHandle = handle;
111 void SetPosition( const wxPoint& position );
115 if ( m_controlHandle )
119 [m_controlHandle retain];
123 // the embedded control is not under the responsibility of the tool, it gets disposed of in the
124 // proper wxControl destructor
126 m_controlHandle = NULL ;
129 #if wxOSX_USE_NATIVE_TOOLBAR
132 [m_toolbarItem release];
133 m_toolbarItem = NULL;
135 #endif // wxOSX_USE_NATIVE_TOOLBAR
138 wxSize GetSize() const
144 curSize = GetControl()->GetSize();
146 else if ( IsButton() )
148 // curSize = GetToolBar()->GetToolSize();
149 NSRect best = [(wxNSToolBarButton*)m_controlHandle frame];
150 curSize = wxSize(best.size.width, best.size.height);
155 curSize = GetToolBar()->GetToolSize();
156 if ( GetToolBar()->IsVertical() )
165 wxPoint GetPosition() const
167 return wxPoint( m_x, m_y );
170 bool Enable( bool enable );
174 void UpdateToggleImage( bool toggle );
178 wxString labelStr = wxStripMenuCodes(m_label);
179 wxCFStringRef l(labelStr, GetToolBarFontEncoding());
180 wxCFStringRef sh( GetShortHelp(), GetToolBarFontEncoding() );
181 #if wxOSX_USE_NATIVE_TOOLBAR
184 // strip mnemonics from the label for compatibility with the usual
185 // labels in wxStaticText sense
187 [m_toolbarItem setLabel:l.AsNSString()];
189 [m_toolbarItem setToolTip:sh.AsNSString()];
193 [(NSButton*)m_controlHandle setTitle:l.AsNSString()];
195 if ( m_controlHandle )
197 [m_controlHandle setToolTip:sh.AsNSString()];
203 wxToolBar *tbar = (wxToolBar*) GetToolBar();
208 shouldToggle = !IsToggled();
209 tbar->ToggleTool( GetId(), shouldToggle );
212 tbar->OnLeftClick( GetId(), IsToggled() );
215 #if wxOSX_USE_NATIVE_TOOLBAR
216 void SetToolbarItemRef( NSToolbarItem* ref )
218 if ( m_controlHandle )
219 [m_controlHandle setHidden:YES];
221 [m_toolbarItem release];
226 NSToolbarItem* GetToolbarItemRef() const
228 return m_toolbarItem;
231 void SetIndex( CFIndex idx )
236 CFIndex GetIndex() const
241 virtual void SetLabel(const wxString& label)
243 wxToolBarToolBase::SetLabel(label);
247 virtual bool SetShortHelp(const wxString& help)
249 if ( !wxToolBarToolBase::SetShortHelp(help) )
256 #endif // wxOSX_USE_NATIVE_TOOLBAR
259 #if wxOSX_USE_NATIVE_TOOLBAR
260 wxFontEncoding GetToolBarFontEncoding() const
264 f = GetToolBar()->GetFont();
265 return f.IsOk() ? f.GetEncoding() : wxFont::GetDefaultEncoding();
267 #endif // wxOSX_USE_NATIVE_TOOLBAR
271 m_controlHandle = NULL;
273 #if wxOSX_USE_NATIVE_TOOLBAR
274 m_toolbarItem = NULL;
279 WXWidget m_controlHandle;
282 wxBitmap m_alternateBitmap;
284 #if wxOSX_USE_NATIVE_TOOLBAR
285 NSToolbarItem* m_toolbarItem;
286 // position in its toolbar, -1 means not inserted
291 #if wxOSX_USE_NATIVE_TOOLBAR
293 @interface wxNSToolbarItem : NSToolbarItem
298 - (id) initWithItemIdentifier: (NSString*) identifier;
299 - (void)setImplementation: (wxToolBarTool *) theImplementation;
300 - (wxToolBarTool*) implementation;
301 - (void) clickedAction: (id) sender;
302 - (BOOL) validateToolbarItem:(NSToolbarItem *)theItem;
307 @interface wxNSToolbarDelegate : NSObject wxOSX_10_6_AND_LATER(<NSToolbarDelegate>)
311 - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag;
313 - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar;
315 - (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar;
317 - (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar;
325 #if wxOSX_USE_NATIVE_TOOLBAR
327 @implementation wxNSToolbarItem
329 - (id)initWithItemIdentifier: (NSString*) identifier
331 self = [super initWithItemIdentifier:identifier];
333 [self setTarget: self];
334 [self setAction: @selector(clickedAction:)];
338 - (void) clickedAction: (id) sender
347 - (void)setImplementation: (wxToolBarTool *) theImplementation
349 impl = theImplementation;
352 - (wxToolBarTool*) implementation
357 - (BOOL)validateToolbarItem:(NSToolbarItem *)theItem
359 wxUnusedVar(theItem);
360 return impl->IsEnabled() ? YES:NO;
365 @implementation wxNSToolbarDelegate
367 - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
369 wxUnusedVar(toolbar);
373 - (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar
375 wxUnusedVar(toolbar);
379 - (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar
381 wxUnusedVar(toolbar);
385 - (NSToolbarItem*) toolbar:(NSToolbar*) toolbar itemForItemIdentifier:(NSString*) itemIdentifier willBeInsertedIntoToolbar:(BOOL) flag
387 wxUnusedVar(toolbar);
389 wxToolBarTool* tool = (wxToolBarTool*) [itemIdentifier longLongValue];
391 wxToolBarTool* tool = (wxToolBarTool*) [itemIdentifier intValue];
395 wxNSToolbarItem* item = (wxNSToolbarItem*) tool->GetToolbarItemRef();
396 if ( flag && tool->IsControl() )
398 NSView* view = tool->GetControl()->GetHandle();
399 [view removeFromSuperview];
401 wxSize sz = tool->GetControl()->GetSize();
402 NSSize size = NSMakeSize((float)sz.x, (float)sz.y);
403 [item setMaxSize:size];
404 [item setMinSize:size];
416 @implementation wxNSToolBarButton
418 - (id)initWithFrame:(NSRect)frame
420 self = [super initWithFrame:frame];
422 [self setTarget: self];
423 [self setAction: @selector(clickedAction:)];
427 - (void) clickedAction: (id) sender
436 - (void)setImplementation: (wxToolBarTool *) theImplementation
438 impl = theImplementation;
441 - (wxToolBarTool*) implementation
453 bool wxToolBarTool::Enable( bool enable )
455 if ( wxToolBarToolBase::Enable( enable ) == false )
460 GetControl()->Enable( enable );
462 else if ( IsButton() )
464 #if wxOSX_USE_NATIVE_TOOLBAR
465 if ( m_toolbarItem != NULL )
466 [m_toolbarItem setEnabled:enable];
469 if ( m_controlHandle != NULL )
470 [(NSControl*)m_controlHandle setEnabled:enable];
476 void wxToolBarTool::SetPosition( const wxPoint& position )
481 int mac_x = position.x;
482 int mac_y = position.y;
486 NSRect frame = [m_controlHandle frame];
487 if ( frame.origin.x != mac_x || frame.origin.y != mac_y )
489 frame.origin.x = mac_x;
490 frame.origin.y = mac_y;
491 [m_controlHandle setFrame:frame];
494 else if ( IsControl() )
496 // embedded native controls are moved by the OS
497 #if wxOSX_USE_NATIVE_TOOLBAR
498 if ( ((wxToolBar*)GetToolBar())->MacWantsNativeToolbar() == false )
501 GetControl()->Move( position );
506 NSRect frame = [m_controlHandle frame];
507 if ( frame.origin.x != mac_x || frame.origin.y != mac_y )
509 frame.origin.x = mac_x;
510 frame.origin.y = mac_y;
511 [m_controlHandle setFrame:frame];
516 void wxToolBarTool::UpdateImages()
518 [(NSButton*) m_controlHandle setImage:m_bmpNormal.GetNSImage()];
520 if ( CanBeToggled() )
522 int w = m_bmpNormal.GetWidth();
523 int h = m_bmpNormal.GetHeight();
524 m_alternateBitmap = wxBitmap( w, h );
527 dc.SelectObject( m_alternateBitmap );
528 dc.SetPen( wxPen(*wxBLACK) );
529 dc.SetBrush( wxBrush( *wxLIGHT_GREY ));
530 dc.DrawRoundedRectangle( 0, 0, w, h, 2 );
531 dc.DrawBitmap( m_bmpNormal, 0, 0, true );
532 dc.SelectObject( wxNullBitmap );
534 [(NSButton*) m_controlHandle setAlternateImage:m_alternateBitmap.GetNSImage()];
536 UpdateToggleImage( CanBeToggled() && IsToggled() );
539 void wxToolBarTool::UpdateToggleImage( bool toggle )
541 #if wxOSX_USE_NATIVE_TOOLBAR
542 if (m_toolbarItem != NULL )
544 // the native toolbar item only has a 'selected' state (one for one toolbar)
545 // so we emulate the toggle here
546 if ( CanBeToggled() && toggle )
547 [m_toolbarItem setImage:m_alternateBitmap.GetNSImage()];
549 [m_toolbarItem setImage:m_bmpNormal.GetNSImage()];
555 [(NSButton*)m_controlHandle setState:(toggle ? NSOnState : NSOffState)];
559 wxToolBarTool::wxToolBarTool(
562 const wxString& label,
563 const wxBitmap& bmpNormal,
564 const wxBitmap& bmpDisabled,
566 wxObject *clientData,
567 const wxString& shortHelp,
568 const wxString& longHelp )
571 tbar, id, label, bmpNormal, bmpDisabled, kind,
572 clientData, shortHelp, longHelp )
578 #pragma mark Toolbar Implementation
580 wxToolBarToolBase *wxToolBar::CreateTool(
582 const wxString& label,
583 const wxBitmap& bmpNormal,
584 const wxBitmap& bmpDisabled,
586 wxObject *clientData,
587 const wxString& shortHelp,
588 const wxString& longHelp )
590 return new wxToolBarTool(
591 this, id, label, bmpNormal, bmpDisabled, kind,
592 clientData, shortHelp, longHelp );
596 wxToolBar::CreateTool(wxControl *control, const wxString& label)
598 return new wxToolBarTool(this, control, label);
601 void wxToolBar::Init()
605 m_defaultWidth = kwxMacToolBarToolDefaultWidth;
606 m_defaultHeight = kwxMacToolBarToolDefaultHeight;
608 #if wxOSX_USE_NATIVE_TOOLBAR
610 m_macUsesNativeToolbar = false;
614 // also for the toolbar we have the dual implementation:
615 // only when MacInstallNativeToolbar is called is the native toolbar set as the window toolbar
617 bool wxToolBar::Create(
623 const wxString& name )
625 if ( !wxToolBarBase::Create( parent, id, pos, size, style, wxDefaultValidator, name ) )
630 OSStatus err = noErr;
632 #if wxOSX_USE_NATIVE_TOOLBAR
634 if (parent->IsKindOf(CLASSINFO(wxFrame)) && wxSystemOptions::GetOptionInt(wxT("mac.toolbar.no-native")) != 1)
636 static wxNSToolbarDelegate* controller = nil;
638 if ( controller == nil )
639 controller = [[wxNSToolbarDelegate alloc] init];
640 wxString identifier = wxString::Format( wxT("%p"), this );
641 wxCFStringRef cfidentifier(identifier);
642 NSToolbar* tb = [[NSToolbar alloc] initWithIdentifier:cfidentifier.AsNSString()];
646 if (m_macToolbar != NULL)
648 [tb setDelegate:controller];
650 NSToolbarDisplayMode mode = NSToolbarDisplayModeDefault;
651 NSToolbarSizeMode displaySize = NSToolbarSizeModeSmall;
653 if ( style & wxTB_NOICONS )
654 mode = NSToolbarDisplayModeLabelOnly;
655 else if ( style & wxTB_TEXT )
656 mode = NSToolbarDisplayModeIconAndLabel;
658 mode = NSToolbarDisplayModeIconOnly;
660 [tb setDisplayMode:mode];
661 [tb setSizeMode:displaySize];
664 #endif // wxOSX_USE_NATIVE_TOOLBAR
666 return (err == noErr);
669 wxToolBar::~wxToolBar()
671 // removal only works while the toolbar is there
672 wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
673 if ( frame && frame->GetToolBar() == this )
675 frame->SetToolBar(NULL);
678 [(NSToolbar*)m_macToolbar setDelegate:nil];
679 [(NSToolbar*)m_macToolbar release];
683 bool wxToolBar::Show( bool show )
685 WXWindow tlw = MacGetTopLevelWindowRef();
686 bool bResult = (tlw != NULL);
690 #if wxOSX_USE_NATIVE_TOOLBAR
691 bool ownToolbarInstalled = false;
692 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
693 if (ownToolbarInstalled)
695 bResult = ([(NSToolbar*)m_macToolbar isVisible] != show);
697 [(NSToolbar*)m_macToolbar setVisible:show];
700 bResult = wxToolBarBase::Show( show );
703 bResult = wxToolBarBase::Show( show );
710 bool wxToolBar::IsShown() const
714 #if wxOSX_USE_NATIVE_TOOLBAR
715 bool ownToolbarInstalled;
717 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
718 if (ownToolbarInstalled)
720 bResult = [(NSToolbar*)m_macToolbar isVisible];
723 bResult = wxToolBarBase::IsShown();
726 bResult = wxToolBarBase::IsShown();
732 void wxToolBar::DoGetSize( int *width, int *height ) const
734 #if wxOSX_USE_NATIVE_TOOLBAR
735 bool ownToolbarInstalled;
737 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
738 if ( ownToolbarInstalled )
740 WXWindow tlw = MacGetTopLevelWindowRef();
741 float toolbarHeight = 0.0;
742 NSRect windowFrame = NSMakeRect(0, 0, 0, 0);
744 if(m_macToolbar && [(NSToolbar*)m_macToolbar isVisible])
746 windowFrame = [NSWindow contentRectForFrameRect:[tlw frame]
747 styleMask:[tlw styleMask]];
748 toolbarHeight = NSHeight(windowFrame)
749 - NSHeight([[tlw contentView] frame]);
753 *width = (int)windowFrame.size.width;
754 if ( height != NULL )
755 *height = (int)toolbarHeight;
758 wxToolBarBase::DoGetSize( width, height );
761 wxToolBarBase::DoGetSize( width, height );
765 wxSize wxToolBar::DoGetBestSize() const
767 // was updated in Realize()
769 wxSize size = GetMinSize();
774 void wxToolBar::SetWindowStyleFlag( long style )
776 wxToolBarBase::SetWindowStyleFlag( style );
778 #if wxOSX_USE_NATIVE_TOOLBAR
779 if (m_macToolbar != NULL)
781 NSToolbarDisplayMode mode = NSToolbarDisplayModeDefault;
783 if ( style & wxTB_NOICONS )
784 mode = NSToolbarDisplayModeLabelOnly;
785 else if ( style & wxTB_TEXT )
786 mode = NSToolbarDisplayModeIconAndLabel;
788 mode = NSToolbarDisplayModeIconOnly;
790 [(NSToolbar*) m_macToolbar setDisplayMode:mode];
795 #if wxOSX_USE_NATIVE_TOOLBAR
796 bool wxToolBar::MacWantsNativeToolbar()
798 return m_macUsesNativeToolbar;
801 bool wxToolBar::MacTopLevelHasNativeToolbar(bool *ownToolbarInstalled) const
803 bool bResultV = false;
805 if (ownToolbarInstalled != NULL)
806 *ownToolbarInstalled = false;
808 WXWindow tlw = MacGetTopLevelWindowRef();
811 NSToolbar* curToolbarRef = [tlw toolbar];
812 bResultV = (curToolbarRef != NULL);
813 if (bResultV && (ownToolbarInstalled != NULL))
814 *ownToolbarInstalled = (curToolbarRef == m_macToolbar);
820 bool wxToolBar::MacInstallNativeToolbar(bool usesNative)
822 bool bResult = false;
824 if (usesNative && (m_macToolbar == NULL))
827 if (usesNative && HasFlag(wxTB_LEFT|wxTB_RIGHT|wxTB_BOTTOM) )
830 WXWindow tlw = MacGetTopLevelWindowRef();
834 // check the existing toolbar
835 NSToolbar* curToolbarRef = [tlw toolbar];
837 m_macUsesNativeToolbar = usesNative;
839 if (m_macUsesNativeToolbar)
841 // only install toolbar if there isn't one installed already
842 if (curToolbarRef == NULL)
845 [tlw setToolbar:(NSToolbar*) m_macToolbar];
846 [(NSToolbar*) m_macToolbar setVisible:YES];
848 GetPeer()->Move(0,0,0,0 );
849 SetSize( wxSIZE_AUTO_WIDTH, 0 );
850 GetPeer()->SetVisibility( false );
851 wxToolBarBase::Show( false );
856 // only deinstall toolbar if this is the installed one
857 if (m_macToolbar == curToolbarRef)
860 [(NSToolbar*) m_macToolbar setVisible:NO];
861 MacUninstallNativeToolbar();
862 GetPeer()->SetVisibility( true );
867 InvalidateBestSize();
869 // wxLogDebug( wxT(" --> [%lx] - result [%s]"), (long)this, bResult ? wxT("T") : wxT("F") );
873 void wxToolBar::MacUninstallNativeToolbar()
878 WXWindow tlw = MacGetTopLevelWindowRef();
880 [tlw setToolbar:nil];
884 void wxToolBar::DoLayout()
886 int maxToolWidth = 0;
887 int maxToolHeight = 0;
892 // find the maximum tool width and height
893 // and the number of stretchable items
894 int numStretchableSpaces = 0;
896 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
899 tool = (wxToolBarTool *) node->GetData();
902 wxSize sz = tool->GetSize();
904 if ( sz.x > maxToolWidth )
906 if ( sz.y > maxToolHeight )
907 maxToolHeight = sz.y;
908 if ( tool->IsStretchableSpace() )
909 numStretchableSpaces++;
912 node = node->GetNext();
915 // layout non-native toolbar
917 bool isHorizontal = !IsVertical();
922 int x = m_xMargin + kwxMacToolBarLeftMargin;
923 int y = m_yMargin + kwxMacToolBarTopMargin;
925 node = m_tools.GetFirst();
928 tool = (wxToolBarTool*) node->GetData();
931 node = node->GetNext();
935 // set tool position:
936 // for the moment just perform a single row/column alignment
937 wxSize cursize = tool->GetSize();
938 if ( x + cursize.x > maxWidth )
939 maxWidth = x + cursize.x;
940 if ( y + cursize.y > maxHeight )
941 maxHeight = y + cursize.y;
943 // update the item positioning state
945 y += cursize.y + kwxMacToolSpacing;
947 x += cursize.x + kwxMacToolSpacing;
949 node = node->GetNext();
954 // if not set yet, only one row
955 if ( m_maxRows <= 0 )
958 maxWidth += m_xMargin + kwxMacToolBarLeftMargin;
959 m_minWidth = maxWidth;
960 m_minHeight = m_maxHeight = maxToolHeight + 2 * (m_yMargin + kwxMacToolBarTopMargin);
964 // if not set yet, have one column
965 if ( (GetToolsCount() > 0) && (m_maxRows <= 0) )
966 SetRows( GetToolsCount() );
968 maxHeight += m_yMargin + kwxMacToolBarTopMargin;
969 m_minHeight = maxHeight;
970 m_minWidth = m_maxWidth = maxToolWidth + 2 * (m_yMargin + kwxMacToolBarTopMargin);
973 int totalStretchableSpace = 0;
974 int spacePerStretchable = 0;
975 if ( numStretchableSpaces > 0 )
978 totalStretchableSpace = tw - maxWidth;
980 totalStretchableSpace = th - maxHeight;
982 if ( totalStretchableSpace > 0 )
983 spacePerStretchable = totalStretchableSpace / numStretchableSpaces;
986 // perform real positioning
988 x = m_xMargin + kwxMacToolBarLeftMargin;
989 y = m_yMargin + kwxMacToolBarTopMargin;
991 node = m_tools.GetFirst();
992 int currentStretchable = 0;
995 tool = (wxToolBarTool*) node->GetData();
998 node = node->GetNext();
1002 wxSize cursize = tool->GetSize();
1003 if ( tool->IsStretchableSpace() )
1005 ++currentStretchable;
1006 int thisSpace = currentStretchable == numStretchableSpaces ?
1007 totalStretchableSpace - (currentStretchable-1)*spacePerStretchable :
1008 spacePerStretchable;
1010 cursize.x += thisSpace;
1012 cursize.y += thisSpace;
1015 if ( !isHorizontal )
1017 int x1 = x + ( maxToolWidth - cursize.x ) / 2;
1018 tool->SetPosition( wxPoint(x1, y) );
1022 int y1 = y + ( maxToolHeight - cursize.y ) / 2;
1023 tool->SetPosition( wxPoint(x, y1) );
1026 // update the item positioning state
1027 if ( !isHorizontal )
1028 y += cursize.y + kwxMacToolSpacing;
1030 x += cursize.x + kwxMacToolSpacing;
1032 node = node->GetNext();
1037 bool wxToolBar::Realize()
1039 if ( !wxToolBarBase::Realize() )
1042 wxToolBarTool *tool;
1043 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1045 #if wxOSX_USE_NATIVE_TOOLBAR
1046 CFIndex currentPosition = 0;
1047 bool insertAll = false;
1049 NSToolbar* refTB = (NSToolbar*)m_macToolbar;
1054 enc = f.GetEncoding();
1056 enc = wxFont::GetDefaultEncoding();
1058 node = m_tools.GetFirst();
1061 tool = (wxToolBarTool*) node->GetData();
1064 node = node->GetNext();
1068 // install in native NSToolbar
1071 NSToolbarItem* hiItemRef = tool->GetToolbarItemRef();
1072 if ( hiItemRef != NULL )
1074 // since setting the help texts is non-virtual we have to update
1076 wxCFStringRef sh( tool->GetShortHelp(), enc);
1077 [hiItemRef setToolTip:sh.AsNSString()];
1079 if ( insertAll || (tool->GetIndex() != currentPosition) )
1085 // if this is the first tool that gets newly inserted or repositioned
1086 // first remove all 'old' tools from here to the right, because of this
1087 // all following tools will have to be reinserted (insertAll).
1088 for ( wxToolBarToolsList::compatibility_iterator node2 = m_tools.GetLast();
1090 node2 = node2->GetPrevious() )
1092 wxToolBarTool *tool2 = (wxToolBarTool*) node2->GetData();
1094 const long idx = tool2->GetIndex();
1097 [refTB removeItemAtIndex:idx];
1098 tool2->SetIndex(-1);
1103 wxCFStringRef cfidentifier;
1105 if (tool->GetStyle() == wxTOOL_STYLE_SEPARATOR)
1107 if ( tool->IsStretchable() )
1108 nsItemId = NSToolbarFlexibleSpaceItemIdentifier;
1111 if ( UMAGetSystemVersion() < 0x1070 )
1112 nsItemId = NSToolbarSeparatorItemIdentifier;
1114 nsItemId = NSToolbarSpaceItemIdentifier;
1119 cfidentifier = wxCFStringRef(wxString::Format("%ld", (long)tool));
1120 nsItemId = cfidentifier.AsNSString();
1123 [refTB insertItemWithItemIdentifier:nsItemId atIndex:currentPosition];
1124 tool->SetIndex( currentPosition );
1130 node = node->GetNext();
1137 // adjust radio items
1139 bool lastIsRadio = false;
1140 bool curIsRadio = false;
1142 node = m_tools.GetFirst();
1145 tool = (wxToolBarTool*) node->GetData();
1148 node = node->GetNext();
1152 // update radio button (and group) state
1153 lastIsRadio = curIsRadio;
1154 curIsRadio = ( tool->IsButton() && (tool->GetKind() == wxITEM_RADIO) );
1158 if ( tool->IsToggled() )
1159 DoToggleTool( tool, true );
1165 if ( tool->Toggle( true ) )
1167 DoToggleTool( tool, true );
1170 else if ( tool->IsToggled() )
1172 if ( tool->IsToggled() )
1173 DoToggleTool( tool, true );
1175 wxToolBarToolsList::compatibility_iterator nodePrev = node->GetPrevious();
1178 wxToolBarToolBase *toggleTool = nodePrev->GetData();
1179 if ( (toggleTool == NULL) || !toggleTool->IsButton() || (toggleTool->GetKind() != wxITEM_RADIO) )
1182 if ( toggleTool->Toggle( false ) )
1183 DoToggleTool( toggleTool, false );
1185 nodePrev = nodePrev->GetPrevious();
1190 node = node->GetNext();
1193 InvalidateBestSize();
1194 SetInitialSize( wxSize(m_minWidth, m_minHeight));
1196 SendSizeEventToParent();
1201 void wxToolBar::DoSetSize(int x, int y, int width, int height, int sizeFlags)
1203 wxToolBarBase::DoSetSize(x, y, width, height, sizeFlags);
1208 void wxToolBar::SetToolBitmapSize(const wxSize& size)
1210 m_defaultWidth = size.x + kwxMacToolBorder;
1211 m_defaultHeight = size.y + kwxMacToolBorder;
1213 #if wxOSX_USE_NATIVE_TOOLBAR
1214 if (m_macToolbar != NULL)
1216 int maxs = wxMax( size.x, size.y );
1217 NSToolbarSizeMode sizeSpec;
1219 sizeSpec = NSToolbarSizeModeRegular;
1220 else if ( maxs > 24 )
1221 sizeSpec = NSToolbarSizeModeDefault;
1223 sizeSpec = NSToolbarSizeModeSmall;
1225 [(NSToolbar*) m_macToolbar setSizeMode:sizeSpec ];
1230 // The button size is bigger than the bitmap size
1231 wxSize wxToolBar::GetToolSize() const
1233 return wxSize(m_defaultWidth + kwxMacToolBorder, m_defaultHeight + kwxMacToolBorder);
1236 void wxToolBar::SetRows(int nRows)
1238 // avoid resizing the frame uselessly
1239 if ( nRows != m_maxRows )
1243 void wxToolBar::MacSuperChangedPosition()
1245 wxWindow::MacSuperChangedPosition();
1248 #if wxOSX_USE_NATIVE_TOOLBAR
1249 if (! m_macUsesNativeToolbar )
1258 void wxToolBar::SetToolNormalBitmap( int id, const wxBitmap& bitmap )
1260 wxToolBarTool* tool = static_cast<wxToolBarTool*>(FindById(id));
1263 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
1265 tool->SetNormalBitmap(bitmap);
1267 // a side-effect of the UpdateToggleImage function is that it always changes the bitmap used on the button.
1268 tool->UpdateImages();
1272 void wxToolBar::SetToolDisabledBitmap( int id, const wxBitmap& bitmap )
1274 wxToolBarTool* tool = static_cast<wxToolBarTool*>(FindById(id));
1277 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
1279 tool->SetDisabledBitmap(bitmap);
1281 // TODO: what to do for this one?
1285 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
1287 wxToolBarTool *tool;
1288 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1291 tool = (wxToolBarTool *)node->GetData();
1294 wxRect2DInt r( tool->GetPosition(), tool->GetSize() );
1295 if ( r.Contains( wxPoint( x, y ) ) )
1299 node = node->GetNext();
1305 wxString wxToolBar::MacGetToolTipString( wxPoint &pt )
1307 wxToolBarToolBase *tool = FindToolForPosition( pt.x, pt.y );
1309 return tool->GetShortHelp();
1311 return wxEmptyString;
1314 void wxToolBar::DoEnableTool(wxToolBarToolBase * WXUNUSED(t), bool WXUNUSED(enable))
1316 // everything already done in the tool's Enable implementation
1319 void wxToolBar::DoToggleTool(wxToolBarToolBase *t, bool toggle)
1321 wxToolBarTool *tool = (wxToolBarTool *)t;
1322 if ( ( tool != NULL ) && tool->IsButton() )
1323 tool->UpdateToggleImage( toggle );
1326 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
1328 wxToolBarTool *tool = static_cast< wxToolBarTool*>(toolBase );
1332 long style = GetWindowStyleFlag();
1334 wxSize toolSize = GetToolSize();
1335 WXWidget controlHandle = NULL;
1336 NSRect toolrect = NSMakeRect(0, 0, toolSize.x, toolSize.y );
1338 #if wxOSX_USE_NATIVE_TOOLBAR
1339 wxString label = tool->GetLabel();
1340 if (m_macToolbar && !label.empty() )
1342 // strip mnemonics from the label for compatibility
1343 // with the usual labels in wxStaticText sense
1344 label = wxStripMenuCodes(label);
1346 #endif // wxOSX_USE_NATIVE_TOOLBAR
1348 switch (tool->GetStyle())
1350 case wxTOOL_STYLE_SEPARATOR:
1352 wxASSERT( tool->GetControlHandle() == NULL );
1356 toolrect.size.height = toolSize.y;
1358 toolrect.size.width = toolSize.x;
1360 // in flat style we need a visual separator
1361 #if wxOSX_USE_NATIVE_TOOLBAR
1362 if (m_macToolbar != NULL)
1364 NSString * nsItemId = nil;
1366 if ( tool->IsStretchable() )
1367 nsItemId = NSToolbarFlexibleSpaceItemIdentifier;
1370 if ( UMAGetSystemVersion() < 0x1070 )
1371 nsItemId = NSToolbarSeparatorItemIdentifier;
1373 nsItemId = NSToolbarSpaceItemIdentifier;
1376 NSToolbarItem* item = [[NSToolbarItem alloc] initWithItemIdentifier:nsItemId];
1377 tool->SetToolbarItemRef( item );
1379 #endif // wxOSX_USE_NATIVE_TOOLBAR
1381 NSBox* box = [[NSBox alloc] initWithFrame:toolrect];
1382 [box setBoxType:NSBoxSeparator];
1383 controlHandle = box;
1384 tool->SetControlHandle( controlHandle );
1388 case wxTOOL_STYLE_BUTTON:
1390 wxASSERT( tool->GetControlHandle() == NULL );
1392 wxNSToolBarButton* v = [[wxNSToolBarButton alloc] initWithFrame:toolrect];
1394 [v setBezelStyle:NSRegularSquareBezelStyle];
1396 [v setButtonType: ( tool->CanBeToggled() ? NSToggleButton : NSMomentaryPushInButton )];
1397 [v setImplementation:tool];
1401 #if wxOSX_USE_NATIVE_TOOLBAR
1402 if (m_macToolbar != NULL)
1404 wxString identifier = wxString::Format(wxT("%ld"), (long) tool);
1405 wxCFStringRef cfidentifier( identifier, wxFont::GetDefaultEncoding() );
1406 wxNSToolbarItem* item = [[wxNSToolbarItem alloc] initWithItemIdentifier:cfidentifier.AsNSString() ];
1407 [item setImplementation:tool];
1408 tool->SetToolbarItemRef( item );
1411 #endif // wxOSX_USE_NATIVE_TOOLBAR
1412 tool->SetControlHandle( controlHandle );
1413 tool->UpdateImages();
1414 tool->UpdateLabel();
1416 if ( style & wxTB_NOICONS )
1417 [v setImagePosition:NSNoImage];
1418 else if ( style & wxTB_TEXT )
1419 [v setImagePosition:NSImageAbove];
1421 [v setImagePosition:NSImageOnly];
1425 InstallControlEventHandler(
1426 (WXWidget) controlHandle, GetwxMacToolBarToolEventHandlerUPP(),
1427 GetEventTypeCount(eventList), eventList, tool, NULL );
1432 case wxTOOL_STYLE_CONTROL:
1434 #if wxOSX_USE_NATIVE_TOOLBAR
1435 if (m_macToolbar != NULL)
1437 WXWidget view = (WXWidget) tool->GetControl()->GetHandle() ;
1438 wxCHECK_MSG( view, false, wxT("control must be non-NULL") );
1440 wxString identifier = wxString::Format(wxT("%ld"), (long) tool);
1441 wxCFStringRef cfidentifier( identifier, wxFont::GetDefaultEncoding() );
1442 wxNSToolbarItem* item = [[wxNSToolbarItem alloc] initWithItemIdentifier:cfidentifier.AsNSString() ];
1443 [item setImplementation:tool];
1444 tool->SetToolbarItemRef( item );
1447 // right now there's nothing to do here
1449 tool->UpdateLabel();
1456 if ( controlHandle )
1458 WXWidget container = (WXWidget) GetHandle();
1459 wxASSERT_MSG( container != NULL, wxT("No valid Mac container control") );
1461 // SetControlVisibility( controlHandle, true, true );
1462 [container addSubview:controlHandle];
1465 // nothing special to do here - we relayout in Realize() later
1466 InvalidateBestSize();
1472 void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
1474 wxFAIL_MSG( wxT("not implemented") );
1477 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolbase)
1479 wxToolBarTool* tool = static_cast< wxToolBarTool*>(toolbase );
1480 wxToolBarToolsList::compatibility_iterator node;
1481 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
1483 wxToolBarToolBase *tool2 = node->GetData();
1484 if ( tool2 == tool )
1486 // let node point to the next node in the list
1487 node = node->GetNext();
1493 wxSize sz = ((wxToolBarTool*)tool)->GetSize();
1495 #if wxOSX_USE_NATIVE_TOOLBAR
1496 CFIndex removeIndex = tool->GetIndex();
1499 #if wxOSX_USE_NATIVE_TOOLBAR
1500 if (m_macToolbar != NULL)
1502 if ( removeIndex != -1 && m_macToolbar )
1504 [(NSToolbar*) m_macToolbar removeItemAtIndex:removeIndex];
1505 tool->SetIndex( -1 );
1510 tool->ClearControl();
1512 // and finally reposition all the controls after this one
1514 for ( /* node -> first after deleted */; node; node = node->GetNext() )
1516 wxToolBarTool *tool2 = (wxToolBarTool*) node->GetData();
1517 wxPoint pt = tool2->GetPosition();
1524 tool2->SetPosition( pt );
1526 #if wxOSX_USE_NATIVE_TOOLBAR
1527 if (m_macToolbar != NULL)
1529 if ( removeIndex != -1 && tool2->GetIndex() > removeIndex )
1530 tool2->SetIndex( tool2->GetIndex() - 1 );
1535 InvalidateBestSize();
1540 #include <Carbon/Carbon.h>
1542 void wxToolBar::OnPaint(wxPaintEvent& event)
1544 #if wxOSX_USE_NATIVE_TOOLBAR
1545 if ( m_macUsesNativeToolbar )
1547 // nothing to do here
1555 bool drawMetalTheme = MacGetTopLevelWindow()->GetExtraStyle() & wxFRAME_EX_METAL;
1557 if ( UMAGetSystemVersion() < 0x1050 )
1559 if ( !drawMetalTheme )
1561 HIThemePlacardDrawInfo info;
1562 memset( &info, 0, sizeof(info) );
1564 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive;
1566 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef();
1567 HIRect rect = CGRectMake( 0, 0, w, h );
1568 HIThemeDrawPlacard( &rect, &info, cgContext, kHIThemeOrientationNormal );
1572 // leave the background as it is (striped or metal)
1579 wxRect rect(0,0,w,h);
1581 dc.GradientFillLinear( rect , wxColour( 0xCC,0xCC,0xCC ), wxColour( 0xA8,0xA8,0xA8 ) , wxSOUTH );
1582 dc.SetPen( wxPen( wxColour( 0x51,0x51,0x51 ) ) );
1583 if ( HasFlag(wxTB_LEFT) )
1584 dc.DrawLine(w-1, 0, w-1, h);
1585 else if ( HasFlag(wxTB_RIGHT) )
1586 dc.DrawLine(0, 0, 0, h);
1587 else if ( HasFlag(wxTB_BOTTOM) )
1588 dc.DrawLine(0, 0, w, 0);
1589 else if ( HasFlag(wxTB_TOP) )
1590 dc.DrawLine(0, h-1, w, h-1);
1596 #endif // wxUSE_TOOLBAR