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