1///////////////////////////////////////////////////////////////////////////// 2// Name: src/mac/classic/toolbar.cpp 3// Purpose: wxToolBar 4// Author: Stefan Csomor 5// Modified by: 6// Created: 04/01/98 7// RCS-ID: $Id: toolbar.cpp 41020 2006-09-05 20:47:48Z VZ $ 8// Copyright: (c) Stefan Csomor 9// Licence: The wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12#include "wx/wxprec.h" 13 14#if wxUSE_TOOLBAR 15 16#include "wx/toolbar.h" 17 18#ifndef WX_PRECOMP 19 #include "wx/wx.h" 20#endif 21 22#include "wx/notebook.h" 23#include "wx/tabctrl.h" 24 25IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl) 26 27BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase) 28 EVT_MOUSE_EVENTS( wxToolBar::OnMouse ) 29 EVT_PAINT( wxToolBar::OnPaint ) 30END_EVENT_TABLE() 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) ; 50 51 wxToolBarTool(wxToolBar *tbar, wxControl *control) 52 : wxToolBarToolBase(tbar, control) 53 { 54 Init() ; 55 } 56 57 virtual ~wxToolBarTool() 58 { 59 if ( m_controlHandle ) 60 DisposeControl( m_controlHandle ) ; 61 } 62 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); 89 } 90private : 91 void Init() 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 ; 126 WindowRef rootwindow = (WindowRef) GetToolBar()->MacGetRootWindow() ; 127 GetToolBar()->MacWindowToRootWindow( &x , &y ) ; 128 int mac_x = x + position.x ; 129 int mac_y = y + position.y ; 130 131 132 Rect contrlRect ; 133 GetControlBounds( m_controlHandle , &contrlRect ) ; 134 int former_mac_x = contrlRect.left ; 135 int former_mac_y = contrlRect.top ; 136 wxSize sz = GetToolBar()->GetToolSize() ; 137 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, 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) 171 : wxToolBarToolBase(tbar, id, label, bmpNormal, bmpDisabled, kind, 172 clientData, shortHelp, longHelp) 173{ 174 Init(); 175 176 if (id == wxID_SEPARATOR) return; 177 178 WindowRef window = (WindowRef) tbar->MacGetRootWindow() ; 179 wxSize toolSize = tbar->GetToolSize() ; 180 Rect toolrect = { 0, 0 , toolSize.y , toolSize.x } ; 181 182 ControlButtonContentInfo info ; 183 wxMacCreateBitmapButton( &info , GetNormalBitmap() ) ; 184 185 SInt16 behaviour = kControlBehaviorOffsetContents ; 186 if ( CanBeToggled() ) 187 behaviour += kControlBehaviorToggles ; 188 189 if ( info.contentType != kControlNoContent ) 190 { 191 m_controlHandle = ::NewControl( window , &toolrect , "\p" , false , 0 , 192 behaviour + info.contentType , 0 , kControlBevelButtonNormalBevelProc , (long) this ) ; 193 194 ::SetControlData( m_controlHandle , kControlButtonPart , kControlBevelButtonContentTag , sizeof(info) , (char*) &info ) ; 195 } 196 else 197 { 198 m_controlHandle = ::NewControl( window , &toolrect , "\p" , false , 0 , 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 } 214 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) 249{ 250 int x = pos.x; 251 int y = pos.y; 252 int width = size.x; 253 int height = size.y; 254 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; 263 264 SetName(name); 265 266 m_windowStyle = style; 267 parent->AddChild(this); 268 269 m_backgroundColour = parent->GetBackgroundColour() ; 270 m_foregroundColour = parent->GetForegroundColour() ; 271 272 if (id == wxID_ANY) 273 m_windowId = NewControlId(); 274 else 275 m_windowId = id; 276 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 } 286 287 return true; 288} 289 290wxToolBar::~wxToolBar() 291{ 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) 299 return false; 300 301 int x = m_xMargin + kwxMacToolBarLeftMargin ; 302 int y = m_yMargin + kwxMacToolBarTopMargin ; 303 304 int tw, th; 305 GetSize(& tw, & th); 306 307 int maxWidth = 0 ; 308 int maxHeight = 0 ; 309 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() ; 333 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 ; 339 340 tool->SetPosition( wxPoint( x , y ) ) ; 341 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 } 353 354 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL ) 355 { 356 if ( m_maxRows == 0 ) 357 { 358 // if not set yet, only one row 359 SetRows(1); 360 } 361 maxWidth = tw ; 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 } 376 377 SetSize(maxWidth, maxHeight); 378 InvalidateBestSize(); 379 380 return true; 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 394void wxToolBar::MacHandleControlClick( WXWidget control , wxInt16 controlpart , bool WXUNUSED( mouseStillDown ) ) 395{ 396 wxToolBarToolsList::Node *node; 397 for ( node = m_tools.GetFirst(); node; node = node->GetNext() ) 398 { 399 wxToolBarTool* tool = (wxToolBarTool*) node->GetData() ; 400 if ( tool->IsButton() ) 401 { 402 if( (WXWidget) tool->GetControlHandle() == control ) 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 426void wxToolBar::MacSuperChangedPosition() 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); 496 InvalidateBestSize(); 497 498 return true; 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 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 InvalidateBestSize(); 544 return true ; 545} 546 547void wxToolBar::OnPaint(wxPaintEvent& event) 548{ 549 wxPaintDC dc(this) ; 550 wxMacPortSetter helper(&dc) ; 551 552 Rect toolbarrect = { dc.YLOG2DEVMAC(0) , dc.XLOG2DEVMAC(0) , 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 { 559 wxToolBarTool* tool = (wxToolBarTool*) node->GetData() ; 560 if ( tool->IsButton() ) 561 { 562 UMADrawControl( tool->GetControlHandle() ) ; 563 } 564 } 565 } 566} 567 568void wxToolBar::OnMouse( wxMouseEvent &event ) 569{ 570 if (event.GetEventType() == wxEVT_LEFT_DOWN || event.GetEventType() == wxEVT_LEFT_DCLICK ) 571 { 572 573 int x = event.m_x ; 574 int y = event.m_y ; 575 576 MacClientToRootWindow( &x , &y ) ; 577 578 ControlHandle control ; 579 Point localwhere ; 580 SInt16 controlpart ; 581 WindowRef window = (WindowRef) MacGetRootWindow() ; 582 583 localwhere.h = x ; 584 localwhere.v = y ; 585 586 short modifiers = 0; 587 588 if ( !event.m_leftDown && !event.m_rightDown ) 589 modifiers |= btnState ; 590 591 if ( event.m_shiftDown ) 592 modifiers |= shiftKey ; 593 594 if ( event.m_controlDown ) 595 modifiers |= controlKey ; 596 597 if ( event.m_altDown ) 598 modifiers |= optionKey ; 599 600 if ( event.m_metaDown ) 601 modifiers |= cmdKey ; 602 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 { 612 MacHandleControlClick( (WXWidget) control , controlpart , false /* not down anymore */ ) ; 613 } 614 } 615 } 616 } 617 } 618} 619 620#endif // wxUSE_TOOLBAR 621