1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-09-23 23:41:21 +02:00

Affordance handle

Adds click behaviour to a TimeShiftHandle
This commit is contained in:
Vitaly Sverchinsky 2021-07-15 14:26:09 +03:00 committed by Panagiotis Vasilopoulos
parent d199f59a7d
commit f0bbb4ecda
No known key found for this signature in database
GPG Key ID: FD806FDB3B2C5270
5 changed files with 177 additions and 2 deletions

View File

@ -853,6 +853,8 @@ list( APPEND SOURCES
# Tracks UI
tracks/ui/AffordanceHandle.cpp
tracks/ui/AffordanceHandle.h
tracks/ui/BackgroundCell.cpp
tracks/ui/BackgroundCell.h
tracks/ui/ButtonHandle.cpp

View File

@ -0,0 +1,116 @@
/*!********************************************************************
*
Audacity: A Digital Audio Editor
AffordanceHandle.cpp
Vitaly Sverchinsky
**********************************************************************/
#include "AffordanceHandle.h"
#include "../../HitTestResult.h"
#include "../../ProjectAudioIO.h"
#include "../../RefreshCode.h"
#include "../../ViewInfo.h"
#include "../../SelectionState.h"
#include "../../ProjectSettings.h"
#include "../../TrackPanelMouseEvent.h"
#include "../../WaveClip.h"
#include "../../ProjectHistory.h"
#include "../../Track.h"
#include "../../WaveTrack.h"
#include "../../../images/Cursors.h"
UIHandlePtr AffordanceHandle::HitAnywhere(std::weak_ptr<AffordanceHandle>& holder, const std::shared_ptr<Track>& pTrack)
{
auto result = std::make_shared<AffordanceHandle>(pTrack);
result = AssignUIHandlePtr(holder, result);
return result;
}
HitTestPreview AffordanceHandle::HitPreview(const AudacityProject*, bool unsafe, bool moving)
{
static auto disabledCursor =
MakeCursor(wxCURSOR_NO_ENTRY, DisabledCursorXpm, 16, 16);
static auto handOpenCursor =
MakeCursor(wxCURSOR_HAND, RearrangeCursorXpm, 16, 16);
static auto handClosedCursor =
MakeCursor(wxCURSOR_HAND, RearrangingCursorXpm, 16, 16);
// i18n-hint Appears on hovering mouse over clip affordance
auto message = XO("Click and drag to move a clip in time, or click to select");
if (unsafe)
return { message, &*disabledCursor };
return {
message,
(moving
? &*handClosedCursor
: &*handOpenCursor)
};
}
HitTestPreview AffordanceHandle::Preview(const TrackPanelMouseState& mouseState, AudacityProject* pProject)
{
const bool unsafe = ProjectAudioIO::Get(*pProject).IsAudioActive();
return HitPreview(pProject, unsafe, Clicked());
}
AffordanceHandle::AffordanceHandle(const std::shared_ptr<Track>& track)
: TimeShiftHandle(track, false)
{
SetChangeHighlight(RefreshCode::RefreshCell | RefreshCode::RefreshLatestCell);
}
UIHandle::Result AffordanceHandle::Click(const TrackPanelMouseEvent& evt, AudacityProject* pProject)
{
auto result = TimeShiftHandle::Click(evt, pProject);
return result | RefreshCode::RefreshCell;
}
UIHandle::Result AffordanceHandle::Release(const TrackPanelMouseEvent& event, AudacityProject* pProject, wxWindow* pParent)
{
auto result = TimeShiftHandle::Release(event, pProject, pParent);
//Clip was not moved
if (!TimeShiftHandle::WasMoved())
{
//almost the same behaviour as provided by SelectHandle
auto& viewInfo = ViewInfo::Get(*pProject);
const auto& settings = ProjectSettings::Get(*pProject);
const auto sTrack = TrackList::Get(*pProject).Lock<Track>(GetTrack());
const auto pTrack = sTrack.get();
auto& selectionState = SelectionState::Get(*pProject);
auto& trackList = TrackList::Get(*pProject);
// Deselect all other tracks and select this one.
selectionState.SelectNone(trackList);
selectionState.SelectTrack(*pTrack, true, true);
pTrack->TypeSwitch(
[&](WaveTrack* wt)
{
auto time = viewInfo.PositionToTime(event.event.m_x, event.rect.x);
WaveClip* const selectedClip = wt->GetClipAtTime(time);
if (selectedClip) {
viewInfo.selectedRegion.setTimes(
selectedClip->GetOffset(), selectedClip->GetEndTime());
}
},
[&](Track* track)
{
// Default behavior: select whole track
SelectionState::SelectTrackLength(viewInfo, *track, settings.IsSyncLocked());
}
);
ProjectHistory::Get(*pProject).ModifyState(false);
// Do not start a drag
result |= RefreshCode::RefreshAll | RefreshCode::Cancelled;
}
return result;
}

View File

@ -0,0 +1,28 @@
/*!********************************************************************
*
Audacity: A Digital Audio Editor
AffordanceHandle.h
Vitaly Sverchinsky
**********************************************************************/
#pragma once
#include "TimeShiftHandle.h"
class AUDACITY_DLL_API AffordanceHandle : public TimeShiftHandle
{
static HitTestPreview HitPreview(const AudacityProject*, bool unsafe, bool moving);
public:
static UIHandlePtr HitAnywhere(std::weak_ptr<AffordanceHandle>& holder, const std::shared_ptr<Track>& pTrack);
HitTestPreview Preview(const TrackPanelMouseState& mouseState, AudacityProject* pProject) override;
AffordanceHandle(const std::shared_ptr<Track>& track);
Result Click(const TrackPanelMouseEvent& evt, AudacityProject* pProject) override;
Result Release(const TrackPanelMouseEvent& event, AudacityProject* pProject, wxWindow* pParent) override;
};

View File

@ -34,6 +34,21 @@ TimeShiftHandle::TimeShiftHandle
mClipMoveState.mCapturedTrack = pTrack;
}
std::shared_ptr<Track> TimeShiftHandle::GetTrack() const
{
return mClipMoveState.mCapturedTrack;
}
bool TimeShiftHandle::WasMoved() const
{
return mDidSlideVertically || (mClipMoveState.initialized && mClipMoveState.wasMoved);
}
bool TimeShiftHandle::Clicked() const
{
return mClipMoveState.initialized;
}
void TimeShiftHandle::Enter(bool, AudacityProject *)
{
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
@ -275,6 +290,8 @@ void ClipMoveState::Init(
{
shifters.clear();
initialized = true;
auto &state = *this;
state.mCapturedTrack = capturedTrack.SharedPointer();
@ -427,6 +444,9 @@ double ClipMoveState::DoSlideHorizontal( double desiredSlideAmount )
if ( desiredSlideAmount != 0.0 )
state.DoHorizontalOffset( desiredSlideAmount );
//attempt to move a clip is counted to
wasMoved = true;
return (state.hSlideAmount = desiredSlideAmount);
}

View File

@ -234,7 +234,9 @@ struct AUDACITY_DLL_API ClipMoveState {
std::shared_ptr<Track> mCapturedTrack;
bool initialized{ false };
bool movingSelection {};
bool wasMoved{ false };
double hSlideAmount {};
ShifterMap shifters;
wxInt64 snapLeft { -1 }, snapRight { -1 };
@ -243,6 +245,8 @@ struct AUDACITY_DLL_API ClipMoveState {
void clear()
{
initialized = false;
wasMoved = false;
movingSelection = false;
hSlideAmount = 0;
shifters.clear();
@ -251,7 +255,7 @@ struct AUDACITY_DLL_API ClipMoveState {
}
};
class AUDACITY_DLL_API TimeShiftHandle final : public UIHandle
class AUDACITY_DLL_API TimeShiftHandle : public UIHandle
{
TimeShiftHandle(const TimeShiftHandle&) = delete;
static HitTestPreview HitPreview
@ -264,7 +268,6 @@ public:
TimeShiftHandle &operator=(TimeShiftHandle&&) = default;
bool IsGripHit() const { return mGripHit; }
std::shared_ptr<Track> GetTrack() const = delete;
// Try to move clips from one track to another, before also moving
// by some horizontal amount, which may be slightly adjusted to fit the
@ -304,6 +307,12 @@ public:
bool StopsOnKeystroke() override { return true; }
bool Clicked() const;
protected:
std::shared_ptr<Track> GetTrack() const;
//There were attempt to move clip/track horizontally, or to move it vertically
bool WasMoved() const;
private:
// TrackPanelDrawable implementation
void Draw(