Files
wxWidgets/src/common/tbarbase.cpp
Vadim Zeitlin 47d67540a0 USE_xxx constants renamed to wxUSE_xxx. This is an incompatible change, you
must recompile everything after upgrading!


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@774 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
1998-09-25 13:28:52 +00:00

742 lines
17 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: tbarbase.cpp
// Purpose: Toolbar base classes
// Author: Julian Smart
// Modified by:
// Created: 04/01/98
// RCS-ID: $Id$
// Copyright: (c) Julian Smart and Markus Holzem
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation "tbarbase.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// For ::UpdateWindow
#ifdef __WXMSW__
#include <windows.h>
#endif
#if wxUSE_TOOLBAR
#include "wx/tbarbase.h"
#if !USE_SHARED_LIBRARY
IMPLEMENT_ABSTRACT_CLASS(wxToolBarBase, wxControl)
IMPLEMENT_DYNAMIC_CLASS(wxToolBarTool, wxObject)
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_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);
GetEventHandler()->ProcessEvent(event);
return TRUE;
}
// Call when right button down.
void wxToolBarBase::OnRightClick(int toolIndex, long x, long y)
{
wxCommandEvent event(wxEVT_COMMAND_TOOL_RCLICKED, toolIndex);
event.SetEventObject(this);
event.SetInt(toolIndex);
GetEventHandler()->ProcessEvent(event);
}
// 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 )
{
wxCommandEvent event(wxEVT_COMMAND_TOOL_ENTER, GetId());
event.SetEventObject(this);
event.SetInt(toolIndex);
GetEventHandler()->ProcessEvent(event);
}
// 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)
{
wxToolBarTool *tool = new wxToolBarTool(index, bitmap, pushedBitmap, toggle, xPos, yPos, helpString1, helpString2);
tool->m_clientData = clientData;
if (xPos > -1)
tool->m_x = xPos;
else
tool->m_x = m_xMargin;
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);
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;
}
void wxToolBarBase::AddSeparator ()
{
wxToolBarTool *tool = new wxToolBarTool;
tool->m_toolStyle = wxTOOL_STYLE_SEPARATOR;
m_tools.Append(tool);
}
void wxToolBarBase::ClearTools(void)
{
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;
}
}
void wxToolBarBase::EnableTool(int index, bool enable)
{
wxNode *node = m_tools.Find((long)index);
if (node)
{
wxToolBarTool *tool = (wxToolBarTool *)node->Data();
if (tool)
tool->m_enabled = enable;
}
}
void wxToolBarBase::ToggleTool(int index, bool toggle)
{
}
void wxToolBarBase::SetToggle(int index, bool value)
{
wxNode *node=m_tools.Find((long)index);
if (node){
wxToolBarTool *tool = (wxToolBarTool *)node->Data();
tool->m_isToggle = value;
}
}
bool wxToolBarBase::GetToolState(int index) const
{
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;
}
bool wxToolBarBase::GetToolEnabled(int index) const
{
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;
}
wxObject *wxToolBarBase::GetToolClientData(int index) const
{
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;
}
void wxToolBarBase::SetToolShortHelp(int index, const wxString& helpString)
{
wxNode *node=m_tools.Find((long)index);
if (node)
{
wxToolBarTool *tool = (wxToolBarTool *)node->Data();
tool->m_shortHelpString = helpString;
}
}
wxString wxToolBarBase::GetToolShortHelp(int index) const
{
wxNode *node=m_tools.Find((long)index);
if (node)
{
wxToolBarTool *tool = (wxToolBarTool *)node->Data();
return tool->m_shortHelpString;
}
else
return wxString("");
}
void wxToolBarBase::SetToolLongHelp(int index, const wxString& helpString)
{
wxNode *node=m_tools.Find((long)index);
if (node)
{
wxToolBarTool *tool = (wxToolBarTool *)node->Data();
tool->m_longHelpString = helpString;
}
}
wxString wxToolBarBase::GetToolLongHelp(int index) const
{
wxNode *node=m_tools.Find((long)index);
if (node)
{
wxToolBarTool *tool = (wxToolBarTool *)node->Data();
return tool->m_longHelpString;
}
else
return wxString("");
}
wxToolBarTool *wxToolBarBase::FindToolForPosition(long x, long y) const
{
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;
}
wxSize wxToolBarBase::GetMaxSize ( void ) const
{
return wxSize(m_maxWidth, m_maxHeight);
}
// 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)
{
m_xMargin = x;
m_yMargin = y;
}
void wxToolBarBase::SetToolPacking(int packing)
{
m_toolPacking = packing;
}
void wxToolBarBase::SetToolSeparation(int separation)
{
m_toolSeparation = separation;
}
void wxToolBarBase::Command(wxCommandEvent& event)
{
}
void wxToolBarBase::Layout(void)
{
}
// 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
{
SetScrollbar(wxHORIZONTAL, 0, 0, 0, FALSE);
m_xScrollPosition = 0;
}
if (m_yScrollLines > 0)
{
m_yScrollPosition = yPos;
SetScrollPos (wxVERTICAL, m_yScrollPosition, TRUE);
}
else
{
SetScrollbar(wxVERTICAL, 0, 0, 0, FALSE);
m_yScrollPosition = 0;
}
AdjustScrollbars();
Refresh();
#ifdef __WXMSW__
::UpdateWindow ((HWND) GetHWND());
#endif
}
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:
{
if (orient == wxHORIZONTAL)
nScrollInc = - m_xScrollPosition;
else
nScrollInc = - m_yScrollPosition;
break;
}
case wxEVT_SCROLL_BOTTOM:
{
if (orient == wxHORIZONTAL)
nScrollInc = m_xScrollLines - m_xScrollPosition;
else
nScrollInc = m_yScrollLines - m_yScrollPosition;
break;
}
case wxEVT_SCROLL_LINEUP:
{
nScrollInc = -1;
break;
}
case wxEVT_SCROLL_LINEDOWN:
{
nScrollInc = 1;
break;
}
case wxEVT_SCROLL_PAGEUP:
{
if (orient == wxHORIZONTAL)
nScrollInc = -GetScrollPageSize(wxHORIZONTAL);
else
nScrollInc = -GetScrollPageSize(wxVERTICAL);
break;
}
case wxEVT_SCROLL_PAGEDOWN:
{
if (orient == wxHORIZONTAL)
nScrollInc = GetScrollPageSize(wxHORIZONTAL);
else
nScrollInc = GetScrollPageSize(wxVERTICAL);
break;
}
case wxEVT_SCROLL_THUMBTRACK:
{
if (orient == wxHORIZONTAL)
nScrollInc = pos - m_xScrollPosition;
else
nScrollInc = pos - m_yScrollPosition;
break;
}
default:
{
break;
}
}
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 wxUSE_CONSTRAINTS
if (GetAutoLayout())
Layout();
#endif
AdjustScrollbars();
}
// Prepare the DC by translating it according to the current scroll position
void wxToolBarBase::PrepareDC(wxDC& dc)
{
dc.SetDeviceOrigin(- m_xScrollPosition * m_xScrollPixelsPerLine, - m_yScrollPosition * m_yScrollPixelsPerLine);
}
void wxToolBarBase::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const
{
*x_unit = m_xScrollPixelsPerLine;
*y_unit = m_yScrollPixelsPerLine;
}
int wxToolBarBase::GetScrollPageSize(int orient) const
{
if ( orient == wxHORIZONTAL )
return m_xScrollLinesPerPage;
else
return m_yScrollLinesPerPage;
}
void wxToolBarBase::SetScrollPageSize(int orient, int pageSize)
{
if ( orient == wxHORIZONTAL )
m_xScrollLinesPerPage = pageSize;
else
m_yScrollLinesPerPage = pageSize;
}
/*
* Scroll to given position (scroll position, not pixel position)
*/
void wxToolBarBase::Scroll (int x_pos, int y_pos)
{
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;
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::EnableScrolling (bool x_scroll, bool y_scroll)
{
m_xScrollingEnabled = x_scroll;
m_yScrollingEnabled = y_scroll;
}
void wxToolBarBase::GetVirtualSize (int *x, int *y) const
{
*x = m_xScrollPixelsPerLine * m_xScrollLines;
*y = m_yScrollPixelsPerLine * m_yScrollLines;
}
// Where the current view starts from
void wxToolBarBase::ViewStart (int *x, int *y) const
{
*x = m_xScrollPosition;
*y = m_yScrollPosition;
}
void wxToolBarBase::OnIdle(wxIdleEvent& event)
{
wxWindow::OnIdle(event);
DoToolbarUpdates();
}
// Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
void wxToolBarBase::DoToolbarUpdates(void)
{
wxNode* node = GetTools().First();
while (node)
{
wxToolBarTool* tool = (wxToolBarTool* ) node->Data();
wxUpdateUIEvent event(tool->m_index);
event.SetEventObject(this);
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?
*/
}
node = node->Next();
}
}
#ifdef __WXMSW__
// Circumvent wxControl::MSWOnMouseMove which doesn't set the cursor.
void wxToolBarBase::MSWOnMouseMove(int x, int y, WXUINT flags)
{
wxWindow::MSWOnMouseMove(x, y, flags);
}
#endif
#endif