]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/toolbar.mm
64 bit fixes
[wxWidgets.git] / src / osx / cocoa / toolbar.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/toolbar.cpp
3 // Purpose: wxToolBar
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id: toolbar.cpp 54954 2008-08-03 11:27:03Z VZ $
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #if wxUSE_TOOLBAR
15
16 #include "wx/toolbar.h"
17
18 #ifndef WX_PRECOMP
19 #include "wx/wx.h"
20 #endif
21
22 #include "wx/app.h"
23 #include "wx/osx/private.h"
24 #include "wx/geometry.h"
25 #include "wx/sysopt.h"
26
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;
33
34 BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
35 EVT_PAINT( wxToolBar::OnPaint )
36 END_EVENT_TABLE()
37
38
39 #pragma mark -
40 #pragma mark Tool Implementation
41
42 #if wxOSX_USE_COCOA
43 #define wxOSX_USE_NATIVE_TOOLBAR 1
44 #endif
45
46 // ----------------------------------------------------------------------------
47 // private classes
48 // ----------------------------------------------------------------------------
49
50 // We have a dual implementation for each tool, WXWidget and NSToolbarItem*
51
52 // when embedding native controls in the native toolbar we must make sure the
53 // control does not get deleted behind our backs, so the retain count gets increased
54 // (after creation it is 1), first be the creation of the custom NSToolbarItem wrapper
55 // object, and second by the code 'creating' the custom HIView (which is the same as the
56 // already existing native control, therefore we just increase the ref count)
57 // when this view is removed from the native toolbar its count gets decremented again
58 // and when the HITooolbarItem wrapper object gets destroyed it is decremented as well
59 // so in the end the control lives with a refcount of one and can be disposed of by the
60 // wxControl code. For embedded controls on a non-native toolbar this ref count is less
61 // so we can only test against a range, not a specific value of the refcount.
62
63 class wxToolBarTool : public wxToolBarToolBase
64 {
65 public:
66 wxToolBarTool(
67 wxToolBar *tbar,
68 int id,
69 const wxString& label,
70 const wxBitmap& bmpNormal,
71 const wxBitmap& bmpDisabled,
72 wxItemKind kind,
73 wxObject *clientData,
74 const wxString& shortHelp,
75 const wxString& longHelp );
76
77 wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
78 : wxToolBarToolBase(tbar, control, label)
79 {
80 Init();
81 if (control != NULL)
82 SetControlHandle( (WXWidget) control->GetHandle() );
83 }
84
85 virtual ~wxToolBarTool()
86 {
87 ClearControl();
88 }
89
90 WXWidget GetControlHandle()
91 {
92 return (WXWidget) m_controlHandle;
93 }
94
95 void SetControlHandle( WXWidget handle )
96 {
97 m_controlHandle = handle;
98 }
99
100 void SetPosition( const wxPoint& position );
101
102 void ClearControl()
103 {
104 if ( m_controlHandle )
105 {
106 if ( !IsControl() )
107 {
108 [m_controlHandle retain];
109 }
110 else
111 {
112 // the embedded control is not under the responsibility of the tool, it gets disposed of in the
113 // proper wxControl destructor
114 }
115 m_controlHandle = NULL ;
116 }
117
118 #if wxOSX_USE_NATIVE_TOOLBAR
119 if ( m_toolbarItem )
120 {
121 [m_toolbarItem release];
122 m_toolbarItem = NULL;
123 }
124 #endif // wxOSX_USE_NATIVE_TOOLBAR
125 }
126
127 wxSize GetSize() const
128 {
129 wxSize curSize;
130
131 if ( IsControl() )
132 {
133 curSize = GetControl()->GetSize();
134 }
135 else if ( IsButton() )
136 {
137 curSize = GetToolBar()->GetToolSize();
138 }
139 else
140 {
141 // separator size
142 curSize = GetToolBar()->GetToolSize();
143 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
144 curSize.y /= 4;
145 else
146 curSize.x /= 4;
147 }
148
149 return curSize;
150 }
151
152 wxPoint GetPosition() const
153 {
154 return wxPoint( m_x, m_y );
155 }
156
157 bool DoEnable( bool enable );
158
159 void UpdateImages();
160
161 void UpdateToggleImage( bool toggle );
162
163 void UpdateLabel()
164 {
165 if ( m_toolbarItem )
166 {
167 // strip mnemonics from the label for compatibility with the usual
168 // labels in wxStaticText sense
169 wxString labelStr = wxStripMenuCodes(m_label);
170 wxCFStringRef l(labelStr, GetToolBarFontEncoding());
171
172 [m_toolbarItem setLabel:l.AsNSString()];
173
174 wxCFStringRef sh( GetShortHelp(), GetToolBarFontEncoding() );
175 [m_toolbarItem setToolTip:sh.AsNSString()];
176 }
177 }
178
179 void Action()
180 {
181 wxToolBar *tbar = (wxToolBar*) GetToolBar();
182 if (CanBeToggled())
183 {
184 bool shouldToggle;
185
186 shouldToggle = !IsToggled();
187 tbar->ToggleTool( GetId(), shouldToggle );
188 }
189
190 tbar->OnLeftClick( GetId(), IsToggled() );
191 }
192
193 #if wxOSX_USE_NATIVE_TOOLBAR
194 void SetToolbarItemRef( NSToolbarItem* ref )
195 {
196 if ( m_controlHandle )
197 [m_controlHandle setHidden:YES];
198 if ( m_toolbarItem )
199 [m_toolbarItem release];
200
201 m_toolbarItem = ref;
202 }
203
204 NSToolbarItem* GetToolbarItemRef() const
205 {
206 return m_toolbarItem;
207 }
208
209 void SetIndex( CFIndex idx )
210 {
211 m_index = idx;
212 }
213
214 CFIndex GetIndex() const
215 {
216 return m_index;
217 }
218
219 virtual void SetLabel(const wxString& label)
220 {
221 wxToolBarToolBase::SetLabel(label);
222 UpdateLabel();
223 }
224 #endif // wxOSX_USE_NATIVE_TOOLBAR
225
226 private:
227 #if wxOSX_USE_NATIVE_TOOLBAR
228 wxFontEncoding GetToolBarFontEncoding() const
229 {
230 wxFont f;
231 if ( GetToolBar() )
232 f = GetToolBar()->GetFont();
233 return f.IsOk() ? f.GetEncoding() : wxFont::GetDefaultEncoding();
234 }
235 #endif // wxOSX_USE_NATIVE_TOOLBAR
236
237 void Init()
238 {
239 m_controlHandle = NULL;
240
241 #if wxOSX_USE_NATIVE_TOOLBAR
242 m_toolbarItem = NULL;
243 m_index = -1;
244 #endif
245 }
246
247 WXWidget m_controlHandle;
248 wxCoord m_x;
249 wxCoord m_y;
250 wxBitmap m_alternateBitmap;
251
252 #if wxOSX_USE_NATIVE_TOOLBAR
253 NSToolbarItem* m_toolbarItem;
254 // position in its toolbar, -1 means not inserted
255 CFIndex m_index;
256 #endif
257 };
258
259 @interface wxNSToolbarItem : NSToolbarItem
260 {
261 wxToolBarTool* impl;
262 }
263
264 - (id) initWithItemIdentifier: (NSString*) identifier;
265 - (void)setImplementation: (wxToolBarTool *) theImplementation;
266 - (wxToolBarTool*) implementation;
267 - (void) clickedAction: (id) sender;
268
269 @end
270
271
272 @interface wxNSToolbarDelegate : NSObject
273 {
274 }
275
276 - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag;
277
278 - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar;
279
280 - (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar;
281
282 - (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar;
283
284
285 @end
286
287
288 @interface wxNSToolBarButton : NSButton
289 {
290 wxToolBarTool* impl;
291 }
292
293 - (id)initWithFrame:(NSRect)frame;
294 - (void) clickedAction: (id) sender;
295 - (void)setImplementation: (wxToolBarTool *) theImplementation;
296 - (wxToolBarTool*) implementation;
297 - (BOOL) isFlipped;
298
299 @end
300
301 @implementation wxNSToolbarItem
302
303 - (id)initWithItemIdentifier: (NSString*) identifier
304 {
305 [super initWithItemIdentifier:identifier];
306 impl = NULL;
307 [self setTarget: self];
308 [self setAction: @selector(clickedAction:)];
309 return self;
310 }
311
312 - (void) clickedAction: (id) sender
313 {
314 if ( impl )
315 {
316 impl->Action();
317 }
318 }
319
320 - (void)setImplementation: (wxToolBarTool *) theImplementation
321 {
322 impl = theImplementation;
323 }
324
325 - (wxToolBarTool*) implementation
326 {
327 return impl;
328 }
329
330 @end
331
332 @implementation wxNSToolbarDelegate
333
334 - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
335 {
336 return nil;
337 }
338
339 - (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar
340 {
341 return nil;
342 }
343
344 - (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar
345 {
346 return nil;
347 }
348
349 - (NSToolbarItem*) toolbar:(NSToolbar*) toolbar itemForItemIdentifier:(NSString*) itemIdentifier willBeInsertedIntoToolbar:(BOOL) flag
350 {
351 #ifdef __LP64__
352 wxToolBarTool* tool = (wxToolBarTool*) [itemIdentifier longLongValue];
353 #else
354 wxToolBarTool* tool = (wxToolBarTool*) [itemIdentifier intValue];
355 #endif
356 if ( tool )
357 {
358 wxNSToolbarItem* item = (wxNSToolbarItem*) tool->GetToolbarItemRef();
359 if ( flag && tool->IsControl() )
360 {
361 NSView* view = tool->GetControl()->GetHandle();
362 [view removeFromSuperview];
363 [item setView:view];
364 wxSize sz = tool->GetControl()->GetSize();
365 NSSize size = NSMakeSize((float)sz.x, (float)sz.y);
366 [item setMaxSize:size];
367 [item setMinSize:size];
368 [view setHidden:NO];
369 }
370 return item;
371 }
372 return nil;
373 }
374
375 @end
376
377 @implementation wxNSToolBarButton
378
379 - (id)initWithFrame:(NSRect)frame
380 {
381 [super initWithFrame:frame];
382 impl = NULL;
383 [self setTarget: self];
384 [self setAction: @selector(clickedAction:)];
385 return self;
386 }
387
388 - (void) clickedAction: (id) sender
389 {
390 if ( impl )
391 {
392 impl->Action();
393 }
394 }
395
396 - (void)setImplementation: (wxToolBarTool *) theImplementation
397 {
398 impl = theImplementation;
399 }
400
401 - (wxToolBarTool*) implementation
402 {
403 return impl;
404 }
405
406 - (BOOL) isFlipped
407 {
408 return YES;
409 }
410
411 @end
412
413 bool wxToolBarTool::DoEnable( bool enable )
414 {
415 if ( IsControl() )
416 {
417 GetControl()->Enable( enable );
418 }
419 else if ( IsButton() )
420 {
421 #if wxOSX_USE_NATIVE_TOOLBAR
422 if ( m_toolbarItem != NULL )
423 [m_toolbarItem setEnabled:enable];
424 #endif
425
426 if ( m_controlHandle != NULL )
427 [(NSControl*)m_controlHandle setEnabled:enable];
428 }
429
430 return true;
431 }
432
433 void wxToolBarTool::SetPosition( const wxPoint& position )
434 {
435 m_x = position.x;
436 m_y = position.y;
437
438 int mac_x = position.x;
439 int mac_y = position.y;
440
441 if ( IsButton() )
442 {
443 NSRect frame = [m_controlHandle frame];
444 if ( frame.origin.x != mac_x || frame.origin.y != mac_y )
445 {
446 frame.origin.x = mac_x;
447 frame.origin.y = mac_y;
448 [m_controlHandle setFrame:frame];
449 }
450 }
451 else if ( IsControl() )
452 {
453 // embedded native controls are moved by the OS
454 #if wxOSX_USE_NATIVE_TOOLBAR
455 if ( ((wxToolBar*)GetToolBar())->MacWantsNativeToolbar() == false )
456 #endif
457 {
458 GetControl()->Move( position );
459 }
460 }
461 else
462 {
463 NSRect frame = [m_controlHandle frame];
464 if ( frame.origin.x != mac_x || frame.origin.y != mac_y )
465 {
466 frame.origin.x = mac_x;
467 frame.origin.y = mac_y;
468 [m_controlHandle setFrame:frame];
469 }
470 }
471 }
472
473 void wxToolBarTool::UpdateImages()
474 {
475 [(NSButton*) m_controlHandle setImage:m_bmpNormal.GetNSImage()];
476
477 if ( CanBeToggled() )
478 {
479 int w = m_bmpNormal.GetWidth();
480 int h = m_bmpNormal.GetHeight();
481 m_alternateBitmap = wxBitmap( w, h );
482 wxMemoryDC dc;
483
484 dc.SelectObject( m_alternateBitmap );
485 dc.SetPen( wxPen(*wxBLACK) );
486 dc.SetBrush( wxBrush( *wxLIGHT_GREY ));
487 dc.DrawRectangle( 0, 0, w, h );
488 dc.DrawBitmap( m_bmpNormal, 0, 0, true );
489 dc.SelectObject( wxNullBitmap );
490
491 [(NSButton*) m_controlHandle setAlternateImage:m_alternateBitmap.GetNSImage()];
492 }
493 UpdateToggleImage( CanBeToggled() && IsToggled() );
494 }
495
496 void wxToolBarTool::UpdateToggleImage( bool toggle )
497 {
498 #if wxOSX_USE_NATIVE_TOOLBAR
499 if (m_toolbarItem != NULL )
500 {
501 // the native toolbar item only has a 'selected' state (one for one toolbar)
502 // so we emulate the toggle here
503 if ( CanBeToggled() && toggle )
504 [m_toolbarItem setImage:m_alternateBitmap.GetNSImage()];
505 else
506 [m_toolbarItem setImage:m_bmpNormal.GetNSImage()];
507 }
508 #endif
509 }
510
511 wxToolBarTool::wxToolBarTool(
512 wxToolBar *tbar,
513 int id,
514 const wxString& label,
515 const wxBitmap& bmpNormal,
516 const wxBitmap& bmpDisabled,
517 wxItemKind kind,
518 wxObject *clientData,
519 const wxString& shortHelp,
520 const wxString& longHelp )
521 :
522 wxToolBarToolBase(
523 tbar, id, label, bmpNormal, bmpDisabled, kind,
524 clientData, shortHelp, longHelp )
525 {
526 Init();
527 }
528
529 #pragma mark -
530 #pragma mark Toolbar Implementation
531
532 wxToolBarToolBase *wxToolBar::CreateTool(
533 int id,
534 const wxString& label,
535 const wxBitmap& bmpNormal,
536 const wxBitmap& bmpDisabled,
537 wxItemKind kind,
538 wxObject *clientData,
539 const wxString& shortHelp,
540 const wxString& longHelp )
541 {
542 return new wxToolBarTool(
543 this, id, label, bmpNormal, bmpDisabled, kind,
544 clientData, shortHelp, longHelp );
545 }
546
547 wxToolBarToolBase *
548 wxToolBar::CreateTool(wxControl *control, const wxString& label)
549 {
550 return new wxToolBarTool(this, control, label);
551 }
552
553 void wxToolBar::Init()
554 {
555 m_maxWidth = -1;
556 m_maxHeight = -1;
557 m_defaultWidth = kwxMacToolBarToolDefaultWidth;
558 m_defaultHeight = kwxMacToolBarToolDefaultHeight;
559
560 #if wxOSX_USE_NATIVE_TOOLBAR
561 m_macToolbar = NULL;
562 m_macUsesNativeToolbar = false;
563 #endif
564 }
565
566 // also for the toolbar we have the dual implementation:
567 // only when MacInstallNativeToolbar is called is the native toolbar set as the window toolbar
568
569 bool wxToolBar::Create(
570 wxWindow *parent,
571 wxWindowID id,
572 const wxPoint& pos,
573 const wxSize& size,
574 long style,
575 const wxString& name )
576 {
577 if ( !wxToolBarBase::Create( parent, id, pos, size, style, wxDefaultValidator, name ) )
578 return false;
579
580 FixupStyle();
581
582 OSStatus err = noErr;
583
584 #if wxOSX_USE_NATIVE_TOOLBAR
585
586 if (parent->IsKindOf(CLASSINFO(wxFrame)) && wxSystemOptions::GetOptionInt(wxT("mac.toolbar.no-native")) != 1)
587 {
588 static wxNSToolbarDelegate* controller = nil;
589
590 if ( controller == nil )
591 controller = [[wxNSToolbarDelegate alloc] init];
592 wxString identifier = wxString::Format( wxT("%p"), this );
593 wxCFStringRef cfidentifier(identifier);
594 NSToolbar* tb = [[NSToolbar alloc] initWithIdentifier:cfidentifier.AsNSString()];
595
596 m_macToolbar = tb ;
597
598 if (m_macToolbar != NULL)
599 {
600 [tb setDelegate:controller];
601
602 NSToolbarDisplayMode mode = NSToolbarDisplayModeDefault;
603 NSToolbarSizeMode displaySize = NSToolbarSizeModeSmall;
604
605 if ( style & wxTB_NOICONS )
606 mode = NSToolbarDisplayModeLabelOnly;
607 else if ( style & wxTB_TEXT )
608 mode = NSToolbarDisplayModeIconAndLabel;
609 else
610 mode = NSToolbarDisplayModeIconOnly;
611
612 [tb setDisplayMode:mode];
613 [tb setSizeMode:displaySize];
614 }
615 }
616 #endif // wxOSX_USE_NATIVE_TOOLBAR
617
618 return (err == noErr);
619 }
620
621 wxToolBar::~wxToolBar()
622 {
623 #if wxOSX_USE_NATIVE_TOOLBAR
624 if (m_macToolbar != NULL)
625 {
626 // if this is the installed toolbar, then deinstall it
627 if (m_macUsesNativeToolbar)
628 MacInstallNativeToolbar( false );
629
630 [(NSToolbar*)m_macToolbar release];
631 m_macToolbar = NULL;
632 }
633 #endif
634 }
635
636 bool wxToolBar::Show( bool show )
637 {
638 WXWindow tlw = MacGetTopLevelWindowRef();
639 bool bResult = (tlw != NULL);
640
641 if (bResult)
642 {
643 #if wxOSX_USE_NATIVE_TOOLBAR
644 bool ownToolbarInstalled = false;
645 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
646 if (ownToolbarInstalled)
647 {
648 bResult = ([(NSToolbar*)m_macToolbar isVisible] != show);
649 if ( bResult )
650 [(NSToolbar*)m_macToolbar setVisible:show];
651 }
652 else
653 bResult = wxToolBarBase::Show( show );
654 #else
655
656 bResult = wxToolBarBase::Show( show );
657 #endif
658 }
659
660 return bResult;
661 }
662
663 bool wxToolBar::IsShown() const
664 {
665 bool bResult;
666
667 #if wxOSX_USE_NATIVE_TOOLBAR
668 bool ownToolbarInstalled;
669
670 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
671 if (ownToolbarInstalled)
672 {
673 bResult = [(NSToolbar*)m_macToolbar isVisible];
674 }
675 else
676 bResult = wxToolBarBase::IsShown();
677 #else
678
679 bResult = wxToolBarBase::IsShown();
680 #endif
681
682 return bResult;
683 }
684
685 void wxToolBar::DoGetSize( int *width, int *height ) const
686 {
687 #if wxOSX_USE_NATIVE_TOOLBAR
688 bool ownToolbarInstalled;
689
690 MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
691 if ( ownToolbarInstalled )
692 {
693 WXWindow tlw = MacGetTopLevelWindowRef();
694 float toolbarHeight = 0.0;
695 NSRect windowFrame;
696
697 if(m_macToolbar && [(NSToolbar*)m_macToolbar isVisible])
698 {
699 windowFrame = [NSWindow contentRectForFrameRect:[tlw frame]
700 styleMask:[tlw styleMask]];
701 toolbarHeight = NSHeight(windowFrame)
702 - NSHeight([[tlw contentView] frame]);
703 }
704
705 if ( width != NULL )
706 *width = windowFrame.size.width;
707 if ( height != NULL )
708 *height = toolbarHeight;
709 }
710 else
711 wxToolBarBase::DoGetSize( width, height );
712
713 #else
714 wxToolBarBase::DoGetSize( width, height );
715 #endif
716 }
717
718 wxSize wxToolBar::DoGetBestSize() const
719 {
720 int width, height;
721
722 DoGetSize( &width, &height );
723
724 return wxSize( width, height );
725 }
726
727 void wxToolBar::SetWindowStyleFlag( long style )
728 {
729 wxToolBarBase::SetWindowStyleFlag( style );
730
731 #if wxOSX_USE_NATIVE_TOOLBAR
732 if (m_macToolbar != NULL)
733 {
734 NSToolbarDisplayMode mode = NSToolbarDisplayModeDefault;
735
736 if ( style & wxTB_NOICONS )
737 mode = NSToolbarDisplayModeLabelOnly;
738 else if ( style & wxTB_TEXT )
739 mode = NSToolbarDisplayModeIconAndLabel;
740 else
741 mode = NSToolbarDisplayModeIconOnly;
742
743 [(NSToolbar*) m_macToolbar setDisplayMode:mode];
744 }
745 #endif
746 }
747
748 #if wxOSX_USE_NATIVE_TOOLBAR
749 bool wxToolBar::MacWantsNativeToolbar()
750 {
751 return m_macUsesNativeToolbar;
752 }
753
754 bool wxToolBar::MacTopLevelHasNativeToolbar(bool *ownToolbarInstalled) const
755 {
756 bool bResultV = false;
757
758 if (ownToolbarInstalled != NULL)
759 *ownToolbarInstalled = false;
760
761 WXWindow tlw = MacGetTopLevelWindowRef();
762 if (tlw != NULL)
763 {
764 NSToolbar* curToolbarRef = [tlw toolbar];
765 bResultV = (curToolbarRef != NULL);
766 if (bResultV && (ownToolbarInstalled != NULL))
767 *ownToolbarInstalled = (curToolbarRef == m_macToolbar);
768 }
769
770 return bResultV;
771 }
772
773 bool wxToolBar::MacInstallNativeToolbar(bool usesNative)
774 {
775 bool bResult = false;
776
777 if (usesNative && (m_macToolbar == NULL))
778 return bResult;
779
780 if (usesNative && ((GetWindowStyleFlag() & wxTB_VERTICAL) != 0))
781 return bResult;
782
783 WXWindow tlw = MacGetTopLevelWindowRef();
784 if (tlw == NULL)
785 return bResult;
786
787 // check the existing toolbar
788 NSToolbar* curToolbarRef = [tlw toolbar];
789
790 m_macUsesNativeToolbar = usesNative;
791
792 if (m_macUsesNativeToolbar)
793 {
794 // only install toolbar if there isn't one installed already
795 if (curToolbarRef == NULL)
796 {
797 bResult = true;
798 [tlw setToolbar:(NSToolbar*) m_macToolbar];
799 [(NSToolbar*) m_macToolbar setVisible:YES];
800
801 m_peer->Move(0,0,0,0 );
802 SetSize( wxSIZE_AUTO_WIDTH, 0 );
803 m_peer->SetVisibility( false );
804 wxToolBarBase::Show( false );
805 }
806 }
807 else
808 {
809 // only deinstall toolbar if this is the installed one
810 if (m_macToolbar == curToolbarRef)
811 {
812 bResult = true;
813 [(NSToolbar*) m_macToolbar setVisible:NO];
814 [tlw setToolbar:nil];
815 m_peer->SetVisibility( true );
816 }
817 }
818
819 if (bResult)
820 InvalidateBestSize();
821
822 // wxLogDebug( wxT(" --> [%lx] - result [%s]"), (long)this, bResult ? wxT("T") : wxT("F") );
823 return bResult;
824 }
825 #endif
826
827 bool wxToolBar::Realize()
828 {
829 if (m_tools.GetCount() == 0)
830 return false;
831
832 int maxWidth = 0;
833 int maxHeight = 0;
834
835 int maxToolWidth = 0;
836 int maxToolHeight = 0;
837
838 int x = m_xMargin + kwxMacToolBarLeftMargin;
839 int y = m_yMargin + kwxMacToolBarTopMargin;
840
841 int tw, th;
842 GetSize( &tw, &th );
843
844 // find the maximum tool width and height
845 wxToolBarTool *tool;
846 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
847 while ( node )
848 {
849 tool = (wxToolBarTool *) node->GetData();
850 if ( tool != NULL )
851 {
852 wxSize sz = tool->GetSize();
853
854 if ( sz.x > maxToolWidth )
855 maxToolWidth = sz.x;
856 if ( sz.y > maxToolHeight )
857 maxToolHeight = sz.y;
858 }
859
860 node = node->GetNext();
861 }
862
863 bool lastIsRadio = false;
864 bool curIsRadio = false;
865
866 #if wxOSX_USE_NATIVE_TOOLBAR
867 CFIndex currentPosition = 0;
868 bool insertAll = false;
869
870 NSToolbar* refTB = (NSToolbar*)m_macToolbar;
871 wxFont f;
872 wxFontEncoding enc;
873 f = GetFont();
874 if ( f.IsOk() )
875 enc = f.GetEncoding();
876 else
877 enc = wxFont::GetDefaultEncoding();
878 #endif
879
880 node = m_tools.GetFirst();
881 while ( node )
882 {
883 tool = (wxToolBarTool*) node->GetData();
884 if ( tool == NULL )
885 {
886 node = node->GetNext();
887 continue;
888 }
889
890 // set tool position:
891 // for the moment just perform a single row/column alignment
892 wxSize cursize = tool->GetSize();
893 if ( x + cursize.x > maxWidth )
894 maxWidth = x + cursize.x;
895 if ( y + cursize.y > maxHeight )
896 maxHeight = y + cursize.y;
897
898 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
899 {
900 int x1 = x + ( maxToolWidth - cursize.x ) / 2;
901 tool->SetPosition( wxPoint(x1, y) );
902 }
903 else
904 {
905 int y1 = y + ( maxToolHeight - cursize.y ) / 2;
906 tool->SetPosition( wxPoint(x, y1) );
907 }
908
909 // update the item positioning state
910 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
911 y += cursize.y + kwxMacToolSpacing;
912 else
913 x += cursize.x + kwxMacToolSpacing;
914
915 #if wxOSX_USE_NATIVE_TOOLBAR
916 // install in native NSToolbar
917 if ( refTB )
918 {
919 NSToolbarItem* hiItemRef = tool->GetToolbarItemRef();
920 if ( hiItemRef != NULL )
921 {
922 // since setting the help texts is non-virtual we have to update
923 // the strings now
924 wxCFStringRef sh( tool->GetShortHelp(), enc);
925 [hiItemRef setToolTip:sh.AsNSString()];
926
927 if ( insertAll || (tool->GetIndex() != currentPosition) )
928 {
929 if ( !insertAll )
930 {
931 insertAll = true;
932
933 // if this is the first tool that gets newly inserted or repositioned
934 // first remove all 'old' tools from here to the right, because of this
935 // all following tools will have to be reinserted (insertAll).
936 for ( wxToolBarToolsList::compatibility_iterator node2 = m_tools.GetLast();
937 node2 != node;
938 node2 = node2->GetPrevious() )
939 {
940 wxToolBarTool *tool2 = (wxToolBarTool*) node2->GetData();
941
942 const long idx = tool2->GetIndex();
943 if ( idx != -1 )
944 {
945 [refTB removeItemAtIndex:idx];
946 tool2->SetIndex(-1);
947 }
948 }
949 }
950 wxString identifier = wxString::Format( wxT("%ld"), (long) tool );
951 wxCFStringRef cfidentifier(identifier);
952
953 [refTB insertItemWithItemIdentifier:cfidentifier.AsNSString() atIndex:currentPosition];
954 tool->SetIndex( currentPosition );
955 }
956
957 currentPosition++;
958 }
959 }
960 #endif
961
962 // update radio button (and group) state
963 lastIsRadio = curIsRadio;
964 curIsRadio = ( tool->IsButton() && (tool->GetKind() == wxITEM_RADIO) );
965
966 if ( !curIsRadio )
967 {
968 if ( tool->IsToggled() )
969 DoToggleTool( tool, true );
970 }
971 else
972 {
973 if ( !lastIsRadio )
974 {
975 if ( tool->Toggle( true ) )
976 {
977 DoToggleTool( tool, true );
978 }
979 }
980 else if ( tool->IsToggled() )
981 {
982 if ( tool->IsToggled() )
983 DoToggleTool( tool, true );
984
985 wxToolBarToolsList::compatibility_iterator nodePrev = node->GetPrevious();
986 while ( nodePrev )
987 {
988 wxToolBarToolBase *toggleTool = nodePrev->GetData();
989 if ( (toggleTool == NULL) || !toggleTool->IsButton() || (toggleTool->GetKind() != wxITEM_RADIO) )
990 break;
991
992 if ( toggleTool->Toggle( false ) )
993 DoToggleTool( toggleTool, false );
994
995 nodePrev = nodePrev->GetPrevious();
996 }
997 }
998 }
999
1000 node = node->GetNext();
1001 }
1002
1003 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
1004 {
1005 // if not set yet, only one row
1006 if ( m_maxRows <= 0 )
1007 SetRows( 1 );
1008
1009 m_minWidth = maxWidth;
1010 maxWidth = tw;
1011 maxHeight += m_yMargin + kwxMacToolBarTopMargin;
1012 m_minHeight = m_maxHeight = maxHeight;
1013 }
1014 else
1015 {
1016 // if not set yet, have one column
1017 if ( (GetToolsCount() > 0) && (m_maxRows <= 0) )
1018 SetRows( GetToolsCount() );
1019
1020 m_minHeight = maxHeight;
1021 maxHeight = th;
1022 maxWidth += m_xMargin + kwxMacToolBarLeftMargin;
1023 m_minWidth = m_maxWidth = maxWidth;
1024 }
1025
1026 #if 0
1027 // FIXME: should this be OSX-only?
1028 {
1029 bool wantNativeToolbar, ownToolbarInstalled;
1030
1031 // attempt to install the native toolbar
1032 wantNativeToolbar = ((GetWindowStyleFlag() & wxTB_VERTICAL) == 0);
1033 MacInstallNativeToolbar( wantNativeToolbar );
1034 (void)MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
1035 if (!ownToolbarInstalled)
1036 {
1037 SetSize( maxWidth, maxHeight );
1038 InvalidateBestSize();
1039 }
1040 }
1041 #else
1042 SetSize( maxWidth, maxHeight );
1043 InvalidateBestSize();
1044 #endif
1045
1046 SetInitialSize();
1047
1048 return true;
1049 }
1050
1051 void wxToolBar::SetToolBitmapSize(const wxSize& size)
1052 {
1053 m_defaultWidth = size.x + kwxMacToolBorder;
1054 m_defaultHeight = size.y + kwxMacToolBorder;
1055
1056 #if wxOSX_USE_NATIVE_TOOLBAR
1057 if (m_macToolbar != NULL)
1058 {
1059 int maxs = wxMax( size.x, size.y );
1060 NSToolbarSizeMode sizeSpec;
1061 if ( maxs > 32 )
1062 sizeSpec = NSToolbarSizeModeRegular;
1063 else if ( maxs > 24 )
1064 sizeSpec = NSToolbarSizeModeDefault;
1065 else
1066 sizeSpec = NSToolbarSizeModeSmall;
1067
1068 [(NSToolbar*) m_macToolbar setSizeMode:sizeSpec ];
1069 }
1070 #endif
1071 }
1072
1073 // The button size is bigger than the bitmap size
1074 wxSize wxToolBar::GetToolSize() const
1075 {
1076 return wxSize(m_defaultWidth + kwxMacToolBorder, m_defaultHeight + kwxMacToolBorder);
1077 }
1078
1079 void wxToolBar::SetRows(int nRows)
1080 {
1081 // avoid resizing the frame uselessly
1082 if ( nRows != m_maxRows )
1083 m_maxRows = nRows;
1084 }
1085
1086 void wxToolBar::MacSuperChangedPosition()
1087 {
1088 wxWindow::MacSuperChangedPosition();
1089
1090 #if wxOSX_USE_NATIVE_TOOLBAR
1091 if (! m_macUsesNativeToolbar )
1092 Realize();
1093 #else
1094
1095 Realize();
1096 #endif
1097 }
1098
1099 void wxToolBar::SetToolNormalBitmap( int id, const wxBitmap& bitmap )
1100 {
1101 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
1102 if ( tool )
1103 {
1104 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
1105
1106 tool->SetNormalBitmap(bitmap);
1107
1108 // a side-effect of the UpdateToggleImage function is that it always changes the bitmap used on the button.
1109 tool->UpdateImages();
1110 }
1111 }
1112
1113 void wxToolBar::SetToolDisabledBitmap( int id, const wxBitmap& bitmap )
1114 {
1115 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
1116 if ( tool )
1117 {
1118 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
1119
1120 tool->SetDisabledBitmap(bitmap);
1121
1122 // TODO: what to do for this one?
1123 }
1124 }
1125
1126 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
1127 {
1128 wxToolBarTool *tool;
1129 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1130 while ( node )
1131 {
1132 tool = (wxToolBarTool *)node->GetData();
1133 if (tool != NULL)
1134 {
1135 wxRect2DInt r( tool->GetPosition(), tool->GetSize() );
1136 if ( r.Contains( wxPoint( x, y ) ) )
1137 return tool;
1138 }
1139
1140 node = node->GetNext();
1141 }
1142
1143 return (wxToolBarToolBase*)NULL;
1144 }
1145
1146 wxString wxToolBar::MacGetToolTipString( wxPoint &pt )
1147 {
1148 wxToolBarToolBase *tool = FindToolForPosition( pt.x, pt.y );
1149 if ( tool != NULL )
1150 return tool->GetShortHelp();
1151
1152 return wxEmptyString;
1153 }
1154
1155 void wxToolBar::DoEnableTool(wxToolBarToolBase *t, bool enable)
1156 {
1157 if ( t != NULL )
1158 ((wxToolBarTool*)t)->DoEnable( enable );
1159 }
1160
1161 void wxToolBar::DoToggleTool(wxToolBarToolBase *t, bool toggle)
1162 {
1163 wxToolBarTool *tool = (wxToolBarTool *)t;
1164 if ( ( tool != NULL ) && tool->IsButton() )
1165 tool->UpdateToggleImage( toggle );
1166 }
1167
1168 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
1169 {
1170 wxToolBarTool *tool = wx_static_cast( wxToolBarTool*, toolBase );
1171 if (tool == NULL)
1172 return false;
1173
1174 wxSize toolSize = GetToolSize();
1175 WXWidget controlHandle = NULL;
1176 NSRect toolrect = NSMakeRect(0, 0, toolSize.x, toolSize.y );
1177
1178 #if wxOSX_USE_NATIVE_TOOLBAR
1179 wxString label = tool->GetLabel();
1180 if (m_macToolbar && !label.empty() )
1181 {
1182 // strip mnemonics from the label for compatibility
1183 // with the usual labels in wxStaticText sense
1184 label = wxStripMenuCodes(label);
1185 }
1186 #endif // wxOSX_USE_NATIVE_TOOLBAR
1187
1188 switch (tool->GetStyle())
1189 {
1190 case wxTOOL_STYLE_SEPARATOR:
1191 {
1192 wxASSERT( tool->GetControlHandle() == NULL );
1193 toolSize.x /= 4;
1194 toolSize.y /= 4;
1195 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1196 toolrect.size.height = toolSize.y;
1197 else
1198 toolrect.size.width = toolSize.x;
1199
1200 // in flat style we need a visual separator
1201 #if wxOSX_USE_NATIVE_TOOLBAR
1202 if (m_macToolbar != NULL)
1203 {
1204 NSToolbarItem* item = [[NSToolbarItem alloc] initWithItemIdentifier:NSToolbarSeparatorItemIdentifier];
1205 tool->SetToolbarItemRef( item );
1206 }
1207 #endif // wxOSX_USE_NATIVE_TOOLBAR
1208
1209 NSBox* box = [[NSBox alloc] initWithFrame:toolrect];
1210 [box setBoxType:NSBoxSeparator];
1211 controlHandle = box;
1212 tool->SetControlHandle( controlHandle );
1213 }
1214 break;
1215
1216 case wxTOOL_STYLE_BUTTON:
1217 {
1218 wxASSERT( tool->GetControlHandle() == NULL );
1219
1220 wxNSToolBarButton* v = [[wxNSToolBarButton alloc] initWithFrame:toolrect];
1221
1222 [v setBezelStyle:NSRegularSquareBezelStyle];
1223 [v setBordered:NO];
1224 [v setButtonType: ( tool->CanBeToggled() ? NSOnOffButton : NSMomentaryPushInButton )];
1225 [v setImplementation:tool];
1226
1227 controlHandle = v;
1228
1229 #if wxOSX_USE_NATIVE_TOOLBAR
1230 if (m_macToolbar != NULL)
1231 {
1232 wxString identifier = wxString::Format(wxT("%ld"), (long) tool);
1233 wxCFStringRef cfidentifier( identifier, wxFont::GetDefaultEncoding() );
1234 wxNSToolbarItem* item = [[wxNSToolbarItem alloc] initWithItemIdentifier:cfidentifier.AsNSString() ];
1235 [item setImplementation:tool];
1236 tool->SetToolbarItemRef( item );
1237 }
1238
1239 #endif // wxOSX_USE_NATIVE_TOOLBAR
1240 tool->SetControlHandle( controlHandle );
1241 tool->UpdateImages();
1242 tool->UpdateLabel();
1243 #if 0
1244 SetBevelButtonTextPlacement( m_controlHandle, kControlBevelButtonPlaceBelowGraphic );
1245 SetControlTitleWithCFString( m_controlHandle , wxCFStringRef( label, wxFont::GetDefaultEncoding() );
1246 #endif
1247 #if 0
1248 InstallControlEventHandler(
1249 (WXWidget) controlHandle, GetwxMacToolBarToolEventHandlerUPP(),
1250 GetEventTypeCount(eventList), eventList, tool, NULL );
1251 #endif
1252 }
1253 break;
1254
1255 case wxTOOL_STYLE_CONTROL:
1256
1257 #if wxOSX_USE_NATIVE_TOOLBAR
1258 if (m_macToolbar != NULL)
1259 {
1260 WXWidget view = (WXWidget) tool->GetControl()->GetHandle() ;
1261 wxCHECK_MSG( view, false, _T("control must be non-NULL") );
1262
1263 wxString identifier = wxString::Format(wxT("%ld"), (long) tool);
1264 wxCFStringRef cfidentifier( identifier, wxFont::GetDefaultEncoding() );
1265 wxNSToolbarItem* item = [[wxNSToolbarItem alloc] initWithItemIdentifier:cfidentifier.AsNSString() ];
1266 [item setImplementation:tool];
1267 tool->SetToolbarItemRef( item );
1268 }
1269 #else
1270 // right now there's nothing to do here
1271 #endif
1272 tool->UpdateLabel();
1273 break;
1274
1275 default:
1276 break;
1277 }
1278
1279 if ( controlHandle )
1280 {
1281 WXWidget container = (WXWidget) GetHandle();
1282 wxASSERT_MSG( container != NULL, wxT("No valid Mac container control") );
1283
1284 // SetControlVisibility( controlHandle, true, true );
1285 [container addSubview:controlHandle];
1286 }
1287
1288 // nothing special to do here - we relayout in Realize() later
1289 InvalidateBestSize();
1290
1291 return true;
1292
1293 }
1294
1295 void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
1296 {
1297 wxFAIL_MSG( wxT("not implemented") );
1298 }
1299
1300 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolbase)
1301 {
1302 wxToolBarTool* tool = wx_static_cast( wxToolBarTool*, toolbase );
1303 wxToolBarToolsList::compatibility_iterator node;
1304 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
1305 {
1306 wxToolBarToolBase *tool2 = node->GetData();
1307 if ( tool2 == tool )
1308 {
1309 // let node point to the next node in the list
1310 node = node->GetNext();
1311
1312 break;
1313 }
1314 }
1315
1316 wxSize sz = ((wxToolBarTool*)tool)->GetSize();
1317
1318 #if wxOSX_USE_NATIVE_TOOLBAR
1319 CFIndex removeIndex = tool->GetIndex();
1320 #endif
1321
1322 #if wxOSX_USE_NATIVE_TOOLBAR
1323 if (m_macToolbar != NULL)
1324 {
1325 if ( removeIndex != -1 && m_macToolbar )
1326 {
1327 [(NSToolbar*) m_macToolbar removeItemAtIndex:removeIndex];
1328 tool->SetIndex( -1 );
1329 }
1330 }
1331 #endif
1332
1333 tool->ClearControl();
1334
1335 // and finally reposition all the controls after this one
1336
1337 for ( /* node -> first after deleted */; node; node = node->GetNext() )
1338 {
1339 wxToolBarTool *tool2 = (wxToolBarTool*) node->GetData();
1340 wxPoint pt = tool2->GetPosition();
1341
1342 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
1343 pt.y -= sz.y;
1344 else
1345 pt.x -= sz.x;
1346
1347 tool2->SetPosition( pt );
1348
1349 #if wxOSX_USE_NATIVE_TOOLBAR
1350 if (m_macToolbar != NULL)
1351 {
1352 if ( removeIndex != -1 && tool2->GetIndex() > removeIndex )
1353 tool2->SetIndex( tool2->GetIndex() - 1 );
1354 }
1355 #endif
1356 }
1357
1358 InvalidateBestSize();
1359
1360 return true;
1361 }
1362
1363 #include <Carbon/Carbon.h>
1364
1365 void wxToolBar::OnPaint(wxPaintEvent& event)
1366 {
1367 #if wxOSX_USE_NATIVE_TOOLBAR
1368 if ( m_macUsesNativeToolbar )
1369 {
1370 event.Skip(true);
1371 return;
1372 }
1373 #endif
1374
1375 wxPaintDC dc(this);
1376
1377 int w, h;
1378 GetSize( &w, &h );
1379
1380 bool drawMetalTheme = MacGetTopLevelWindow()->GetExtraStyle() & wxFRAME_EX_METAL;
1381
1382 if ( !drawMetalTheme )
1383 {
1384 HIThemePlacardDrawInfo info;
1385 memset( &info, 0, sizeof(info) );
1386 info.version = 0;
1387 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive;
1388
1389 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef();
1390 HIRect rect = CGRectMake( 0, 0, w, h );
1391 HIThemeDrawPlacard( &rect, &info, cgContext, kHIThemeOrientationNormal );
1392 }
1393 else
1394 {
1395 // leave the background as it is (striped or metal)
1396 }
1397
1398 event.Skip();
1399 }
1400
1401 #endif // wxUSE_TOOLBAR