X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7bce84396ef8d92be3649b46c84d85abec9739f8..3b81609771af63664f9265c503e5f1668906969a:/src/aui/auibar.cpp diff --git a/src/aui/auibar.cpp b/src/aui/auibar.cpp index 18c00b0da4..b9039efd55 100644 --- a/src/aui/auibar.cpp +++ b/src/aui/auibar.cpp @@ -5,7 +5,7 @@ // Author: Benjamin I. Williams // Modified by: // Created: 2005-05-17 -// RCS-ID: $Id: dockart.cpp 48848 2007-09-21 10:19:53Z SC $ +// RCS-ID: $Id$ // Copyright: (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved // Licence: wxWindows Library Licence, Version 3.1 /////////////////////////////////////////////////////////////////////////////// @@ -38,19 +38,17 @@ #ifdef __WXMAC__ #include "wx/osx/private.h" -// for themeing support -#include #endif #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxAuiToolBarItemArray) -DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN) -DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK) -DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK) -DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK) -DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG) +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) @@ -187,8 +185,8 @@ wxAuiDefaultToolBarArt::wxAuiDefaultToolBarArt() 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); @@ -227,6 +225,21 @@ void wxAuiDefaultToolBarArt::SetTextOrientation(int orientation) m_text_orientation = orientation; } +unsigned int wxAuiDefaultToolBarArt::GetFlags() +{ + return m_flags; +} + +wxFont wxAuiDefaultToolBarArt::GetFont() +{ + return m_font; +} + +int wxAuiDefaultToolBarArt::GetTextOrientation() +{ + return m_text_orientation; +} + void wxAuiDefaultToolBarArt::DrawBackground( wxDC& dc, wxWindow* WXUNUSED(wnd), @@ -443,6 +456,8 @@ void wxAuiDefaultToolBarArt::DrawDropDownButton( dc.SetPen(wxPen(m_highlight_colour)); dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 140))); dc.DrawRectangle(button_rect); + + dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 170))); dc.DrawRectangle(dropdown_rect); } else if (item.GetState() & wxAUI_BUTTON_STATE_HOVER || @@ -540,6 +555,12 @@ wxSize wxAuiDefaultToolBarArt::GetLabelSize( // 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); } @@ -713,9 +734,9 @@ void wxAuiDefaultToolBarArt::SetElementSize(int element_id, int size) { 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; } } @@ -773,6 +794,22 @@ int wxAuiDefaultToolBarArt::ShowDropDown(wxWindow* wnd, +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) @@ -789,6 +826,7 @@ BEGIN_EVENT_TABLE(wxAuiToolBar, wxControl) 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() @@ -818,16 +856,22 @@ wxAuiToolBar::wxAuiToolBar(wxWindow* parent, 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); } @@ -839,13 +883,17 @@ wxAuiToolBar::~wxAuiToolBar() 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) @@ -865,6 +913,10 @@ void wxAuiToolBar::SetWindowStyleFlag(long style) SetToolTextOrientation(wxAUI_TBTOOL_TEXT_BOTTOM); } +long wxAuiToolBar::GetWindowStyleFlag() const +{ + return m_style; +} void wxAuiToolBar::SetArtProvider(wxAuiToolBarArt* art) { @@ -874,7 +926,7 @@ void wxAuiToolBar::SetArtProvider(wxAuiToolBarArt* art) if (m_art) { - m_art->SetFlags((unsigned int)m_style); + SetArtFlags(); m_art->SetTextOrientation(m_tool_text_orientation); } } @@ -932,6 +984,9 @@ wxAuiToolBarItem* wxAuiToolBar::AddTool(int tool_id, item.user_data = 0; item.sticky = false; + if (item.id == wxID_ANY) + item.id = wxNewId(); + if (!item.disabled_bitmap.IsOk()) { // no disabled bitmap specified, we need to make one @@ -996,6 +1051,9 @@ wxAuiToolBarItem* wxAuiToolBar::AddLabel(int tool_id, item.user_data = 0; item.sticky = false; + if (item.id == wxID_ANY) + item.id = wxNewId(); + m_items.Add(item); return &m_items.Last(); } @@ -1312,8 +1370,16 @@ int wxAuiToolBar::GetToolPacking() const } -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) @@ -1338,6 +1404,8 @@ void wxAuiToolBar::SetGripperVisible(bool visible) m_gripper_visible = visible; if (visible) m_style |= wxAUI_TB_GRIPPER; + else + m_style &= ~wxAUI_TB_GRIPPER; Realize(); Refresh(false); } @@ -1353,6 +1421,8 @@ void wxAuiToolBar::SetOverflowVisible(bool visible) m_overflow_visible = visible; if (visible) m_style |= wxAUI_TB_OVERFLOW; + else + m_style &= ~wxAUI_TB_OVERFLOW; Refresh(false); } @@ -1440,7 +1510,7 @@ void wxAuiToolBar::RefreshOverflowState() // 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; @@ -1460,15 +1530,39 @@ void wxAuiToolBar::ToggleTool(int tool_id, bool state) { wxAuiToolBarItem* tool = FindTool(tool_id); - if (tool) + if (tool && (tool->kind == wxITEM_CHECK || tool->kind == wxITEM_RADIO)) { - if (tool->kind != wxITEM_CHECK) - return; + if (tool->kind == wxITEM_RADIO) + { + int i, idx, count; + idx = GetToolIndex(tool_id); + count = (int)m_items.GetCount(); + + if (idx >= 0 && idx < count) + { + for (i = idx; 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--) + { + if (m_items[i].kind != wxITEM_RADIO) + break; + m_items[i].state &= ~wxAUI_BUTTON_STATE_CHECKED; + } + } - if (state == true) tool->state |= wxAUI_BUTTON_STATE_CHECKED; - else - tool->state &= ~wxAUI_BUTTON_STATE_CHECKED; + } + else if (tool->kind == wxITEM_CHECK) + { + if (state == true) + tool->state |= wxAUI_BUTTON_STATE_CHECKED; + else + tool->state &= ~wxAUI_BUTTON_STATE_CHECKED; + } } } @@ -1478,7 +1572,7 @@ bool wxAuiToolBar::GetToolToggled(int tool_id) const if (tool) { - if (tool->kind != wxITEM_CHECK) + if ( (tool->kind != wxITEM_CHECK) && (tool->kind != wxITEM_RADIO) ) return false; return (tool->state & wxAUI_BUTTON_STATE_CHECKED) ? true : false; @@ -1593,6 +1687,65 @@ void wxAuiToolBar::SetCustomOverflowItems(const wxAuiToolBarItemArray& prepend, 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(this)); + if (manager) + { + return IsPaneValid(style, manager->GetPane(const_cast(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 { @@ -1630,7 +1783,7 @@ bool wxAuiToolBar::GetToolFitsByIndex(int tool_idx) const 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) @@ -1687,11 +1840,40 @@ bool wxAuiToolBar::Realize() 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); @@ -1733,7 +1915,7 @@ bool wxAuiToolBar::Realize() sizer_item = sizer->Add(size.x + (m_tool_border_padding*2), size.y + (m_tool_border_padding*2), item.proportion, - wxALIGN_CENTER); + item.alignment); if (i+1 < count) { sizer->AddSpacer(m_tool_packing); @@ -1744,12 +1926,13 @@ bool wxAuiToolBar::Realize() case wxITEM_CHECK: case wxITEM_NORMAL: + case wxITEM_RADIO: { wxSize size = m_art->GetToolSize(dc, this, item); sizer_item = sizer->Add(size.x + (m_tool_border_padding*2), size.y + (m_tool_border_padding*2), 0, - wxALIGN_CENTER); + item.alignment); // add tool packing if (i+1 < count) { @@ -1927,7 +2110,6 @@ bool wxAuiToolBar::Realize() m_sizer->SetDimension(0, 0, cur_size.x, cur_size.y); } - Refresh(false); return true; } @@ -1942,7 +2124,7 @@ wxRect wxAuiToolBar::GetOverflowRect() const 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; @@ -2060,11 +2242,6 @@ void wxAuiToolBar::OnSize(wxSizeEvent& WXUNUSED(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)) { @@ -2099,6 +2276,11 @@ void wxAuiToolBar::OnSize(wxSizeEvent& WXUNUSED(evt)) 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); } @@ -2121,19 +2303,87 @@ void wxAuiToolBar::DoSetSize(int x, 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); @@ -2202,6 +2452,11 @@ void wxAuiToolBar::OnPaint(wxPaintEvent& WXUNUSED(evt)) // draw a toggle button m_art->DrawButton(dc, this, item, item_rect); } + else if (item.kind == wxITEM_RADIO) + { + // draw a toggle button + m_art->DrawButton(dc, this, item, item_rect); + } else if (item.kind == wxITEM_CONTROL) { // draw the control's label @@ -2260,7 +2515,7 @@ void wxAuiToolBar::OnLeftDown(wxMouseEvent& evt) e.SetEventObject(this); e.SetToolId(-1); e.SetClickPoint(wxPoint(evt.GetX(), evt.GetY())); - bool processed = ProcessEvent(e); + bool processed = GetEventHandler()->ProcessEvent(e); if (processed) { @@ -2297,7 +2552,7 @@ void wxAuiToolBar::OnLeftDown(wxMouseEvent& evt) { wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, res); e.SetEventObject(this); - GetParent()->ProcessEvent(e); + GetParent()->GetEventHandler()->ProcessEvent(e); } } @@ -2318,33 +2573,45 @@ void wxAuiToolBar::OnLeftDown(wxMouseEvent& evt) return; } - SetPressedItem(m_action_item); + UnsetToolTip(); // fire the tool dropdown event wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, m_action_item->id); e.SetEventObject(this); e.SetToolId(m_action_item->id); - e.SetDropDownClicked(false); 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); + + 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 (m_action_item->dropdown && - mouse_x >= (rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1) && - mouse_x < (rect.x+rect.width)) + if(dropDownHit) { - e.SetDropDownClicked(true); + m_action_pos = wxPoint(-1,-1); + m_action_item = NULL; } - e.SetClickPoint(evt.GetPosition()); - e.SetItemRect(rect); - 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()); @@ -2353,14 +2620,15 @@ void wxAuiToolBar::OnLeftUp(wxMouseEvent& evt) 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 { @@ -2371,36 +2639,34 @@ void wxAuiToolBar::OnLeftUp(wxMouseEvent& evt) { UnsetToolTip(); - if (hit_item->kind == wxITEM_CHECK) - { - bool toggle = false; + wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, m_action_item->id); + e.SetEventObject(this); - if (m_action_item->state & wxAUI_BUTTON_STATE_CHECKED) - toggle = false; - else - toggle = true; + if (hit_item->kind == wxITEM_CHECK || hit_item->kind == wxITEM_RADIO) + { + const bool toggle = !(m_action_item->state & wxAUI_BUTTON_STATE_CHECKED); ToggleTool(m_action_item->id, toggle); - wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, m_action_item->id); - e.SetEventObject(this); - ProcessEvent(e); - DoIdleUpdate(); - } - else - { - wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, m_action_item->id); - e.SetEventObject(this); - ProcessEvent(e); - DoIdleUpdate(); + // 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(); } - - // reset drag and drop member variables - m_dragging = false; - m_action_pos = wxPoint(-1,-1); - m_action_item = NULL; } void wxAuiToolBar::OnRightDown(wxMouseEvent& evt) @@ -2430,15 +2696,14 @@ 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) @@ -2454,7 +2719,7 @@ void wxAuiToolBar::OnRightUp(wxMouseEvent& evt) e.SetEventObject(this); e.SetToolId(m_action_item->id); e.SetClickPoint(m_action_pos); - ProcessEvent(e); + GetEventHandler()->ProcessEvent(e); DoIdleUpdate(); } } @@ -2465,7 +2730,7 @@ void wxAuiToolBar::OnRightUp(wxMouseEvent& evt) e.SetEventObject(this); e.SetToolId(-1); e.SetClickPoint(m_action_pos); - ProcessEvent(e); + GetEventHandler()->ProcessEvent(e); DoIdleUpdate(); } @@ -2510,6 +2775,8 @@ void wxAuiToolBar::OnMiddleDown(wxMouseEvent& evt) return; } } + + UnsetToolTip(); } void wxAuiToolBar::OnMiddleUp(wxMouseEvent& evt) @@ -2525,7 +2792,7 @@ void wxAuiToolBar::OnMiddleUp(wxMouseEvent& evt) e.SetEventObject(this); e.SetToolId(m_action_item->id); e.SetClickPoint(m_action_pos); - ProcessEvent(e); + GetEventHandler()->ProcessEvent(e); DoIdleUpdate(); } } @@ -2537,82 +2804,104 @@ void wxAuiToolBar::OnMiddleUp(wxMouseEvent& evt) 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); - ProcessEvent(e); + 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) {