]> git.saurik.com Git - wxWidgets.git/blobdiff - src/univ/toolbar.cpp
use wxIsSameDouble() and wxIsNullDouble() for warning-less double comparison of doubles
[wxWidgets.git] / src / univ / toolbar.cpp
index 774c5d5a75047e000daa4e8a733a3f5927a94567..d07923834ebff398ef85daba5724861ff5640ff3 100644 (file)
 // headers
 // ----------------------------------------------------------------------------
 
-#ifdef __GNUG__
-    #pragma implementation "univtoolbar.h"
-#endif
-
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
     #pragma hdrstop
 #endif
 
+#if wxUSE_TOOLBAR
+
 #ifndef WX_PRECOMP
     #include "wx/utils.h"
     #include "wx/app.h"
-
-    #include "wx/univ/renderer.h"
 #endif
 
+#include "wx/univ/renderer.h"
+
+#include "wx/frame.h"
 #include "wx/toolbar.h"
 #include "wx/image.h"
+#include "wx/log.h"
 
 // ----------------------------------------------------------------------------
 // constants
 // ----------------------------------------------------------------------------
 
 // value meaning that m_widthSeparator is not initialized
-static const wxCoord INVALID_WIDTH = -1;
+static const wxCoord INVALID_WIDTH = wxDefaultCoord;
 
 // ----------------------------------------------------------------------------
 // wxToolBarTool: our implementation of wxToolBarToolBase
@@ -53,23 +53,45 @@ static const wxCoord INVALID_WIDTH = -1;
 class WXDLLEXPORT wxToolBarTool : public wxToolBarToolBase
 {
 public:
-    wxToolBarTool( wxToolBarBase *tbar = (wxToolBarBase *)NULL,
-                   int id = wxID_SEPARATOR,
-                   const wxBitmap& bitmap1 = wxNullBitmap,
-                   const wxBitmap& bitmap2 = wxNullBitmap,
-                   bool toggle = FALSE,
-                   wxObject *clientData = (wxObject *) NULL,
-                   const wxString& shortHelpString = wxEmptyString,
-                   const wxString& longHelpString = wxEmptyString )
-        : wxToolBarToolBase(tbar, id, bitmap1, bitmap2, toggle, clientData,
-                            shortHelpString, longHelpString)
+    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)
     {
         // no position yet
         m_x =
-        m_y = -1;
+        m_y = wxDefaultCoord;
+        m_width =
+        m_height = 0;
 
         // not pressed yet
-        m_isInverted = FALSE;
+        m_isInverted = false;
+
+        // mouse not here yet
+        m_underMouse = false;
+    }
+
+    wxToolBarTool(wxToolBar *tbar, wxControl *control)
+        : wxToolBarToolBase(tbar, control)
+    {
+        // no position yet
+        m_x =
+        m_y = wxDefaultCoord;
+        m_width =
+        m_height = 0;
+
+        // not pressed yet
+        m_isInverted = false;
+
+        // mouse not here yet
+        m_underMouse = false;
     }
 
     // is this tool pressed, even temporarily? (this is different from being
@@ -83,14 +105,23 @@ public:
     // press the tool temporarily by inverting its toggle state
     void Invert() { m_isInverted = !m_isInverted; }
 
+    // Set underMouse
+    void SetUnderMouse( bool under = true ) { m_underMouse = under; }
+    bool IsUnderMouse() { return m_underMouse; }
+
 public:
-    // the tool position (the size is known by the toolbar itself)
-    int m_x,
-        m_y;
+    // the tool position (for controls)
+    wxCoord m_x;
+    wxCoord m_y;
+    wxCoord m_width;
+    wxCoord m_height;
 
 private:
-    // TRUE if the tool is pressed
+    // true if the tool is pressed
     bool m_isInverted;
+
+    // true if the tool is under the mouse
+    bool m_underMouse;
 };
 
 // ============================================================================
@@ -106,7 +137,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl);
 void wxToolBar::Init()
 {
     // no tools yet
-    m_needsLayout = FALSE;
+    m_needsLayout = false;
 
     // unknown widths for the tools and separators
     m_widthSeparator = INVALID_WIDTH;
@@ -114,9 +145,6 @@ void wxToolBar::Init()
     m_maxWidth =
     m_maxHeight = 0;
 
-    m_toolPressed = NULL;
-    m_toolCurrent = NULL;
-
     wxRenderer *renderer = GetRenderer();
 
     SetToolBitmapSize(renderer->GetToolBarButtonSize(&m_widthSeparator));
@@ -133,18 +161,27 @@ bool wxToolBar::Create(wxWindow *parent,
     if ( !wxToolBarBase::Create(parent, id, pos, size, style,
                                 wxDefaultValidator, name) )
     {
-        return FALSE;
+        return false;
     }
 
     CreateInputHandler(wxINP_HANDLER_TOOLBAR);
 
     SetBestSize(size);
 
-    return TRUE;
+    return true;
 }
 
 wxToolBar::~wxToolBar()
 {
+    // Make sure the toolbar is removed from the parent.
+    SetSize(0,0);
+}
+
+void wxToolBar::SetMargins(int x, int y)
+{
+    // This required for similar visual effects under
+    // native platforms and wxUniv.
+    wxToolBarBase::SetMargins( x + 3, y + 3 );
 }
 
 // ----------------------------------------------------------------------------
@@ -170,7 +207,7 @@ wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
             return NULL;
     }
 
-    for ( wxToolBarToolsList::Node *node = m_tools.GetFirst();
+    for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
           node;
           node = node->GetNext() )
     {
@@ -204,23 +241,23 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
                              wxToolBarToolBase * WXUNUSED(tool))
 {
     // recalculate the toolbar geometry before redrawing it the next time
-    m_needsLayout = TRUE;
+    m_needsLayout = true;
 
     // and ensure that we indeed are going to redraw
     Refresh();
 
-    return TRUE;
+    return true;
 }
 
 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos),
                              wxToolBarToolBase * WXUNUSED(tool))
 {
     // as above
-    m_needsLayout = TRUE;
+    m_needsLayout = true;
 
     Refresh();
 
-    return TRUE;
+    return true;
 }
 
 void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
@@ -228,7 +265,7 @@ void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
     // created disabled-state bitmap on demand
     if ( !enable && !tool->GetDisabledBitmap().Ok() )
     {
-        wxImage image( tool->GetNormalBitmap() );
+        wxImage image( tool->GetNormalBitmap().ConvertToImage() );
 
         // TODO: don't hardcode 180
         unsigned char bg_red = 180;
@@ -251,9 +288,9 @@ void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
                 unsigned char blue = image.GetBlue(x,y);
                 if (!has_mask || red != mask_red || green != mask_green || blue != mask_blue)
                 {
-                    red = (((wxInt32) red  - bg_red) >> 1) + bg_red;
-                    green = (((wxInt32) green  - bg_green) >> 1) + bg_green;
-                    blue = (((wxInt32) blue  - bg_blue) >> 1) + bg_blue;
+                    red = (unsigned char)((((wxInt32) red  - bg_red) >> 1) + bg_red);
+                    green = (unsigned char)((((wxInt32) green  - bg_green) >> 1) + bg_green);
+                    blue = (unsigned char)((((wxInt32) blue  - bg_blue) >> 1) + bg_blue);
                     image.SetRGB( x, y, red, green, blue );
                 }
             }
@@ -268,15 +305,15 @@ void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
                 unsigned char blue = image.GetBlue(x,y);
                 if (!has_mask || red != mask_red || green != mask_green || blue != mask_blue)
                 {
-                    red = (((wxInt32) red  - bg_red) >> 1) + bg_red;
-                    green = (((wxInt32) green  - bg_green) >> 1) + bg_green;
-                    blue = (((wxInt32) blue  - bg_blue) >> 1) + bg_blue;
+                    red = (unsigned char)((((wxInt32) red  - bg_red) >> 1) + bg_red);
+                    green = (unsigned char)((((wxInt32) green  - bg_green) >> 1) + bg_green);
+                    blue = (unsigned char)((((wxInt32) blue  - bg_blue) >> 1) + bg_blue);
                     image.SetRGB( x, y, red, green, blue );
                 }
             }
         }
 
-        tool->SetDisabledBitmap( image.ConvertToBitmap() );
+        tool->SetDisabledBitmap(image);
     }
 
     RefreshTool(tool);
@@ -295,22 +332,21 @@ void wxToolBar::DoSetToggle(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
 }
 
 wxToolBarToolBase *wxToolBar::CreateTool(int id,
-                                         const wxBitmap& bitmap1,
-                                         const wxBitmap& bitmap2,
-                                         bool toggle,
+                                         const wxString& label,
+                                         const wxBitmap& bmpNormal,
+                                         const wxBitmap& bmpDisabled,
+                                         wxItemKind kind,
                                          wxObject *clientData,
-                                         const wxString& shortHelpString,
-                                         const wxString& longHelpString)
+                                         const wxString& shortHelp,
+                                         const wxString& longHelp)
 {
-    return new wxToolBarTool( this, id, bitmap1, bitmap2, toggle,
-                              clientData, shortHelpString, longHelpString);
+    return new wxToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
+                             clientData, shortHelp, longHelp);
 }
 
 wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
 {
-    wxFAIL_MSG( wxT("Toolbar doesn't support controls yet (TODO)") );
-
-    return NULL;
+    return new wxToolBarTool(this, control);
 }
 
 // ----------------------------------------------------------------------------
@@ -336,13 +372,39 @@ wxRect wxToolBar::GetToolRect(wxToolBarToolBase *toolBase) const
 
     if ( IsVertical() )
     {
-        rect.width = m_defaultWidth;
-        rect.height = tool->IsSeparator() ? m_widthSeparator : m_defaultHeight;
+        if (tool->IsButton())
+        {
+            rect.width = m_defaultWidth;
+            rect.height = m_defaultHeight;
+        }
+        else if (tool->IsSeparator())
+        {
+            rect.width = m_defaultWidth;
+            rect.height = m_widthSeparator;
+        }
+        else // control
+        {
+            rect.width = tool->m_width;
+            rect.height = tool->m_height;
+        }
     }
     else // horizontal
     {
-        rect.width = tool->IsSeparator() ? m_widthSeparator : m_defaultWidth;
-        rect.height = m_defaultHeight;
+        if (tool->IsButton())
+        {
+            rect.width = m_defaultWidth;
+            rect.height = m_defaultHeight;
+        }
+        else if (tool->IsSeparator())
+        {
+            rect.width = m_widthSeparator;
+            rect.height = m_defaultHeight;
+        }
+        else // control
+        {
+            rect.width = tool->m_width;
+            rect.height = tool->m_height;
+        }
     }
 
     rect.width += 2*m_xMargin;
@@ -354,31 +416,31 @@ wxRect wxToolBar::GetToolRect(wxToolBarToolBase *toolBase) const
 bool wxToolBar::Realize()
 {
     if ( !wxToolBarBase::Realize() )
-        return FALSE;
+        return false;
 
-    m_needsLayout = TRUE;
+    m_needsLayout = true;
     DoLayout();
 
     SetBestSize(wxDefaultSize);
 
-    return TRUE;
+    return true;
 }
 
 void wxToolBar::DoLayout()
 {
     wxASSERT_MSG( m_needsLayout, _T("why are we called?") );
 
-    m_needsLayout = FALSE;
+    m_needsLayout = false;
 
     wxCoord x = m_xMargin,
             y = m_yMargin;
 
     const wxCoord widthTool = IsVertical() ? m_defaultHeight : m_defaultWidth;
-    wxCoord margin = IsVertical() ? m_xMargin : m_yMargin,
-           *pCur = IsVertical() ? &y : &x;
+    wxCoord margin = IsVertical() ? m_xMargin : m_yMargin;
+    wxCoord *pCur = IsVertical() ? &y : &x;
 
     // calculate the positions of all elements
-    for ( wxToolBarToolsList::Node *node = m_tools.GetFirst();
+    for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
           node;
           node = node->GetNext() )
     {
@@ -387,7 +449,26 @@ void wxToolBar::DoLayout()
         tool->m_x = x;
         tool->m_y = y;
 
-        *pCur += (tool->IsSeparator() ? m_widthSeparator : widthTool) + margin;
+        // TODO ugly number fiddling
+        if (tool->IsButton())
+        {
+            *pCur += widthTool;
+        }
+        else if (tool->IsSeparator())
+        {
+            *pCur += m_widthSeparator;
+        }
+        else if (!IsVertical()) // horizontal control
+        {
+            wxControl *control = tool->GetControl();
+            wxSize size = control->GetSize();
+            tool->m_y += (m_defaultHeight - size.y)/2;
+            tool->m_width = size.x;
+            tool->m_height = size.y;
+
+            *pCur += tool->m_width;
+        }
+        *pCur += margin;
     }
 
     // calculate the total toolbar size
@@ -403,6 +484,39 @@ wxSize wxToolBar::DoGetBestClientSize() const
     return wxSize(m_maxWidth, m_maxHeight);
 }
 
+void wxToolBar::DoSetSize(int x, int y, int width, int height, int sizeFlags)
+{
+    int old_width, old_height;
+    GetSize(&old_width, &old_height);
+
+    wxToolBarBase::DoSetSize(x, y, width, height, sizeFlags);
+
+    // Correct width and height if needed.
+    if ( width == wxDefaultCoord || height == wxDefaultCoord )
+    {
+        int tmp_width, tmp_height;
+        GetSize(&tmp_width, &tmp_height);
+
+        if ( width == wxDefaultCoord )
+            width = tmp_width;
+        if ( height == wxDefaultCoord )
+            height = tmp_height;
+    }
+
+    // We must refresh the frame size when the toolbar changes size
+    // otherwise the toolbar can be shown incorrectly
+    if ( old_width != width || old_height != height )
+    {
+        // But before we send the size event check it
+        // we have a frame that is not being deleted.
+        wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
+        if ( frame && !frame->IsBeingDeleted() )
+        {
+            frame->SendSizeEvent();
+        }
+    }
+}
+
 // ----------------------------------------------------------------------------
 // wxToolBar drawing
 // ----------------------------------------------------------------------------
@@ -450,11 +564,11 @@ void wxToolBar::DoDraw(wxControlRenderer *renderer)
     GetRectLimits(rectUpdate, &start, &end);
 
     // and redraw all the tools intersecting it
-    for ( wxToolBarToolsList::Node *node = m_tools.GetFirst();
+    for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
           node;
           node = node->GetNext() )
     {
-        wxToolBarToolBase *tool = node->GetData();
+        wxToolBarTool *tool = (wxToolBarTool*) node->GetData();
         wxRect rectTool = GetToolRect(tool);
         wxCoord startTool, endTool;
         GetRectLimits(rectTool, &startTool, &endTool);
@@ -471,13 +585,19 @@ void wxToolBar::DoDraw(wxControlRenderer *renderer)
             break;
         }
 
+        if (tool->IsSeparator() && !HasFlag(wxTB_FLAT))
+        {
+            // Draw separators only in flat mode
+            continue;
+        }
+
         // deal with the flags
         int flags = 0;
 
         if ( tool->IsEnabled() )
         {
-            // the toolbars without wxTB_FLAT don't react to the mouse hovering
-            if ( HasFlag(wxTB_FLAT) && (tool == m_toolCurrent) )
+            // The toolbars without wxTB_FLAT don't react to the mouse hovering
+            if ( !HasFlag(wxTB_FLAT) || tool->IsUnderMouse() )
                 flags |= wxCONTROL_CURRENT;
         }
         else // disabled tool
@@ -485,22 +605,30 @@ void wxToolBar::DoDraw(wxControlRenderer *renderer)
             flags |= wxCONTROL_DISABLED;
         }
 
-        if ( tool == m_toolPressed )
-            flags |= wxCONTROL_FOCUSED;
+        //if ( tool == m_toolCaptured )
+        //    flags |= wxCONTROL_FOCUSED;
 
-        if ( ((wxToolBarTool *)tool)->IsPressed() )
-            flags |= wxCONTROL_PRESSED;
+        if ( tool->IsPressed() )
+            flags = wxCONTROL_PRESSED;
 
         wxString label;
         wxBitmap bitmap;
         if ( !tool->IsSeparator() )
         {
-            label = tool->GetLabel();
+            // label = tool->GetLabel();
             bitmap = tool->GetBitmap();
         }
         //else: leave both the label and the bitmap invalid to draw a separator
 
-        rend->DrawToolBarButton(dc, label, bitmap, rectTool, flags);
+        if ( !tool->IsControl() )
+        {
+            rend->DrawToolBarButton(dc, label, bitmap, rectTool, flags, tool->GetStyle());
+        }
+        else // control
+        {
+            wxControl *control = tool->GetControl();
+            control->Move(tool->m_x, tool->m_y);
+        }
     }
 }
 
@@ -508,122 +636,83 @@ void wxToolBar::DoDraw(wxControlRenderer *renderer)
 // wxToolBar actions
 // ----------------------------------------------------------------------------
 
-void wxToolBar::Press()
-{
-    wxCHECK_RET( m_toolCurrent, _T("no tool to press?") );
-
-    wxLogTrace(_T("toolbar"),
-               _T("Button '%s' pressed."),
-               m_toolCurrent->GetShortHelp().c_str());
-
-    // this is the tool whose state is going to change
-    m_toolPressed = (wxToolBarTool *)m_toolCurrent;
-
-    // we must toggle it regardless of whether it is a checkable tool or not,
-    // so use Invert() and not Toggle() here
-    m_toolPressed->Invert();
-
-    RefreshTool(m_toolPressed);
-}
-
-void wxToolBar::Release()
-{
-    wxCHECK_RET( m_toolPressed, _T("no tool to release?") );
-
-    wxLogTrace(_T("toolbar"),
-               _T("Button '%s' released."),
-               m_toolCurrent->GetShortHelp().c_str());
-
-    wxASSERT_MSG( m_toolPressed->IsInverted(), _T("release unpressed button?") );
-
-    m_toolPressed->Invert();
-
-    RefreshTool(m_toolPressed);
-}
-
-void wxToolBar::Toggle()
+bool wxToolBar::PerformAction(const wxControlAction& action,
+                              long numArg,
+                              const wxString& strArg)
 {
-    m_toolCurrent = m_toolPressed;
+    wxToolBarTool *tool = (wxToolBarTool*) FindById(numArg);
+    if (!tool)
+        return false;
 
-    Release();
+    if ( action == wxACTION_TOOLBAR_TOGGLE )
+    {
+        PerformAction( wxACTION_BUTTON_RELEASE, numArg );
 
-    Click();
-}
+        PerformAction( wxACTION_BUTTON_CLICK, numArg );
+    }
+    else if ( action == wxACTION_TOOLBAR_PRESS )
+    {
+        wxLogTrace(_T("toolbar"), _T("Button '%s' pressed."), tool->GetShortHelp().c_str());
 
-void wxToolBar::Click()
-{
-    wxCHECK_RET( m_toolCurrent, _T("no tool to click?") );
+        tool->Invert();
 
-    bool isToggled;
-    if ( m_toolCurrent->CanBeToggled() )
+        RefreshTool( tool );
+    }
+    else if ( action == wxACTION_TOOLBAR_RELEASE )
     {
-        m_toolCurrent->Toggle();
+        wxLogTrace(_T("toolbar"), _T("Button '%s' released."), tool->GetShortHelp().c_str());
+
+        wxASSERT_MSG( tool->IsInverted(), _T("release unpressed button?") );
 
-        RefreshTool(m_toolCurrent);
+        tool->Invert();
 
-        isToggled = m_toolCurrent->IsToggled();
+        RefreshTool( tool );
     }
-    else // simple non-checkable tool
+    else if ( action == wxACTION_TOOLBAR_CLICK )
     {
-        isToggled = FALSE;
-    }
+        bool isToggled;
+        if ( tool->CanBeToggled() )
+        {
+            tool->Toggle();
 
-    OnLeftClick(m_toolCurrent->GetId(), isToggled);
-}
+            RefreshTool( tool );
 
-bool wxToolBar::PerformAction(const wxControlAction& action,
-                              long numArg,
-                              const wxString& strArg)
-{
-    if ( action == wxACTION_TOOLBAR_TOGGLE )
-        Toggle();
-    else if ( action == wxACTION_TOOLBAR_PRESS )
-        Press();
-    else if ( action == wxACTION_TOOLBAR_RELEASE )
-        Release();
-    else if ( action == wxACTION_TOOLBAR_CLICK )
-        Click();
+            isToggled = tool->IsToggled();
+        }
+        else // simple non-checkable tool
+        {
+            isToggled = false;
+        }
+        OnLeftClick( tool->GetId(), isToggled );
+    }
     else if ( action == wxACTION_TOOLBAR_ENTER )
     {
-        wxToolBarToolBase *toolCurrentOld = m_toolCurrent;
-        m_toolCurrent = FindById((int)numArg);
+        wxCHECK_MSG( tool, false, _T("no tool to enter?") );
 
-        if ( m_toolCurrent != toolCurrentOld )
+        if ( HasFlag(wxTB_FLAT) && tool->IsEnabled() )
         {
-            // the appearance of the current tool only changes for the flat
-            // toolbars
-            if ( HasFlag(wxTB_FLAT) )
-            {
-                // and only if the tool was/is enabled
-                if ( toolCurrentOld && toolCurrentOld->IsEnabled() )
-                    RefreshTool(toolCurrentOld);
+            tool->SetUnderMouse( true );
 
-                if ( m_toolCurrent )
-                {
-                    if ( m_toolCurrent->IsEnabled() )
-                        RefreshTool(m_toolCurrent);
-                }
-                else
-                {
-                    wxFAIL_MSG( _T("no current tool in wxACTION_TOOLBAR_ENTER?") );
-                }
-            }
+            if ( !tool->IsToggled() )
+                RefreshTool( tool );
         }
     }
     else if ( action == wxACTION_TOOLBAR_LEAVE )
     {
-        if ( m_toolCurrent )
+        wxCHECK_MSG( tool, false, _T("no tool to leave?") );
+
+        if ( HasFlag(wxTB_FLAT) && tool->IsEnabled() )
         {
-            wxToolBarToolBase *toolCurrentOld = m_toolCurrent;
-            m_toolCurrent = NULL;
+            tool->SetUnderMouse( false );
 
-            RefreshTool(toolCurrentOld);
+            if ( !tool->IsToggled() )
+                RefreshTool( tool );
         }
     }
     else
         return wxControl::PerformAction(action, numArg, strArg);
 
-    return TRUE;
+    return true;
 }
 
 // ============================================================================
@@ -631,8 +720,11 @@ bool wxToolBar::PerformAction(const wxControlAction& action,
 // ============================================================================
 
 wxStdToolbarInputHandler::wxStdToolbarInputHandler(wxInputHandler *handler)
-                        : wxStdButtonInputHandler(handler)
+                        : wxStdInputHandler(handler)
 {
+    m_winCapture = NULL;
+    m_toolCapture = NULL;
+    m_toolLast = NULL;
 }
 
 bool wxStdToolbarInputHandler::HandleKey(wxInputConsumer *consumer,
@@ -647,61 +739,136 @@ bool wxStdToolbarInputHandler::HandleKey(wxInputConsumer *consumer,
 bool wxStdToolbarInputHandler::HandleMouse(wxInputConsumer *consumer,
                                            const wxMouseEvent& event)
 {
-    // don't let the base class press the disabled buttons but simply ignore
-    // all events on them
     wxToolBar *tbar = wxStaticCast(consumer->GetInputWindow(), wxToolBar);
     wxToolBarToolBase *tool = tbar->FindToolForPosition(event.GetX(), event.GetY());
 
-    if ( !tool || !tool->IsEnabled() )
-        return TRUE;
+    if ( event.Button(1) )
+    {
+
+        if ( event.LeftDown() || event.LeftDClick() )
+        {
+            if ( !tool || !tool->IsEnabled() )
+                return true;
+
+            m_winCapture = tbar;
+            m_winCapture->CaptureMouse();
+
+            m_toolCapture = tool;
+
+            consumer->PerformAction( wxACTION_BUTTON_PRESS, tool->GetId() );
+
+            return true;
+        }
+        else if ( event.LeftUp() )
+        {
+            if ( m_winCapture )
+            {
+                m_winCapture->ReleaseMouse();
+                m_winCapture = NULL;
+            }
 
-    return wxStdButtonInputHandler::HandleMouse(consumer, event);
+            if (m_toolCapture)
+            {
+                if ( tool == m_toolCapture )
+                    consumer->PerformAction( wxACTION_BUTTON_TOGGLE, m_toolCapture->GetId() );
+                else
+                    consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolCapture->GetId() );
+            }
+
+            m_toolCapture = NULL;
+
+            return true;
+        }
+        //else: don't do anything special about the double click
+    }
+
+    return wxStdInputHandler::HandleMouse(consumer, event);
 }
 
 bool wxStdToolbarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
                                                const wxMouseEvent& event)
 {
-    if ( !wxStdButtonInputHandler::HandleMouseMove(consumer, event) )
+    if ( !wxStdInputHandler::HandleMouseMove(consumer, event) )
     {
-        wxToolBarToolBase *tool;
+        wxToolBar *tbar = wxStaticCast(consumer->GetInputWindow(), wxToolBar);
 
+        wxToolBarTool *tool;
         if ( event.Leaving() )
         {
+            // We cannot possibly be over a tool when
+            // leaving the toolbar
             tool = NULL;
         }
         else
         {
-            wxToolBar *tbar = wxStaticCast(consumer->GetInputWindow(), wxToolBar);
-            tool = tbar->FindToolForPosition(event.GetX(), event.GetY());
+            tool = (wxToolBarTool*) tbar->FindToolForPosition( event.GetX(), event.GetY() );
         }
 
-        if ( tool )
-            consumer->PerformAction(wxACTION_TOOLBAR_ENTER, tool->GetId());
+        if (m_toolCapture)
+        {
+            // During capture we only care of the captured tool
+            if (tool && (tool != m_toolCapture))
+                tool = NULL;
+
+            if (tool == m_toolLast)
+                return true;
+
+            if (tool)
+                consumer->PerformAction( wxACTION_BUTTON_PRESS, m_toolCapture->GetId() );
+            else
+                consumer->PerformAction( wxACTION_BUTTON_RELEASE, m_toolCapture->GetId() );
+
+            m_toolLast = tool;
+        }
         else
-            consumer->PerformAction(wxACTION_TOOLBAR_LEAVE);
+        {
+            if (tool == m_toolLast)
+               return true;
 
-        return TRUE;
+            if (m_toolLast)
+            {
+                // Leave old tool if any
+                consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolLast->GetId() );
+            }
+
+            if (tool)
+            {
+                // Enter new tool if any
+                consumer->PerformAction( wxACTION_TOOLBAR_ENTER, tool->GetId() );
+            }
+
+            m_toolLast = tool;
+        }
+
+        return true;
     }
 
-    return FALSE;
+    return false;
 }
 
 bool wxStdToolbarInputHandler::HandleFocus(wxInputConsumer *consumer,
-                                           const wxFocusEvent& event)
+                                           const wxFocusEvent& WXUNUSED(event))
 {
-    // we shouldn't be left with a highlighted button
-    consumer->PerformAction(wxACTION_TOOLBAR_LEAVE);
+    if ( m_toolCapture )
+    {
+        // We shouldn't be left with a highlighted button
+        consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolCapture->GetId() );
+    }
 
-    return TRUE;
+    return true;
 }
 
 bool wxStdToolbarInputHandler::HandleActivation(wxInputConsumer *consumer,
                                                 bool activated)
 {
-    // as above
-    if ( !activated )
-        consumer->PerformAction(wxACTION_TOOLBAR_LEAVE);
+    if (m_toolCapture && !activated)
+    {
+        // We shouldn't be left with a highlighted button
+        consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolCapture->GetId() );
+    }
 
-    return TRUE;
+    return true;
 }
 
+#endif // wxUSE_TOOLBAR
+