]> git.saurik.com Git - wxWidgets.git/blobdiff - src/os2/toolbar.cpp
fixed event generation for wxChoice: it now sends one and exactly one wxEVT_COMMAND_C...
[wxWidgets.git] / src / os2 / toolbar.cpp
index 3cb859e3663f8890c53ac03a83946a4211578515..ea8d5f8480b4421105eab0ffdb2daac8db377319 100644 (file)
 /////////////////////////////////////////////////////////////////////////////
 // Name:        toolbar.cpp
 // Purpose:     wxToolBar
-// Author:      AUTHOR
+// Author:      David Webster
 // Modified by:
-// Created:     04/01/98
+// Created:     06/30/02
 // RCS-ID:      $Id$
-// Copyright:   (c) AUTHOR
-// Licence:    wxWindows licence
+// Copyright:   (c) David Webster
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
-#pragma implementation "toolbar.h"
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE
+
+#ifndef WX_PRECOMP
+    #include "wx/settings.h"
+    #include "wx/window.h"
+    #include "wx/frame.h"
+    #include "wx/app.h"
+    #include "wx/dcclient.h"
+    #include "wx/dcmemory.h"
 #endif
 
-#include "wx/wx.h"
+#include "wx/tooltip.h"
 #include "wx/toolbar.h"
 
-#if !USE_SHARED_LIBRARY
-IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
+bool                                wxToolBar::m_bInitialized = FALSE;
+
+// ----------------------------------------------------------------------------
+// private classes
+// ----------------------------------------------------------------------------
+
+class wxToolBarTool : public wxToolBarToolBase
+{
+public:
+    inline wxToolBarTool( wxToolBar*      pTbar
+                         ,int             vId
+                         ,const wxString& rsLabel
+                         ,const wxBitmap& rBitmap1
+                         ,const wxBitmap& rBitmap2
+                         ,wxItemKind      vKind
+                         ,wxObject*       pClientData
+                         ,const wxString& rsShortHelpString
+                         ,const wxString& rsLongHelpString
+                        ) : wxToolBarToolBase( pTbar
+                                              ,vId
+                                              ,rsLabel
+                                              ,rBitmap1
+                                              ,rBitmap2
+                                              ,vKind
+                                              ,pClientData
+                                              ,rsShortHelpString
+                                              ,rsLongHelpString
+                                             )
+    {
+    }
+
+    inline wxToolBarTool( wxToolBar* pTbar
+                         ,wxControl* pControl
+                        ) : wxToolBarToolBase( pTbar
+                                              ,pControl
+                                             )
+    {
+    }
+
+    void SetSize(const wxSize& rSize)
+    {
+        m_vWidth = rSize.x;
+        m_vHeight = rSize.y;
+    }
+
+    wxCoord GetWidth(void) const { return m_vWidth; }
+    wxCoord GetHeight(void) const { return m_vHeight; }
+
+    wxCoord                         m_vX;
+    wxCoord                         m_vY;
+    wxCoord                         m_vWidth;
+    wxCoord                         m_vHeight;
+}; // end of CLASS wxToolBarTool
+
+// ----------------------------------------------------------------------------
+// wxWin macros
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxToolBar, 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()
-#endif
 
-wxToolBar::wxToolBar()
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// tool bar tools creation
+// ----------------------------------------------------------------------------
+
+wxToolBarToolBase* wxToolBar::CreateTool(
+  int                               nId
+, const wxString&                   rsLabel
+, const wxBitmap&                   rBmpNormal
+, const wxBitmap&                   rBmpDisabled
+, wxItemKind                        eKind
+, wxObject*                         pClientData
+, const wxString&                   rsShortHelp
+, const wxString&                   rsLongHelp
+)
 {
-  m_maxWidth = -1;
-  m_maxHeight = -1;
-  m_defaultWidth = 24;
-  m_defaultHeight = 22;
-  // TODO
-}
+    return new wxToolBarTool( this
+                             ,nId
+                             ,rsLabel
+                             ,rBmpNormal
+                             ,rBmpDisabled
+                             ,eKind
+                             ,pClientData
+                             ,rsShortHelp
+                             ,rsLongHelp
+                            );
+} // end of wxToolBarSimple::CreateTool
 
-bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
-            long style, const wxString& name)
+wxToolBarToolBase *wxToolBar::CreateTool(
+  wxControl*                        pControl
+)
 {
-    m_maxWidth = -1;
-    m_maxHeight = -1;
-  
-    m_defaultWidth = 24;
-    m_defaultHeight = 22;
-    SetName(name);
+    return new wxToolBarTool( this
+                             ,pControl
+                            );
+} // end of wxToolBarSimple::CreateTool
 
-    m_windowStyle = style;
+// ----------------------------------------------------------------------------
+// wxToolBarSimple creation
+// ----------------------------------------------------------------------------
 
-    SetParent(parent);
+void wxToolBar::Init()
+{
+    m_nCurrentRowsOrColumns = 0;
 
-    if (parent) parent->AddChild(this);
+    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;
 
-    // TODO create toolbar
-  
-    return FALSE;
-}
+    m_toolPacking = 1;
+    m_toolSeparation = 5;
 
-wxToolBar::~wxToolBar()
+    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
+)
 {
-    // TODO
-}
+    //
+    // Rememeber the position for DoInsertTool()
+    //
+    m_vXPos = vXPos;
+    m_vYPos = vYPos;
 
-bool wxToolBar::CreateTools()
+    return wxToolBarBase::DoAddTool( vId
+                                    ,rsLabel
+                                    ,rBitmap
+                                    ,rBmpDisabled
+                                    ,eKind
+                                    ,rsShortHelp
+                                    ,rsLongHelp
+                                    ,pClientData
+                                    ,vXPos
+                                    ,vYPos
+                                   );
+} // end of wxToolBar::DoAddTool
+
+bool wxToolBar::DeleteTool(
+  int                               nId
+)
+{
+    bool                            bOk = wxToolBarBase::DeleteTool(nId);
+
+    if (bOk)
+    {
+        Realize();
+    }
+    return bOk;
+} // end of wxToolBar::DeleteTool
+
+bool wxToolBar::DeleteToolByPos(
+  size_t                            nPos
+)
 {
-    if (m_tools.Number() == 0)
+    bool                            bOk = wxToolBarBase::DeleteToolByPos(nPos);
+
+    if (bOk)
+    {
+        Realize();
+    }
+    return bOk;
+} // end of wxToolBar::DeleteTool
+
+wxToolBarToolBase* wxToolBar::InsertControl(
+  size_t                            nPos
+, wxControl*                        pControl
+)
+{
+    wxToolBarToolBase*              pTool = wxToolBarBase::InsertControl( nPos
+                                                                         ,pControl
+                                                                        );
+    if (m_bInitialized)
+    {
+        Realize();
+        Refresh();
+    }
+    return pTool;
+} // end of wxToolBar::InsertControl
+
+wxToolBarToolBase* wxToolBar::InsertSeparator(
+  size_t                            nPos
+)
+{
+    wxToolBarToolBase*              pTool = wxToolBarBase::InsertSeparator(nPos);
+
+    if (m_bInitialized)
+    {
+        Realize();
+        Refresh();
+    }
+    return pTool;
+} // end of wxToolBar::InsertSeparator
+
+wxToolBarToolBase* wxToolBar::InsertTool(
+  size_t                            nPos
+, int                               nId
+, const wxString&                   rsLabel
+, const wxBitmap&                   rBitmap
+, const wxBitmap&                   rBmpDisabled
+, wxItemKind                        eKind
+, const wxString&                   rsShortHelp
+, const wxString&                   rsLongHelp
+, wxObject*                         pClientData
+)
+{
+    wxToolBarToolBase*              pTool = wxToolBarBase::InsertTool( nPos
+                                                                      ,nId
+                                                                      ,rsLabel
+                                                                      ,rBitmap
+                                                                      ,rBmpDisabled
+                                                                      ,eKind
+                                                                      ,rsShortHelp
+                                                                      ,rsLongHelp
+                                                                      ,pClientData
+                                                                     );
+    if (m_bInitialized)
+    {
+        Realize();
+        Refresh();
+    }
+    return pTool;
+} // end of wxToolBar::InsertTool
+
+bool wxToolBar::DoInsertTool(
+  size_t                            WXUNUSED(nPos)
+, wxToolBarToolBase*                pToolBase
+)
+{
+    wxToolBarTool*                  pTool = (wxToolBarTool *)pToolBase;
+
+    pTool->m_vX = m_vXPos;
+    if (pTool->m_vX == -1)
+        pTool->m_vX = m_xMargin;
+
+    pTool->m_vY = m_vYPos;
+    if (pTool->m_vY == -1)
+        pTool->m_vX = m_yMargin;
+
+    pTool->SetSize(GetToolSize());
+
+    if (pTool->IsButton())
+    {
+        //
+        // Calculate reasonable max size in case Layout() not called
+        //
+        if ((pTool->m_vX + pTool->GetNormalBitmap().GetWidth() + m_xMargin) > m_vMaxWidth)
+            m_vMaxWidth = (wxCoord)((pTool->m_vX + pTool->GetWidth() + m_xMargin));
+
+        if ((pTool->m_vY + pTool->GetNormalBitmap().GetHeight() + m_yMargin) > m_vMaxHeight)
+            m_vMaxHeight = (wxCoord)((pTool->m_vY + pTool->GetHeight() + m_yMargin));
+    }
+    return TRUE;
+} // end of wxToolBar::DoInsertTool
+
+bool wxToolBar::DoDeleteTool(
+  size_t                            WXUNUSED(nPos)
+, wxToolBarToolBase*                pTool
+)
+{
+    pTool->Detach();
+    Refresh();
+    return TRUE;
+} // end of wxToolBar::DoDeleteTool
+
+bool wxToolBar::Create(
+  wxWindow*                         pParent
+, wxWindowID                        vId
+, const wxPoint&                    rPos
+, const wxSize&                     rSize
+, long                              lStyle
+, const wxString&                   rsName
+)
+{
+    if ( !wxWindow::Create( pParent
+                           ,vId
+                           ,rPos
+                           ,rSize
+                           ,lStyle
+                           ,rsName
+                          ))
         return FALSE;
 
-    // TODO
-    return FALSE;
-}
+    // Set it to grey (or other 3D face colour)
+    SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_MENUBAR));
+    SetFont(*wxSMALL_FONT);
+
+    if (GetWindowStyleFlag() & wxTB_VERTICAL)
+    {
+        m_vLastX = 7;
+        m_vLastY = 3;
+
+        m_maxRows = 32000;      // a lot
+        m_maxCols = 1;
+    }
+    else
+    {
+        m_vLastX = 3;
+        m_vLastY = 7;
+
+        m_maxRows = 1;
+        m_maxCols = 32000;      // a lot
+    }
+    SetCursor(*wxSTANDARD_CURSOR);
+
+    //
+    // The toolbar's tools, if they have labels and the winTB_TEXT
+    // style is set, then we need to take into account the size of
+    // the text when drawing tool bitmaps and the text
+    //
+    if (HasFlag(wxTB_TEXT))
+    {
+        wxClientDC                  vDC(this);
+
+        vDC.SetFont(GetFont());
+        vDC.GetTextExtent( wxT("XXXX")
+                          ,&m_vTextX
+                          ,&m_vTextY
+                         );
+    }
+
+    //
+    // Position it
+    //
+    int                             nX      = rPos.x;
+    int                             nY      = rPos.y;
+    int                             nWidth  = rSize.x;
+    int                             nHeight = rSize.y;
+
+    if (lStyle & wxTB_HORIZONTAL)
+    {
+        if (nWidth <= 0)
+        {
+            nWidth = pParent->GetClientSize().x;
+        }
+        if (nHeight <= 0)
+        {
+            if (lStyle & wxTB_TEXT)
+                nHeight = m_defaultHeight + m_vTextY;
+            else
+                nHeight = m_defaultHeight;
+        }
+    }
+    else
+    {
+        if (nHeight <= 0)
+        {
+            nHeight = pParent->GetClientSize().y;
+        }
+        if (nWidth <= 0)
+        {
+            if (lStyle & wxTB_TEXT)
+                nWidth = m_vTextX + (int)(m_vTextX/2); // a little margin
+            else
+                nWidth = m_defaultWidth + (int)(m_defaultWidth/2); // a little margin
+        }
+    }
+    if (nX < 0)
+        nX = 0;
+    if (nY < 0)
+        nY = 0;
+
+    SetSize( nX
+            ,nY
+            ,nWidth
+            ,nHeight
+           );
+    return TRUE;
+} // end of wxToolBar::Create
 
-void wxToolBar::SetToolBitmapSize(const wxSize& size)
+wxToolBar::~wxToolBar()
 {
-    m_defaultWidth = size.x; m_defaultHeight = size.y;
-    // TODO
-}
+    if (m_pToolTip)
+    {
+        delete m_pToolTip;
+        m_pToolTip = NULL;
+    }
+} // end of wxToolBar::~wxToolBar
 
-wxSize wxToolBar::GetMaxSize() const
+bool wxToolBar::Realize()
 {
-    // TODO
-    return wxSize(0, 0);
-}
+    int                             nMaxToolWidth  = 0;
+    int                             nMaxToolHeight = 0;
+
+    m_nCurrentRowsOrColumns = 0;
+    m_vLastX               = m_xMargin;
+    m_vLastY               = m_yMargin;
+    m_vMaxWidth            = 0;
+    m_vMaxHeight           = 0;
+
+
+    //
+    // Find the maximum tool width and height
+    //
+    wxToolBarToolsList::compatibility_iterator     node = m_tools.GetFirst();
 
-// The button size is bigger than the bitmap size
-wxSize wxToolBar::GetToolSize() const
+    while (node )
+    {
+        wxToolBarTool*              pTool = (wxToolBarTool *)node->GetData();
+
+        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();
+    }
+
+    wxCoord                         vTbWidth = 0L;
+    wxCoord                         vTbHeight = 0L;
+
+    GetSize( &vTbWidth
+            ,&vTbHeight
+           );
+    if (vTbHeight < nMaxToolHeight)
+    {
+        SetSize( -1L
+                ,-1L
+                ,vTbWidth
+                ,nMaxToolHeight + 4
+               );
+        if (GetParent()->IsKindOf(CLASSINFO(wxFrame)))
+        {
+            wxFrame*            pFrame = wxDynamicCast(GetParent(), wxFrame);
+
+            if (pFrame)
+                pFrame->PositionToolBar();
+        }
+    }
+
+    int                             nSeparatorSize = m_toolSeparation;
+
+    node = m_tools.GetFirst();
+    while (node)
+    {
+        wxToolBarTool*              pTool = (wxToolBarTool *)node->GetData();
+
+        if (pTool->IsSeparator())
+        {
+            if (GetWindowStyleFlag() & wxTB_HORIZONTAL)
+            {
+                pTool->m_vX = m_vLastX + nSeparatorSize;
+                pTool->m_vHeight = m_defaultHeight + m_vTextY;
+                if (m_nCurrentRowsOrColumns >= m_maxCols)
+                    m_vLastY += nSeparatorSize;
+                else
+                    m_vLastX += nSeparatorSize * 4;
+            }
+            else
+            {
+                pTool->m_vY = m_vLastY + nSeparatorSize;
+                pTool->m_vHeight = m_defaultHeight + m_vTextY;
+                if (m_nCurrentRowsOrColumns >= m_maxRows)
+                    m_vLastX += nSeparatorSize;
+                else
+                    m_vLastY += nSeparatorSize * 4;
+            }
+        }
+        else if (pTool->IsButton())
+        {
+            if (GetWindowStyleFlag() & wxTB_HORIZONTAL)
+            {
+                if (m_nCurrentRowsOrColumns >= m_maxCols)
+                {
+                    m_nCurrentRowsOrColumns = 0;
+                    m_vLastX                = m_xMargin;
+                    m_vLastY               += nMaxToolHeight + m_toolPacking;
+                }
+                pTool->m_vX = m_vLastX + (nMaxToolWidth - ((int)(nMaxToolWidth/2) + (int)(pTool->GetWidth()/2)));
+                if (HasFlag(wxTB_TEXT))
+                    pTool->m_vY = m_vLastY + nSeparatorSize - 2; // just bit of adjustment
+                else
+                    pTool->m_vY = m_vLastY + (nMaxToolHeight - (int)(pTool->GetHeight()/2));
+                m_vLastX += nMaxToolWidth + m_toolPacking + m_toolSeparation;
+            }
+            else
+            {
+                if (m_nCurrentRowsOrColumns >= m_maxRows)
+                {
+                    m_nCurrentRowsOrColumns = 0;
+                    m_vLastX               += (nMaxToolWidth + m_toolPacking);
+                    m_vLastY                = m_yMargin;
+                }
+                pTool->m_vX = m_vLastX + pTool->GetWidth();
+                if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
+                    pTool->m_vY = m_vLastY + (nMaxToolHeight - m_vTextY) + m_toolPacking;
+                else
+                    pTool->m_vY = m_vLastY + (nMaxToolHeight - (int)(pTool->GetHeight()/2));
+                m_vLastY += nMaxToolHeight + m_toolPacking + m_toolSeparation;
+            }
+            m_nCurrentRowsOrColumns++;
+        }
+        else
+        {
+            // TODO: support the controls
+        }
+
+        if (m_vLastX > m_maxWidth)
+            m_maxWidth = m_vLastX;
+        if (m_vLastY > m_maxHeight)
+            m_maxHeight = m_vLastY;
+
+        node = node->GetNext();
+    }
+
+    if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
+        m_maxWidth += nMaxToolWidth;
+    else
+        m_maxHeight += nMaxToolHeight;
+
+    m_maxWidth += m_xMargin;
+    m_maxHeight += m_yMargin;
+    m_bInitialized = TRUE;
+    return TRUE;
+} // end of wxToolBar::Realize
+
+// ----------------------------------------------------------------------------
+// event handlers
+// ----------------------------------------------------------------------------
+
+void wxToolBar::OnPaint (
+  wxPaintEvent&                     WXUNUSED(rEvent)
+)
 {
-    // TODO
-    return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
-}
+    wxPaintDC                       vDc(this);
+
+    PrepareDC(vDc);
 
-void wxToolBar::EnableTool(int toolIndex, bool enable)
+    static int                      nCount = 0;
+
+    //
+    // Prevent reentry of OnPaint which would cause wxMemoryDC errors.
+    //
+    if (nCount > 0)
+        return;
+    nCount++;
+
+    ::WinFillRect(vDc.GetHPS(), &vDc.m_vRclPaint, GetBackgroundColour().GetPixel());
+    for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        wxToolBarTool*              pTool = (wxToolBarTool*)node->GetData();
+
+        if (pTool->IsButton() )
+            DrawTool(vDc, pTool);
+        if (pTool->IsSeparator())
+        {
+            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_HORIZONTAL))
+                {
+                    nX = pTool->m_vX;
+                    nY = pTool->m_vY - (m_vTextY - 6);
+                    nHeight = (m_vTextY - 2) + pTool->GetHeight();
+                }
+                else
+                {
+                    nX = pTool->m_vX + m_xMargin + 10;
+                    nY = pTool->m_vY + m_vTextY + m_toolSeparation;
+                    nWidth = pTool->GetWidth() > m_vTextX ? pTool->GetWidth() : m_vTextX;
+                }
+            }
+            else
+            {
+                nX = pTool->m_vX;
+                nY = pTool->m_vY;
+                if (HasFlag(wxTB_HORIZONTAL))
+                    nHeight = pTool->GetHeight() - 2;
+                else
+                {
+                    nX += m_xMargin + 10;
+                    nY +=  m_yMargin + m_toolSeparation;
+                    nWidth = pTool->GetWidth();
+                }
+            }
+            vDc.DrawLine(nX, nY, nX + nWidth, nY + nHeight);
+        }
+    }
+    nCount--;
+} // end of wxToolBar::OnPaint
+
+void wxToolBar::OnSize (
+  wxSizeEvent&                      WXUNUSED(rEvent)
+)
+{
+#if wxUSE_CONSTRAINTS
+    if (GetAutoLayout())
+        Layout();
+#endif
+} // end of wxToolBar::OnSize
+
+void wxToolBar::OnKillFocus(
+  wxFocusEvent&                     WXUNUSED(rEvent)
+)
+{
+    OnMouseEnter(m_nPressedTool = m_nCurrentTool = -1);
+} // end of wxToolBar::OnKillFocus
+
+void wxToolBar::OnMouseEvent(
+  wxMouseEvent&                     rEvent
+)
 {
-    wxNode *node = m_tools.Find((long)toolIndex);
-    if (node)
+    POINTL                          vPoint;
+    HWND                            hWnd;
+    wxCoord                         vX;
+    wxCoord                         vY;
+    HPOINTER                        hPtr = ::WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE);
+
+    ::WinSetPointer(HWND_DESKTOP, hPtr);
+    ::WinQueryPointerPos(HWND_DESKTOP, &vPoint);
+    hWnd = ::WinWindowFromPoint(HWND_DESKTOP, &vPoint, TRUE);
+    if (hWnd != (HWND)GetHwnd())
+    {
+        m_vToolTimer.Stop();
+        return;
+    }
+
+    rEvent.GetPosition(&vX, &vY);
+
+    wxToolBarTool*            pTool = (wxToolBarTool *)FindToolForPosition( vX
+                                                                           ,vY
+                                                                          );
+
+    if (rEvent.LeftDown())
+    {
+        CaptureMouse();
+    }
+    if (rEvent.LeftUp())
+    {
+        ReleaseMouse();
+    }
+
+    if (!pTool)
+    {
+        m_vToolTimer.Stop();
+        if (m_nCurrentTool > -1)
+        {
+            if (rEvent.LeftIsDown())
+                SpringUpButton(m_nCurrentTool);
+            pTool = (wxToolBarTool *)FindById(m_nCurrentTool);
+            if (pTool && !pTool->IsToggled())
+            {
+                RaiseTool( pTool
+                          ,FALSE
+                         );
+            }
+            m_nCurrentTool = -1;
+            OnMouseEnter(-1);
+        }
+        return;
+    }
+    if (!rEvent.IsButton())
     {
-        wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-        tool->m_enabled = enable;
-        // TODO enable button
+        if (pTool->GetId() != m_nCurrentTool)
+        {
+            //
+            // If the left button is kept down and moved over buttons,
+            // press those buttons.
+            //
+            if (rEvent.LeftIsDown() && pTool->IsEnabled())
+            {
+                SpringUpButton(m_nCurrentTool);
+                if (pTool->CanBeToggled())
+                {
+                    pTool->Toggle();
+                }
+                DrawTool(pTool);
+            }
+            wxToolBarTool*          pOldTool = (wxToolBarTool*)FindById(m_nCurrentTool);
+
+            if (pOldTool && !pTool->IsToggled())
+                RaiseTool( pOldTool
+                          ,FALSE
+                         );
+            m_nCurrentTool = pTool->GetId();
+            OnMouseEnter(m_nCurrentTool);
+            if (!pTool->GetShortHelp().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);
+        }
+        return;
     }
-}
 
-void wxToolBar::ToggleTool(int toolIndex, bool toggle)
+    // Left button pressed.
+    if (rEvent.LeftDown() && pTool->IsEnabled())
+    {
+        if (pTool->CanBeToggled())
+        {
+            pTool->Toggle();
+        }
+        DrawTool(pTool);
+    }
+    else if (rEvent.RightDown())
+    {
+        OnRightClick( pTool->GetId()
+                     ,vX
+                     ,vY
+                    );
+    }
+
+    //
+    // Left Button Released.  Only this action confirms selection.
+    // If the button is enabled and it is not a toggle tool and it is
+    // in the pressed state, then raise the button and call OnLeftClick.
+    //
+    if (rEvent.LeftUp() && pTool->IsEnabled() )
+    {
+        //
+        // Pass the OnLeftClick event to tool
+        //
+        if (!OnLeftClick( pTool->GetId()
+                         ,pTool->IsToggled()) &&
+                          pTool->CanBeToggled())
+        {
+            //
+            // If it was a toggle, and OnLeftClick says No Toggle allowed,
+            // then change it back
+            //
+            pTool->Toggle();
+        }
+        DrawTool(pTool);
+    }
+} // end of wxToolBar::OnMouseEvent
+
+// ----------------------------------------------------------------------------
+// drawing
+// ----------------------------------------------------------------------------
+
+void wxToolBar::DrawTool(
+  wxToolBarToolBase*                pTool
+)
+{
+    wxClientDC                      vDc(this);
+
+    DrawTool( vDc
+             ,pTool
+            );
+} // end of wxToolBar::DrawTool
+
+void wxToolBar::DrawTool(
+  wxDC&                             rDc
+, wxToolBarToolBase*                pToolBase
+)
 {
-    wxNode *node = m_tools.Find((long)toolIndex);
-    if (node)
+    wxToolBarTool* pTool = (wxToolBarTool *)pToolBase;
+    wxColour gray85( 85,85,85 );
+    wxPen vDarkGreyPen( gray85, 1, wxSOLID );
+    wxBitmap vBitmap = pTool->GetNormalBitmap();
+    bool bUseMask = FALSE;
+    wxMask* pMask = NULL;
+
+    PrepareDC(rDc);
+
+    if (!vBitmap.Ok())
+        return;
+    if ((pMask = vBitmap.GetMask()) != NULL)
+        if (pMask->GetMaskBitmap() != NULLHANDLE)
+            bUseMask = TRUE;
+
+    if (!pTool->IsToggled())
     {
-        wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-        if (tool->m_isToggle)
+        LowerTool(pTool, FALSE);
+        if (!pTool->IsEnabled())
         {
-            tool->m_toggleState = toggle;
-            // TODO: set toggle state
+            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
+                          );
+        }
+        else
+        {
+            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 - 2)
+                            );
+            }
+            else  // normal tools
+            {
+                vLeft += (wxCoord)((m_vTextX - vX)/2);
+                rDc.DrawText( pTool->GetLabel()
+                             ,vLeft
+                             ,pTool->m_vY + m_vTextY + 4 // a bit of margin
+                            );
+            }
         }
     }
-}
+    else
+    {
+        wxColour vColor(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 + 4 // a bit of margin
+                        );
+        }
+    }
+} // end of wxToolBar::DrawTool
+
+// ----------------------------------------------------------------------------
+// toolbar geometry
+// ----------------------------------------------------------------------------
 
-void wxToolBar::ClearTools()
+void wxToolBar::SetRows(
+  int                               nRows
+)
 {
-    // TODO
-    wxToolBarBase::ClearTools();
-}
+    wxCHECK_RET( nRows != 0, _T("max number of rows must be > 0") );
 
-// If pushedBitmap is NULL, a reversed version of bitmap is
-// created and used as the pushed/toggled image.
-// If toggle is TRUE, the button toggles between the two states.
+    m_maxCols = (GetToolsCount() + nRows - 1) / nRows;
+    Refresh();
+} // end of wxToolBar::SetRows
 
-wxToolBarTool *wxToolBar::AddTool(int index, const wxBitmap& bitmap, const wxBitmap& pushedBitmap,
-             bool toggle, long xPos, long yPos, wxObject *clientData, const wxString& helpString1, const wxString& helpString2)
+wxToolBarToolBase* wxToolBar::FindToolForPosition(
+  wxCoord                           vX
+, wxCoord                           vY
+) const
 {
-  wxToolBarTool *tool = new wxToolBarTool(index, bitmap, wxNullBitmap, toggle, xPos, yPos, helpString1, helpString2);
-  tool->m_clientData = clientData;
+    wxCoord                         vTBarHeight = 0;
 
-  if (xPos > -1)
-    tool->m_x = xPos;
-  else
-    tool->m_x = m_xMargin;
+    GetSize( NULL
+            ,&vTBarHeight
+           );
+    vY = vTBarHeight - vY;
+    wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
+    while (node)
+    {
+        wxToolBarTool*              pTool = (wxToolBarTool *)node->GetData();
+
+        if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().IsNull())
+        {
+            if ((vX >= (pTool->m_vX - ((wxCoord)(pTool->GetWidth()/2) - 2))) &&
+                (vY >= (pTool->m_vY - 2)) &&
+                (vX <= (pTool->m_vX + pTool->GetWidth())) &&
+                (vY <= (pTool->m_vY + pTool->GetHeight() + m_vTextY + 2)))
+            {
+                return pTool;
+            }
+        }
+        else
+        {
+            if ((vX >= pTool->m_vX) &&
+                (vY >= pTool->m_vY) &&
+                (vX <= (pTool->m_vX + pTool->GetWidth())) &&
+                (vY <= (pTool->m_vY + pTool->GetHeight())))
+            {
+                return pTool;
+            }
+        }
+        node = node->GetNext();
+    }
+    return (wxToolBarToolBase *)NULL;
+} // end of wxToolBar::FindToolForPosition
+
+// ----------------------------------------------------------------------------
+// tool state change handlers
+// ----------------------------------------------------------------------------
+
+void wxToolBar::DoEnableTool(
+  wxToolBarToolBase*                pTool
+, bool                              WXUNUSED(bEnable)
+)
+{
+    DrawTool(pTool);
+} // end of wxToolBar::DoEnableTool
+
+void wxToolBar::DoToggleTool(
+  wxToolBarToolBase*                pTool
+, bool                              WXUNUSED(bToggle)
+)
+{
+    DrawTool(pTool);
+} // end of wxToolBar::DoToggleTool
+
+void wxToolBar::DoSetToggle(
+  wxToolBarToolBase*                WXUNUSED(pTool)
+, bool                              WXUNUSED(bToggle)
+)
+{
+    // nothing to do
+} // end of wxToolBar::DoSetToggle
+
+//
+// Okay, so we've left the tool we're in ... we must check if the tool we're
+// leaving was a 'sprung push button' and if so, spring it back to the up
+// state.
+//
+void wxToolBar::SpringUpButton(
+  int                               vId
+)
+{
+    wxToolBarToolBase*              pTool = FindById(vId);
+
+    if (pTool && pTool->CanBeToggled())
+    {
+        if (pTool->IsToggled())
+            pTool->Toggle();
+
+        DrawTool(pTool);
+    }
+} // end of wxToolBar::SpringUpButton
+
+// ----------------------------------------------------------------------------
+// private helpers
+// ----------------------------------------------------------------------------
+
+void wxToolBar::LowerTool ( wxToolBarToolBase* pToolBase,
+                            bool               bLower )
+{
+    wxToolBarTool*                  pTool = (wxToolBarTool*)pToolBase;
+    wxCoord vX;
+    wxCoord vY;
+    wxCoord vWidth;
+    wxCoord vHeight;
+    wxColour gray85( 85,85,85 );
+    wxPen vDarkGreyPen( gray85, 1, wxSOLID );
+    wxPen vClearPen( GetBackgroundColour(), 1, wxSOLID );
+    wxClientDC vDC(this);
+
+    if (!pTool)
+        return;
+
+    if (pTool->IsSeparator())
+        return;
+
+    //
+    // We only do this for flat toolbars
+    //
+    if (!HasFlag(wxTB_FLAT))
+        return;
+
+    if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().empty())
+    {
+        if (pTool->GetWidth() > m_vTextX)
+        {
+            vX = pTool->m_vX - 2;
+            vWidth = pTool->GetWidth() + 4;
+        }
+        else
+        {
+            vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
+            vWidth = m_vTextX + 4;
+        }
+        vY = pTool->m_vY - 2;
+        vHeight = pTool->GetHeight() + m_vTextY + 2;
+    }
+    else
+    {
+        vX = pTool->m_vX - 2;
+        vY = pTool->m_vY - 2;
+        vWidth = pTool->GetWidth() + 4;
+        vHeight = pTool->GetHeight() + 4;
+    }
+    if (bLower)
+    {
+        vDC.SetPen(*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 (yPos > -1)
-    tool->m_y = yPos;
-  else
-    tool->m_y = m_yMargin;
+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 (!pTool)
+        return;
+
+    if (pTool->IsSeparator())
+        return;
+
+    if (!pTool->IsEnabled())
+        return;
 
-  tool->SetSize(GetDefaultButtonWidth(), GetDefaultButtonHeight());
+    //
+    // We only do this for flat toolbars
+    //
+    if (!HasFlag(wxTB_FLAT))
+        return;
 
-  m_tools.Append((long)index, tool);
-  return tool;
-}
+    if (HasFlag(wxTB_TEXT) && !pTool->GetLabel().empty())
+    {
+        if (pTool->GetWidth() > m_vTextX)
+        {
+            vX = pTool->m_vX - 2;
+            vWidth = pTool->GetWidth() + 4;
+        }
+        else
+        {
+            vX = pTool->m_vX - (wxCoord)(pTool->GetWidth()/2);
+            vWidth = m_vTextX + 4;
+        }
+        vY = pTool->m_vY - 2;
+        vHeight = pTool->GetHeight() + m_vTextY + 2;
+    }
+    else
+    {
+        vX = pTool->m_vX - 2;
+        vY = pTool->m_vY - 2;
+        vWidth = pTool->GetWidth() + 4;
+        vHeight = pTool->GetHeight() + 4;
+    }
+    if (bRaise)
+    {
+        vDC.SetPen(vDarkGreyPen);
+        vDC.DrawLine(vX + vWidth, vY + vHeight, vX, vY + vHeight);
+        vDC.DrawLine(vX + vWidth, vY, vX + vWidth, vY + vHeight);
+        vDC.SetPen(*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.GetTimerId())
+    {
+        wxPoint                     vPos( m_vXMouse
+                                         ,m_vYMouse
+                                        );
+
+        m_pToolTip->DisplayToolTipWindow(vPos);
+        m_vToolTimer.Stop();
+        m_vToolExpTimer.Start(4000L, TRUE);
+    }
+    else if (rEvent.GetId() == m_vToolExpTimer.GetTimerId())
+    {
+        m_pToolTip->HideToolTipWindow();
+        GetParent()->Refresh();
+        m_vToolExpTimer.Stop();
+    }
+} // end of wxToolBar::OnTimer
 
+#endif // ndef for wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE