mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-01 16:19:43 +02:00
Fix the weird mouse pointer behavior over toolbar resizers
I couldn't handle it anymore. The darn pointer would seemingly switch to left/right arrows whenever it felt like it...and stay that way. Actually, it was when it passed over the toolbar resizer when docked. The problem was that it wouldn't change back to a normal pointer because it didn't have the events it needed to do that. So, I moved the resizer logic into it's own window and now the pointer changes like it should. As a bonus, we get a tooltip so the user will know what to do when the pointer changes as it passes over the resizer.
This commit is contained in:
parent
2e29d9d2b1
commit
2f177032ed
@ -51,6 +51,208 @@ in which buttons can be placed.
|
||||
#include "../widgets/AButton.h"
|
||||
#include "../widgets/Grabber.h"
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// ToolBarResizer
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Width of the resize grab area
|
||||
//
|
||||
#define RWIDTH 4
|
||||
|
||||
class ToolBarResizer : public wxWindow
|
||||
{
|
||||
public:
|
||||
ToolBarResizer(ToolBar *mBar);
|
||||
virtual ~ToolBarResizer();
|
||||
|
||||
private:
|
||||
void OnErase(wxEraseEvent & event);
|
||||
void OnPaint(wxPaintEvent & event);
|
||||
void OnLeftDown(wxMouseEvent & event);
|
||||
void OnLeftUp(wxMouseEvent & event);
|
||||
void OnEnter(wxMouseEvent & event);
|
||||
void OnLeave(wxMouseEvent & event);
|
||||
void OnMotion(wxMouseEvent & event);
|
||||
void OnCaptureLost(wxMouseCaptureLostEvent & event);
|
||||
|
||||
private:
|
||||
ToolBar *mBar;
|
||||
wxPoint mResizeStart;
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
//
|
||||
// Event table
|
||||
//
|
||||
BEGIN_EVENT_TABLE( ToolBarResizer, wxWindow )
|
||||
EVT_ERASE_BACKGROUND( ToolBarResizer::OnErase )
|
||||
EVT_PAINT( ToolBarResizer::OnPaint )
|
||||
EVT_LEFT_DOWN( ToolBarResizer::OnLeftDown )
|
||||
EVT_LEFT_UP( ToolBarResizer::OnLeftUp )
|
||||
EVT_MOTION( ToolBarResizer::OnMotion )
|
||||
EVT_ENTER_WINDOW( ToolBarResizer::OnEnter )
|
||||
EVT_LEAVE_WINDOW( ToolBarResizer::OnLeave )
|
||||
EVT_MOUSE_CAPTURE_LOST( ToolBarResizer::OnCaptureLost )
|
||||
END_EVENT_TABLE();
|
||||
|
||||
ToolBarResizer::ToolBarResizer(ToolBar *bar)
|
||||
: wxWindow(bar, wxID_ANY, wxDefaultPosition, wxSize(RWIDTH, -1))
|
||||
{
|
||||
mBar = bar;
|
||||
}
|
||||
|
||||
ToolBarResizer::~ToolBarResizer()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Handle background erasure
|
||||
//
|
||||
void ToolBarResizer::OnErase( wxEraseEvent & WXUNUSED(event) )
|
||||
{
|
||||
// Ignore it to prevent flashing
|
||||
}
|
||||
|
||||
//
|
||||
// This draws the background of a toolbar
|
||||
//
|
||||
void ToolBarResizer::OnPaint( wxPaintEvent & event )
|
||||
{
|
||||
wxPaintDC dc( (wxWindow *) event.GetEventObject() );
|
||||
|
||||
// Start with a clean background
|
||||
//
|
||||
// Under GTK, we specifically set the toolbar background to the background
|
||||
// colour in the system theme.
|
||||
#if defined( __WXGTK__ )
|
||||
dc.SetBackground( wxBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BACKGROUND ) ) );
|
||||
#endif
|
||||
|
||||
dc.Clear();
|
||||
|
||||
wxSize sz = GetSize();
|
||||
|
||||
wxLogDebug(wxT("x = %d y = %d"), sz.x, sz.y);
|
||||
|
||||
AColor::Dark( &dc, false );
|
||||
AColor::Line(dc, sz.x - 4, 0, sz.x - 4, sz.y );
|
||||
AColor::Line(dc, sz.x - 1, 0, sz.x - 1, sz.y );
|
||||
}
|
||||
|
||||
//
|
||||
// Handle toolbar resizing
|
||||
//
|
||||
void ToolBarResizer::OnLeftDown( wxMouseEvent & event )
|
||||
{
|
||||
// Go ahead and set the event to propagate
|
||||
event.Skip();
|
||||
|
||||
// Retrieve the mouse position
|
||||
mResizeStart = ClientToScreen( event.GetPosition() );
|
||||
|
||||
// We want all of the mouse events
|
||||
CaptureMouse();
|
||||
|
||||
// SetCursor( wxCURSOR_SIZEWE );
|
||||
}
|
||||
|
||||
void ToolBarResizer::OnLeftUp( wxMouseEvent & event )
|
||||
{
|
||||
// Go ahead and set the event to propagate
|
||||
event.Skip();
|
||||
|
||||
if( HasCapture() )
|
||||
{
|
||||
ReleaseMouse();
|
||||
}
|
||||
|
||||
// SetCursor( wxCURSOR_ARROW );
|
||||
}
|
||||
|
||||
void ToolBarResizer::OnEnter( wxMouseEvent & event )
|
||||
{
|
||||
// Go ahead and set the event to propagate
|
||||
event.Skip();
|
||||
|
||||
if( !HasCapture() )
|
||||
{
|
||||
SetCursor( wxCURSOR_SIZEWE );
|
||||
}
|
||||
}
|
||||
|
||||
void ToolBarResizer::OnLeave( wxMouseEvent & event )
|
||||
{
|
||||
// Go ahead and set the event to propagate
|
||||
event.Skip();
|
||||
|
||||
if( !HasCapture() )
|
||||
{
|
||||
SetCursor( wxCURSOR_ARROW );
|
||||
}
|
||||
}
|
||||
|
||||
void ToolBarResizer::OnMotion( wxMouseEvent & event )
|
||||
{
|
||||
// Go ahead and set the event to propagate
|
||||
event.Skip();
|
||||
|
||||
// Retrieve the mouse position
|
||||
wxPoint raw_pos = event.GetPosition();
|
||||
wxPoint pos = ClientToScreen( raw_pos );
|
||||
|
||||
if( event.Dragging() )
|
||||
{
|
||||
wxRect r = mBar->GetRect();
|
||||
wxSize msz = mBar->GetMinSize();
|
||||
wxSize psz = mBar->GetParent()->GetClientSize();
|
||||
|
||||
// Adjust the size by the difference between the
|
||||
// last mouse and current mouse positions.
|
||||
r.width += ( pos.x - mResizeStart.x );
|
||||
|
||||
// Constrain
|
||||
if( r.width < msz.x )
|
||||
{
|
||||
// Don't allow resizing to go too small
|
||||
r.width = msz.x;
|
||||
}
|
||||
else if( r.GetRight() > psz.x - 3 )
|
||||
{
|
||||
// Don't allow resizing to go too large
|
||||
//
|
||||
// The 3 magic pixels are because I'm too chicken to change the
|
||||
// calculations in ToolDock::LayoutToolBars() even though I'm
|
||||
// the one that set them up. :-)
|
||||
r.SetRight( psz.x - 3 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remember for next go round
|
||||
mResizeStart = pos;
|
||||
}
|
||||
|
||||
// Resize the bar
|
||||
mBar->SetSize( r.GetSize() );
|
||||
|
||||
// Tell everyone we've changed sizes
|
||||
mBar->Updated();
|
||||
|
||||
// Refresh our world
|
||||
mBar->GetParent()->Refresh();
|
||||
mBar->GetParent()->Update();
|
||||
}
|
||||
}
|
||||
|
||||
void ToolBarResizer::OnCaptureLost( wxMouseCaptureLostEvent & WXUNUSED(event) )
|
||||
{
|
||||
if( HasCapture() )
|
||||
{
|
||||
ReleaseMouse();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Methods for ToolBar
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -65,21 +267,12 @@ IMPLEMENT_CLASS( ToolBar, wxPanel );
|
||||
//
|
||||
DEFINE_EVENT_TYPE(EVT_TOOLBAR_UPDATED)
|
||||
|
||||
//
|
||||
// Width of the resize grab area
|
||||
//
|
||||
#define RWIDTH 4
|
||||
|
||||
//
|
||||
// Event table
|
||||
//
|
||||
BEGIN_EVENT_TABLE( ToolBar, wxPanel )
|
||||
EVT_PAINT( ToolBar::OnPaint )
|
||||
EVT_ERASE_BACKGROUND( ToolBar::OnErase )
|
||||
EVT_LEFT_DOWN( ToolBar::OnLeftDown )
|
||||
EVT_LEFT_UP( ToolBar::OnLeftUp )
|
||||
EVT_MOTION( ToolBar::OnMotion )
|
||||
EVT_MOUSE_CAPTURE_LOST( ToolBar::OnCaptureLost )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
//
|
||||
@ -104,6 +297,9 @@ ToolBar::ToolBar( int type,
|
||||
mDock = NULL;
|
||||
mVisible = false;
|
||||
mPositioned = false;
|
||||
|
||||
mGrabber = NULL;
|
||||
mResizer = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
@ -264,7 +460,10 @@ void ToolBar::ReCreateButtons()
|
||||
// Add some space for the resize border
|
||||
if( IsResizable() )
|
||||
{
|
||||
mSpacer = ms->Add( RWIDTH, 1 );
|
||||
// Create the resizer and add it to the main sizer
|
||||
mResizer = new ToolBarResizer( this );
|
||||
ms->Add( mResizer, 0, wxEXPAND | wxALIGN_RIGHT | wxALIGN_TOP | wxLEFT, 1 );
|
||||
mResizer->SetToolTip( _("Click and drag to resize toolbar") );
|
||||
}
|
||||
|
||||
// Set the sizer
|
||||
@ -300,7 +499,16 @@ void ToolBar::UpdatePrefs()
|
||||
{
|
||||
#if wxUSE_TOOLTIPS
|
||||
// Change the tooltip of the grabber
|
||||
mGrabber->SetToolTip( GetTitle() );
|
||||
if ( mGrabber )
|
||||
{
|
||||
mGrabber->SetToolTip( GetTitle() );
|
||||
}
|
||||
|
||||
// Change the tooltip of the resizer
|
||||
if ( mResizer )
|
||||
{
|
||||
mResizer->SetToolTip( _("Click and drag to resize toolbar") );
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
@ -329,6 +537,13 @@ void ToolBar::SetDocked( ToolDock *dock, bool pushed )
|
||||
|
||||
// Set the grabber button state
|
||||
mGrabber->PushButton( pushed );
|
||||
|
||||
if (mResizer)
|
||||
{
|
||||
mResizer->Show(mDock != NULL);
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@ -619,149 +834,9 @@ void ToolBar::OnPaint( wxPaintEvent & event )
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if( IsResizable() && IsDocked() )
|
||||
{
|
||||
wxSize sz = GetSize();
|
||||
|
||||
AColor::Dark( &dc, false );
|
||||
AColor::Line(dc, sz.x - 4, 0, sz.x - 4, sz.y );
|
||||
AColor::Line(dc, sz.x - 1, 0, sz.x - 1, sz.y );
|
||||
}
|
||||
}
|
||||
|
||||
int ToolBar::GetResizeGrabberWidth()
|
||||
{
|
||||
return RWIDTH;
|
||||
}
|
||||
|
||||
|
||||
/// @return true iff pos is in resize grabber.
|
||||
bool ToolBar::IsResizeGrabberHit( wxPoint & pos )
|
||||
{
|
||||
wxRect rect = GetRect();
|
||||
|
||||
// Adjust to size of resize grabber
|
||||
rect.x = rect.width - RWIDTH;
|
||||
rect.y = 0;
|
||||
rect.width = RWIDTH;
|
||||
return rect.Contains( pos );
|
||||
}
|
||||
|
||||
//
|
||||
// Handle toolbar resizing
|
||||
//
|
||||
void ToolBar::OnLeftDown( wxMouseEvent & event )
|
||||
{
|
||||
// Go ahead and set the event to propagate
|
||||
event.Skip();
|
||||
|
||||
// Don't do anything if we're not docked
|
||||
if( !IsDocked() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Can we be resized?
|
||||
if( IsResizable() )
|
||||
{
|
||||
wxPoint pos = event.GetPosition();
|
||||
// Is left click within resize grabber?
|
||||
if( IsResizeGrabberHit( pos ) )
|
||||
{
|
||||
// Retrieve the mouse position
|
||||
mResizeStart = ClientToScreen( pos );
|
||||
// We want all of the mouse events
|
||||
CaptureMouse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ToolBar::OnLeftUp( wxMouseEvent & event )
|
||||
{
|
||||
// Go ahead and set the event to propagate
|
||||
event.Skip();
|
||||
|
||||
if( HasCapture() )
|
||||
{
|
||||
ReleaseMouse();
|
||||
}
|
||||
|
||||
SetCursor( wxCURSOR_ARROW );
|
||||
}
|
||||
|
||||
void ToolBar::OnMotion( wxMouseEvent & event )
|
||||
{
|
||||
// Go ahead and set the event to propagate
|
||||
event.Skip();
|
||||
|
||||
// Don't do anything if we're not docked
|
||||
if( !IsDocked() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve the mouse position
|
||||
wxPoint raw_pos = event.GetPosition();
|
||||
wxPoint pos = ClientToScreen( raw_pos );
|
||||
|
||||
if( !HasCapture() )
|
||||
{
|
||||
// JKC: Wrong place for this? Surely the cursor should change on
|
||||
// mouse-down and capture-lost rather than with mouse movement?
|
||||
if( IsResizable() )
|
||||
{
|
||||
// Is left click within resize grabber?
|
||||
SetCursor( IsResizeGrabberHit( raw_pos ) ? wxCURSOR_SIZEWE : wxCURSOR_ARROW);
|
||||
}
|
||||
}
|
||||
else if( event.Dragging() )
|
||||
{
|
||||
wxRect r = GetRect();
|
||||
wxSize msz = GetMinSize();
|
||||
wxSize psz = GetParent()->GetClientSize();
|
||||
|
||||
// Adjust the size by the difference between the
|
||||
// last mouse and current mouse positions.
|
||||
r.width += ( pos.x - mResizeStart.x );
|
||||
|
||||
// Constrain
|
||||
if( r.width < msz.x )
|
||||
{
|
||||
// Don't allow resizing to go too small
|
||||
r.width = msz.x;
|
||||
}
|
||||
else if( r.GetRight() > psz.x - 3 )
|
||||
{
|
||||
// Don't allow resizing to go too large
|
||||
//
|
||||
// The 3 magic pixels are because I'm too chicken to change the
|
||||
// calculations in ToolDock::LayoutToolBars() even though I'm
|
||||
// the one that set them up. :-)
|
||||
r.SetRight( psz.x - 3 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remember for next go round
|
||||
mResizeStart = pos;
|
||||
}
|
||||
|
||||
// Resize the bar
|
||||
SetSize( r.GetSize() );
|
||||
|
||||
// Tell everyone we've changed sizes
|
||||
Updated();
|
||||
|
||||
// Refresh our world
|
||||
GetParent()->Refresh();
|
||||
GetParent()->Update();
|
||||
}
|
||||
}
|
||||
|
||||
void ToolBar::OnCaptureLost( wxMouseCaptureLostEvent & WXUNUSED(event) )
|
||||
{
|
||||
if( HasCapture() )
|
||||
{
|
||||
ReleaseMouse();
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ class AButton;
|
||||
class Grabber;
|
||||
class ToolDock;
|
||||
|
||||
class ToolBarResizer;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// class ToolBar
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -181,26 +183,22 @@ class ToolBar:public wxPanel
|
||||
|
||||
void OnErase(wxEraseEvent & event);
|
||||
void OnPaint(wxPaintEvent & event);
|
||||
void OnLeftDown(wxMouseEvent & event);
|
||||
void OnLeftUp(wxMouseEvent & event);
|
||||
void OnMotion(wxMouseEvent & event);
|
||||
void OnCaptureLost(wxMouseCaptureLostEvent & event);
|
||||
|
||||
protected:
|
||||
wxString mLabel;
|
||||
wxString mSection;
|
||||
int mType;
|
||||
private:
|
||||
bool IsResizeGrabberHit( wxPoint & pos );
|
||||
void Init(wxWindow *parent, int type, const wxString & title, const wxString & label);
|
||||
|
||||
wxWindow *mParent;
|
||||
|
||||
Grabber *mGrabber;
|
||||
ToolBarResizer *mResizer;
|
||||
|
||||
wxBoxSizer *mHSizer;
|
||||
wxSizerItem *mSpacer;
|
||||
|
||||
wxPoint mResizeStart;
|
||||
ToolDock *mDock;
|
||||
|
||||
bool mVisible;
|
||||
@ -211,6 +209,8 @@ class ToolBar:public wxPanel
|
||||
|
||||
DECLARE_CLASS(ToolBar);
|
||||
DECLARE_EVENT_TABLE();
|
||||
|
||||
friend class ToolBarResizer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user