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