1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-30 15:39:27 +02:00

Draggable pinned play head, double click to re-center

This commit is contained in:
Paul Licameli 2018-07-31 23:51:46 -04:00
parent 616ff31d04
commit 27dc8ffead
2 changed files with 130 additions and 1 deletions

View File

@ -248,4 +248,7 @@
// PRL 1 Jun 2018
#define EXPERIMENTAL_PUNCH_AND_ROLL
// PRL 31 July 2018
#define EXPERIMENTAL_DRAGGABLE_PLAY_HEAD
#endif

View File

@ -2168,6 +2168,121 @@ private:
SelectedRegion mOldSelection;
};
namespace
{
wxCoord GetPlayHeadX( const AudacityProject *pProject )
{
const TrackPanel *tp = pProject->GetTrackPanel();
int width;
tp->GetTracksUsableArea(&width, NULL);
return tp->GetLeftOffset()
+ width * TracksPrefs::GetPinnedHeadPositionPreference();
}
double GetPlayHeadFraction( const AudacityProject *pProject, wxCoord xx )
{
const TrackPanel *tp = pProject->GetTrackPanel();
int width;
tp->GetTracksUsableArea(&width, NULL);
auto fraction = (xx - tp->GetLeftOffset()) / double(width);
return std::max(0.0, std::min(1.0, fraction));
}
// Handle for dragging the pinned play head, which so far does not need
// to be a friend of the AdornedRulerPanel class, so we don't make it nested.
class PlayheadHandle : public UIHandle
{
public:
explicit
PlayheadHandle( wxCoord xx )
: mX( xx )
{}
static UIHandle::Result NeedChangeHighlight
(const PlayheadHandle &oldState, const PlayheadHandle &newState)
{
if (oldState.mX != newState.mX)
return RefreshCode::DrawOverlays;
return 0;
}
static std::shared_ptr<PlayheadHandle>
HitTest( const AudacityProject *pProject, wxCoord xx )
{
if( TracksPrefs::GetPinnedHeadPreference() &&
pProject->IsAudioActive() )
{
const auto targetX = GetPlayHeadX( pProject );
if ( abs( xx - targetX ) <= SELECT_TOLERANCE_PIXEL )
return std::make_shared<PlayheadHandle>( xx );
}
return {};
}
protected:
Result Click
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
{
if (event.event.LeftDClick()) {
// Restore default position on double click
TracksPrefs::SetPinnedHeadPositionPreference( 0.5, true );
return RefreshCode::DrawOverlays |
// Do not start a drag
RefreshCode::Cancelled;
}
mOrigPreference = TracksPrefs::GetPinnedHeadPositionPreference();
return 0;
}
Result Drag
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
{
auto value = GetPlayHeadFraction(pProject, event.event.m_x );
TracksPrefs::SetPinnedHeadPositionPreference( value );
return RefreshCode::DrawOverlays;
}
HitTestPreview Preview
(const TrackPanelMouseState &state, const AudacityProject *pProject)
override
{
static wxCursor cursor{ wxCURSOR_SIZEWE };
return {
_( "Click and drag to adjust, double-click to reset" ),
&cursor,
_( "Record/Play head" )
};
}
Result Release
(const TrackPanelMouseEvent &event, AudacityProject *pProject,
wxWindow *) override
{
auto value = GetPlayHeadFraction(pProject, event.event.m_x );
TracksPrefs::SetPinnedHeadPositionPreference( value, true );
return RefreshCode::DrawOverlays;
}
Result Cancel(AudacityProject *pProject) override
{
TracksPrefs::SetPinnedHeadPositionPreference( mOrigPreference );
return RefreshCode::DrawOverlays;
}
void Enter(bool) override
{
mChangeHighlight = RefreshCode::DrawOverlays;
}
wxCoord mX;
double mOrigPreference {};
};
}
class AdornedRulerPanel::QPCell final : public CommonCell
{
public:
@ -2192,6 +2307,7 @@ public:
}
std::weak_ptr<QPHandle> mHolder;
std::weak_ptr<PlayheadHandle> mPlayheadHolder;
};
std::vector<UIHandlePtr> AdornedRulerPanel::QPCell::HitTest
@ -2203,11 +2319,21 @@ std::vector<UIHandlePtr> AdornedRulerPanel::QPCell::HitTest
mParent->CreateOverlays();
std::vector<UIHandlePtr> results;
auto xx = state.state.m_x;
#ifdef EXPERIMENTAL_DRAGGABLE_PLAY_HEAD
// Allow click and drag on the play head even while recording
// Make this handle more prominent then the quick play handle
auto result = PlayheadHandle::HitTest( pProject, xx );
if (result) {
result = AssignUIHandlePtr( mPlayheadHolder, result );
results.push_back( result );
}
#endif
// Disable mouse actions on Timeline while recording.
if (!mParent->mIsRecording) {
auto xx = state.state.m_x;
mParent->UpdateQuickPlayPos( xx, state.state.ShiftDown() );
auto result = std::make_shared<QPHandle>( mParent, xx );