]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/tbarbase.cpp
fixing RTTI
[wxWidgets.git] / src / common / tbarbase.cpp
index 751873f2b36ee9c607706c091bf7df3ad7f16b47..2a33c1979bf8d61f340400252f8f3cc9c6dd090c 100644 (file)
 /////////////////////////////////////////////////////////////////////////////
-// Name:        tbarbase.cpp
-// Purpose:     Toolbar base classes
+// Name:        src/common/tbarbase.cpp
+// Purpose:     wxToolBarBase implementation
 // Author:      Julian Smart
-// Modified by:
+// Modified by: VZ at 11.12.99 (wxScrollableToolBar split off)
 // Created:     04/01/98
 // RCS-ID:      $Id$
-// Copyright:   (c) Julian Smart and Markus Holzem
-// Licence:       wxWindows license
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
-#pragma implementation "tbarbase.h"
-#endif
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-#pragma hdrstop
+    #pragma hdrstop
 #endif
 
-#ifndef WX_PRECOMP
-#include "wx/wx.h"
-#endif
+#if wxUSE_TOOLBAR
 
-#include "wx/frame.h"
+#include "wx/toolbar.h"
 
-// For ::UpdateWindow
-#ifdef __WXMSW__
-#include <windows.h>
+#ifndef WX_PRECOMP
+    #include "wx/control.h"
+    #include "wx/frame.h"
+    #include "wx/settings.h"
+    #if WXWIN_COMPATIBILITY_2_8
+        #include "wx/image.h"
+    #endif // WXWIN_COMPATIBILITY_2_8
+    #include "wx/menu.h"
 #endif
 
-#if wxUSE_TOOLBAR
-
-#include "wx/tbarbase.h"
+extern WXDLLEXPORT_DATA(const char) wxToolBarNameStr[] = "toolbar";
 
-#if !USE_SHARED_LIBRARY
-IMPLEMENT_ABSTRACT_CLASS(wxToolBarBase, wxControl)
-IMPLEMENT_DYNAMIC_CLASS(wxToolBarTool, wxObject)
+// ----------------------------------------------------------------------------
+// wxWidgets macros
+// ----------------------------------------------------------------------------
 
 BEGIN_EVENT_TABLE(wxToolBarBase, wxControl)
-  EVT_SCROLL(wxToolBarBase::OnScroll)
-  EVT_SIZE(wxToolBarBase::OnSize)
-  EVT_IDLE(wxToolBarBase::OnIdle)
 END_EVENT_TABLE()
-#endif
 
-// Keep a list of all toolbars created, so you can tell whether a toolbar
-// is still valid: a tool may have quit the toolbar.
-static wxList gs_ToolBars;
-
-#ifdef __WXGTK__
-wxToolBarTool::wxToolBarTool(wxToolBar *owner, int theIndex,
-                    const wxBitmap& theBitmap1, const  wxBitmap& theBitmap2,
-            bool toggle, wxObject *clientData,
-                 const wxString& helpS1, const wxString& helpS2,
-                    GtkWidget *item  )
-#else
-wxToolBarTool::wxToolBarTool(int theIndex,
-                    const wxBitmap& theBitmap1, const wxBitmap& theBitmap2, bool toggle,
-                    long xPos, long yPos, const wxString& helpS1, const wxString& helpS2)
-#endif
+#include "wx/listimpl.cpp"
+
+WX_DEFINE_LIST(wxToolBarToolsList)
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxToolBarToolBase
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxToolBarToolBase, wxObject)
+
+wxToolBarToolBase::~wxToolBarToolBase()
 {
-  m_toolStyle = wxTOOL_STYLE_BUTTON;
-#ifdef __WXGTK__
-  m_owner = owner;
-  m_item = item;
-  m_clientData = clientData;
-  m_x = 0;
-  m_y = 0;
-#else
-  m_clientData = NULL;
-  m_x = xPos;
-  m_y = yPos;
+#if wxUSE_MENUS
+    delete m_dropdownMenu;
 #endif
-  m_index = theIndex;
-  m_isToggle = toggle;
-  m_toggleState = FALSE;
-  m_enabled = TRUE;
-  m_bitmap1 = theBitmap1;
-  m_bitmap2 = theBitmap2;
-  m_width = m_height = 0;
-  m_deleteSecondBitmap = FALSE;
-  if (m_bitmap1.Ok())
-  {
-    m_width = m_bitmap1.GetWidth()+2;
-    m_height = m_bitmap1.GetHeight()+2;
-  }
-  m_shortHelpString = helpS1;
-  m_longHelpString = helpS2;
-}
-
-wxToolBarTool::~wxToolBarTool()
-{
-/*
-  if (m_deleteSecondBitmap && m_bitmap2)
-    delete m_bitmap2;
-*/
-}
-
-
-// class wxToolBar
-
-wxToolBarBase::wxToolBarBase(void) : m_tools(wxKEY_INTEGER)
-{
-  gs_ToolBars.Append(this);
-
-  m_maxRows = 1;
-  m_maxCols = 32000;
-  m_maxWidth = 0;
-  m_maxHeight = 0;
-  m_defaultWidth = 16;
-  m_defaultHeight = 15;
-  m_xMargin = 0;
-  m_yMargin = 0;
-  m_toolPacking = 1;
-  m_toolSeparation = 5;
-  m_currentTool = -1;
-
-  m_xScrollPixelsPerLine = 0;
-  m_yScrollPixelsPerLine = 0;
-  m_xScrollingEnabled = TRUE;
-  m_yScrollingEnabled = TRUE;
-  m_xScrollPosition = 0;
-  m_yScrollPosition = 0;
-  m_calcScrolledOffset = TRUE;
-  m_xScrollLines = 0;
-  m_yScrollLines = 0;
-  m_xScrollLinesPerPage = 0;
-  m_yScrollLinesPerPage = 0;
-}
-
-wxToolBarBase::~wxToolBarBase ()
-{
-  gs_ToolBars.DeleteObject(this);
-
-  for ( wxNode *node = m_tools.First(); node; node = node->Next() )
-  {
-    wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-    delete tool;
-  }
-}
-
-// Only allow toggle if returns TRUE
-bool wxToolBarBase::OnLeftClick(int toolIndex, bool toggleDown)
-{
-    wxCommandEvent event(wxEVT_COMMAND_TOOL_CLICKED, toolIndex);
-    event.SetEventObject(this);
-    event.SetExtraLong((long) toggleDown);
 
-    // Send events to this toolbar instead (and thence up the window hierarchy)
-    GetEventHandler()->ProcessEvent(event);
-
-    return TRUE;
+    if ( IsControl() )
+        GetControl()->Destroy();
 }
 
-// Call when right button down.
-void wxToolBarBase::OnRightClick(int toolIndex,
-                                 long WXUNUSED(x),
-                                 long WXUNUSED(y))
+
+bool wxToolBarToolBase::Enable(bool enable)
 {
-    wxCommandEvent event(wxEVT_COMMAND_TOOL_RCLICKED, toolIndex);
-    event.SetEventObject(this);
-    event.SetInt(toolIndex);
+    if ( m_enabled == enable )
+        return false;
 
-    GetEventHandler()->ProcessEvent(event);
+    m_enabled = enable;
+
+    return true;
 }
 
-// Called when the mouse cursor enters a tool bitmap (no button pressed).
-// Argument is -1 if mouse is exiting the toolbar.
-// Note that for this event, the id of the window is used,
-// and the integer parameter of wxCommandEvent is used to retrieve
-// the tool id.
-void wxToolBarBase::OnMouseEnter ( int toolIndex )
+bool wxToolBarToolBase::Toggle(bool toggle)
 {
-    wxCommandEvent event(wxEVT_COMMAND_TOOL_ENTER, GetId());
-    event.SetEventObject(this);
-    event.SetInt(toolIndex);
+    wxASSERT_MSG( CanBeToggled(), wxT("can't toggle this tool") );
 
-    GetEventHandler()->ProcessEvent(event);
+    if ( m_toggled == toggle )
+        return false;
+
+    m_toggled = toggle;
+
+    return true;
 }
 
-// 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.
-wxToolBarTool *wxToolBarBase::AddTool(int index, const wxBitmap& bitmap, const wxBitmap& pushedBitmap,
-             bool toggle, long xPos, long yPos, wxObject *clientData,
-             const wxString& helpString1, const wxString& helpString2)
+bool wxToolBarToolBase::SetToggle(bool toggle)
 {
-#ifdef __WXGTK__
-  wxToolBarTool *tool = new wxToolBarTool( (wxToolBar*)this, index, bitmap, pushedBitmap, toggle,
-                                           (wxObject*) NULL, helpString1, helpString2);
-#else
-  wxToolBarTool *tool = new wxToolBarTool(index, bitmap, pushedBitmap, toggle, xPos, yPos, helpString1, helpString2);
-#endif
-  tool->m_clientData = clientData;
+    wxItemKind kind = toggle ? wxITEM_CHECK : wxITEM_NORMAL;
+    if ( m_kind == kind )
+        return false;
 
-  if (xPos > -1)
-    tool->m_x = xPos;
-  else
-    tool->m_x = m_xMargin;
+    m_kind = kind;
 
-  if (yPos > -1)
-    tool->m_y = yPos;
-  else
-    tool->m_y = m_yMargin;
+    return true;
+}
 
-  // Calculate reasonable max size in case Layout() not called
-  if ((tool->m_x + bitmap.GetWidth() + m_xMargin) > m_maxWidth)
-    m_maxWidth = (tool->m_x + bitmap.GetWidth() + m_xMargin);
+bool wxToolBarToolBase::SetShortHelp(const wxString& help)
+{
+    if ( m_shortHelpString == help )
+        return false;
 
-  if ((tool->m_y + bitmap.GetHeight() + m_yMargin) > m_maxHeight)
-    m_maxHeight = (tool->m_y + bitmap.GetHeight() + m_yMargin);
+    m_shortHelpString = help;
 
-  m_tools.Append((long)index, tool);
-  return tool;
+    return true;
 }
 
-void wxToolBarBase::AddSeparator ()
+bool wxToolBarToolBase::SetLongHelp(const wxString& help)
 {
-  wxToolBarTool *tool = new wxToolBarTool;
-  tool->m_index = -1;
-  tool->m_toolStyle = wxTOOL_STYLE_SEPARATOR;
-  m_tools.Append(-1, tool);
+    if ( m_longHelpString == help )
+        return false;
+
+    m_longHelpString = help;
+
+    return true;
 }
 
-void wxToolBarBase::ClearTools()
+
+#if wxUSE_MENUS
+void wxToolBarToolBase::SetDropdownMenu(wxMenu* menu)
 {
-  m_pressedTool = m_currentTool = -1;
-  wxNode *node = m_tools.First();
-  while (node)
-  {
-    wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-    wxNode *nextNode = node->Next();
-    delete tool;
-    delete node;
-    node = nextNode;
-  }
+    delete m_dropdownMenu;
+    m_dropdownMenu = menu;
 }
+#endif
+
 
-void wxToolBarBase::EnableTool(int index, bool enable)
+// ----------------------------------------------------------------------------
+// wxToolBarBase adding/deleting items
+// ----------------------------------------------------------------------------
+
+wxToolBarBase::wxToolBarBase()
 {
-  wxNode *node = m_tools.Find((long)index);
-  if (node)
-  {
-    wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-    if (tool)
-      tool->m_enabled = enable;
-  }
+    // the list owns the pointers
+    m_xMargin = m_yMargin = 0;
+    m_maxRows = m_maxCols = 0;
+    m_toolPacking = m_toolSeparation = 0;
+    m_defaultWidth = 16;
+    m_defaultHeight = 15;
 }
 
-void wxToolBarBase::ToggleTool(int WXUNUSED(index),
-                               bool WXUNUSED(toggle))
+void wxToolBarBase::FixupStyle()
 {
+    if ( !HasFlag(wxTB_TOP | wxTB_LEFT | wxTB_RIGHT | wxTB_BOTTOM) )
+    {
+        // this is the default
+        m_windowStyle |= wxTB_TOP;
+    }
 }
 
-void wxToolBarBase::SetToggle(int index, bool value)
+wxToolBarToolBase *wxToolBarBase::DoAddTool(int toolid,
+                                            const wxString& label,
+                                            const wxBitmap& bitmap,
+                                            const wxBitmap& bmpDisabled,
+                                            wxItemKind kind,
+                                            const wxString& shortHelp,
+                                            const wxString& longHelp,
+                                            wxObject *clientData,
+                                            wxCoord WXUNUSED(xPos),
+                                            wxCoord WXUNUSED(yPos))
 {
-  wxNode *node=m_tools.Find((long)index);
-  if (node){
-    wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-    tool->m_isToggle = value;
-  }
+    InvalidateBestSize();
+    return InsertTool(GetToolsCount(), toolid, label, bitmap, bmpDisabled,
+                      kind, shortHelp, longHelp, clientData);
 }
 
-bool wxToolBarBase::GetToolState(int index) const
+wxToolBarToolBase *wxToolBarBase::InsertTool(size_t pos,
+                                             int toolid,
+                                             const wxString& label,
+                                             const wxBitmap& bitmap,
+                                             const wxBitmap& bmpDisabled,
+                                             wxItemKind kind,
+                                             const wxString& shortHelp,
+                                             const wxString& longHelp,
+                                             wxObject *clientData)
 {
-  wxNode *node = m_tools.Find((long)index);
-  if (node)
-  {
-    wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-    if (tool)
-    {
-      return tool->m_toggleState;
-    }
-    else return FALSE;
-  }
-  else return FALSE;
+    wxCHECK_MSG( pos <= GetToolsCount(), NULL,
+                 wxT("invalid position in wxToolBar::InsertTool()") );
+
+    return DoInsertNewTool(pos, CreateTool(toolid, label, bitmap, bmpDisabled, kind,
+                                           clientData, shortHelp, longHelp));
 }
 
-bool wxToolBarBase::GetToolEnabled(int index) const
+wxToolBarToolBase *wxToolBarBase::AddTool(wxToolBarToolBase *tool)
 {
-  wxNode *node = m_tools.Find((long)index);
-  if (node)
-  {
-    wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-    if (tool)
-    {
-      return tool->m_enabled;
-    }
-    else return FALSE;
-  }
-  else return FALSE;
+    return InsertTool(GetToolsCount(), tool);
 }
 
-wxObject *wxToolBarBase::GetToolClientData(int index) const
+wxToolBarToolBase *
+wxToolBarBase::InsertTool(size_t pos, wxToolBarToolBase *tool)
 {
-  wxNode *node = m_tools.Find((long)index);
-  if (node)
-  {
-    wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-    if (tool)
+    wxCHECK_MSG( pos <= GetToolsCount(), NULL,
+                 wxT("invalid position in wxToolBar::InsertTool()") );
+
+    if ( !tool || !DoInsertTool(pos, tool) )
     {
-      return tool->m_clientData;
+        return NULL;
     }
-    else return NULL;
-  }
-  else return NULL;
+
+    m_tools.Insert(pos, tool);
+    tool->Attach(this);
+
+    return tool;
 }
 
-void wxToolBarBase::SetToolShortHelp(int index, const wxString& helpString)
+wxToolBarToolBase *
+wxToolBarBase::AddControl(wxControl *control, const wxString& label)
 {
-  wxNode *node=m_tools.Find((long)index);
-  if (node)
-  {
-    wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-    tool->m_shortHelpString = helpString;
-  }
+    return InsertControl(GetToolsCount(), control, label);
 }
 
-wxString wxToolBarBase::GetToolShortHelp(int index) const
+wxToolBarToolBase *
+wxToolBarBase::InsertControl(size_t pos,
+                             wxControl *control,
+                             const wxString& label)
 {
-  wxNode *node=m_tools.Find((long)index);
-  if (node)
-  {
-    wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-    return tool->m_shortHelpString;
-  }
-  else
-    return wxString("");
+    wxCHECK_MSG( control, NULL,
+                 wxT("toolbar: can't insert NULL control") );
+
+    wxCHECK_MSG( control->GetParent() == this, NULL,
+                 wxT("control must have toolbar as parent") );
+
+    return DoInsertNewTool(pos, CreateTool(control, label));
 }
 
-void wxToolBarBase::SetToolLongHelp(int index, const wxString& helpString)
+wxControl *wxToolBarBase::FindControl( int toolid )
 {
-  wxNode *node=m_tools.Find((long)index);
-  if (node)
-  {
-    wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-    tool->m_longHelpString = helpString;
-  }
+    for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        const wxToolBarToolBase * const tool = node->GetData();
+        if ( tool->IsControl() )
+        {
+            wxControl * const control = tool->GetControl();
+
+            if ( !control )
+            {
+                wxFAIL_MSG( wxT("NULL control in toolbar?") );
+            }
+            else if ( control->GetId() == toolid )
+            {
+                // found
+                return control;
+            }
+        }
+    }
+
+   return NULL;
 }
 
-wxString wxToolBarBase::GetToolLongHelp(int index) const
+wxToolBarToolBase *wxToolBarBase::AddSeparator()
 {
-  wxNode *node=m_tools.Find((long)index);
-  if (node)
-  {
-    wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-    return tool->m_longHelpString;
-  }
-  else
-    return wxString("");
+    return InsertSeparator(GetToolsCount());
 }
 
-wxToolBarTool *wxToolBarBase::FindToolForPosition(long x, long y) const
+wxToolBarToolBase *wxToolBarBase::InsertSeparator(size_t pos)
 {
-  wxNode *node = m_tools.First();
-  while (node)
-  {
-    wxToolBarTool *tool = (wxToolBarTool *)node->Data();
-    if ((x >= tool->m_x) && (y >= tool->m_y) &&
-        (x <= (tool->m_x + tool->GetWidth())) &&
-        (y <= (tool->m_y + tool->GetHeight())))
-      return tool;
-
-    node = node->Next();
-  }
-  return NULL;
+    return DoInsertNewTool(pos, CreateSeparator());
 }
 
-wxSize wxToolBarBase::GetMaxSize ( void ) const
+wxToolBarToolBase *wxToolBarBase::AddStretchableSpace()
 {
-  return wxSize(m_maxWidth, m_maxHeight);
+    return InsertStretchableSpace(GetToolsCount());
 }
 
-// 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 wxToolBarBase::SetMargins(int x, int y)
+wxToolBarToolBase *wxToolBarBase::InsertStretchableSpace(size_t pos)
 {
-  m_xMargin = x;
-  m_yMargin = y;
+    wxToolBarToolBase * const tool = CreateSeparator();
+    if ( tool )
+    {
+        // this is a hack but we know that all the current implementations
+        // don't really use the tool when it's created, they will do it
+        // InsertTool() at earliest and maybe even in Realize() much later
+        //
+        // so we can create the tool as a plain separator and mark it as being
+        // a stretchable space later
+        tool->MakeStretchable();
+    }
+
+    return DoInsertNewTool(pos, tool);
 }
 
-void wxToolBarBase::SetToolPacking(int packing)
+wxToolBarToolBase *wxToolBarBase::RemoveTool(int toolid)
 {
-  m_toolPacking = packing;
+    size_t pos = 0;
+    wxToolBarToolsList::compatibility_iterator node;
+    for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
+    {
+        if ( node->GetData()->GetId() == toolid )
+            break;
+
+        pos++;
+    }
+
+    if ( !node )
+    {
+        // don't give any error messages - sometimes we might call RemoveTool()
+        // without knowing whether the tool is or not in the toolbar
+        return NULL;
+    }
+
+    wxToolBarToolBase *tool = node->GetData();
+    wxCHECK_MSG( tool, NULL, "NULL tool in the tools list?" );
+
+    if ( !DoDeleteTool(pos, tool) )
+        return NULL;
+
+    m_tools.Erase(node);
+
+    tool->Detach();
+
+    return tool;
 }
 
-void wxToolBarBase::SetToolSeparation(int separation)
+bool wxToolBarBase::DeleteToolByPos(size_t pos)
 {
-  m_toolSeparation = separation;
+    wxCHECK_MSG( pos < GetToolsCount(), false,
+                 wxT("invalid position in wxToolBar::DeleteToolByPos()") );
+
+    wxToolBarToolsList::compatibility_iterator node = m_tools.Item(pos);
+
+    if ( !DoDeleteTool(pos, node->GetData()) )
+    {
+        return false;
+    }
+
+    delete node->GetData();
+    m_tools.Erase(node);
+
+    return true;
 }
 
-void wxToolBarBase::Command(wxCommandEvent& WXUNUSED(event))
+bool wxToolBarBase::DeleteTool(int toolid)
 {
+    size_t pos = 0;
+    wxToolBarToolsList::compatibility_iterator node;
+    for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
+    {
+        if ( node->GetData()->GetId() == toolid )
+            break;
+
+        pos++;
+    }
+
+    if ( !node || !DoDeleteTool(pos, node->GetData()) )
+    {
+        return false;
+    }
+
+    delete node->GetData();
+    m_tools.Erase(node);
+
+    return true;
 }
 
-void wxToolBarBase::LayoutTools()
+wxToolBarToolBase *wxToolBarBase::FindById(int toolid) const
 {
-}
+    wxToolBarToolBase *tool = NULL;
 
+    for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        tool = node->GetData();
+        if ( tool->GetId() == toolid )
+        {
+            // found
+            break;
+        }
 
-// SCROLLING IMPLEMENTATION
+        tool = NULL;
+    }
+
+    return tool;
+}
 
-/*
- * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line)
- * noUnitsX/noUnitsY:        : no. units per scrollbar
- */
-void wxToolBarBase::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY,
-           int noUnitsX, int noUnitsY,
-           int xPos, int yPos)
+void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase *tool)
 {
-      m_xScrollPixelsPerLine = pixelsPerUnitX;
-      m_yScrollPixelsPerLine = pixelsPerUnitY;
-      m_xScrollLines = noUnitsX;
-      m_yScrollLines = noUnitsY;
+    wxCHECK_RET( tool, wxT("NULL tool in wxToolBarTool::UnToggleRadioGroup") );
 
-      int w, h;
-      GetSize(&w, &h);
+    if ( !tool->IsButton() || tool->GetKind() != wxITEM_RADIO )
+        return;
 
-      // Recalculate scroll bar range and position
-    if (m_xScrollLines > 0)
-    {
-      m_xScrollPosition = xPos;
-      SetScrollPos (wxHORIZONTAL, m_xScrollPosition, TRUE);
-    }
-    else
+    wxToolBarToolsList::compatibility_iterator node = m_tools.Find(tool);
+    wxCHECK_RET( node, wxT("invalid tool in wxToolBarTool::UnToggleRadioGroup") );
+
+    wxToolBarToolsList::compatibility_iterator nodeNext = node->GetNext();
+    while ( nodeNext )
     {
-      SetScrollbar(wxHORIZONTAL, 0, 0, 0, FALSE);
-      m_xScrollPosition = 0;
+        wxToolBarToolBase *toolNext = nodeNext->GetData();
+
+        if ( !toolNext->IsButton() || toolNext->GetKind() != wxITEM_RADIO )
+            break;
+
+        if ( toolNext->Toggle(false) )
+        {
+            DoToggleTool(toolNext, false);
+        }
+
+        nodeNext = nodeNext->GetNext();
     }
 
-    if (m_yScrollLines > 0)
+    wxToolBarToolsList::compatibility_iterator nodePrev = node->GetPrevious();
+    while ( nodePrev )
     {
-      m_yScrollPosition = yPos;
-      SetScrollPos (wxVERTICAL, m_yScrollPosition, TRUE);
+        wxToolBarToolBase *toolNext = nodePrev->GetData();
+
+        if ( !toolNext->IsButton() || toolNext->GetKind() != wxITEM_RADIO )
+            break;
+
+        if ( toolNext->Toggle(false) )
+        {
+            DoToggleTool(toolNext, false);
+        }
+
+        nodePrev = nodePrev->GetPrevious();
     }
-    else
+}
+
+void wxToolBarBase::ClearTools()
+{
+    while ( GetToolsCount() )
     {
-      SetScrollbar(wxVERTICAL, 0, 0, 0, FALSE);
-      m_yScrollPosition = 0;
+        DeleteToolByPos(0);
     }
-    AdjustScrollbars();
-    Refresh();
-#ifdef __WXMSW__
-    ::UpdateWindow ((HWND) GetHWND());
-#endif
 }
 
+void wxToolBarBase::AdjustToolBitmapSize()
+{
+    const wxSize sizeOrig(m_defaultWidth, m_defaultHeight);
+
+    wxSize sizeActual(sizeOrig);
 
-void wxToolBarBase::OnScroll(wxScrollEvent& event)
-{
-  int orient = event.GetOrientation();
-
-  int nScrollInc = CalcScrollInc(event);
-  if (nScrollInc == 0)
-    return;
-
-  if (orient == wxHORIZONTAL)
-  {
-    int newPos = m_xScrollPosition + nScrollInc;
-    SetScrollPos(wxHORIZONTAL, newPos, TRUE );
-  }
-  else
-  {
-    int newPos = m_yScrollPosition + nScrollInc;
-    SetScrollPos(wxVERTICAL, newPos, TRUE );
-  }
-
-  if (orient == wxHORIZONTAL)
-  {
-    if (m_xScrollingEnabled)
-      ScrollWindow(-m_xScrollPixelsPerLine * nScrollInc, 0, NULL);
-    else
-      Refresh();
-  }
-  else
-  {
-    if (m_yScrollingEnabled)
-      ScrollWindow(0, -m_yScrollPixelsPerLine * nScrollInc, NULL);
-    else
-      Refresh();
-  }
-
-  if (orient == wxHORIZONTAL)
-  {
-    m_xScrollPosition += nScrollInc;
-  }
-  else
-  {
-    m_yScrollPosition += nScrollInc;
-  }
-
-}
-
-int wxToolBarBase::CalcScrollInc(wxScrollEvent& event)
-{
-  int pos = event.GetPosition();
-  int orient = event.GetOrientation();
-
-  int nScrollInc = 0;
-  switch (event.GetEventType())
-  {
-    case wxEVT_SCROLL_TOP:
+    for ( wxToolBarToolsList::const_iterator i = m_tools.begin();
+          i != m_tools.end();
+          ++i )
     {
-      if (orient == wxHORIZONTAL)
-        nScrollInc = - m_xScrollPosition;
-      else
-        nScrollInc = - m_yScrollPosition;
-      break;
+        const wxBitmap& bmp = (*i)->GetNormalBitmap();
+        if ( bmp.IsOk() )
+            sizeActual.IncTo(bmp.GetSize());
     }
-    case wxEVT_SCROLL_BOTTOM:
+
+    if ( sizeActual != sizeOrig )
+        SetToolBitmapSize(sizeActual);
+}
+
+bool wxToolBarBase::Realize()
+{
+    // check if we have anything to do
+    if ( m_tools.empty() )
+        return false;
+
+    // make sure tool size is large enough for all bitmaps to fit in
+    AdjustToolBitmapSize();
+
+    return true;
+}
+
+wxToolBarBase::~wxToolBarBase()
+{
+    WX_CLEAR_LIST(wxToolBarToolsList, m_tools);
+
+    // notify the frame that it doesn't have a tool bar any longer to avoid
+    // dangling pointers
+    wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
+    if ( frame && frame->GetToolBar() == this )
     {
-      if (orient == wxHORIZONTAL)
-        nScrollInc = m_xScrollLines - m_xScrollPosition;
-      else
-        nScrollInc = m_yScrollLines - m_yScrollPosition;
-      break;
+        frame->SetToolBar(NULL);
     }
-    case wxEVT_SCROLL_LINEUP:
+}
+
+// ----------------------------------------------------------------------------
+// wxToolBarBase tools state
+// ----------------------------------------------------------------------------
+
+void wxToolBarBase::EnableTool(int toolid, bool enable)
+{
+    wxToolBarToolBase *tool = FindById(toolid);
+    if ( tool )
     {
-      nScrollInc = -1;
-      break;
+        if ( tool->Enable(enable) )
+        {
+            DoEnableTool(tool, enable);
+        }
     }
-    case wxEVT_SCROLL_LINEDOWN:
+}
+
+void wxToolBarBase::ToggleTool(int toolid, bool toggle)
+{
+    wxToolBarToolBase *tool = FindById(toolid);
+    if ( tool && tool->CanBeToggled() )
     {
-      nScrollInc = 1;
-      break;
+        if ( tool->Toggle(toggle) )
+        {
+            UnToggleRadioGroup(tool);
+            DoToggleTool(tool, toggle);
+        }
     }
-    case wxEVT_SCROLL_PAGEUP:
+}
+
+void wxToolBarBase::SetToggle(int toolid, bool toggle)
+{
+    wxToolBarToolBase *tool = FindById(toolid);
+    if ( tool )
     {
-      if (orient == wxHORIZONTAL)
-        nScrollInc = -GetScrollPageSize(wxHORIZONTAL);
-      else
-        nScrollInc = -GetScrollPageSize(wxVERTICAL);
-      break;
+        if ( tool->SetToggle(toggle) )
+        {
+            DoSetToggle(tool, toggle);
+        }
     }
-    case wxEVT_SCROLL_PAGEDOWN:
+}
+
+void wxToolBarBase::SetToolShortHelp(int toolid, const wxString& help)
+{
+    wxToolBarToolBase *tool = FindById(toolid);
+    if ( tool )
     {
-      if (orient == wxHORIZONTAL)
-        nScrollInc = GetScrollPageSize(wxHORIZONTAL);
-      else
-        nScrollInc = GetScrollPageSize(wxVERTICAL);
-      break;
+        (void)tool->SetShortHelp(help);
     }
-    case wxEVT_SCROLL_THUMBTRACK:
+}
+
+void wxToolBarBase::SetToolLongHelp(int toolid, const wxString& help)
+{
+    wxToolBarToolBase *tool = FindById(toolid);
+    if ( tool )
     {
-      if (orient == wxHORIZONTAL)
-        nScrollInc = pos - m_xScrollPosition;
-      else
-        nScrollInc = pos - m_yScrollPosition;
-      break;
+        (void)tool->SetLongHelp(help);
     }
-    default:
+}
+
+wxObject *wxToolBarBase::GetToolClientData(int toolid) const
+{
+    wxToolBarToolBase *tool = FindById(toolid);
+
+    return tool ? tool->GetClientData() : NULL;
+}
+
+void wxToolBarBase::SetToolClientData(int toolid, wxObject *clientData)
+{
+    wxToolBarToolBase *tool = FindById(toolid);
+
+    wxCHECK_RET( tool, wxT("no such tool in wxToolBar::SetToolClientData") );
+
+    tool->SetClientData(clientData);
+}
+
+int wxToolBarBase::GetToolPos(int toolid) const
+{
+    size_t pos = 0;
+    wxToolBarToolsList::compatibility_iterator node;
+
+    for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
     {
-      break;
+        if ( node->GetData()->GetId() == toolid )
+            return pos;
+
+        pos++;
     }
-  }
-  if (orient == wxHORIZONTAL)
-  {
-        int w, h;
-        GetClientSize(&w, &h);
-
-        int nMaxWidth = m_xScrollLines*m_xScrollPixelsPerLine;
-        int noPositions = (int) ( ((nMaxWidth - w)/(float)m_xScrollPixelsPerLine) + 0.5 );
-        if (noPositions < 0)
-              noPositions = 0;
-
-        if ( (m_xScrollPosition + nScrollInc) < 0 )
-            nScrollInc = -m_xScrollPosition; // As -ve as we can go
-        else if ( (m_xScrollPosition + nScrollInc) > noPositions )
-            nScrollInc = noPositions - m_xScrollPosition; // As +ve as we can go
-
-        return nScrollInc;
-  }
-  else
-  {
-        int w, h;
-        GetClientSize(&w, &h);
-
-        int nMaxHeight = m_yScrollLines*m_yScrollPixelsPerLine;
-        int noPositions = (int) ( ((nMaxHeight - h)/(float)m_yScrollPixelsPerLine) + 0.5 );
-        if (noPositions < 0)
-              noPositions = 0;
-
-        if ( (m_yScrollPosition + nScrollInc) < 0 )
-            nScrollInc = -m_yScrollPosition; // As -ve as we can go
-        else if ( (m_yScrollPosition + nScrollInc) > noPositions )
-            nScrollInc = noPositions - m_yScrollPosition; // As +ve as we can go
-
-        return nScrollInc;
-  }
-}
-
-// Adjust the scrollbars - new version.
-void wxToolBarBase::AdjustScrollbars()
-{
-  int w, h;
-  GetClientSize(&w, &h);
-
-  // Recalculate scroll bar range and position
-  if (m_xScrollLines > 0)
-  {
-    int nMaxWidth = m_xScrollLines*m_xScrollPixelsPerLine;
-    int newRange = (int) ( ((nMaxWidth)/(float)m_xScrollPixelsPerLine) + 0.5 );
-    if (newRange < 0)
-      newRange = 0;
-
-    m_xScrollPosition = wxMin(newRange, m_xScrollPosition);
-
-    // Calculate page size i.e. number of scroll units you get on the
-    // current client window
-    int noPagePositions = (int) ( (w/(float)m_xScrollPixelsPerLine) + 0.5 );
-    if (noPagePositions < 1)
-      noPagePositions = 1;
-
-    SetScrollbar(wxHORIZONTAL, m_xScrollPosition, noPagePositions, newRange);
-    SetScrollPageSize(wxHORIZONTAL, noPagePositions);
-  }
-  if (m_yScrollLines > 0)
-  {
-    int nMaxHeight = m_yScrollLines*m_yScrollPixelsPerLine;
-    int newRange = (int) ( ((nMaxHeight)/(float)m_yScrollPixelsPerLine) + 0.5 );
-    if (newRange < 0)
-      newRange = 0;
-
-    m_yScrollPosition = wxMin(newRange, m_yScrollPosition);
-
-    // Calculate page size i.e. number of scroll units you get on the
-    // current client window
-    int noPagePositions = (int) ( (h/(float)m_yScrollPixelsPerLine) + 0.5 );
-    if (noPagePositions < 1)
-      noPagePositions = 1;
-
-    SetScrollbar(wxVERTICAL, m_yScrollPosition, noPagePositions, newRange);
-    SetScrollPageSize(wxVERTICAL, noPagePositions);
-  }
-}
-
-// Default OnSize resets scrollbars, if any
-void wxToolBarBase::OnSize(wxSizeEvent& WXUNUSED(event))
-{
-#if wxUSE_CONSTRAINTS
-  if (GetAutoLayout())
-    Layout();
-#endif
 
-  AdjustScrollbars();
+    return wxNOT_FOUND;
 }
 
-// Prepare the DC by translating it according to the current scroll position
-void wxToolBarBase::PrepareDC(wxDC& dc)
+bool wxToolBarBase::GetToolState(int toolid) const
 {
-    dc.SetDeviceOrigin(- m_xScrollPosition * m_xScrollPixelsPerLine, - m_yScrollPosition * m_yScrollPixelsPerLine);
+    wxToolBarToolBase *tool = FindById(toolid);
+    wxCHECK_MSG( tool, false, wxT("no such tool") );
+
+    return tool->IsToggled();
 }
 
-void wxToolBarBase::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const
+bool wxToolBarBase::GetToolEnabled(int toolid) const
 {
-      *x_unit = m_xScrollPixelsPerLine;
-      *y_unit = m_yScrollPixelsPerLine;
+    wxToolBarToolBase *tool = FindById(toolid);
+    wxCHECK_MSG( tool, false, wxT("no such tool") );
+
+    return tool->IsEnabled();
 }
 
-int wxToolBarBase::GetScrollPageSize(int orient) const
+wxString wxToolBarBase::GetToolShortHelp(int toolid) const
 {
-    if ( orient == wxHORIZONTAL )
-        return m_xScrollLinesPerPage;
-    else
-        return m_yScrollLinesPerPage;
+    wxToolBarToolBase *tool = FindById(toolid);
+    wxCHECK_MSG( tool, wxEmptyString, wxT("no such tool") );
+
+    return tool->GetShortHelp();
 }
 
-void wxToolBarBase::SetScrollPageSize(int orient, int pageSize)
+wxString wxToolBarBase::GetToolLongHelp(int toolid) const
 {
-    if ( orient == wxHORIZONTAL )
-        m_xScrollLinesPerPage = pageSize;
-    else
-        m_yScrollLinesPerPage = pageSize;
+    wxToolBarToolBase *tool = FindById(toolid);
+    wxCHECK_MSG( tool, wxEmptyString, wxT("no such tool") );
+
+    return tool->GetLongHelp();
 }
 
-/*
- * Scroll to given position (scroll position, not pixel position)
- */
-void wxToolBarBase::Scroll (int x_pos, int y_pos)
+// ----------------------------------------------------------------------------
+// wxToolBarBase geometry
+// ----------------------------------------------------------------------------
+
+void wxToolBarBase::SetMargins(int x, int y)
 {
-  int old_x, old_y;
-  ViewStart (&old_x, &old_y);
-  if (((x_pos == -1) || (x_pos == old_x)) && ((y_pos == -1) || (y_pos == old_y)))
-    return;
+    m_xMargin = x;
+    m_yMargin = y;
+}
 
-  if (x_pos > -1)
-    {
-      m_xScrollPosition = x_pos;
-      SetScrollPos (wxHORIZONTAL, x_pos, TRUE);
-    }
-  if (y_pos > -1)
-    {
-      m_yScrollPosition = y_pos;
-      SetScrollPos (wxVERTICAL, y_pos, TRUE);
-    }
-  Refresh();
-#ifdef __WXMSW__
-  UpdateWindow ((HWND) GetHWND());
-#endif
+void wxToolBarBase::SetRows(int WXUNUSED(nRows))
+{
+    // nothing
 }
 
-void wxToolBarBase::EnableScrolling (bool x_scroll, bool y_scroll)
+bool wxToolBarBase::IsVertical() const
 {
-  m_xScrollingEnabled = x_scroll;
-  m_yScrollingEnabled = y_scroll;
+    return HasFlag(wxTB_LEFT | wxTB_RIGHT);
 }
 
-void wxToolBarBase::GetVirtualSize (int *x, int *y) const
+
+// ----------------------------------------------------------------------------
+// event processing
+// ----------------------------------------------------------------------------
+
+// Only allow toggle if returns true
+bool wxToolBarBase::OnLeftClick(int toolid, bool toggleDown)
 {
-      *x = m_xScrollPixelsPerLine * m_xScrollLines;
-      *y = m_yScrollPixelsPerLine * m_yScrollLines;
+    wxCommandEvent event(wxEVT_COMMAND_TOOL_CLICKED, toolid);
+    event.SetEventObject(this);
+
+    // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
+    event.SetInt((int)toggleDown);
+
+    // and SetExtraLong() for backwards compatibility
+    event.SetExtraLong((long)toggleDown);
+
+    // Send events to this toolbar instead (and thence up the window hierarchy)
+    HandleWindowEvent(event);
+
+    return true;
 }
 
-// Where the current view starts from
-void wxToolBarBase::ViewStart (int *x, int *y) const
+// Call when right button down.
+void wxToolBarBase::OnRightClick(int toolid,
+                                 long WXUNUSED(x),
+                                 long WXUNUSED(y))
 {
-  *x = m_xScrollPosition;
-  *y = m_yScrollPosition;
+    wxCommandEvent event(wxEVT_COMMAND_TOOL_RCLICKED, toolid);
+    event.SetEventObject(this);
+    event.SetInt(toolid);
+
+    GetEventHandler()->ProcessEvent(event);
 }
 
-void wxToolBarBase::OnIdle(wxIdleEvent&
-#ifdef __WXGTK__
-                            WXUNUSED(event)
-#else
-                            event
-#endif
-                          )
+// Called when the mouse cursor enters a tool bitmap (no button pressed).
+// Argument is wxID_ANY if mouse is exiting the toolbar.
+// Note that for this event, the toolid of the window is used,
+// and the integer parameter of wxCommandEvent is used to retrieve
+// the tool toolid.
+void wxToolBarBase::OnMouseEnter(int toolid)
 {
-#ifndef __WXGTK__
-    wxWindow::OnIdle(event);
-#endif
+    wxCommandEvent event(wxEVT_COMMAND_TOOL_ENTER, GetId());
+    event.SetEventObject(this);
+    event.SetInt(toolid);
+
+    wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
+    if ( frame )
+    {
+        wxString help;
+        if ( toolid != wxID_ANY )
+        {
+           const wxToolBarToolBase * const tool = FindById(toolid);
+           if ( tool )
+               help = tool->GetLongHelp();
+        }
+
+        // call DoGiveHelp() even if help string is empty to avoid showing the
+        // help for the previously selected tool when another one is selected
+        frame->DoGiveHelp(help, toolid != wxID_ANY);
+    }
 
-    DoToolbarUpdates();
+    (void)GetEventHandler()->ProcessEvent(event);
 }
 
+// ----------------------------------------------------------------------------
+// UI updates
+// ----------------------------------------------------------------------------
+
 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
-void wxToolBarBase::DoToolbarUpdates()
+void wxToolBarBase::UpdateWindowUI(long flags)
 {
+    wxWindowBase::UpdateWindowUI(flags);
+
+    // don't waste time updating state of tools in a hidden toolbar
+    if ( !IsShown() )
+        return;
+
     wxEvtHandler* evtHandler = GetEventHandler() ;
 
-    wxNode* node = GetTools().First();
-    while (node)
+    for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
+          node;
+          node = node->GetNext() )
     {
-        wxToolBarTool* tool = (wxToolBarTool* ) node->Data();
+        wxToolBarToolBase * const tool = node->GetData();
+        if ( tool->IsSeparator() )
+            continue;
 
-        wxUpdateUIEvent event(tool->m_index);
+        int toolid = tool->GetId();
+
+        wxUpdateUIEvent event(toolid);
         event.SetEventObject(this);
 
-        if (evtHandler->ProcessEvent(event))
+        if ( evtHandler->ProcessEvent(event) )
         {
-            if (event.GetSetEnabled())
-                EnableTool(tool->m_index, event.GetEnabled());
-            if (event.GetSetChecked())
-                ToggleTool(tool->m_index, event.GetChecked());
-/*
-            if (event.GetSetText())
+            if ( event.GetSetEnabled() )
+                EnableTool(toolid, event.GetEnabled());
+            if ( event.GetSetChecked() )
+                ToggleTool(toolid, event.GetChecked());
+#if 0
+            if ( event.GetSetText() )
                 // Set tooltip?
-*/
+#endif // 0
         }
-
-        node = node->Next();
     }
 }
 
+#if wxUSE_MENUS
+bool wxToolBarBase::SetDropdownMenu(int toolid, wxMenu* menu)
+{
+    wxToolBarToolBase * const tool = FindById(toolid);
+    wxCHECK_MSG( tool, false, wxT("invalid tool toolid") );
+
+    wxCHECK_MSG( tool->GetKind() == wxITEM_DROPDOWN, false,
+                    wxT("menu can be only associated with drop down tools") );
+
+    tool->SetDropdownMenu(menu);
+
+    return true;
+}
 #endif
+
+#if WXWIN_COMPATIBILITY_2_8
+
+bool wxCreateGreyedImage(const wxImage& in, wxImage& out)
+{
+#if wxUSE_IMAGE
+    out = in.ConvertToGreyscale();
+    if ( out.IsOk() )
+        return true;
+#endif // wxUSE_IMAGE
+    return false;
+}
+
+#endif // WXWIN_COMPATIBILITY_2_8
+
+#endif // wxUSE_TOOLBAR