]> git.saurik.com Git - wxWidgets.git/blob - src/mac/classic/toolbar.cpp
applying patch 1345435
[wxWidgets.git] / src / mac / classic / toolbar.cpp
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 #include "wx/wx.h"
13
14 #if wxUSE_TOOLBAR
15
16 #include "wx/toolbar.h"
17 #include "wx/notebook.h"
18 #include "wx/tabctrl.h"
19 #include "wx/bitmap.h"
20
21 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
22
23 BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
24 EVT_MOUSE_EVENTS( wxToolBar::OnMouse )
25 EVT_PAINT( wxToolBar::OnPaint )
26 END_EVENT_TABLE()
27
28 #include "wx/mac/uma.h"
29 #include "wx/geometry.h"
30 // ----------------------------------------------------------------------------
31 // private classes
32 // ----------------------------------------------------------------------------
33
34 class wxToolBarTool : public wxToolBarToolBase
35 {
36 public:
37 wxToolBarTool(wxToolBar *tbar,
38 int id,
39 const wxString& label,
40 const wxBitmap& bmpNormal,
41 const wxBitmap& bmpDisabled,
42 wxItemKind kind,
43 wxObject *clientData,
44 const wxString& shortHelp,
45 const wxString& longHelp) ;
46
47 wxToolBarTool(wxToolBar *tbar, wxControl *control)
48 : wxToolBarToolBase(tbar, control)
49 {
50 Init() ;
51 }
52
53 ~wxToolBarTool()
54 {
55 if ( m_controlHandle )
56 DisposeControl( m_controlHandle ) ;
57 }
58
59 ControlHandle GetControlHandle() { return m_controlHandle ; }
60 void SetControlHandle( ControlHandle handle ) { m_controlHandle = handle ; }
61
62 void SetSize(const wxSize& size) ;
63 void SetPosition( const wxPoint& position ) ;
64 wxSize GetSize() const
65 {
66 if ( IsControl() )
67 {
68 return GetControl()->GetSize() ;
69 }
70 else if ( IsButton() )
71 {
72 return GetToolBar()->GetToolSize() ;
73 }
74 else
75 {
76 wxSize sz = GetToolBar()->GetToolSize() ;
77 sz.x /= 4 ;
78 sz.y /= 4 ;
79 return sz ;
80 }
81 }
82 wxPoint GetPosition() const
83 {
84 return wxPoint(m_x, m_y);
85 }
86 private :
87 void Init()
88 {
89 m_controlHandle = NULL ;
90 }
91 ControlHandle m_controlHandle ;
92
93 wxCoord m_x;
94 wxCoord m_y;
95 };
96
97 // ============================================================================
98 // implementation
99 // ============================================================================
100
101 // ----------------------------------------------------------------------------
102 // wxToolBarTool
103 // ----------------------------------------------------------------------------
104
105 void wxToolBarTool::SetSize(const wxSize& size)
106 {
107 if ( IsControl() )
108 {
109 GetControl()->SetSize( size ) ;
110 }
111 }
112
113 void wxToolBarTool::SetPosition(const wxPoint& position)
114 {
115 m_x = position.x;
116 m_y = position.y;
117
118 if ( IsButton() )
119 {
120 int x , y ;
121 x = y = 0 ;
122 WindowRef rootwindow = (WindowRef) GetToolBar()->MacGetRootWindow() ;
123 GetToolBar()->MacWindowToRootWindow( &x , &y ) ;
124 int mac_x = x + position.x ;
125 int mac_y = y + position.y ;
126
127
128 Rect contrlRect ;
129 GetControlBounds( m_controlHandle , &contrlRect ) ;
130 int former_mac_x = contrlRect.left ;
131 int former_mac_y = contrlRect.top ;
132 wxSize sz = GetToolBar()->GetToolSize() ;
133
134 if ( mac_x != former_mac_x || mac_y != former_mac_y )
135 {
136 {
137 Rect inval = { former_mac_y , former_mac_x , former_mac_y + sz.y , former_mac_x + sz.x } ;
138 InvalWindowRect( rootwindow , &inval ) ;
139 }
140 UMAMoveControl( m_controlHandle , mac_x , mac_y ) ;
141 {
142 Rect inval = { mac_y , mac_x , mac_y + sz.y , mac_x + sz.x } ;
143 InvalWindowRect( rootwindow , &inval ) ;
144 }
145 }
146 }
147 else if ( IsControl() )
148 {
149 GetControl()->Move( position ) ;
150 }
151 }
152
153 const short kwxMacToolBarToolDefaultWidth = 24 ;
154 const short kwxMacToolBarToolDefaultHeight = 22 ;
155 const short kwxMacToolBarTopMargin = 2 ;
156 const short kwxMacToolBarLeftMargin = 2 ;
157
158 wxToolBarTool::wxToolBarTool(wxToolBar *tbar,
159 int id,
160 const wxString& label,
161 const wxBitmap& bmpNormal,
162 const wxBitmap& bmpDisabled,
163 wxItemKind kind,
164 wxObject *clientData,
165 const wxString& shortHelp,
166 const wxString& longHelp)
167 : wxToolBarToolBase(tbar, id, label, bmpNormal, bmpDisabled, kind,
168 clientData, shortHelp, longHelp)
169 {
170 Init();
171
172 if (id == wxID_SEPARATOR) return;
173
174 WindowRef window = (WindowRef) tbar->MacGetRootWindow() ;
175 wxSize toolSize = tbar->GetToolSize() ;
176 Rect toolrect = { 0, 0 , toolSize.y , toolSize.x } ;
177
178 ControlButtonContentInfo info ;
179 wxMacCreateBitmapButton( &info , GetNormalBitmap() ) ;
180
181 SInt16 behaviour = kControlBehaviorOffsetContents ;
182 if ( CanBeToggled() )
183 behaviour += kControlBehaviorToggles ;
184
185 if ( info.contentType != kControlNoContent )
186 {
187 m_controlHandle = ::NewControl( window , &toolrect , "\p" , false , 0 ,
188 behaviour + info.contentType , 0 , kControlBevelButtonNormalBevelProc , (long) this ) ;
189
190 ::SetControlData( m_controlHandle , kControlButtonPart , kControlBevelButtonContentTag , sizeof(info) , (char*) &info ) ;
191 }
192 else
193 {
194 m_controlHandle = ::NewControl( window , &toolrect , "\p" , false , 0 ,
195 behaviour , 0 , kControlBevelButtonNormalBevelProc , (long) this ) ;
196 }
197 UMAShowControl( m_controlHandle ) ;
198 if ( !IsEnabled() )
199 {
200 UMADeactivateControl( m_controlHandle ) ;
201 }
202 if ( CanBeToggled() && IsToggled() )
203 {
204 ::SetControl32BitValue( m_controlHandle , 1 ) ;
205 }
206 else
207 {
208 ::SetControl32BitValue( m_controlHandle , 0 ) ;
209 }
210
211 ControlHandle container = (ControlHandle) tbar->MacGetContainerForEmbedding() ;
212 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
213 ::EmbedControl( m_controlHandle , container ) ;
214 }
215
216
217 wxToolBarToolBase *wxToolBar::CreateTool(int id,
218 const wxString& label,
219 const wxBitmap& bmpNormal,
220 const wxBitmap& bmpDisabled,
221 wxItemKind kind,
222 wxObject *clientData,
223 const wxString& shortHelp,
224 const wxString& longHelp)
225 {
226 return new wxToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
227 clientData, shortHelp, longHelp);
228 }
229
230 wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
231 {
232 return new wxToolBarTool(this, control);
233 }
234
235 void wxToolBar::Init()
236 {
237 m_maxWidth = -1;
238 m_maxHeight = -1;
239 m_defaultWidth = kwxMacToolBarToolDefaultWidth;
240 m_defaultHeight = kwxMacToolBarToolDefaultHeight;
241 }
242
243 bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
244 long style, const wxString& name)
245 {
246 int x = pos.x;
247 int y = pos.y;
248 int width = size.x;
249 int height = size.y;
250
251 if (width <= 0)
252 width = 100;
253 if (height <= 0)
254 height = 30;
255 if (x < 0)
256 x = 0;
257 if (y < 0)
258 y = 0;
259
260 SetName(name);
261
262 m_windowStyle = style;
263 parent->AddChild(this);
264
265 m_backgroundColour = parent->GetBackgroundColour() ;
266 m_foregroundColour = parent->GetForegroundColour() ;
267
268 if (id == -1)
269 m_windowId = NewControlId();
270 else
271 m_windowId = id;
272
273 {
274 m_width = size.x ;
275 m_height = size.y ;
276 int x = pos.x ;
277 int y = pos.y ;
278 AdjustForParentClientOrigin(x, y, wxSIZE_USE_EXISTING);
279 m_x = x ;
280 m_y = y ;
281 }
282
283 return TRUE;
284 }
285
286 wxToolBar::~wxToolBar()
287 {
288 // we must refresh the frame size when the toolbar is deleted but the frame
289 // is not - otherwise toolbar leaves a hole in the place it used to occupy
290 }
291
292 bool wxToolBar::Realize()
293 {
294 if (m_tools.GetCount() == 0)
295 return FALSE;
296
297 int x = m_xMargin + kwxMacToolBarLeftMargin ;
298 int y = m_yMargin + kwxMacToolBarTopMargin ;
299
300 int tw, th;
301 GetSize(& tw, & th);
302
303 int maxWidth = 0 ;
304 int maxHeight = 0 ;
305
306 int maxToolWidth = 0;
307 int maxToolHeight = 0;
308
309 // Find the maximum tool width and height
310 wxToolBarToolsList::Node *node = m_tools.GetFirst();
311 while ( node )
312 {
313 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
314 wxSize sz = tool->GetSize() ;
315
316 if ( sz.x > maxToolWidth )
317 maxToolWidth = sz.x ;
318 if (sz.y> maxToolHeight)
319 maxToolHeight = sz.y;
320
321 node = node->GetNext();
322 }
323
324 node = m_tools.GetFirst();
325 while (node)
326 {
327 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
328 wxSize cursize = tool->GetSize() ;
329
330 // for the moment we just do a single row/column alignement
331 if ( x + cursize.x > maxWidth )
332 maxWidth = x + cursize.x ;
333 if ( y + cursize.y > maxHeight )
334 maxHeight = y + cursize.y ;
335
336 tool->SetPosition( wxPoint( x , y ) ) ;
337
338 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
339 {
340 y += cursize.y ;
341 }
342 else
343 {
344 x += cursize.x ;
345 }
346
347 node = node->GetNext();
348 }
349
350 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
351 {
352 if ( m_maxRows == 0 )
353 {
354 // if not set yet, only one row
355 SetRows(1);
356 }
357 maxWidth = tw ;
358 maxHeight += m_yMargin + kwxMacToolBarTopMargin;
359 m_maxHeight = maxHeight ;
360 }
361 else
362 {
363 if ( GetToolsCount() > 0 && m_maxRows == 0 )
364 {
365 // if not set yet, have one column
366 SetRows(GetToolsCount());
367 }
368 maxHeight = th ;
369 maxWidth += m_xMargin + kwxMacToolBarLeftMargin;
370 m_maxWidth = maxWidth ;
371 }
372
373 SetSize(maxWidth, maxHeight);
374 InvalidateBestSize();
375
376 return TRUE;
377 }
378
379 void wxToolBar::SetToolBitmapSize(const wxSize& size)
380 {
381 m_defaultWidth = size.x+4; m_defaultHeight = size.y+4;
382 }
383
384 // The button size is bigger than the bitmap size
385 wxSize wxToolBar::GetToolSize() const
386 {
387 return wxSize(m_defaultWidth + 4, m_defaultHeight + 4);
388 }
389
390 void wxToolBar::MacHandleControlClick( WXWidget control , wxInt16 controlpart , bool WXUNUSED( mouseStillDown ) )
391 {
392 wxToolBarToolsList::Node *node;
393 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
394 {
395 wxToolBarTool* tool = (wxToolBarTool*) node->GetData() ;
396 if ( tool->IsButton() )
397 {
398 if( (WXWidget) tool->GetControlHandle() == control )
399 {
400 if ( tool->CanBeToggled() )
401 {
402 tool->Toggle( GetControl32BitValue( (ControlHandle) control ) ) ;
403 }
404 OnLeftClick( tool->GetId() , tool -> IsToggled() ) ;
405 break ;
406 }
407 }
408 }
409 }
410
411 void wxToolBar::SetRows(int nRows)
412 {
413 if ( nRows == m_maxRows )
414 {
415 // avoid resizing the frame uselessly
416 return;
417 }
418
419 m_maxRows = nRows;
420 }
421
422 void wxToolBar::MacSuperChangedPosition()
423 {
424 wxWindow::MacSuperChangedPosition() ;
425 Realize() ;
426 }
427
428 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
429 {
430 wxToolBarToolsList::Node *node = m_tools.GetFirst();
431 while (node)
432 {
433 wxToolBarTool *tool = (wxToolBarTool *)node->GetData() ;
434 wxRect2DInt r( tool->GetPosition() , tool->GetSize() ) ;
435 if ( r.Contains( wxPoint( x , y ) ) )
436 {
437 return tool;
438 }
439
440 node = node->GetNext();
441 }
442
443 return (wxToolBarToolBase *)NULL;
444 }
445
446 wxString wxToolBar::MacGetToolTipString( wxPoint &pt )
447 {
448 wxToolBarToolBase* tool = FindToolForPosition( pt.x , pt.y ) ;
449 if ( tool )
450 {
451 return tool->GetShortHelp() ;
452 }
453 return wxEmptyString ;
454 }
455
456 void wxToolBar::DoEnableTool(wxToolBarToolBase *t, bool enable)
457 {
458 if (!IsShown())
459 return ;
460
461 wxToolBarTool *tool = (wxToolBarTool *)t;
462 if ( tool->IsControl() )
463 {
464 tool->GetControl()->Enable( enable ) ;
465 }
466 else if ( tool->IsButton() )
467 {
468 if ( enable )
469 UMAActivateControl( tool->GetControlHandle() ) ;
470 else
471 UMADeactivateControl( tool->GetControlHandle() ) ;
472 }
473 }
474
475 void wxToolBar::DoToggleTool(wxToolBarToolBase *t, bool toggle)
476 {
477 if (!IsShown())
478 return ;
479
480 wxToolBarTool *tool = (wxToolBarTool *)t;
481 if ( tool->IsButton() )
482 {
483 ::SetControl32BitValue( tool->GetControlHandle() , toggle ) ;
484 }
485 }
486
487 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
488 wxToolBarToolBase *tool)
489 {
490 // nothing special to do here - we relayout in Realize() later
491 tool->Attach(this);
492 InvalidateBestSize();
493
494 return TRUE;
495 }
496
497 void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
498 {
499 wxFAIL_MSG( _T("not implemented") );
500 }
501
502 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
503 {
504 wxToolBarToolsList::Node *node;
505 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
506 {
507 wxToolBarToolBase *tool2 = node->GetData();
508 if ( tool2 == tool )
509 {
510 // let node point to the next node in the list
511 node = node->GetNext();
512
513 break;
514 }
515 }
516
517 wxSize sz = ((wxToolBarTool*)tool)->GetSize() ;
518
519 tool->Detach();
520
521 // and finally reposition all the controls after this one
522
523 for ( /* node -> first after deleted */ ; node; node = node->GetNext() )
524 {
525 wxToolBarTool *tool2 = (wxToolBarTool*) node->GetData();
526 wxPoint pt = tool2->GetPosition() ;
527
528 if ( GetWindowStyleFlag() & wxTB_VERTICAL )
529 {
530 pt.y -= sz.y ;
531 }
532 else
533 {
534 pt.x -= sz.x ;
535 }
536 tool2->SetPosition( pt ) ;
537 }
538
539 InvalidateBestSize();
540 return TRUE ;
541 }
542
543 void wxToolBar::OnPaint(wxPaintEvent& event)
544 {
545 wxPaintDC dc(this) ;
546 wxMacPortSetter helper(&dc) ;
547
548 Rect toolbarrect = { dc.YLOG2DEVMAC(0) , dc.XLOG2DEVMAC(0) ,
549 dc.YLOG2DEVMAC(m_height) , dc.XLOG2DEVMAC(m_width) } ;
550 UMADrawThemePlacard( &toolbarrect , IsEnabled() ? kThemeStateActive : kThemeStateInactive) ;
551 {
552 wxToolBarToolsList::Node *node;
553 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
554 {
555 wxToolBarTool* tool = (wxToolBarTool*) node->GetData() ;
556 if ( tool->IsButton() )
557 {
558 UMADrawControl( tool->GetControlHandle() ) ;
559 }
560 }
561 }
562 }
563
564 void wxToolBar::OnMouse( wxMouseEvent &event )
565 {
566 if (event.GetEventType() == wxEVT_LEFT_DOWN || event.GetEventType() == wxEVT_LEFT_DCLICK )
567 {
568
569 int x = event.m_x ;
570 int y = event.m_y ;
571
572 MacClientToRootWindow( &x , &y ) ;
573
574 ControlHandle control ;
575 Point localwhere ;
576 SInt16 controlpart ;
577 WindowRef window = (WindowRef) MacGetRootWindow() ;
578
579 localwhere.h = x ;
580 localwhere.v = y ;
581
582 short modifiers = 0;
583
584 if ( !event.m_leftDown && !event.m_rightDown )
585 modifiers |= btnState ;
586
587 if ( event.m_shiftDown )
588 modifiers |= shiftKey ;
589
590 if ( event.m_controlDown )
591 modifiers |= controlKey ;
592
593 if ( event.m_altDown )
594 modifiers |= optionKey ;
595
596 if ( event.m_metaDown )
597 modifiers |= cmdKey ;
598
599 controlpart = ::FindControl( localwhere , window , &control ) ;
600 {
601 if ( control && ::IsControlActive( control ) )
602 {
603 {
604 controlpart = ::HandleControlClick( control , localwhere , modifiers , (ControlActionUPP) -1 ) ;
605 wxTheApp->s_lastMouseDown = 0 ;
606 if ( control && controlpart != kControlNoPart ) // otherwise we will get the event twice
607 {
608 MacHandleControlClick( (WXWidget) control , controlpart , false /* not down anymore */ ) ;
609 }
610 }
611 }
612 }
613 }
614 }
615
616 #endif // wxUSE_TOOLBAR
617