///////////////////////////////////////////////////////////////////////////////
-// Name: src/aui/dockart.cpp
+// Name: src/aui/auibar.cpp
// Purpose: wxaui: wx advanced user interface - docking window manager
// Author: Benjamin I. Williams
// Modified by:
#ifdef __WXMAC__
#include "wx/osx/private.h"
-// for themeing support
-#include <Carbon/Carbon.h>
#endif
#include "wx/arrimpl.cpp"
wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h,
const wxColour& color);
-unsigned char wxAuiBlendColour(unsigned char fg, unsigned char bg, double alpha);
-wxColor wxAuiStepColour(const wxColor& c, int percent);
-
-static wxBitmap MakeDisabledBitmap(wxBitmap& bmp)
-{
- wxImage image = bmp.ConvertToImage();
-
- int mr, mg, mb;
- mr = image.GetMaskRed();
- mg = image.GetMaskGreen();
- mb = image.GetMaskBlue();
-
- unsigned char* data = image.GetData();
- int width = image.GetWidth();
- int height = image.GetHeight();
- bool has_mask = image.HasMask();
-
- for (int y = height-1; y >= 0; --y)
- {
- for (int x = width-1; x >= 0; --x)
- {
- data = image.GetData() + (y*(width*3))+(x*3);
- unsigned char* r = data;
- unsigned char* g = data+1;
- unsigned char* b = data+2;
-
- if (has_mask && *r == mr && *g == mg && *b == mb)
- continue;
-
- *r = wxAuiBlendColour(*r, 255, 0.4);
- *g = wxAuiBlendColour(*g, 255, 0.4);
- *b = wxAuiBlendColour(*b, 255, 0.4);
- }
- }
-
- return wxBitmap(image);
-}
-
static wxColor GetBaseColor()
{
(255-base_colour.Green()) +
(255-base_colour.Blue()) < 60)
{
- base_colour = wxAuiStepColour(base_colour, 92);
+ base_colour = base_colour.ChangeLightness(92);
}
return base_colour;
static const unsigned char
- DISABLED_TEXT_GREY_HUE = wxAuiBlendColour(0, 255, 0.4);
+ 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);
m_gripper_size = 7;
m_overflow_size = 16;
- wxColor darker1_colour = wxAuiStepColour(m_base_colour, 85);
- wxColor darker2_colour = wxAuiStepColour(m_base_colour, 75);
- wxColor darker3_colour = wxAuiStepColour(m_base_colour, 60);
- wxColor darker4_colour = wxAuiStepColour(m_base_colour, 50);
- wxColor darker5_colour = wxAuiStepColour(m_base_colour, 40);
+ wxColor darker1_colour = m_base_colour.ChangeLightness(85);
+ wxColor darker2_colour = m_base_colour.ChangeLightness(75);
+ wxColor darker3_colour = m_base_colour.ChangeLightness(60);
+ wxColor darker4_colour = m_base_colour.ChangeLightness(50);
+ wxColor darker5_colour = m_base_colour.ChangeLightness(40);
m_gripper_pen1 = wxPen(darker5_colour);
m_gripper_pen2 = wxPen(darker3_colour);
m_gripper_pen3 = *wxWHITE_PEN;
- static unsigned char button_dropdown_bits[] = { 0xe0, 0xf1, 0xfb };
- static unsigned char overflow_bits[] = { 0x80, 0xff, 0x80, 0xc1, 0xe3, 0xf7 };
+ static const unsigned char button_dropdown_bits[] = { 0xe0, 0xf1, 0xfb };
+ static const unsigned char overflow_bits[] = { 0x80, 0xff, 0x80, 0xc1, 0xe3, 0xf7 };
m_button_dropdown_bmp = wxAuiBitmapFromBits(button_dropdown_bits, 5, 3,
*wxBLACK);
{
wxRect rect = _rect;
rect.height++;
- wxColour start_colour = wxAuiStepColour(m_base_colour, 150);
- wxColour end_colour = wxAuiStepColour(m_base_colour, 90);
+ wxColour start_colour = m_base_colour.ChangeLightness(150);
+ wxColour end_colour = m_base_colour.ChangeLightness(90);
dc.GradientFillLinear(rect, start_colour, end_colour, wxSOUTH);
}
if (item.GetState() & wxAUI_BUTTON_STATE_PRESSED)
{
dc.SetPen(wxPen(m_highlight_colour));
- dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 150)));
+ dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(150)));
dc.DrawRectangle(rect);
}
else if ((item.GetState() & wxAUI_BUTTON_STATE_HOVER) || item.IsSticky())
{
dc.SetPen(wxPen(m_highlight_colour));
- dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 170)));
+ dc.SetBrush(wxBrush(m_highlight_colour.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(wxAuiStepColour(m_highlight_colour, 180)));
+ dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(180)));
dc.DrawRectangle(rect);
}
// 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_highlight_colour));
- dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 170)));
+ dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(170)));
dc.DrawRectangle(rect);
}
}
else
bmp = item.GetBitmap();
- if (!bmp.IsOk())
- return;
-
- dc.DrawBitmap(bmp, bmp_x, bmp_y, true);
+ if ( bmp.IsOk() )
+ dc.DrawBitmap(bmp, bmp_x, bmp_y, true);
// set the item's text color based on if it is disabled
dc.SetTextForeground(*wxBLACK);
if (item.GetState() & wxAUI_BUTTON_STATE_PRESSED)
{
dc.SetPen(wxPen(m_highlight_colour));
- dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 140)));
+ dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(140)));
dc.DrawRectangle(button_rect);
+
+ dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(170)));
dc.DrawRectangle(dropdown_rect);
}
else if (item.GetState() & wxAUI_BUTTON_STATE_HOVER ||
item.IsSticky())
{
dc.SetPen(wxPen(m_highlight_colour));
- dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 170)));
+ dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(170)));
+ dc.DrawRectangle(button_rect);
+ dc.DrawRectangle(dropdown_rect);
+ }
+ 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.
+ dc.SetPen(wxPen(m_highlight_colour));
+ dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(170)));
dc.DrawRectangle(button_rect);
dc.DrawRectangle(dropdown_rect);
}
// 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);
}
rect.width = new_width;
}
- wxColour start_colour = wxAuiStepColour(m_base_colour, 80);
- wxColour end_colour = wxAuiStepColour(m_base_colour, 80);
+ wxColour start_colour = m_base_colour.ChangeLightness(80);
+ wxColour end_colour = m_base_colour.ChangeLightness(80);
dc.GradientFillLinear(rect, start_colour, end_colour, horizontal ? wxSOUTH : wxEAST);
}
state & wxAUI_BUTTON_STATE_PRESSED)
{
wxRect cli_rect = wnd->GetClientRect();
- wxColor light_gray_bg = wxAuiStepColour(m_highlight_colour, 170);
+ wxColor light_gray_bg = m_highlight_colour.ChangeLightness(170);
if (m_flags & wxAUI_TB_VERTICAL)
{
{
switch (element_id)
{
- case wxAUI_TBART_SEPARATOR_SIZE: m_separator_size = size;
- case wxAUI_TBART_GRIPPER_SIZE: m_gripper_size = size;
- case wxAUI_TBART_OVERFLOW_SIZE: m_overflow_size = size;
+ case wxAUI_TBART_SEPARATOR_SIZE: m_separator_size = size; break;
+ case wxAUI_TBART_GRIPPER_SIZE: m_gripper_size = size; break;
+ case wxAUI_TBART_OVERFLOW_SIZE: m_overflow_size = size; break;
}
}
+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_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()
m_gripper_sizer_item = NULL;
m_overflow_sizer_item = NULL;
m_dragging = false;
- m_style = style;
+ m_orientation = GetOrientation(style);
+ if (m_orientation == wxBOTH)
+ {
+ m_orientation = wxHORIZONTAL;
+ }
+ m_style = style | wxBORDER_NONE;
m_gripper_visible = (m_style & wxAUI_TB_GRIPPER) ? true : false;
m_overflow_visible = (m_style & wxAUI_TB_OVERFLOW) ? true : false;
m_overflow_state = 0;
SetMargins(5, 5, 2, 2);
SetFont(*wxNORMAL_FONT);
- m_art->SetFlags((unsigned int)m_style);
+ SetArtFlags();
SetExtraStyle(wxWS_EX_PROCESS_IDLE);
if (style & wxAUI_TB_HORZ_LAYOUT)
SetToolTextOrientation(wxAUI_TBTOOL_TEXT_RIGHT);
+ SetBackgroundStyle(wxBG_STYLE_CUSTOM);
}
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)
{
- m_art->SetFlags((unsigned int)m_style);
+ SetArtFlags();
}
if (m_style & wxAUI_TB_GRIPPER)
if (m_art)
{
- m_art->SetFlags((unsigned int)m_style);
+ SetArtFlags();
m_art->SetTextOrientation(m_tool_text_orientation);
}
}
item.active = true;
item.dropdown = false;
item.spacer_pixels = 0;
- item.id = tool_id;
+ item.toolid = tool_id;
item.state = 0;
item.proportion = 0;
item.kind = kind;
item.min_size = wxDefaultSize;
item.user_data = 0;
item.sticky = false;
-
- if (item.id == wxID_ANY)
- item.id = wxNewId();
+
+ if (item.toolid == wxID_ANY)
+ item.toolid = wxNewId();
if (!item.disabled_bitmap.IsOk())
{
// no disabled bitmap specified, we need to make one
if (item.bitmap.IsOk())
{
- //wxImage img = item.bitmap.ConvertToImage();
- //wxImage grey_version = img.ConvertToGreyscale();
- //item.disabled_bitmap = wxBitmap(grey_version);
- item.disabled_bitmap = MakeDisabledBitmap(item.bitmap);
+ item.disabled_bitmap = item.bitmap.ConvertToDisabled();
}
}
m_items.Add(item);
item.active = true;
item.dropdown = false;
item.spacer_pixels = 0;
- item.id = control->GetId();
+ item.toolid = control->GetId();
item.state = 0;
item.proportion = 0;
item.kind = wxITEM_CONTROL;
item.active = true;
item.dropdown = false;
item.spacer_pixels = 0;
- item.id = tool_id;
+ item.toolid = tool_id;
item.state = 0;
item.proportion = 0;
item.kind = wxITEM_LABEL;
item.user_data = 0;
item.sticky = false;
- if (item.id == wxID_ANY)
- item.id = wxNewId();
-
+ if (item.toolid == wxID_ANY)
+ item.toolid = wxNewId();
+
m_items.Add(item);
return &m_items.Last();
}
item.disabled_bitmap = wxNullBitmap;
item.active = true;
item.dropdown = false;
- item.id = -1;
+ item.toolid = -1;
item.state = 0;
item.proportion = 0;
item.kind = wxITEM_SEPARATOR;
item.active = true;
item.dropdown = false;
item.spacer_pixels = pixels;
- item.id = -1;
+ item.toolid = -1;
item.state = 0;
item.proportion = 0;
item.kind = wxITEM_SPACER;
item.active = true;
item.dropdown = false;
item.spacer_pixels = 0;
- item.id = -1;
+ item.toolid = -1;
item.state = 0;
item.proportion = proportion;
item.kind = wxITEM_SPACER;
for (i = 0, count = m_items.GetCount(); i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
- if (item.id == tool_id)
+ if (item.toolid == tool_id)
return &item;
}
}
-void wxAuiToolBar::SetOrientation(int WXUNUSED(orientation))
+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)
// find out if the mouse cursor is inside the dropdown rectangle
if (overflow_rect.Contains(pt.x, pt.y))
{
- if (::wxGetMouseState().LeftDown())
+ if (::wxGetMouseState().LeftIsDown())
overflow_state = wxAUI_BUTTON_STATE_PRESSED;
else
overflow_state = wxAUI_BUTTON_STATE_HOVER;
int i, idx, count;
idx = GetToolIndex(tool_id);
count = (int)m_items.GetCount();
-
+
if (idx >= 0 && idx < count)
{
- for (i = idx; i < count; ++i)
+ for (i = idx + 1; i < count; ++i)
{
if (m_items[i].kind != wxITEM_RADIO)
break;
m_items[i].state &= ~wxAUI_BUTTON_STATE_CHECKED;
}
- for (i = idx; i > 0; i--)
+ for (i = idx - 1; i >= 0; i--)
{
if (m_items[i].kind != wxITEM_RADIO)
break;
m_items[i].state &= ~wxAUI_BUTTON_STATE_CHECKED;
}
}
-
+
tool->state |= wxAUI_BUTTON_STATE_CHECKED;
}
else if (tool->kind == wxITEM_CHECK)
m_custom_overflow_append = 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:
+ wxCHECK_MSG(false, wxDefaultSize, "invalid dock location value");
+ }
+}
+
+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
{
for (i = 0; i < count; ++i)
{
wxAuiToolBarItem& item = m_items.Item(i);
- if (item.id == tool_id)
+ if (item.toolid == tool_id)
return i;
}
wxRect rect = m_items[tool_idx].sizer_item->GetRect();
- if (m_style & wxAUI_TB_VERTICAL)
+ if (m_orientation == wxVERTICAL)
{
// take the dropdown size into account
if (m_overflow_visible)
if (!dc.IsOk())
return false;
- bool horizontal = true;
- if (m_style & wxAUI_TB_VERTICAL)
- horizontal = 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);
m_sizer->SetDimension(0, 0, cur_size.x, cur_size.y);
}
- Refresh(false);
return true;
}
wxRect overflow_rect = m_overflow_sizer_item->GetRect();
int overflow_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
- if (m_style & wxAUI_TB_VERTICAL)
+ if (m_orientation == wxVERTICAL)
{
overflow_rect.y = cli_rect.height - overflow_size;
overflow_rect.x = 0;
{
wxAuiToolBarItem& item = m_items.Item(i);
- if (item.id == -1)
+ if (item.toolid == -1)
continue;
- wxUpdateUIEvent evt(item.id);
+ wxUpdateUIEvent evt(item.toolid);
evt.SetEventObject(this);
if (handler->ProcessEvent(evt))
int x, y;
GetClientSize(&x, &y);
- if (x > y)
- SetOrientation(wxHORIZONTAL);
- else
- SetOrientation(wxVERTICAL);
-
if (((x >= y) && m_absolute_min_size.x > x) ||
((y > x) && m_absolute_min_size.y > 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::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();
+ }
+ }
+ }
+
DoIdleUpdate();
evt.Skip();
}
void wxAuiToolBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
{
- wxBufferedPaintDC dc(this);
+ wxAutoBufferedPaintDC dc(this);
wxRect cli_rect(wxPoint(0,0), GetClientSize());
- bool horizontal = true;
- if (m_style & wxAUI_TB_VERTICAL)
- horizontal = false;
+ bool horizontal = m_orientation == wxHORIZONTAL;
m_art->DrawBackground(dc, this, cli_rect);
}
else if (item.kind == wxITEM_CHECK)
{
- // draw a toggle button
- m_art->DrawButton(dc, this, item, item_rect);
+ // draw either a regular or dropdown toggle button
+ if (!item.dropdown)
+ m_art->DrawButton(dc, this, item, item_rect);
+ else
+ m_art->DrawDropDownButton(dc, this, item, item_rect);
}
else if (item.kind == wxITEM_RADIO)
{
return;
}
- SetPressedItem(m_action_item);
+ UnsetToolTip();
// fire the tool dropdown event
- wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, m_action_item->id);
+ wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, m_action_item->toolid);
e.SetEventObject(this);
- e.SetToolId(m_action_item->id);
- e.SetDropDownClicked(false);
+ e.SetToolId(m_action_item->toolid);
int mouse_x = evt.GetX();
wxRect rect = m_action_item->sizer_item->GetRect();
+ const bool dropDownHit = m_action_item->dropdown &&
+ mouse_x >= (rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1) &&
+ mouse_x < (rect.x+rect.width);
+ e.SetDropDownClicked(dropDownHit);
- if (m_action_item->dropdown &&
- mouse_x >= (rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1) &&
- mouse_x < (rect.x+rect.width))
+ 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_action_item);
+
+ if(dropDownHit)
{
- e.SetDropDownClicked(true);
+ m_action_pos = wxPoint(-1,-1);
+ m_action_item = NULL;
}
- e.SetClickPoint(evt.GetPosition());
- e.SetItemRect(rect);
- GetEventHandler()->ProcessEvent(e);
+ if(!GetEventHandler()->ProcessEvent(e) || e.GetSkipped())
+ CaptureMouse();
+
DoIdleUpdate();
}
}
void wxAuiToolBar::OnLeftUp(wxMouseEvent& evt)
{
+ if (!HasCapture())
+ return;
+
SetPressedItem(NULL);
wxAuiToolBarItem* hit_item = FindToolByPosition(evt.GetX(), evt.GetY());
SetHoverItem(hit_item);
}
-
if (m_dragging)
{
- // reset drag and drop member variables
- m_dragging = false;
- m_action_pos = wxPoint(-1,-1);
- m_action_item = NULL;
- return;
+ // 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
{
- wxAuiToolBarItem* hit_item;
- hit_item = FindToolByPosition(evt.GetX(), evt.GetY());
-
if (m_action_item && hit_item == m_action_item)
{
UnsetToolTip();
+ wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, m_action_item->toolid);
+ e.SetEventObject(this);
+
if (hit_item->kind == wxITEM_CHECK || hit_item->kind == wxITEM_RADIO)
{
- bool toggle = false;
+ const bool toggle = !(m_action_item->state & wxAUI_BUTTON_STATE_CHECKED);
- if (m_action_item->state & wxAUI_BUTTON_STATE_CHECKED)
- toggle = false;
- else
- toggle = true;
+ ToggleTool(m_action_item->toolid, toggle);
- ToggleTool(m_action_item->id, toggle);
-
// repaint immediately
Refresh(false);
Update();
-
- wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, m_action_item->id);
- e.SetEventObject(this);
- GetEventHandler()->ProcessEvent(e);
- DoIdleUpdate();
- }
- else
- {
- wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, m_action_item->id);
- e.SetEventObject(this);
- GetEventHandler()->ProcessEvent(e);
- DoIdleUpdate();
+
+ 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();
}
-
- // reset drag and drop member variables
- m_dragging = false;
- m_action_pos = wxPoint(-1,-1);
- m_action_item = NULL;
}
void wxAuiToolBar::OnRightDown(wxMouseEvent& evt)
m_action_pos = wxPoint(evt.GetX(), evt.GetY());
m_action_item = FindToolByPosition(evt.GetX(), evt.GetY());
- if (m_action_item)
+ if (m_action_item && m_action_item->state & wxAUI_BUTTON_STATE_DISABLED)
{
- if (m_action_item->state & wxAUI_BUTTON_STATE_DISABLED)
- {
- m_action_pos = wxPoint(-1,-1);
- m_action_item = NULL;
- return;
- }
+ m_action_pos = wxPoint(-1,-1);
+ m_action_item = NULL;
+ return;
}
+
+ UnsetToolTip();
}
void wxAuiToolBar::OnRightUp(wxMouseEvent& evt)
{
if (hit_item->kind == wxITEM_NORMAL)
{
- wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, m_action_item->id);
+ wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, m_action_item->toolid);
e.SetEventObject(this);
- e.SetToolId(m_action_item->id);
+ e.SetToolId(m_action_item->toolid);
e.SetClickPoint(m_action_pos);
GetEventHandler()->ProcessEvent(e);
DoIdleUpdate();
return;
}
}
+
+ UnsetToolTip();
}
void wxAuiToolBar::OnMiddleUp(wxMouseEvent& evt)
{
if (hit_item->kind == wxITEM_NORMAL)
{
- wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, m_action_item->id);
+ wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, m_action_item->toolid);
e.SetEventObject(this);
- e.SetToolId(m_action_item->id);
+ e.SetToolId(m_action_item->toolid);
e.SetClickPoint(m_action_pos);
GetEventHandler()->ProcessEvent(e);
DoIdleUpdate();
void wxAuiToolBar::OnMotion(wxMouseEvent& evt)
{
+ const bool button_pressed = HasCapture();
+
// start a drag event
- if (!m_dragging &&
- m_action_item != NULL &&
- m_action_pos != wxPoint(-1,-1) &&
- abs(evt.m_x - m_action_pos.x) + abs(evt.m_y - m_action_pos.y) > 5)
+ if (!m_dragging && button_pressed &&
+ abs(evt.GetX() - m_action_pos.x) + abs(evt.GetY() - m_action_pos.y) > 5)
{
- UnsetToolTip();
-
- m_dragging = true;
-
+ // 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_action_item->id);
- GetEventHandler()->ProcessEvent(e);
+ e.SetToolId(m_action_item->toolid);
+ m_dragging = GetEventHandler()->ProcessEvent(e) && !e.GetSkipped();
+
DoIdleUpdate();
- return;
}
+ if(m_dragging)
+ return;
+
wxAuiToolBarItem* hit_item = FindToolByPosition(evt.GetX(), evt.GetY());
- if (hit_item)
+ if(button_pressed)
{
- if (!(hit_item->state & wxAUI_BUTTON_STATE_DISABLED))
- SetHoverItem(hit_item);
+ // 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 (hit_item == m_action_item)
+ SetPressedItem(m_action_item);
else
- SetHoverItem(NULL);
+ {
+ SetPressedItem(NULL);
+ SetHoverItem(m_action_item);
+ }
}
else
{
- // no hit item, remove any hit item
- SetHoverItem(hit_item);
- }
+ if (hit_item && (hit_item->state & wxAUI_BUTTON_STATE_DISABLED))
+ SetHoverItem(NULL);
+ else
+ SetHoverItem(hit_item);
- // figure out tooltips
- wxAuiToolBarItem* packing_hit_item;
- packing_hit_item = FindToolByPositionWithPacking(evt.GetX(), evt.GetY());
- if (packing_hit_item)
- {
- if (packing_hit_item != m_tip_item)
+ // tooltips handling
+ wxAuiToolBarItem* packing_hit_item;
+ packing_hit_item = FindToolByPositionWithPacking(evt.GetX(), evt.GetY());
+ if (packing_hit_item)
{
- m_tip_item = packing_hit_item;
+ if (packing_hit_item != m_tip_item)
+ {
+ m_tip_item = packing_hit_item;
- if ( !packing_hit_item->short_help.empty() )
- SetToolTip(packing_hit_item->short_help);
- else
- UnsetToolTip();
+ if ( !packing_hit_item->short_help.empty() )
+ SetToolTip(packing_hit_item->short_help);
+ else
+ UnsetToolTip();
+ }
}
- }
- else
- {
- UnsetToolTip();
- m_tip_item = NULL;
- }
-
- // if we've pressed down an item and we're hovering
- // over it, make sure it's state is set to pressed
- if (m_action_item)
- {
- if (m_action_item == hit_item)
- SetPressedItem(m_action_item);
else
- SetPressedItem(NULL);
- }
+ {
+ UnsetToolTip();
+ m_tip_item = NULL;
+ }
- // figure out the dropdown button state (are we hovering or pressing it?)
- RefreshOverflowState();
+ // figure out the dropdown button state (are we hovering or pressing it?)
+ RefreshOverflowState();
+ }
}
-void wxAuiToolBar::OnLeaveWindow(wxMouseEvent& WXUNUSED(evt))
+void wxAuiToolBar::DoResetMouseState()
{
RefreshOverflowState();
SetHoverItem(NULL);
SetPressedItem(NULL);
m_tip_item = 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_action_pos = wxPoint(-1,-1);
+ m_action_item = 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)
{