Files
wxWidgets/src/generic/buttonbar.cpp
Vadim Zeitlin 3f66f6a5b3 Remove all lines containing cvs/svn "$Id$" keyword.
This keyword is not expanded by Git which means it's not replaced with the
correct revision value in the releases made using git-based scripts and it's
confusing to have lines with unexpanded "$Id$" in the released files. As
expanding them with Git is not that simple (it could be done with git archive
and export-subst attribute) and there are not many benefits in having them in
the first place, just remove all these lines.

If nothing else, this will make an eventual transition to Git simpler.

Closes #14487.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2013-07-26 16:02:46 +00:00

561 lines
16 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/generic/buttonbar.cpp
// Purpose: wxButtonToolBar implementation
// Author: Julian Smart, after Robert Roebling, Vadim Zeitlin, SciTech
// Modified by:
// Created: 2006-04-13
// Copyright: (c) Julian Smart, Robert Roebling, Vadim Zeitlin,
// SciTech Software, Inc.
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// Currently, only for Mac as a toolbar replacement.
#if defined(__WXMAC__) && wxUSE_TOOLBAR && wxUSE_BMPBUTTON
#include "wx/generic/buttonbar.h"
#ifndef WX_PRECOMP
#include "wx/utils.h"
#include "wx/app.h"
#include "wx/log.h"
#include "wx/frame.h"
#include "wx/dcclient.h"
#include "wx/settings.h"
#include "wx/image.h"
#endif
// ----------------------------------------------------------------------------
// wxButtonToolBarTool: our implementation of wxToolBarToolBase
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxButtonToolBarTool : public wxToolBarToolBase
{
public:
wxButtonToolBarTool(wxButtonToolBar *tbar,
int id,
const wxString& label,
const wxBitmap& bmpNormal,
const wxBitmap& bmpDisabled,
wxItemKind kind,
wxObject *clientData,
const wxString& shortHelp,
const wxString& longHelp)
: wxToolBarToolBase(tbar, id, label, bmpNormal, bmpDisabled, kind,
clientData, shortHelp, longHelp)
{
m_x = m_y = wxDefaultCoord;
m_width =
m_height = 0;
m_button = NULL;
}
wxButtonToolBarTool(wxButtonToolBar *tbar,
wxControl *control,
const wxString& label)
: wxToolBarToolBase(tbar, control, label)
{
m_x = m_y = wxDefaultCoord;
m_width =
m_height = 0;
m_button = NULL;
}
wxBitmapButton* GetButton() const { return m_button; }
void SetButton(wxBitmapButton* button) { m_button = button; }
public:
// the tool position (for controls)
wxCoord m_x;
wxCoord m_y;
wxCoord m_width;
wxCoord m_height;
private:
// the control representing the button
wxBitmapButton* m_button;
};
// ============================================================================
// wxButtonToolBar implementation
// ============================================================================
IMPLEMENT_DYNAMIC_CLASS(wxButtonToolBar, wxControl)
BEGIN_EVENT_TABLE(wxButtonToolBar, wxControl)
EVT_BUTTON(wxID_ANY, wxButtonToolBar::OnCommand)
EVT_PAINT(wxButtonToolBar::OnPaint)
EVT_LEFT_UP(wxButtonToolBar::OnLeftUp)
END_EVENT_TABLE()
// ----------------------------------------------------------------------------
// wxButtonToolBar creation
// ----------------------------------------------------------------------------
void wxButtonToolBar::Init()
{
// no tools yet
m_needsLayout = false;
// unknown widths for the tools and separators
m_widthSeparator = wxDefaultCoord;
m_maxWidth = m_maxHeight = 0;
m_labelMargin = 2;
m_labelHeight = 0;
SetMargins(8, 2);
SetToolPacking(8);
}
bool wxButtonToolBar::Create(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{
if ( !wxToolBarBase::Create(parent, id, pos, size, style,
wxDefaultValidator, name) )
{
return false;
}
// wxColour lightBackground(244, 244, 244);
wxFont font(wxSMALL_FONT->GetPointSize(),
wxNORMAL_FONT->GetFamily(),
wxNORMAL_FONT->GetStyle(),
wxFONTWEIGHT_NORMAL);
SetFont(font);
// Calculate the label height if necessary
if (GetWindowStyle() & wxTB_TEXT)
{
wxClientDC dc(this);
dc.SetFont(font);
int w, h;
dc.GetTextExtent(wxT("X"), & w, & h);
m_labelHeight = h;
}
return true;
}
wxButtonToolBar::~wxButtonToolBar()
{
}
// ----------------------------------------------------------------------------
// wxButtonToolBar tool-related methods
// ----------------------------------------------------------------------------
wxToolBarToolBase *wxButtonToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
{
// check the "other" direction first: it must be inside the toolbar or we
// don't risk finding anything
if ( IsVertical() )
{
if ( x < 0 || x > m_maxWidth )
return NULL;
// we always use x, even for a vertical toolbar, this makes the code
// below simpler
x = y;
}
else // horizontal
{
if ( y < 0 || y > m_maxHeight )
return NULL;
}
for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
node;
node = node->GetNext() )
{
wxButtonToolBarTool *tool = (wxButtonToolBarTool*) node->GetData();
wxRect rectTool = GetToolRect(tool);
wxCoord startTool, endTool;
GetRectLimits(rectTool, &startTool, &endTool);
if ( x >= startTool && x <= endTool )
{
// don't return the separators from here, they don't accept any
// input anyhow
return tool->IsSeparator() ? NULL : tool;
}
}
return NULL;
}
void wxButtonToolBar::GetRectLimits(const wxRect& rect,
wxCoord *start,
wxCoord *end) const
{
wxCHECK_RET( start && end, wxT("NULL pointer in GetRectLimits") );
if ( IsVertical() )
{
*start = rect.GetTop();
*end = rect.GetBottom();
}
else // horizontal
{
*start = rect.GetLeft();
*end = rect.GetRight();
}
}
void wxButtonToolBar::SetToolShortHelp(int id, const wxString& help)
{
wxToolBarToolBase *tool = FindById(id);
wxCHECK_RET( tool, wxT("SetToolShortHelp: no such tool") );
// TODO: set tooltip/short help
tool->SetShortHelp(help);
}
bool wxButtonToolBar::DoInsertTool(size_t WXUNUSED(pos),
wxToolBarToolBase * WXUNUSED(tool))
{
return true;
}
bool wxButtonToolBar::DoDeleteTool(size_t WXUNUSED(pos),
wxToolBarToolBase * WXUNUSED(tool))
{
// TODO
return true;
}
void wxButtonToolBar::DoEnableTool(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(enable))
{
// TODO
}
void wxButtonToolBar::DoToggleTool(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
{
// TODO
}
void wxButtonToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
{
// TODO
}
wxToolBarToolBase *wxButtonToolBar::CreateTool(int id,
const wxString& label,
const wxBitmap& bmpNormal,
const wxBitmap& bmpDisabled,
wxItemKind kind,
wxObject *clientData,
const wxString& shortHelp,
const wxString& longHelp)
{
return new wxButtonToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
clientData, shortHelp, longHelp);
}
wxToolBarToolBase *wxButtonToolBar::CreateTool(wxControl *control,
const wxString& label)
{
return new wxButtonToolBarTool(this, control, label);
}
// ----------------------------------------------------------------------------
// wxButtonToolBar geometry
// ----------------------------------------------------------------------------
wxRect wxButtonToolBar::GetToolRect(wxToolBarToolBase *toolBase) const
{
const wxButtonToolBarTool *tool = (wxButtonToolBarTool *)toolBase;
wxRect rect;
wxCHECK_MSG( tool, rect, wxT("GetToolRect: NULL tool") );
// ensure that we always have the valid tool position
if ( m_needsLayout )
{
wxConstCast(this, wxButtonToolBar)->DoLayout();
}
rect.x = tool->m_x - (m_toolPacking/2);
rect.y = tool->m_y;
if ( IsVertical() )
{
if (tool->IsButton())
{
rect.width = m_defaultWidth;
rect.height = m_defaultHeight;
if (tool->GetButton())
rect.SetSize(wxSize(tool->m_width, tool->m_height));
}
else if (tool->IsSeparator())
{
rect.width = m_defaultWidth;
rect.height = m_widthSeparator;
}
else // control
{
rect.width = tool->m_width;
rect.height = tool->m_height;
}
}
else // horizontal
{
if (tool->IsButton())
{
rect.width = m_defaultWidth;
rect.height = m_defaultHeight;
if (tool->GetButton())
rect.SetSize(wxSize(tool->m_width, tool->m_height));
}
else if (tool->IsSeparator())
{
rect.width = m_widthSeparator;
rect.height = m_defaultHeight;
}
else // control
{
rect.width = tool->m_width;
rect.height = tool->m_height;
}
}
rect.width += m_toolPacking;
return rect;
}
bool wxButtonToolBar::Realize()
{
if ( !wxToolBarBase::Realize() )
return false;
m_needsLayout = true;
DoLayout();
SetInitialSize(wxSize(m_maxWidth, m_maxHeight));
return true;
}
void wxButtonToolBar::DoLayout()
{
m_needsLayout = false;
wxCoord x = m_xMargin,
y = m_yMargin;
int maxHeight = 0;
const wxCoord widthTool = IsVertical() ? m_defaultHeight : m_defaultWidth;
wxCoord margin = IsVertical() ? m_xMargin : m_yMargin;
wxCoord *pCur = IsVertical() ? &y : &x;
// calculate the positions of all elements
for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
node;
node = node->GetNext() )
{
wxButtonToolBarTool *tool = (wxButtonToolBarTool *) node->GetData();
tool->m_x = x;
tool->m_y = y;
if (tool->IsButton())
{
if (!tool->GetButton())
{
wxBitmapButton* bmpButton = new wxBitmapButton(this, tool->GetId(), tool->GetNormalBitmap(), wxPoint(tool->m_x, tool->m_y), wxDefaultSize,
wxBU_AUTODRAW|wxBORDER_NONE);
if (!tool->GetShortHelp().empty())
bmpButton->SetLabel(tool->GetShortHelp());
tool->SetButton(bmpButton);
}
else
{
tool->GetButton()->Move(wxPoint(tool->m_x, tool->m_y));
}
int w = widthTool;
if (tool->GetButton())
{
wxSize sz = tool->GetButton()->GetSize();
w = sz.x;
if (m_labelHeight > 0)
{
sz.y += (m_labelHeight + m_labelMargin);
if (!tool->GetShortHelp().empty())
{
wxClientDC dc(this);
dc.SetFont(GetFont());
int tw, th;
dc.GetTextExtent(tool->GetShortHelp(), & tw, & th);
// If the label is bigger than the icon, the label width
// becomes the new tool width, and we need to centre the
// the bitmap in this box.
if (tw > sz.x)
{
int newX = int(tool->m_x + (tw - sz.x)/2.0);
tool->GetButton()->Move(newX, tool->m_y);
sz.x = tw;
}
}
}
maxHeight = wxMax(maxHeight, sz.y);
tool->m_width = sz.x;
tool->m_height = sz.y;
w = sz.x;
}
*pCur += (w + GetToolPacking());
}
else if (tool->IsSeparator())
{
*pCur += m_widthSeparator;
}
else if (!IsVertical()) // horizontal control
{
wxControl *control = tool->GetControl();
wxSize size = control->GetSize();
tool->m_y += (m_defaultHeight - size.y)/2;
tool->m_width = size.x;
tool->m_height = size.y;
*pCur += tool->m_width;
maxHeight = wxMax(maxHeight, size.y);
}
*pCur += margin;
}
// calculate the total toolbar size
m_maxWidth = x + 2*m_xMargin;
m_maxHeight = maxHeight + 2*m_yMargin;
if ((GetWindowStyle() & wxTB_NODIVIDER) == 0)
m_maxHeight += 2;
}
wxSize wxButtonToolBar::DoGetBestClientSize() const
{
return wxSize(m_maxWidth, m_maxHeight);
}
// receives button commands
void wxButtonToolBar::OnCommand(wxCommandEvent& event)
{
wxButtonToolBarTool* tool = (wxButtonToolBarTool*) FindById(event.GetId());
if (!tool)
{
event.Skip();
return;
}
if (tool->CanBeToggled())
tool->Toggle(tool->IsToggled());
// TODO: handle toggle items
OnLeftClick(event.GetId(), false);
if (tool->GetKind() == wxITEM_RADIO)
UnToggleRadioGroup(tool);
if (tool->CanBeToggled())
Refresh();
}
// paints a border
void wxButtonToolBar::OnPaint(wxPaintEvent& WXUNUSED(event))
{
wxPaintDC dc(this);
dc.SetFont(GetFont());
dc.SetBackgroundMode(wxTRANSPARENT);
for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
node;
node = node->GetNext() )
{
wxButtonToolBarTool *tool = (wxButtonToolBarTool*) node->GetData();
wxRect rectTool = GetToolRect(tool);
if (tool->IsToggled())
{
wxRect backgroundRect = rectTool;
backgroundRect.y = -1; backgroundRect.height = GetClientSize().y + 1;
wxBrush brush(wxColour(219, 219, 219));
wxPen pen(wxColour(159, 159, 159));
dc.SetBrush(brush);
dc.SetPen(pen);
dc.DrawRectangle(backgroundRect);
}
if (m_labelHeight > 0 && !tool->GetShortHelp().empty())
{
int tw, th;
dc.GetTextExtent(tool->GetShortHelp(), & tw, & th);
int x = tool->m_x;
dc.DrawText(tool->GetShortHelp(), x, tool->m_y + tool->GetButton()->GetSize().y + m_labelMargin);
}
}
if ((GetWindowStyle() & wxTB_NODIVIDER) == 0)
{
wxPen pen(wxColour(159, 159, 159));
dc.SetPen(pen);
int x1 = 0;
int y1 = GetClientSize().y-1;
int x2 = GetClientSize().x;
int y2 = y1;
dc.DrawLine(x1, y1, x2, y2);
}
}
// detects mouse clicks outside buttons
void wxButtonToolBar::OnLeftUp(wxMouseEvent& event)
{
if (m_labelHeight > 0)
{
wxButtonToolBarTool* tool = (wxButtonToolBarTool*) FindToolForPosition(event.GetX(), event.GetY());
if (tool && tool->GetButton() && (event.GetY() > (tool->m_y + tool->GetButton()->GetSize().y)))
{
wxCommandEvent event(wxEVT_BUTTON, tool->GetId());
event.SetEventObject(tool->GetButton());
if (!GetEventHandler()->ProcessEvent(event))
event.Skip();
}
}
}
#endif // wxUSE_TOOLBAR && wxUSE_BMPBUTTON