///////////////////////////////////////////////////////////////////////////// // Name: toolbar.cpp // Purpose: wxToolBar // Author: David Webster // Modified by: // Created: 06/30/02 // RCS-ID: $Id$ // Copyright: (c) David Webster // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #if wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE #ifndef WX_PRECOMP #include "wx/settings.h" #include "wx/window.h" #include "wx/dcclient.h" #include "wx/dcmemory.h" #endif #include "wx/tooltip.h" #include "wx/toolbar.h" bool wxToolBar::m_bInitialized = FALSE; // --------------------------------------------------------------------------- // Helper for taking a regular bitmap and giving it a disabled look // --------------------------------------------------------------------------- wxBitmap wxDisableBitmap( const wxBitmap& rBmp , long lColor ) { wxMask* pMask = rBmp.GetMask(); if (!pMask) return(wxNullBitmap); DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; SIZEL vSize = {0, 0}; HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE); HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC); BITMAPINFOHEADER2 vHeader; BITMAPINFO2 vInfo; ERRORID vError; wxString sError; HBITMAP hBitmap = (HBITMAP)rBmp.GetHBITMAP(); HBITMAP hOldBitmap = NULLHANDLE; HBITMAP hOldMask = NULLHANDLE; HBITMAP hMask = (HBITMAP)rBmp.GetMask()->GetMaskBitmap(); unsigned char* pucBits; // buffer that will contain the bitmap data unsigned char* pucData; // pointer to use to traverse bitmap data unsigned char* pucBitsMask; // buffer that will contain the mask data unsigned char* pucDataMask; // pointer to use to traverse mask data LONG lScans = 0L; LONG lScansSet = 0L; bool bpp16 = (wxDisplayDepth() == 16); memset(&vHeader, '\0', 16); vHeader.cbFix = 16; memset(&vInfo, '\0', 16); vInfo.cbFix = 16; vInfo.cx = (ULONG)rBmp.GetWidth(); vInfo.cy = (ULONG)rBmp.GetHeight(); vInfo.cPlanes = 1; vInfo.cBitCount = 24; // Set to desired count going in // // Create the buffers for data....all wxBitmaps are 24 bit internally // int nBytesPerLine = rBmp.GetWidth() * 3; int nSizeDWORD = sizeof(DWORD); int nLineBoundary = nBytesPerLine % nSizeDWORD; int nPadding = 0; int i; int j; // // Bitmap must be ina double-word alligned address so we may // have some padding to worry about // if (nLineBoundary > 0) { nPadding = nSizeDWORD - nLineBoundary; nBytesPerLine += nPadding; } pucBits = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight()); memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight())); pucBitsMask = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight()); memset(pucBitsMask, '\0', (nBytesPerLine * rBmp.GetHeight())); // // Extract the bitmap and mask data // if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR) { vError = ::WinGetLastError(vHabmain); sError = wxPMErrorToStr(vError); } ::GpiQueryBitmapInfoHeader(hBitmap, &vHeader); vInfo.cBitCount = 24; if ((lScans = ::GpiQueryBitmapBits( hPS ,0L ,(LONG)rBmp.GetHeight() ,(PBYTE)pucBits ,&vInfo )) == GPI_ALTERROR) { vError = ::WinGetLastError(vHabmain); sError = wxPMErrorToStr(vError); } if ((hOldMask = ::GpiSetBitmap(hPS, hMask)) == HBM_ERROR) { vError = ::WinGetLastError(vHabmain); sError = wxPMErrorToStr(vError); } ::GpiQueryBitmapInfoHeader(hMask, &vHeader); vInfo.cBitCount = 24; if ((lScans = ::GpiQueryBitmapBits( hPS ,0L ,(LONG)rBmp.GetHeight() ,(PBYTE)pucBitsMask ,&vInfo )) == GPI_ALTERROR) { vError = ::WinGetLastError(vHabmain); sError = wxPMErrorToStr(vError); } if (( hMask = ::GpiSetBitmap(hPS, hOldMask)) == HBM_ERROR) { vError = ::WinGetLastError(vHabmain); sError = wxPMErrorToStr(vError); } pucData = pucBits; pucDataMask = pucBitsMask; // // Get the mask value // for (i = 0; i < rBmp.GetHeight(); i++) { for (j = 0; j < rBmp.GetWidth(); j++) { // Byte 1 if (bpp16 && *pucDataMask == 0xF8) // 16 bit display gobblygook { *pucData = 0x7F; pucData++; } else if (*pucDataMask == 0xFF) // set to grey { *pucData = 0x7F; pucData++; } else { *pucData = ((unsigned char)(lColor >> 16)); pucData++; } // Byte 2 if (bpp16 && *(pucDataMask + 1) == 0xFC) // 16 bit display gobblygook { *pucData = 0x7F; pucData++; } else if (*(pucDataMask + 1) == 0xFF) // set to grey { *pucData = 0x7F; pucData++; } else { *pucData = ((unsigned char)(lColor >> 8)); pucData++; } // Byte 3 if (bpp16 && *(pucDataMask + 2) == 0xF8) // 16 bit display gobblygook { *pucData = 0x7F; pucData++; } else if (*(pucDataMask + 2) == 0xFF) // set to grey { *pucData = 0x7F; pucData++; } else { *pucData = ((unsigned char)lColor); pucData++; } pucDataMask += 3; } for (j = 0; j < nPadding; j++) { pucData++; pucDataMask++; } } // // Create a new bitmap and set the modified bits // wxBitmap vNewBmp( rBmp.GetWidth() ,rBmp.GetHeight() ,24 ); HBITMAP hNewBmp = (HBITMAP)vNewBmp.GetHBITMAP(); if ((hOldBitmap = ::GpiSetBitmap(hPS, hNewBmp)) == HBM_ERROR) { vError = ::WinGetLastError(vHabmain); sError = wxPMErrorToStr(vError); } if ((lScansSet = ::GpiSetBitmapBits( hPS ,0L ,(LONG)rBmp.GetHeight() ,(PBYTE)pucBits ,&vInfo )) == GPI_ALTERROR) { vError = ::WinGetLastError(vHabmain); sError = wxPMErrorToStr(vError); } wxMask* pNewMask; pNewMask = new wxMask(pMask->GetMaskBitmap()); vNewBmp.SetMask(pNewMask); free(pucBits); ::GpiSetBitmap(hPS, NULLHANDLE); ::GpiDestroyPS(hPS); ::DevCloseDC(hDC); if (vNewBmp.Ok()) return(vNewBmp); return(wxNullBitmap); } // end of wxDisableBitmap // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- class wxToolBarTool : public wxToolBarToolBase { public: inline wxToolBarTool( wxToolBar* pTbar ,int vId ,const wxString& rsLabel ,const wxBitmap& rBitmap1 ,const wxBitmap& rBitmap2 ,wxItemKind vKind ,wxObject* pClientData ,const wxString& rsShortHelpString ,const wxString& rsLongHelpString ) : wxToolBarToolBase( pTbar ,vId ,rsLabel ,rBitmap1 ,rBitmap2 ,vKind ,pClientData ,rsShortHelpString ,rsLongHelpString ) { } inline wxToolBarTool( wxToolBar* pTbar ,wxControl* pControl ) : wxToolBarToolBase( pTbar ,pControl ) { } void SetSize(const wxSize& rSize) { m_vWidth = rSize.x; m_vHeight = rSize.y; } wxCoord GetWidth(void) const { return m_vWidth; } wxCoord GetHeight(void) const { return m_vHeight; } wxCoord m_vX; wxCoord m_vY; wxCoord m_vWidth; wxCoord m_vHeight; }; // end of CLASS wxToolBarTool // ---------------------------------------------------------------------------- // wxWin macros // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase) BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase) EVT_SIZE(wxToolBar::OnSize) EVT_PAINT(wxToolBar::OnPaint) EVT_KILL_FOCUS(wxToolBar::OnKillFocus) EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent) EVT_TIMER(-1, wxToolBar::OnTimer) END_EVENT_TABLE() // ============================================================================ // implementation // ============================================================================ // ---------------------------------------------------------------------------- // tool bar tools creation // ---------------------------------------------------------------------------- wxToolBarToolBase* wxToolBar::CreateTool( int nId , const wxString& rsLabel , const wxBitmap& rBmpNormal , const wxBitmap& rBmpDisabled , wxItemKind eKind , wxObject* pClientData , const wxString& rsShortHelp , const wxString& rsLongHelp ) { return new wxToolBarTool( this ,nId ,rsLabel ,rBmpNormal ,rBmpDisabled ,eKind ,pClientData ,rsShortHelp ,rsLongHelp ); } // end of wxToolBarSimple::CreateTool wxToolBarToolBase *wxToolBar::CreateTool( wxControl* pControl ) { return new wxToolBarTool( this ,pControl ); } // end of wxToolBarSimple::CreateTool // ---------------------------------------------------------------------------- // wxToolBarSimple creation // ---------------------------------------------------------------------------- void wxToolBar::Init() { m_nCurrentRowsOrColumns = 0; m_vLastX = m_vLastY = 0; m_vMaxWidth = m_vMaxHeight = 0; m_nPressedTool = m_nCurrentTool = -1; m_vXPos = m_vYPos = -1; m_vTextX = m_vTextY = 0; m_toolPacking = 1; m_toolSeparation = 5; m_defaultWidth = 16; m_defaultHeight = 15; m_pToolTip = NULL; } // end of wxToolBar::Init wxToolBarToolBase* wxToolBar::DoAddTool( int vId , const wxString& rsLabel , const wxBitmap& rBitmap , const wxBitmap& rBmpDisabled , wxItemKind eKind , const wxString& rsShortHelp , const wxString& rsLongHelp , wxObject* pClientData , wxCoord vXPos , wxCoord vYPos ) { // // Rememeber the position for DoInsertTool() // m_vXPos = vXPos; m_vYPos = vYPos; return wxToolBarBase::DoAddTool( vId ,rsLabel ,rBitmap ,rBmpDisabled ,eKind ,rsShortHelp ,rsLongHelp ,pClientData ,vXPos ,vYPos ); } // end of wxToolBar::DoAddTool bool wxToolBar::DeleteTool( int nId ) { bool bOk = wxToolBarBase::DeleteTool(nId); if (bOk) { Realize(); } return bOk; } // end of wxToolBar::DeleteTool bool wxToolBar::DeleteToolByPos( size_t nPos ) { bool bOk = wxToolBarBase::DeleteToolByPos(nPos); if (bOk) { Realize(); } return bOk; } // end of wxToolBar::DeleteTool wxToolBarToolBase* wxToolBar::InsertControl( size_t nPos , wxControl* pControl ) { wxToolBarToolBase* pTool = wxToolBarBase::InsertControl( nPos ,pControl ); if (m_bInitialized) { Realize(); Refresh(); } return pTool; } // end of wxToolBar::InsertControl wxToolBarToolBase* wxToolBar::InsertSeparator( size_t nPos ) { wxToolBarToolBase* pTool = wxToolBarBase::InsertSeparator(nPos); if (m_bInitialized) { Realize(); Refresh(); } return pTool; } // end of wxToolBar::InsertSeparator wxToolBarToolBase* wxToolBar::InsertTool( size_t nPos , int nId , const wxString& rsLabel , const wxBitmap& rBitmap , const wxBitmap& rBmpDisabled , wxItemKind eKind , const wxString& rsShortHelp , const wxString& rsLongHelp , wxObject* pClientData ) { wxToolBarToolBase* pTool = wxToolBarBase::InsertTool( nPos ,nId ,rsLabel ,rBitmap ,rBmpDisabled ,eKind ,rsShortHelp ,rsLongHelp ,pClientData ); if (m_bInitialized) { Realize(); Refresh(); } return pTool; } // end of wxToolBar::InsertTool bool wxToolBar::DoInsertTool( size_t WXUNUSED(nPos) , wxToolBarToolBase* pToolBase ) { wxToolBarTool* pTool = (wxToolBarTool *)pToolBase; pTool->m_vX = m_vXPos; if (pTool->m_vX == -1) pTool->m_vX = m_xMargin; pTool->m_vY = m_vYPos; if (pTool->m_vY == -1) pTool->m_vX = m_yMargin; pTool->SetSize(GetToolSize()); if (pTool->IsButton()) { // // Calculate reasonable max size in case Layout() not called // if ((pTool->m_vX + pTool->GetNormalBitmap().GetWidth() + m_xMargin) > m_vMaxWidth) m_vMaxWidth = (wxCoord)((pTool->m_vX + pTool->GetWidth() + m_xMargin)); if ((pTool->m_vY + pTool->GetNormalBitmap().GetHeight() + m_yMargin) > m_vMaxHeight) m_vMaxHeight = (wxCoord)((pTool->m_vY + pTool->GetHeight() + m_yMargin)); } return TRUE; } // end of wxToolBar::DoInsertTool bool wxToolBar::DoDeleteTool( size_t WXUNUSED(nPos) , wxToolBarToolBase* pTool ) { pTool->Detach(); Refresh(); return TRUE; } // end of wxToolBar::DoDeleteTool bool wxToolBar::Create( wxWindow* pParent , wxWindowID vId , const wxPoint& rPos , const wxSize& rSize , long lStyle , const wxString& rsName ) { if ( !wxWindow::Create( pParent ,vId ,rPos ,rSize ,lStyle ,rsName )) return FALSE; // Set it to grey (or other 3D face colour) SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_MENUBAR)); SetFont(*wxSMALL_FONT); if (GetWindowStyleFlag() & wxTB_VERTICAL) { m_vLastX = 7; m_vLastY = 3; m_maxRows = 32000; // a lot m_maxCols = 1; } else { m_vLastX = 3; m_vLastY = 7; m_maxRows = 1; m_maxCols = 32000; // a lot } SetCursor(*wxSTANDARD_CURSOR); // // The toolbar's tools, if they have labels and the winTB_TEXT // style is set, then we need to take into account the size of // the text when drawing tool bitmaps and the text // if (HasFlag(wxTB_TEXT)) { wxClientDC vDC(this); vDC.SetFont(GetFont()); vDC.GetTextExtent( "XXXX" ,&m_vTextX ,&m_vTextY ); } // // Position it // int nX = rPos.x; int nY = rPos.y; int nWidth = rSize.x; int nHeight = rSize.y; wxFrame* pFrame = wxDynamicCast(GetParent(), wxFrame); if (lStyle & wxTB_HORIZONTAL) { if (nWidth <= 0) { nWidth = pParent->GetClientSize().x; } if (nHeight <= 0) { if (lStyle & wxTB_TEXT) nHeight = m_defaultHeight + m_vTextY; else nHeight = m_defaultHeight; } } else { if (nHeight <= 0) { nHeight = pParent->GetClientSize().y; } if (nWidth <= 0) { if (lStyle & wxTB_TEXT) nWidth = m_vTextX + (int)(m_vTextX/2); // a little margin else nWidth = m_defaultWidth + (int)(m_defaultWidth/2); // a little margin } } if (nX < 0) nX = 0; if (nY < 0) nY = 0; SetSize( nX ,nY ,nWidth ,nHeight ); return TRUE; } // end of wxToolBar::Create wxToolBar::~wxToolBar() { if (m_pToolTip) { delete m_pToolTip; m_pToolTip = NULL; } } // end of wxToolBar::~wxToolBar bool wxToolBar::Realize() { int nMaxToolWidth = 0; int nMaxToolHeight = 0; int nX; int nY; m_nCurrentRowsOrColumns = 0; m_vLastX = m_xMargin; m_vLastY = m_yMargin; m_vMaxWidth = 0; m_vMaxHeight = 0; // // Find the maximum tool width and height // wxToolBarToolsList::Node* pNode = m_tools.GetFirst(); while (pNode ) { wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData(); if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty()) { // // Set the height according to the font and the border size // if (pTool->GetWidth() > m_vTextX) nMaxToolWidth = pTool->GetWidth() + 4; else nMaxToolWidth = m_vTextX; if (pTool->GetHeight() + m_vTextY > nMaxToolHeight) nMaxToolHeight = pTool->GetHeight() + m_vTextY; } else { if (pTool->GetWidth() > nMaxToolWidth ) nMaxToolWidth = pTool->GetWidth() + 4; if (pTool->GetHeight() > nMaxToolHeight) nMaxToolHeight = pTool->GetHeight(); } pNode = pNode->GetNext(); } wxCoord vTbWidth = 0L; wxCoord vTbHeight = 0L; GetSize( &vTbWidth ,&vTbHeight ); if (vTbHeight < nMaxToolHeight) { SetSize( -1L ,-1L ,vTbWidth ,nMaxToolHeight + 4 ); if (GetParent()->IsKindOf(CLASSINFO(wxFrame))) { wxFrame* pFrame = wxDynamicCast(GetParent(), wxFrame); if (pFrame) pFrame->PositionToolBar(); } } int nSeparatorSize = m_toolSeparation; pNode = m_tools.GetFirst(); while (pNode) { wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData(); if (pTool->IsSeparator()) { if (GetWindowStyleFlag() & wxTB_HORIZONTAL) { pTool->m_vX = m_vLastX + nSeparatorSize; pTool->m_vHeight = m_defaultHeight + m_vTextY; if (m_nCurrentRowsOrColumns >= m_maxCols) m_vLastY += nSeparatorSize; else m_vLastX += nSeparatorSize * 4; } else { pTool->m_vY = m_vLastY + nSeparatorSize; pTool->m_vHeight = m_defaultHeight + m_vTextY; if (m_nCurrentRowsOrColumns >= m_maxRows) m_vLastX += nSeparatorSize; else m_vLastY += nSeparatorSize * 4; } } else if (pTool->IsButton()) { if (GetWindowStyleFlag() & wxTB_HORIZONTAL) { if (m_nCurrentRowsOrColumns >= m_maxCols) { m_nCurrentRowsOrColumns = 0; m_vLastX = m_xMargin; m_vLastY += nMaxToolHeight + m_toolPacking; } pTool->m_vX = m_vLastX + (nMaxToolWidth - ((int)(nMaxToolWidth/2) + (int)(pTool->GetWidth()/2))); if (HasFlag(wxTB_TEXT)) pTool->m_vY = m_vLastY + nSeparatorSize - 2; // just bit of adjustment else pTool->m_vY = m_vLastY + (nMaxToolHeight - (int)(pTool->GetHeight()/2)); m_vLastX += nMaxToolWidth + m_toolPacking + m_toolSeparation; } else { if (m_nCurrentRowsOrColumns >= m_maxRows) { m_nCurrentRowsOrColumns = 0; m_vLastX += (nMaxToolWidth + m_toolPacking); m_vLastY = m_yMargin; } pTool->m_vX = m_vLastX + pTool->GetWidth(); if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull()) pTool->m_vY = m_vLastY + (nMaxToolHeight - m_vTextY) + m_toolPacking; else pTool->m_vY = m_vLastY + (nMaxToolHeight - (int)(pTool->GetHeight()/2)); m_vLastY += nMaxToolHeight + m_toolPacking + m_toolSeparation; } m_nCurrentRowsOrColumns++; } else { // TODO: support the controls } if (m_vLastX > m_maxWidth) m_maxWidth = m_vLastX; if (m_vLastY > m_maxHeight) m_maxHeight = m_vLastY; pNode = pNode->GetNext(); } if ( GetWindowStyleFlag() & wxTB_HORIZONTAL ) m_maxWidth += nMaxToolWidth; else m_maxHeight += nMaxToolHeight; m_maxWidth += m_xMargin; m_maxHeight += m_yMargin; m_bInitialized = TRUE; return TRUE; } // end of wxToolBar::Realize // ---------------------------------------------------------------------------- // event handlers // ---------------------------------------------------------------------------- void wxToolBar::OnPaint ( wxPaintEvent& WXUNUSED(rEvent) ) { wxPaintDC vDc(this); PrepareDC(vDc); static int nCount = 0; // // Prevent reentry of OnPaint which would cause wxMemoryDC errors. // if (nCount > 0) return; nCount++; ::WinFillRect(vDc.GetHPS(), &vDc.m_vRclPaint, GetBackgroundColour().GetPixel()); for ( wxToolBarToolsList::Node* pNode = m_tools.GetFirst(); pNode; pNode = pNode->GetNext() ) { wxToolBarTool* pTool = (wxToolBarTool*)pNode->GetData(); if (pTool->IsButton() ) DrawTool(vDc, pTool); if (pTool->IsSeparator()) { wxPen vDarkGreyPen( wxColour(85, 85, 85) ,1 ,wxSOLID ); int nX; int nY; int nHeight = 0; int nWidth = 0; vDc.SetPen(vDarkGreyPen); if (HasFlag(wxTB_TEXT)) { if (HasFlag(wxTB_HORIZONTAL)) { nX = pTool->m_vX; nY = pTool->m_vY - (m_vTextY - 6); nHeight = (m_vTextY - 2) + pTool->GetHeight(); } else { nX = pTool->m_vX + m_xMargin + 10; nY = pTool->m_vY + m_vTextY + m_toolSeparation; nWidth = pTool->GetWidth() > m_vTextX ? pTool->GetWidth() : m_vTextX; } } else { nX = pTool->m_vX; nY = pTool->m_vY; if (HasFlag(wxTB_HORIZONTAL)) nHeight = pTool->GetHeight() - 2; else { nX += m_xMargin + 10; nY += m_yMargin + m_toolSeparation; nWidth = pTool->GetWidth(); } } vDc.DrawLine(nX, nY, nX + nWidth, nY + nHeight); } } nCount--; } // end of wxToolBar::OnPaint void wxToolBar::OnSize ( wxSizeEvent& WXUNUSED(rEvent) ) { #if wxUSE_CONSTRAINTS if (GetAutoLayout()) Layout(); #endif } // end of wxToolBar::OnSize void wxToolBar::OnKillFocus( wxFocusEvent& WXUNUSED(rEvent) ) { OnMouseEnter(m_nPressedTool = m_nCurrentTool = -1); } // end of wxToolBar::OnKillFocus void wxToolBar::OnMouseEvent( wxMouseEvent& rEvent ) { POINTL vPoint; HWND hWnd; wxCoord vX; wxCoord vY; HPOINTER hPtr = ::WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE); ::WinSetPointer(HWND_DESKTOP, hPtr); ::WinQueryPointerPos(HWND_DESKTOP, &vPoint); hWnd = ::WinWindowFromPoint(HWND_DESKTOP, &vPoint, TRUE); if (hWnd != (HWND)GetHwnd()) { m_vToolTimer.Stop(); return; } rEvent.GetPosition(&vX, &vY); wxToolBarTool* pTool = (wxToolBarTool *)FindToolForPosition( vX ,vY ); if (rEvent.LeftDown()) { CaptureMouse(); } if (rEvent.LeftUp()) { ReleaseMouse(); } if (!pTool) { m_vToolTimer.Stop(); if (m_nCurrentTool > -1) { if (rEvent.LeftIsDown()) SpringUpButton(m_nCurrentTool); pTool = (wxToolBarTool *)FindById(m_nCurrentTool); if (pTool && !pTool->IsToggled()) { RaiseTool( pTool ,FALSE ); } m_nCurrentTool = -1; OnMouseEnter(-1); } return; } if (!rEvent.IsButton()) { if (pTool->GetId() != m_nCurrentTool) { // // If the left button is kept down and moved over buttons, // press those buttons. // if (rEvent.LeftIsDown() && pTool->IsEnabled()) { SpringUpButton(m_nCurrentTool); if (pTool->CanBeToggled()) { pTool->Toggle(); } DrawTool(pTool); } wxToolBarTool* pOldTool = (wxToolBarTool*)FindById(m_nCurrentTool); if (pOldTool && !pTool->IsToggled()) RaiseTool( pOldTool ,FALSE ); m_nCurrentTool = pTool->GetId(); OnMouseEnter(m_nCurrentTool); if (!pTool->GetShortHelp().IsEmpty()) { if (m_pToolTip) delete m_pToolTip; m_pToolTip = new wxToolTip(pTool->GetShortHelp()); m_vXMouse = (wxCoord)vPoint.x; m_vYMouse = (wxCoord)vPoint.y; m_vToolTimer.Start(3000L, TRUE); } if (!pTool->IsToggled()) RaiseTool(pTool); } return; } // Left button pressed. if (rEvent.LeftDown() && pTool->IsEnabled()) { if (pTool->CanBeToggled()) { pTool->Toggle(); } DrawTool(pTool); } else if (rEvent.RightDown()) { OnRightClick( pTool->GetId() ,vX ,vY ); } // // Left Button Released. Only this action confirms selection. // If the button is enabled and it is not a toggle tool and it is // in the pressed state, then raise the button and call OnLeftClick. // if (rEvent.LeftUp() && pTool->IsEnabled() ) { // // Pass the OnLeftClick event to tool // if (!OnLeftClick( pTool->GetId() ,pTool->IsToggled()) && pTool->CanBeToggled()) { // // If it was a toggle, and OnLeftClick says No Toggle allowed, // then change it back // pTool->Toggle(); } DrawTool(pTool); } } // end of wxToolBar::OnMouseEvent // ---------------------------------------------------------------------------- // drawing // ---------------------------------------------------------------------------- void wxToolBar::DrawTool( wxToolBarToolBase* pTool ) { wxClientDC vDc(this); DrawTool( vDc ,pTool ); } // end of wxToolBar::DrawTool void wxToolBar::DrawTool( wxDC& rDc , wxToolBarToolBase* pToolBase ) { wxToolBarTool* pTool = (wxToolBarTool *)pToolBase; wxPen vDarkGreyPen( wxColour( 85,85,85 ) ,1 ,wxSOLID ); wxPen vWhitePen( wxT("WHITE") ,1 ,wxSOLID ); wxPen vBlackPen( wxT("BLACK") ,1 ,wxSOLID ); wxBitmap vBitmap = pTool->GetNormalBitmap(); bool bUseMask = FALSE; wxMask* pMask = NULL; RECTL vRect; PrepareDC(rDc); if (!vBitmap.Ok()) return; if ((pMask = vBitmap.GetMask()) != NULL) if (pMask->GetMaskBitmap() != NULLHANDLE) bUseMask = TRUE; if (!pTool->IsToggled()) { LowerTool(pTool, FALSE); if (!pTool->IsEnabled()) { wxColour vColor("GREY"); rDc.SetTextForeground(vColor); if (!pTool->GetDisabledBitmap().Ok()) pTool->SetDisabledBitmap(wxDisableBitmap( vBitmap ,(long)GetBackgroundColour().GetPixel() )); rDc.DrawBitmap( pTool->GetDisabledBitmap() ,pTool->m_vX ,pTool->m_vY ,bUseMask ); } else { wxColour vColor("BLACK"); rDc.SetTextForeground(vColor); rDc.DrawBitmap( vBitmap ,pTool->m_vX ,pTool->m_vY ,bUseMask ); } if (m_windowStyle & wxTB_3DBUTTONS) { RaiseTool(pTool); } if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull()) { wxCoord vX; wxCoord vY; wxCoord vLeft = pTool->m_vX - (int)(pTool->GetWidth()/2); rDc.SetFont(GetFont()); rDc.GetTextExtent( pTool->GetLabel() ,&vX ,&vY ); if (pTool->GetWidth() > vX) // large tools { vLeft = pTool->m_vX + (pTool->GetWidth() - vX); GetSize(&vX, &vY); rDc.DrawText( pTool->GetLabel() ,vLeft ,vY - (m_vTextY - 2) ); } else // normal tools { vLeft += (wxCoord)((m_vTextX - vX)/2); rDc.DrawText( pTool->GetLabel() ,vLeft ,pTool->m_vY + m_vTextY + 4 // a bit of margin ); } } } else { wxColour vColor("GREY"); LowerTool(pTool); rDc.SetTextForeground(vColor); if (!pTool->GetDisabledBitmap().Ok()) pTool->SetDisabledBitmap(wxDisableBitmap( vBitmap ,(long)GetBackgroundColour().GetPixel() )); rDc.DrawBitmap( pTool->GetDisabledBitmap() ,pTool->m_vX ,pTool->m_vY ,bUseMask ); if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull()) { wxCoord vX; wxCoord vY; wxCoord vLeft = pTool->m_vX - (int)(pTool->GetWidth()/2); rDc.SetFont(GetFont()); rDc.GetTextExtent( pTool->GetLabel() ,&vX ,&vY ); vLeft += (wxCoord)((m_vTextX - vX)/2); rDc.DrawText( pTool->GetLabel() ,vLeft ,pTool->m_vY + m_vTextY + 4 // a bit of margin ); } } } // end of wxToolBar::DrawTool // ---------------------------------------------------------------------------- // toolbar geometry // ---------------------------------------------------------------------------- void wxToolBar::SetRows( int nRows ) { wxCHECK_RET( nRows != 0, _T("max number of rows must be > 0") ); m_maxCols = (GetToolsCount() + nRows - 1) / nRows; Refresh(); } // end of wxToolBar::SetRows wxToolBarToolBase* wxToolBar::FindToolForPosition( wxCoord vX , wxCoord vY ) const { wxCoord vTextX = 0; wxCoord vTextY = 0; wxCoord vTBarHeight = 0; GetSize( NULL ,&vTBarHeight ); vY = vTBarHeight - vY; wxToolBarToolsList::Node* pNode = m_tools.GetFirst(); while (pNode) { wxToolBarTool* pTool = (wxToolBarTool *)pNode->GetData(); if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull()) { if ((vX >= (pTool->m_vX - ((wxCoord)(pTool->GetWidth()/2) - 2))) && (vY >= (pTool->m_vY - 2)) && (vX <= (pTool->m_vX + pTool->GetWidth())) && (vY <= (pTool->m_vY + pTool->GetHeight() + m_vTextY + 2))) { return pTool; } } else { if ((vX >= pTool->m_vX) && (vY >= pTool->m_vY) && (vX <= (pTool->m_vX + pTool->GetWidth())) && (vY <= (pTool->m_vY + pTool->GetHeight()))) { return pTool; } } pNode = pNode->GetNext(); } return (wxToolBarToolBase *)NULL; } // end of wxToolBar::FindToolForPosition // ---------------------------------------------------------------------------- // tool state change handlers // ---------------------------------------------------------------------------- void wxToolBar::DoEnableTool( wxToolBarToolBase* pTool , bool WXUNUSED(bEnable) ) { DrawTool(pTool); } // end of wxToolBar::DoEnableTool void wxToolBar::DoToggleTool( wxToolBarToolBase* pTool , bool WXUNUSED(bToggle) ) { DrawTool(pTool); } // end of wxToolBar::DoToggleTool void wxToolBar::DoSetToggle( wxToolBarToolBase* WXUNUSED(pTool) , bool WXUNUSED(bToggle) ) { // nothing to do } // end of wxToolBar::DoSetToggle // // Okay, so we've left the tool we're in ... we must check if the tool we're // leaving was a 'sprung push button' and if so, spring it back to the up // state. // void wxToolBar::SpringUpButton( int vId ) { wxToolBarToolBase* pTool = FindById(vId); if (pTool && pTool->CanBeToggled()) { if (pTool->IsToggled()) pTool->Toggle(); DrawTool(pTool); } } // end of wxToolBar::SpringUpButton // ---------------------------------------------------------------------------- // private helpers // ---------------------------------------------------------------------------- void wxToolBar::LowerTool ( wxToolBarToolBase* pToolBase , bool bLower ) { wxToolBarTool* pTool = (wxToolBarTool*)pToolBase; wxCoord vX; wxCoord vY; wxCoord vWidth; wxCoord vHeight; wxPen vDarkGreyPen( wxColour(85, 85, 85) ,1 ,wxSOLID ); wxPen vWhitePen( "WHITE" ,1 ,wxSOLID ); wxPen vClearPen( GetBackgroundColour() ,1 ,wxSOLID ); wxClientDC vDC(this); if (!pTool) return; if (pTool->IsSeparator()) return; // // We only do this for flat toolbars // if (!HasFlag(wxTB_FLAT)) return; if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty()) { if (pTool->GetWidth() > m_vTextX) { vX = pTool->m_vX - 2; vWidth = pTool->GetWidth() + 4; } else { vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2); vWidth = m_vTextX + 4; } vY = pTool->m_vY - 2; vHeight = pTool->GetHeight() + m_vTextY + 2; } else { vX = pTool->m_vX - 2; vY = pTool->m_vY - 2; vWidth = pTool->GetWidth() + 4; vHeight = pTool->GetHeight() + 4; } if (bLower) { vDC.SetPen(vWhitePen); vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight); vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight); vDC.SetPen(vDarkGreyPen); vDC.DrawLine(vX, vY, vX + vWidth, vY); vDC.DrawLine(vX, vY + vHeight, vX, vY); } else { vDC.SetPen(vClearPen); vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight); vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight); vDC.DrawLine(vX, vY, vX + vWidth, vY); vDC.DrawLine(vX, vY + vHeight, vX, vY); } } // end of WinGuiBase_CToolBarTool::LowerTool void wxToolBar::RaiseTool ( wxToolBarToolBase* pToolBase , bool bRaise ) { wxToolBarTool* pTool = (wxToolBarTool*)pToolBase; wxCoord vX; wxCoord vY; wxCoord vWidth; wxCoord vHeight; wxPen vDarkGreyPen( wxColour(85, 85, 85) ,1 ,wxSOLID ); wxPen vWhitePen( "WHITE" ,1 ,wxSOLID ); wxPen vClearPen( GetBackgroundColour() ,1 ,wxSOLID ); wxClientDC vDC(this); if (!pTool) return; if (pTool->IsSeparator()) return; if (!pTool->IsEnabled()) return; // // We only do this for flat toolbars // if (!HasFlag(wxTB_FLAT)) return; if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsEmpty()) { if (pTool->GetWidth() > m_vTextX) { vX = pTool->m_vX - 2; vWidth = pTool->GetWidth() + 4; } else { vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2); vWidth = m_vTextX + 4; } vY = pTool->m_vY - 2; vHeight = pTool->GetHeight() + m_vTextY + 2; } else { vX = pTool->m_vX - 2; vY = pTool->m_vY - 2; vWidth = pTool->GetWidth() + 4; vHeight = pTool->GetHeight() + 4; } if (bRaise) { vDC.SetPen(vDarkGreyPen); vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight); vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight); vDC.SetPen(vWhitePen); vDC.DrawLine(vX, vY, vX + vWidth, vY); vDC.DrawLine(vX, vY + vHeight, vX, vY); } else { vDC.SetPen(vClearPen); vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight); vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight); vDC.DrawLine(vX, vY, vX + vWidth, vY); vDC.DrawLine(vX, vY + vHeight, vX, vY); } } // end of wxToolBar::RaiseTool void wxToolBar::OnTimer ( wxTimerEvent& rEvent ) { if (rEvent.GetId() == m_vToolTimer.GetTimerId()) { wxPoint vPos( m_vXMouse ,m_vYMouse ); m_pToolTip->DisplayToolTipWindow(vPos); m_vToolTimer.Stop(); m_vToolExpTimer.Start(3000L, TRUE); } else if (rEvent.GetId() == m_vToolExpTimer.GetTimerId()) { m_pToolTip->HideToolTipWindow(); GetParent()->Refresh(); m_vToolExpTimer.Stop(); } } // end of wxToolBar::OnTimer #endif // ndef for wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE