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