]> git.saurik.com Git - wxWidgets.git/commitdiff
[start of] a wxUniversal implementation of wxToolBar
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 27 Feb 2002 21:42:48 +0000 (21:42 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 27 Feb 2002 21:42:48 +0000 (21:42 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14422 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/tbarbase.h
include/wx/univ/inphand.h
include/wx/univ/renderer.h
include/wx/univ/toolbar.h
src/common/tbarbase.cpp
src/univ/themes/gtk.cpp
src/univ/themes/win32.cpp
src/univ/toolbar.cpp

index d57869579bc663dc94675c4490b02af4a0fd39b4..469c4f36a1de3300bec6cabc387e5ee57d29eb1a 100644 (file)
@@ -132,11 +132,13 @@ public:
     bool CanBeToggled() const { return m_isToggle; }
 
     // attributes
-    const wxBitmap& GetBitmap1() const { return m_bitmap1; }
-    const wxBitmap& GetBitmap2() const { return m_bitmap2; }
+    const wxBitmap& GetNormalBitmap() const { return m_bitmap1; }
+    const wxBitmap& GetDisabledBitmap() const { return m_bitmap2; }
 
     const wxBitmap& GetBitmap() const
-        { return IsToggled() ? m_bitmap2 : m_bitmap1; }
+        { return IsEnabled() ? GetNormalBitmap() : GetDisabledBitmap(); }
+
+    wxString GetLabel() const { return m_label; }
 
     wxString GetShortHelp() const { return m_shortHelpString; }
     wxString GetLongHelp() const { return m_longHelpString; }
@@ -162,8 +164,10 @@ public:
 
     void Toggle() { Toggle(!IsToggled()); }
 
-    void SetBitmap1(const wxBitmap& bmp) { m_bitmap1 = bmp; }
-    void SetBitmap2(const wxBitmap& bmp) { m_bitmap2 = bmp; }
+    void SetNormalBitmap(const wxBitmap& bmp) { m_bitmap1 = bmp; }
+    void SetDisabledBitmap(const wxBitmap& bmp) { m_bitmap2 = bmp; }
+
+    void SetLabel(const wxString& label) { m_label = label; }
 
     void SetClientData(wxObject *clientData)
     {
@@ -181,6 +185,15 @@ public:
     virtual void Detach() { m_tbar = (wxToolBarBase *)NULL; }
     virtual void Attach(wxToolBarBase *tbar) { m_tbar = tbar; }
 
+    // compatibility only, don't use
+#if WXWIN_COMPATIBILITY_2_2
+    const wxBitmap& GetBitmap1() const { return GetNormalBitmap(); }
+    const wxBitmap& GetBitmap2() const { return GetDisabledBitmap(); }
+
+    void SetBitmap1(const wxBitmap& bmp) { SetNormalBitmap(bmp); }
+    void SetBitmap2(const wxBitmap& bmp) { SetDisabledBitmap(bmp); }
+#endif // WXWIN_COMPATIBILITY_2_2
+
 protected:
     wxToolBarBase *m_tbar;  // the toolbar to which we belong (may be NULL)
 
@@ -199,10 +212,13 @@ protected:
     bool m_isToggle;
     bool m_enabled;
 
-    // normal and toggles bitmaps
+    // normal and disabled bitmaps
     wxBitmap m_bitmap1;
     wxBitmap m_bitmap2;
 
+    // the button label
+    wxString m_label;
+
     // short and long help strings
     wxString m_shortHelpString;
     wxString m_longHelpString;
@@ -374,6 +390,9 @@ public:
     virtual wxToolBarToolBase *FindToolForPosition(wxCoord x,
                                                    wxCoord y) const = 0;
 
+    // return TRUE if this is a vertical toolbar, otherwise FALSE
+    bool IsVertical() const { return HasFlag(wxTB_VERTICAL); }
+
     // event handlers
     // --------------
 
index ea16294242998124d3efc6a535b6f70d59cb9f73..55c0ac7e975f7adb25c1e8d5c00c07c265ad8147 100644 (file)
@@ -37,6 +37,7 @@
 #define wxINP_HANDLER_SPINBTN           _T("spinbtn")
 #define wxINP_HANDLER_STATUSBAR         _T("statusbar")
 #define wxINP_HANDLER_TEXTCTRL          _T("textctrl")
+#define wxINP_HANDLER_TOOLBAR           _T("toolbar")
 #define wxINP_HANDLER_TOPLEVEL          _T("toplevel")
 
 // ----------------------------------------------------------------------------
index 74043e1b1422a38eadba37f38472dc533d2f48b3..d00bc1c066833e6b3e8324e12a7b13af9a821b44 100644 (file)
@@ -188,6 +188,14 @@ public:
                                  wxAlignment align = wxALIGN_LEFT,
                                  int indexAccel = -1) = 0;
 
+    // draw a toolbar button (label may be empty, bitmap may be invalid, if
+    // both conditions are true this function draws a separator)
+    virtual void DrawToolBarButton(wxDC& dc,
+                                   const wxString& label,
+                                   const wxBitmap& bitmap,
+                                   const wxRect& rect,
+                                   int flags = 0) = 0;
+
     // draw a (part of) line in the text control
     virtual void DrawTextLine(wxDC& dc,
                               const wxString& text,
@@ -356,15 +364,22 @@ public:
     virtual wxSize GetRadioBitmapSize() const = 0;
     virtual wxCoord GetCheckItemMargin() const = 0;
 
+    // get the standard size of a toolbar button and also return the size of
+    // a toolbar separator in the provided pointer
+    virtual wxSize GetToolBarButtonSize(wxCoord *separator) const = 0;
+
+    // get the margins between/around the toolbar buttons
+    virtual wxSize GetToolBarMargin() const = 0;
+
     // convert between text rectangle and client rectangle for text controls:
     // the former is typicall smaller to leave margins around text
     virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
-                                    const wxRect& rectText) = 0;
+                                    const wxRect& rectText) const = 0;
 
     // extra space is for line indicators
     virtual wxRect GetTextClientArea(const wxTextCtrl *text,
                                      const wxRect& rectTotal,
-                                     wxCoord *extraSpaceBeyond) = 0;
+                                     wxCoord *extraSpaceBeyond) const = 0;
 
     // get the overhang of a selected tab
     virtual wxSize GetTabIndent() const = 0;
@@ -591,6 +606,12 @@ public:
                                  int indexAccel = -1)
         { m_renderer->DrawRadioButton(dc, label, bitmap, rect,
                                       flags, align, indexAccel); }
+    virtual void DrawToolBarButton(wxDC& dc,
+                                   const wxString& label,
+                                   const wxBitmap& bitmap,
+                                   const wxRect& rect,
+                                   int flags = 0)
+        { m_renderer->DrawToolBarButton(dc, label, bitmap, rect, flags); }
     virtual void DrawTextLine(wxDC& dc,
                               const wxString& text,
                               const wxRect& rect,
@@ -731,11 +752,17 @@ public:
     virtual wxCoord GetCheckItemMargin() const
         { return m_renderer->GetCheckItemMargin(); }
 
-    virtual wxRect GetTextTotalArea(const wxTextCtrl *text, const wxRect& rect)
+    virtual wxSize GetToolBarButtonSize(wxCoord *separator) const
+        { return m_renderer->GetToolBarButtonSize(separator); }
+    virtual wxSize GetToolBarMargin() const
+        { return m_renderer->GetToolBarMargin(); }
+
+    virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
+                                    const wxRect& rect) const
         { return m_renderer->GetTextTotalArea(text, rect); }
     virtual wxRect GetTextClientArea(const wxTextCtrl *text,
                                      const wxRect& rect,
-                                     wxCoord *extraSpaceBeyond)
+                                     wxCoord *extraSpaceBeyond) const
         { return m_renderer->GetTextClientArea(text, rect, extraSpaceBeyond); }
 
     virtual wxSize GetTabIndent() const { return m_renderer->GetTabIndent(); }
index d797ffa0e1b46f6c16227efc16a0e4839a663576..52d53e606b1770fc67d11357d43276e247a6bf6a 100644 (file)
     #pragma interface "univtoolbar.h"
 #endif
 
-#include "wx/window.h"
+#include "wx/button.h"      // for wxStdButtonInputHandler
+
+class WXDLLEXPORT wxToolBarTool;
 
 // ----------------------------------------------------------------------------
-// wxToolbar
+// the actions supported by this control
 // ----------------------------------------------------------------------------
 
-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 )
-    {
-        m_isDown = FALSE;
-        m_x = -1;
-        m_y = -1;
-    }
+#define wxACTION_TOOLBAR_TOGGLE  wxACTION_BUTTON_TOGGLE
+#define wxACTION_TOOLBAR_PRESS   wxACTION_BUTTON_PRESS
+#define wxACTION_TOOLBAR_RELEASE wxACTION_BUTTON_RELEASE
+#define wxACTION_TOOLBAR_CLICK   wxACTION_BUTTON_CLICK
+#define wxACTION_TOOLBAR_ENTER   _T("enter")     // highlight the tool
+#define wxACTION_TOOLBAR_LEAVE   _T("leave")     // unhighlight the tool
 
-public:
-    bool        m_isDown;
-    int         m_x;
-    int         m_y;
-};
+// ----------------------------------------------------------------------------
+// wxToolBar
+// ----------------------------------------------------------------------------
 
-class WXDLLEXPORT wxToolBar: public wxToolBarBase
+class WXDLLEXPORT wxToolBar : public wxToolBarBase
 {    
 public:
     // construction/destruction
     wxToolBar() { Init(); }
-    wxToolBar( wxWindow *parent,
-               wxWindowID id,
-               const wxPoint& pos = wxDefaultPosition,
-               const wxSize& size = wxDefaultSize,
-               long style = 0,
-               const wxString& name = wxToolBarNameStr )
+    wxToolBar(wxWindow *parent,
+              wxWindowID id,
+              const wxPoint& pos = wxDefaultPosition,
+              const wxSize& size = wxDefaultSize,
+              long style = 0,
+              const wxString& name = wxToolBarNameStr)
     {
         Init();
 
@@ -71,9 +59,7 @@ public:
                  long style = 0,
                  const wxString& name = wxToolBarNameStr );
                  
-#ifdef __DARWIN__
-    virtual ~wxToolBar() { }
-#endif
+    virtual ~wxToolBar();
 
     virtual bool Realize();
 
@@ -102,21 +88,72 @@ protected:
                                           const wxString& longHelpString);
     virtual wxToolBarToolBase *CreateTool(wxControl *control);
 
-private:
-    wxToolBarTool    *m_captured;
-    wxToolBarTool    *m_underMouse;
-    wxCoord           m_maxWidth, m_maxHeight;
+    // implement wxUniversal methods
+    virtual bool PerformAction(const wxControlAction& action,
+                               long numArg = -1,
+                               const wxString& strArg = wxEmptyString);
+    virtual wxSize DoGetBestClientSize() const;
+    virtual void DoDraw(wxControlRenderer *renderer);
+
+    // get the bounding rect for the given tool
+    wxRect GetToolRect(wxToolBarToolBase *tool) const;
+
+    // redraw the given tool
+    void RefreshTool(wxToolBarToolBase *tool);
+
+    // (re)calculate the tool positions, should only be called if it is
+    // necessary to do it, i.e. m_needsLayout == TRUE
+    void DoLayout();
     
-private:
-    void OnMouse( wxMouseEvent &event );
-    void OnEnter( wxMouseEvent &event );
-    void OnLeave( wxMouseEvent &event );
-    void RefreshTool( wxToolBarTool *tool );
-    void DrawToolBarTool( wxToolBarTool *tool, wxDC &dc, bool down );
-    void OnPaint( wxPaintEvent &event );
+    // get the rect limits depending on the orientation: top/bottom for a
+    // vertical toolbar, left/right for a horizontal one
+    void GetRectLimits(const wxRect& rect, wxCoord *start, wxCoord *end) const;
+
+    // wxButton actions: all these use m_toolPressed and can only be called if
+    // we have one
+    void Toggle();
+    void Press();
+    void Release();
+
+    // this one used m_toolCurrent
+    void Click();
 
 private:
-    DECLARE_EVENT_TABLE()
+    // have we calculated the positions of our tools?
+    bool m_needsLayout;
+
+    // the width of a separator
+    wxCoord m_widthSeparator;
+
+    // the total size of all toolbar elements
+    wxCoord m_maxWidth,
+            m_maxHeight;
+    
+    // the current tool or NULL
+    wxToolBarToolBase *m_toolCurrent;
+
+    // the currently pressed tool or NULL
+    wxToolBarToolBase *m_toolPressed;
+
+    DECLARE_DYNAMIC_CLASS(wxToolBar)
+};
+
+// ----------------------------------------------------------------------------
+// wxStdToolbarInputHandler: translates SPACE and ENTER keys and the left mouse
+// click into button press/release actions
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxStdToolbarInputHandler : public wxStdButtonInputHandler
+{
+public:
+    wxStdToolbarInputHandler(wxInputHandler *inphand);
+
+    virtual bool HandleKey(wxInputConsumer *consumer,
+                           const wxKeyEvent& event,
+                           bool pressed);
+    virtual bool HandleMouseMove(wxInputConsumer *consumer, const wxMouseEvent& event);
+    virtual bool HandleFocus(wxInputConsumer *consumer, const wxFocusEvent& event);
+    virtual bool HandleActivation(wxInputConsumer *consumer, bool activated);
 };
 
 #endif // _WX_UNIV_TOOLBAR_H_
index f0f946c192ea54325325d178620674bfdd43321b..2a66297a2b0e06979e0b3e8926a0bc51d722d3a6 100644 (file)
 #include "wx/image.h"
 #include "wx/settings.h"
 
-// For ::UpdateWindow
-#ifdef __WXMSW__
-#include <windows.h>
-#endif
-
 #include "wx/tbarbase.h"
 
 // ----------------------------------------------------------------------------
@@ -79,7 +74,9 @@ bool wxToolBarToolBase::Enable(bool enable)
 
 bool wxToolBarToolBase::Toggle(bool toggle)
 {
-    wxASSERT_MSG( m_isToggle, _T("can't toggle this tool") );
+    // wxUniv toolbar toggles even non-checkable tools temporarily - should we
+    // change the code there or just allow doing it?
+    //wxASSERT_MSG( m_isToggle, _T("can't toggle this tool") );
 
     if ( m_toggled == toggle )
         return FALSE;
index 392160d221c4a9c9507e13bd4c8aecf9659cd856..6bacb6303d838448a411b80282c7ddd82e61cc4b 100644 (file)
@@ -39,6 +39,7 @@
     #include "wx/scrolbar.h"
     #include "wx/slider.h"
     #include "wx/textctrl.h"
+    #include "wx/toolbar.h"
 #endif // WX_PRECOMP
 
 #include "wx/notebook.h"
@@ -152,6 +153,12 @@ public:
                                  wxAlignment align = wxALIGN_LEFT,
                                  int indexAccel = -1);
 
+    virtual void DrawToolBarButton(wxDC& dc,
+                                   const wxString& label,
+                                   const wxBitmap& bitmap,
+                                   const wxRect& rect,
+                                   int flags);
+
     virtual void DrawTextLine(wxDC& dc,
                               const wxString& text,
                               const wxRect& rect,
@@ -275,11 +282,16 @@ public:
     virtual wxCoord GetCheckItemMargin() const
         { return 2; }
 
+    virtual wxSize GetToolBarButtonSize(wxCoord *separator) const
+        { if ( separator ) *separator = 5; return wxSize(16, 15); }
+    virtual wxSize GetToolBarMargin() const
+        { return wxSize(6, 6); }
+
     virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
-                                    const wxRect& rect);
+                                    const wxRect& rect) const;
     virtual wxRect GetTextClientArea(const wxTextCtrl *text,
                                      const wxRect& rect,
-                                     wxCoord *extraSpaceBeyond);
+                                     wxCoord *extraSpaceBeyond) const;
 
     virtual wxSize GetTabIndent() const { return wxSize(2, 2); }
     virtual wxSize GetTabPadding() const { return wxSize(6, 6); }
@@ -385,7 +397,7 @@ protected:
     }
 
     // get the line wrap indicator bitmap
-    wxBitmap GetLineWrapBitmap();
+    wxBitmap GetLineWrapBitmap() const;
 
     // DrawCheckBitmap and DrawRadioBitmap helpers
 
@@ -678,6 +690,10 @@ wxInputHandler *wxGTKTheme::GetInputHandler(const wxString& control)
         else if ( control == wxINP_HANDLER_NOTEBOOK )
             handler = new wxStdNotebookInputHandler(GetDefaultInputHandler());
 #endif // wxUSE_NOTEBOOK
+#if wxUSE_TOOLBAR
+        else if ( control == wxINP_HANDLER_TOOLBAR )
+            handler = new wxStdToolbarInputHandler(GetDefaultInputHandler());
+#endif // wxUSE_TOOLBAR
         else if ( control == wxINP_HANDLER_TOPLEVEL )
             handler = new wxStdFrameInputHandler(GetDefaultInputHandler());
         else
@@ -1424,7 +1440,7 @@ wxBitmap wxGTKRenderer::GetCheckBitmap(int flags)
     return m_bitmapsCheckbox[row][col];
 }
 
-wxBitmap wxGTKRenderer::GetLineWrapBitmap()
+wxBitmap wxGTKRenderer::GetLineWrapBitmap() const
 {
     if ( !m_bmpLineWrap.Ok() )
     {
@@ -1443,7 +1459,7 @@ wxBitmap wxGTKRenderer::GetLineWrapBitmap()
         }
         else
         {
-            m_bmpLineWrap = bmpLineWrap;
+            wxConstCast(this, wxGTKRenderer)->m_bmpLineWrap = bmpLineWrap;
         }
     }
 
@@ -1552,12 +1568,37 @@ void wxGTKRenderer::DrawRadioButton(wxDC& dc,
                              flags, align, indexAccel);
 }
 
+void wxGTKRenderer::DrawToolBarButton(wxDC& dc,
+                                      const wxString& label,
+                                      const wxBitmap& bitmap,
+                                      const wxRect& rectOrig,
+                                      int flags)
+{
+    // we don't draw the separators at all
+    if ( !label.empty() || bitmap.Ok() )
+    {
+        wxRect rect = rectOrig;
+        rect.Deflate(BORDER_THICKNESS);
+
+        if ( flags & wxCONTROL_PRESSED )
+        {
+            DrawBorder(dc, wxBORDER_SUNKEN, rect, flags);
+        }
+        else if ( flags & wxCONTROL_CURRENT )
+        {
+            DrawBorder(dc, wxBORDER_RAISED, rect, flags);
+        }
+
+        dc.DrawLabel(label, bitmap, rect, wxALIGN_CENTRE);
+    }
+}
+
 // ----------------------------------------------------------------------------
 // text control
 // ----------------------------------------------------------------------------
 
 wxRect wxGTKRenderer::GetTextTotalArea(const wxTextCtrl *text,
-                                       const wxRect& rect)
+                                       const wxRect& rect) const
 {
     wxRect rectTotal = rect;
     rectTotal.Inflate(2*BORDER_THICKNESS);
@@ -1566,7 +1607,7 @@ wxRect wxGTKRenderer::GetTextTotalArea(const wxTextCtrl *text,
 
 wxRect wxGTKRenderer::GetTextClientArea(const wxTextCtrl *text,
                                         const wxRect& rect,
-                                        wxCoord *extraSpaceBeyond)
+                                        wxCoord *extraSpaceBeyond) const
 {
     wxRect rectText = rect;
     rectText.Deflate(2*BORDER_THICKNESS);
index 4142f5940fae2867e15f6ecc487d3f52d24701c3..8352e502e8c0974d57bb51a6280a4e0a56e52b34 100644 (file)
@@ -38,6 +38,7 @@
     #include "wx/scrolbar.h"
     #include "wx/slider.h"
     #include "wx/textctrl.h"
+    #include "wx/toolbar.h"
 
     #ifdef __WXMSW__
         // for COLOR_* constants
@@ -228,6 +229,11 @@ public:
                                  int flags = 0,
                                  wxAlignment align = wxALIGN_LEFT,
                                  int indexAccel = -1);
+    virtual void DrawToolBarButton(wxDC& dc,
+                                   const wxString& label,
+                                   const wxBitmap& bitmap,
+                                   const wxRect& rect,
+                                   int flags);
     virtual void DrawTextLine(wxDC& dc,
                               const wxString& text,
                               const wxRect& rect,
@@ -346,11 +352,16 @@ public:
     virtual wxCoord GetCheckItemMargin() const
         { return 0; }
 
+    virtual wxSize GetToolBarButtonSize(wxCoord *separator) const
+        { if ( separator ) *separator = 5; return wxSize(16, 15); }
+    virtual wxSize GetToolBarMargin() const
+        { return wxSize(6, 6); }
+
     virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
-                                    const wxRect& rect);
+                                    const wxRect& rect) const;
     virtual wxRect GetTextClientArea(const wxTextCtrl *text,
                                      const wxRect& rect,
-                                     wxCoord *extraSpaceBeyond);
+                                     wxCoord *extraSpaceBeyond) const;
 
     virtual wxSize GetTabIndent() const { return wxSize(2, 2); }
     virtual wxSize GetTabPadding() const { return wxSize(6, 5); }
@@ -1226,6 +1237,10 @@ wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control)
         else if ( control == wxINP_HANDLER_STATUSBAR )
             handler = new wxWin32StatusBarInputHandler(GetDefaultInputHandler());
 #endif // wxUSE_STATUSBAR
+#if wxUSE_TOOLBAR
+        else if ( control == wxINP_HANDLER_TOOLBAR )
+            handler = new wxStdToolbarInputHandler(GetDefaultInputHandler());
+#endif // wxUSE_TOOLBAR
         else if ( control == wxINP_HANDLER_TOPLEVEL )
             handler = new wxWin32FrameInputHandler(GetDefaultInputHandler());
         else
@@ -2332,6 +2347,34 @@ void wxWin32Renderer::DrawCheckButton(wxDC& dc,
                            0); // no focus rect offset for checkboxes
 }
 
+void wxWin32Renderer::DrawToolBarButton(wxDC& dc,
+                                        const wxString& label,
+                                        const wxBitmap& bitmap,
+                                        const wxRect& rectOrig,
+                                        int flags)
+{
+    if ( !label.empty() || bitmap.Ok() )
+    {
+        wxRect rect = rectOrig;
+        rect.Deflate(BORDER_THICKNESS);
+
+        if ( flags & wxCONTROL_PRESSED )
+        {
+            DrawBorder(dc, wxBORDER_SUNKEN, rect, flags);
+        }
+        else if ( flags & wxCONTROL_CURRENT )
+        {
+            DrawBorder(dc, wxBORDER_RAISED, rect, flags);
+        }
+
+        dc.DrawLabel(label, bitmap, rect, wxALIGN_CENTRE);
+    }
+    else // a separator
+    {
+        // TODO
+    }
+}
+
 // ----------------------------------------------------------------------------
 // text control
 // ----------------------------------------------------------------------------
@@ -3829,7 +3872,7 @@ static inline int GetTextBorderWidth()
 }
 
 wxRect wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text,
-                                         const wxRect& rect)
+                                         const wxRect& rect) const
 {
     wxRect rectTotal = rect;
 
@@ -3844,7 +3887,7 @@ wxRect wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text,
 
 wxRect wxWin32Renderer::GetTextClientArea(const wxTextCtrl *text,
                                           const wxRect& rect,
-                                          wxCoord *extraSpaceBeyond)
+                                          wxCoord *extraSpaceBeyond) const
 {
     wxRect rectText = rect;
 
index 47758d569d54a5fb7bccd1c549e7a23437597c82..6692e1fbff018f62c30bbdcf44c9b8d3cc63e0b0 100644 (file)
@@ -1,8 +1,12 @@
 /////////////////////////////////////////////////////////////////////////////
 // Name:        src/univ/toolbar.cpp
-// Author:      Robert Roebling
+// Purpose:     implementation of wxToolBar for wxUniversal
+// Author:      Robert Roebling, Vadim Zeitlin (universalization)
+// Modified by:
+// Created:     20.02.02
 // Id:          $Id$
-// Copyright:   (c) 2001 Robert Roebling
+// Copyright:   (c) 2001 Robert Roebling,
+//              (c) 2002 SciTech Software, Inc. (www.scitechsoft.com)
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 #ifndef WX_PRECOMP
     #include "wx/utils.h"
     #include "wx/app.h"
+
+    #include "wx/univ/renderer.h"
 #endif
 
 #include "wx/toolbar.h"
 #include "wx/image.h"
 
-//-----------------------------------------------------------------------------
-// wxToolBar
-//-----------------------------------------------------------------------------
-
-BEGIN_EVENT_TABLE(wxToolBar,wxToolBarBase)
-    EVT_MOUSE_EVENTS( wxToolBar::OnMouse )
-    EVT_PAINT( wxToolBar::OnPaint )
-    EVT_SIZE( wxToolBar::OnSize )
-    EVT_ENTER_WINDOW( wxToolBar::OnEnter )
-    EVT_LEAVE_WINDOW( wxToolBar::OnLeave )
-END_EVENT_TABLE()
-
-bool wxToolBar::Create( wxWindow *parent, wxWindowID id,
-                 const wxPoint& pos, const wxSize& size,
-                 long style, const wxString& name )
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// value meaning that m_widthSeparator is not initialized
+static const wxCoord INVALID_WIDTH = -1;
+
+// ----------------------------------------------------------------------------
+// wxToolBarTool: our implementation of wxToolBarToolBase
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxToolBarTool : public wxToolBarToolBase
 {
-    bool ret = wxToolBarBase::Create( parent, id, pos, size, style, wxDefaultValidator, name );
-    
-    return ret;
-}
+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)
+    {
+        // no position yet
+        m_x =
+        m_y = -1;
+    }
+
+public:
+    // the tool position (the size is known by the toolbar itself)
+    int m_x,
+        m_y;
+};
+
+// ============================================================================
+// wxToolBar implementation
+// ============================================================================
+
+IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl);
+
+// ----------------------------------------------------------------------------
+// wxToolBar creation
+// ----------------------------------------------------------------------------
 
 void wxToolBar::Init()
 {
-    // TODO: this is from tbarbase.cpp, but should be in
-    // wxToolbarBase::Init
-    // the list owns the pointers
-    m_tools.DeleteContents(TRUE);
-    m_xMargin = m_yMargin = 0;
-    m_maxRows = m_maxCols = 0;
-    // End TODO
-
-    m_maxWidth = 0;
+    // no tools yet
+    m_needsLayout = FALSE;
+
+    // unknown widths for the tools and separators
+    m_widthSeparator = INVALID_WIDTH;
+
+    m_maxWidth =
     m_maxHeight = 0;
 
-    m_captured = NULL;
-    m_underMouse = NULL;
-    
-    SetToolBitmapSize( wxSize(16,15) );
+    m_toolPressed =
+    m_toolCurrent = NULL;
+
+    wxRenderer *renderer = GetRenderer();
+
+    SetToolBitmapSize(renderer->GetToolBarButtonSize(&m_widthSeparator));
+    SetMargins(renderer->GetToolBarMargin());
 }
 
+bool wxToolBar::Create(wxWindow *parent,
+                       wxWindowID id,
+                       const wxPoint& pos,
+                       const wxSize& size,
+                       long style,
+                       const wxString& name)
+{
+    if ( !wxToolBarBase::Create(parent, id, pos, size, style,
+                                wxDefaultValidator, name) )
+    {
+        return FALSE;
+    }
+
+    CreateInputHandler(wxINP_HANDLER_TOOLBAR);
+
+    SetBestSize(size);
+
+    return TRUE;
+}
+
+wxToolBar::~wxToolBar()
+{
+}
+
+// ----------------------------------------------------------------------------
+// wxToolBar tool-related methods
+// ----------------------------------------------------------------------------
+
 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
 {
+    // check the "other" direction first: it must be inside the toolbar or we
+    // don't risk finding anything
+    if ( IsVertical() )
+    {
+        if ( x < 0 || x > m_maxWidth )
+            return NULL;
+
+        // we always use x, even for a vertical toolbar, this makes the code
+        // below simpler
+        x = y;
+    }
+    else // horizontal
+    {
+        if ( y < 0 || y > m_maxHeight )
+            return NULL;
+    }
+
+    for ( wxToolBarToolsList::Node *node = m_tools.GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        wxToolBarToolBase *tool =  node->GetData();
+        wxRect rectTool = GetToolRect(tool);
+
+        wxCoord startTool, endTool;
+        GetRectLimits(rectTool, &startTool, &endTool);
+
+        if ( x >= startTool && x <= endTool )
+        {
+            // don't return the separators from here, they don't accept any
+            // input anyhow
+            return tool->IsSeparator() ? NULL : tool;
+        }
+    }
+
     return NULL;
 }
 
-void wxToolBar::SetToolShortHelp(int id, const wxString& helpString)
+void wxToolBar::SetToolShortHelp(int id, const wxString& help)
 {
+    wxToolBarToolBase *tool = FindById(id);
+
+    wxCHECK_RET( tool, _T("SetToolShortHelp: no such tool") );
+
+    tool->SetShortHelp(help);
 }
 
-bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *tool)
+bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
+                             wxToolBarToolBase * WXUNUSED(tool))
 {
+    // recalculate the toolbar geometry before redrawing it the next time
+    m_needsLayout = TRUE;
+
+    // and ensure that we indeed are going to redraw
+    Refresh();
+
     return TRUE;
 }
 
-bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool)
+bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos),
+                             wxToolBarToolBase * WXUNUSED(tool))
 {
+    // as above
+    m_needsLayout = TRUE;
+
+    Refresh();
+
     return TRUE;
 }
 
 void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
 {
-    // Comment this out if you don't want the disabled look,
-    // which currently acts weirdly for the scissors icon
-    // in the toolbar sample. See src/common/tbarbase.cpp
-    // for the wxCreateGreyedImage function.
-#if 1
-    // Created disabled-state bitmap on demand
-    if (!enable && !tool->GetBitmap2().Ok())
+    // created disabled-state bitmap on demand
+    if ( !enable && !tool->GetDisabledBitmap().Ok() )
     {
-        wxImage image( tool->GetBitmap1() );
+        wxImage image( tool->GetNormalBitmap() );
 
+        // TODO: don't hardcode 180
         unsigned char bg_red = 180;
         unsigned char bg_green = 180;
         unsigned char bg_blue = 180;
-        
+
         unsigned char mask_red = image.GetMaskRed();
         unsigned char mask_green = image.GetMaskGreen();
         unsigned char mask_blue = image.GetMaskBlue();
-        
+
         bool has_mask = image.HasMask();
-        
+
         int x,y;
         for (y = 0; y < image.GetHeight(); y++)
         {
-            for (x = 0; x < image.GetWidth(); x++) 
+            for (x = 0; x < image.GetWidth(); x++)
             {
                 unsigned char red = image.GetRed(x,y);
                 unsigned char green = image.GetGreen(x,y);
@@ -127,14 +236,14 @@ void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
                     red = (((wxInt32) red  - bg_red) >> 1) + bg_red;
                     green = (((wxInt32) green  - bg_green) >> 1) + bg_green;
                     blue = (((wxInt32) blue  - bg_blue) >> 1) + bg_blue;
-                    image.SetRGB( x, y, red, green, blue );                
+                    image.SetRGB( x, y, red, green, blue );
                 }
             }
         }
 
         for (y = 0; y < image.GetHeight(); y++)
         {
-            for (x = y % 2; x < image.GetWidth(); x += 2) 
+            for (x = y % 2; x < image.GetWidth(); x += 2)
             {
                 unsigned char red = image.GetRed(x,y);
                 unsigned char green = image.GetGreen(x,y);
@@ -149,304 +258,404 @@ void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
             }
         }
 
-        tool->SetBitmap2( image.ConvertToBitmap() );
+        tool->SetDisabledBitmap( image.ConvertToBitmap() );
     }
-    
-    RefreshTool((wxToolBarTool*) tool);
-#endif
+
+    RefreshTool(tool);
 }
 
-void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool toggle)
+void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
 {
-    wxToolBarTool *my_tool = (wxToolBarTool*) tool;
-    
-    bool refresh = (my_tool->IsToggled() != toggle);
-    
-    my_tool->m_isDown = toggle;
-    
-    if (refresh)
-        RefreshTool( my_tool );
+    // note that if we're called the tool did change state (the base class
+    // checks for it), so it's not necessary to check for this again here
+    RefreshTool(tool);
 }
 
-void wxToolBar::DoSetToggle(wxToolBarToolBase *tool, bool toggle)
+void wxToolBar::DoSetToggle(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
 {
+    RefreshTool(tool);
 }
 
 wxToolBarToolBase *wxToolBar::CreateTool(int id,
-                                          const wxBitmap& bitmap1,
-                                          const wxBitmap& bitmap2,
-                                          bool toggle,
-                                          wxObject *clientData,
-                                          const wxString& shortHelpString,
-                                          const wxString& longHelpString)
+                                         const wxBitmap& bitmap1,
+                                         const wxBitmap& bitmap2,
+                                         bool toggle,
+                                         wxObject *clientData,
+                                         const wxString& shortHelpString,
+                                         const wxString& longHelpString)
 {
     return new wxToolBarTool( this, id, bitmap1, bitmap2, toggle,
                               clientData, shortHelpString, longHelpString);
 }
-                                          
+
 wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
 {
-    wxFAIL_MSG( wxT("Toolbar doesn't support controls yet.") );
-    
+    wxFAIL_MSG( wxT("Toolbar doesn't support controls yet (TODO)") );
+
     return NULL;
 }
 
-void wxToolBar::RefreshTool( wxToolBarTool *tool )
-{
-    wxRect rect( tool->m_x, tool->m_y, m_defaultWidth+6, m_defaultHeight+6 );
-    Refresh( TRUE, &rect );
-}
+// ----------------------------------------------------------------------------
+// wxToolBar geometry
+// ----------------------------------------------------------------------------
 
-void wxToolBar::DrawToolBarTool( wxToolBarTool *tool, wxDC &dc, bool down )
+wxRect wxToolBar::GetToolRect(wxToolBarToolBase *toolBase) const
 {
-    const wxBitmap& bitmap = (tool->IsEnabled() || !tool->GetBitmap2().Ok()) ? tool->GetBitmap1() : tool->GetBitmap2() ;
-    
-    if (HasFlag(wxTB_FLAT) && (tool != m_underMouse))
+    const wxToolBarTool *tool = (wxToolBarTool *)toolBase;
+
+    wxRect rect;
+
+    wxCHECK_MSG( tool, rect, _T("GetToolRect: NULL tool") );
+
+    // ensure that we always have the valid tool position
+    if ( m_needsLayout )
     {
-        if (down)
-            dc.DrawBitmap( bitmap, tool->m_x+4, tool->m_y+4, TRUE );
-        else
-            dc.DrawBitmap( bitmap, tool->m_x+3, tool->m_y+3, TRUE );
-            
-        return;
+        wxConstCast(this, wxToolBar)->DoLayout();
     }
-    
-    if (down)
+
+    rect.x = tool->m_x - m_xMargin;
+    rect.y = tool->m_y - m_yMargin;
+
+    if ( IsVertical() )
     {
-        dc.DrawBitmap( bitmap, tool->m_x+4, tool->m_y+4, TRUE );
-        
-        dc.SetPen( *wxGREY_PEN );
-        dc.DrawLine( tool->m_x, tool->m_y, tool->m_x+m_defaultWidth+5, tool->m_y );
-        dc.DrawLine( tool->m_x, tool->m_y, tool->m_x, tool->m_y+m_defaultHeight+5 );
-        
-        dc.SetPen( *wxBLACK_PEN );
-        dc.DrawLine( tool->m_x+1, tool->m_y+1, tool->m_x+m_defaultWidth+4, tool->m_y+1 );
-        dc.DrawLine( tool->m_x+1, tool->m_y+1, tool->m_x+1, tool->m_y+m_defaultHeight+4 );
-        
-        dc.SetPen( *wxWHITE_PEN );
-        dc.DrawLine( tool->m_x, tool->m_y+m_defaultHeight+5, tool->m_x+m_defaultWidth+6, tool->m_y+m_defaultHeight+5 );
-        dc.DrawLine( tool->m_x+m_defaultWidth+5, tool->m_y, tool->m_x+m_defaultWidth+5, tool->m_y+m_defaultHeight+6 );
+        rect.width = m_defaultWidth;
+        rect.height = tool->IsSeparator() ? m_widthSeparator : m_defaultHeight;
     }
-    else
+    else // horizontal
     {
-        dc.DrawBitmap( bitmap, tool->m_x+3, tool->m_y+3, TRUE );
-        
-        dc.SetPen( *wxWHITE_PEN );
-        dc.DrawLine( tool->m_x, tool->m_y, tool->m_x+m_defaultWidth+5, tool->m_y );
-        dc.DrawLine( tool->m_x, tool->m_y, tool->m_x, tool->m_y+m_defaultHeight+5 );
-        dc.DrawLine( tool->m_x+m_defaultWidth+4, tool->m_y, tool->m_x+m_defaultWidth+4, tool->m_y+2 );
-        dc.DrawLine( tool->m_x, tool->m_y+m_defaultHeight+4, tool->m_x+2, tool->m_y+m_defaultHeight+4 );
-        
-        dc.SetPen( *wxBLACK_PEN );
-        dc.DrawLine( tool->m_x, tool->m_y+m_defaultHeight+5, tool->m_x+m_defaultWidth+6, tool->m_y+m_defaultHeight+5 );
-        dc.DrawLine( tool->m_x+m_defaultWidth+5, tool->m_y, tool->m_x+m_defaultWidth+5, tool->m_y+m_defaultHeight+6 );
-        
-        dc.SetPen( *wxGREY_PEN );
-        dc.DrawLine( tool->m_x+1, tool->m_y+m_defaultHeight+4, tool->m_x+m_defaultWidth+5, tool->m_y+m_defaultHeight+4 );
-        dc.DrawLine( tool->m_x+m_defaultWidth+4, tool->m_y+1, tool->m_x+m_defaultWidth+4, tool->m_y+m_defaultHeight+5 );
+        rect.width = tool->IsSeparator() ? m_widthSeparator : m_defaultWidth;
+        rect.height = m_defaultHeight;
     }
+
+    rect.width += 2*m_xMargin;
+    rect.height += 2*m_yMargin;
+
+    return rect;
 }
 
-void wxToolBar::OnPaint(wxPaintEvent &event)
+bool wxToolBar::Realize()
 {
-    wxPaintDC dc(this);
-    
-    wxSize clientSize = GetClientSize();
-    dc.SetPen( *wxBLACK_PEN );
-    dc.DrawLine( 0,0, clientSize.x,0 );
-    
+    if ( !wxToolBarBase::Realize() )
+        return FALSE;
+
+    m_needsLayout = TRUE;
+    DoLayout();
+
+    SetBestSize(wxDefaultSize);
+
+    return TRUE;
+}
+
+void wxToolBar::DoLayout()
+{
+    wxASSERT_MSG( m_needsLayout, _T("why are we called?") );
+
+    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;
+
+    // calculate the positions of all elements
     for ( wxToolBarToolsList::Node *node = m_tools.GetFirst();
           node;
           node = node->GetNext() )
     {
-        wxToolBarTool *tool = (wxToolBarTool*) node->Data();
-        
-        if (tool->GetId() == -1) continue;
-        
-        DrawToolBarTool( tool, dc, tool->m_isDown );
+        wxToolBarTool *tool = (wxToolBarTool *) node->GetData();
+
+        tool->m_x = x;
+        tool->m_y = y;
+
+        *pCur += (tool->IsSeparator() ? m_widthSeparator : widthTool) + margin;
     }
+
+    // calculate the total toolbar size
+    wxCoord xMin = m_defaultWidth + 2*m_xMargin,
+            yMin = m_defaultHeight + 2*m_yMargin;
+
+    m_maxWidth = x < xMin ? xMin : x;
+    m_maxHeight = y < yMin ? yMin : y;
 }
 
-bool wxToolBar::Realize()
+wxSize wxToolBar::DoGetBestClientSize() const
 {
-    if (!wxToolBarBase::Realize())
-        return FALSE;
+    return wxSize(m_maxWidth, m_maxHeight);
+}
+
+// ----------------------------------------------------------------------------
+// wxToolBar drawing
+// ----------------------------------------------------------------------------
 
-    int x;
-    int y;
-    
-    if (GetWindowStyleFlag() & wxTB_VERTICAL)
+void wxToolBar::RefreshTool(wxToolBarToolBase *tool)
+{
+    RefreshRect(GetToolRect(tool));
+}
+
+void wxToolBar::GetRectLimits(const wxRect& rect,
+                              wxCoord *start,
+                              wxCoord *end) const
+{
+    wxCHECK_RET( start && end, _T("NULL pointer in GetRectLimits") );
+
+    if ( IsVertical() )
     {
-        m_xMargin += 1;   // Cannot help it, but otherwise it look ugly
-        
-        x = m_xMargin;
-        y = 5;
+        *start = rect.GetTop();
+        *end = rect.GetBottom();
     }
-    else
+    else // horizontal
     {
-        m_yMargin += 1;   // Cannot help it, but otherwise it look ugly
-        
-        y = m_yMargin;
-        x = 5;
+        *start = rect.GetLeft();
+        *end = rect.GetRight();
     }
+}
 
+void wxToolBar::DoDraw(wxControlRenderer *renderer)
+{
+    // prepare the variables used below
+    wxDC& dc = renderer->GetDC();
+    wxRenderer *rend = renderer->GetRenderer();
+    // dc.SetFont(GetFont()); -- uncomment when we support labels
+
+    // draw the border separating us from the menubar (if there is no menubar
+    // we probably shouldn't draw it?)
+    if ( !IsVertical() )
+    {
+        rend->DrawHorizontalLine(dc, 0, 0, GetClientSize().x);
+    }
+
+    // get the update rect and its limits depending on the orientation
+    wxRect rectUpdate = GetUpdateClientRect();
+    wxCoord start, end;
+    GetRectLimits(rectUpdate, &start, &end);
+
+    // and redraw all the tools intersecting it
     for ( wxToolBarToolsList::Node *node = m_tools.GetFirst();
           node;
           node = node->GetNext() )
     {
-        wxToolBarTool *tool = (wxToolBarTool*) node->Data();
-        
-        if (GetWindowStyleFlag() & wxTB_VERTICAL)
+        wxToolBarToolBase *tool = node->GetData();
+        wxRect rectTool = GetToolRect(tool);
+        wxCoord startTool, endTool;
+        GetRectLimits(rectTool, &startTool, &endTool);
+
+        if ( endTool < start )
         {
-            if (tool->GetId() == -1)
-            {
-                y += 6;
-                continue;
-            }
-            tool->m_x = m_xMargin;
-            tool->m_y = y;
-            y += m_defaultHeight + 6;
-
-            // Calculate the maximum height or width (depending on style)
-            // so we know how to size the toolbar in Realize.
-            // We could get the size of the tool instead of the
-            // default bitmap size
-            if (m_maxWidth < (m_defaultWidth + 2*(m_xMargin + 2)))
-                m_maxWidth = (m_defaultWidth + 2*(m_xMargin + 2)) ;
+            // we're still to the left of the area to redraw
+            continue;
         }
-        else
+
+        if ( startTool > end )
         {
-            if (tool->GetId() == -1)
-            {
-                x += 6;
-                continue;
-            }
-            tool->m_x = x;
-            tool->m_y = m_yMargin;
-            x += m_defaultWidth + 6;
-
-            // Calculate the maximum height or width (depending on style)
-            // so we know how to size the toolbar in Realize.
-            // We could get the size of the tool instead of the
-            // default bitmap size
-            if (m_maxHeight < (m_defaultHeight + 2*(m_yMargin + 2)))
-                m_maxHeight = (m_defaultHeight + 2*(m_yMargin + 2)) ;
+            // we're beyond the area to redraw, nothing left to do
+            break;
+        }
+
+        // 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) )
+                flags |= wxCONTROL_CURRENT;
+        }
+        else // disabled tool
+        {
+            flags |= wxCONTROL_DISABLED;
         }
-        
+
+        if ( tool->IsToggled() )
+            flags |= wxCONTROL_PRESSED;
+
+        wxString label;
+        wxBitmap bitmap;
+        if ( !tool->IsSeparator() )
+        {
+            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);
     }
+}
 
-    wxSize sz = GetSize();
-    if (GetWindowStyleFlag() & wxTB_VERTICAL)
+// ----------------------------------------------------------------------------
+// wxToolBar actions
+// ----------------------------------------------------------------------------
+
+void wxToolBar::Press()
+{
+    wxCHECK_RET( m_toolCurrent, _T("no tool to press?") );
+
+    m_toolPressed = m_toolCurrent;
+    if ( !m_toolPressed->IsToggled() )
     {
-        SetSize(m_maxWidth, sz.y);
+        m_toolPressed->Toggle(TRUE);
+
+        RefreshTool(m_toolPressed);
     }
-    else
+}
+
+void wxToolBar::Release()
+{
+    wxCHECK_RET( m_toolPressed, _T("no tool to release?") );
+
+    if ( m_toolPressed->IsToggled() )
     {
-        SetSize(sz.x, m_maxHeight);
-    }
+        m_toolPressed->Toggle(FALSE);
 
-    return TRUE;
+        RefreshTool(m_toolPressed);
+
+        m_toolPressed = NULL;
+    }
 }
 
-void wxToolBar::OnLeave(wxMouseEvent &event)
+void wxToolBar::Toggle()
 {
-    if (HasFlag( wxTB_FLAT ))
+    wxCHECK_RET( m_toolPressed, _T("no tool to toggle?") );
+
+    // the togglable tools should keep their state when the mouse is released
+    if ( !m_toolPressed->CanBeToggled() )
     {
-        wxToolBarTool *oldMouseUnder = m_underMouse;
-        if (m_underMouse)
-        {
-            m_underMouse = NULL;
-            RefreshTool( oldMouseUnder );
-        }
+        m_toolPressed->Toggle();
     }
+
+    RefreshTool(m_toolPressed);
+
+    m_toolCurrent = m_toolPressed;
+    m_toolPressed = NULL;
+
+    Click();
 }
 
-void wxToolBar::OnEnter(wxMouseEvent &event)
+void wxToolBar::Click()
 {
+    wxCHECK_RET( m_toolCurrent, _T("no tool to click?") );
+
+    OnLeftClick(m_toolCurrent->GetId(), m_toolCurrent->IsToggled());
 }
 
-void wxToolBar::OnMouse(wxMouseEvent &event)
+bool wxToolBar::PerformAction(const wxControlAction& action,
+                              long numArg,
+                              const wxString& strArg)
 {
-    wxToolBarTool *hit = NULL;
-    int x = event.GetX();
-    int y = event.GetY();
-    
-    for ( wxToolBarToolsList::Node *node = m_tools.GetFirst();
-          node;
-          node = node->GetNext() )
+    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();
+    else if ( action == wxACTION_TOOLBAR_ENTER )
     {
-        wxToolBarTool *tool = (wxToolBarTool*) node->Data();
-        
-        if ((x > tool->m_x) && (x < tool->m_x+m_defaultWidth+5)  &&
-            (y > tool->m_y) && (y < tool->m_y+m_defaultHeight+5))
+        wxToolBarToolBase *toolCurrentOld = m_toolCurrent;
+        m_toolCurrent = FindById((int)numArg);
+
+        if ( m_toolCurrent != toolCurrentOld )
         {
-            hit = tool;
-            break;
+            // 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);
+
+                if ( m_toolCurrent )
+                {
+                    if ( m_toolCurrent->IsEnabled() )
+                        RefreshTool(m_toolCurrent);
+                }
+                else
+                {
+                    wxFAIL_MSG( _T("no current tool in wxACTION_TOOLBAR_ENTER?") );
+                }
+            }
         }
     }
-    
-    wxToolBarTool *oldMouseUnder = m_underMouse;
-    if (HasFlag( wxTB_FLAT))
+    else if ( action == wxACTION_TOOLBAR_LEAVE )
     {
-        if (m_underMouse && (m_underMouse != hit))
+        if ( m_toolCurrent )
         {
-            m_underMouse = NULL;
-            RefreshTool( oldMouseUnder );
+            wxToolBarToolBase *toolCurrentOld = m_toolCurrent;
+            m_toolCurrent = NULL;
+
+            RefreshTool(toolCurrentOld);
         }
-        m_underMouse = hit;
-    }
-    
-    if (event.LeftDown() && (hit) && hit->IsEnabled())
-    {
-        CaptureMouse();
-        m_captured = hit;
-        
-        m_captured->m_isDown = TRUE;
-        RefreshTool( m_captured );
-        
-        return;
     }
-    
-    if (event.Dragging() && (m_captured))
+    else
+        return wxControl::PerformAction(action, numArg, strArg);
+
+    return TRUE;
+}
+
+// ============================================================================
+// wxStdToolbarInputHandler implementation
+// ============================================================================
+
+wxStdToolbarInputHandler::wxStdToolbarInputHandler(wxInputHandler *handler)
+                        : wxStdButtonInputHandler(handler)
+{
+}
+
+bool wxStdToolbarInputHandler::HandleKey(wxInputConsumer *consumer,
+                                         const wxKeyEvent& event,
+                                         bool pressed)
+{
+    // TODO: when we have a current button we should allow the arrow
+    //       keys to move it
+    return wxStdInputHandler::HandleKey(consumer, event, pressed);
+}
+
+bool wxStdToolbarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
+                                               const wxMouseEvent& event)
+{
+    if ( !wxStdButtonInputHandler::HandleMouseMove(consumer, event) )
     {
-        bool is_down = (hit == m_captured);
-        if (is_down != m_captured->m_isDown)
+        wxToolBarToolBase *tool;
+
+        if ( event.Leaving() )
         {
-            m_captured->m_isDown = is_down;
-            RefreshTool( m_captured );
+            tool = NULL;
         }
-        
-        return;
-    }
-    
-    if (event.LeftUp() && (m_captured))
-    {
-        ReleaseMouse();
-        
-        m_captured->m_isDown = FALSE;
-        
-        // Bad trick...
-        m_underMouse = NULL;
-        
-        RefreshTool( m_captured );
-        
-        if (hit == m_captured)
+        else
         {
-            wxCommandEvent cevent( wxEVT_COMMAND_TOOL_CLICKED, m_captured->GetId() );
-            cevent.SetEventObject( this );
-            // cevent.SetExtraLong((long) toggleDown);
-            GetEventHandler()->ProcessEvent( cevent );
+            wxToolBar *tbar = wxStaticCast(consumer->GetInputWindow(), wxToolBar);
+            tool = tbar->FindToolForPosition(event.GetX(), event.GetY());
         }
-        
-        m_captured = NULL;
-        
-        return;
-    }
-    
-    if (HasFlag(wxTB_FLAT))
-    {
-        if (m_underMouse && (m_underMouse != oldMouseUnder))
-            RefreshTool( m_underMouse );
+
+        if ( tool )
+            consumer->PerformAction(wxACTION_TOOLBAR_ENTER, tool->GetId());
+        else
+            consumer->PerformAction(wxACTION_TOOLBAR_LEAVE);
+
+        return TRUE;
     }
+
+    return FALSE;
+}
+
+bool wxStdToolbarInputHandler::HandleFocus(wxInputConsumer *consumer,
+                                           const wxFocusEvent& event)
+{
+    // we shouldn't be left with a highlighted button
+    consumer->PerformAction(wxACTION_TOOLBAR_LEAVE);
+
+    return TRUE;
+}
+
+bool wxStdToolbarInputHandler::HandleActivation(wxInputConsumer *consumer,
+                                                bool activated)
+{
+    // as above
+    if ( !activated )
+        consumer->PerformAction(wxACTION_TOOLBAR_LEAVE);
+
+    return TRUE;
 }