Steps towards implementing native-style, non-top-level toolbars on Mac

by implementing a toolbar class that uses native buttons.
Ultimately this should allow wxToolbook and wxPropertySheetDialog
classes to look native, when we complete the button API improvements
to combine text, bitmaps and toggling.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38703 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Julian Smart
2006-04-14 09:15:10 +00:00
parent 44c930ebba
commit 64d3ed176d
16 changed files with 718 additions and 16 deletions

428
src/generic/buttonbar.cpp Normal file
View File

@@ -0,0 +1,428 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/generic/buttonbar.cpp
// Purpose: wxButtonToolBar implementation
// Author: Julian Smart, after Robert Roebling, Vadim Zeitlin, SciTech
// Modified by:
// Created: 2006-04-13
// Id: $Id$
// 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
#if wxUSE_TOOLBAR && wxUSE_BMPBUTTON
#ifndef WX_PRECOMP
#include "wx/utils.h"
#include "wx/app.h"
#endif
#include "wx/generic/buttonbar.h"
#include "wx/frame.h"
#include "wx/image.h"
#include "wx/log.h"
// ----------------------------------------------------------------------------
// 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)
: wxToolBarToolBase(tbar, control)
{
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)
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;
}
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;
}
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, _T("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, _T("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)
{
return new wxButtonToolBarTool(this, control);
}
// ----------------------------------------------------------------------------
// wxButtonToolBar geometry
// ----------------------------------------------------------------------------
wxRect wxButtonToolBar::GetToolRect(wxToolBarToolBase *toolBase) const
{
const wxButtonToolBarTool *tool = (wxButtonToolBarTool *)toolBase;
wxRect rect;
wxCHECK_MSG( tool, rect, _T("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_xMargin;
rect.y = tool->m_y - m_yMargin;
if ( IsVertical() )
{
if (tool->IsButton())
{
rect.width = m_defaultWidth;
rect.height = m_defaultHeight;
if (tool->GetButton())
rect.SetSize(tool->GetButton()->GetSize());
}
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(tool->GetButton()->GetSize());
}
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 += 2*m_xMargin;
rect.height += 2*m_yMargin;
return rect;
}
bool wxButtonToolBar::Realize()
{
if ( !wxToolBarBase::Realize() )
return false;
m_needsLayout = true;
DoLayout();
SetBestSize(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);
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;
maxHeight = wxMax(maxHeight, sz.y);
}
*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;
}
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;
}
// TODO: handle toggle items
OnLeftClick(event.GetId(), false);
}
#endif // wxUSE_TOOLBAR && wxUSE_BMPBUTTON