Files
wxWidgets/src/aui/auibar.cpp
Vadim Zeitlin f90b69e028 Move checks for m_art != NULL before code using m_art in wxAuiToolBar.
It doesn't make sense to check whether a pointer is NULL after using it, so do
the checks first.

In fact the m_art pointer probably can never be NULL at all as other code uses
it without checking and so these checks could probably be removed completely,
but keep them for now as I'm not totally sure if having NULL art provider is
really impossible.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@70748 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2012-02-29 13:58:52 +00:00

2894 lines
76 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: src/aui/auibar.cpp
// Purpose: wxaui: wx advanced user interface - docking window manager
// Author: Benjamin I. Williams
// Modified by:
// Created: 2005-05-17
// RCS-ID: $Id$
// Copyright: (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved
// Licence: wxWindows Library Licence, Version 3.1
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_AUI
#include "wx/statline.h"
#include "wx/dcbuffer.h"
#include "wx/sizer.h"
#include "wx/image.h"
#include "wx/settings.h"
#include "wx/menu.h"
#include "wx/aui/auibar.h"
#include "wx/aui/framemanager.h"
#ifdef __WXMAC__
#include "wx/osx/private.h"
#endif
#include "wx/arrimpl.cpp"
WX_DEFINE_OBJARRAY(wxAuiToolBarItemArray)
wxDEFINE_EVENT( wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, wxAuiToolBarEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, wxAuiToolBarEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, wxAuiToolBarEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, wxAuiToolBarEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG, wxAuiToolBarEvent );
IMPLEMENT_CLASS(wxAuiToolBar, wxControl)
IMPLEMENT_DYNAMIC_CLASS(wxAuiToolBarEvent, wxEvent)
// missing wxITEM_* items
enum
{
wxITEM_CONTROL = wxITEM_MAX,
wxITEM_LABEL,
wxITEM_SPACER
};
const int BUTTON_DROPDOWN_WIDTH = 10;
wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h,
const wxColour& color);
static wxColor GetBaseColor()
{
#if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON
wxColor baseColour = wxColour( wxMacCreateCGColorFromHITheme(kThemeBrushToolbarBackground));
#else
wxColor baseColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
#endif
// the baseColour is too pale to use as our base colour,
// so darken it a bit --
if ((255-baseColour.Red()) +
(255-baseColour.Green()) +
(255-baseColour.Blue()) < 60)
{
baseColour = baseColour.ChangeLightness(92);
}
return baseColour;
}
class ToolbarCommandCapture : public wxEvtHandler
{
public:
ToolbarCommandCapture() { m_lastId = 0; }
int GetCommandId() const { return m_lastId; }
bool ProcessEvent(wxEvent& evt)
{
if (evt.GetEventType() == wxEVT_COMMAND_MENU_SELECTED)
{
m_lastId = evt.GetId();
return true;
}
if (GetNextHandler())
return GetNextHandler()->ProcessEvent(evt);
return false;
}
private:
int m_lastId;
};
static const unsigned char
DISABLED_TEXT_GREY_HUE = wxColour::AlphaBlend(0, 255, 0.4);
const wxColour DISABLED_TEXT_COLOR(DISABLED_TEXT_GREY_HUE,
DISABLED_TEXT_GREY_HUE,
DISABLED_TEXT_GREY_HUE);
wxAuiDefaultToolBarArt::wxAuiDefaultToolBarArt()
{
m_baseColour = GetBaseColor();
m_flags = 0;
m_textOrientation = wxAUI_TBTOOL_TEXT_BOTTOM;
m_highlightColour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
m_separatorSize = 7;
m_gripperSize = 7;
m_overflowSize = 16;
wxColor darker1Colour = m_baseColour.ChangeLightness(85);
wxColor darker2Colour = m_baseColour.ChangeLightness(75);
wxColor darker3Colour = m_baseColour.ChangeLightness(60);
wxColor darker4Colour = m_baseColour.ChangeLightness(50);
wxColor darker5Colour = m_baseColour.ChangeLightness(40);
m_gripperPen1 = wxPen(darker5Colour);
m_gripperPen2 = wxPen(darker3Colour);
m_gripperPen3 = *wxWHITE_PEN;
static const unsigned char buttonDropdownBits[] = { 0xe0, 0xf1, 0xfb };
static const unsigned char overflowBits[] = { 0x80, 0xff, 0x80, 0xc1, 0xe3, 0xf7 };
m_buttonDropDownBmp = wxAuiBitmapFromBits(buttonDropdownBits, 5, 3,
*wxBLACK);
m_disabledButtonDropDownBmp = wxAuiBitmapFromBits(
buttonDropdownBits, 5, 3,
wxColor(128,128,128));
m_overflowBmp = wxAuiBitmapFromBits(overflowBits, 7, 6, *wxBLACK);
m_disabledOverflowBmp = wxAuiBitmapFromBits(overflowBits, 7, 6, wxColor(128,128,128));
m_font = *wxNORMAL_FONT;
}
wxAuiDefaultToolBarArt::~wxAuiDefaultToolBarArt()
{
m_font = *wxNORMAL_FONT;
}
wxAuiToolBarArt* wxAuiDefaultToolBarArt::Clone()
{
return static_cast<wxAuiToolBarArt*>(new wxAuiDefaultToolBarArt);
}
void wxAuiDefaultToolBarArt::SetFlags(unsigned int flags)
{
m_flags = flags;
}
void wxAuiDefaultToolBarArt::SetFont(const wxFont& font)
{
m_font = font;
}
void wxAuiDefaultToolBarArt::SetTextOrientation(int orientation)
{
m_textOrientation = orientation;
}
unsigned int wxAuiDefaultToolBarArt::GetFlags()
{
return m_flags;
}
wxFont wxAuiDefaultToolBarArt::GetFont()
{
return m_font;
}
int wxAuiDefaultToolBarArt::GetTextOrientation()
{
return m_textOrientation;
}
void wxAuiDefaultToolBarArt::DrawBackground(
wxDC& dc,
wxWindow* WXUNUSED(wnd),
const wxRect& _rect)
{
wxRect rect = _rect;
rect.height++;
wxColour startColour = m_baseColour.ChangeLightness(150);
wxColour endColour = m_baseColour.ChangeLightness(90);
dc.GradientFillLinear(rect, startColour, endColour, wxSOUTH);
}
void wxAuiDefaultToolBarArt::DrawLabel(
wxDC& dc,
wxWindow* WXUNUSED(wnd),
const wxAuiToolBarItem& item,
const wxRect& rect)
{
dc.SetFont(m_font);
dc.SetTextForeground(*wxBLACK);
// we only care about the text height here since the text
// will get cropped based on the width of the item
int textWidth = 0, textHeight = 0;
dc.GetTextExtent(wxT("ABCDHgj"), &textWidth, &textHeight);
// set the clipping region
wxRect clipRect = rect;
clipRect.width -= 1;
dc.SetClippingRegion(clipRect);
int textX, textY;
textX = rect.x + 1;
textY = rect.y + (rect.height-textHeight)/2;
dc.DrawText(item.GetLabel(), textX, textY);
dc.DestroyClippingRegion();
}
void wxAuiDefaultToolBarArt::DrawButton(
wxDC& dc,
wxWindow* WXUNUSED(wnd),
const wxAuiToolBarItem& item,
const wxRect& rect)
{
int textWidth = 0, textHeight = 0;
if (m_flags & wxAUI_TB_TEXT)
{
dc.SetFont(m_font);
int tx, ty;
dc.GetTextExtent(wxT("ABCDHgj"), &tx, &textHeight);
textWidth = 0;
dc.GetTextExtent(item.GetLabel(), &textWidth, &ty);
}
int bmpX = 0, bmpY = 0;
int textX = 0, textY = 0;
if (m_textOrientation == wxAUI_TBTOOL_TEXT_BOTTOM)
{
bmpX = rect.x +
(rect.width/2) -
(item.GetBitmap().GetWidth()/2);
bmpY = rect.y +
((rect.height-textHeight)/2) -
(item.GetBitmap().GetHeight()/2);
textX = rect.x + (rect.width/2) - (textWidth/2) + 1;
textY = rect.y + rect.height - textHeight - 1;
}
else if (m_textOrientation == wxAUI_TBTOOL_TEXT_RIGHT)
{
bmpX = rect.x + 3;
bmpY = rect.y +
(rect.height/2) -
(item.GetBitmap().GetHeight()/2);
textX = bmpX + 3 + item.GetBitmap().GetWidth();
textY = rect.y +
(rect.height/2) -
(textHeight/2);
}
if (!(item.GetState() & wxAUI_BUTTON_STATE_DISABLED))
{
if (item.GetState() & wxAUI_BUTTON_STATE_PRESSED)
{
dc.SetPen(wxPen(m_highlightColour));
dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(150)));
dc.DrawRectangle(rect);
}
else if ((item.GetState() & wxAUI_BUTTON_STATE_HOVER) || item.IsSticky())
{
dc.SetPen(wxPen(m_highlightColour));
dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(170)));
// draw an even lighter background for checked item hovers (since
// the hover background is the same color as the check background)
if (item.GetState() & wxAUI_BUTTON_STATE_CHECKED)
dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(180)));
dc.DrawRectangle(rect);
}
else if (item.GetState() & wxAUI_BUTTON_STATE_CHECKED)
{
// it's important to put this code in an else statment after the
// hover, otherwise hovers won't draw properly for checked items
dc.SetPen(wxPen(m_highlightColour));
dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(170)));
dc.DrawRectangle(rect);
}
}
wxBitmap bmp;
if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
bmp = item.GetDisabledBitmap();
else
bmp = item.GetBitmap();
if ( bmp.IsOk() )
dc.DrawBitmap(bmp, bmpX, bmpY, true);
// set the item's text color based on if it is disabled
dc.SetTextForeground(*wxBLACK);
if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
dc.SetTextForeground(DISABLED_TEXT_COLOR);
if ( (m_flags & wxAUI_TB_TEXT) && !item.GetLabel().empty() )
{
dc.DrawText(item.GetLabel(), textX, textY);
}
}
void wxAuiDefaultToolBarArt::DrawDropDownButton(
wxDC& dc,
wxWindow* WXUNUSED(wnd),
const wxAuiToolBarItem& item,
const wxRect& rect)
{
int textWidth = 0, textHeight = 0, textX = 0, textY = 0;
int bmpX = 0, bmpY = 0, dropBmpX = 0, dropBmpY = 0;
wxRect buttonRect = wxRect(rect.x,
rect.y,
rect.width-BUTTON_DROPDOWN_WIDTH,
rect.height);
wxRect dropDownRect = wxRect(rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1,
rect.y,
BUTTON_DROPDOWN_WIDTH+1,
rect.height);
if (m_flags & wxAUI_TB_TEXT)
{
dc.SetFont(m_font);
int tx, ty;
if (m_flags & wxAUI_TB_TEXT)
{
dc.GetTextExtent(wxT("ABCDHgj"), &tx, &textHeight);
textWidth = 0;
}
dc.GetTextExtent(item.GetLabel(), &textWidth, &ty);
}
dropBmpX = dropDownRect.x +
(dropDownRect.width/2) -
(m_buttonDropDownBmp.GetWidth()/2);
dropBmpY = dropDownRect.y +
(dropDownRect.height/2) -
(m_buttonDropDownBmp.GetHeight()/2);
if (m_textOrientation == wxAUI_TBTOOL_TEXT_BOTTOM)
{
bmpX = buttonRect.x +
(buttonRect.width/2) -
(item.GetBitmap().GetWidth()/2);
bmpY = buttonRect.y +
((buttonRect.height-textHeight)/2) -
(item.GetBitmap().GetHeight()/2);
textX = rect.x + (rect.width/2) - (textWidth/2) + 1;
textY = rect.y + rect.height - textHeight - 1;
}
else if (m_textOrientation == wxAUI_TBTOOL_TEXT_RIGHT)
{
bmpX = rect.x + 3;
bmpY = rect.y +
(rect.height/2) -
(item.GetBitmap().GetHeight()/2);
textX = bmpX + 3 + item.GetBitmap().GetWidth();
textY = rect.y +
(rect.height/2) -
(textHeight/2);
}
if (item.GetState() & wxAUI_BUTTON_STATE_PRESSED)
{
dc.SetPen(wxPen(m_highlightColour));
dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(140)));
dc.DrawRectangle(buttonRect);
dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(170)));
dc.DrawRectangle(dropDownRect);
}
else if (item.GetState() & wxAUI_BUTTON_STATE_HOVER ||
item.IsSticky())
{
dc.SetPen(wxPen(m_highlightColour));
dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(170)));
dc.DrawRectangle(buttonRect);
dc.DrawRectangle(dropDownRect);
}
else if (item.GetState() & wxAUI_BUTTON_STATE_CHECKED)
{
// Notice that this branch must come after the hover one to ensure the
// correct appearance when the mouse hovers over a checked item.m_
dc.SetPen(wxPen(m_highlightColour));
dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(170)));
dc.DrawRectangle(buttonRect);
dc.DrawRectangle(dropDownRect);
}
wxBitmap bmp;
wxBitmap dropbmp;
if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
{
bmp = item.GetDisabledBitmap();
dropbmp = m_disabledButtonDropDownBmp;
}
else
{
bmp = item.GetBitmap();
dropbmp = m_buttonDropDownBmp;
}
if (!bmp.IsOk())
return;
dc.DrawBitmap(bmp, bmpX, bmpY, true);
dc.DrawBitmap(dropbmp, dropBmpX, dropBmpY, true);
// set the item's text color based on if it is disabled
dc.SetTextForeground(*wxBLACK);
if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
dc.SetTextForeground(DISABLED_TEXT_COLOR);
if ( (m_flags & wxAUI_TB_TEXT) && !item.GetLabel().empty() )
{
dc.DrawText(item.GetLabel(), textX, textY);
}
}
void wxAuiDefaultToolBarArt::DrawControlLabel(
wxDC& dc,
wxWindow* WXUNUSED(wnd),
const wxAuiToolBarItem& item,
const wxRect& rect)
{
if (!(m_flags & wxAUI_TB_TEXT))
return;
if (m_textOrientation != wxAUI_TBTOOL_TEXT_BOTTOM)
return;
int textX = 0, textY = 0;
int textWidth = 0, textHeight = 0;
dc.SetFont(m_font);
int tx, ty;
if (m_flags & wxAUI_TB_TEXT)
{
dc.GetTextExtent(wxT("ABCDHgj"), &tx, &textHeight);
textWidth = 0;
}
dc.GetTextExtent(item.GetLabel(), &textWidth, &ty);
// don't draw the label if it is wider than the item width
if (textWidth > rect.width)
return;
// set the label's text color
dc.SetTextForeground(*wxBLACK);
textX = rect.x + (rect.width/2) - (textWidth/2) + 1;
textY = rect.y + rect.height - textHeight - 1;
if ( (m_flags & wxAUI_TB_TEXT) && !item.GetLabel().empty() )
{
dc.DrawText(item.GetLabel(), textX, textY);
}
}
wxSize wxAuiDefaultToolBarArt::GetLabelSize(
wxDC& dc,
wxWindow* WXUNUSED(wnd),
const wxAuiToolBarItem& item)
{
dc.SetFont(m_font);
// get label's height
int width = 0, height = 0;
dc.GetTextExtent(wxT("ABCDHgj"), &width, &height);
// get item's width
width = item.GetMinSize().GetWidth();
if (width == -1)
{
// no width specified, measure the text ourselves
width = dc.GetTextExtent(item.GetLabel()).GetX();
}
return wxSize(width, height);
}
wxSize wxAuiDefaultToolBarArt::GetToolSize(
wxDC& dc,
wxWindow* WXUNUSED(wnd),
const wxAuiToolBarItem& item)
{
if (!item.GetBitmap().IsOk() && !(m_flags & wxAUI_TB_TEXT))
return wxSize(16,16);
int width = item.GetBitmap().GetWidth();
int height = item.GetBitmap().GetHeight();
if (m_flags & wxAUI_TB_TEXT)
{
dc.SetFont(m_font);
int tx, ty;
if (m_textOrientation == wxAUI_TBTOOL_TEXT_BOTTOM)
{
dc.GetTextExtent(wxT("ABCDHgj"), &tx, &ty);
height += ty;
if ( !item.GetLabel().empty() )
{
dc.GetTextExtent(item.GetLabel(), &tx, &ty);
width = wxMax(width, tx+6);
}
}
else if ( m_textOrientation == wxAUI_TBTOOL_TEXT_RIGHT &&
!item.GetLabel().empty() )
{
width += 3; // space between left border and bitmap
width += 3; // space between bitmap and text
if ( !item.GetLabel().empty() )
{
dc.GetTextExtent(item.GetLabel(), &tx, &ty);
width += tx;
height = wxMax(height, ty);
}
}
}
// if the tool has a dropdown button, add it to the width
if (item.HasDropDown())
width += (BUTTON_DROPDOWN_WIDTH+4);
return wxSize(width, height);
}
void wxAuiDefaultToolBarArt::DrawSeparator(
wxDC& dc,
wxWindow* WXUNUSED(wnd),
const wxRect& _rect)
{
bool horizontal = true;
if (m_flags & wxAUI_TB_VERTICAL)
horizontal = false;
wxRect rect = _rect;
if (horizontal)
{
rect.x += (rect.width/2);
rect.width = 1;
int new_height = (rect.height*3)/4;
rect.y += (rect.height/2) - (new_height/2);
rect.height = new_height;
}
else
{
rect.y += (rect.height/2);
rect.height = 1;
int new_width = (rect.width*3)/4;
rect.x += (rect.width/2) - (new_width/2);
rect.width = new_width;
}
wxColour startColour = m_baseColour.ChangeLightness(80);
wxColour endColour = m_baseColour.ChangeLightness(80);
dc.GradientFillLinear(rect, startColour, endColour, horizontal ? wxSOUTH : wxEAST);
}
void wxAuiDefaultToolBarArt::DrawGripper(wxDC& dc,
wxWindow* WXUNUSED(wnd),
const wxRect& rect)
{
int i = 0;
while (1)
{
int x, y;
if (m_flags & wxAUI_TB_VERTICAL)
{
x = rect.x + (i*4) + 5;
y = rect.y + 3;
if (x > rect.GetWidth()-5)
break;
}
else
{
x = rect.x + 3;
y = rect.y + (i*4) + 5;
if (y > rect.GetHeight()-5)
break;
}
dc.SetPen(m_gripperPen1);
dc.DrawPoint(x, y);
dc.SetPen(m_gripperPen2);
dc.DrawPoint(x, y+1);
dc.DrawPoint(x+1, y);
dc.SetPen(m_gripperPen3);
dc.DrawPoint(x+2, y+1);
dc.DrawPoint(x+2, y+2);
dc.DrawPoint(x+1, y+2);
i++;
}
}
void wxAuiDefaultToolBarArt::DrawOverflowButton(wxDC& dc,
wxWindow* /*wnd*/,
const wxRect& rect,
int state)
{
if (state & wxAUI_BUTTON_STATE_HOVER ||
state & wxAUI_BUTTON_STATE_PRESSED)
{
wxColor light_gray_bg = m_highlightColour.ChangeLightness(170);
if (m_flags & wxAUI_TB_VERTICAL)
{
dc.SetPen(wxPen(m_highlightColour));
dc.DrawLine(rect.x, rect.y, rect.x+rect.width, rect.y);
dc.SetPen(wxPen(light_gray_bg));
dc.SetBrush(wxBrush(light_gray_bg));
dc.DrawRectangle(rect.x, rect.y+1, rect.width, rect.height);
}
else
{
dc.SetPen(wxPen(m_highlightColour));
dc.DrawLine(rect.x, rect.y, rect.x, rect.y+rect.height);
dc.SetPen(wxPen(light_gray_bg));
dc.SetBrush(wxBrush(light_gray_bg));
dc.DrawRectangle(rect.x+1, rect.y, rect.width, rect.height);
}
}
int x = rect.x+1+(rect.width-m_overflowBmp.GetWidth())/2;
int y = rect.y+1+(rect.height-m_overflowBmp.GetHeight())/2;
dc.DrawBitmap(m_overflowBmp, x, y, true);
}
int wxAuiDefaultToolBarArt::GetElementSize(int element_id)
{
switch (element_id)
{
case wxAUI_TBART_SEPARATOR_SIZE: return m_separatorSize;
case wxAUI_TBART_GRIPPER_SIZE: return m_gripperSize;
case wxAUI_TBART_OVERFLOW_SIZE: return m_overflowSize;
default: return 0;
}
}
void wxAuiDefaultToolBarArt::SetElementSize(int element_id, int size)
{
switch (element_id)
{
case wxAUI_TBART_SEPARATOR_SIZE: m_separatorSize = size; break;
case wxAUI_TBART_GRIPPER_SIZE: m_gripperSize = size; break;
case wxAUI_TBART_OVERFLOW_SIZE: m_overflowSize = size; break;
}
}
int wxAuiDefaultToolBarArt::ShowDropDown(wxWindow* wnd,
const wxAuiToolBarItemArray& items)
{
wxMenu menuPopup;
size_t items_added = 0;
size_t i, count = items.GetCount();
for (i = 0; i < count; ++i)
{
wxAuiToolBarItem& item = items.Item(i);
if (item.GetKind() == wxITEM_NORMAL)
{
wxString text = item.GetShortHelp();
if (text.empty())
text = item.GetLabel();
if (text.empty())
text = wxT(" ");
wxMenuItem* m = new wxMenuItem(&menuPopup, item.GetId(), text, item.GetShortHelp());
m->SetBitmap(item.GetBitmap());
menuPopup.Append(m);
items_added++;
}
else if (item.GetKind() == wxITEM_SEPARATOR)
{
if (items_added > 0)
menuPopup.AppendSeparator();
}
}
// find out where to put the popup menu of window items
wxPoint pt = ::wxGetMousePosition();
pt = wnd->ScreenToClient(pt);
// find out the screen coordinate at the bottom of the tab ctrl
wxRect cli_rect = wnd->GetClientRect();
pt.y = cli_rect.y + cli_rect.height;
ToolbarCommandCapture* cc = new ToolbarCommandCapture;
wnd->PushEventHandler(cc);
wnd->PopupMenu(&menuPopup, pt);
int command = cc->GetCommandId();
wnd->PopEventHandler(true);
return command;
}
static wxOrientation GetOrientation(long& style)
{
switch (style & wxAUI_ORIENTATION_MASK)
{
case wxAUI_TB_HORIZONTAL:
return wxHORIZONTAL;
case wxAUI_TB_VERTICAL:
return wxVERTICAL;
default:
wxFAIL_MSG("toolbar cannot be locked in both horizontal and vertical orientations (maybe no lock was intended?)");
// fall through
case 0:
return wxBOTH;
}
}
BEGIN_EVENT_TABLE(wxAuiToolBar, wxControl)
EVT_SIZE(wxAuiToolBar::OnSize)
EVT_IDLE(wxAuiToolBar::OnIdle)
EVT_ERASE_BACKGROUND(wxAuiToolBar::OnEraseBackground)
EVT_PAINT(wxAuiToolBar::OnPaint)
EVT_LEFT_DOWN(wxAuiToolBar::OnLeftDown)
EVT_LEFT_DCLICK(wxAuiToolBar::OnLeftDown)
EVT_LEFT_UP(wxAuiToolBar::OnLeftUp)
EVT_RIGHT_DOWN(wxAuiToolBar::OnRightDown)
EVT_RIGHT_DCLICK(wxAuiToolBar::OnRightDown)
EVT_RIGHT_UP(wxAuiToolBar::OnRightUp)
EVT_MIDDLE_DOWN(wxAuiToolBar::OnMiddleDown)
EVT_MIDDLE_DCLICK(wxAuiToolBar::OnMiddleDown)
EVT_MIDDLE_UP(wxAuiToolBar::OnMiddleUp)
EVT_MOTION(wxAuiToolBar::OnMotion)
EVT_LEAVE_WINDOW(wxAuiToolBar::OnLeaveWindow)
EVT_MOUSE_CAPTURE_LOST(wxAuiToolBar::OnCaptureLost)
EVT_SET_CURSOR(wxAuiToolBar::OnSetCursor)
END_EVENT_TABLE()
wxAuiToolBar::wxAuiToolBar(wxWindow* parent,
wxWindowID id,
const wxPoint& position,
const wxSize& size,
long style)
: wxControl(parent,
id,
position,
size,
style | wxBORDER_NONE)
{
m_sizer = new wxBoxSizer(wxHORIZONTAL);
m_buttonWidth = -1;
m_buttonHeight = -1;
m_sizerElementCount = 0;
m_actionPos = wxPoint(-1,-1);
m_actionItem = NULL;
m_tipItem = NULL;
m_art = new wxAuiDefaultToolBarArt;
m_toolPacking = 2;
m_toolBorderPadding = 3;
m_toolTextOrientation = wxAUI_TBTOOL_TEXT_BOTTOM;
m_gripperSizerItem = NULL;
m_overflowSizerItem = NULL;
m_dragging = false;
m_orientation = GetOrientation(style);
if (m_orientation == wxBOTH)
{
m_orientation = wxHORIZONTAL;
}
m_style = style | wxBORDER_NONE;
m_gripperVisible = (m_style & wxAUI_TB_GRIPPER) ? true : false;
m_overflowVisible = (m_style & wxAUI_TB_OVERFLOW) ? true : false;
m_overflowState = 0;
SetMargins(5, 5, 2, 2);
SetFont(*wxNORMAL_FONT);
SetArtFlags();
SetExtraStyle(wxWS_EX_PROCESS_IDLE);
if (style & wxAUI_TB_HORZ_LAYOUT)
SetToolTextOrientation(wxAUI_TBTOOL_TEXT_RIGHT);
SetBackgroundStyle(wxBG_STYLE_CUSTOM);
}
wxAuiToolBar::~wxAuiToolBar()
{
delete m_art;
delete m_sizer;
}
void wxAuiToolBar::SetWindowStyleFlag(long style)
{
GetOrientation(style); // assert if style is invalid
wxCHECK_RET(IsPaneValid(style),
"window settings and pane settings are incompatible");
wxControl::SetWindowStyleFlag(style);
m_style = style;
if (m_art)
{
SetArtFlags();
}
if (m_style & wxAUI_TB_GRIPPER)
m_gripperVisible = true;
else
m_gripperVisible = false;
if (m_style & wxAUI_TB_OVERFLOW)
m_overflowVisible = true;
else
m_overflowVisible = false;
if (style & wxAUI_TB_HORZ_LAYOUT)
SetToolTextOrientation(wxAUI_TBTOOL_TEXT_RIGHT);
else
SetToolTextOrientation(wxAUI_TBTOOL_TEXT_BOTTOM);
}
long wxAuiToolBar::GetWindowStyleFlag() const
{
return m_style;
}
void wxAuiToolBar::SetArtProvider(wxAuiToolBarArt* art)
{
delete m_art;
m_art = art;
if (m_art)
{
SetArtFlags();
m_art->SetTextOrientation(m_toolTextOrientation);
}
}
wxAuiToolBarArt* wxAuiToolBar::GetArtProvider() const
{
return m_art;
}
wxAuiToolBarItem* wxAuiToolBar::AddTool(int tool_id,
const wxString& label,
const wxBitmap& bitmap,
const wxString& shortHelp_string,
wxItemKind kind)
{
return AddTool(tool_id,
label,
bitmap,
wxNullBitmap,
kind,
shortHelp_string,
wxEmptyString,
NULL);
}
wxAuiToolBarItem* wxAuiToolBar::AddTool(int tool_id,
const wxString& label,
const wxBitmap& bitmap,
const wxBitmap& disabledBitmap,
wxItemKind kind,
const wxString& shortHelpString,
const wxString& longHelpString,
wxObject* WXUNUSED(client_data))
{
wxAuiToolBarItem item;
item.m_window = NULL;
item.m_label = label;
item.m_bitmap = bitmap;
item.m_disabledBitmap = disabledBitmap;
item.m_shortHelp = shortHelpString;
item.m_longHelp = longHelpString;
item.m_active = true;
item.m_dropDown = false;
item.m_spacerPixels = 0;
item.m_toolId = tool_id;
item.m_state = 0;
item.m_proportion = 0;
item.m_kind = kind;
item.m_sizerItem = NULL;
item.m_minSize = wxDefaultSize;
item.m_userData = 0;
item.m_sticky = false;
if (item.m_toolId == wxID_ANY)
item.m_toolId = wxNewId();
if (!item.m_disabledBitmap.IsOk())
{
// no disabled bitmap specified, we need to make one
if (item.m_bitmap.IsOk())
{
item.m_disabledBitmap = item.m_bitmap.ConvertToDisabled();
}
}
m_items.Add(item);
return &m_items.Last();
}
wxAuiToolBarItem* wxAuiToolBar::AddControl(wxControl* control,
const wxString& label)
{
wxAuiToolBarItem item;
item.m_window = (wxWindow*)control;
item.m_label = label;
item.m_bitmap = wxNullBitmap;
item.m_disabledBitmap = wxNullBitmap;
item.m_active = true;
item.m_dropDown = false;
item.m_spacerPixels = 0;
item.m_toolId = control->GetId();
item.m_state = 0;
item.m_proportion = 0;
item.m_kind = wxITEM_CONTROL;
item.m_sizerItem = NULL;
item.m_minSize = control->GetEffectiveMinSize();
item.m_userData = 0;
item.m_sticky = false;
m_items.Add(item);
return &m_items.Last();
}
wxAuiToolBarItem* wxAuiToolBar::AddLabel(int tool_id,
const wxString& label,
const int width)
{
wxSize min_size = wxDefaultSize;
if (width != -1)
min_size.x = width;
wxAuiToolBarItem item;
item.m_window = NULL;
item.m_label = label;
item.m_bitmap = wxNullBitmap;
item.m_disabledBitmap = wxNullBitmap;
item.m_active = true;
item.m_dropDown = false;
item.m_spacerPixels = 0;
item.m_toolId = tool_id;
item.m_state = 0;
item.m_proportion = 0;
item.m_kind = wxITEM_LABEL;
item.m_sizerItem = NULL;
item.m_minSize = min_size;
item.m_userData = 0;
item.m_sticky = false;
if (item.m_toolId == wxID_ANY)
item.m_toolId = wxNewId();
m_items.Add(item);
return &m_items.Last();
}
wxAuiToolBarItem* wxAuiToolBar::AddSeparator()
{
wxAuiToolBarItem item;
item.m_window = NULL;
item.m_label = wxEmptyString;
item.m_bitmap = wxNullBitmap;
item.m_disabledBitmap = wxNullBitmap;
item.m_active = true;
item.m_dropDown = false;
item.m_toolId = -1;
item.m_state = 0;
item.m_proportion = 0;
item.m_kind = wxITEM_SEPARATOR;
item.m_sizerItem = NULL;
item.m_minSize = wxDefaultSize;
item.m_userData = 0;
item.m_sticky = false;
m_items.Add(item);
return &m_items.Last();
}
wxAuiToolBarItem* wxAuiToolBar::AddSpacer(int pixels)
{
wxAuiToolBarItem item;
item.m_window = NULL;
item.m_label = wxEmptyString;
item.m_bitmap = wxNullBitmap;
item.m_disabledBitmap = wxNullBitmap;
item.m_active = true;
item.m_dropDown = false;
item.m_spacerPixels = pixels;
item.m_toolId = -1;
item.m_state = 0;
item.m_proportion = 0;
item.m_kind = wxITEM_SPACER;
item.m_sizerItem = NULL;
item.m_minSize = wxDefaultSize;
item.m_userData = 0;
item.m_sticky = false;
m_items.Add(item);
return &m_items.Last();
}
wxAuiToolBarItem* wxAuiToolBar::AddStretchSpacer(int proportion)
{
wxAuiToolBarItem item;
item.m_window = NULL;
item.m_label = wxEmptyString;
item.m_bitmap = wxNullBitmap;
item.m_disabledBitmap = wxNullBitmap;
item.m_active = true;
item.m_dropDown = false;
item.m_spacerPixels = 0;
item.m_toolId = -1;
item.m_state = 0;
item.m_proportion = proportion;
item.m_kind = wxITEM_SPACER;
item.m_sizerItem = NULL;
item.m_minSize = wxDefaultSize;
item.m_userData = 0;
item.m_sticky = false;
m_items.Add(item);
return &m_items.Last();
}
void wxAuiToolBar::Clear()
{
m_items.Clear();
m_sizerElementCount = 0;
}
bool wxAuiToolBar::DeleteTool(int tool_id)
{
int idx = GetToolIndex(tool_id);
if (idx >= 0 && idx < (int)m_items.GetCount())
{
m_items.RemoveAt(idx);
Realize();
return true;
}
return false;
}
bool wxAuiToolBar::DeleteByIndex(int idx)
{
if (idx >= 0 && idx < (int)m_items.GetCount())
{
m_items.RemoveAt(idx);
Realize();
return true;
}
return false;
}
wxControl* wxAuiToolBar::FindControl(int id)
{
wxWindow* wnd = FindWindow(id);
return (wxControl*)wnd;
}
wxAuiToolBarItem* wxAuiToolBar::FindTool(int tool_id) const
{
size_t i, count;
for (i = 0, count = m_items.GetCount(); i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
if (item.m_toolId == tool_id)
return &item;
}
return NULL;
}
wxAuiToolBarItem* wxAuiToolBar::FindToolByPosition(wxCoord x, wxCoord y) const
{
size_t i, count;
for (i = 0, count = m_items.GetCount(); i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
if (!item.m_sizerItem)
continue;
wxRect rect = item.m_sizerItem->GetRect();
if (rect.Contains(x,y))
{
// if the item doesn't fit on the toolbar, return NULL
if (!GetToolFitsByIndex(i))
return NULL;
return &item;
}
}
return NULL;
}
wxAuiToolBarItem* wxAuiToolBar::FindToolByPositionWithPacking(wxCoord x, wxCoord y) const
{
size_t i, count;
for (i = 0, count = m_items.GetCount(); i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
if (!item.m_sizerItem)
continue;
wxRect rect = item.m_sizerItem->GetRect();
// apply tool packing
if (i+1 < count)
rect.width += m_toolPacking;
if (rect.Contains(x,y))
{
// if the item doesn't fit on the toolbar, return NULL
if (!GetToolFitsByIndex(i))
return NULL;
return &item;
}
}
return NULL;
}
wxAuiToolBarItem* wxAuiToolBar::FindToolByIndex(int idx) const
{
if (idx < 0)
return NULL;
if (idx >= (int)m_items.size())
return NULL;
return &(m_items[idx]);
}
void wxAuiToolBar::SetToolBitmapSize(const wxSize& WXUNUSED(size))
{
// TODO: wxToolBar compatibility
}
wxSize wxAuiToolBar::GetToolBitmapSize() const
{
// TODO: wxToolBar compatibility
return wxSize(16,15);
}
void wxAuiToolBar::SetToolProportion(int tool_id, int proportion)
{
wxAuiToolBarItem* item = FindTool(tool_id);
if (!item)
return;
item->m_proportion = proportion;
}
int wxAuiToolBar::GetToolProportion(int tool_id) const
{
wxAuiToolBarItem* item = FindTool(tool_id);
if (!item)
return 0;
return item->m_proportion;
}
void wxAuiToolBar::SetToolSeparation(int separation)
{
if (m_art)
m_art->SetElementSize(wxAUI_TBART_SEPARATOR_SIZE, separation);
}
int wxAuiToolBar::GetToolSeparation() const
{
if (m_art)
return m_art->GetElementSize(wxAUI_TBART_SEPARATOR_SIZE);
else
return 5;
}
void wxAuiToolBar::SetToolDropDown(int tool_id, bool dropdown)
{
wxAuiToolBarItem* item = FindTool(tool_id);
if (!item)
return;
item->m_dropDown = dropdown;
}
bool wxAuiToolBar::GetToolDropDown(int tool_id) const
{
wxAuiToolBarItem* item = FindTool(tool_id);
if (!item)
return 0;
return item->m_dropDown;
}
void wxAuiToolBar::SetToolSticky(int tool_id, bool sticky)
{
// ignore separators
if (tool_id == -1)
return;
wxAuiToolBarItem* item = FindTool(tool_id);
if (!item)
return;
if (item->m_sticky == sticky)
return;
item->m_sticky = sticky;
Refresh(false);
Update();
}
bool wxAuiToolBar::GetToolSticky(int tool_id) const
{
wxAuiToolBarItem* item = FindTool(tool_id);
if (!item)
return 0;
return item->m_sticky;
}
void wxAuiToolBar::SetToolBorderPadding(int padding)
{
m_toolBorderPadding = padding;
}
int wxAuiToolBar::GetToolBorderPadding() const
{
return m_toolBorderPadding;
}
void wxAuiToolBar::SetToolTextOrientation(int orientation)
{
m_toolTextOrientation = orientation;
if (m_art)
{
m_art->SetTextOrientation(orientation);
}
}
int wxAuiToolBar::GetToolTextOrientation() const
{
return m_toolTextOrientation;
}
void wxAuiToolBar::SetToolPacking(int packing)
{
m_toolPacking = packing;
}
int wxAuiToolBar::GetToolPacking() const
{
return m_toolPacking;
}
void wxAuiToolBar::SetOrientation(int orientation)
{
wxCHECK_RET(orientation == wxHORIZONTAL ||
orientation == wxVERTICAL,
"invalid orientation value");
if (orientation != m_orientation)
{
m_orientation = wxOrientation(orientation);
SetArtFlags();
}
}
void wxAuiToolBar::SetMargins(int left, int right, int top, int bottom)
{
if (left != -1)
m_leftPadding = left;
if (right != -1)
m_rightPadding = right;
if (top != -1)
m_topPadding = top;
if (bottom != -1)
m_bottomPadding = bottom;
}
bool wxAuiToolBar::GetGripperVisible() const
{
return m_gripperVisible;
}
void wxAuiToolBar::SetGripperVisible(bool visible)
{
m_gripperVisible = visible;
if (visible)
m_style |= wxAUI_TB_GRIPPER;
else
m_style &= ~wxAUI_TB_GRIPPER;
Realize();
Refresh(false);
}
bool wxAuiToolBar::GetOverflowVisible() const
{
return m_overflowVisible;
}
void wxAuiToolBar::SetOverflowVisible(bool visible)
{
m_overflowVisible = visible;
if (visible)
m_style |= wxAUI_TB_OVERFLOW;
else
m_style &= ~wxAUI_TB_OVERFLOW;
Refresh(false);
}
bool wxAuiToolBar::SetFont(const wxFont& font)
{
bool res = wxWindow::SetFont(font);
if (m_art)
{
m_art->SetFont(font);
}
return res;
}
void wxAuiToolBar::SetHoverItem(wxAuiToolBarItem* pitem)
{
wxAuiToolBarItem* former_hover = NULL;
size_t i, count;
for (i = 0, count = m_items.GetCount(); i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
if (item.m_state & wxAUI_BUTTON_STATE_HOVER)
former_hover = &item;
item.m_state &= ~wxAUI_BUTTON_STATE_HOVER;
}
if (pitem)
{
pitem->m_state |= wxAUI_BUTTON_STATE_HOVER;
}
if (former_hover != pitem)
{
Refresh(false);
Update();
}
}
void wxAuiToolBar::SetPressedItem(wxAuiToolBarItem* pitem)
{
wxAuiToolBarItem* former_item = NULL;
size_t i, count;
for (i = 0, count = m_items.GetCount(); i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
if (item.m_state & wxAUI_BUTTON_STATE_PRESSED)
former_item = &item;
item.m_state &= ~wxAUI_BUTTON_STATE_PRESSED;
}
if (pitem)
{
pitem->m_state &= ~wxAUI_BUTTON_STATE_HOVER;
pitem->m_state |= wxAUI_BUTTON_STATE_PRESSED;
}
if (former_item != pitem)
{
Refresh(false);
Update();
}
}
void wxAuiToolBar::RefreshOverflowState()
{
if (!m_overflowSizerItem)
{
m_overflowState = 0;
return;
}
int overflow_state = 0;
wxRect overflow_rect = GetOverflowRect();
// find out the mouse's current position
wxPoint pt = ::wxGetMousePosition();
pt = this->ScreenToClient(pt);
// find out if the mouse cursor is inside the dropdown rectangle
if (overflow_rect.Contains(pt.x, pt.y))
{
if (::wxGetMouseState().LeftIsDown())
overflow_state = wxAUI_BUTTON_STATE_PRESSED;
else
overflow_state = wxAUI_BUTTON_STATE_HOVER;
}
if (overflow_state != m_overflowState)
{
m_overflowState = overflow_state;
Refresh(false);
Update();
}
m_overflowState = overflow_state;
}
void wxAuiToolBar::ToggleTool(int tool_id, bool state)
{
wxAuiToolBarItem* tool = FindTool(tool_id);
if (tool && (tool->m_kind == wxITEM_CHECK || tool->m_kind == wxITEM_RADIO))
{
if (tool->m_kind == wxITEM_RADIO)
{
int i, idx, count;
idx = GetToolIndex(tool_id);
count = (int)m_items.GetCount();
if (idx >= 0 && idx < count)
{
for (i = idx + 1; i < count; ++i)
{
if (m_items[i].m_kind != wxITEM_RADIO)
break;
m_items[i].m_state &= ~wxAUI_BUTTON_STATE_CHECKED;
}
for (i = idx - 1; i >= 0; i--)
{
if (m_items[i].m_kind != wxITEM_RADIO)
break;
m_items[i].m_state &= ~wxAUI_BUTTON_STATE_CHECKED;
}
}
tool->m_state |= wxAUI_BUTTON_STATE_CHECKED;
}
else if (tool->m_kind == wxITEM_CHECK)
{
if (state == true)
tool->m_state |= wxAUI_BUTTON_STATE_CHECKED;
else
tool->m_state &= ~wxAUI_BUTTON_STATE_CHECKED;
}
}
}
bool wxAuiToolBar::GetToolToggled(int tool_id) const
{
wxAuiToolBarItem* tool = FindTool(tool_id);
if (tool)
{
if ( (tool->m_kind != wxITEM_CHECK) && (tool->m_kind != wxITEM_RADIO) )
return false;
return (tool->m_state & wxAUI_BUTTON_STATE_CHECKED) ? true : false;
}
return false;
}
void wxAuiToolBar::EnableTool(int tool_id, bool state)
{
wxAuiToolBarItem* tool = FindTool(tool_id);
if (tool)
{
if (state == true)
tool->m_state &= ~wxAUI_BUTTON_STATE_DISABLED;
else
tool->m_state |= wxAUI_BUTTON_STATE_DISABLED;
}
}
bool wxAuiToolBar::GetToolEnabled(int tool_id) const
{
wxAuiToolBarItem* tool = FindTool(tool_id);
if (tool)
return (tool->m_state & wxAUI_BUTTON_STATE_DISABLED) ? false : true;
return false;
}
wxString wxAuiToolBar::GetToolLabel(int tool_id) const
{
wxAuiToolBarItem* tool = FindTool(tool_id);
wxASSERT_MSG(tool, wxT("can't find tool in toolbar item array"));
if (!tool)
return wxEmptyString;
return tool->m_label;
}
void wxAuiToolBar::SetToolLabel(int tool_id, const wxString& label)
{
wxAuiToolBarItem* tool = FindTool(tool_id);
if (tool)
{
tool->m_label = label;
}
}
wxBitmap wxAuiToolBar::GetToolBitmap(int tool_id) const
{
wxAuiToolBarItem* tool = FindTool(tool_id);
wxASSERT_MSG(tool, wxT("can't find tool in toolbar item array"));
if (!tool)
return wxNullBitmap;
return tool->m_bitmap;
}
void wxAuiToolBar::SetToolBitmap(int tool_id, const wxBitmap& bitmap)
{
wxAuiToolBarItem* tool = FindTool(tool_id);
if (tool)
{
tool->m_bitmap = bitmap;
}
}
wxString wxAuiToolBar::GetToolShortHelp(int tool_id) const
{
wxAuiToolBarItem* tool = FindTool(tool_id);
wxASSERT_MSG(tool, wxT("can't find tool in toolbar item array"));
if (!tool)
return wxEmptyString;
return tool->m_shortHelp;
}
void wxAuiToolBar::SetToolShortHelp(int tool_id, const wxString& help_string)
{
wxAuiToolBarItem* tool = FindTool(tool_id);
if (tool)
{
tool->m_shortHelp = help_string;
}
}
wxString wxAuiToolBar::GetToolLongHelp(int tool_id) const
{
wxAuiToolBarItem* tool = FindTool(tool_id);
wxASSERT_MSG(tool, wxT("can't find tool in toolbar item array"));
if (!tool)
return wxEmptyString;
return tool->m_longHelp;
}
void wxAuiToolBar::SetToolLongHelp(int tool_id, const wxString& help_string)
{
wxAuiToolBarItem* tool = FindTool(tool_id);
if (tool)
{
tool->m_longHelp = help_string;
}
}
void wxAuiToolBar::SetCustomOverflowItems(const wxAuiToolBarItemArray& prepend,
const wxAuiToolBarItemArray& append)
{
m_customOverflowPrepend = prepend;
m_customOverflowAppend = append;
}
// get size of hint rectangle for a particular dock location
wxSize wxAuiToolBar::GetHintSize(int dock_direction) const
{
switch (dock_direction)
{
case wxAUI_DOCK_TOP:
case wxAUI_DOCK_BOTTOM:
return m_horzHintSize;
case wxAUI_DOCK_RIGHT:
case wxAUI_DOCK_LEFT:
return m_vertHintSize;
default:
wxFAIL_MSG("invalid dock location value");
}
return wxDefaultSize;
}
bool wxAuiToolBar::IsPaneValid(const wxAuiPaneInfo& pane) const
{
return IsPaneValid(m_style, pane);
}
bool wxAuiToolBar::IsPaneValid(long style, const wxAuiPaneInfo& pane)
{
if (style & wxAUI_TB_HORIZONTAL)
{
if (pane.IsLeftDockable() || pane.IsRightDockable())
{
return false;
}
}
else if (style & wxAUI_TB_VERTICAL)
{
if (pane.IsTopDockable() || pane.IsBottomDockable())
{
return false;
}
}
return true;
}
bool wxAuiToolBar::IsPaneValid(long style) const
{
wxAuiManager* manager = wxAuiManager::GetManager(const_cast<wxAuiToolBar*>(this));
if (manager)
{
return IsPaneValid(style, manager->GetPane(const_cast<wxAuiToolBar*>(this)));
}
return true;
}
void wxAuiToolBar::SetArtFlags() const
{
unsigned int artflags = m_style & ~wxAUI_ORIENTATION_MASK;
if (m_orientation == wxVERTICAL)
{
artflags |= wxAUI_TB_VERTICAL;
}
m_art->SetFlags(artflags);
}
size_t wxAuiToolBar::GetToolCount() const
{
return m_items.size();
}
int wxAuiToolBar::GetToolIndex(int tool_id) const
{
// this will prevent us from returning the index of the
// first separator in the toolbar since its id is equal to -1
if (tool_id == -1)
return wxNOT_FOUND;
size_t i, count = m_items.GetCount();
for (i = 0; i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
if (item.m_toolId == tool_id)
return i;
}
return wxNOT_FOUND;
}
bool wxAuiToolBar::GetToolFitsByIndex(int tool_idx) const
{
if (tool_idx < 0 || tool_idx >= (int)m_items.GetCount())
return false;
if (!m_items[tool_idx].m_sizerItem)
return false;
int cli_w, cli_h;
GetClientSize(&cli_w, &cli_h);
wxRect rect = m_items[tool_idx].m_sizerItem->GetRect();
if (m_orientation == wxVERTICAL)
{
// take the dropdown size into account
if (m_overflowVisible)
cli_h -= m_overflowSizerItem->GetSize().y;
if (rect.y+rect.height < cli_h)
return true;
}
else
{
// take the dropdown size into account
if (m_overflowVisible)
cli_w -= m_overflowSizerItem->GetSize().x;
if (rect.x+rect.width < cli_w)
return true;
}
return false;
}
bool wxAuiToolBar::GetToolFits(int tool_id) const
{
return GetToolFitsByIndex(GetToolIndex(tool_id));
}
wxRect wxAuiToolBar::GetToolRect(int tool_id) const
{
wxAuiToolBarItem* tool = FindTool(tool_id);
if (tool && tool->m_sizerItem)
{
return tool->m_sizerItem->GetRect();
}
return wxRect();
}
bool wxAuiToolBar::GetToolBarFits() const
{
if (m_items.GetCount() == 0)
{
// empty toolbar always 'fits'
return true;
}
// entire toolbar content fits if the last tool fits
return GetToolFitsByIndex(m_items.GetCount() - 1);
}
bool wxAuiToolBar::Realize()
{
wxClientDC dc(this);
if (!dc.IsOk())
return false;
// calculate hint sizes for both horizontal and vertical
// in the order that leaves toolbar in correct final state
bool retval = false;
if (m_orientation == wxHORIZONTAL)
{
if (RealizeHelper(dc, false))
{
m_vertHintSize = GetSize();
if (RealizeHelper(dc, true))
{
m_horzHintSize = GetSize();
retval = true;
}
}
}
else
{
if (RealizeHelper(dc, true))
{
m_horzHintSize = GetSize();
if (RealizeHelper(dc, false))
{
m_vertHintSize = GetSize();
retval = true;
}
}
}
Refresh(false);
return retval;
}
bool wxAuiToolBar::RealizeHelper(wxClientDC& dc, bool horizontal)
{
// create the new sizer to add toolbar elements to
wxBoxSizer* sizer = new wxBoxSizer(horizontal ? wxHORIZONTAL : wxVERTICAL);
// add gripper area
int separatorSize = m_art->GetElementSize(wxAUI_TBART_SEPARATOR_SIZE);
int gripperSize = m_art->GetElementSize(wxAUI_TBART_GRIPPER_SIZE);
if (gripperSize > 0 && m_gripperVisible)
{
if (horizontal)
m_gripperSizerItem = sizer->Add(gripperSize, 1, 0, wxEXPAND);
else
m_gripperSizerItem = sizer->Add(1, gripperSize, 0, wxEXPAND);
}
else
{
m_gripperSizerItem = NULL;
}
// add "left" padding
if (m_leftPadding > 0)
{
if (horizontal)
sizer->Add(m_leftPadding, 1);
else
sizer->Add(1, m_leftPadding);
}
size_t i, count;
for (i = 0, count = m_items.GetCount(); i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
wxSizerItem* m_sizerItem = NULL;
switch (item.m_kind)
{
case wxITEM_LABEL:
{
wxSize size = m_art->GetLabelSize(dc, this, item);
m_sizerItem = sizer->Add(size.x + (m_toolBorderPadding*2),
size.y + (m_toolBorderPadding*2),
item.m_proportion,
item.m_alignment);
if (i+1 < count)
{
sizer->AddSpacer(m_toolPacking);
}
break;
}
case wxITEM_CHECK:
case wxITEM_NORMAL:
case wxITEM_RADIO:
{
wxSize size = m_art->GetToolSize(dc, this, item);
m_sizerItem = sizer->Add(size.x + (m_toolBorderPadding*2),
size.y + (m_toolBorderPadding*2),
0,
item.m_alignment);
// add tool packing
if (i+1 < count)
{
sizer->AddSpacer(m_toolPacking);
}
break;
}
case wxITEM_SEPARATOR:
{
if (horizontal)
m_sizerItem = sizer->Add(separatorSize, 1, 0, wxEXPAND);
else
m_sizerItem = sizer->Add(1, separatorSize, 0, wxEXPAND);
// add tool packing
if (i+1 < count)
{
sizer->AddSpacer(m_toolPacking);
}
break;
}
case wxITEM_SPACER:
if (item.m_proportion > 0)
m_sizerItem = sizer->AddStretchSpacer(item.m_proportion);
else
m_sizerItem = sizer->Add(item.m_spacerPixels, 1);
break;
case wxITEM_CONTROL:
{
//m_sizerItem = sizer->Add(item.m_window, item.m_proportion, wxEXPAND);
wxSizerItem* ctrl_m_sizerItem;
wxBoxSizer* vert_sizer = new wxBoxSizer(wxVERTICAL);
vert_sizer->AddStretchSpacer(1);
ctrl_m_sizerItem = vert_sizer->Add(item.m_window, 0, wxEXPAND);
vert_sizer->AddStretchSpacer(1);
if ( (m_style & wxAUI_TB_TEXT) &&
m_toolTextOrientation == wxAUI_TBTOOL_TEXT_BOTTOM &&
!item.GetLabel().empty() )
{
wxSize s = GetLabelSize(item.GetLabel());
vert_sizer->Add(1, s.y);
}
m_sizerItem = sizer->Add(vert_sizer, item.m_proportion, wxEXPAND);
wxSize min_size = item.m_minSize;
// proportional items will disappear from the toolbar if
// their min width is not set to something really small
if (item.m_proportion != 0)
{
min_size.x = 1;
}
if (min_size.IsFullySpecified())
{
m_sizerItem->SetMinSize(min_size);
ctrl_m_sizerItem->SetMinSize(min_size);
}
// add tool packing
if (i+1 < count)
{
sizer->AddSpacer(m_toolPacking);
}
}
}
item.m_sizerItem = m_sizerItem;
}
// add "right" padding
if (m_rightPadding > 0)
{
if (horizontal)
sizer->Add(m_rightPadding, 1);
else
sizer->Add(1, m_rightPadding);
}
// add drop down area
m_overflowSizerItem = NULL;
if (m_style & wxAUI_TB_OVERFLOW)
{
int overflow_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
if (overflow_size > 0 && m_overflowVisible)
{
if (horizontal)
m_overflowSizerItem = sizer->Add(overflow_size, 1, 0, wxEXPAND);
else
m_overflowSizerItem = sizer->Add(1, overflow_size, 0, wxEXPAND);
}
else
{
m_overflowSizerItem = NULL;
}
}
// the outside sizer helps us apply the "top" and "bottom" padding
wxBoxSizer* outside_sizer = new wxBoxSizer(horizontal ? wxVERTICAL : wxHORIZONTAL);
// add "top" padding
if (m_topPadding > 0)
{
if (horizontal)
outside_sizer->Add(1, m_topPadding);
else
outside_sizer->Add(m_topPadding, 1);
}
// add the sizer that contains all of the toolbar elements
outside_sizer->Add(sizer, 1, wxEXPAND);
// add "bottom" padding
if (m_bottomPadding > 0)
{
if (horizontal)
outside_sizer->Add(1, m_bottomPadding);
else
outside_sizer->Add(m_bottomPadding, 1);
}
delete m_sizer; // remove old sizer
m_sizer = outside_sizer;
// calculate the rock-bottom minimum size
for (i = 0, count = m_items.GetCount(); i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
if (item.m_sizerItem && item.m_proportion > 0 && item.m_minSize.IsFullySpecified())
item.m_sizerItem->SetMinSize(0,0);
}
m_absoluteMinSize = m_sizer->GetMinSize();
// reset the min sizes to what they were
for (i = 0, count = m_items.GetCount(); i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
if (item.m_sizerItem && item.m_proportion > 0 && item.m_minSize.IsFullySpecified())
item.m_sizerItem->SetMinSize(item.m_minSize);
}
// set control size
wxSize size = m_sizer->GetMinSize();
m_minWidth = size.x;
m_minHeight = size.y;
if ((m_style & wxAUI_TB_NO_AUTORESIZE) == 0)
{
wxSize curSize = GetClientSize();
wxSize new_size = GetMinSize();
if (new_size != curSize)
{
SetClientSize(new_size);
}
else
{
m_sizer->SetDimension(0, 0, curSize.x, curSize.y);
}
}
else
{
wxSize curSize = GetClientSize();
m_sizer->SetDimension(0, 0, curSize.x, curSize.y);
}
return true;
}
int wxAuiToolBar::GetOverflowState() const
{
return m_overflowState;
}
wxRect wxAuiToolBar::GetOverflowRect() const
{
wxRect cli_rect(wxPoint(0,0), GetClientSize());
wxRect overflow_rect = m_overflowSizerItem->GetRect();
int overflow_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
if (m_orientation == wxVERTICAL)
{
overflow_rect.y = cli_rect.height - overflow_size;
overflow_rect.x = 0;
overflow_rect.width = cli_rect.width;
overflow_rect.height = overflow_size;
}
else
{
overflow_rect.x = cli_rect.width - overflow_size;
overflow_rect.y = 0;
overflow_rect.width = overflow_size;
overflow_rect.height = cli_rect.height;
}
return overflow_rect;
}
wxSize wxAuiToolBar::GetLabelSize(const wxString& label)
{
wxClientDC dc(this);
int tx, ty;
int textWidth = 0, textHeight = 0;
dc.SetFont(m_font);
// get the text height
dc.GetTextExtent(wxT("ABCDHgj"), &tx, &textHeight);
// get the text width
dc.GetTextExtent(label, &textWidth, &ty);
return wxSize(textWidth, textHeight);
}
void wxAuiToolBar::DoIdleUpdate()
{
wxEvtHandler* handler = GetEventHandler();
bool need_refresh = false;
size_t i, count;
for (i = 0, count = m_items.GetCount(); i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
if (item.m_toolId == -1)
continue;
wxUpdateUIEvent evt(item.m_toolId);
evt.SetEventObject(this);
if (handler->ProcessEvent(evt))
{
if (evt.GetSetEnabled())
{
bool is_enabled;
if (item.m_window)
is_enabled = item.m_window->IsThisEnabled();
else
is_enabled = (item.m_state & wxAUI_BUTTON_STATE_DISABLED) ? false : true;
bool new_enabled = evt.GetEnabled();
if (new_enabled != is_enabled)
{
if (item.m_window)
{
item.m_window->Enable(new_enabled);
}
else
{
if (new_enabled)
item.m_state &= ~wxAUI_BUTTON_STATE_DISABLED;
else
item.m_state |= wxAUI_BUTTON_STATE_DISABLED;
}
need_refresh = true;
}
}
if (evt.GetSetChecked())
{
// make sure we aren't checking an item that can't be
if (item.m_kind != wxITEM_CHECK && item.m_kind != wxITEM_RADIO)
continue;
bool is_checked = (item.m_state & wxAUI_BUTTON_STATE_CHECKED) ? true : false;
bool new_checked = evt.GetChecked();
if (new_checked != is_checked)
{
if (new_checked)
item.m_state |= wxAUI_BUTTON_STATE_CHECKED;
else
item.m_state &= ~wxAUI_BUTTON_STATE_CHECKED;
need_refresh = true;
}
}
}
}
if (need_refresh)
{
Refresh(false);
}
}
void wxAuiToolBar::OnSize(wxSizeEvent& WXUNUSED(evt))
{
int x, y;
GetClientSize(&x, &y);
if (((x >= y) && m_absoluteMinSize.x > x) ||
((y > x) && m_absoluteMinSize.y > y))
{
// hide all flexible items
size_t i, count;
for (i = 0, count = m_items.GetCount(); i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
if (item.m_sizerItem && item.m_proportion > 0 && item.m_sizerItem->IsShown())
{
item.m_sizerItem->Show(false);
item.m_sizerItem->SetProportion(0);
}
}
}
else
{
// show all flexible items
size_t i, count;
for (i = 0, count = m_items.GetCount(); i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
if (item.m_sizerItem && item.m_proportion > 0 && !item.m_sizerItem->IsShown())
{
item.m_sizerItem->Show(true);
item.m_sizerItem->SetProportion(item.m_proportion);
}
}
}
m_sizer->SetDimension(0, 0, x, y);
Refresh(false);
Update();
// idle events aren't sent while user is resizing frame (why?),
// but resizing toolbar here causes havoc,
// so force idle handler to run after size handling complete
QueueEvent(new wxIdleEvent);
}
void wxAuiToolBar::DoSetSize(int x,
int y,
int width,
int height,
int sizeFlags)
{
wxSize parent_size = GetParent()->GetClientSize();
if (x + width > parent_size.x)
width = wxMax(0, parent_size.x - x);
if (y + height > parent_size.y)
height = wxMax(0, parent_size.y - y);
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
}
void wxAuiToolBar::OnIdle(wxIdleEvent& evt)
{
// if orientation doesn't match dock, fix it
wxAuiManager* manager = wxAuiManager::GetManager(this);
if (manager)
{
wxAuiPaneInfo& pane = manager->GetPane(this);
// pane state member is public, so it might have been changed
// without going through wxPaneInfo::SetFlag() check
bool ok = pane.IsOk();
wxCHECK2_MSG(!ok || IsPaneValid(m_style, pane), ok = false,
"window settings and pane settings are incompatible");
if (ok)
{
wxOrientation newOrientation = m_orientation;
if (pane.IsDocked())
{
switch (pane.dock_direction)
{
case wxAUI_DOCK_TOP:
case wxAUI_DOCK_BOTTOM:
newOrientation = wxHORIZONTAL;
break;
case wxAUI_DOCK_LEFT:
case wxAUI_DOCK_RIGHT:
newOrientation = wxVERTICAL;
break;
default:
wxFAIL_MSG("invalid dock location value");
}
}
else if (pane.IsResizable() &&
GetOrientation(m_style) == wxBOTH)
{
// changing orientation in OnSize causes havoc
int x, y;
GetClientSize(&x, &y);
if (x > y)
{
newOrientation = wxHORIZONTAL;
}
else
{
newOrientation = wxVERTICAL;
}
}
if (newOrientation != m_orientation)
{
SetOrientation(newOrientation);
Realize();
if (newOrientation == wxHORIZONTAL)
{
pane.best_size = GetHintSize(wxAUI_DOCK_TOP);
}
else
{
pane.best_size = GetHintSize(wxAUI_DOCK_LEFT);
}
if (pane.IsDocked())
{
pane.floating_size = wxDefaultSize;
}
else
{
SetSize(GetParent()->GetClientSize());
}
manager->Update();
}
}
}
evt.Skip();
}
void wxAuiToolBar::UpdateWindowUI(long flags)
{
if ( flags & wxUPDATE_UI_FROMIDLE )
{
DoIdleUpdate();
}
wxControl::UpdateWindowUI(flags);
}
void wxAuiToolBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
{
wxAutoBufferedPaintDC dc(this);
wxRect cli_rect(wxPoint(0,0), GetClientSize());
bool horizontal = m_orientation == wxHORIZONTAL;
m_art->DrawBackground(dc, this, cli_rect);
int gripperSize = m_art->GetElementSize(wxAUI_TBART_GRIPPER_SIZE);
int dropdown_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
// paint the gripper
if (gripperSize > 0 && m_gripperSizerItem)
{
wxRect gripper_rect = m_gripperSizerItem->GetRect();
if (horizontal)
gripper_rect.width = gripperSize;
else
gripper_rect.height = gripperSize;
m_art->DrawGripper(dc, this, gripper_rect);
}
// calculated how far we can draw items
int last_extent;
if (horizontal)
last_extent = cli_rect.width;
else
last_extent = cli_rect.height;
if (m_overflowVisible)
last_extent -= dropdown_size;
// paint each individual tool
size_t i, count = m_items.GetCount();
for (i = 0; i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
if (!item.m_sizerItem)
continue;
wxRect item_rect = item.m_sizerItem->GetRect();
if ((horizontal && item_rect.x + item_rect.width >= last_extent) ||
(!horizontal && item_rect.y + item_rect.height >= last_extent))
{
break;
}
if (item.m_kind == wxITEM_SEPARATOR)
{
// draw a separator
m_art->DrawSeparator(dc, this, item_rect);
}
else if (item.m_kind == wxITEM_LABEL)
{
// draw a text label only
m_art->DrawLabel(dc, this, item, item_rect);
}
else if (item.m_kind == wxITEM_NORMAL)
{
// draw a regular button or dropdown button
if (!item.m_dropDown)
m_art->DrawButton(dc, this, item, item_rect);
else
m_art->DrawDropDownButton(dc, this, item, item_rect);
}
else if (item.m_kind == wxITEM_CHECK)
{
// draw either a regular or dropdown toggle button
if (!item.m_dropDown)
m_art->DrawButton(dc, this, item, item_rect);
else
m_art->DrawDropDownButton(dc, this, item, item_rect);
}
else if (item.m_kind == wxITEM_RADIO)
{
// draw a toggle button
m_art->DrawButton(dc, this, item, item_rect);
}
else if (item.m_kind == wxITEM_CONTROL)
{
// draw the control's label
m_art->DrawControlLabel(dc, this, item, item_rect);
}
// fire a signal to see if the item wants to be custom-rendered
OnCustomRender(dc, item, item_rect);
}
// paint the overflow button
if (dropdown_size > 0 && m_overflowSizerItem)
{
wxRect dropDownRect = GetOverflowRect();
m_art->DrawOverflowButton(dc, this, dropDownRect, m_overflowState);
}
}
void wxAuiToolBar::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
{
// empty
}
void wxAuiToolBar::OnLeftDown(wxMouseEvent& evt)
{
wxRect cli_rect(wxPoint(0,0), GetClientSize());
if (m_gripperSizerItem)
{
wxRect gripper_rect = m_gripperSizerItem->GetRect();
if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
{
// find aui manager
wxAuiManager* manager = wxAuiManager::GetManager(this);
if (!manager)
return;
int x_drag_offset = evt.GetX() - gripper_rect.GetX();
int y_drag_offset = evt.GetY() - gripper_rect.GetY();
// gripper was clicked
manager->StartPaneDrag(this, wxPoint(x_drag_offset, y_drag_offset));
return;
}
}
if (m_overflowSizerItem)
{
wxRect overflow_rect = GetOverflowRect();
if (m_art &&
m_overflowVisible &&
overflow_rect.Contains(evt.m_x, evt.m_y))
{
wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, -1);
e.SetEventObject(this);
e.SetToolId(-1);
e.SetClickPoint(wxPoint(evt.GetX(), evt.GetY()));
bool processed = GetEventHandler()->ProcessEvent(e);
if (processed)
{
DoIdleUpdate();
}
else
{
size_t i, count;
wxAuiToolBarItemArray overflow_items;
// add custom overflow prepend items, if any
count = m_customOverflowPrepend.GetCount();
for (i = 0; i < count; ++i)
overflow_items.Add(m_customOverflowPrepend[i]);
// only show items that don't fit in the dropdown
count = m_items.GetCount();
for (i = 0; i < count; ++i)
{
if (!GetToolFitsByIndex(i))
overflow_items.Add(m_items[i]);
}
// add custom overflow append items, if any
count = m_customOverflowAppend.GetCount();
for (i = 0; i < count; ++i)
overflow_items.Add(m_customOverflowAppend[i]);
int res = m_art->ShowDropDown(this, overflow_items);
m_overflowState = 0;
Refresh(false);
if (res != -1)
{
wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, res);
e.SetEventObject(this);
GetParent()->GetEventHandler()->ProcessEvent(e);
}
}
return;
}
}
m_dragging = false;
m_actionPos = wxPoint(evt.GetX(), evt.GetY());
m_actionItem = FindToolByPosition(evt.GetX(), evt.GetY());
if (m_actionItem)
{
if (m_actionItem->m_state & wxAUI_BUTTON_STATE_DISABLED)
{
m_actionPos = wxPoint(-1,-1);
m_actionItem = NULL;
return;
}
UnsetToolTip();
// fire the tool dropdown event
wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, m_actionItem->m_toolId);
e.SetEventObject(this);
e.SetToolId(m_actionItem->m_toolId);
int mouse_x = evt.GetX();
wxRect rect = m_actionItem->m_sizerItem->GetRect();
const bool dropDownHit = m_actionItem->m_dropDown &&
mouse_x >= (rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1) &&
mouse_x < (rect.x+rect.width);
e.SetDropDownClicked(dropDownHit);
e.SetClickPoint(evt.GetPosition());
e.SetItemRect(rect);
// we only set the 'pressed button' state if we hit the actual button
// and not just the drop-down
SetPressedItem(dropDownHit ? 0 : m_actionItem);
if(dropDownHit)
{
m_actionPos = wxPoint(-1,-1);
m_actionItem = NULL;
}
if(!GetEventHandler()->ProcessEvent(e) || e.GetSkipped())
CaptureMouse();
DoIdleUpdate();
}
}
void wxAuiToolBar::OnLeftUp(wxMouseEvent& evt)
{
if (!HasCapture())
return;
SetPressedItem(NULL);
wxAuiToolBarItem* hitItem = FindToolByPosition(evt.GetX(), evt.GetY());
if (hitItem && !(hitItem->m_state & wxAUI_BUTTON_STATE_DISABLED))
{
SetHoverItem(hitItem);
}
if (m_dragging)
{
// TODO: it would make sense to send out an 'END_DRAG' event here,
// otherwise a client would never know what to do with the 'BEGIN_DRAG'
// event
// OnCaptureLost() will be called now and this will reset all our state
// tracking variables
ReleaseMouse();
}
else
{
if (m_actionItem && hitItem == m_actionItem)
{
UnsetToolTip();
wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, m_actionItem->m_toolId);
e.SetEventObject(this);
if (hitItem->m_kind == wxITEM_CHECK || hitItem->m_kind == wxITEM_RADIO)
{
const bool toggle = !(m_actionItem->m_state & wxAUI_BUTTON_STATE_CHECKED);
ToggleTool(m_actionItem->m_toolId, toggle);
// repaint immediately
Refresh(false);
Update();
e.SetInt(toggle);
}
// we have to release the mouse *before* sending the event, because
// we don't know what a handler might do. It could open up a popup
// menu for example and that would make us lose our capture anyway.
ReleaseMouse();
GetEventHandler()->ProcessEvent(e);
DoIdleUpdate();
}
else
ReleaseMouse();
}
}
void wxAuiToolBar::OnRightDown(wxMouseEvent& evt)
{
wxRect cli_rect(wxPoint(0,0), GetClientSize());
if (m_gripperSizerItem)
{
wxRect gripper_rect = m_gripperSizerItem->GetRect();
if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
return;
}
if (m_overflowSizerItem && m_art)
{
int dropdown_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
if (dropdown_size > 0 &&
evt.m_x > cli_rect.width - dropdown_size &&
evt.m_y >= 0 &&
evt.m_y < cli_rect.height)
{
return;
}
}
m_actionPos = wxPoint(evt.GetX(), evt.GetY());
m_actionItem = FindToolByPosition(evt.GetX(), evt.GetY());
if (m_actionItem && m_actionItem->m_state & wxAUI_BUTTON_STATE_DISABLED)
{
m_actionPos = wxPoint(-1,-1);
m_actionItem = NULL;
return;
}
UnsetToolTip();
}
void wxAuiToolBar::OnRightUp(wxMouseEvent& evt)
{
wxAuiToolBarItem* hitItem;
hitItem = FindToolByPosition(evt.GetX(), evt.GetY());
if (m_actionItem && hitItem == m_actionItem)
{
wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, m_actionItem->m_toolId);
e.SetEventObject(this);
e.SetToolId(m_actionItem->m_toolId);
e.SetClickPoint(m_actionPos);
GetEventHandler()->ProcessEvent(e);
DoIdleUpdate();
}
else
{
// right-clicked on the invalid area of the toolbar
wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, -1);
e.SetEventObject(this);
e.SetToolId(-1);
e.SetClickPoint(m_actionPos);
GetEventHandler()->ProcessEvent(e);
DoIdleUpdate();
}
// reset member variables
m_actionPos = wxPoint(-1,-1);
m_actionItem = NULL;
}
void wxAuiToolBar::OnMiddleDown(wxMouseEvent& evt)
{
wxRect cli_rect(wxPoint(0,0), GetClientSize());
if (m_gripperSizerItem)
{
wxRect gripper_rect = m_gripperSizerItem->GetRect();
if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
return;
}
if (m_overflowSizerItem && m_art)
{
int dropdown_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
if (dropdown_size > 0 &&
evt.m_x > cli_rect.width - dropdown_size &&
evt.m_y >= 0 &&
evt.m_y < cli_rect.height)
{
return;
}
}
m_actionPos = wxPoint(evt.GetX(), evt.GetY());
m_actionItem = FindToolByPosition(evt.GetX(), evt.GetY());
if (m_actionItem)
{
if (m_actionItem->m_state & wxAUI_BUTTON_STATE_DISABLED)
{
m_actionPos = wxPoint(-1,-1);
m_actionItem = NULL;
return;
}
}
UnsetToolTip();
}
void wxAuiToolBar::OnMiddleUp(wxMouseEvent& evt)
{
wxAuiToolBarItem* hitItem;
hitItem = FindToolByPosition(evt.GetX(), evt.GetY());
if (m_actionItem && hitItem == m_actionItem)
{
if (hitItem->m_kind == wxITEM_NORMAL)
{
wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, m_actionItem->m_toolId);
e.SetEventObject(this);
e.SetToolId(m_actionItem->m_toolId);
e.SetClickPoint(m_actionPos);
GetEventHandler()->ProcessEvent(e);
DoIdleUpdate();
}
}
// reset member variables
m_actionPos = wxPoint(-1,-1);
m_actionItem = NULL;
}
void wxAuiToolBar::OnMotion(wxMouseEvent& evt)
{
const bool button_pressed = HasCapture();
// start a drag event
if (!m_dragging && button_pressed &&
abs(evt.GetX() - m_actionPos.x) + abs(evt.GetY() - m_actionPos.y) > 5)
{
// TODO: sending this event only makes sense if there is an 'END_DRAG'
// event sent sometime in the future (see OnLeftUp())
wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG, GetId());
e.SetEventObject(this);
e.SetToolId(m_actionItem->m_toolId);
m_dragging = GetEventHandler()->ProcessEvent(e) && !e.GetSkipped();
DoIdleUpdate();
}
if(m_dragging)
return;
wxAuiToolBarItem* hitItem = FindToolByPosition(evt.GetX(), evt.GetY());
if(button_pressed)
{
// if we have a button pressed we want it to be shown in 'depressed'
// state unless we move the mouse outside the button, then we want it
// to show as just 'highlighted'
if (hitItem == m_actionItem)
SetPressedItem(m_actionItem);
else
{
SetPressedItem(NULL);
SetHoverItem(m_actionItem);
}
}
else
{
if (hitItem && (hitItem->m_state & wxAUI_BUTTON_STATE_DISABLED))
SetHoverItem(NULL);
else
SetHoverItem(hitItem);
// tooltips handling
wxAuiToolBarItem* packingHitItem;
packingHitItem = FindToolByPositionWithPacking(evt.GetX(), evt.GetY());
if (packingHitItem)
{
if (packingHitItem != m_tipItem)
{
m_tipItem = packingHitItem;
if ( !packingHitItem->m_shortHelp.empty() )
SetToolTip(packingHitItem->m_shortHelp);
else
UnsetToolTip();
}
}
else
{
UnsetToolTip();
m_tipItem = NULL;
}
// figure out the dropdown button state (are we hovering or pressing it?)
RefreshOverflowState();
}
}
void wxAuiToolBar::DoResetMouseState()
{
RefreshOverflowState();
SetHoverItem(NULL);
SetPressedItem(NULL);
m_tipItem = NULL;
// we have to reset those here, because the mouse-up handlers which do
// it usually won't be called if we let go of a mouse button while we
// are outside of the window
m_actionPos = wxPoint(-1,-1);
m_actionItem = NULL;
}
void wxAuiToolBar::OnLeaveWindow(wxMouseEvent& evt)
{
if(HasCapture())
{
evt.Skip();
return;
}
DoResetMouseState();
}
void wxAuiToolBar::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(evt))
{
m_dragging = false;
DoResetMouseState();
}
void wxAuiToolBar::OnSetCursor(wxSetCursorEvent& evt)
{
wxCursor cursor = wxNullCursor;
if (m_gripperSizerItem)
{
wxRect gripper_rect = m_gripperSizerItem->GetRect();
if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
{
cursor = wxCursor(wxCURSOR_SIZING);
}
}
evt.SetCursor(cursor);
}
#endif // wxUSE_AUI