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