mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-19 09:01:15 +02:00
Improve selection handling in Quick-Play
This commit is contained in:
@@ -1640,7 +1640,9 @@ AdornedRulerPanel::AdornedRulerPanel(wxWindow* parent,
|
|||||||
mPlayRegionEnd = -1;
|
mPlayRegionEnd = -1;
|
||||||
mOldPlayRegionStart = -1;
|
mOldPlayRegionStart = -1;
|
||||||
mOldPlayRegionEnd = -1;
|
mOldPlayRegionEnd = -1;
|
||||||
|
mLeftDownClick = -1;
|
||||||
mMouseEventState = mesNone;
|
mMouseEventState = mesNone;
|
||||||
|
mIsDragging = false;
|
||||||
|
|
||||||
mBuffer = new wxBitmap( 1, 1 );
|
mBuffer = new wxBitmap( 1, 1 );
|
||||||
mViewInfo = viewinfo;
|
mViewInfo = viewinfo;
|
||||||
@@ -1666,7 +1668,7 @@ AdornedRulerPanel::AdornedRulerPanel(wxWindow* parent,
|
|||||||
mIsRecording = false;
|
mIsRecording = false;
|
||||||
|
|
||||||
mTimelineToolTip = gPrefs->Read(wxT("/QuickPlay/ToolTips"), wxT("Enabled")) == wxT("Enabled");
|
mTimelineToolTip = gPrefs->Read(wxT("/QuickPlay/ToolTips"), wxT("Enabled")) == wxT("Enabled");
|
||||||
mPlayRegionDragsSelection = gPrefs->Read(wxT("/QuickPlay/DragLoopSelection"), wxT("Enabled")) == wxT("Enabled");
|
mPlayRegionDragsSelection = gPrefs->Read(wxT("/QuickPlay/DragSelection"), wxT("Enabled")) == wxT("Enabled");
|
||||||
mQuickPlayEnabled = gPrefs->Read(wxT("/QuickPlay/QuickPlayEnabled"), wxT("Enabled")) == wxT("Enabled");
|
mQuickPlayEnabled = gPrefs->Read(wxT("/QuickPlay/QuickPlayEnabled"), wxT("Enabled")) == wxT("Enabled");
|
||||||
|
|
||||||
#if wxUSE_TOOLTIPS
|
#if wxUSE_TOOLTIPS
|
||||||
@@ -1829,13 +1831,11 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
if (mIsRecording)
|
if (mIsRecording)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool isLocked = mProject->IsPlayRegionLocked();
|
// Store the initial play region state
|
||||||
|
if(mMouseEventState == mesNone) {
|
||||||
if (isLocked && evt.LeftDown()) {
|
|
||||||
mPlayRegionLock = true;
|
|
||||||
mOldPlayRegionStart = mPlayRegionStart;
|
mOldPlayRegionStart = mPlayRegionStart;
|
||||||
mOldPlayRegionEnd = mPlayRegionEnd;
|
mOldPlayRegionEnd = mPlayRegionEnd;
|
||||||
mProject->OnUnlockPlayRegion();
|
mPlayRegionLock = mProject->IsPlayRegionLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep Quick-Play within usable track area.
|
// Keep Quick-Play within usable track area.
|
||||||
@@ -1845,22 +1845,18 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
mousePosX = wxMax(evt.GetX(), tp->GetLeftOffset());
|
mousePosX = wxMax(evt.GetX(), tp->GetLeftOffset());
|
||||||
mousePosX = wxMin(mousePosX, tp->GetLeftOffset() + width - 1);
|
mousePosX = wxMin(mousePosX, tp->GetLeftOffset() + width - 1);
|
||||||
|
|
||||||
bool isWithinStart = IsWithinMarker(mousePosX, mPlayRegionStart);
|
bool isWithinStart = IsWithinMarker(mousePosX, mOldPlayRegionStart);
|
||||||
bool isWithinEnd = IsWithinMarker(mousePosX, mPlayRegionEnd);
|
bool isWithinEnd = IsWithinMarker(mousePosX, mOldPlayRegionEnd);
|
||||||
|
bool isWithinClick = (mLeftDownClick >= 0) && IsWithinMarker(mousePosX, mLeftDownClick);
|
||||||
bool canDragSel = !mPlayRegionLock && mPlayRegionDragsSelection;
|
bool canDragSel = !mPlayRegionLock && mPlayRegionDragsSelection;
|
||||||
|
|
||||||
mLastMouseX = mousePosX;
|
|
||||||
|
|
||||||
mQuickPlayPos = Pos2Time(mousePosX);
|
|
||||||
|
|
||||||
double t0 = mProject->GetTracks()->GetStartTime();
|
double t0 = mProject->GetTracks()->GetStartTime();
|
||||||
double t1 = mProject->GetTracks()->GetEndTime();
|
double t1 = mProject->GetTracks()->GetEndTime();
|
||||||
double sel0 = mProject->GetSel0();
|
double sel0 = mProject->GetSel0();
|
||||||
double sel1 = mProject->GetSel1();
|
double sel1 = mProject->GetSel1();
|
||||||
|
|
||||||
// Restrict Quick-Play region to where there is something to play or is selected.
|
mLastMouseX = mousePosX;
|
||||||
mQuickPlayPos = wxMax(0.0, mQuickPlayPos);
|
mQuickPlayPos = Pos2Time(mousePosX);
|
||||||
|
|
||||||
// If not looping, restrict selection to end of project
|
// If not looping, restrict selection to end of project
|
||||||
if (!evt.ShiftDown()) mQuickPlayPos = wxMin(t1, mQuickPlayPos);
|
if (!evt.ShiftDown()) mQuickPlayPos = wxMin(t1, mQuickPlayPos);
|
||||||
|
|
||||||
@@ -1876,8 +1872,6 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
mQuickPlayInd = false;
|
mQuickPlayInd = false;
|
||||||
wxClientDC cdc(this);
|
wxClientDC cdc(this);
|
||||||
DrawQuickPlayIndicator(&cdc, true);
|
DrawQuickPlayIndicator(&cdc, true);
|
||||||
|
|
||||||
|
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
}
|
}
|
||||||
else if (mQuickPlayEnabled) {
|
else if (mQuickPlayEnabled) {
|
||||||
@@ -1895,6 +1889,7 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
SetCursor(wxCursor(wxCURSOR_HAND));
|
SetCursor(wxCursor(wxCURSOR_HAND));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (evt.RightDown()) {
|
if (evt.RightDown()) {
|
||||||
ShowMenu(evt.GetPosition());
|
ShowMenu(evt.GetPosition());
|
||||||
}
|
}
|
||||||
@@ -1902,78 +1897,109 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
if (!mQuickPlayEnabled)
|
if (!mQuickPlayEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mSnapManager) {
|
|
||||||
// Create a new snap manager in case any snap-points have changed
|
HandleSnapping();
|
||||||
delete mSnapManager;
|
|
||||||
}
|
|
||||||
mSnapManager = new SnapManager(mProject->GetTracks(), NULL,
|
|
||||||
mViewInfo->zoom,
|
|
||||||
QUICK_PLAY_SNAP_PIXEL);
|
|
||||||
bool snappedPoint, snappedTime;
|
|
||||||
mIsSnapped = (mSnapManager->Snap(NULL, mQuickPlayPos, false,
|
|
||||||
&mQuickPlayPos, &snappedPoint, &snappedTime));
|
|
||||||
|
|
||||||
if (evt.LeftDown())
|
if (evt.LeftDown())
|
||||||
{
|
{
|
||||||
mButtonDownMousePos = mousePosX;
|
// Temporarily unlock locked play region
|
||||||
|
if (mPlayRegionLock && evt.LeftDown()) {
|
||||||
|
//mPlayRegionLock = true;
|
||||||
|
mProject->OnUnlockPlayRegion();
|
||||||
|
}
|
||||||
|
|
||||||
if (isWithinStart && isWithinEnd) {
|
mLeftDownClick = mQuickPlayPos;
|
||||||
// Both could be selected, check which marker is nearer
|
isWithinClick = IsWithinMarker(mousePosX, mLeftDownClick);
|
||||||
if (fabs(mQuickPlayPos - mPlayRegionStart) < fabs(mQuickPlayPos - mPlayRegionEnd))
|
|
||||||
mMouseEventState = mesDraggingPlayRegionStart;
|
if (isWithinStart || isWithinEnd) {
|
||||||
else
|
// If Quick-Play is playing from a point, we need to treat it as a click
|
||||||
mMouseEventState = mesDraggingPlayRegionEnd;
|
// not as dragging.
|
||||||
|
if (mOldPlayRegionStart == mOldPlayRegionEnd)
|
||||||
|
mMouseEventState = mesSelectingPlayRegionClick;
|
||||||
|
// otherwise check which marker is nearer
|
||||||
|
else {
|
||||||
|
if (fabs(mQuickPlayPos - mOldPlayRegionStart) < fabs(mQuickPlayPos - mOldPlayRegionEnd))
|
||||||
|
mMouseEventState = mesDraggingPlayRegionStart;
|
||||||
|
else
|
||||||
|
mMouseEventState = mesDraggingPlayRegionEnd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (isWithinStart)
|
|
||||||
mMouseEventState = mesDraggingPlayRegionStart;
|
|
||||||
else if (isWithinEnd)
|
|
||||||
mMouseEventState = mesDraggingPlayRegionEnd;
|
|
||||||
else {
|
else {
|
||||||
// First, we enter "click" mode to avoid selecting a small range
|
// Clicked but not yet dragging
|
||||||
// accidentially
|
|
||||||
mMouseEventState = mesSelectingPlayRegionClick;
|
mMouseEventState = mesSelectingPlayRegionClick;
|
||||||
mPlayRegionStart = mQuickPlayPos;
|
|
||||||
mPlayRegionEnd = mQuickPlayPos;
|
|
||||||
Refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we are dragging BEFORE CaptureMouse.
|
// Check if we are dragging BEFORE CaptureMouse.
|
||||||
if (mMouseEventState != mesNone)
|
if (mMouseEventState != mesNone)
|
||||||
SetCursor(wxCursor(wxCURSOR_SIZEWE));
|
SetCursor(wxCursor(wxCURSOR_SIZEWE));
|
||||||
CaptureMouse();
|
CaptureMouse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
switch (mMouseEventState)
|
switch (mMouseEventState)
|
||||||
{
|
{
|
||||||
case mesNone:
|
case mesNone:
|
||||||
// do nothing
|
// If close to either end of play region, snap to closest
|
||||||
|
if (isWithinStart || isWithinEnd) {
|
||||||
|
if (fabs(mQuickPlayPos - mOldPlayRegionStart) < fabs(mQuickPlayPos - mOldPlayRegionEnd))
|
||||||
|
mQuickPlayPos = mOldPlayRegionStart;
|
||||||
|
else
|
||||||
|
mQuickPlayPos = mOldPlayRegionEnd;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case mesDraggingPlayRegionStart:
|
case mesDraggingPlayRegionStart:
|
||||||
|
// Don't start dragging until beyond tollerance initial playback start
|
||||||
|
if (!mIsDragging && isWithinStart)
|
||||||
|
mQuickPlayPos = mOldPlayRegionStart;
|
||||||
|
else
|
||||||
|
mIsDragging = true;
|
||||||
|
// avoid accidental tiny selection
|
||||||
|
if (isWithinEnd)
|
||||||
|
mQuickPlayPos = mOldPlayRegionEnd;
|
||||||
mPlayRegionStart = mQuickPlayPos;
|
mPlayRegionStart = mQuickPlayPos;
|
||||||
if (canDragSel) {
|
if (canDragSel) {
|
||||||
DragSelection();
|
DragSelection();
|
||||||
}
|
}
|
||||||
Refresh();
|
|
||||||
break;
|
break;
|
||||||
case mesDraggingPlayRegionEnd:
|
case mesDraggingPlayRegionEnd:
|
||||||
|
if (!mIsDragging && isWithinEnd)
|
||||||
|
mQuickPlayPos = mOldPlayRegionEnd;
|
||||||
|
else
|
||||||
|
mIsDragging = true;
|
||||||
|
if (isWithinStart)
|
||||||
|
mQuickPlayPos = mOldPlayRegionStart;
|
||||||
mPlayRegionEnd = mQuickPlayPos;
|
mPlayRegionEnd = mQuickPlayPos;
|
||||||
if (canDragSel) {
|
if (canDragSel) {
|
||||||
DragSelection();
|
DragSelection();
|
||||||
}
|
}
|
||||||
Refresh();
|
|
||||||
break;
|
break;
|
||||||
case mesSelectingPlayRegionClick:
|
case mesSelectingPlayRegionClick:
|
||||||
if (abs(mousePosX - mButtonDownMousePos) > SELECT_TOLERANCE_PIXEL)
|
// Don't start dragging until mouse is beyond tollerance of initial click.
|
||||||
{
|
if (isWithinClick || mLeftDownClick == -1) {
|
||||||
// User moved mouse at least SELECT_TOLERANCE_PIXEL, so change
|
mQuickPlayPos = mLeftDownClick;
|
||||||
// from "click" mode to "range" mode to allow selecting a range
|
mPlayRegionStart = mLeftDownClick;
|
||||||
|
mPlayRegionEnd = mLeftDownClick;
|
||||||
|
}
|
||||||
|
else {
|
||||||
mMouseEventState = mesSelectingPlayRegionRange;
|
mMouseEventState = mesSelectingPlayRegionRange;
|
||||||
mPlayRegionEnd = mQuickPlayPos;
|
|
||||||
Refresh();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case mesSelectingPlayRegionRange:
|
case mesSelectingPlayRegionRange:
|
||||||
mPlayRegionEnd = mQuickPlayPos;
|
if (isWithinClick) {
|
||||||
Refresh();
|
mQuickPlayPos = mLeftDownClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mQuickPlayPos < mLeftDownClick) {
|
||||||
|
mPlayRegionStart = mQuickPlayPos;
|
||||||
|
mPlayRegionEnd = mLeftDownClick;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mPlayRegionEnd = mQuickPlayPos;
|
||||||
|
mPlayRegionStart = mLeftDownClick;
|
||||||
|
}
|
||||||
|
if (canDragSel) {
|
||||||
|
DragSelection();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1986,13 +2012,7 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
if (HasCapture())
|
if (HasCapture())
|
||||||
ReleaseMouse();
|
ReleaseMouse();
|
||||||
|
|
||||||
int playlength = Seconds2Pixels(fabs(mPlayRegionEnd - mPlayRegionStart));
|
if (mPlayRegionEnd < mPlayRegionStart) {
|
||||||
if (playlength < SELECT_TOLERANCE_PIXEL) {
|
|
||||||
// Mouse has slipped back within tolerance range.
|
|
||||||
// We have been dragging mPlayRegionEnd, so snap it back to mPlayRegionStart.
|
|
||||||
mPlayRegionEnd = mPlayRegionStart;
|
|
||||||
}
|
|
||||||
else if (mPlayRegionEnd < mPlayRegionStart) {
|
|
||||||
// Swap values to ensure mPlayRegionStart < mPlayRegionEnd
|
// Swap values to ensure mPlayRegionStart < mPlayRegionEnd
|
||||||
double tmp = mPlayRegionStart;
|
double tmp = mPlayRegionStart;
|
||||||
mPlayRegionStart = mPlayRegionEnd;
|
mPlayRegionStart = mPlayRegionEnd;
|
||||||
@@ -2023,8 +2043,6 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
// Start / Restart playback on left click.
|
// Start / Restart playback on left click.
|
||||||
bool startPlaying = (mPlayRegionStart >= 0);
|
bool startPlaying = (mPlayRegionStart >= 0);
|
||||||
|
|
||||||
mMouseEventState = mesNone;
|
|
||||||
|
|
||||||
if (startPlaying) {
|
if (startPlaying) {
|
||||||
ControlToolBar* ctb = mProject->GetControlToolBar();
|
ControlToolBar* ctb = mProject->GetControlToolBar();
|
||||||
ctb->StopPlaying();
|
ctb->StopPlaying();
|
||||||
@@ -2054,14 +2072,14 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
AudioIOStartStreamOptions options(mProject->GetDefaultPlayOptions());
|
AudioIOStartStreamOptions options(mProject->GetDefaultPlayOptions());
|
||||||
options.playLooped = (loopEnabled && evt.ShiftDown());
|
options.playLooped = (loopEnabled && evt.ShiftDown());
|
||||||
|
|
||||||
if (!evt.ControlDown())
|
if (!evt.CmdDown()) // Use CmdDown rather than ControlDown. See bug 746
|
||||||
options.pStartTime = &mPlayRegionStart;
|
options.pStartTime = &mPlayRegionStart;
|
||||||
else
|
else
|
||||||
options.timeTrack = NULL;
|
options.timeTrack = NULL;
|
||||||
|
|
||||||
ctb->PlayPlayRegion((SelectedRegion(start, end)),
|
ctb->PlayPlayRegion((SelectedRegion(start, end)),
|
||||||
options,
|
options,
|
||||||
evt.ControlDown(),
|
evt.CmdDown(),
|
||||||
false,
|
false,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
@@ -2070,6 +2088,10 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt)
|
|||||||
DoDrawPlayRegion(&cdc);
|
DoDrawPlayRegion(&cdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mMouseEventState = mesNone;
|
||||||
|
mIsDragging = false;
|
||||||
|
mLeftDownClick = -1;
|
||||||
|
|
||||||
if (mPlayRegionLock) {
|
if (mPlayRegionLock) {
|
||||||
// Restore Locked Play region
|
// Restore Locked Play region
|
||||||
SetPlayRegion(mOldPlayRegionStart, mOldPlayRegionEnd);
|
SetPlayRegion(mOldPlayRegionStart, mOldPlayRegionEnd);
|
||||||
@@ -2148,7 +2170,7 @@ void AdornedRulerPanel::OnToggleQuickPlay(wxCommandEvent& evt)
|
|||||||
void AdornedRulerPanel::OnSyncSelToQuickPlay(wxCommandEvent& evt)
|
void AdornedRulerPanel::OnSyncSelToQuickPlay(wxCommandEvent& evt)
|
||||||
{
|
{
|
||||||
mPlayRegionDragsSelection = (mPlayRegionDragsSelection)? false : true;
|
mPlayRegionDragsSelection = (mPlayRegionDragsSelection)? false : true;
|
||||||
gPrefs->Write(wxT("/QuickPlay/DragLoopSelection"), mPlayRegionDragsSelection ? wxT("Enabled") : wxT("Disabled"));
|
gPrefs->Write(wxT("/QuickPlay/DragSelection"), mPlayRegionDragsSelection ? wxT("Enabled") : wxT("Disabled"));
|
||||||
gPrefs->Flush();
|
gPrefs->Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2166,6 +2188,22 @@ void AdornedRulerPanel::DragSelection()
|
|||||||
mProject->GetTrackPanel()->TrackPanel::Refresh(false);
|
mProject->GetTrackPanel()->TrackPanel::Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AdornedRulerPanel::HandleSnapping()
|
||||||
|
{
|
||||||
|
if (mSnapManager) {
|
||||||
|
// Create a new snap manager in case any snap-points have changed
|
||||||
|
delete mSnapManager;
|
||||||
|
}
|
||||||
|
mSnapManager = new SnapManager(mProject->GetTracks(), NULL,
|
||||||
|
mViewInfo->zoom,
|
||||||
|
QUICK_PLAY_SNAP_PIXEL);
|
||||||
|
bool snappedPoint, snappedTime;
|
||||||
|
mIsSnapped = (mSnapManager->Snap(NULL, mQuickPlayPos, false,
|
||||||
|
&mQuickPlayPos, &snappedPoint, &snappedTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void AdornedRulerPanel::OnTimelineToolTips(wxCommandEvent& evt)
|
void AdornedRulerPanel::OnTimelineToolTips(wxCommandEvent& evt)
|
||||||
{
|
{
|
||||||
mTimelineToolTip = (mTimelineToolTip)? false : true;
|
mTimelineToolTip = (mTimelineToolTip)? false : true;
|
||||||
|
@@ -327,6 +327,7 @@ private:
|
|||||||
//
|
//
|
||||||
void ShowMenu(const wxPoint & pos);
|
void ShowMenu(const wxPoint & pos);
|
||||||
void DragSelection();
|
void DragSelection();
|
||||||
|
void HandleSnapping();
|
||||||
void OnToggleQuickPlay(wxCommandEvent &evt);
|
void OnToggleQuickPlay(wxCommandEvent &evt);
|
||||||
void OnSyncSelToQuickPlay(wxCommandEvent &evt);
|
void OnSyncSelToQuickPlay(wxCommandEvent &evt);
|
||||||
void OnTimelineToolTips(wxCommandEvent &evt);
|
void OnTimelineToolTips(wxCommandEvent &evt);
|
||||||
@@ -347,8 +348,9 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
MouseEventState mMouseEventState;
|
MouseEventState mMouseEventState;
|
||||||
int mButtonDownMousePos;
|
double mLeftDownClick; // click position in seconds
|
||||||
int mLastMouseX;
|
int mLastMouseX; // Pixel position
|
||||||
|
bool mIsDragging;
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user