mirror of
https://github.com/cookiengineer/audacity
synced 2025-09-23 15:41:09 +02:00
Affordance handle
Adds click behaviour to a TimeShiftHandle
This commit is contained in:
parent
d199f59a7d
commit
f0bbb4ecda
@ -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
|
||||
|
116
src/tracks/ui/AffordanceHandle.cpp
Normal file
116
src/tracks/ui/AffordanceHandle.cpp
Normal 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;
|
||||
}
|
28
src/tracks/ui/AffordanceHandle.h
Normal file
28
src/tracks/ui/AffordanceHandle.h
Normal 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;
|
||||
};
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
Loading…
x
Reference in New Issue
Block a user