/////////////////////////////////////////////////////////////////////////////
-// 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
-// For ::UpdateWindow
-#ifdef __WXMSW__
-#include <windows.h>
-#endif
+#include "wx/toolbar.h"
-#if USE_TOOLBAR
+#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
-#include "wx/tbarbase.h"
+extern WXDLLEXPORT_DATA(const char) wxToolBarNameStr[] = "toolbar";
-#if !USE_SHARED_LIBRARY
-IMPLEMENT_DYNAMIC_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;
-
-wxToolBarTool::wxToolBarTool(int theIndex,
- const wxBitmap& theBitmap1, const wxBitmap& theBitmap2, bool toggle,
- long xPos, long yPos, const wxString& helpS1, const wxString& helpS2)
-{
- m_toolStyle = wxTOOL_STYLE_BUTTON;
- m_clientData = NULL;
- m_index = theIndex;
- m_isToggle = toggle;
- m_toggleState = FALSE;
- m_enabled = TRUE;
- m_bitmap1 = theBitmap1;
- m_bitmap2 = theBitmap2;
- m_x = xPos;
- m_y = yPos;
- 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(void)
-{
-/*
- if (m_deleteSecondBitmap && m_bitmap2)
- delete m_bitmap2;
-*/
-}
-
-
-// class wxToolBar
-
-wxToolBarBase::wxToolBarBase(void) : m_tools(wxKEY_INTEGER)
-{
- gs_ToolBars.Append(this);
-
- m_tilingDirection = wxVERTICAL;
- m_rowsOrColumns = 0;
- 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);
+#include "wx/listimpl.cpp"
- GetEventHandler()->ProcessEvent(event);
+WX_DEFINE_LIST(wxToolBarToolsList)
- return TRUE;
-}
+// ============================================================================
+// implementation
+// ============================================================================
-// Call when right button down.
-void wxToolBarBase::OnRightClick(int toolIndex, long x, long y)
+// ----------------------------------------------------------------------------
+// wxToolBarToolBase
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxToolBarToolBase, wxObject)
+
+wxToolBarToolBase::~wxToolBarToolBase()
{
- wxCommandEvent event(wxEVT_COMMAND_TOOL_RCLICKED, toolIndex);
- event.SetEventObject(this);
- event.SetInt(toolIndex);
+#if wxUSE_MENUS
+ delete m_dropdownMenu;
+#endif
- GetEventHandler()->ProcessEvent(event);
+ if ( IsControl() )
+ GetControl()->Destroy();
}
-// Called when the mouse cursor enters a tool bitmap (no button pressed).
-// Argument is -1 if mouse is exiting the toolbar.
-void wxToolBarBase::OnMouseEnter ( int toolIndex )
+
+bool wxToolBarToolBase::Enable(bool enable)
{
- wxCommandEvent event(wxEVT_COMMAND_TOOL_ENTER, toolIndex);
- event.SetEventObject(this);
- event.SetInt(toolIndex);
+ if ( m_enabled == enable )
+ return false;
- GetEventHandler()->ProcessEvent(event);
+ m_enabled = enable;
+
+ 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::Toggle(bool toggle)
{
- wxToolBarTool *tool = new wxToolBarTool(index, bitmap, pushedBitmap, toggle, xPos, yPos, helpString1, helpString2);
- tool->m_clientData = clientData;
+ wxASSERT_MSG( CanBeToggled(), wxT("can't toggle this tool") );
- if (xPos > -1)
- tool->m_x = xPos;
- else
- tool->m_x = m_xMargin;
+ if ( m_toggled == toggle )
+ return false;
- if (yPos > -1)
- tool->m_y = yPos;
- else
- tool->m_y = m_yMargin;
-
- // 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);
+ m_toggled = toggle;
- if ((tool->m_y + bitmap.GetHeight() + m_yMargin) > m_maxHeight)
- m_maxHeight = (tool->m_y + bitmap.GetHeight() + m_yMargin);
-
- m_tools.Append((long)index, tool);
- return tool;
+ return true;
}
-void wxToolBarBase::AddSeparator ()
+bool wxToolBarToolBase::SetToggle(bool toggle)
{
- wxToolBarTool *tool = new wxToolBarTool;
- tool->m_toolStyle = wxTOOL_STYLE_SEPARATOR;
- m_tools.Append(tool);
+ wxItemKind kind = toggle ? wxITEM_CHECK : wxITEM_NORMAL;
+ if ( m_kind == kind )
+ return false;
+
+ m_kind = kind;
+
+ return true;
}
-void wxToolBarBase::ClearTools(void)
+bool wxToolBarToolBase::SetShortHelp(const wxString& help)
{
- 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;
- }
+ if ( m_shortHelpString == help )
+ return false;
+
+ m_shortHelpString = help;
+
+ return true;
}
-void wxToolBarBase::EnableTool(int index, bool enable)
+bool wxToolBarToolBase::SetLongHelp(const wxString& help)
{
- wxNode *node = m_tools.Find((long)index);
- if (node)
- {
- wxToolBarTool *tool = (wxToolBarTool *)node->Data();
- if (tool)
- tool->m_enabled = enable;
- }
+ if ( m_longHelpString == help )
+ return false;
+
+ m_longHelpString = help;
+
+ return true;
}
-void wxToolBarBase::ToggleTool(int index, bool toggle)
+
+#if wxUSE_MENUS
+void wxToolBarToolBase::SetDropdownMenu(wxMenu* menu)
{
+ delete m_dropdownMenu;
+ m_dropdownMenu = menu;
}
+#endif
+
-void wxToolBarBase::SetToggle(int index, bool value)
+// ----------------------------------------------------------------------------
+// wxToolBarBase adding/deleting items
+// ----------------------------------------------------------------------------
+
+wxToolBarBase::wxToolBarBase()
{
- wxNode *node=m_tools.Find((long)index);
- if (node){
- wxToolBarTool *tool = (wxToolBarTool *)node->Data();
- tool->m_isToggle = value;
- }
+ // 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;
}
-bool wxToolBarBase::GetToolState(int index) const
+void wxToolBarBase::FixupStyle()
{
- wxNode *node = m_tools.Find((long)index);
- if (node)
- {
- wxToolBarTool *tool = (wxToolBarTool *)node->Data();
- if (tool)
+ if ( !HasFlag(wxTB_TOP | wxTB_LEFT | wxTB_RIGHT | wxTB_BOTTOM) )
{
- return tool->m_toggleState;
+ // this is the default
+ m_windowStyle |= wxTB_TOP;
}
- else return FALSE;
- }
- else return FALSE;
}
-bool wxToolBarBase::GetToolEnabled(int index) const
+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();
- if (tool)
- {
- return tool->m_enabled;
- }
- else return FALSE;
- }
- else return FALSE;
+ InvalidateBestSize();
+ return InsertTool(GetToolsCount(), toolid, label, bitmap, bmpDisabled,
+ kind, shortHelp, longHelp, clientData);
}
-wxObject *wxToolBarBase::GetToolClientData(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_clientData;
- }
- else return NULL;
- }
- else return NULL;
+ wxCHECK_MSG( pos <= GetToolsCount(), NULL,
+ wxT("invalid position in wxToolBar::InsertTool()") );
+
+ return DoInsertNewTool(pos, CreateTool(toolid, label, bitmap, bmpDisabled, kind,
+ clientData, shortHelp, longHelp));
}
-void wxToolBarBase::SetToolShortHelp(int index, const wxString& helpString)
+wxToolBarToolBase *wxToolBarBase::AddTool(wxToolBarToolBase *tool)
{
- wxNode *node=m_tools.Find((long)index);
- if (node)
- {
- wxToolBarTool *tool = (wxToolBarTool *)node->Data();
- tool->m_shortHelpString = helpString;
- }
+ return InsertTool(GetToolsCount(), tool);
}
-wxString wxToolBarBase::GetToolShortHelp(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();
- return tool->m_shortHelpString;
- }
- else
- return wxString("");
+ wxCHECK_MSG( pos <= GetToolsCount(), NULL,
+ wxT("invalid position in wxToolBar::InsertTool()") );
+
+ if ( !tool || !DoInsertTool(pos, tool) )
+ {
+ return NULL;
+ }
+
+ m_tools.Insert(pos, tool);
+ tool->Attach(this);
+
+ return tool;
}
-void wxToolBarBase::SetToolLongHelp(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_longHelpString = helpString;
- }
+ return InsertControl(GetToolsCount(), control, label);
}
-wxString wxToolBarBase::GetToolLongHelp(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_longHelpString;
- }
- 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));
}
-wxToolBarTool *wxToolBarBase::FindToolForPosition(long x, long y) const
+wxControl *wxToolBarBase::FindControl( int toolid )
{
- 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;
+ 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;
+ }
+ }
+ }
- node = node->Next();
- }
- return NULL;
+ return NULL;
}
-wxSize wxToolBarBase::GetMaxSize ( void ) const
+wxToolBarToolBase *wxToolBarBase::AddSeparator()
{
- return wxSize(m_maxWidth, m_maxHeight);
+ return InsertSeparator(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::InsertSeparator(size_t pos)
{
- m_xMargin = x;
- m_yMargin = y;
+ return DoInsertNewTool(pos, CreateSeparator());
}
-void wxToolBarBase::SetToolPacking(int packing)
+wxToolBarToolBase *wxToolBarBase::AddStretchableSpace()
{
- m_toolPacking = packing;
+ return InsertStretchableSpace(GetToolsCount());
}
-void wxToolBarBase::SetToolSeparation(int separation)
+wxToolBarToolBase *wxToolBarBase::InsertStretchableSpace(size_t pos)
{
- m_toolSeparation = separation;
+ 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::Command(wxCommandEvent& event)
+wxToolBarToolBase *wxToolBarBase::RemoveTool(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 )
+ {
+ // 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::Layout(void)
+bool wxToolBarBase::DeleteToolByPos(size_t pos)
{
- m_currentRowsOrColumns = 0;
- m_lastX = m_xMargin;
- m_lastY = m_yMargin;
- int maxToolWidth = 0;
- int maxToolHeight = 0;
- m_maxWidth = 0;
- m_maxHeight = 0;
+ 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;
+ }
- // Find the maximum tool width and height
- wxNode *node = m_tools.First();
- while (node)
- {
- wxToolBarTool *tool = (wxToolBarTool *)node->Data();
- if (tool->GetWidth() > maxToolWidth)
- maxToolWidth = (int)tool->GetWidth();
- if (tool->GetHeight() > maxToolHeight)
- maxToolHeight = (int)tool->GetHeight();
- node = node->Next();
- }
+ delete node->GetData();
+ m_tools.Erase(node);
- int separatorSize = m_toolSeparation;
+ return true;
+}
- node = m_tools.First();
- while (node)
- {
- wxToolBarTool *tool = (wxToolBarTool *)node->Data();
- if (tool->m_toolStyle == wxTOOL_STYLE_SEPARATOR)
+bool wxToolBarBase::DeleteTool(int toolid)
+{
+ size_t pos = 0;
+ wxToolBarToolsList::compatibility_iterator node;
+ for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
{
- if (m_tilingDirection == wxHORIZONTAL)
- {
- if (m_currentRowsOrColumns >= m_rowsOrColumns)
- m_lastY += separatorSize;
- else
- m_lastX += separatorSize;
- }
- else
- {
- if (m_currentRowsOrColumns >= m_rowsOrColumns)
- m_lastX += separatorSize;
- else
- m_lastY += separatorSize;
- }
+ if ( node->GetData()->GetId() == toolid )
+ break;
+
+ pos++;
}
- else if (tool->m_toolStyle == wxTOOL_STYLE_BUTTON)
+
+ if ( !node || !DoDeleteTool(pos, node->GetData()) )
{
- if (m_tilingDirection == wxHORIZONTAL)
- {
- if (m_currentRowsOrColumns >= m_rowsOrColumns)
+ return false;
+ }
+
+ delete node->GetData();
+ m_tools.Erase(node);
+
+ return true;
+}
+
+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 )
{
- m_currentRowsOrColumns = 0;
- m_lastX = m_xMargin;
- m_lastY += maxToolHeight + m_toolPacking;
+ // found
+ break;
}
- tool->m_x = (long) (m_lastX + (maxToolWidth - tool->GetWidth())/2.0);
- tool->m_y = (long) (m_lastY + (maxToolHeight - tool->GetHeight())/2.0);
-
- m_lastX += maxToolWidth + m_toolPacking;
- }
- else
- {
- if (m_currentRowsOrColumns >= m_rowsOrColumns)
+
+ tool = NULL;
+ }
+
+ return tool;
+}
+
+void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase *tool)
+{
+ wxCHECK_RET( tool, wxT("NULL tool in wxToolBarTool::UnToggleRadioGroup") );
+
+ if ( !tool->IsButton() || tool->GetKind() != wxITEM_RADIO )
+ return;
+
+ 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 )
+ {
+ wxToolBarToolBase *toolNext = nodeNext->GetData();
+
+ if ( !toolNext->IsButton() || toolNext->GetKind() != wxITEM_RADIO )
+ break;
+
+ if ( toolNext->Toggle(false) )
{
- m_currentRowsOrColumns = 0;
- m_lastX += (maxToolWidth + m_toolPacking);
- m_lastY = m_yMargin;
+ DoToggleTool(toolNext, false);
}
- tool->m_x = (long) (m_lastX + (maxToolWidth - tool->GetWidth())/2.0);
- tool->m_y = (long) (m_lastY + (maxToolHeight - tool->GetHeight())/2.0);
-
- m_lastY += maxToolHeight + m_toolPacking;
- }
- m_currentRowsOrColumns ++;
+
+ nodeNext = nodeNext->GetNext();
}
-
- if (m_lastX > m_maxWidth)
- m_maxWidth = m_lastX;
- if (m_lastY > m_maxHeight)
- m_maxHeight = m_lastY;
-
- node = node->Next();
- }
- if (m_tilingDirection == wxVERTICAL)
- m_maxWidth += maxToolWidth;
- else
- m_maxHeight += maxToolHeight;
-
- m_maxWidth += m_xMargin;
- m_maxHeight += m_yMargin;
-}
-
-
-// SCROLLING IMPLEMENTATION
-
-/*
- * 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)
-{
- m_xScrollPixelsPerLine = pixelsPerUnitX;
- m_yScrollPixelsPerLine = pixelsPerUnitY;
- m_xScrollLines = noUnitsX;
- m_yScrollLines = noUnitsY;
-
- int w, h;
- GetSize(&w, &h);
-
- // Recalculate scroll bar range and position
- if (m_xScrollLines > 0)
- {
- m_xScrollPosition = xPos;
- SetScrollPos (wxHORIZONTAL, m_xScrollPosition, TRUE);
- }
- else
+
+ wxToolBarToolsList::compatibility_iterator nodePrev = node->GetPrevious();
+ while ( nodePrev )
{
- SetScrollbar(wxHORIZONTAL, 0, 0, 0, FALSE);
- m_xScrollPosition = 0;
+ wxToolBarToolBase *toolNext = nodePrev->GetData();
+
+ if ( !toolNext->IsButton() || toolNext->GetKind() != wxITEM_RADIO )
+ break;
+
+ if ( toolNext->Toggle(false) )
+ {
+ DoToggleTool(toolNext, false);
+ }
+
+ nodePrev = nodePrev->GetPrevious();
}
+}
- if (m_yScrollLines > 0)
- {
- m_yScrollPosition = yPos;
- SetScrollPos (wxVERTICAL, m_yScrollPosition, TRUE);
- }
- 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);
-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 wxEVENT_TYPE_SCROLL_TOP:
- {
- if (orient == wxHORIZONTAL)
- nScrollInc = - m_xScrollPosition;
- else
- nScrollInc = - m_yScrollPosition;
- break;
- }
- case wxEVENT_TYPE_SCROLL_BOTTOM:
+ wxSize sizeActual(sizeOrig);
+
+ for ( wxToolBarToolsList::const_iterator i = m_tools.begin();
+ i != m_tools.end();
+ ++i )
{
- if (orient == wxHORIZONTAL)
- nScrollInc = m_xScrollLines - m_xScrollPosition;
- else
- nScrollInc = m_yScrollLines - m_yScrollPosition;
- break;
+ const wxBitmap& bmp = (*i)->GetNormalBitmap();
+ if ( bmp.IsOk() )
+ sizeActual.IncTo(bmp.GetSize());
}
- case wxEVENT_TYPE_SCROLL_LINEUP:
+
+ 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 )
{
- nScrollInc = -1;
- break;
+ frame->SetToolBar(NULL);
}
- case wxEVENT_TYPE_SCROLL_LINEDOWN:
+}
+
+// ----------------------------------------------------------------------------
+// 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 wxEVENT_TYPE_SCROLL_PAGEUP:
+}
+
+void wxToolBarBase::ToggleTool(int toolid, bool toggle)
+{
+ wxToolBarToolBase *tool = FindById(toolid);
+ if ( tool && tool->CanBeToggled() )
{
- if (orient == wxHORIZONTAL)
- nScrollInc = -GetScrollPageSize(wxHORIZONTAL);
- else
- nScrollInc = -GetScrollPageSize(wxVERTICAL);
- break;
+ if ( tool->Toggle(toggle) )
+ {
+ UnToggleRadioGroup(tool);
+ DoToggleTool(tool, toggle);
+ }
}
- case wxEVENT_TYPE_SCROLL_PAGEDOWN:
+}
+
+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 wxEVENT_TYPE_SCROLL_THUMBTRACK:
+}
+
+void wxToolBarBase::SetToolShortHelp(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->SetShortHelp(help);
}
- default:
+}
+
+void wxToolBarBase::SetToolLongHelp(int toolid, const wxString& help)
+{
+ wxToolBarToolBase *tool = FindById(toolid);
+ if ( tool )
{
- break;
+ (void)tool->SetLongHelp(help);
}
- }
- 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(void)
-{
- 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& event)
-{
-#if USE_CONSTRAINTS
- if (GetAutoLayout())
- Layout();
-#endif
+}
- AdjustScrollbars();
+wxObject *wxToolBarBase::GetToolClientData(int toolid) const
+{
+ wxToolBarToolBase *tool = FindById(toolid);
+
+ return tool ? tool->GetClientData() : NULL;
}
-// Prepare the DC by translating it according to the current scroll position
-void wxToolBarBase::PrepareDC(wxDC& dc)
+void wxToolBarBase::SetToolClientData(int toolid, wxObject *clientData)
{
- dc.SetDeviceOrigin(- m_xScrollPosition * m_xScrollPixelsPerLine, - m_yScrollPosition * m_yScrollPixelsPerLine);
+ wxToolBarToolBase *tool = FindById(toolid);
+
+ wxCHECK_RET( tool, wxT("no such tool in wxToolBar::SetToolClientData") );
+
+ tool->SetClientData(clientData);
}
-void wxToolBarBase::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const
+int wxToolBarBase::GetToolPos(int toolid) const
{
- *x_unit = m_xScrollPixelsPerLine;
- *y_unit = m_yScrollPixelsPerLine;
+ size_t pos = 0;
+ wxToolBarToolsList::compatibility_iterator node;
+
+ for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
+ {
+ if ( node->GetData()->GetId() == toolid )
+ return pos;
+
+ pos++;
+ }
+
+ return wxNOT_FOUND;
}
-int wxToolBarBase::GetScrollPageSize(int orient) const
+bool wxToolBarBase::GetToolState(int toolid) const
{
- if ( orient == wxHORIZONTAL )
- return m_xScrollLinesPerPage;
- else
- return m_yScrollLinesPerPage;
+ wxToolBarToolBase *tool = FindById(toolid);
+ wxCHECK_MSG( tool, false, wxT("no such tool") );
+
+ return tool->IsToggled();
}
-void wxToolBarBase::SetScrollPageSize(int orient, int pageSize)
+bool wxToolBarBase::GetToolEnabled(int toolid) const
{
- if ( orient == wxHORIZONTAL )
- m_xScrollLinesPerPage = pageSize;
- else
- m_yScrollLinesPerPage = pageSize;
+ wxToolBarToolBase *tool = FindById(toolid);
+ wxCHECK_MSG( tool, false, wxT("no such tool") );
+
+ return tool->IsEnabled();
}
-/*
- * Scroll to given position (scroll position, not pixel position)
- */
-void wxToolBarBase::Scroll (int x_pos, int y_pos)
+wxString wxToolBarBase::GetToolShortHelp(int toolid) const
{
- 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;
+ wxToolBarToolBase *tool = FindById(toolid);
+ wxCHECK_MSG( tool, wxEmptyString, wxT("no such tool") );
- 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
+ return tool->GetShortHelp();
}
-void wxToolBarBase::EnableScrolling (bool x_scroll, bool y_scroll)
+wxString wxToolBarBase::GetToolLongHelp(int toolid) const
{
- m_xScrollingEnabled = x_scroll;
- m_yScrollingEnabled = y_scroll;
+ wxToolBarToolBase *tool = FindById(toolid);
+ wxCHECK_MSG( tool, wxEmptyString, wxT("no such tool") );
+
+ return tool->GetLongHelp();
}
-void wxToolBarBase::GetVirtualSize (int *x, int *y) const
+// ----------------------------------------------------------------------------
+// wxToolBarBase geometry
+// ----------------------------------------------------------------------------
+
+void wxToolBarBase::SetMargins(int x, int y)
{
- *x = m_xScrollPixelsPerLine * m_xScrollLines;
- *y = m_yScrollPixelsPerLine * m_yScrollLines;
+ m_xMargin = x;
+ m_yMargin = y;
}
-// Where the current view starts from
-void wxToolBarBase::ViewStart (int *x, int *y) const
+void wxToolBarBase::SetRows(int WXUNUSED(nRows))
{
- *x = m_xScrollPosition;
- *y = m_yScrollPosition;
+ // nothing
}
-/*
-void wxToolBarBase::CalcScrolledPosition(int x, int y, int *xx, int *yy) const
+bool wxToolBarBase::IsVertical() const
{
- *xx = (m_calcScrolledOffset ? (x - m_xScrollPosition * m_xScrollPixelsPerLine) : x);
- *yy = (m_calcScrolledOffset ? (y - m_yScrollPosition * m_yScrollPixelsPerLine) : y);
+ return HasFlag(wxTB_LEFT | wxTB_RIGHT);
}
-void wxToolBarBase::CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const
+
+// ----------------------------------------------------------------------------
+// event processing
+// ----------------------------------------------------------------------------
+
+// Only allow toggle if returns true
+bool wxToolBarBase::OnLeftClick(int toolid, bool toggleDown)
{
- *xx = (float)(m_calcScrolledOffset ? (x + m_xScrollPosition * m_xScrollPixelsPerLine) : x);
- *yy = (float)(m_calcScrolledOffset ? (y + m_yScrollPosition * m_yScrollPixelsPerLine) : y);
+ wxCommandEvent event(wxEVT_TOOL, 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;
}
-*/
-void wxToolBarBase::OnIdle(wxIdleEvent& event)
+// Call when right button down.
+void wxToolBarBase::OnRightClick(int toolid,
+ long WXUNUSED(x),
+ long WXUNUSED(y))
{
- wxWindow::OnIdle(event);
+ wxCommandEvent event(wxEVT_TOOL_RCLICKED, toolid);
+ event.SetEventObject(this);
+ event.SetInt(toolid);
- DoToolbarUpdates();
+ GetEventHandler()->ProcessEvent(event);
}
+// 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)
+{
+ wxCommandEvent event(wxEVT_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);
+ }
+
+ (void)GetEventHandler()->ProcessEvent(event);
+}
+
+// ----------------------------------------------------------------------------
+// UI updates
+// ----------------------------------------------------------------------------
+
// Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
-void wxToolBarBase::DoToolbarUpdates(void)
+void wxToolBarBase::UpdateWindowUI(long flags)
{
- wxNode* node = GetTools().First();
- while (node)
- {
- wxToolBarTool* tool = (wxToolBarTool* ) node->Data();
+ wxWindowBase::UpdateWindowUI(flags);
+
+ // don't waste time updating state of tools in a hidden toolbar
+ if ( !IsShown() )
+ return;
+
+ wxEvtHandler* evtHandler = GetEventHandler() ;
+
+ for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ wxToolBarToolBase * const tool = node->GetData();
+ if ( tool->IsSeparator() )
+ continue;
- wxUpdateUIEvent event(tool->m_index);
- event.SetEventObject(this);
+ int toolid = tool->GetId();
- if (GetEventHandler()->ProcessEvent(event))
- {
- if (event.GetSetEnabled())
- EnableTool(tool->m_index, event.GetEnabled());
- if (event.GetSetChecked())
- ToggleTool(tool->m_index, event.GetChecked());
-/*
- if (event.GetSetText())
- // Set tooltip?
-*/
- }
+ wxUpdateUIEvent event(toolid);
+ event.SetEventObject(this);
- node = node->Next();
- }
+ if ( evtHandler->ProcessEvent(event) )
+ {
+ if ( event.GetSetEnabled() )
+ EnableTool(toolid, event.GetEnabled());
+ if ( event.GetSetChecked() )
+ ToggleTool(toolid, event.GetChecked());
+#if 0
+ if ( event.GetSetText() )
+ // Set tooltip?
+#endif // 0
+ }
+ }
}
-#ifdef __WXMSW__
-// Circumvent wxControl::MSWOnMouseMove which doesn't set the cursor.
-void wxToolBarBase::MSWOnMouseMove(int x, int y, const WXUINT flags)
+#if wxUSE_MENUS
+bool wxToolBarBase::SetDropdownMenu(int toolid, wxMenu* menu)
{
- wxWindow::MSWOnMouseMove(x, y, flags);
+ 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
-#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