X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/86a37794ff323ea540505c5e3af6e2dbca83943a..19984725d5e943c8f212a80451ec1b1dc1eac8cd:/src/os2/toolbar.cpp diff --git a/src/os2/toolbar.cpp b/src/os2/toolbar.cpp index 03734d30b4..edc4752374 100644 --- a/src/os2/toolbar.cpp +++ b/src/os2/toolbar.cpp @@ -1,9 +1,9 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: toolbar.cpp +// Name: src/os2/toolbar.cpp // Purpose: wxToolBar // Author: David Webster // Modified by: -// Created: 10/17/99 +// Created: 06/30/02 // RCS-ID: $Id$ // Copyright: (c) David Webster // Licence: wxWindows licence @@ -12,68 +12,22 @@ // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" -#ifndef WX_PRECOMP -#include "wx/wx.h" -#endif - #if wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE -#include "wx/toolbar.h" - -#include "malloc.h" -#include "wx/os2/private.h" - -#include "wx/app.h" // for GetComCtl32Version - -// ---------------------------------------------------------------------------- -// constants -// ---------------------------------------------------------------------------- - -// these standard constants are not always defined in compilers headers - -// Styles -#ifndef TBSTYLE_FLAT - #define TBSTYLE_LIST 0x1000 - #define TBSTYLE_FLAT 0x0800 - #define TBSTYLE_TRANSPARENT 0x8000 -#endif - // use TBSTYLE_TRANSPARENT if you use TBSTYLE_FLAT -// Messages -#ifndef TB_GETSTYLE - #define TB_SETSTYLE (WM_USER + 56) - #define TB_GETSTYLE (WM_USER + 57) -#endif +#include "wx/toolbar.h" -#ifndef TB_HITTEST - #define TB_HITTEST (WM_USER + 69) +#ifndef WX_PRECOMP + #include "wx/settings.h" + #include "wx/window.h" + #include "wx/frame.h" + #include "wx/app.h" + #include "wx/dcclient.h" + #include "wx/dcmemory.h" #endif -// these values correspond to those used by comctl32.dll -#define DEFAULTBITMAPX 16 -#define DEFAULTBITMAPY 15 -#define DEFAULTBUTTONX 24 -#define DEFAULTBUTTONY 24 -#define DEFAULTBARHEIGHT 27 - -// ---------------------------------------------------------------------------- -// private function prototypes -// ---------------------------------------------------------------------------- - -static void wxMapBitmap( HBITMAP hBitmap - ,int nWidth - ,int nHeight - ); - -// ---------------------------------------------------------------------------- -// wxWin macros -// ---------------------------------------------------------------------------- - -IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl) +#include "wx/tooltip.h" -BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase) - EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent) - EVT_SYS_COLOUR_CHANGED(wxToolBar::OnSysColourChanged) -END_EVENT_TABLE() +bool wxToolBar::m_bInitialized = false; // ---------------------------------------------------------------------------- // private classes @@ -84,1000 +38,1151 @@ class wxToolBarTool : public wxToolBarToolBase public: inline wxToolBarTool( wxToolBar* pTbar ,int vId + ,const wxString& rsLabel ,const wxBitmap& rBitmap1 ,const wxBitmap& rBitmap2 - ,bool bToggle + ,wxItemKind vKind ,wxObject* pClientData - ,const wxString& rShortHelpString - ,const wxString& rLongHelpString + ,const wxString& rsShortHelpString + ,const wxString& rsLongHelpString ) : wxToolBarToolBase( pTbar ,vId + ,rsLabel ,rBitmap1 ,rBitmap2 - ,bToggle + ,vKind ,pClientData - ,rShortHelpString - ,rLongHelpString + ,rsShortHelpString + ,rsLongHelpString ) { - m_nSepCount = 0; } inline wxToolBarTool( wxToolBar* pTbar ,wxControl* pControl + ,const wxString& label ) : wxToolBarToolBase( pTbar ,pControl + ,label ) { - m_nSepCount = 1; } - // set/get the number of separators which we use to cover the space used by - // a control in the toolbar - inline void SetSeparatorsCount(size_t nCount) { m_nSepCount = nCount; } - inline size_t GetSeparatorsCount(void) const { return m_nSepCount; } + 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 +// ---------------------------------------------------------------------------- -private: - size_t m_nSepCount; -}; +IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl) +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 // ============================================================================ // ---------------------------------------------------------------------------- -// wxToolBarTool +// tool bar tools creation // ---------------------------------------------------------------------------- wxToolBarToolBase* wxToolBar::CreateTool( int nId -, const wxBitmap& rBitmap1 -, const wxBitmap& rBitmap2 -, bool bToggle +, const wxString& rsLabel +, const wxBitmap& rBmpNormal +, const wxBitmap& rBmpDisabled +, wxItemKind eKind , wxObject* pClientData -, const wxString& rShortHelpString -, const wxString& rLongHelpString +, const wxString& rsShortHelp +, const wxString& rsLongHelp ) { - return(new wxToolBarTool( this + return new wxToolBarTool( this ,nId - ,rBitmap1 - ,rBitmap2 - ,bToggle + ,rsLabel + ,rBmpNormal + ,rBmpDisabled + ,eKind ,pClientData - ,rShortHelpString - ,rLongHelpString - )); -} + ,rsShortHelp + ,rsLongHelp + ); +} // end of wxToolBarSimple::CreateTool -wxToolBarToolBase* wxToolBar::CreateTool( +wxToolBarToolBase *wxToolBar::CreateTool( wxControl* pControl +, const wxString& label ) { - return(new wxToolBarTool( this + return new wxToolBarTool( this ,pControl - )); -} + ,label + ); +} // end of wxToolBarSimple::CreateTool // ---------------------------------------------------------------------------- -// wxToolBar construction +// wxToolBarSimple creation // ---------------------------------------------------------------------------- void wxToolBar::Init() { - m_hBitmap = 0; - m_nButtons = 0; - m_defaultWidth = DEFAULTBITMAPX; - m_defaultHeight = DEFAULTBITMAPY; -} - -bool wxToolBar::Create( - wxWindow* pParent -, wxWindowID vId -, const wxPoint& rPos -, const wxSize& rSize -, long lStyle -, const wxString& rName + 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 ) { - // common initialisation - if (!CreateControl( pParent - ,vId - ,rPos - ,rSize - ,lStyle - , wxDefaultValidator - ,rName - )) - return(FALSE); - - // prepare flags - DWORD msflags = 0; // WS_VISIBLE | WS_CHILD always included - // TODO - /* - - if (lStyle & wxBORDER) - msflags |= WS_BORDER; - msflags |= TBSTYLE_TOOLTIPS; - - if (style & wxTB_FLAT) + // + // 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) { - if (wxTheApp->GetComCtl32Version() > 400) - msflags |= TBSTYLE_FLAT; + Realize(); } + return bOk; +} // end of wxToolBar::DeleteTool - // MSW-specific initialisation - if ( !wxControl::MSWCreateControl(TOOLBARCLASSNAME, msflags) ) - return FALSE; - - // toolbar-specific post initialisation - ::SendMessage(GetHwnd(), TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); - - // set up the colors and fonts - wxRGBToColour(m_backgroundColour, GetSysColor(COLOR_BTNFACE)); - m_foregroundColour = *wxBLACK; - - SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT)); - - // position it - 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 = m_defaultHeight; - if (x < 0) - x = 0; - if (y < 0) - y = 0; +bool wxToolBar::DeleteToolByPos( + size_t nPos +) +{ + bool bOk = wxToolBarBase::DeleteToolByPos(nPos); - SetSize(x, y, width, height); - */ - return(TRUE); -} + if (bOk) + { + Realize(); + } + return bOk; +} // end of wxToolBar::DeleteTool -wxToolBar::~wxToolBar() +wxToolBarToolBase* wxToolBar::InsertControl( + size_t nPos +, wxControl* pControl +) { - if (m_hBitmap) + wxToolBarToolBase* pTool = wxToolBarBase::InsertControl( nPos + ,pControl + ); + if (m_bInitialized) { - ::GpiDeleteBitmap((HBITMAP) m_hBitmap); + Realize(); + Refresh(); } -} + return pTool; +} // end of wxToolBar::InsertControl -// ---------------------------------------------------------------------------- -// adding/removing tools -// ---------------------------------------------------------------------------- - -bool wxToolBar::DoInsertTool( - size_t WXUNUSED(nPos) -, wxToolBarToolBase* pTool +wxToolBarToolBase* wxToolBar::InsertSeparator( + size_t nPos ) { - // nothing special to do here - we really create the toolbar buttons in - // Realize() later - pTool->Attach(this); - return(TRUE); -} + wxToolBarToolBase* pTool = wxToolBarBase::InsertSeparator(nPos); + + if (m_bInitialized) + { + Realize(); + Refresh(); + } + return pTool; +} // end of wxToolBar::InsertSeparator -bool wxToolBar::DoDeleteTool( +wxToolBarToolBase* wxToolBar::InsertTool( size_t nPos -, wxToolBarToolBase* pTool +, int nId +, const wxString& rsLabel +, const wxBitmap& rBitmap +, const wxBitmap& rBmpDisabled +, wxItemKind eKind +, const wxString& rsShortHelp +, const wxString& rsLongHelp +, wxObject* pClientData ) { - // normally, we only delete one button, but we use several separators to - // cover the space used by one control sometimes (with old comctl32.dll) - size_t nButtonsToDelete = 1; + 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; - // get the size of the button we're going to delete - RECTL vRect; + pTool->m_vY = m_vYPos; + if (pTool->m_vY == -1) + pTool->m_vX = m_yMargin; - // TODO: - /* - if ( !::SendMessage(GetHwnd(), TB_GETITEMRECT, pos, (LPARAM)&r) ) + pTool->SetSize(GetToolSize()); + + if (pTool->IsButton()) { - wxLogLastError(_T("TB_GETITEMRECT")); + // + // 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 - int width = r.right - r.left; - - if ( tool->IsControl() ) +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_LEFT | wxTB_RIGHT)) { - nButtonsToDelete = ((wxToolBarTool *)tool)->GetSeparatorsCount(); + m_vLastX = 7; + m_vLastY = 3; - width *= nButtonsToDelete; + m_maxRows = 32000; // a lot + m_maxCols = 1; } - - while ( nButtonsToDelete-- > 0 ) + else { - if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, pos, 0) ) - { - wxLogLastError("TB_DELETEBUTTON"); + m_vLastX = 3; + m_vLastY = 7; - return FALSE; - } + 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); - tool->Detach(); + vDC.SetFont(GetFont()); + vDC.GetTextExtent( wxT("XXXX") + ,&m_vTextX + ,&m_vTextY + ); + } - m_nButtons -= nButtonsToDelete; + // + // Position it + // + int nX = rPos.x; + int nY = rPos.y; + int nWidth = rSize.x; + int nHeight = rSize.y; - // reposition all the controls after this button - wxToolBarToolsList::Node *node = m_tools.Item(pos); - for ( node = node->GetNext(); node; node = node->GetNext() ) + if (lStyle & (wxTB_TOP | wxTB_BOTTOM)) + { + if (nWidth <= 0) + { + nWidth = pParent->GetClientSize().x; + } + if (nHeight <= 0) + { + if (lStyle & wxTB_TEXT) + nHeight = m_defaultHeight + m_vTextY; + else + nHeight = m_defaultHeight; + } + } + else { - wxToolBarToolBase *tool2 = node->GetData(); - if ( tool2->IsControl() ) + if (nHeight <= 0) { - int x; - wxControl *control = tool2->GetControl(); - control->GetPosition(&x, NULL); - control->Move(x - width, -1); + 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 } } - */ - return(TRUE); -} + if (nX < 0) + nX = 0; + if (nY < 0) + nY = 0; + + SetSize( nX + ,nY + ,nWidth + ,nHeight + ); + return true; +} // end of wxToolBar::Create -bool wxToolBar::Realize() +wxToolBar::~wxToolBar() { - size_t nTools = GetToolsCount(); - - if (nTools == 0) + if (m_pToolTip) { - // nothing to do - return(TRUE); + delete m_pToolTip; + m_pToolTip = NULL; } +} // end of wxToolBar::~wxToolBar - bool bIsVertical = (GetWindowStyle() & wxTB_VERTICAL) != 0; +bool wxToolBar::Realize() +{ + int nMaxToolWidth = 0; + int nMaxToolHeight = 0; - // TODO: - /* - // First, add the bitmap: we use one bitmap for all toolbar buttons - // ---------------------------------------------------------------- + m_nCurrentRowsOrColumns = 0; + m_vLastX = m_xMargin; + m_vLastY = m_yMargin; + m_vMaxWidth = 0; + m_vMaxHeight = 0; - // if we already have a bitmap, we'll replace the existing one - otherwise - // we'll install a new one - HBITMAP oldToolBarBitmap = (HBITMAP)m_hBitmap; - int totalBitmapWidth = (int)(m_defaultWidth * nTools); - int totalBitmapHeight = (int)m_defaultHeight; + // + // Find the maximum tool width and height + // + wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst(); - // Create a bitmap for all the tool bitmaps - HBITMAP hBitmap = ::CreateCompatibleBitmap(ScreenHDC(), - totalBitmapWidth, - totalBitmapHeight); - if ( !hBitmap ) + while (node ) { - wxLogLastError(_T("CreateCompatibleBitmap")); + wxToolBarTool* pTool = (wxToolBarTool *)node->GetData(); - return FALSE; + if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().empty()) + { + // + // 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(); + } + node = node->GetNext(); } - m_hBitmap = (WXHBITMAP)hBitmap; - - // Now blit all the tools onto this bitmap - HDC memoryDC = ::CreateCompatibleDC(NULL); - HBITMAP oldBitmap = (HBITMAP) ::SelectObject(memoryDC, hBitmap); + wxCoord vTbWidth = 0L; + wxCoord vTbHeight = 0L; - HDC memoryDC2 = ::CreateCompatibleDC(NULL); + GetSize( &vTbWidth + ,&vTbHeight + ); + if (vTbHeight < nMaxToolHeight) + { + SetSize( -1L + ,-1L + ,vTbWidth + ,nMaxToolHeight + 4 + ); + if (GetParent()->IsKindOf(CLASSINFO(wxFrame))) + { + wxFrame* pFrame = wxDynamicCast(GetParent(), wxFrame); - // the button position - wxCoord x = 0; + if (pFrame) + pFrame->PositionToolBar(); + } + } - // the number of buttons (not separators) - int nButtons = 0; + int nSeparatorSize = m_toolSeparation; - wxToolBarToolsList::Node *node = m_tools.GetFirst(); - while ( node ) + node = m_tools.GetFirst(); + while (node) { - wxToolBarToolBase *tool = node->GetData(); - if ( tool->IsButton() ) + wxToolBarTool* pTool = (wxToolBarTool *)node->GetData(); + + if (pTool->IsSeparator()) { - HBITMAP hbmp = GetHbitmapOf(tool->GetBitmap1()); - if ( hbmp ) + if (GetWindowStyleFlag() & (wxTB_TOP | wxTB_BOTTOM)) { - HBITMAP oldBitmap2 = (HBITMAP)::SelectObject(memoryDC2, hbmp); - if ( !BitBlt(memoryDC, x, 0, m_defaultWidth, m_defaultHeight, - memoryDC2, 0, 0, SRCCOPY) ) - { - wxLogLastError("BitBlt"); - } - - ::SelectObject(memoryDC2, oldBitmap2); + 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 { - wxFAIL_MSG( _T("invalid tool button bitmap") ); + 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; } - - // still inc width and number of buttons because otherwise the - // subsequent buttons will all be shifted which is rather confusing - // (and like this you'd see immediately which bitmap was bad) - x += m_defaultWidth; - nButtons++; - } - - node = node->GetNext(); - } - - ::SelectObject(memoryDC, oldBitmap); - ::DeleteDC(memoryDC); - ::DeleteDC(memoryDC2); - - // Map to system colours - wxMapBitmap(hBitmap, totalBitmapWidth, totalBitmapHeight); - - if ( oldToolBarBitmap ) - { - TBREPLACEBITMAP replaceBitmap; - replaceBitmap.hInstOld = NULL; - replaceBitmap.hInstNew = NULL; - replaceBitmap.nIDOld = (UINT) oldToolBarBitmap; - replaceBitmap.nIDNew = (UINT) hBitmap; - replaceBitmap.nButtons = nButtons; - if ( !::SendMessage(GetHwnd(), TB_REPLACEBITMAP, - 0, (LPARAM) &replaceBitmap) ) - { - wxFAIL_MSG(wxT("Could not add bitmap to toolbar")); } - - ::DeleteObject(oldToolBarBitmap); - - // Now delete all the buttons - for ( size_t pos = 0; pos < m_nButtons; pos++ ) + else if (pTool->IsButton()) { - if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, 0, 0) ) + if (GetWindowStyleFlag() & (wxTB_TOP | wxTB_BOTTOM)) { - wxLogLastError("TB_DELETEBUTTON"); + 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 // no old bitmap - { - TBADDBITMAP addBitmap; - addBitmap.hInst = 0; - addBitmap.nID = (UINT) hBitmap; - if ( ::SendMessage(GetHwnd(), TB_ADDBITMAP, - (WPARAM) nButtons, (LPARAM)&addBitmap) == -1 ) + else { - wxFAIL_MSG(wxT("Could not add bitmap to toolbar")); + // TODO: support the controls } + + if (m_vLastX > m_maxWidth) + m_maxWidth = m_vLastX; + if (m_vLastY > m_maxHeight) + m_maxHeight = m_vLastY; + + node = node->GetNext(); } - // Next add the buttons and separators - // ----------------------------------- + if (GetWindowStyleFlag() & (wxTB_TOP | wxTB_BOTTOM)) + m_maxWidth += nMaxToolWidth; + else + m_maxHeight += nMaxToolHeight; - TBBUTTON *buttons = new TBBUTTON[nTools]; + m_maxWidth += m_xMargin; + m_maxHeight += m_yMargin; + m_bInitialized = true; + return true; +} // end of wxToolBar::Realize - // this array will hold the indices of all controls in the toolbar - wxArrayInt controlIds; +// ---------------------------------------------------------------------------- +// event handlers +// ---------------------------------------------------------------------------- - int i = 0; - int bitmapId = 0; +void wxToolBar::OnPaint ( + wxPaintEvent& WXUNUSED(rEvent) +) +{ + wxPaintDC vDc(this); - for ( node = m_tools.GetFirst(); node; node = node->GetNext() ) - { - wxToolBarToolBase *tool = node->GetData(); + PrepareDC(vDc); - // don't add separators to the vertical toolbar - looks ugly - if ( isVertical && tool->IsSeparator() ) - continue; + static int nCount = 0; - TBBUTTON& button = buttons[i]; + // + // Prevent reentry of OnPaint which would cause wxMemoryDC errors. + // + if (nCount > 0) + return; + nCount++; - wxZeroMemory(button); + ::WinFillRect(vDc.GetHPS(), &vDc.m_vRclPaint, GetBackgroundColour().GetPixel()); + for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst(); + node; + node = node->GetNext() ) + { + wxToolBarTool* pTool = (wxToolBarTool*)node->GetData(); - switch ( tool->GetStyle() ) + if (pTool->IsButton() ) + DrawTool(vDc, pTool); + if (pTool->IsSeparator()) { - case wxTOOL_STYLE_CONTROL: - button.idCommand = tool->GetId(); - // fall through: create just a separator too + wxColour gray85(85, 85, 85); + wxPen vDarkGreyPen( gray85, 1, wxSOLID ); + int nX; + int nY; + int nHeight = 0; + int nWidth = 0; + + vDc.SetPen(vDarkGreyPen); + if (HasFlag(wxTB_TEXT)) + { + if (HasFlag(wxTB_TOP) || HasFlag(wxTB_BOTTOM)) + { + 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_TOP) || HasFlag(wxTB_BOTTOM)) + 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 - case wxTOOL_STYLE_SEPARATOR: - button.fsState = TBSTATE_ENABLED; - button.fsStyle = TBSTYLE_SEP; - break; +void wxToolBar::OnSize ( + wxSizeEvent& WXUNUSED(rEvent) +) +{ +#if wxUSE_CONSTRAINTS + if (GetAutoLayout()) + Layout(); +#endif +} // end of wxToolBar::OnSize - case wxTOOL_STYLE_BUTTON: - button.iBitmap = bitmapId; - button.idCommand = tool->GetId(); +void wxToolBar::OnKillFocus( + wxFocusEvent& WXUNUSED(rEvent) +) +{ + OnMouseEnter(m_nPressedTool = m_nCurrentTool = -1); +} // end of wxToolBar::OnKillFocus - if ( tool->IsEnabled() ) - button.fsState |= TBSTATE_ENABLED; - if ( tool->IsToggled() ) - button.fsState |= TBSTATE_CHECKED; +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; + } - button.fsStyle = tool->CanBeToggled() ? TBSTYLE_CHECK - : TBSTYLE_BUTTON; + rEvent.GetPosition(&vX, &vY); - bitmapId++; - break; - } + wxToolBarTool* pTool = (wxToolBarTool *)FindToolForPosition( vX + ,vY + ); - i++; + if (rEvent.LeftDown()) + { + CaptureMouse(); } - - if ( !::SendMessage(GetHwnd(), TB_ADDBUTTONS, - (WPARAM)i, (LPARAM)buttons) ) + if (rEvent.LeftUp()) { - wxLogLastError("TB_ADDBUTTONS"); + ReleaseMouse(); } - delete [] buttons; - - // Deal with the controls finally - // ------------------------------ - - // adjust the controls size to fit nicely in the toolbar - size_t index = 0; - for ( node = m_tools.GetFirst(); node; node = node->GetNext(), index++ ) + if (!pTool) { - wxToolBarToolBase *tool = node->GetData(); - if ( !tool->IsControl() ) - continue; - - wxControl *control = tool->GetControl(); - - wxSize size = control->GetSize(); - - // the position of the leftmost controls corner - int left = -1; - - // note that we use TB_GETITEMRECT and not TB_GETRECT because the - // latter only appeared in v4.70 of comctl32.dll - RECT r; - if ( !SendMessage(GetHwnd(), TB_GETITEMRECT, - index, (LPARAM)(LPRECT)&r) ) + m_vToolTimer.Stop(); + if (m_nCurrentTool > -1) { - wxLogLastError("TB_GETITEMRECT"); - } - - // TB_SETBUTTONINFO message is only supported by comctl32.dll 4.71+ - #if defined(_WIN32_IE) && (_WIN32_IE >= 0x400 ) - // available in headers, now check whether it is available now - // (during run-time) - if ( wxTheApp->GetComCtl32Version() >= 471 ) + if (rEvent.LeftIsDown()) + SpringUpButton(m_nCurrentTool); + pTool = (wxToolBarTool *)FindById(m_nCurrentTool); + if (pTool && !pTool->IsToggled()) { - // set the (underlying) separators width to be that of the - // control - TBBUTTONINFO tbbi; - tbbi.cbSize = sizeof(tbbi); - tbbi.dwMask = TBIF_SIZE; - tbbi.cx = size.x; - if ( !SendMessage(GetHwnd(), TB_SETBUTTONINFO, - tool->GetId(), (LPARAM)&tbbi) ) - { - // the id is probably invalid? - wxLogLastError("TB_SETBUTTONINFO"); - } - + RaiseTool( pTool, FALSE ); } - else - #endif // comctl32.dll 4.71 - // TB_SETBUTTONINFO unavailable + 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()) { - // try adding several separators to fit the controls width - int widthSep = r.right - r.left; - left = r.left; - - TBBUTTON tbb; - wxZeroMemory(tbb); - tbb.idCommand = 0; - tbb.fsState = TBSTATE_ENABLED; - tbb.fsStyle = TBSTYLE_SEP; - - size_t nSeparators = size.x / widthSep; - for ( size_t nSep = 0; nSep < nSeparators; nSep++ ) + SpringUpButton(m_nCurrentTool); + if (pTool->CanBeToggled()) { - if ( !SendMessage(GetHwnd(), TB_INSERTBUTTON, - index, (LPARAM)&tbb) ) - { - wxLogLastError("TB_INSERTBUTTON"); - } - - index++; + pTool->Toggle(); } - - // remember the number of separators we used - we'd have to - // delete all of them later - ((wxToolBarTool *)tool)->SetSeparatorsCount(nSeparators); - - // adjust the controls width to exactly cover the separators - control->SetSize((nSeparators + 1)*widthSep, -1); + DrawTool(pTool); } + wxToolBarTool* pOldTool = (wxToolBarTool*)FindById(m_nCurrentTool); - // and position the control itself correctly vertically - int height = r.bottom - r.top; - int diff = height - size.y; - if ( diff < 0 ) - { - // the control is too high, resize to fit - control->SetSize(-1, height - 2); - - diff = 2; + if (pOldTool && !pTool->IsToggled()) + RaiseTool( pOldTool, FALSE ); + m_nCurrentTool = pTool->GetId(); + OnMouseEnter(m_nCurrentTool); + if (!pTool->GetShortHelp().empty()) + { + 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(1000L, TRUE); + } + if (!pTool->IsToggled()) + RaiseTool(pTool); } - - control->Move(left == -1 ? r.left : left, r.top + (diff + 1) / 2); + return; } - // the max index is the "real" number of buttons - i.e. counting even the - // separators which we added just for aligning the controls - m_nButtons = index; - - if ( !isVertical ) + // Left button pressed. + if (rEvent.LeftDown() && pTool->IsEnabled()) { - if ( m_maxRows == 0 ) + if (pTool->CanBeToggled()) { - // if not set yet, only one row - SetRows(1); + pTool->Toggle(); } + DrawTool(pTool); + } + else if (rEvent.RightDown()) + { + OnRightClick( pTool->GetId() + ,vX + ,vY + ); } - else if ( m_nButtons > 0 ) // vertical non empty toolbar + + // + // 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() ) { - if ( m_maxRows == 0 ) + // + // Pass the OnLeftClick event to tool + // + if (!OnLeftClick( pTool->GetId() + ,pTool->IsToggled()) && + pTool->CanBeToggled()) { - // if not set yet, have one column - SetRows(m_nButtons); + // + // If it was a toggle, and OnLeftClick says No Toggle allowed, + // then change it back + // + pTool->Toggle(); } + DrawTool(pTool); } - */ - return TRUE; -} +} // end of wxToolBar::OnMouseEvent // ---------------------------------------------------------------------------- -// message handlers +// drawing // ---------------------------------------------------------------------------- -bool wxToolBar::OS2Command( - WXUINT nCmd -, WXWORD nId -) +void wxToolBar::DrawTool( wxToolBarToolBase* pTool ) { - wxToolBarToolBase* pTool = FindById((int)nId); + wxClientDC vDc(this); - if (!pTool) - return(FALSE); - // TODO: - /* - if (pTool->CanBeToggled()) - { - LRESULT state = ::SendMessage(GetHwnd(), TB_GETSTATE, id, 0); - tool->SetToggle((state & TBSTATE_CHECKED) != 0); - } + DrawTool( vDc, pTool ); +} // end of wxToolBar::DrawTool - bool toggled = tool->IsToggled(); - - // OnLeftClick() can veto the button state change - for buttons which may - // be toggled only, of couse - if ( !OnLeftClick((int)id, toggled) && tool->CanBeToggled() ) - { - // revert back - toggled = !toggled; - tool->SetToggle(toggled); - - ::SendMessage(GetHwnd(), TB_CHECKBUTTON, id, MAKELONG(toggled, 0)); - } - */ - return(TRUE); -} - -bool wxToolBar::OS2OnNotify( - int WXUNUSED(idCtrl) -, WXLPARAM lParam -, WXLPARAM* pResult -) +void wxToolBar::DrawTool( wxDC& rDc, wxToolBarToolBase* pToolBase ) { - // TODO: - /* - // First check if this applies to us - NMHDR *hdr = (NMHDR *)lParam; + wxToolBarTool* pTool = (wxToolBarTool *)pToolBase; + wxColour gray85( 85,85,85 ); + wxPen vDarkGreyPen( gray85, 1, wxSOLID ); + wxBitmap vBitmap = pTool->GetNormalBitmap(); + bool bUseMask = false; + wxMask* pMask = NULL; - // the tooltips control created by the toolbar is sometimes Unicode, even - // in an ANSI application - this seems to be a bug in comctl32.dll v5 - int code = (int)hdr->code; - if ( (code != TTN_NEEDTEXTA) && (code != TTN_NEEDTEXTW) ) - return FALSE; + PrepareDC(rDc); - HWND toolTipWnd = (HWND)::SendMessage((HWND)GetHWND(), TB_GETTOOLTIPS, 0, 0); - if ( toolTipWnd != hdr->hwndFrom ) - return FALSE; - - LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam; - int id = (int)ttText->hdr.idFrom; - - wxToolBarToolBase *tool = FindById(id); - if ( !tool ) - return FALSE; - - const wxString& help = tool->GetShortHelp(); + if (!vBitmap.Ok()) + return; + if ((pMask = vBitmap.GetMask()) != NULL) + if (pMask->GetMaskBitmap() != NULLHANDLE) + bUseMask = true; - if ( !help.IsEmpty() ) + if (!pTool->IsToggled()) { - if ( code == TTN_NEEDTEXTA ) + LowerTool(pTool, FALSE); + if (!pTool->IsEnabled()) { - ttText->lpszText = (wxChar *)help.c_str(); + wxColour vColor(wxT("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 + ); } -#if (_WIN32_IE >= 0x0300) else { - // FIXME this is a temp hack only until I understand better what - // must be done in both ANSI and Unicode builds - - size_t lenAnsi = help.Len(); - #ifdef __MWERKS__ - // MetroWerks doesn't like calling mbstowcs with NULL argument - size_t lenUnicode = 2*lenAnsi; - #else - size_t lenUnicode = mbstowcs(NULL, help, lenAnsi); - #endif - - // using the pointer of right type avoids us doing all sorts of - // pointer arithmetics ourselves - wchar_t *dst = (wchar_t *)ttText->szText, - *pwz = new wchar_t[lenUnicode + 1]; - mbstowcs(pwz, help, lenAnsi + 1); - memcpy(dst, pwz, lenUnicode*sizeof(wchar_t)); - - // put the terminating _wide_ NUL - dst[lenUnicode] = 0; - - delete [] pwz; + rDc.SetTextForeground(*wxBLACK); + 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 - 1 + ); + } + else // normal tools + { + vLeft += (wxCoord)((m_vTextX - vX)/2); + rDc.DrawText( pTool->GetLabel() + ,vLeft + ,pTool->m_vY + m_vTextY - 1 // a bit of margin + ); + } + } + } + else + { + wxColour vColor(wxT("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 - 1 // a bit of margin + ); } -#endif // _WIN32_IE >= 0x0300 } - - // For backward compatibility... - OnMouseEnter(tool->GetId()); - */ - return(TRUE); -} +} // end of wxToolBar::DrawTool // ---------------------------------------------------------------------------- // toolbar geometry // ---------------------------------------------------------------------------- -void wxToolBar::SetToolBitmapSize( - const wxSize& rSize -) -{ - wxToolBarBase::SetToolBitmapSize(rSize); - - // ::SendMessage(GetHwnd(), TB_SETBITMAPSIZE, 0, MAKELONG(size.x, size.y)); -} - void wxToolBar::SetRows( int nRows ) { - if (nRows == m_maxRows) - { - // avoid resizing the frame uselessly - return; - } - // TODO: - /* - // TRUE in wParam means to create at least as many rows, FALSE - - // at most as many - RECT rect; - ::SendMessage(GetHwnd(), TB_SETROWS, - MAKEWPARAM(nRows, !(GetWindowStyle() & wxTB_VERTICAL)), - (LPARAM) &rect); - - m_maxRows = nRows; - - UpdateSize(); - */ -} - -// The button size is bigger than the bitmap size -wxSize wxToolBar::GetToolSize() const -{ - // TODO: - /* - // TB_GETBUTTONSIZE is supported from version 4.70 -#if defined(_WIN32_IE) && (_WIN32_IE >= 0x300 ) - if ( wxTheApp->GetComCtl32Version() >= 470 ) - { - DWORD dw = ::SendMessage(GetHwnd(), TB_GETBUTTONSIZE, 0, 0); + wxCHECK_RET( nRows != 0, _T("max number of rows must be > 0") ); - return wxSize(LOWORD(dw), HIWORD(dw)); - } - else -#endif // comctl32.dll 4.70+ - { - // defaults - return wxSize(m_defaultWidth + 8, m_defaultHeight + 7); - } - */ - return wxSize(m_defaultWidth + 8, m_defaultHeight + 7); -} + m_maxCols = (GetToolsCount() + nRows - 1) / nRows; + Refresh(); +} // end of wxToolBar::SetRows -wxToolBarToolBase *wxToolBar::FindToolForPosition( +wxToolBarToolBase* wxToolBar::FindToolForPosition( wxCoord vX , wxCoord vY ) const { - POINTL vPt; - - vPt.x = vX; - vPt.y = vY; - - int nIndex = 0; //(int)::SendMessage(GetHwnd(), TB_HITTEST, 0, (LPARAM)&pt); - if (nIndex < 0) + wxCoord vTBarHeight = 0; + + GetSize( NULL + ,&vTBarHeight + ); + vY = vTBarHeight - vY; + wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst(); + while (node) { - // it's a separator or there is no tool at all there - return (wxToolBarToolBase *)NULL; - } - return(m_tools.Item((size_t)nIndex)->GetData()); -} + wxToolBarTool* pTool = (wxToolBarTool *)node->GetData(); -void wxToolBar::UpdateSize() -{ - // we must refresh the frame after the toolbar size (possibly) changed - wxFrame* pFrame = wxDynamicCast(GetParent(), wxFrame); - - if (pFrame) - { - // don't change the size, we just need to generate a WM_SIZE - RECTL vR; - // TODO: - /* - if ( !GetWindowRect(GetHwndOf(frame), &r) ) + if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull()) { - wxLogLastError(_T("GetWindowRect")); + 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; + } } - - (void)::SendMessage(GetHwndOf(frame), WM_SIZE, SIZE_RESTORED, - MAKELPARAM(r.right - r.left, r.bottom - r.top)); - */ + else + { + if ((vX >= pTool->m_vX) && + (vY >= pTool->m_vY) && + (vX <= (pTool->m_vX + pTool->GetWidth())) && + (vY <= (pTool->m_vY + pTool->GetHeight()))) + { + return pTool; + } + } + node = node->GetNext(); } -} + return (wxToolBarToolBase *)NULL; +} // end of wxToolBar::FindToolForPosition // ---------------------------------------------------------------------------- -// tool state +// tool state change handlers // ---------------------------------------------------------------------------- void wxToolBar::DoEnableTool( wxToolBarToolBase* pTool -, bool bEnable +, bool WXUNUSED(bEnable) ) { - // TODO: - /* - ::SendMessage(GetHwnd(), TB_ENABLEBUTTON, - (WPARAM)tool->GetId(), (LPARAM)MAKELONG(enable, 0)); - */ -} + DrawTool(pTool); +} // end of wxToolBar::DoEnableTool void wxToolBar::DoToggleTool( wxToolBarToolBase* pTool -, bool bToggle +, bool WXUNUSED(bToggle) ) { - // TODO: - /* - ::SendMessage(GetHwnd(), TB_CHECKBUTTON, - (WPARAM)tool->GetId(), (LPARAM)MAKELONG(toggle, 0)); - */ -} + DrawTool(pTool); +} // end of wxToolBar::DoToggleTool void wxToolBar::DoSetToggle( - wxToolBarToolBase* pTool -, bool bToggle + wxToolBarToolBase* WXUNUSED(pTool) +, bool WXUNUSED(bToggle) ) { - // VZ: AFAIK, the button has to be created either with TBSTYLE_CHECK or - // without, so we really need to delete the button and recreate it here - wxFAIL_MSG( _T("not implemented") ); -} + // 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 // ---------------------------------------------------------------------------- -// event handlers +// private helpers // ---------------------------------------------------------------------------- -// Responds to colour changes, and passes event on to children. -void wxToolBar::OnSysColourChanged( - wxSysColourChangedEvent& rEvent -) +void wxToolBar::LowerTool ( wxToolBarToolBase* pToolBase, + bool bLower ) { - // TODO: - /* - m_backgroundColour = wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)), - GetGValue(GetSysColor(COLOR_BTNFACE)), GetBValue(GetSysColor(COLOR_BTNFACE))); - */ + wxToolBarTool* pTool = (wxToolBarTool*)pToolBase; + wxCoord vX; + wxCoord vY; + wxCoord vWidth; + wxCoord vHeight; + wxColour gray85( 85,85,85 ); + wxPen vDarkGreyPen( gray85, 1, wxSOLID ); + wxPen vClearPen( GetBackgroundColour(), 1, wxSOLID ); + wxClientDC vDC(this); - // Remap the buttons - Realize(); + if (!pTool) + return; - Refresh(); + if (pTool->IsSeparator()) + return; - // Propagate the event to the non-top-level children - wxWindow::OnSysColourChanged(rEvent); -} + // + // We only do this for flat toolbars + // + if (!HasFlag(wxTB_FLAT)) + return; -void wxToolBar::OnMouseEvent( - wxMouseEvent& rEvent -) -{ - if (rEvent.RightDown()) + if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().empty()) { - // For now, we don't have an id. Later we could - // try finding the tool. - OnRightClick( (int)-1 - ,rEvent.GetX() - ,rEvent.GetY() - ); + 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 { - rEvent.Skip(); + vX = pTool->m_vX - 2; + vY = pTool->m_vY - 2; + vWidth = pTool->GetWidth() + 4; + vHeight = pTool->GetHeight() + 4; } -} - -MRESULT wxToolBar::OS2WindowProc( - HWND hWnd -, WXUINT ulMsg -, MPARAM wParam -, MPARAM lParam -) -{ - // TODO: - /* - if (nMsg == WM_SIZE) + if (bLower) { - // calculate our minor dimenstion ourselves - we're confusing the - // standard logic (TB_AUTOSIZE) with our horizontal toolbars and other - // hacks - RECT r; - if ( ::SendMessage(GetHwnd(), TB_GETITEMRECT, 0, (LPARAM)&r) ) - { - int w, h; + vDC.SetPen(*wxWHITE_PEN); + 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 - if ( GetWindowStyle() & wxTB_VERTICAL ) - { - w = r.right - r.left; - if ( m_maxRows ) - { - w *= (m_nButtons + m_maxRows - 1)/m_maxRows; - } - h = HIWORD(lParam); - } - else - { - w = LOWORD(lParam); - h = r.bottom - r.top; - if ( m_maxRows ) - { - h += 6; // FIXME: this is the separator line height... - h *= m_maxRows; - } - } +void wxToolBar::RaiseTool ( wxToolBarToolBase* pToolBase, + bool bRaise ) +{ + wxToolBarTool* pTool = (wxToolBarTool*)pToolBase; + wxCoord vX; + wxCoord vY; + wxCoord vWidth; + wxCoord vHeight; + wxColour gray85( 85,85,85 ); + wxPen vDarkGreyPen( gray85, 1, wxSOLID ); + wxPen vClearPen( GetBackgroundColour(), 1, wxSOLID ); + wxClientDC vDC(this); - if ( MAKELPARAM(w, h) != lParam ) - { - // size really changed - SetSize(w, h); - } + if (!pTool) + return; - // message processed - return 0; - } - } + if (pTool->IsSeparator()) + return; - return wxControl::MSWWindowProc(nMsg, wParam, lParam); - */ - return((MRESULT)0); -} + if (!pTool->IsEnabled()) + return; -// ---------------------------------------------------------------------------- -// private functions -// ---------------------------------------------------------------------------- + // + // We only do this for flat toolbars + // + if (!HasFlag(wxTB_FLAT)) + return; -// These are the default colors used to map the bitmap colors to the current -// system colors. Note that they are in BGR format because this is what Windows -// wants (and not RGB) - -#define BGR_BUTTONTEXT (RGB(000,000,000)) // black -#define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey -#define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey -#define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white -#define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue -#define BGR_BACKGROUND (RGB(255,000,255)) // magenta - -void wxMapBitmap( - HBITMAP hBitmap -, int nWidth -, int nHeight -) -{ - // TODO: - /* - COLORMAP ColorMap[] = - { - {BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black - {BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey - {BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey - {BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white - {BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue - {BGR_BACKGROUND, COLOR_WINDOW} // magenta - }; - - int NUM_MAPS = (sizeof(ColorMap)/sizeof(COLORMAP)); - int n; - for ( n = 0; n < NUM_MAPS; n++) - { - ColorMap[n].to = ::GetSysColor(ColorMap[n].to); - } - - HBITMAP hbmOld; - HDC hdcMem = CreateCompatibleDC(NULL); - - if (hdcMem) - { - hbmOld = (HBITMAP) SelectObject(hdcMem, hBitmap); - - int i, j, k; - for ( i = 0; i < width; i++) + if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().empty()) { - for ( j = 0; j < height; j++) + if (pTool->GetWidth() > m_vTextX) { - COLORREF pixel = ::GetPixel(hdcMem, i, j); -// -// BYTE red = GetRValue(pixel); -// BYTE green = GetGValue(pixel); -// BYTE blue = GetBValue(pixel); -// - - for ( k = 0; k < NUM_MAPS; k ++) - { - if ( ColorMap[k].from == pixel ) - { - // COLORREF actualPixel = ::SetPixel(hdcMem, i, j, ColorMap[k].to); - break; - } - } + 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(*wxWHITE_PEN); + 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.GetId()) + { + wxPoint vPos( m_vXMouse, m_vYMouse ); - SelectObject(hdcMem, hbmOld); - DeleteObject(hdcMem); - } - */ -} - -// Some experiments... -#if 0 - // What we want to do is create another bitmap which has a depth of 4, - // and set the bits. So probably we want to convert this HBITMAP into a - // DIB, then call SetDIBits. - // AAAGH. The stupid thing is that if newBitmap has a depth of 4 (less than that of - // the screen), then SetDIBits fails. - HBITMAP newBitmap = ::CreateBitmap(totalBitmapWidth, totalBitmapHeight, 1, 4, NULL); - HANDLE newDIB = ::BitmapToDIB((HBITMAP) m_hBitmap, NULL); - LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) GlobalLock(newDIB); - - dc = ::GetDC(NULL); -// LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) newDIB; - - int result = ::SetDIBits(dc, newBitmap, 0, lpbmi->biHeight, FindDIBBits((LPSTR)lpbmi), (LPBITMAPINFO)lpbmi, - DIB_PAL_COLORS); - DWORD err = GetLastError(); - - ::ReleaseDC(NULL, dc); - - // Delete the DIB - GlobalUnlock (newDIB); - GlobalFree (newDIB); - -// WXHBITMAP hBitmap2 = wxCreateMappedBitmap((WXHINSTANCE) wxGetInstance(), (WXHBITMAP) m_hBitmap); - // Substitute our new bitmap for the old one - ::DeleteObject((HBITMAP) m_hBitmap); - m_hBitmap = (WXHBITMAP) newBitmap; -#endif + m_pToolTip->DisplayToolTipWindow(vPos); + m_vToolTimer.Stop(); + m_vToolExpTimer.Start(4000L, TRUE); + } + else if (rEvent.GetId() == m_vToolExpTimer.GetId()) + { + m_pToolTip->HideToolTipWindow(); + GetParent()->Refresh(); + m_vToolExpTimer.Stop(); + } +} // end of wxToolBar::OnTimer -#endif +#endif // ndef for wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE