]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/mac/carbon/toolbar.cpp
Applied [ 1059554 ] patch for [1028659] fixes a couple of bugs with menus
[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// private classes
38// ----------------------------------------------------------------------------
39
40class wxToolBarTool : public wxToolBarToolBase
41{
42public:
43 wxToolBarTool(wxToolBar *tbar,
44 int id,
45 const wxString& label,
46 const wxBitmap& bmpNormal,
47 const wxBitmap& bmpDisabled,
48 wxItemKind kind,
49 wxObject *clientData,
50 const wxString& shortHelp,
51 const wxString& longHelp) ;
52
53 wxToolBarTool(wxToolBar *tbar, wxControl *control)
54 : wxToolBarToolBase(tbar, control)
55 {
56 Init() ;
57 }
58
59 ~wxToolBarTool()
60 {
61 if ( m_controlHandle )
62 DisposeControl( m_controlHandle ) ;
63 }
64
65 WXWidget GetControlHandle() { return (WXWidget) m_controlHandle ; }
66 void SetControlHandle( ControlRef handle ) { m_controlHandle = handle ; }
67
68 void SetSize(const wxSize& size) ;
69 void SetPosition( const wxPoint& position ) ;
70
71 wxSize GetSize() const
72 {
73 if ( IsControl() )
74 {
75 return GetControl()->GetSize() ;
76 }
77 else if ( IsButton() )
78 {
79 return GetToolBar()->GetToolSize() ;
80 }
81 else
82 {
83 wxSize sz = GetToolBar()->GetToolSize() ;
84 sz.x /= 4 ;
85 sz.y /= 4 ;
86 return sz ;
87 }
88 }
89 wxPoint GetPosition() const
90 {
91 return wxPoint(m_x, m_y);
92 }
93 bool DoEnable( bool enable ) ;
94private :
95 void Init()
96 {
97 m_controlHandle = NULL ;
98 }
99 ControlRef m_controlHandle ;
100
101 wxCoord m_x;
102 wxCoord m_y;
103};
104
105static const EventTypeSpec eventList[] =
106{
107 { kEventClassControl , kEventControlHit } ,
108} ;
109
110static pascal OSStatus wxMacToolBarToolControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
111{
112 OSStatus result = eventNotHandledErr ;
113
114 wxMacCarbonEvent cEvent( event ) ;
115
116 ControlRef controlRef ;
117
118 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
119
120 switch( GetEventKind( event ) )
121 {
122 case kEventControlHit :
123 {
124 wxToolBarTool* tbartool = (wxToolBarTool*)data ;
125 if ( tbartool->CanBeToggled() )
126 {
127 ((wxToolBar*)tbartool->GetToolBar())->ToggleTool(tbartool->GetId(), GetControl32BitValue((ControlRef)tbartool->GetControlHandle()));
128 }
129 ((wxToolBar*)tbartool->GetToolBar())->OnLeftClick( tbartool->GetId() , tbartool -> IsToggled() ) ;
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
156// ============================================================================
157// implementation
158// ============================================================================
159
160// ----------------------------------------------------------------------------
161// wxToolBarTool
162// ----------------------------------------------------------------------------
163
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}
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 ;
203 int mac_x = position.x ;
204 int mac_y = position.y ;
205#if !TARGET_API_MAC_OSX
206 WindowRef rootwindow = (WindowRef) GetToolBar()->MacGetTopLevelWindowRef() ;
207 GetToolBar()->MacWindowToRootWindow( &x , &y ) ;
208 mac_x += x;
209 mac_y += y;
210#endif
211 Rect contrlRect ;
212 GetControlBounds( m_controlHandle , &contrlRect ) ;
213 int former_mac_x = contrlRect.left ;
214 int former_mac_y = contrlRect.top ;
215 GetToolBar()->GetToolSize() ;
216
217 if ( mac_x != former_mac_x || mac_y != former_mac_y )
218 {
219 UMAMoveControl( m_controlHandle , mac_x , mac_y ) ;
220 }
221 }
222 else if ( IsControl() )
223 {
224 GetControl()->Move( position ) ;
225 }
226}
227
228const short kwxMacToolBarToolDefaultWidth = 24 ;
229const short kwxMacToolBarToolDefaultHeight = 22 ;
230const short kwxMacToolBarTopMargin = 2 ;
231const short kwxMacToolBarLeftMargin = 2 ;
232
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{
245 Init();
246
247 if (id == wxID_SEPARATOR) return;
248
249 WindowRef window = (WindowRef) tbar->MacGetTopLevelWindowRef() ;
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 ;
259
260 CreateBevelButtonControl( window , &toolrect , CFSTR("") , kControlBevelButtonNormalBevel , behaviour , &info ,
261 0 , 0 , 0 , &m_controlHandle ) ;
262
263 InstallControlEventHandler( (ControlRef) m_controlHandle, GetwxMacToolBarToolEventHandlerUPP(),
264 GetEventTypeCount(eventList), eventList, this,NULL);
265
266 UMAShowControl( m_controlHandle ) ;
267
268 if ( CanBeToggled() && IsToggled() )
269 ::SetControl32BitValue( m_controlHandle , 1 ) ;
270 else
271 ::SetControl32BitValue( m_controlHandle , 0 ) ;
272
273 ControlRef container = (ControlRef) tbar->GetHandle() ;
274 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
275 ::EmbedControl( m_controlHandle , container ) ;
276}
277
278
279wxToolBarToolBase *wxToolBar::CreateTool(int id,
280 const wxString& label,
281 const wxBitmap& bmpNormal,
282 const wxBitmap& bmpDisabled,
283 wxItemKind kind,
284 wxObject *clientData,
285 const wxString& shortHelp,
286 const wxString& longHelp)
287{
288 return new wxToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
289 clientData, shortHelp, longHelp);
290}
291
292wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
293{
294 return new wxToolBarTool(this, control);
295}
296
297void wxToolBar::Init()
298{
299 m_maxWidth = -1;
300 m_maxHeight = -1;
301 m_defaultWidth = kwxMacToolBarToolDefaultWidth;
302 m_defaultHeight = kwxMacToolBarToolDefaultHeight;
303}
304
305bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
306 long style, const wxString& name)
307{
308 if ( !wxToolBarBase::Create( parent , id , pos , size , style ) )
309 return FALSE ;
310
311 return TRUE;
312}
313
314wxToolBar::~wxToolBar()
315{
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
318}
319
320bool wxToolBar::Realize()
321{
322 if (m_tools.GetCount() == 0)
323 return FALSE;
324
325 int x = m_xMargin + kwxMacToolBarLeftMargin ;
326 int y = m_yMargin + kwxMacToolBarTopMargin ;
327
328 int tw, th;
329 GetSize(& tw, & th);
330
331 int maxWidth = 0 ;
332 int maxHeight = 0 ;
333
334 int maxToolWidth = 0;
335 int maxToolHeight = 0;
336
337 // Find the maximum tool width and height
338 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
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
352 bool lastWasRadio = FALSE;
353 node = m_tools.GetFirst();
354 while (node)
355 {
356 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
357 wxSize cursize = tool->GetSize() ;
358
359 bool isRadio = FALSE;
360
361 if ( tool->IsButton() && tool->GetKind() == wxITEM_RADIO )
362 {
363 if ( !lastWasRadio )
364 {
365 if (tool->Toggle(true))
366 {
367 DoToggleTool(tool, true);
368 }
369 }
370 isRadio = TRUE;
371 }
372 else
373 {
374 isRadio = FALSE;
375 }
376 lastWasRadio = isRadio;
377
378 // for the moment we just do a single row/column alignement
379 if ( x + cursize.x > maxWidth )
380 maxWidth = x + cursize.x ;
381 if ( y + cursize.y > maxHeight )
382 maxHeight = y + cursize.y ;
383
384 tool->SetPosition( wxPoint( x , y ) ) ;
385
386 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
387 {
388 y += cursize.y ;
389 }
390 else
391 {
392 x += cursize.x ;
393 }
394
395 node = node->GetNext();
396 }
397
398 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
399 {
400 if ( m_maxRows == 0 )
401 {
402 // if not set yet, only one row
403 SetRows(1);
404 }
405 m_minWidth = maxWidth;
406 maxWidth = tw ;
407 maxHeight += m_yMargin + kwxMacToolBarTopMargin;
408 m_minHeight = m_maxHeight = maxHeight ;
409 }
410 else
411 {
412 if ( GetToolsCount() > 0 && m_maxRows == 0 )
413 {
414 // if not set yet, have one column
415 SetRows(GetToolsCount());
416 }
417 m_minHeight = maxHeight;
418 maxHeight = th ;
419 maxWidth += m_xMargin + kwxMacToolBarLeftMargin;
420 m_minWidth = m_maxWidth = maxWidth ;
421 }
422
423 SetSize( maxWidth, maxHeight );
424 InvalidateBestSize();
425
426 return TRUE;
427}
428
429void wxToolBar::SetToolBitmapSize(const wxSize& size)
430{
431 m_defaultWidth = size.x+4; m_defaultHeight = size.y+4;
432}
433
434// The button size is bigger than the bitmap size
435wxSize wxToolBar::GetToolSize() const
436{
437 return wxSize(m_defaultWidth + 4, m_defaultHeight + 4);
438}
439
440void wxToolBar::SetRows(int nRows)
441{
442 if ( nRows == m_maxRows )
443 {
444 // avoid resizing the frame uselessly
445 return;
446 }
447
448 m_maxRows = nRows;
449}
450
451void wxToolBar::MacSuperChangedPosition()
452{
453 wxWindow::MacSuperChangedPosition() ;
454 Realize() ;
455}
456
457wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
458{
459 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
460 while (node)
461 {
462 wxToolBarTool *tool = (wxToolBarTool *)node->GetData() ;
463 wxRect2DInt r( tool->GetPosition() , tool->GetSize() ) ;
464 if ( r.Contains( wxPoint( x , y ) ) )
465 {
466 return tool;
467 }
468
469 node = node->GetNext();
470 }
471
472 return (wxToolBarToolBase *)NULL;
473}
474
475wxString wxToolBar::MacGetToolTipString( wxPoint &pt )
476{
477 wxToolBarToolBase* tool = FindToolForPosition( pt.x , pt.y ) ;
478 if ( tool )
479 {
480 return tool->GetShortHelp() ;
481 }
482 return wxEmptyString ;
483}
484
485void wxToolBar::DoEnableTool(wxToolBarToolBase *t, bool enable)
486{
487 ((wxToolBarTool*)t)->DoEnable( enable ) ;
488}
489
490void wxToolBar::DoToggleTool(wxToolBarToolBase *t, bool toggle)
491{
492 wxToolBarTool *tool = (wxToolBarTool *)t;
493 if ( tool->IsButton() )
494 {
495 ::SetControl32BitValue( (ControlRef) tool->GetControlHandle() , toggle ) ;
496 }
497}
498
499bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
500 wxToolBarToolBase *tool)
501{
502 // nothing special to do here - we relayout in Realize() later
503 tool->Attach(this);
504 InvalidateBestSize();
505
506 return TRUE;
507}
508
509void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
510{
511 wxFAIL_MSG( _T("not implemented") );
512}
513
514bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
515{
516 wxToolBarToolsList::compatibility_iterator node;
517 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
518 {
519 wxToolBarToolBase *tool2 = node->GetData();
520 if ( tool2 == tool )
521 {
522 // let node point to the next node in the list
523 node = node->GetNext();
524
525 break;
526 }
527 }
528
529 wxSize sz = ((wxToolBarTool*)tool)->GetSize() ;
530
531 tool->Detach();
532
533 // and finally reposition all the controls after this one
534
535 for ( /* node -> first after deleted */ ; node; node = node->GetNext() )
536 {
537 wxToolBarTool *tool2 = (wxToolBarTool*) node->GetData();
538 wxPoint pt = tool2->GetPosition() ;
539
540 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
541 {
542 pt.y -= sz.y ;
543 }
544 else
545 {
546 pt.x -= sz.x ;
547 }
548 tool2->SetPosition( pt ) ;
549 }
550
551 InvalidateBestSize();
552 return TRUE ;
553}
554
555void wxToolBar::OnPaint(wxPaintEvent& event)
556{
557 wxPaintDC dc(this) ;
558 wxMacPortSetter helper(&dc) ;
559 int w, h ;
560 GetSize( &w , &h ) ;
561
562 Rect toolbarrect = { dc.YLOG2DEVMAC(0) , dc.XLOG2DEVMAC(0) ,
563 dc.YLOG2DEVMAC(h) , dc.XLOG2DEVMAC(w) } ;
564/*
565 if( toolbarrect.left < 0 )
566 toolbarrect.left = 0 ;
567 if ( toolbarrect.top < 0 )
568 toolbarrect.top = 0 ;
569*/
570 if ( !MacGetTopLevelWindow()->MacGetMetalAppearance() )
571 {
572 UMADrawThemePlacard( &toolbarrect , IsEnabled() ? kThemeStateActive : kThemeStateInactive) ;
573 }
574 else
575 {
576#if TARGET_API_MAC_OSX
577#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
578 if ( UMAGetSystemVersion() >= 0x1030 )
579 {
580 HIRect hiToolbarrect = CGRectMake( dc.YLOG2DEVMAC(0) , dc.XLOG2DEVMAC(0) ,
581 dc.YLOG2DEVREL(h) , dc.XLOG2DEVREL(w) );
582 CGContextRef cgContext ;
583 Rect bounds ;
584 GetPortBounds( (CGrafPtr) dc.m_macPort , &bounds ) ;
585 QDBeginCGContext( (CGrafPtr) dc.m_macPort , &cgContext ) ;
586 CGContextTranslateCTM( cgContext , 0 , bounds.bottom - bounds.top ) ;
587 CGContextScaleCTM( cgContext , 1 , -1 ) ;
588
589 {
590 HIThemeBackgroundDrawInfo drawInfo ;
591 drawInfo.version = 0 ;
592 drawInfo.state = kThemeStateActive ;
593 drawInfo.kind = kThemeBackgroundMetal ;
594 HIThemeApplyBackground( &hiToolbarrect, &drawInfo , cgContext,kHIThemeOrientationNormal) ;
595 }
596 QDEndCGContext( (CGrafPtr) dc.m_macPort , &cgContext ) ;
597 }
598 else
599#endif
600 {
601 UMADrawThemePlacard( &toolbarrect , IsEnabled() ? kThemeStateActive : kThemeStateInactive) ;
602 }
603#endif
604 }
605 event.Skip() ;
606}
607
608#endif // wxUSE_TOOLBAR
609