///////////////////////////////////////////////////////////////////////////// // Name: src/mac/classic/toolbar.cpp // Purpose: wxToolBar // Author: Stefan Csomor // Modified by: // Created: 04/01/98 // RCS-ID: $Id: toolbar.cpp 41020 2006-09-05 20:47:48Z VZ $ // Copyright: (c) Stefan Csomor // Licence: The wxWindows licence ///////////////////////////////////////////////////////////////////////////// #include "wx/wxprec.h" #if wxUSE_TOOLBAR #include "wx/toolbar.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/notebook.h" #include "wx/tabctrl.h" IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl) BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase) EVT_MOUSE_EVENTS( wxToolBar::OnMouse ) EVT_PAINT( wxToolBar::OnPaint ) END_EVENT_TABLE() #include "wx/mac/uma.h" #include "wx/geometry.h" // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- class wxToolBarTool : public wxToolBarToolBase { public: wxToolBarTool(wxToolBar *tbar, int id, const wxString& label, const wxBitmap& bmpNormal, const wxBitmap& bmpDisabled, wxItemKind kind, wxObject *clientData, const wxString& shortHelp, const wxString& longHelp) ; wxToolBarTool(wxToolBar *tbar, wxControl *control) : wxToolBarToolBase(tbar, control) { Init() ; } virtual ~wxToolBarTool() { if ( m_controlHandle ) DisposeControl( m_controlHandle ) ; } ControlHandle GetControlHandle() { return m_controlHandle ; } void SetControlHandle( ControlHandle handle ) { m_controlHandle = handle ; } void SetSize(const wxSize& size) ; void SetPosition( const wxPoint& position ) ; wxSize GetSize() const { if ( IsControl() ) { return GetControl()->GetSize() ; } else if ( IsButton() ) { return GetToolBar()->GetToolSize() ; } else { wxSize sz = GetToolBar()->GetToolSize() ; sz.x /= 4 ; sz.y /= 4 ; return sz ; } } wxPoint GetPosition() const { return wxPoint(m_x, m_y); } private : void Init() { m_controlHandle = NULL ; } ControlHandle m_controlHandle ; wxCoord m_x; wxCoord m_y; }; // ============================================================================ // implementation // ============================================================================ // ---------------------------------------------------------------------------- // wxToolBarTool // ---------------------------------------------------------------------------- void wxToolBarTool::SetSize(const wxSize& size) { if ( IsControl() ) { GetControl()->SetSize( size ) ; } } void wxToolBarTool::SetPosition(const wxPoint& position) { m_x = position.x; m_y = position.y; if ( IsButton() ) { int x , y ; x = y = 0 ; WindowRef rootwindow = (WindowRef) GetToolBar()->MacGetRootWindow() ; GetToolBar()->MacWindowToRootWindow( &x , &y ) ; int mac_x = x + position.x ; int mac_y = y + position.y ; Rect contrlRect ; GetControlBounds( m_controlHandle , &contrlRect ) ; int former_mac_x = contrlRect.left ; int former_mac_y = contrlRect.top ; wxSize sz = GetToolBar()->GetToolSize() ; if ( mac_x != former_mac_x || mac_y != former_mac_y ) { { Rect inval = { former_mac_y , former_mac_x , former_mac_y + sz.y , former_mac_x + sz.x } ; InvalWindowRect( rootwindow , &inval ) ; } UMAMoveControl( m_controlHandle , mac_x , mac_y ) ; { Rect inval = { mac_y , mac_x , mac_y + sz.y , mac_x + sz.x } ; InvalWindowRect( rootwindow , &inval ) ; } } } else if ( IsControl() ) { GetControl()->Move( position ) ; } } const short kwxMacToolBarToolDefaultWidth = 24 ; const short kwxMacToolBarToolDefaultHeight = 22 ; const short kwxMacToolBarTopMargin = 2 ; const short kwxMacToolBarLeftMargin = 2 ; wxToolBarTool::wxToolBarTool(wxToolBar *tbar, int id, const wxString& label, const wxBitmap& bmpNormal, const wxBitmap& bmpDisabled, wxItemKind kind, wxObject *clientData, const wxString& shortHelp, const wxString& longHelp) : wxToolBarToolBase(tbar, id, label, bmpNormal, bmpDisabled, kind, clientData, shortHelp, longHelp) { Init(); if (id == wxID_SEPARATOR) return; WindowRef window = (WindowRef) tbar->MacGetRootWindow() ; wxSize toolSize = tbar->GetToolSize() ; Rect toolrect = { 0, 0 , toolSize.y , toolSize.x } ; ControlButtonContentInfo info ; wxMacCreateBitmapButton( &info , GetNormalBitmap() ) ; SInt16 behaviour = kControlBehaviorOffsetContents ; if ( CanBeToggled() ) behaviour += kControlBehaviorToggles ; if ( info.contentType != kControlNoContent ) { m_controlHandle = ::NewControl( window , &toolrect , "\p" , false , 0 , behaviour + info.contentType , 0 , kControlBevelButtonNormalBevelProc , (long) this ) ; ::SetControlData( m_controlHandle , kControlButtonPart , kControlBevelButtonContentTag , sizeof(info) , (char*) &info ) ; } else { m_controlHandle = ::NewControl( window , &toolrect , "\p" , false , 0 , behaviour , 0 , kControlBevelButtonNormalBevelProc , (long) this ) ; } UMAShowControl( m_controlHandle ) ; if ( !IsEnabled() ) { UMADeactivateControl( m_controlHandle ) ; } if ( CanBeToggled() && IsToggled() ) { ::SetControl32BitValue( m_controlHandle , 1 ) ; } else { ::SetControl32BitValue( m_controlHandle , 0 ) ; } ControlHandle container = (ControlHandle) tbar->MacGetContainerForEmbedding() ; wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ; ::EmbedControl( m_controlHandle , container ) ; } wxToolBarToolBase *wxToolBar::CreateTool(int id, const wxString& label, const wxBitmap& bmpNormal, const wxBitmap& bmpDisabled, wxItemKind kind, wxObject *clientData, const wxString& shortHelp, const wxString& longHelp) { return new wxToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind, clientData, shortHelp, longHelp); } wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control) { return new wxToolBarTool(this, control); } void wxToolBar::Init() { m_maxWidth = -1; m_maxHeight = -1; m_defaultWidth = kwxMacToolBarToolDefaultWidth; m_defaultHeight = kwxMacToolBarToolDefaultHeight; } bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { int x = pos.x; int y = pos.y; int width = size.x; int height = size.y; if (width <= 0) width = 100; if (height <= 0) height = 30; if (x < 0) x = 0; if (y < 0) y = 0; SetName(name); m_windowStyle = style; parent->AddChild(this); m_backgroundColour = parent->GetBackgroundColour() ; m_foregroundColour = parent->GetForegroundColour() ; if (id == wxID_ANY) m_windowId = NewControlId(); else m_windowId = id; { m_width = size.x ; m_height = size.y ; int x = pos.x ; int y = pos.y ; AdjustForParentClientOrigin(x, y, wxSIZE_USE_EXISTING); m_x = x ; m_y = y ; } return true; } wxToolBar::~wxToolBar() { // we must refresh the frame size when the toolbar is deleted but the frame // is not - otherwise toolbar leaves a hole in the place it used to occupy } bool wxToolBar::Realize() { if (m_tools.GetCount() == 0) return false; int x = m_xMargin + kwxMacToolBarLeftMargin ; int y = m_yMargin + kwxMacToolBarTopMargin ; int tw, th; GetSize(& tw, & th); int maxWidth = 0 ; int maxHeight = 0 ; int maxToolWidth = 0; int maxToolHeight = 0; // Find the maximum tool width and height wxToolBarToolsList::Node *node = m_tools.GetFirst(); while ( node ) { wxToolBarTool *tool = (wxToolBarTool *)node->GetData(); wxSize sz = tool->GetSize() ; if ( sz.x > maxToolWidth ) maxToolWidth = sz.x ; if (sz.y> maxToolHeight) maxToolHeight = sz.y; node = node->GetNext(); } node = m_tools.GetFirst(); while (node) { wxToolBarTool *tool = (wxToolBarTool *)node->GetData(); wxSize cursize = tool->GetSize() ; // for the moment we just do a single row/column alignement if ( x + cursize.x > maxWidth ) maxWidth = x + cursize.x ; if ( y + cursize.y > maxHeight ) maxHeight = y + cursize.y ; tool->SetPosition( wxPoint( x , y ) ) ; if ( GetWindowStyleFlag() & wxTB_VERTICAL ) { y += cursize.y ; } else { x += cursize.x ; } node = node->GetNext(); } if ( GetWindowStyleFlag() & wxTB_HORIZONTAL ) { if ( m_maxRows == 0 ) { // if not set yet, only one row SetRows(1); } maxWidth = tw ; maxHeight += m_yMargin + kwxMacToolBarTopMargin; m_maxHeight = maxHeight ; } else { if ( GetToolsCount() > 0 && m_maxRows == 0 ) { // if not set yet, have one column SetRows(GetToolsCount()); } maxHeight = th ; maxWidth += m_xMargin + kwxMacToolBarLeftMargin; m_maxWidth = maxWidth ; } SetSize(maxWidth, maxHeight); InvalidateBestSize(); return true; } void wxToolBar::SetToolBitmapSize(const wxSize& size) { m_defaultWidth = size.x+4; m_defaultHeight = size.y+4; } // The button size is bigger than the bitmap size wxSize wxToolBar::GetToolSize() const { return wxSize(m_defaultWidth + 4, m_defaultHeight + 4); } void wxToolBar::MacHandleControlClick( WXWidget control , wxInt16 controlpart , bool WXUNUSED( mouseStillDown ) ) { wxToolBarToolsList::Node *node; for ( node = m_tools.GetFirst(); node; node = node->GetNext() ) { wxToolBarTool* tool = (wxToolBarTool*) node->GetData() ; if ( tool->IsButton() ) { if( (WXWidget) tool->GetControlHandle() == control ) { if ( tool->CanBeToggled() ) { tool->Toggle( GetControl32BitValue( (ControlHandle) control ) ) ; } OnLeftClick( tool->GetId() , tool -> IsToggled() ) ; break ; } } } } void wxToolBar::SetRows(int nRows) { if ( nRows == m_maxRows ) { // avoid resizing the frame uselessly return; } m_maxRows = nRows; } void wxToolBar::MacSuperChangedPosition() { wxWindow::MacSuperChangedPosition() ; Realize() ; } wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const { wxToolBarToolsList::Node *node = m_tools.GetFirst(); while (node) { wxToolBarTool *tool = (wxToolBarTool *)node->GetData() ; wxRect2DInt r( tool->GetPosition() , tool->GetSize() ) ; if ( r.Contains( wxPoint( x , y ) ) ) { return tool; } node = node->GetNext(); } return (wxToolBarToolBase *)NULL; } wxString wxToolBar::MacGetToolTipString( wxPoint &pt ) { wxToolBarToolBase* tool = FindToolForPosition( pt.x , pt.y ) ; if ( tool ) { return tool->GetShortHelp() ; } return wxEmptyString ; } void wxToolBar::DoEnableTool(wxToolBarToolBase *t, bool enable) { if (!IsShown()) return ; wxToolBarTool *tool = (wxToolBarTool *)t; if ( tool->IsControl() ) { tool->GetControl()->Enable( enable ) ; } else if ( tool->IsButton() ) { if ( enable ) UMAActivateControl( tool->GetControlHandle() ) ; else UMADeactivateControl( tool->GetControlHandle() ) ; } } void wxToolBar::DoToggleTool(wxToolBarToolBase *t, bool toggle) { if (!IsShown()) return ; wxToolBarTool *tool = (wxToolBarTool *)t; if ( tool->IsButton() ) { ::SetControl32BitValue( tool->GetControlHandle() , toggle ) ; } } bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool) { // nothing special to do here - we relayout in Realize() later tool->Attach(this); InvalidateBestSize(); return true; } void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle)) { wxFAIL_MSG( _T("not implemented") ); } bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool) { wxToolBarToolsList::Node *node; for ( node = m_tools.GetFirst(); node; node = node->GetNext() ) { wxToolBarToolBase *tool2 = node->GetData(); if ( tool2 == tool ) { // let node point to the next node in the list node = node->GetNext(); break; } } wxSize sz = ((wxToolBarTool*)tool)->GetSize() ; tool->Detach(); // and finally reposition all the controls after this one for ( /* node -> first after deleted */ ; node; node = node->GetNext() ) { wxToolBarTool *tool2 = (wxToolBarTool*) node->GetData(); wxPoint pt = tool2->GetPosition() ; if ( GetWindowStyleFlag() & wxTB_VERTICAL ) { pt.y -= sz.y ; } else { pt.x -= sz.x ; } tool2->SetPosition( pt ) ; } InvalidateBestSize(); return true ; } void wxToolBar::OnPaint(wxPaintEvent& event) { wxPaintDC dc(this) ; wxMacPortSetter helper(&dc) ; Rect toolbarrect = { dc.YLOG2DEVMAC(0) , dc.XLOG2DEVMAC(0) , dc.YLOG2DEVMAC(m_height) , dc.XLOG2DEVMAC(m_width) } ; UMADrawThemePlacard( &toolbarrect , IsEnabled() ? kThemeStateActive : kThemeStateInactive) ; { wxToolBarToolsList::Node *node; for ( node = m_tools.GetFirst(); node; node = node->GetNext() ) { wxToolBarTool* tool = (wxToolBarTool*) node->GetData() ; if ( tool->IsButton() ) { UMADrawControl( tool->GetControlHandle() ) ; } } } } void wxToolBar::OnMouse( wxMouseEvent &event ) { if (event.GetEventType() == wxEVT_LEFT_DOWN || event.GetEventType() == wxEVT_LEFT_DCLICK ) { int x = event.m_x ; int y = event.m_y ; MacClientToRootWindow( &x , &y ) ; ControlHandle control ; Point localwhere ; SInt16 controlpart ; WindowRef window = (WindowRef) MacGetRootWindow() ; localwhere.h = x ; localwhere.v = y ; short modifiers = 0; if ( !event.m_leftDown && !event.m_rightDown ) modifiers |= btnState ; if ( event.m_shiftDown ) modifiers |= shiftKey ; if ( event.m_controlDown ) modifiers |= controlKey ; if ( event.m_altDown ) modifiers |= optionKey ; if ( event.m_metaDown ) modifiers |= cmdKey ; controlpart = ::FindControl( localwhere , window , &control ) ; { if ( control && ::IsControlActive( control ) ) { { controlpart = ::HandleControlClick( control , localwhere , modifiers , (ControlActionUPP) -1 ) ; wxTheApp->s_lastMouseDown = 0 ; if ( control && controlpart != kControlNoPart ) // otherwise we will get the event twice { MacHandleControlClick( (WXWidget) control , controlpart , false /* not down anymore */ ) ; } } } } } } #endif // wxUSE_TOOLBAR