]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/mac/carbon/toolbar.cpp
update from Hans F. Nordhaug
[wxWidgets.git] / src / mac / carbon / toolbar.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: 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: The wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13#pragma implementation "toolbar.h"
14#endif
15
16#include "wx/wxprec.h"
17
18#if wxUSE_TOOLBAR
19
20#include "wx/wx.h"
21#include "wx/toolbar.h"
22#include "wx/notebook.h"
23#include "wx/tabctrl.h"
24#include "wx/bitmap.h"
25
26#if !USE_SHARED_LIBRARY
27IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
28
29BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
30 EVT_PAINT( wxToolBar::OnPaint )
31END_EVENT_TABLE()
32#endif
33
34#include "wx/mac/uma.h"
35#include "wx/geometry.h"
36
37#ifdef __WXMAC_OSX__
38const short kwxMacToolBarToolDefaultWidth = 32 ;
39const short kwxMacToolBarToolDefaultHeight = 32 ;
40const short kwxMacToolBarTopMargin = 4 ;
41const short kwxMacToolBarLeftMargin = 4 ;
42const short kwxMacToolBorder = 0 ;
43#else
44const short kwxMacToolBarToolDefaultWidth = 24 ;
45const short kwxMacToolBarToolDefaultHeight = 22 ;
46const short kwxMacToolBarTopMargin = 2 ;
47const short kwxMacToolBarLeftMargin = 2 ;
48const short kwxMacToolBorder = 4 ;
49#endif
50
51// ----------------------------------------------------------------------------
52// private classes
53// ----------------------------------------------------------------------------
54
55class wxToolBarTool : public wxToolBarToolBase
56{
57public:
58 wxToolBarTool(wxToolBar *tbar,
59 int id,
60 const wxString& label,
61 const wxBitmap& bmpNormal,
62 const wxBitmap& bmpDisabled,
63 wxItemKind kind,
64 wxObject *clientData,
65 const wxString& shortHelp,
66 const wxString& longHelp) ;
67
68 wxToolBarTool(wxToolBar *tbar, wxControl *control)
69 : wxToolBarToolBase(tbar, control)
70 {
71 Init() ;
72 }
73
74 ~wxToolBarTool()
75 {
76 if ( m_controlHandle )
77 DisposeControl( m_controlHandle ) ;
78 }
79
80 WXWidget GetControlHandle() { return (WXWidget) m_controlHandle ; }
81 void SetControlHandle( ControlRef handle ) { m_controlHandle = handle ; }
82
83 void SetSize(const wxSize& size) ;
84 void SetPosition( const wxPoint& position ) ;
85
86 wxSize GetSize() const
87 {
88 if ( IsControl() )
89 {
90 return GetControl()->GetSize() ;
91 }
92 else if ( IsButton() )
93 {
94 return GetToolBar()->GetToolSize() ;
95 }
96 else
97 {
98 wxSize sz = GetToolBar()->GetToolSize() ;
99 sz.x /= 4 ;
100 sz.y /= 4 ;
101 return sz ;
102 }
103 }
104 wxPoint GetPosition() const
105 {
106 return wxPoint(m_x, m_y);
107 }
108 bool DoEnable( bool enable ) ;
109private :
110 void Init()
111 {
112 m_controlHandle = NULL ;
113 }
114 ControlRef m_controlHandle ;
115
116 wxCoord m_x;
117 wxCoord m_y;
118};
119
120static const EventTypeSpec eventList[] =
121{
122 { kEventClassControl , kEventControlHit } ,
123} ;
124
125static pascal OSStatus wxMacToolBarToolControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
126{
127 OSStatus result = eventNotHandledErr ;
128
129 wxMacCarbonEvent cEvent( event ) ;
130
131 ControlRef controlRef ;
132
133 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
134
135 switch( GetEventKind( event ) )
136 {
137 case kEventControlHit :
138 {
139 wxToolBarTool* tbartool = (wxToolBarTool*)data ;
140 if ( tbartool->CanBeToggled() )
141 {
142 ((wxToolBar*)tbartool->GetToolBar())->ToggleTool(tbartool->GetId(), GetControl32BitValue((ControlRef)tbartool->GetControlHandle()));
143 }
144 ((wxToolBar*)tbartool->GetToolBar())->OnLeftClick( tbartool->GetId() , tbartool -> IsToggled() ) ;
145 result = noErr;
146 }
147 break ;
148 default :
149 break ;
150 }
151 return result ;
152}
153
154pascal OSStatus wxMacToolBarToolEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
155{
156 OSStatus result = eventNotHandledErr ;
157
158 switch ( GetEventClass( event ) )
159 {
160 case kEventClassControl :
161 result = wxMacToolBarToolControlEventHandler( handler, event, data ) ;
162 break ;
163 default :
164 break ;
165 }
166 return result ;
167}
168
169DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacToolBarToolEventHandler )
170
171// ============================================================================
172// implementation
173// ============================================================================
174
175// ----------------------------------------------------------------------------
176// wxToolBarTool
177// ----------------------------------------------------------------------------
178
179bool wxToolBarTool::DoEnable(bool enable)
180{
181 if ( IsControl() )
182 {
183 GetControl()->Enable( enable ) ;
184 }
185 else if ( IsButton() )
186 {
187#if TARGET_API_MAC_OSX
188 if ( enable )
189 EnableControl( m_controlHandle ) ;
190 else
191 DisableControl( m_controlHandle ) ;
192#else
193 if ( enable )
194 ActivateControl( m_controlHandle ) ;
195 else
196 DeactivateControl( m_controlHandle ) ;
197#endif
198 }
199 return true ;
200}
201void wxToolBarTool::SetSize(const wxSize& size)
202{
203 if ( IsControl() )
204 {
205 GetControl()->SetSize( size ) ;
206 }
207}
208
209void wxToolBarTool::SetPosition(const wxPoint& position)
210{
211 m_x = position.x;
212 m_y = position.y;
213
214 if ( IsButton() )
215 {
216 int x , y ;
217 x = y = 0 ;
218 int mac_x = position.x ;
219 int mac_y = position.y ;
220#ifdef __WXMAC_OSX__
221 wxSize toolSize = m_tbar->GetToolSize() ;
222 int iconsize = 16 ;
223 if ( toolSize.x >= 32 && toolSize.y >= 32)
224 {
225 iconsize = 32 ;
226 }
227 mac_x += ( toolSize.x - iconsize ) / 2 ;
228 mac_y += ( toolSize.y - iconsize ) / 2 ;
229#else
230 WindowRef rootwindow = (WindowRef) GetToolBar()->MacGetTopLevelWindowRef() ;
231 GetToolBar()->MacWindowToRootWindow( &x , &y ) ;
232 mac_x += x;
233 mac_y += y;
234#endif
235 Rect contrlRect ;
236 GetControlBounds( m_controlHandle , &contrlRect ) ;
237 int former_mac_x = contrlRect.left ;
238 int former_mac_y = contrlRect.top ;
239 GetToolBar()->GetToolSize() ;
240
241 if ( mac_x != former_mac_x || mac_y != former_mac_y )
242 {
243 UMAMoveControl( m_controlHandle , mac_x , mac_y ) ;
244 }
245 }
246 else if ( IsControl() )
247 {
248 GetControl()->Move( position ) ;
249 }
250}
251
252wxToolBarTool::wxToolBarTool(wxToolBar *tbar,
253 int id,
254 const wxString& label,
255 const wxBitmap& bmpNormal,
256 const wxBitmap& bmpDisabled,
257 wxItemKind kind,
258 wxObject *clientData,
259 const wxString& shortHelp,
260 const wxString& longHelp)
261 : wxToolBarToolBase(tbar, id, label, bmpNormal, bmpDisabled, kind,
262 clientData, shortHelp, longHelp)
263{
264 Init();
265
266 if (id == wxID_SEPARATOR) return;
267
268 WindowRef window = (WindowRef) tbar->MacGetTopLevelWindowRef() ;
269 wxSize toolSize = tbar->GetToolSize() ;
270 Rect toolrect = { 0, 0 , toolSize.y , toolSize.x } ;
271
272 ControlButtonContentInfo info ;
273 wxMacCreateBitmapButton( &info , GetNormalBitmap() ) ;
274
275 SInt16 behaviour = kControlBehaviorOffsetContents ;
276 if ( CanBeToggled() )
277 behaviour += kControlBehaviorToggles ;
278
279#ifdef __WXMAC_OSX__
280 int iconsize = 16 ;
281 if ( toolSize.x >= 32 && toolSize.y >= 32)
282 {
283 iconsize = 32 ;
284 }
285 toolrect.left += ( toolSize.x - iconsize ) / 2 ;
286 toolrect.right = toolrect.left + iconsize ;
287 toolrect.top += ( toolSize.y - iconsize ) / 2 ;
288 toolrect.bottom = toolrect.top + iconsize ;
289 CreateIconControl( window , &toolrect , &info , false , &m_controlHandle ) ;
290#else
291 CreateBevelButtonControl( window , &toolrect , CFSTR("") , kControlBevelButtonNormalBevel , behaviour , &info ,
292 0 , 0 , 0 , &m_controlHandle ) ;
293#endif
294
295 wxMacReleaseBitmapButton( &info ) ;
296 /*
297 SetBevelButtonTextPlacement( m_controlHandle , kControlBevelButtonPlaceBelowGraphic ) ;
298 UMASetControlTitle( m_controlHandle , label , wxFont::GetDefaultEncoding() ) ;
299 */
300
301 InstallControlEventHandler( (ControlRef) m_controlHandle, GetwxMacToolBarToolEventHandlerUPP(),
302 GetEventTypeCount(eventList), eventList, this,NULL);
303
304 UMAShowControl( m_controlHandle ) ;
305
306 if ( CanBeToggled() && IsToggled() )
307 ::SetControl32BitValue( m_controlHandle , 1 ) ;
308 else
309 ::SetControl32BitValue( m_controlHandle , 0 ) ;
310
311 ControlRef container = (ControlRef) tbar->GetHandle() ;
312 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
313 ::EmbedControl( m_controlHandle , container ) ;
314}
315
316
317wxToolBarToolBase *wxToolBar::CreateTool(int id,
318 const wxString& label,
319 const wxBitmap& bmpNormal,
320 const wxBitmap& bmpDisabled,
321 wxItemKind kind,
322 wxObject *clientData,
323 const wxString& shortHelp,
324 const wxString& longHelp)
325{
326 return new wxToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
327 clientData, shortHelp, longHelp);
328}
329
330wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
331{
332 return new wxToolBarTool(this, control);
333}
334
335void wxToolBar::Init()
336{
337 m_maxWidth = -1;
338 m_maxHeight = -1;
339 m_defaultWidth = kwxMacToolBarToolDefaultWidth;
340 m_defaultHeight = kwxMacToolBarToolDefaultHeight;
341}
342
343bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
344 long style, const wxString& name)
345{
346
347 if ( !wxToolBarBase::Create( parent , id , pos , size , style ) )
348 return FALSE ;
349
350 return TRUE;
351}
352
353wxToolBar::~wxToolBar()
354{
355 // we must refresh the frame size when the toolbar is deleted but the frame
356 // is not - otherwise toolbar leaves a hole in the place it used to occupy
357}
358
359bool wxToolBar::Realize()
360{
361 if (m_tools.GetCount() == 0)
362 return FALSE;
363
364 int x = m_xMargin + kwxMacToolBarLeftMargin ;
365 int y = m_yMargin + kwxMacToolBarTopMargin ;
366
367 int tw, th;
368 GetSize(& tw, & th);
369
370 int maxWidth = 0 ;
371 int maxHeight = 0 ;
372
373 int maxToolWidth = 0;
374 int maxToolHeight = 0;
375
376 // Find the maximum tool width and height
377 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
378 while ( node )
379 {
380 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
381 wxSize sz = tool->GetSize() ;
382
383 if ( sz.x > maxToolWidth )
384 maxToolWidth = sz.x ;
385 if (sz.y> maxToolHeight)
386 maxToolHeight = sz.y;
387
388 node = node->GetNext();
389 }
390
391 bool lastWasRadio = FALSE;
392 node = m_tools.GetFirst();
393 while (node)
394 {
395 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
396 wxSize cursize = tool->GetSize() ;
397
398 bool isRadio = FALSE;
399
400 if ( tool->IsButton() && tool->GetKind() == wxITEM_RADIO )
401 {
402 if ( !lastWasRadio )
403 {
404 if (tool->Toggle(true))
405 {
406 DoToggleTool(tool, true);
407 }
408 }
409 isRadio = TRUE;
410 }
411 else
412 {
413 isRadio = FALSE;
414 }
415 lastWasRadio = isRadio;
416
417 // for the moment we just do a single row/column alignement
418 if ( x + cursize.x > maxWidth )
419 maxWidth = x + cursize.x ;
420 if ( y + cursize.y > maxHeight )
421 maxHeight = y + cursize.y ;
422
423 tool->SetPosition( wxPoint( x , y ) ) ;
424
425 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
426 {
427 y += cursize.y ;
428 }
429 else
430 {
431 x += cursize.x ;
432 }
433
434 node = node->GetNext();
435 }
436
437 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
438 {
439 if ( m_maxRows == 0 )
440 {
441 // if not set yet, only one row
442 SetRows(1);
443 }
444 m_minWidth = maxWidth;
445 maxWidth = tw ;
446 maxHeight += m_yMargin + kwxMacToolBarTopMargin;
447 m_minHeight = m_maxHeight = maxHeight ;
448 }
449 else
450 {
451 if ( GetToolsCount() > 0 && m_maxRows == 0 )
452 {
453 // if not set yet, have one column
454 SetRows(GetToolsCount());
455 }
456 m_minHeight = maxHeight;
457 maxHeight = th ;
458 maxWidth += m_xMargin + kwxMacToolBarLeftMargin;
459 m_minWidth = m_maxWidth = maxWidth ;
460 }
461
462 SetSize( maxWidth, maxHeight );
463 InvalidateBestSize();
464
465 return TRUE;
466}
467
468void wxToolBar::SetToolBitmapSize(const wxSize& size)
469{
470 m_defaultWidth = size.x+kwxMacToolBorder; m_defaultHeight = size.y+kwxMacToolBorder;
471}
472
473// The button size is bigger than the bitmap size
474wxSize wxToolBar::GetToolSize() const
475{
476 return wxSize(m_defaultWidth + kwxMacToolBorder, m_defaultHeight + kwxMacToolBorder);
477}
478
479void wxToolBar::SetRows(int nRows)
480{
481 if ( nRows == m_maxRows )
482 {
483 // avoid resizing the frame uselessly
484 return;
485 }
486
487 m_maxRows = nRows;
488}
489
490void wxToolBar::MacSuperChangedPosition()
491{
492 wxWindow::MacSuperChangedPosition() ;
493 Realize() ;
494}
495
496wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
497{
498 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
499 while (node)
500 {
501 wxToolBarTool *tool = (wxToolBarTool *)node->GetData() ;
502 wxRect2DInt r( tool->GetPosition() , tool->GetSize() ) ;
503 if ( r.Contains( wxPoint( x , y ) ) )
504 {
505 return tool;
506 }
507
508 node = node->GetNext();
509 }
510
511 return (wxToolBarToolBase *)NULL;
512}
513
514wxString wxToolBar::MacGetToolTipString( wxPoint &pt )
515{
516 wxToolBarToolBase* tool = FindToolForPosition( pt.x , pt.y ) ;
517 if ( tool )
518 {
519 return tool->GetShortHelp() ;
520 }
521 return wxEmptyString ;
522}
523
524void wxToolBar::DoEnableTool(wxToolBarToolBase *t, bool enable)
525{
526 ((wxToolBarTool*)t)->DoEnable( enable ) ;
527}
528
529void wxToolBar::DoToggleTool(wxToolBarToolBase *t, bool toggle)
530{
531 wxToolBarTool *tool = (wxToolBarTool *)t;
532 if ( tool->IsButton() )
533 {
534#ifdef __WXMAC_OSX__
535 IconTransformType transform = toggle ? kTransformSelected : kTransformNone ;
536 SetControlData( (ControlRef) tool->GetControlHandle(), 0, kControlIconTransformTag, sizeof( transform ),
537 (Ptr)&transform );
538#else
539 ::SetControl32BitValue( (ControlRef) tool->GetControlHandle() , toggle ) ;
540#endif
541 }
542}
543
544bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
545 wxToolBarToolBase *tool)
546{
547 // nothing special to do here - we relayout in Realize() later
548 tool->Attach(this);
549 InvalidateBestSize();
550
551 return TRUE;
552}
553
554void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
555{
556 wxFAIL_MSG( _T("not implemented") );
557}
558
559bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
560{
561 wxToolBarToolsList::compatibility_iterator node;
562 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
563 {
564 wxToolBarToolBase *tool2 = node->GetData();
565 if ( tool2 == tool )
566 {
567 // let node point to the next node in the list
568 node = node->GetNext();
569
570 break;
571 }
572 }
573
574 wxSize sz = ((wxToolBarTool*)tool)->GetSize() ;
575
576 tool->Detach();
577
578 // and finally reposition all the controls after this one
579
580 for ( /* node -> first after deleted */ ; node; node = node->GetNext() )
581 {
582 wxToolBarTool *tool2 = (wxToolBarTool*) node->GetData();
583 wxPoint pt = tool2->GetPosition() ;
584
585 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
586 {
587 pt.y -= sz.y ;
588 }
589 else
590 {
591 pt.x -= sz.x ;
592 }
593 tool2->SetPosition( pt ) ;
594 }
595
596 InvalidateBestSize();
597 return TRUE ;
598}
599
600void wxToolBar::OnPaint(wxPaintEvent& event)
601{
602 wxPaintDC dc(this) ;
603#if wxMAC_USE_CORE_GRAPHICS
604 // leave the background as it is (striped or metal)
605#else
606 wxMacPortSetter helper(&dc) ;
607 int w, h ;
608 GetSize( &w , &h ) ;
609
610 Rect toolbarrect = { dc.YLOG2DEVMAC(0) , dc.XLOG2DEVMAC(0) ,
611 dc.YLOG2DEVMAC(h) , dc.XLOG2DEVMAC(w) } ;
612/*
613 if( toolbarrect.left < 0 )
614 toolbarrect.left = 0 ;
615 if ( toolbarrect.top < 0 )
616 toolbarrect.top = 0 ;
617*/
618 if ( !MacGetTopLevelWindow()->MacGetMetalAppearance() )
619 {
620 UMADrawThemePlacard( &toolbarrect , IsEnabled() ? kThemeStateActive : kThemeStateInactive) ;
621 }
622 else
623 {
624#if TARGET_API_MAC_OSX
625#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
626 if ( UMAGetSystemVersion() >= 0x1030 )
627 {
628 HIRect hiToolbarrect = CGRectMake( dc.YLOG2DEVMAC(0) , dc.XLOG2DEVMAC(0) ,
629 dc.YLOG2DEVREL(h) , dc.XLOG2DEVREL(w) );
630 CGContextRef cgContext ;
631 Rect bounds ;
632 GetPortBounds( (CGrafPtr) dc.m_macPort , &bounds ) ;
633 QDBeginCGContext( (CGrafPtr) dc.m_macPort , &cgContext ) ;
634 CGContextTranslateCTM( cgContext , 0 , bounds.bottom - bounds.top ) ;
635 CGContextScaleCTM( cgContext , 1 , -1 ) ;
636
637 {
638 HIThemeBackgroundDrawInfo drawInfo ;
639 drawInfo.version = 0 ;
640 drawInfo.state = kThemeStateActive ;
641 drawInfo.kind = kThemeBackgroundMetal ;
642 HIThemeApplyBackground( &hiToolbarrect, &drawInfo , cgContext,kHIThemeOrientationNormal) ;
643 }
644 QDEndCGContext( (CGrafPtr) dc.m_macPort , &cgContext ) ;
645 }
646 else
647#endif
648 {
649 UMADrawThemePlacard( &toolbarrect , IsEnabled() ? kThemeStateActive : kThemeStateInactive) ;
650 }
651#endif
652 }
653#endif
654
655 event.Skip() ;
656}
657
658#endif // wxUSE_TOOLBAR
659