]> git.saurik.com Git - wxWidgets.git/blobdiff - src/motif/toolbar.cpp
Don't enter an infinite loop if a spacer with min size of -1 is used.
[wxWidgets.git] / src / motif / toolbar.cpp
index 903b69be330ddd3d88b34089d50c8216c4598e2f..6cc0576b5575829309dc1c24abda0642313e884c 100644 (file)
@@ -1,23 +1,37 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        toolbar.cpp
+// Name:        src/motif/toolbar.cpp
 // Purpose:     wxToolBar
 // Author:      Julian Smart
-// Modified by:
+// Modified by: 13.12.99 by VZ during toolbar classes reorganization
 // Created:     04/01/98
 // RCS-ID:      $Id$
 // Copyright:   (c) Julian Smart
-// Licence:    wxWindows licence
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
-#pragma implementation "toolbar.h"
-#endif
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
 
-#include "wx/wx.h"
-#include "wx/app.h"
-#include "wx/timer.h"
-#include "wx/motif/toolbar.h"
+#include "wx/toolbar.h"
+
+#ifndef WX_PRECOMP
+    #include "wx/app.h"
+    #include "wx/frame.h"
+    #include "wx/timer.h"
+    #include "wx/settings.h"
+#endif
 
+#ifdef __VMS__
+#pragma message disable nosimpint
+#endif
 #include <Xm/Xm.h>
 #include <Xm/PushBG.h>
 #include <Xm/PushB.h>
 #include <Xm/ToggleB.h>
 #include <Xm/ToggleBG.h>
 #include <Xm/Form.h>
+#ifdef __VMS__
+#pragma message enable nosimpint
+#endif
 
 #include "wx/motif/private.h"
+#include "wx/motif/bmpmotif.h"
 
-#if !USE_SHARED_LIBRARY
-IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
+// ----------------------------------------------------------------------------
+// wxWin macros
+// ----------------------------------------------------------------------------
 
-BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
-END_EVENT_TABLE()
-#endif
+IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
+
+// ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
 
 static void wxToolButtonCallback (Widget w, XtPointer clientData,
-                   XtPointer ptr);
+                    XtPointer ptr);
 static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
                      XEvent *event, Boolean *continue_to_dispatch);
 
-wxBitmap wxCreateMaskedBitmap(wxBitmap& bitmap, wxColour& colour);
+// ----------------------------------------------------------------------------
+// private classes
+// ----------------------------------------------------------------------------
 
-class wxToolBarTimer: public wxTimer
+class wxToolBarTimer : public wxTimer
 {
 public:
-  wxToolBarTimer() { }
-  virtual void Notify();
+    virtual void Notify();
 
-  static Widget help_popup;
-  static Widget buttonWidget;
-  static wxString helpString;
+    static Widget help_popup;
+    static Widget buttonWidget;
+    static wxString helpString;
 };
 
-static wxToolBarTimer* wxTheToolBarTimer = (wxToolBarTimer*) NULL;
+class wxToolBarTool : public wxToolBarToolBase
+{
+public:
+    wxToolBarTool(wxToolBar *tbar,
+                  int id,
+                  const wxString& label,
+                  const wxBitmap& bmpNormal,
+                  const wxBitmap& bmpToggled,
+                  wxItemKind kind,
+                  wxObject *clientData,
+                  const wxString& shortHelp,
+                  const wxString& longHelp)
+        : wxToolBarToolBase(tbar, id, label, bmpNormal, bmpToggled, kind,
+                            clientData, shortHelp, longHelp)
+    {
+        Init();
+    }
+
+    wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
+        : wxToolBarToolBase(tbar, control, label)
+    {
+        Init();
+    }
+
+    virtual ~wxToolBarTool();
+
+    // accessors
+    void SetWidget(Widget widget) { m_widget = widget; }
+    Widget GetButtonWidget() const { return m_widget; }
+
+    Pixmap GetArmPixmap()
+    {
+        m_bitmapCache.SetBitmap( GetNormalBitmap() );
+        return (Pixmap)m_bitmapCache.GetArmPixmap( (WXWidget)m_widget );
+    }
+
+    Pixmap GetInsensPixmap()
+    {
+        m_bitmapCache.SetBitmap( GetNormalBitmap() );
+        return (Pixmap)m_bitmapCache.GetInsensPixmap( (WXWidget)m_widget );
+    }
+protected:
+    void Init();
+
+    Widget m_widget;
+    wxBitmapCache m_bitmapCache;
+};
+
+// ----------------------------------------------------------------------------
+// globals
+// ----------------------------------------------------------------------------
+
+static wxToolBarTimer* wxTheToolBarTimer = NULL;
 
 Widget wxToolBarTimer::help_popup = (Widget) 0;
 Widget wxToolBarTimer::buttonWidget = (Widget) 0;
-wxString wxToolBarTimer::helpString = "";
+wxString wxToolBarTimer::helpString;
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxToolBarTool
+// ----------------------------------------------------------------------------
+
+wxToolBarToolBase *wxToolBar::CreateTool(int id,
+                                         const wxString& label,
+                                         const wxBitmap& bmpNormal,
+                                         const wxBitmap& bmpToggled,
+                                         wxItemKind kind,
+                                         wxObject *clientData,
+                                         const wxString& shortHelp,
+                                         const wxString& longHelp)
+{
+    return new wxToolBarTool(this, id, label, bmpNormal, bmpToggled, kind,
+                             clientData, shortHelp, longHelp);
+}
 
-wxToolBar::wxToolBar():
-  m_widgets(wxKEY_INTEGER)
+
+wxToolBarToolBase *
+wxToolBar::CreateTool(wxControl *control, const wxString& label)
 {
-  m_maxWidth = -1;
-  m_maxHeight = -1;
-  m_defaultWidth = 24;
-  m_defaultHeight = 22;
+    return new wxToolBarTool(this, control, label);
 }
 
-bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
-            long style, const wxString& name)
+void wxToolBarTool::Init()
+{
+    m_widget = (Widget)0;
+}
+
+wxToolBarTool::~wxToolBarTool()
+{
+    if ( m_widget )
+        XtDestroyWidget(m_widget);
+}
+
+// ----------------------------------------------------------------------------
+// wxToolBar construction
+// ----------------------------------------------------------------------------
+
+void wxToolBar::Init()
 {
     m_maxWidth = -1;
     m_maxHeight = -1;
-  
     m_defaultWidth = 24;
     m_defaultHeight = 22;
-    SetName(name);
-    m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
-    m_foregroundColour = parent->GetForegroundColour();
-    m_windowStyle = style;
+    m_toolPacking = 2;
+    m_toolSeparation = 8;
+    m_xMargin = 2;
+    m_yMargin = 2;
+    m_maxRows = 100;
+    m_maxCols = 100;
+}
 
-    SetParent(parent);
+bool wxToolBar::Create(wxWindow *parent,
+                       wxWindowID id,
+                       const wxPoint& pos,
+                       const wxSize& size,
+                       long style,
+                       const wxString& name)
+{
+    if( !wxControl::CreateControl( parent, id, pos, size, style,
+                                   wxDefaultValidator, name ) )
+        return false;
+    PreCreation();
 
-    if (parent) parent->AddChild(this);
+    FixupStyle();
 
     Widget parentWidget = (Widget) parent->GetClientWidget();
 
     Widget toolbar = XtVaCreateManagedWidget("toolbar",
-                xmFormWidgetClass, parentWidget,
+                    xmBulletinBoardWidgetClass, (Widget) parentWidget,
+                    XmNmarginWidth, 0,
+                    XmNmarginHeight, 0,
+                    XmNresizePolicy, XmRESIZE_NONE,
+                    NULL);
+/*
+    Widget toolbar = XtVaCreateManagedWidget("toolbar",
+                xmFormWidgetClass, (Widget) m_clientWidget,
                 XmNtraversalOn, False,
                 XmNhorizontalSpacing, 0,
                 XmNverticalSpacing, 0,
@@ -97,402 +223,481 @@ bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, cons
                 XmNmarginWidth, 0,
                 XmNmarginHeight, 0,
                 NULL);
+*/
 
     m_mainWidget = (WXWidget) toolbar;
 
-    SetCanAddEventHandler(TRUE);
-    AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y);
+    wxPoint rPos = pos;
+    wxSize  rSize = size;
+
+    if( rPos.x == -1 ) rPos.x = 0;
+    if( rPos.y == -1 ) rPos.y = 0;
+    if( rSize.x == -1 && GetParent() )
+        rSize.x = GetParent()->GetSize().x;
+
+    PostCreation();
+    AttachWidget (parent, m_mainWidget, (WXWidget) NULL,
+                  rPos.x, rPos.y, rSize.x, rSize.y);
 
-    SetFont(* parent->GetFont());
-    ChangeBackgroundColour();
-  
-    return TRUE;
+    return true;
 }
 
 wxToolBar::~wxToolBar()
 {
     delete wxTheToolBarTimer;
     wxTheToolBarTimer = NULL;
-    ClearTools();
-    DestroyPixmaps();
 }
 
-bool wxToolBar::CreateTools()
+bool wxToolBar::Realize()
 {
-    if (m_tools.Number() == 0)
-        return FALSE;
+    if ( m_tools.GetCount() == 0 )
+    {
+        // nothing to do
+        return true;
+    }
+
+    bool isVertical = GetWindowStyle() & wxTB_VERTICAL;
 
     // Separator spacing
     const int separatorSize = GetToolSeparation(); // 8;
+    wxSize margins = GetToolMargins();
+    int packing = GetToolPacking();
+    int marginX = margins.x;
+    int marginY = margins.y;
 
-    int currentSpacing = 0;
+    int currentX = marginX;
+    int currentY = marginY;
 
-    m_widgets.Clear();
-    Widget prevButton = (Widget) 0;
-    wxNode* node = m_tools.First();
-    while (node)
-    {
-        wxToolBarTool *tool = (wxToolBarTool *)node->Data();
+    int buttonHeight = 0, buttonWidth = 0;
 
-        if (tool->m_toolStyle == wxTOOL_STYLE_SEPARATOR)
-            currentSpacing = separatorSize;
-        else if (tool->m_bitmap1.Ok())
-        {
-            Widget button = (Widget) 0;
+    Widget button;
+    Pixmap pixmap, insensPixmap;
+    wxBitmap bmp, insensBmp;
 
-            if (tool->m_isToggle)
-            {
-                button = XtVaCreateManagedWidget("toggleButton", 
-                   xmToggleButtonWidgetClass, (Widget) m_mainWidget,
-                   XmNleftAttachment, (prevButton == (Widget) 0) ? XmATTACH_FORM : XmATTACH_WIDGET,
-                   XmNleftWidget, (prevButton == (Widget) 0) ? NULL : prevButton,
-                   XmNleftOffset, currentSpacing,
-                   XmNtopAttachment, XmATTACH_FORM,
-                                                //                   XmNpushButtonEnabled, True,
-                   XmNmultiClick, XmMULTICLICK_KEEP,
-                   XmNlabelType, XmPIXMAP,
-                   NULL);
-                XtAddCallback ((Widget) button, XmNvalueChangedCallback, (XtCallbackProc) wxToolButtonCallback,
-                (XtPointer) this);
-            }
-            else
-            {
-                button = XtVaCreateManagedWidget("button", 
-                   xmPushButtonWidgetClass, (Widget) m_mainWidget,
-                   XmNleftAttachment, (prevButton == (Widget) 0) ? XmATTACH_FORM : XmATTACH_WIDGET,
-                   XmNleftWidget, (prevButton == (Widget) 0) ? NULL : prevButton,
-                   XmNleftOffset, currentSpacing,
-                   XmNtopAttachment, XmATTACH_FORM,
-                   XmNpushButtonEnabled, True,
-                   XmNmultiClick, XmMULTICLICK_KEEP,
-                   XmNlabelType, XmPIXMAP,
-                   NULL);
-                XtAddCallback (button,
-                   XmNactivateCallback, (XtCallbackProc) wxToolButtonCallback,
-                   (XtPointer) this);
-            }
-
-            // For each button, if there is a mask, we must create
-            // a new wxBitmap that has the correct background colour
-            // for the button. Otherwise the background will just be
-            // e.g. black if a transparent XPM has been loaded.
-            wxBitmap originalBitmap = tool->m_bitmap1;
+    wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
+    while ( node )
+    {
+        wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
 
-            if (tool->m_bitmap1.GetMask())
+        switch ( tool->GetStyle() )
+        {
+            case wxTOOL_STYLE_CONTROL:
             {
-                int backgroundPixel;
-                XtVaGetValues(button, XmNbackground, &backgroundPixel,
-                             NULL);
-
-
-                wxColour col;
-                col.SetPixel(backgroundPixel);
-                
-                wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap1, col);
+                wxControl* control = tool->GetControl();
+                wxSize sz = control->GetSize();
+                wxPoint pos = control->GetPosition();
+                // Allow a control to specify a y[x]-offset by setting
+                // its initial position, but still don't allow it to
+                // position itself above the top[left] margin.
+                int controlY = (pos.y > 0) ? pos.y : currentY;
+                int controlX = (pos.x > 0) ? pos.x : currentX;
+                control->Move( isVertical ? controlX : currentX,
+                               isVertical ? currentY : controlY );
+                if ( isVertical )
+                    currentY += sz.y + packing;
+                else
+                    currentX += sz.x + packing;
 
-                tool->m_bitmap1 = newBitmap;
+                break;
             }
+            case wxTOOL_STYLE_SEPARATOR:
+                // skip separators for vertical toolbars
+                if( !isVertical )
+                {
+                    currentX += separatorSize;
+                }
+                break;
 
-            // Create a selected/toggled bitmap. If there isn't a m_bitmap2,
-            // we need to create it (with a darker, selected background)
-            int backgroundPixel;
-            if (tool->m_isToggle)
-                XtVaGetValues(button, XmNselectColor, &backgroundPixel,
-                     NULL);
-            else
-                XtVaGetValues(button, XmNarmColor, &backgroundPixel,
-                     NULL);
-
-            wxColour col;
-            col.SetPixel(backgroundPixel);
+            case wxTOOL_STYLE_BUTTON:
+                button = (Widget) 0;
 
-            if (tool->m_bitmap2.Ok() && tool->m_bitmap2.GetMask())
-            {
-                // Use what's there
-                wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap2, col);
-                tool->m_bitmap2 = newBitmap;
-            }
-            else
-            {
-                // Use unselected bitmap
-                if (originalBitmap.GetMask())
+                if ( tool->CanBeToggled() && !tool->GetButtonWidget() )
                 {
-                    wxBitmap newBitmap = wxCreateMaskedBitmap(originalBitmap, col);
-                    tool->m_bitmap2 = newBitmap;
-               }
-                else
-                    tool->m_bitmap2 = tool->m_bitmap1;
-            }
+                    button = XtVaCreateWidget("toggleButton",
+                            xmToggleButtonWidgetClass, (Widget) m_mainWidget,
+                            XmNx, currentX, XmNy, currentY,
+                            XmNindicatorOn, False,
+                            XmNshadowThickness, 2,
+                            XmNborderWidth, 0,
+                            XmNspacing, 0,
+                            XmNmarginWidth, 0,
+                            XmNmarginHeight, 0,
+                            XmNmultiClick, XmMULTICLICK_KEEP,
+                            XmNlabelType, XmPIXMAP,
+                            NULL);
+                    XtAddCallback ((Widget) button,
+                                   XmNvalueChangedCallback,
+                                   (XtCallbackProc) wxToolButtonCallback,
+                                   (XtPointer) this);
+
+                    XtVaSetValues ((Widget) button,
+                                   XmNselectColor,
+                                   m_backgroundColour.AllocColour
+                                       (XtDisplay((Widget) button)),
+                                   NULL);
+                }
+                else if( !tool->GetButtonWidget() )
+                {
+                    button = XtVaCreateWidget("button",
+                            xmPushButtonWidgetClass, (Widget) m_mainWidget,
+                            XmNx, currentX, XmNy, currentY,
+                            XmNpushButtonEnabled, True,
+                            XmNmultiClick, XmMULTICLICK_KEEP,
+                            XmNlabelType, XmPIXMAP,
+                            NULL);
+                    XtAddCallback (button,
+                                   XmNactivateCallback,
+                                   (XtCallbackProc) wxToolButtonCallback,
+                                   (XtPointer) this);
+                }
 
-            Pixmap pixmap = (Pixmap) tool->m_bitmap1.GetPixmap();
-            Pixmap insensPixmap = (Pixmap) tool->m_bitmap1.GetInsensPixmap();
+                if( !tool->GetButtonWidget() )
+                {
+                    wxDoChangeBackgroundColour((WXWidget) button,
+                                               m_backgroundColour, true);
 
-            if (tool->m_isToggle)
-            {
-                // Toggle button
-                Pixmap pixmap2 = (Pixmap) 0;
-                Pixmap insensPixmap2 = (Pixmap) 0;
+                    tool->SetWidget(button);
+                }
+                else
+                {
+                    button = (Widget)tool->GetButtonWidget();
+                    XtVaSetValues( button,
+                                   XmNx, currentX, XmNy, currentY,
+                                   NULL );
+                }
 
-                // If there's a bitmap for the toggled state, use it,
-                // otherwise generate one.
-                if (tool->m_bitmap2.Ok())
+                // For each button, if there is a mask, we must create
+                // a new wxBitmap that has the correct background colour
+                // for the button. Otherwise the background will just be
+                // e.g. black if a transparent XPM has been loaded.
+                bmp = tool->GetNormalBitmap();
+                insensBmp = tool->GetDisabledBitmap();
+                if ( bmp.GetMask() || insensBmp.GetMask() )
                 {
-                    pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap();
-                    insensPixmap2 = (Pixmap) tool->m_bitmap2.GetInsensPixmap();
+                    WXPixel backgroundPixel;
+                    XtVaGetValues(button, XmNbackground, &backgroundPixel,
+                                  NULL);
+
+                    wxColour col;
+                    col.SetPixel(backgroundPixel);
+
+                    if( bmp.Ok() && bmp.GetMask() )
+                    {
+                        bmp = wxCreateMaskedBitmap(bmp, col);
+                        tool->SetNormalBitmap(bmp);
+                    }
+
+                    if( insensBmp.Ok() && insensBmp.GetMask() )
+                    {
+                        insensBmp = wxCreateMaskedBitmap(insensBmp, col);
+                        tool->SetDisabledBitmap(insensBmp);
+                    }
                 }
+
+                // Create a selected/toggled bitmap. If there isn't a 2nd
+                // bitmap, we need to create it (with a darker, selected
+                // background)
+                WXPixel backgroundPixel;
+                if ( tool->CanBeToggled() )
+                    XtVaGetValues(button, XmNselectColor, &backgroundPixel,
+                                  NULL);
                 else
+                    XtVaGetValues(button, XmNarmColor, &backgroundPixel,
+                                  NULL);
+                wxColour col;
+                col.SetPixel(backgroundPixel);
+
+                pixmap = (Pixmap) bmp.GetDrawable();
                 {
-                    pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button);
-                    insensPixmap2 = XCreateInsensitivePixmap((Display*) wxGetDisplay(), pixmap2);
-                    m_pixmaps.Append((wxObject*) insensPixmap2); // Store for later deletion
+                    wxBitmap tmp = tool->GetDisabledBitmap();
+
+                    insensPixmap = tmp.Ok() ?
+                            (Pixmap)tmp.GetDrawable() :
+                            tool->GetInsensPixmap();
                 }
-                XtVaSetValues (button,
-                    XmNindicatorOn, False,
-                   XmNshadowThickness, 2,
-                              //                   XmNborderWidth, 0,
-                              //                   XmNspacing, 0,
-                   XmNmarginWidth, 0,
-                   XmNmarginHeight, 0,
-                    XmNfillOnSelect, True,
-                    XmNlabelPixmap, pixmap,
-                    XmNselectPixmap, pixmap2,
-                    XmNlabelInsensitivePixmap, insensPixmap,
-                    XmNselectInsensitivePixmap, insensPixmap2,
-                    XmNlabelType, XmPIXMAP,
-                    NULL);
-            }
-            else
-            {
-                Pixmap pixmap2 = (Pixmap) 0;
 
-                // If there's a bitmap for the armed state, use it,
-                // otherwise generate one.
-                if (tool->m_bitmap2.Ok())
+                if (tool->CanBeToggled())
                 {
-                    pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap();
+                    // Toggle button
+                    Pixmap pixmap2 = tool->GetArmPixmap();
+                    Pixmap insensPixmap2 = tool->GetInsensPixmap();
+
+                    XtVaSetValues (button,
+                            XmNfillOnSelect, True,
+                            XmNlabelPixmap, pixmap,
+                            XmNselectPixmap, pixmap2,
+                            XmNlabelInsensitivePixmap, insensPixmap,
+                            XmNselectInsensitivePixmap, insensPixmap2,
+                            XmNlabelType, XmPIXMAP,
+                            NULL);
                 }
                 else
                 {
-                    pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button);
+                    Pixmap pixmap2 = tool->GetArmPixmap();
+
+                    // Normal button
+                    XtVaSetValues(button,
+                            XmNlabelPixmap, pixmap,
+                            XmNlabelInsensitivePixmap, insensPixmap,
+                            XmNarmPixmap, pixmap2,
+                            NULL);
+                }
 
+                XtManageChild(button);
+
+                {
+                    Dimension width, height;
+                    XtVaGetValues(button,
+                                  XmNwidth, &width,
+                                  XmNheight, & height,
+                                  NULL);
+                    if ( isVertical )
+                        currentY += height + packing;
+                    else
+                        currentX += width + packing;
+                    buttonHeight = wxMax(buttonHeight, height);
+                    buttonWidth = wxMax(buttonWidth, width);
                 }
-                // Normal button
-                XtVaSetValues(button,
-                   XmNlabelPixmap, pixmap,
-                   XmNlabelInsensitivePixmap, insensPixmap,
-                   XmNarmPixmap, pixmap2,
-                   NULL);
-            }
 
-            XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask, 
-                       False, wxToolButtonPopupCallback, (XtPointer) this);
-            m_widgets.Append(tool->m_index, (wxObject*) button);
+                XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask,
+                        False, wxToolButtonPopupCallback, (XtPointer) this);
 
-            prevButton = button;
-            currentSpacing = 0;
+                break;
         }
-        node = node->Next();
+
+        node = node->GetNext();
     }
 
-    return TRUE;
-}
+    SetSize( -1, -1,
+             isVertical ? buttonWidth + 2 * marginX : -1,
+             isVertical ? -1 : buttonHeight +  2*marginY );
 
-void wxToolBar::SetToolBitmapSize(const wxSize& size)
-{
-    m_defaultWidth = size.x; m_defaultHeight = size.y;
-    // TODO
+    return true;
 }
 
-wxSize wxToolBar::GetMaxSize() const
+wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord WXUNUSED(x),
+                                                  wxCoord WXUNUSED(y)) const
 {
-    // TODO
-    return wxSize(0, 0);
+    wxFAIL_MSG( wxT("TODO") );
+
+    return NULL;
 }
 
-// The button size is bigger than the bitmap size
-wxSize wxToolBar::GetToolSize() const
+bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
 {
-    // TODO
-    return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
+    tool->Attach(this);
+
+    return true;
 }
 
-void wxToolBar::EnableTool(int toolIndex, bool enable)
+bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
 {
-    wxNode *node = m_tools.Find((long)toolIndex);
-    if (node)
+    tool->Detach();
+
+    bool isVertical = GetWindowStyle() & wxTB_VERTICAL;
+    const int separatorSize = GetToolSeparation(); // 8;
+    int packing = GetToolPacking();
+    int offset = 0;
+
+    for( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
+         node; node = node->GetNext() )
     {
-        wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-        tool->m_enabled = enable;
+        wxToolBarTool *t = (wxToolBarTool*)node->GetData();
 
-        WXWidget widget = FindWidgetForIndex(tool->m_index);
-        if (widget == (WXWidget) 0)
-            return;
+        if( t == tool )
+        {
+            switch ( t->GetStyle() )
+            {
+            case wxTOOL_STYLE_CONTROL:
+            {
+                wxSize size = t->GetControl()->GetSize();
+                offset = isVertical ? size.y : size.x;
+                offset += packing;
+                break;
+            }
+            case wxTOOL_STYLE_SEPARATOR:
+                offset = isVertical ? 0 : separatorSize;
+                break;
+            case wxTOOL_STYLE_BUTTON:
+            {
+                Widget w = t->GetButtonWidget();
+                Dimension width, height;
 
-        XtSetSensitive((Widget) widget, (Boolean) enable);
-    }
-}
+                XtVaGetValues( w,
+                               XmNwidth, &width,
+                               XmNheight, &height,
+                               NULL );
 
-void wxToolBar::ToggleTool(int toolIndex, bool toggle)
-{
-    wxNode *node = m_tools.Find((long)toolIndex);
-    if (node)
-    {
-        wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-        if (tool->m_isToggle)
+                offset = isVertical ? height : width;
+                offset += packing;
+                break;
+            }
+            }
+        }
+        else if( offset )
         {
-            tool->m_toggleState = toggle;
+            switch ( t->GetStyle() )
+            {
+            case wxTOOL_STYLE_CONTROL:
+            {
+                wxPoint location = t->GetControl()->GetPosition();
+
+                if( isVertical )
+                    location.y -= offset;
+                else
+                    location.x -= offset;
 
-            WXWidget widget = FindWidgetForIndex(tool->m_index);
-            if (widget == (WXWidget) 0)
-                return;
+                t->GetControl()->Move( location );
+                break;
+            }
+            case wxTOOL_STYLE_SEPARATOR:
+                break;
+            case wxTOOL_STYLE_BUTTON:
+            {
+                Dimension x, y;
+                XtVaGetValues( t->GetButtonWidget(),
+                               XmNx, &x,
+                               XmNy, &y,
+                               NULL );
+
+                if( isVertical )
+                    y = (Dimension)(y - offset);
+                else
+                    x = (Dimension)(x - offset);
 
-            XmToggleButtonSetState((Widget) widget, (Boolean) toggle, False);
+                XtVaSetValues( t->GetButtonWidget(),
+                               XmNx, x,
+                               XmNy, y,
+                               NULL );
+                break;
+            }
+            }
         }
     }
+
+    return true;
 }
 
-void wxToolBar::ClearTools()
+void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
 {
-    wxNode* node = m_widgets.First();
-    while (node)
-    {
-        Widget button = (Widget) node->Data();
-        XtDestroyWidget(button);
-        node = node->Next();
+    wxToolBarTool *tool = (wxToolBarTool *)toolBase;
+    if (tool->GetButtonWidget()){
+        XtSetSensitive(tool->GetButtonWidget(), (Boolean) enable);
+    } else if (wxTOOL_STYLE_CONTROL == tool->GetStyle()){
+        // Controls (such as wxChoice) do not have button widgets
+        tool->GetControl()->Enable(enable);
     }
-    m_widgets.Clear();
-    DestroyPixmaps();
-
-    wxToolBarBase::ClearTools();
 }
 
-void wxToolBar::DestroyPixmaps()
+void wxToolBar::DoToggleTool(wxToolBarToolBase *toolBase, bool toggle)
 {
-    wxNode* node = m_pixmaps.First();
-    while (node)
-    {
-        Pixmap pixmap = (Pixmap) node->Data();
-        XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) GetXDisplay()), pixmap);
-        node = node->Next();
-    }
-    m_pixmaps.Clear();
+    wxToolBarTool *tool = (wxToolBarTool *)toolBase;
+
+    XmToggleButtonSetState(tool->GetButtonWidget(), (Boolean) toggle, False);
 }
 
-// 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.
+void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
+                            bool WXUNUSED(toggle))
+{
+    // nothing to do
+}
 
-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)
+void wxToolBar::DoSetSize(int x, int y, int width, int height, int sizeFlags)
 {
-  wxToolBarTool *tool = new wxToolBarTool(index, bitmap, (wxBitmap *)NULL, toggle, xPos, yPos, helpString1, helpString2);
-  tool->m_clientData = clientData;
+    int old_width, old_height;
+    GetSize(&old_width, &old_height);
 
-  if (xPos > -1)
-    tool->m_x = xPos;
-  else
-    tool->m_x = m_xMargin;
+    // Correct width and height if needed.
+    if ( width == -1 || height == -1 )
+    {
+        wxSize defaultSize = GetSize();
 
-  if (yPos > -1)
-    tool->m_y = yPos;
-  else
-    tool->m_y = m_yMargin;
+        if ( width == -1 )
+            width = defaultSize.x;
+        if ( height == -1 )
+            height = defaultSize.y;
+    }
 
-  tool->SetSize(GetDefaultButtonWidth(), GetDefaultButtonHeight());
+    wxToolBarBase::DoSetSize(x, y, width, height, sizeFlags);
 
-  m_tools.Append((long)index, tool);
-  return tool;
+    // We must refresh the frame size when the toolbar changes size
+    // otherwise the toolbar can be shown incorrectly
+    if ( old_width != width || old_height != height )
+    {
+        // But before we send the size event check it
+        // we have a frame that is not being deleted.
+        wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
+        if ( frame && !frame->IsBeingDeleted() )
+        {
+            frame->SendSizeEvent();
+        }
+    }
 }
 
-int wxToolBar::FindIndexForWidget(WXWidget w)
+// ----------------------------------------------------------------------------
+// Motif callbacks
+// ----------------------------------------------------------------------------
+
+wxToolBarToolBase *wxToolBar::FindToolByWidget(WXWidget w) const
 {
-    wxNode* node = m_widgets.First();
-    while (node)
+    wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
+    while ( node )
     {
-        WXWidget widget = (WXWidget) node->Data();
-        if (widget == w)
-            return (int) node->key.integer;
-        node = node->Next();
+        wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
+        if ( tool->GetButtonWidget() == w)
+        {
+            return tool;
+        }
+
+        node = node->GetNext();
     }
-    return -1;
-}
 
-WXWidget wxToolBar::FindWidgetForIndex(int index)
-{
-    wxNode* node = m_widgets.Find((long) index);
-    if (!node)
-        return (WXWidget) 0;
-    else
-        return (WXWidget) node->Data();
+    return NULL;
 }
 
-void wxToolButtonCallback (Widget w, XtPointer clientData,
-                   XtPointer ptr)
+static void wxToolButtonCallback(Widget w,
+                                 XtPointer clientData,
+                                 XtPointer WXUNUSED(ptr))
 {
     wxToolBar *toolBar = (wxToolBar *) clientData;
-    int index = toolBar->FindIndexForWidget((WXWidget) w);
+    wxToolBarToolBase *tool = toolBar->FindToolByWidget((WXWidget) w);
+    if ( !tool )
+        return;
 
-    if (index != -1)
+    if ( tool->CanBeToggled() )
+        tool->Toggle();
+
+    if ( !toolBar->OnLeftClick(tool->GetId(), tool->IsToggled()) )
     {
-        wxNode *node = toolBar->GetTools().Find((long)index);
-        if (!node)
-            return;
-        wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-        if (tool->m_isToggle)
-            tool->m_toggleState = toolBar->GetToolState(index);
-
-        (void) toolBar->OnLeftClick(index, tool->m_toggleState);
+        // revert
+        tool->Toggle();
     }
-
-}
-
-// Creates a bitmap with transparent areas drawn in
-// the given colour.
-wxBitmap wxCreateMaskedBitmap(wxBitmap& bitmap, wxColour& colour)
-{
-    wxBitmap newBitmap(bitmap.GetWidth(),
-                       bitmap.GetHeight(),
-                       bitmap.GetDepth());
-    wxMemoryDC destDC;
-    wxMemoryDC srcDC;
-    srcDC.SelectObject(bitmap);
-    destDC.SelectObject(newBitmap);
-
-    wxBrush brush(colour, wxSOLID);
-    destDC.SetOptimization(FALSE);
-    destDC.SetBackground(brush);
-    destDC.Clear();
-    destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), & srcDC, 0, 0, wxCOPY, TRUE);
-
-    return newBitmap;
 }
 
 
-static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
-                     XEvent *event, Boolean *continue_to_dispatch)
+static void wxToolButtonPopupCallback(Widget w,
+                                      XtPointer client_data,
+                                      XEvent *event,
+                                      Boolean *WXUNUSED(continue_to_dispatch))
 {
     // TODO: retrieve delay before popping up tooltip from wxSystemSettings.
-    int delayMilli = 800;
+    static const int delayMilli = 800;
+
     wxToolBar* toolBar = (wxToolBar*) client_data;
+    wxToolBarToolBase *tool = toolBar->FindToolByWidget((WXWidget) w);
 
-    int index = toolBar->FindIndexForWidget((WXWidget) w);
+    if ( !tool )
+        return;
 
-    if (index != -1)
-    {
-        wxNode *node = toolBar->GetTools().Find((long)index);
-        if (!node)
-            return;
-        wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-        wxString str(toolBar->GetToolShortHelp(index));
-        if (str.IsNull() || str == "")
-            return;
+    wxString tooltip = tool->GetShortHelp();
+    if ( !tooltip )
+        return;
 
-        if (!wxTheToolBarTimer)
-          wxTheToolBarTimer = new wxToolBarTimer;
-
-       wxToolBarTimer::buttonWidget = w;
-       wxToolBarTimer::helpString = str;
+    if (!wxTheToolBarTimer)
+        wxTheToolBarTimer = new wxToolBarTimer;
 
+    wxToolBarTimer::buttonWidget = w;
+    wxToolBarTimer::helpString = tooltip;
 
     /************************************************************/
     /* Popup help label                                         */
@@ -503,11 +708,11 @@ static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
         {
             XtDestroyWidget (wxToolBarTimer::help_popup);
             XtPopdown (wxToolBarTimer::help_popup);
-       }
+        }
         wxToolBarTimer::help_popup = (Widget) 0;
 
         // One shot
-        wxTheToolBarTimer->Start(delayMilli, TRUE);
+        wxTheToolBarTimer->Start(delayMilli, true);
 
     }
     /************************************************************/
@@ -521,10 +726,9 @@ static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
         {
             XtDestroyWidget (wxToolBarTimer::help_popup);
             XtPopdown (wxToolBarTimer::help_popup);
-       }
+        }
         wxToolBarTimer::help_popup = (Widget) 0;
     }
-    }
 }
 
 void wxToolBarTimer::Notify()
@@ -534,44 +738,44 @@ void wxToolBarTimer::Notify()
         /************************************************************/
         /* Create shell without window decorations                  */
         /************************************************************/
-        help_popup = XtVaCreatePopupShell ("shell", 
-                                           overrideShellWidgetClass, (Widget) wxTheApp->GetTopLevelWidget(), 
+        help_popup = XtVaCreatePopupShell ("shell",
+                                           overrideShellWidgetClass, (Widget) wxTheApp->GetTopLevelWidget(),
                                            NULL);
 
         /************************************************************/
         /* Get absolute position on display of toolbar button       */
         /************************************************************/
         XtTranslateCoords (buttonWidget,
-                           (Position) 0, 
-                           (Position) 0, 
+                           (Position) 0,
+                           (Position) 0,
                            &x, &y);
 
         // Move the tooltip more or less above the button
         int yOffset = 20; // TODO: What should be really?
-        y -= yOffset;
+        y = (Position)(y - yOffset);
         if (y < yOffset) y = 0;
 
         /************************************************************/
         /* Set the position of the help popup                       */
         /************************************************************/
-        XtVaSetValues (help_popup, 
-                       XmNx, (Position) x, 
-                       XmNy, (Position) y, 
+        XtVaSetValues (help_popup,
+                       XmNx, (Position) x,
+                       XmNy, (Position) y,
                        NULL);
-        
+
         /************************************************************/
         /* Create help label                                        */
         /************************************************************/
         XmString text = XmStringCreateSimple ((char*) (const char*) helpString);
-        XtVaCreateManagedWidget ("help_label", 
-                                 xmLabelWidgetClass, help_popup, 
+        XtVaCreateManagedWidget ("help_label",
+                                 xmLabelWidgetClass, help_popup,
                                  XmNlabelString, text,
-                                 XtVaTypedArg, 
-                                 XmNforeground, XtRString, "black", 
-                                                strlen("black")+1,      
-                                 XtVaTypedArg, 
-                                 XmNbackground, XtRString, "LightGoldenrod", 
-                                                strlen("LightGoldenrod")+1, 
+                                 XtVaTypedArg,
+                                 XmNforeground, XtRString, "black",
+                                                strlen("black")+1,
+                                 XtVaTypedArg,
+                                 XmNbackground, XtRString, "LightGoldenrod",
+                                                strlen("LightGoldenrod")+1,
                                  NULL);
         XmStringFree (text);
 
@@ -580,4 +784,3 @@ void wxToolBarTimer::Notify()
         /************************************************************/
         XtPopup (help_popup, XtGrabNone);
 }
-