mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-16 16:10:06 +02:00
TrackPanel no longer implements the envelope tool...
... also implement ESC key for it
This commit is contained in:
parent
ef38af71dd
commit
2496b0d7bc
@ -1206,6 +1206,7 @@
|
|||||||
28FE4A090ABF4E960056F5C4 /* sse_optimized.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 28FE4A070ABF4E960056F5C4 /* sse_optimized.cpp */; };
|
28FE4A090ABF4E960056F5C4 /* sse_optimized.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 28FE4A070ABF4E960056F5C4 /* sse_optimized.cpp */; };
|
||||||
5E000A211EC7B5D500E8FD93 /* SampleHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E000A1F1EC7B5D500E8FD93 /* SampleHandle.cpp */; };
|
5E000A211EC7B5D500E8FD93 /* SampleHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E000A1F1EC7B5D500E8FD93 /* SampleHandle.cpp */; };
|
||||||
5E7396441DAFD8C600BA0A4D /* TimeShiftHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E7396421DAFD8C600BA0A4D /* TimeShiftHandle.cpp */; };
|
5E7396441DAFD8C600BA0A4D /* TimeShiftHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E7396421DAFD8C600BA0A4D /* TimeShiftHandle.cpp */; };
|
||||||
|
5E7396471DAFD8F200BA0A4D /* EnvelopeHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E7396451DAFD8F200BA0A4D /* EnvelopeHandle.cpp */; };
|
||||||
5E02BFF21D1164DF00EB7578 /* Distortion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E02BFF01D1164DF00EB7578 /* Distortion.cpp */; };
|
5E02BFF21D1164DF00EB7578 /* Distortion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E02BFF01D1164DF00EB7578 /* Distortion.cpp */; };
|
||||||
5E07842E1DEE6B8600CA76EA /* FileException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E07842C1DEE6B8600CA76EA /* FileException.cpp */; };
|
5E07842E1DEE6B8600CA76EA /* FileException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E07842C1DEE6B8600CA76EA /* FileException.cpp */; };
|
||||||
5E0784311DF1E4F400CA76EA /* UserException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E07842F1DF1E4F400CA76EA /* UserException.cpp */; };
|
5E0784311DF1E4F400CA76EA /* UserException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E07842F1DF1E4F400CA76EA /* UserException.cpp */; };
|
||||||
@ -3007,6 +3008,8 @@
|
|||||||
5E000A201EC7B5D500E8FD93 /* SampleHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SampleHandle.h; sourceTree = "<group>"; };
|
5E000A201EC7B5D500E8FD93 /* SampleHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SampleHandle.h; sourceTree = "<group>"; };
|
||||||
5E7396421DAFD8C600BA0A4D /* TimeShiftHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeShiftHandle.cpp; sourceTree = "<group>"; };
|
5E7396421DAFD8C600BA0A4D /* TimeShiftHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeShiftHandle.cpp; sourceTree = "<group>"; };
|
||||||
5E7396431DAFD8C600BA0A4D /* TimeShiftHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TimeShiftHandle.h; sourceTree = "<group>"; };
|
5E7396431DAFD8C600BA0A4D /* TimeShiftHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TimeShiftHandle.h; sourceTree = "<group>"; };
|
||||||
|
5E7396451DAFD8F200BA0A4D /* EnvelopeHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EnvelopeHandle.cpp; sourceTree = "<group>"; };
|
||||||
|
5E7396461DAFD8F200BA0A4D /* EnvelopeHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EnvelopeHandle.h; sourceTree = "<group>"; };
|
||||||
5E02BFF01D1164DF00EB7578 /* Distortion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Distortion.cpp; sourceTree = "<group>"; };
|
5E02BFF01D1164DF00EB7578 /* Distortion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Distortion.cpp; sourceTree = "<group>"; };
|
||||||
5E02BFF11D1164DF00EB7578 /* Distortion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Distortion.h; sourceTree = "<group>"; };
|
5E02BFF11D1164DF00EB7578 /* Distortion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Distortion.h; sourceTree = "<group>"; };
|
||||||
5E07842C1DEE6B8600CA76EA /* FileException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileException.cpp; sourceTree = "<group>"; };
|
5E07842C1DEE6B8600CA76EA /* FileException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileException.cpp; sourceTree = "<group>"; };
|
||||||
@ -5733,6 +5736,7 @@
|
|||||||
children = (
|
children = (
|
||||||
5E1512661DB0010C00702E29 /* CommonTrackPanelCell.cpp */,
|
5E1512661DB0010C00702E29 /* CommonTrackPanelCell.cpp */,
|
||||||
5E74D2DD1CC4429700D88B0B /* EditCursorOverlay.cpp */,
|
5E74D2DD1CC4429700D88B0B /* EditCursorOverlay.cpp */,
|
||||||
|
5E7396451DAFD8F200BA0A4D /* EnvelopeHandle.cpp */,
|
||||||
5E74D2DF1CC4429700D88B0B /* PlayIndicatorOverlay.cpp */,
|
5E74D2DF1CC4429700D88B0B /* PlayIndicatorOverlay.cpp */,
|
||||||
5E74D2E11CC4429700D88B0B /* Scrubbing.cpp */,
|
5E74D2E11CC4429700D88B0B /* Scrubbing.cpp */,
|
||||||
5E7396421DAFD8C600BA0A4D /* TimeShiftHandle.cpp */,
|
5E7396421DAFD8C600BA0A4D /* TimeShiftHandle.cpp */,
|
||||||
@ -5742,6 +5746,7 @@
|
|||||||
5E73963C1DAFD86000BA0A4D /* ZoomHandle.cpp */,
|
5E73963C1DAFD86000BA0A4D /* ZoomHandle.cpp */,
|
||||||
5E1512671DB0010C00702E29 /* CommonTrackPanelCell.h */,
|
5E1512671DB0010C00702E29 /* CommonTrackPanelCell.h */,
|
||||||
5E74D2DE1CC4429700D88B0B /* EditCursorOverlay.h */,
|
5E74D2DE1CC4429700D88B0B /* EditCursorOverlay.h */,
|
||||||
|
5E7396461DAFD8F200BA0A4D /* EnvelopeHandle.h */,
|
||||||
5E74D2E01CC4429700D88B0B /* PlayIndicatorOverlay.h */,
|
5E74D2E01CC4429700D88B0B /* PlayIndicatorOverlay.h */,
|
||||||
5E74D2E21CC4429700D88B0B /* Scrubbing.h */,
|
5E74D2E21CC4429700D88B0B /* Scrubbing.h */,
|
||||||
5E7396431DAFD8C600BA0A4D /* TimeShiftHandle.h */,
|
5E7396431DAFD8C600BA0A4D /* TimeShiftHandle.h */,
|
||||||
@ -7877,6 +7882,7 @@
|
|||||||
280A8B4719F4403B0091DE70 /* ModuleManager.cpp in Sources */,
|
280A8B4719F4403B0091DE70 /* ModuleManager.cpp in Sources */,
|
||||||
5EA018291EC7B226001F2996 /* NoteTrackUI.cpp in Sources */,
|
5EA018291EC7B226001F2996 /* NoteTrackUI.cpp in Sources */,
|
||||||
280A8B4A19F440880091DE70 /* EffectRack.cpp in Sources */,
|
280A8B4A19F440880091DE70 /* EffectRack.cpp in Sources */,
|
||||||
|
5E7396471DAFD8F200BA0A4D /* EnvelopeHandle.cpp in Sources */,
|
||||||
28001B3E1A0F0E5D007DD161 /* NumericTextCtrl.cpp in Sources */,
|
28001B3E1A0F0E5D007DD161 /* NumericTextCtrl.cpp in Sources */,
|
||||||
28001B4B1A0F0EB6007DD161 /* SpectralSelectionBar.cpp in Sources */,
|
28001B4B1A0F0EB6007DD161 /* SpectralSelectionBar.cpp in Sources */,
|
||||||
28BB98051A15BE6800D1CC80 /* NoiseReduction.cpp in Sources */,
|
28BB98051A15BE6800D1CC80 /* NoiseReduction.cpp in Sources */,
|
||||||
|
@ -575,6 +575,8 @@ audacity_SOURCES = \
|
|||||||
tracks/ui/CommonTrackPanelCell.h \
|
tracks/ui/CommonTrackPanelCell.h \
|
||||||
tracks/ui/EditCursorOverlay.cpp \
|
tracks/ui/EditCursorOverlay.cpp \
|
||||||
tracks/ui/EditCursorOverlay.h \
|
tracks/ui/EditCursorOverlay.h \
|
||||||
|
tracks/ui/EnvelopeHandle.cpp \
|
||||||
|
tracks/ui/EnvelopeHandle.h \
|
||||||
tracks/ui/PlayIndicatorOverlay.cpp \
|
tracks/ui/PlayIndicatorOverlay.cpp \
|
||||||
tracks/ui/PlayIndicatorOverlay.h \
|
tracks/ui/PlayIndicatorOverlay.h \
|
||||||
tracks/ui/Scrubbing.cpp \
|
tracks/ui/Scrubbing.cpp \
|
||||||
|
@ -170,7 +170,6 @@ is time to refresh some aspect of the screen.
|
|||||||
#include "AColor.h"
|
#include "AColor.h"
|
||||||
#include "AllThemeResources.h"
|
#include "AllThemeResources.h"
|
||||||
#include "AudioIO.h"
|
#include "AudioIO.h"
|
||||||
#include "Envelope.h"
|
|
||||||
#include "float_cast.h"
|
#include "float_cast.h"
|
||||||
#include "LabelTrack.h"
|
#include "LabelTrack.h"
|
||||||
#include "MixerBoard.h"
|
#include "MixerBoard.h"
|
||||||
@ -1150,7 +1149,6 @@ void TrackPanel::HandleInterruptedDrag()
|
|||||||
IsClosing,
|
IsClosing,
|
||||||
IsAdjustingLabel,
|
IsAdjustingLabel,
|
||||||
IsRearranging,
|
IsRearranging,
|
||||||
IsEnveloping,
|
|
||||||
IsGainSliding,
|
IsGainSliding,
|
||||||
IsPanSliding,
|
IsPanSliding,
|
||||||
WasOverCutLine,
|
WasOverCutLine,
|
||||||
@ -1406,9 +1404,6 @@ bool TrackPanel::SetCursorByActivity( )
|
|||||||
case IsSelecting:
|
case IsSelecting:
|
||||||
SetCursor(*mSelectCursor);
|
SetCursor(*mSelectCursor);
|
||||||
return true;
|
return true;
|
||||||
case IsEnveloping:
|
|
||||||
SetCursor( unsafe ? *mDisabledCursor : *mEnvelopeCursor);
|
|
||||||
return true;
|
|
||||||
case IsRearranging:
|
case IsRearranging:
|
||||||
SetCursor( unsafe ? *mDisabledCursor : *mRearrangeCursor);
|
SetCursor( unsafe ? *mDisabledCursor : *mRearrangeCursor);
|
||||||
return true;
|
return true;
|
||||||
@ -1750,16 +1745,11 @@ void TrackPanel::SetCursorAndTipWhenSelectTool( Track * t,
|
|||||||
void TrackPanel::SetCursorAndTipByTool( int tool,
|
void TrackPanel::SetCursorAndTipByTool( int tool,
|
||||||
const wxMouseEvent &, wxString& )
|
const wxMouseEvent &, wxString& )
|
||||||
{
|
{
|
||||||
bool unsafe = IsUnsafe();
|
|
||||||
|
|
||||||
// Change the cursor based on the active tool.
|
// Change the cursor based on the active tool.
|
||||||
switch (tool) {
|
switch (tool) {
|
||||||
case selectTool:
|
case selectTool:
|
||||||
wxFAIL;// should have already been handled
|
wxFAIL;// should have already been handled
|
||||||
break;
|
break;
|
||||||
case envelopeTool:
|
|
||||||
SetCursor(unsafe ? *mDisabledCursor : *mEnvelopeCursor);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
// doesn't actually change the tip itself, but it could (should?) do at some
|
// doesn't actually change the tip itself, but it could (should?) do at some
|
||||||
// future date.
|
// future date.
|
||||||
@ -3138,171 +3128,6 @@ bool mayDragWidth, bool onlyWithinSnapDistance,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HandleEnvelope gets called when the user is changing the
|
|
||||||
/// amplitude envelope on a track.
|
|
||||||
void TrackPanel::HandleEnvelope(wxMouseEvent & event)
|
|
||||||
{
|
|
||||||
if (event.LeftDown()) {
|
|
||||||
const auto foundCell = FindCell(event.m_x, event.m_y);
|
|
||||||
auto &pTrack = foundCell.pTrack;
|
|
||||||
auto &rect = foundCell.rect;
|
|
||||||
|
|
||||||
if (!pTrack || foundCell.type != CellType::Track)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetCapturedTrack(pTrack, IsEnveloping);
|
|
||||||
|
|
||||||
if (mCapturedTrack->GetKind() == Track::Wave)
|
|
||||||
{
|
|
||||||
mCapturedEnvelope =
|
|
||||||
((WaveTrack*)mCapturedTrack)->GetEnvelopeAtX(event.GetX());
|
|
||||||
} else {
|
|
||||||
mCapturedEnvelope = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mCapturedRect = rect;
|
|
||||||
mCapturedRect.y += kTopMargin;
|
|
||||||
mCapturedRect.height -= kTopMargin + kBottomMargin;
|
|
||||||
}
|
|
||||||
// AS: if there's actually a selected track, then forward all of the
|
|
||||||
// mouse events to its envelope.
|
|
||||||
if (mCapturedTrack)
|
|
||||||
ForwardEventToEnvelope(event);
|
|
||||||
|
|
||||||
// We test for IsEnveloping, because we could have had our action stopped already,
|
|
||||||
// and already recorded and the second mouse up is bogus.
|
|
||||||
// e.g could be stopped by some key press. Bug 1496.
|
|
||||||
if ((mMouseCapture == IsEnveloping ) && event.LeftUp()) {
|
|
||||||
SetCapturedTrack( NULL );
|
|
||||||
MakeParentPushState(
|
|
||||||
/* i18n-hint: (verb) Audacity has just adjusted the envelope .*/
|
|
||||||
_("Adjusted envelope."),
|
|
||||||
/* i18n-hint: The envelope is a curve that controls the audio loudness.*/
|
|
||||||
_("Envelope")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// We've established we're a time track.
|
|
||||||
/// send events for its envelope.
|
|
||||||
void TrackPanel::ForwardEventToTimeTrackEnvelope(wxMouseEvent & event)
|
|
||||||
{
|
|
||||||
// Assume captured track was time
|
|
||||||
const auto ptimetrack = static_cast<TimeTrack *>(mCapturedTrack);
|
|
||||||
Envelope *pspeedenvelope = ptimetrack->GetEnvelope();
|
|
||||||
|
|
||||||
wxRect envRect = mCapturedRect;
|
|
||||||
double lower = ptimetrack->GetRangeLower(), upper = ptimetrack->GetRangeUpper();
|
|
||||||
const double dBRange = mViewInfo->dBr;
|
|
||||||
if (ptimetrack->GetDisplayLog()) {
|
|
||||||
// MB: silly way to undo the work of GetWaveYPos while still getting a logarithmic scale
|
|
||||||
lower = LINEAR_TO_DB(std::max(1.0e-7, lower)) / dBRange + 1.0;
|
|
||||||
upper = LINEAR_TO_DB(std::max(1.0e-7, upper)) / dBRange + 1.0;
|
|
||||||
}
|
|
||||||
if (event.ButtonDown()) {
|
|
||||||
mEnvelopeEditor = std::make_unique<EnvelopeEditor>(*pspeedenvelope, false);
|
|
||||||
mEnvelopeEditorRight.reset();
|
|
||||||
}
|
|
||||||
bool needUpdate =
|
|
||||||
mEnvelopeEditor &&
|
|
||||||
mEnvelopeEditor->MouseEvent(
|
|
||||||
event, envRect,
|
|
||||||
*mViewInfo,
|
|
||||||
ptimetrack->GetDisplayLog(), dBRange, lower, upper);
|
|
||||||
if (needUpdate) {
|
|
||||||
RefreshTrack(mCapturedTrack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// We've established we're a wave track.
|
|
||||||
/// send events for its envelope.
|
|
||||||
void TrackPanel::ForwardEventToWaveTrackEnvelope(wxMouseEvent & event)
|
|
||||||
{
|
|
||||||
// Assume captured track was wave
|
|
||||||
const auto pwavetrack = static_cast<WaveTrack*>(mCapturedTrack);
|
|
||||||
Envelope *penvelope = mCapturedEnvelope;
|
|
||||||
|
|
||||||
// Possibly no-envelope, for example when in spectrum view mode.
|
|
||||||
// if so, then bail out.
|
|
||||||
if (!penvelope)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// AS: WaveTracks can be displayed in several different formats.
|
|
||||||
// This asks which one is in use. (ie, Wave, Spectrum, etc)
|
|
||||||
int display = pwavetrack->GetDisplay();
|
|
||||||
|
|
||||||
if (display == WaveTrack::Waveform) {
|
|
||||||
const bool dB = !pwavetrack->GetWaveformSettings().isLinear();
|
|
||||||
const double dBRange = pwavetrack->GetWaveformSettings().dBRange;
|
|
||||||
bool needUpdate;
|
|
||||||
|
|
||||||
// AS: Then forward our mouse event to the envelope.
|
|
||||||
// It'll recalculate and then tell us whether or not to redraw.
|
|
||||||
wxRect envRect = mCapturedRect;
|
|
||||||
float zoomMin, zoomMax;
|
|
||||||
pwavetrack->GetDisplayBounds(&zoomMin, &zoomMax);
|
|
||||||
if (event.ButtonDown()) {
|
|
||||||
mEnvelopeEditor = std::make_unique<EnvelopeEditor>(*penvelope, true);
|
|
||||||
mEnvelopeEditorRight.reset();
|
|
||||||
}
|
|
||||||
needUpdate =
|
|
||||||
mEnvelopeEditor &&
|
|
||||||
mEnvelopeEditor->MouseEvent(
|
|
||||||
event, envRect,
|
|
||||||
*mViewInfo,
|
|
||||||
dB, dBRange, zoomMin, zoomMax);
|
|
||||||
|
|
||||||
// If this track is linked to another track, make the identical
|
|
||||||
// change to the linked envelope:
|
|
||||||
// Assume linked track is wave or null
|
|
||||||
const auto link = static_cast<WaveTrack *>(mCapturedTrack->GetLink());
|
|
||||||
if (link) {
|
|
||||||
if (event.ButtonDown()) {
|
|
||||||
Envelope *e2 = link->GetEnvelopeAtX(event.GetX());
|
|
||||||
if (e2)
|
|
||||||
mEnvelopeEditorRight = std::make_unique<EnvelopeEditor>(*e2, true);
|
|
||||||
else {
|
|
||||||
// There isn't necessarily an envelope there; no guarantee a
|
|
||||||
// linked track has the same WaveClip structure...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mEnvelopeEditorRight) {
|
|
||||||
wxRect envRect = mCapturedRect;
|
|
||||||
float zoomMin, zoomMax;
|
|
||||||
pwavetrack->GetDisplayBounds(&zoomMin, &zoomMax);
|
|
||||||
needUpdate|= mEnvelopeEditorRight->MouseEvent(event, envRect,
|
|
||||||
*mViewInfo,
|
|
||||||
dB, dBRange,
|
|
||||||
zoomMin, zoomMax);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needUpdate) {
|
|
||||||
RefreshTrack(mCapturedTrack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// The Envelope class actually handles things at the mouse
|
|
||||||
/// event level, so we have to forward the events over. Envelope
|
|
||||||
/// will then tell us whether or not we need to redraw.
|
|
||||||
|
|
||||||
// AS: I'm not sure why we can't let the Envelope take care of
|
|
||||||
// redrawing itself. ?
|
|
||||||
|
|
||||||
void TrackPanel::ForwardEventToEnvelope(wxMouseEvent & event)
|
|
||||||
{
|
|
||||||
if (mCapturedTrack && mCapturedTrack->GetKind() == Track::Time)
|
|
||||||
{
|
|
||||||
ForwardEventToTimeTrackEnvelope( event );
|
|
||||||
}
|
|
||||||
else if (mCapturedTrack && mCapturedTrack->GetKind() == Track::Wave)
|
|
||||||
{
|
|
||||||
ForwardEventToWaveTrackEnvelope( event );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Determines if drag zooming is active
|
/// Determines if drag zooming is active
|
||||||
bool TrackPanel::IsDragZooming(int zoomStart, int zoomEnd)
|
bool TrackPanel::IsDragZooming(int zoomStart, int zoomEnd)
|
||||||
{
|
{
|
||||||
@ -5700,8 +5525,6 @@ void TrackPanel::HandleTrackSpecificMouseEvent(wxMouseEvent & event)
|
|||||||
auto &pCell = foundCell.pCell;
|
auto &pCell = foundCell.pCell;
|
||||||
auto &rect = foundCell.rect;
|
auto &rect = foundCell.rect;
|
||||||
|
|
||||||
bool unsafe = IsUnsafe();
|
|
||||||
|
|
||||||
//call HandleResize if I'm over the border area
|
//call HandleResize if I'm over the border area
|
||||||
// (Add margin back to bottom of the rectangle)
|
// (Add margin back to bottom of the rectangle)
|
||||||
if (event.LeftDown() &&
|
if (event.LeftDown() &&
|
||||||
@ -5804,18 +5627,13 @@ void TrackPanel::HandleTrackSpecificMouseEvent(wxMouseEvent & event)
|
|||||||
case selectTool:
|
case selectTool:
|
||||||
HandleSelect(event);
|
HandleSelect(event);
|
||||||
break;
|
break;
|
||||||
case envelopeTool:
|
|
||||||
if (!unsafe)
|
|
||||||
HandleEnvelope(event);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((event.Moving() || event.LeftUp()) &&
|
if ((event.Moving() || event.LeftUp()) &&
|
||||||
(mMouseCapture == IsUncaptured ))
|
(mMouseCapture == IsUncaptured ))
|
||||||
// (mMouseCapture != IsSelecting ) &&
|
// (mMouseCapture != IsSelecting )
|
||||||
// (mMouseCapture != IsEnveloping)
|
|
||||||
{
|
{
|
||||||
HandleCursor(event);
|
HandleCursor(event);
|
||||||
}
|
}
|
||||||
@ -5857,9 +5675,7 @@ int TrackPanel::DetermineToolToUse( ToolsToolBar * pTtb, const wxMouseEvent & ev
|
|||||||
int trackKind = pTrack->GetKind();
|
int trackKind = pTrack->GetKind();
|
||||||
currentTool = selectTool; // the default.
|
currentTool = selectTool; // the default.
|
||||||
|
|
||||||
if (trackKind == Track::Time){
|
if( trackKind == Track::Label ){
|
||||||
currentTool = envelopeTool;
|
|
||||||
} else if( trackKind == Track::Label ){
|
|
||||||
currentTool = selectTool;
|
currentTool = selectTool;
|
||||||
} else if( trackKind != Track::Wave) {
|
} else if( trackKind != Track::Wave) {
|
||||||
currentTool = selectTool;
|
currentTool = selectTool;
|
||||||
@ -5868,8 +5684,6 @@ int TrackPanel::DetermineToolToUse( ToolsToolBar * pTtb, const wxMouseEvent & ev
|
|||||||
// From here on the order in which we hit test determines
|
// From here on the order in which we hit test determines
|
||||||
// which tool takes priority in the rare cases where it
|
// which tool takes priority in the rare cases where it
|
||||||
// could be more than one.
|
// could be more than one.
|
||||||
} else if( HitTestEnvelope( pTrack, rect, event ) ) {
|
|
||||||
currentTool = envelopeTool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Use the false argument since in multimode we don't
|
//Use the false argument since in multimode we don't
|
||||||
@ -5910,75 +5724,6 @@ auto TrackPanel::HitTestStretch
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/// method that tells us if the mouse event landed on an
|
|
||||||
/// envelope boundary.
|
|
||||||
bool TrackPanel::HitTestEnvelope(Track *track, const wxRect &rect, const wxMouseEvent & event)
|
|
||||||
{
|
|
||||||
wxASSERT(track);
|
|
||||||
if( track->GetKind() != Track::Wave )
|
|
||||||
return false;
|
|
||||||
WaveTrack *wavetrack = (WaveTrack *)track;
|
|
||||||
Envelope *envelope = wavetrack->GetEnvelopeAtX(event.GetX());
|
|
||||||
|
|
||||||
if (!envelope)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const int displayType = wavetrack->GetDisplay();
|
|
||||||
// Not an envelope hit, unless we're using a type of wavetrack display
|
|
||||||
// suitable for envelopes operations, ie one of the Wave displays.
|
|
||||||
if ( displayType != WaveTrack::Waveform)
|
|
||||||
return false; // No envelope, not a hit, so return.
|
|
||||||
|
|
||||||
// Get envelope point, range 0.0 to 1.0
|
|
||||||
const bool dB = !wavetrack->GetWaveformSettings().isLinear();
|
|
||||||
|
|
||||||
const double envValue = envelope->GetValue(mViewInfo->PositionToTime(event.m_x, rect.x));
|
|
||||||
|
|
||||||
float zoomMin, zoomMax;
|
|
||||||
wavetrack->GetDisplayBounds(&zoomMin, &zoomMax);
|
|
||||||
|
|
||||||
const double dBRange = wavetrack->GetWaveformSettings().dBRange;
|
|
||||||
|
|
||||||
// Get y position of envelope point.
|
|
||||||
int yValue = GetWaveYPos( envValue,
|
|
||||||
zoomMin, zoomMax,
|
|
||||||
rect.height, dB, true, dBRange, false) + rect.y;
|
|
||||||
|
|
||||||
// Get y position of center line
|
|
||||||
int ctr = GetWaveYPos( 0.0,
|
|
||||||
zoomMin, zoomMax,
|
|
||||||
rect.height, dB, true, dBRange, false) + rect.y;
|
|
||||||
|
|
||||||
// Get y distance of mouse from center line (in pixels).
|
|
||||||
int yMouse = abs(ctr - event.m_y);
|
|
||||||
// Get y distance of envelope from center line (in pixels)
|
|
||||||
yValue = abs(ctr-yValue);
|
|
||||||
|
|
||||||
// JKC: It happens that the envelope is actually drawn offset from its
|
|
||||||
// 'true' position (it is 3 pixels wide). yMisalign is really a fudge
|
|
||||||
// factor to allow us to hit it exactly, but I wouldn't dream of
|
|
||||||
// calling it yFudgeFactor :)
|
|
||||||
const int yMisalign = 2;
|
|
||||||
// Perhaps yTolerance should be put into preferences?
|
|
||||||
const int yTolerance = 5; // how far from envelope we may be and count as a hit.
|
|
||||||
int distance;
|
|
||||||
|
|
||||||
// For amplification using the envelope we introduced the idea of contours.
|
|
||||||
// The contours have the same shape as the envelope, which may be partially off-screen.
|
|
||||||
// The contours are closer in to the center line.
|
|
||||||
int ContourSpacing = (int) (rect.height / (2* (zoomMax-zoomMin)));
|
|
||||||
const int MaxContours = 2;
|
|
||||||
|
|
||||||
// Adding ContourSpacing/2 selects a region either side of the contour.
|
|
||||||
int yDisplace = yValue - yMisalign - yMouse + ContourSpacing/2;
|
|
||||||
if (yDisplace > (MaxContours * ContourSpacing))
|
|
||||||
return false;
|
|
||||||
// Subtracting the ContourSpacing/2 we added earlier ensures distance is centred on the contour.
|
|
||||||
distance = abs( ( yDisplace % ContourSpacing ) - ContourSpacing/2);
|
|
||||||
return( distance < yTolerance );
|
|
||||||
}
|
|
||||||
|
|
||||||
double TrackPanel::GetMostRecentXPos()
|
double TrackPanel::GetMostRecentXPos()
|
||||||
{
|
{
|
||||||
return mViewInfo->PositionToTime(mMouseMostRecentX, GetLabelWidth());
|
return mViewInfo->PositionToTime(mMouseMostRecentX, GetLabelWidth());
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
class wxMenu;
|
class wxMenu;
|
||||||
class wxRect;
|
class wxRect;
|
||||||
|
|
||||||
class EnvelopeEditor;
|
|
||||||
class LabelTrack;
|
class LabelTrack;
|
||||||
class SpectrumAnalyst;
|
class SpectrumAnalyst;
|
||||||
class Track;
|
class Track;
|
||||||
@ -52,7 +51,6 @@ class ViewInfo;
|
|||||||
class NoteTrack;
|
class NoteTrack;
|
||||||
class WaveTrack;
|
class WaveTrack;
|
||||||
class WaveClip;
|
class WaveClip;
|
||||||
class Envelope;
|
|
||||||
class UIHandle;
|
class UIHandle;
|
||||||
|
|
||||||
// Declared elsewhere, to reduce compilation dependencies
|
// Declared elsewhere, to reduce compilation dependencies
|
||||||
@ -375,7 +373,6 @@ class AUDACITY_DLL_API TrackPanel final : public OverlayPanel {
|
|||||||
|
|
||||||
// Working out where to dispatch the event to.
|
// Working out where to dispatch the event to.
|
||||||
virtual int DetermineToolToUse( ToolsToolBar * pTtb, const wxMouseEvent & event);
|
virtual int DetermineToolToUse( ToolsToolBar * pTtb, const wxMouseEvent & event);
|
||||||
virtual bool HitTestEnvelope(Track *track, const wxRect &rect, const wxMouseEvent & event);
|
|
||||||
#ifdef USE_MIDI
|
#ifdef USE_MIDI
|
||||||
// data for NoteTrack interactive stretch operations:
|
// data for NoteTrack interactive stretch operations:
|
||||||
// Stretching applies to a selected region after quantizing the
|
// Stretching applies to a selected region after quantizing the
|
||||||
@ -470,12 +467,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void MaySetOnDemandTip( Track * t, wxString &tip );
|
virtual void MaySetOnDemandTip( Track * t, wxString &tip );
|
||||||
|
|
||||||
// AS: Envelope editing handlers
|
|
||||||
virtual void HandleEnvelope(wxMouseEvent & event);
|
|
||||||
virtual void ForwardEventToTimeTrackEnvelope(wxMouseEvent & event);
|
|
||||||
virtual void ForwardEventToWaveTrackEnvelope(wxMouseEvent & event);
|
|
||||||
virtual void ForwardEventToEnvelope(wxMouseEvent &event);
|
|
||||||
|
|
||||||
static bool IsDragZooming(int zoomStart, int zoomEnd);
|
static bool IsDragZooming(int zoomStart, int zoomEnd);
|
||||||
virtual bool IsDragZooming() { return IsDragZooming(mZoomStart, mZoomEnd); }
|
virtual bool IsDragZooming() { return IsDragZooming(mZoomStart, mZoomEnd); }
|
||||||
|
|
||||||
@ -728,7 +719,6 @@ protected:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Track *mCapturedTrack;
|
Track *mCapturedTrack;
|
||||||
Envelope *mCapturedEnvelope;
|
|
||||||
WaveTrackLocation mCapturedTrackLocation;
|
WaveTrackLocation mCapturedTrackLocation;
|
||||||
wxRect mCapturedTrackLocationRect;
|
wxRect mCapturedTrackLocationRect;
|
||||||
wxRect mCapturedRect;
|
wxRect mCapturedRect;
|
||||||
@ -821,7 +811,6 @@ public:
|
|||||||
IsResizingBetweenLinkedTracks,
|
IsResizingBetweenLinkedTracks,
|
||||||
IsResizingBelowLinkedTracks,
|
IsResizingBelowLinkedTracks,
|
||||||
IsRearranging,
|
IsRearranging,
|
||||||
IsEnveloping,
|
|
||||||
IsMuting,
|
IsMuting,
|
||||||
IsSoloing,
|
IsSoloing,
|
||||||
IsGainSliding,
|
IsGainSliding,
|
||||||
@ -892,9 +881,6 @@ protected:
|
|||||||
// Keeps track of extra fractional vertical scroll steps
|
// Keeps track of extra fractional vertical scroll steps
|
||||||
double mVertScrollRemainder;
|
double mVertScrollRemainder;
|
||||||
|
|
||||||
std::unique_ptr<EnvelopeEditor> mEnvelopeEditor;
|
|
||||||
std::unique_ptr<EnvelopeEditor> mEnvelopeEditorRight;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// The screenshot class needs to access internals
|
// The screenshot class needs to access internals
|
||||||
|
@ -87,6 +87,7 @@ ToolsToolBar::ToolsToolBar()
|
|||||||
|
|
||||||
mMessageOfTool[selectTool] = _("Click and drag to select audio");
|
mMessageOfTool[selectTool] = _("Click and drag to select audio");
|
||||||
|
|
||||||
|
// TODO: this message isn't appropriate for time track
|
||||||
mMessageOfTool[envelopeTool] = _("Click and drag to edit the amplitude envelope");
|
mMessageOfTool[envelopeTool] = _("Click and drag to edit the amplitude envelope");
|
||||||
|
|
||||||
// TODO: message should also mention the brush. Describing the modifier key
|
// TODO: message should also mention the brush. Describing the modifier key
|
||||||
|
@ -17,6 +17,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
#include "../../../../TrackPanelMouseEvent.h"
|
#include "../../../../TrackPanelMouseEvent.h"
|
||||||
#include "../../../../toolbars/ToolsToolBar.h"
|
#include "../../../../toolbars/ToolsToolBar.h"
|
||||||
|
|
||||||
|
#include "../../../ui/EnvelopeHandle.h"
|
||||||
#include "SampleHandle.h"
|
#include "SampleHandle.h"
|
||||||
#include "../../../ui/TimeShiftHandle.h"
|
#include "../../../ui/TimeShiftHandle.h"
|
||||||
|
|
||||||
@ -34,6 +35,10 @@ HitTestResult WaveTrack::HitTest
|
|||||||
int currentTool = -1;
|
int currentTool = -1;
|
||||||
if (event.event.CmdDown())
|
if (event.event.CmdDown())
|
||||||
result = TimeShiftHandle::HitAnywhere(pProject);
|
result = TimeShiftHandle::HitAnywhere(pProject);
|
||||||
|
else if (NULL !=
|
||||||
|
(result = EnvelopeHandle::WaveTrackHitTest(event.event, event.rect, pProject, this))
|
||||||
|
.preview.cursor)
|
||||||
|
;
|
||||||
else if (NULL != (result =
|
else if (NULL != (result =
|
||||||
TimeShiftHandle::HitTest(event.event, event.rect, pProject)).preview.cursor)
|
TimeShiftHandle::HitTest(event.event, event.rect, pProject)).preview.cursor)
|
||||||
;
|
;
|
||||||
|
@ -13,12 +13,25 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
#include "TimeTrackVRulerControls.h"
|
#include "TimeTrackVRulerControls.h"
|
||||||
|
|
||||||
#include "../../../HitTestResult.h"
|
#include "../../../HitTestResult.h"
|
||||||
|
#include "../../../Project.h"
|
||||||
|
#include "../../../toolbars/ToolsToolBar.h"
|
||||||
|
|
||||||
|
#include "../../ui/EnvelopeHandle.h"
|
||||||
|
|
||||||
HitTestResult TimeTrack::HitTest
|
HitTestResult TimeTrack::HitTest
|
||||||
(const TrackPanelMouseEvent &event,
|
(const TrackPanelMouseEvent &event,
|
||||||
const AudacityProject *pProject)
|
const AudacityProject *pProject)
|
||||||
{
|
{
|
||||||
return Track::HitTest(event, pProject);
|
HitTestResult result = Track::HitTest(event, pProject);
|
||||||
|
if (result.preview.cursor)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
const ToolsToolBar *const pTtb = pProject->GetToolsToolBar();
|
||||||
|
if (pTtb->IsDown(multiTool))
|
||||||
|
// No hit test --unconditional availability.
|
||||||
|
result = EnvelopeHandle::HitAnywhere(pProject);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackControls *TimeTrack::GetControls()
|
TrackControls *TimeTrack::GetControls()
|
||||||
|
286
src/tracks/ui/EnvelopeHandle.cpp
Normal file
286
src/tracks/ui/EnvelopeHandle.cpp
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
/**********************************************************************
|
||||||
|
|
||||||
|
Audacity: A Digital Audio Editor
|
||||||
|
|
||||||
|
EnvelopeHandle.cpp
|
||||||
|
|
||||||
|
Paul Licameli split from TrackPanel.cpp
|
||||||
|
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
#include "../../Audacity.h"
|
||||||
|
#include "EnvelopeHandle.h"
|
||||||
|
|
||||||
|
#include "../../MemoryX.h"
|
||||||
|
|
||||||
|
#include "../../Envelope.h"
|
||||||
|
#include "../../HitTestResult.h"
|
||||||
|
#include "../../prefs/WaveformSettings.h"
|
||||||
|
#include "../../Project.h"
|
||||||
|
#include "../../RefreshCode.h"
|
||||||
|
#include "../../toolbars/ToolsToolBar.h"
|
||||||
|
#include "../../TimeTrack.h"
|
||||||
|
#include "../../TrackArtist.h"
|
||||||
|
#include "../../TrackPanelMouseEvent.h"
|
||||||
|
#include "../../ViewInfo.h"
|
||||||
|
#include "../../WaveTrack.h"
|
||||||
|
#include "../../../images/Cursors.h"
|
||||||
|
|
||||||
|
EnvelopeHandle::EnvelopeHandle()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EnvelopeHandle &EnvelopeHandle::Instance()
|
||||||
|
{
|
||||||
|
static EnvelopeHandle instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
HitTestPreview EnvelopeHandle::HitPreview(const AudacityProject *pProject, bool unsafe)
|
||||||
|
{
|
||||||
|
static auto disabledCursor =
|
||||||
|
::MakeCursor(wxCURSOR_NO_ENTRY, DisabledCursorXpm, 16, 16);
|
||||||
|
static auto envelopeCursor =
|
||||||
|
::MakeCursor(wxCURSOR_ARROW, EnvCursorXpm, 16, 16);
|
||||||
|
const ToolsToolBar *const ttb = pProject->GetToolsToolBar();
|
||||||
|
return {
|
||||||
|
ttb->GetMessageForTool(envelopeTool),
|
||||||
|
(unsafe
|
||||||
|
? &*disabledCursor
|
||||||
|
: &*envelopeCursor)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
HitTestResult EnvelopeHandle::HitAnywhere(const AudacityProject *pProject)
|
||||||
|
{
|
||||||
|
const bool unsafe = pProject->IsAudioActive();
|
||||||
|
return {
|
||||||
|
HitPreview(pProject, unsafe),
|
||||||
|
(unsafe
|
||||||
|
? NULL
|
||||||
|
: &Instance())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
HitTestResult EnvelopeHandle::WaveTrackHitTest
|
||||||
|
(const wxMouseEvent &event, const wxRect &rect,
|
||||||
|
const AudacityProject *pProject, Cell *pCell)
|
||||||
|
{
|
||||||
|
const ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||||
|
Track *const pTrack = static_cast<Track*>(pCell);
|
||||||
|
|
||||||
|
/// method that tells us if the mouse event landed on an
|
||||||
|
/// envelope boundary.
|
||||||
|
if (pTrack->GetKind() != Track::Wave)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
WaveTrack *const wavetrack = static_cast<WaveTrack*>(pTrack);
|
||||||
|
Envelope *const envelope = wavetrack->GetEnvelopeAtX(event.GetX());
|
||||||
|
|
||||||
|
if (!envelope)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const int displayType = wavetrack->GetDisplay();
|
||||||
|
// Not an envelope hit, unless we're using a type of wavetrack display
|
||||||
|
// suitable for envelopes operations, ie one of the Wave displays.
|
||||||
|
if (displayType != WaveTrack::Waveform)
|
||||||
|
return {}; // No envelope, not a hit, so return.
|
||||||
|
|
||||||
|
// Get envelope point, range 0.0 to 1.0
|
||||||
|
const bool dB = !wavetrack->GetWaveformSettings().isLinear();
|
||||||
|
const double envValue =
|
||||||
|
envelope->GetValue(viewInfo.PositionToTime(event.m_x, rect.x));
|
||||||
|
|
||||||
|
float zoomMin, zoomMax;
|
||||||
|
wavetrack->GetDisplayBounds(&zoomMin, &zoomMax);
|
||||||
|
|
||||||
|
const float dBRange = wavetrack->GetWaveformSettings().dBRange;
|
||||||
|
|
||||||
|
// Get y position of envelope point.
|
||||||
|
int yValue = GetWaveYPos(envValue,
|
||||||
|
zoomMin, zoomMax,
|
||||||
|
rect.height, dB, true, dBRange, false) + rect.y;
|
||||||
|
|
||||||
|
// Get y position of center line
|
||||||
|
int ctr = GetWaveYPos(0.0,
|
||||||
|
zoomMin, zoomMax,
|
||||||
|
rect.height, dB, true, dBRange, false) + rect.y;
|
||||||
|
|
||||||
|
// Get y distance of mouse from center line (in pixels).
|
||||||
|
int yMouse = abs(ctr - event.m_y);
|
||||||
|
// Get y distance of envelope from center line (in pixels)
|
||||||
|
yValue = abs(ctr - yValue);
|
||||||
|
|
||||||
|
// JKC: It happens that the envelope is actually drawn offset from its
|
||||||
|
// 'true' position (it is 3 pixels wide). yMisalign is really a fudge
|
||||||
|
// factor to allow us to hit it exactly, but I wouldn't dream of
|
||||||
|
// calling it yFudgeFactor :)
|
||||||
|
const int yMisalign = 2;
|
||||||
|
// Perhaps yTolerance should be put into preferences?
|
||||||
|
const int yTolerance = 5; // how far from envelope we may be and count as a hit.
|
||||||
|
int distance;
|
||||||
|
|
||||||
|
// For amplification using the envelope we introduced the idea of contours.
|
||||||
|
// The contours have the same shape as the envelope, which may be partially off-screen.
|
||||||
|
// The contours are closer in to the center line.
|
||||||
|
int ContourSpacing = (int)(rect.height / (2 * (zoomMax - zoomMin)));
|
||||||
|
const int MaxContours = 2;
|
||||||
|
|
||||||
|
// Adding ContourSpacing/2 selects a region either side of the contour.
|
||||||
|
int yDisplace = yValue - yMisalign - yMouse + ContourSpacing / 2;
|
||||||
|
if (yDisplace > (MaxContours * ContourSpacing))
|
||||||
|
return {};
|
||||||
|
// Subtracting the ContourSpacing/2 we added earlier ensures distance is centred on the contour.
|
||||||
|
distance = abs((yDisplace % ContourSpacing) - ContourSpacing / 2);
|
||||||
|
if (distance >= yTolerance)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return HitAnywhere(pProject);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnvelopeHandle::~EnvelopeHandle()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
UIHandle::Result EnvelopeHandle::Click
|
||||||
|
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
||||||
|
{
|
||||||
|
const wxMouseEvent &event = evt.event;
|
||||||
|
const ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||||
|
Track *const pTrack = static_cast<Track*>(evt.pCell);
|
||||||
|
|
||||||
|
using namespace RefreshCode;
|
||||||
|
const bool unsafe = pProject->IsAudioActive();
|
||||||
|
if (unsafe)
|
||||||
|
return Cancelled;
|
||||||
|
|
||||||
|
if (pTrack->GetKind() == Track::Wave) {
|
||||||
|
WaveTrack *const wt = static_cast<WaveTrack*>(pTrack);
|
||||||
|
if (wt->GetDisplay() != WaveTrack::Waveform)
|
||||||
|
return Cancelled;
|
||||||
|
|
||||||
|
auto clickedEnvelope =
|
||||||
|
wt->GetEnvelopeAtX(event.GetX());
|
||||||
|
if (!clickedEnvelope)
|
||||||
|
return Cancelled;
|
||||||
|
|
||||||
|
mLog = !wt->GetWaveformSettings().isLinear();
|
||||||
|
wt->GetDisplayBounds(&mLower, &mUpper);
|
||||||
|
mdBRange = wt->GetWaveformSettings().dBRange;
|
||||||
|
mEnvelopeEditor =
|
||||||
|
std::make_unique< EnvelopeEditor >( *clickedEnvelope, true );
|
||||||
|
mEnvelopeEditorRight.reset();
|
||||||
|
|
||||||
|
// Assume linked track is wave or null
|
||||||
|
auto partner = static_cast<WaveTrack*>(wt->GetLink());
|
||||||
|
if (partner)
|
||||||
|
{
|
||||||
|
clickedEnvelope = partner->GetEnvelopeAtX(event.GetX());
|
||||||
|
if (clickedEnvelope)
|
||||||
|
mEnvelopeEditorRight =
|
||||||
|
std::make_unique< EnvelopeEditor >( *clickedEnvelope, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pTrack->GetKind() == Track::Time)
|
||||||
|
{
|
||||||
|
TimeTrack *const tt = static_cast<TimeTrack*>(pTrack);
|
||||||
|
auto clickedEnvelope = tt->GetEnvelope();
|
||||||
|
if (!clickedEnvelope)
|
||||||
|
return Cancelled;
|
||||||
|
mLog = tt->GetDisplayLog();
|
||||||
|
mLower = tt->GetRangeLower(), mUpper = tt->GetRangeUpper();
|
||||||
|
if (mLog) {
|
||||||
|
// MB: silly way to undo the work of GetWaveYPos while still getting a logarithmic scale
|
||||||
|
mdBRange = viewInfo.dBr;
|
||||||
|
mLower = LINEAR_TO_DB(std::max(1.0e-7, double(mLower))) / mdBRange + 1.0;
|
||||||
|
mUpper = LINEAR_TO_DB(std::max(1.0e-7, double(mUpper))) / mdBRange + 1.0;
|
||||||
|
}
|
||||||
|
mEnvelopeEditor =
|
||||||
|
std::make_unique< EnvelopeEditor >( *clickedEnvelope, false );
|
||||||
|
mEnvelopeEditorRight.reset();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Cancelled;
|
||||||
|
|
||||||
|
mRect = evt.rect;
|
||||||
|
|
||||||
|
const bool needUpdate = ForwardEventToEnvelopes(event, viewInfo);
|
||||||
|
return needUpdate ? RefreshCell : RefreshNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIHandle::Result EnvelopeHandle::Drag
|
||||||
|
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
||||||
|
{
|
||||||
|
using namespace RefreshCode;
|
||||||
|
const wxMouseEvent &event = evt.event;
|
||||||
|
const ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||||
|
const bool unsafe = pProject->IsAudioActive();
|
||||||
|
if (unsafe) {
|
||||||
|
this->Cancel(pProject);
|
||||||
|
return RefreshCell | Cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool needUpdate = ForwardEventToEnvelopes(event, viewInfo);
|
||||||
|
return needUpdate ? RefreshCell : RefreshNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
HitTestPreview EnvelopeHandle::Preview
|
||||||
|
(const TrackPanelMouseEvent &, const AudacityProject *pProject)
|
||||||
|
{
|
||||||
|
return HitPreview(pProject, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
UIHandle::Result EnvelopeHandle::Release
|
||||||
|
(const TrackPanelMouseEvent &evt, AudacityProject *pProject,
|
||||||
|
wxWindow *)
|
||||||
|
{
|
||||||
|
const wxMouseEvent &event = evt.event;
|
||||||
|
const ViewInfo &viewInfo = pProject->GetViewInfo();
|
||||||
|
const bool unsafe = pProject->IsAudioActive();
|
||||||
|
if (unsafe)
|
||||||
|
return this->Cancel(pProject);
|
||||||
|
|
||||||
|
const bool needUpdate = ForwardEventToEnvelopes(event, viewInfo);
|
||||||
|
|
||||||
|
pProject->PushState(
|
||||||
|
/* i18n-hint: (verb) Audacity has just adjusted the envelope .*/
|
||||||
|
_("Adjusted envelope."),
|
||||||
|
/* i18n-hint: The envelope is a curve that controls the audio loudness.*/
|
||||||
|
_("Envelope")
|
||||||
|
);
|
||||||
|
|
||||||
|
mEnvelopeEditor.reset();
|
||||||
|
mEnvelopeEditorRight.reset();
|
||||||
|
|
||||||
|
using namespace RefreshCode;
|
||||||
|
return needUpdate ? RefreshCell : RefreshNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIHandle::Result EnvelopeHandle::Cancel(AudacityProject *pProject)
|
||||||
|
{
|
||||||
|
pProject->RollbackState();
|
||||||
|
mEnvelopeEditor.reset();
|
||||||
|
mEnvelopeEditorRight.reset();
|
||||||
|
return RefreshCode::RefreshCell;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EnvelopeHandle::ForwardEventToEnvelopes
|
||||||
|
(const wxMouseEvent &event, const ViewInfo &viewInfo)
|
||||||
|
{
|
||||||
|
/// The Envelope class actually handles things at the mouse
|
||||||
|
/// event level, so we have to forward the events over. Envelope
|
||||||
|
/// will then tell us whether or not we need to redraw.
|
||||||
|
|
||||||
|
// AS: I'm not sure why we can't let the Envelope take care of
|
||||||
|
// redrawing itself. ?
|
||||||
|
bool needUpdate =
|
||||||
|
mEnvelopeEditor->MouseEvent(
|
||||||
|
event, mRect, viewInfo, mLog, mdBRange, mLower, mUpper);
|
||||||
|
|
||||||
|
if (mEnvelopeEditorRight)
|
||||||
|
needUpdate |=
|
||||||
|
mEnvelopeEditorRight->MouseEvent(
|
||||||
|
event, mRect, viewInfo, mLog, mdBRange, mLower, mUpper);
|
||||||
|
|
||||||
|
return needUpdate;
|
||||||
|
}
|
72
src/tracks/ui/EnvelopeHandle.h
Normal file
72
src/tracks/ui/EnvelopeHandle.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/**********************************************************************
|
||||||
|
|
||||||
|
Audacity: A Digital Audio Editor
|
||||||
|
|
||||||
|
EnvelopeHandle.h
|
||||||
|
|
||||||
|
Paul Licameli split from TrackPanel.cpp
|
||||||
|
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
#ifndef __AUDACITY_ENVELOPE_HANDLE__
|
||||||
|
#define __AUDACITY_ENVELOPE_HANDLE__
|
||||||
|
|
||||||
|
#include "../../UIHandle.h"
|
||||||
|
#include "../../MemoryX.h"
|
||||||
|
|
||||||
|
class wxMouseEvent;
|
||||||
|
#include <wx/gdicmn.h>
|
||||||
|
|
||||||
|
class EnvelopeEditor;
|
||||||
|
struct HitTestResult;
|
||||||
|
class ViewInfo;
|
||||||
|
class WaveTrack;
|
||||||
|
|
||||||
|
class EnvelopeHandle final : public UIHandle
|
||||||
|
{
|
||||||
|
EnvelopeHandle();
|
||||||
|
EnvelopeHandle(const EnvelopeHandle&) = delete;
|
||||||
|
EnvelopeHandle &operator=(const EnvelopeHandle&) = delete;
|
||||||
|
static EnvelopeHandle& Instance();
|
||||||
|
static HitTestPreview HitPreview(const AudacityProject *pProject, bool unsafe);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static HitTestResult HitAnywhere(const AudacityProject *pProject);
|
||||||
|
static HitTestResult WaveTrackHitTest
|
||||||
|
(const wxMouseEvent &event, const wxRect &rect,
|
||||||
|
const AudacityProject *pProject, Cell *pCell);
|
||||||
|
|
||||||
|
virtual ~EnvelopeHandle();
|
||||||
|
|
||||||
|
Result Click
|
||||||
|
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
|
||||||
|
|
||||||
|
Result Drag
|
||||||
|
(const TrackPanelMouseEvent &event, AudacityProject *pProject) override;
|
||||||
|
|
||||||
|
HitTestPreview Preview
|
||||||
|
(const TrackPanelMouseEvent &event, const AudacityProject *pProject)
|
||||||
|
override;
|
||||||
|
|
||||||
|
Result Release
|
||||||
|
(const TrackPanelMouseEvent &event, AudacityProject *pProject,
|
||||||
|
wxWindow *pParent) override;
|
||||||
|
|
||||||
|
Result Cancel(AudacityProject *pProject) override;
|
||||||
|
|
||||||
|
bool StopsOnKeystroke() override { return true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool ForwardEventToEnvelopes
|
||||||
|
(const wxMouseEvent &event, const ViewInfo &viewInfo);
|
||||||
|
|
||||||
|
wxRect mRect{};
|
||||||
|
bool mLog{};
|
||||||
|
float mLower{}, mUpper{};
|
||||||
|
double mdBRange{};
|
||||||
|
|
||||||
|
std::unique_ptr<EnvelopeEditor> mEnvelopeEditor;
|
||||||
|
std::unique_ptr<EnvelopeEditor> mEnvelopeEditorRight;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -17,6 +17,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
#include "../../Project.h"
|
#include "../../Project.h"
|
||||||
#include "../../toolbars/ToolsToolBar.h"
|
#include "../../toolbars/ToolsToolBar.h"
|
||||||
|
|
||||||
|
#include "EnvelopeHandle.h"
|
||||||
#include "../playabletrack/wavetrack/ui/SampleHandle.h"
|
#include "../playabletrack/wavetrack/ui/SampleHandle.h"
|
||||||
#include "ZoomHandle.h"
|
#include "ZoomHandle.h"
|
||||||
#include "TimeShiftHandle.h"
|
#include "TimeShiftHandle.h"
|
||||||
@ -30,6 +31,9 @@ HitTestResult Track::HitTest
|
|||||||
const bool isMultiTool = pTtb->IsDown(multiTool);
|
const bool isMultiTool = pTtb->IsDown(multiTool);
|
||||||
if (!isMultiTool) {
|
if (!isMultiTool) {
|
||||||
switch (pTtb->GetCurrentTool()) {
|
switch (pTtb->GetCurrentTool()) {
|
||||||
|
case envelopeTool:
|
||||||
|
// Pass "false" for unsafe -- let the tool decide to cancel itself
|
||||||
|
return EnvelopeHandle::HitAnywhere(pProject);
|
||||||
case drawTool:
|
case drawTool:
|
||||||
return SampleHandle::HitAnywhere(event.event, pProject);
|
return SampleHandle::HitAnywhere(event.event, pProject);
|
||||||
case zoomTool:
|
case zoomTool:
|
||||||
@ -38,7 +42,6 @@ HitTestResult Track::HitTest
|
|||||||
return TimeShiftHandle::HitAnywhere(pProject);
|
return TimeShiftHandle::HitAnywhere(pProject);
|
||||||
|
|
||||||
case selectTool:
|
case selectTool:
|
||||||
case envelopeTool:
|
|
||||||
default:
|
default:
|
||||||
// cases not yet implemented
|
// cases not yet implemented
|
||||||
// fallthru
|
// fallthru
|
||||||
|
@ -239,6 +239,7 @@
|
|||||||
<ClCompile Include="..\..\..\src\tracks\timetrack\ui\TimeTrackVRulerControls.cpp" />
|
<ClCompile Include="..\..\..\src\tracks\timetrack\ui\TimeTrackVRulerControls.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\tracks\ui\CommonTrackPanelCell.cpp" />
|
<ClCompile Include="..\..\..\src\tracks\ui\CommonTrackPanelCell.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\tracks\ui\EditCursorOverlay.cpp" />
|
<ClCompile Include="..\..\..\src\tracks\ui\EditCursorOverlay.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\src\tracks\ui\EnvelopeHandle.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\tracks\ui\PlayIndicatorOverlay.cpp" />
|
<ClCompile Include="..\..\..\src\tracks\ui\PlayIndicatorOverlay.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\tracks\ui\Scrubbing.cpp" />
|
<ClCompile Include="..\..\..\src\tracks\ui\Scrubbing.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\tracks\ui\TimeShiftHandle.cpp" />
|
<ClCompile Include="..\..\..\src\tracks\ui\TimeShiftHandle.cpp" />
|
||||||
@ -500,6 +501,7 @@
|
|||||||
<ClInclude Include="..\..\..\src\tracks\labeltrack\ui\LabelTrackVRulerControls.h" />
|
<ClInclude Include="..\..\..\src\tracks\labeltrack\ui\LabelTrackVRulerControls.h" />
|
||||||
<ClInclude Include="..\..\..\src\tracks\timetrack\ui\TimeTrackControls.h" />
|
<ClInclude Include="..\..\..\src\tracks\timetrack\ui\TimeTrackControls.h" />
|
||||||
<ClInclude Include="..\..\..\src\tracks\ui\EditCursorOverlay.h" />
|
<ClInclude Include="..\..\..\src\tracks\ui\EditCursorOverlay.h" />
|
||||||
|
<ClInclude Include="..\..\..\src\tracks\ui\EnvelopeHandle.h" />
|
||||||
<ClInclude Include="..\..\..\src\tracks\ui\PlayIndicatorOverlay.h" />
|
<ClInclude Include="..\..\..\src\tracks\ui\PlayIndicatorOverlay.h" />
|
||||||
<ClInclude Include="..\..\..\src\tracks\ui\Scrubbing.h" />
|
<ClInclude Include="..\..\..\src\tracks\ui\Scrubbing.h" />
|
||||||
<ClInclude Include="..\..\..\src\TranslatableStringArray.h" />
|
<ClInclude Include="..\..\..\src\TranslatableStringArray.h" />
|
||||||
|
@ -956,6 +956,9 @@
|
|||||||
<ClCompile Include="..\..\..\src\tracks\ui\TimeShiftHandle.cpp">
|
<ClCompile Include="..\..\..\src\tracks\ui\TimeShiftHandle.cpp">
|
||||||
<Filter>src\tracks\ui</Filter>
|
<Filter>src\tracks\ui</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\src\tracks\ui\EnvelopeHandle.cpp">
|
||||||
|
<Filter>src\tracks\ui</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\src\tracks\timetrack\ui\TimeTrackControls.cpp">
|
<ClCompile Include="..\..\..\src\tracks\timetrack\ui\TimeTrackControls.cpp">
|
||||||
<Filter>src\tracks\timetrack\ui</Filter>
|
<Filter>src\tracks\timetrack\ui</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1990,6 +1993,9 @@
|
|||||||
<ClInclude Include="..\..\..\src\tracks\ui\TimeShiftHandle.h">
|
<ClInclude Include="..\..\..\src\tracks\ui\TimeShiftHandle.h">
|
||||||
<Filter>src\tracks\ui</Filter>
|
<Filter>src\tracks\ui</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\src\tracks\ui\EnvelopeHandle.h">
|
||||||
|
<Filter>src\tracks\ui</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="..\..\audacity.ico">
|
<Image Include="..\..\audacity.ico">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user