1
0
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:
lllucius 2014-12-11 08:05:11 +00:00
parent 2e29d9d2b1
commit 2f177032ed
2 changed files with 232 additions and 157 deletions

View File

@ -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();
}
}

View File

@ -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