1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-23 15:50:05 +02:00

Move cursor moving functions out of TrackPanel

This commit is contained in:
Paul Licameli 2015-08-27 19:26:00 -04:00
parent 05d8023af6
commit e7482c74bd
6 changed files with 403 additions and 404 deletions

View File

@ -2514,22 +2514,22 @@ void AudacityProject::OnSkipEnd()
void AudacityProject::OnSeekLeftShort()
{
mTrackPanel->OnCursorLeft( false, false );
OnCursorLeft( false, false );
}
void AudacityProject::OnSeekRightShort()
{
mTrackPanel->OnCursorRight( false, false );
OnCursorRight( false, false );
}
void AudacityProject::OnSeekLeftLong()
{
mTrackPanel->OnCursorLeft( true, false );
OnCursorLeft( true, false );
}
void AudacityProject::OnSeekRightLong()
{
mTrackPanel->OnCursorRight( true, false );
OnCursorRight( true, false );
}
void AudacityProject::OnSelToStart()
@ -2581,62 +2581,62 @@ void AudacityProject::OnToggle()
void AudacityProject::OnCursorLeft(const wxEvent * evt)
{
mTrackPanel->OnCursorLeft( false, false, evt->GetEventType() == wxEVT_KEY_UP );
OnCursorLeft( false, false, evt->GetEventType() == wxEVT_KEY_UP );
}
void AudacityProject::OnCursorRight(const wxEvent * evt)
{
mTrackPanel->OnCursorRight( false, false, evt->GetEventType() == wxEVT_KEY_UP );
OnCursorRight( false, false, evt->GetEventType() == wxEVT_KEY_UP );
}
void AudacityProject::OnCursorShortJumpLeft()
{
mTrackPanel->OnCursorMove( false, true, false );
OnCursorMove( false, true, false );
}
void AudacityProject::OnCursorShortJumpRight()
{
mTrackPanel->OnCursorMove( true, true, false );
OnCursorMove( true, true, false );
}
void AudacityProject::OnCursorLongJumpLeft()
{
mTrackPanel->OnCursorMove( false, true, true );
OnCursorMove( false, true, true );
}
void AudacityProject::OnCursorLongJumpRight()
{
mTrackPanel->OnCursorMove( true, true, true );
OnCursorMove( true, true, true );
}
void AudacityProject::OnSelSetExtendLeft()
{
mTrackPanel->OnBoundaryMove( true, false);
OnBoundaryMove( true, false);
}
void AudacityProject::OnSelSetExtendRight()
{
mTrackPanel->OnBoundaryMove( false, false);
OnBoundaryMove( false, false);
}
void AudacityProject::OnSelExtendLeft(const wxEvent * evt)
{
mTrackPanel->OnCursorLeft( true, false, evt->GetEventType() == wxEVT_KEY_UP );
OnCursorLeft( true, false, evt->GetEventType() == wxEVT_KEY_UP );
}
void AudacityProject::OnSelExtendRight(const wxEvent * evt)
{
mTrackPanel->OnCursorRight( true, false, evt->GetEventType() == wxEVT_KEY_UP );
OnCursorRight( true, false, evt->GetEventType() == wxEVT_KEY_UP );
}
void AudacityProject::OnSelContractLeft(const wxEvent * evt)
{
mTrackPanel->OnCursorRight( true, true, evt->GetEventType() == wxEVT_KEY_UP );
OnCursorRight( true, true, evt->GetEventType() == wxEVT_KEY_UP );
}
void AudacityProject::OnSelContractRight(const wxEvent * evt)
{
mTrackPanel->OnCursorLeft( true, true, evt->GetEventType() == wxEVT_KEY_UP );
OnCursorLeft( true, true, evt->GetEventType() == wxEVT_KEY_UP );
}
//this pops up a dialog which allows the left selection to be set.
@ -6592,3 +6592,360 @@ void AudacityProject::OnFullScreen()
wxTopLevelWindow::ShowFullScreen(true);
}
void AudacityProject::OnCursorLeft(bool shift, bool ctrl, bool keyup)
{
// PRL: What I found and preserved, strange though it be:
// During playback: jump depends on preferences and is independent of the zoom
// and does not vary if the key is held
// Else: jump depends on the zoom and gets bigger if the key is held
int snapToTime = GetSnapTo();
double quietSeekStepPositive = 1.0; // pixels
double audioSeekStepPositive = shift ? mSeekLong : mSeekShort;
SeekLeftOrRight
(true, shift, ctrl, keyup, snapToTime, true, false,
quietSeekStepPositive, true,
audioSeekStepPositive, false);
}
void AudacityProject::OnCursorRight(bool shift, bool ctrl, bool keyup)
{
// PRL: What I found and preserved, strange though it be:
// During playback: jump depends on preferences and is independent of the zoom
// and does not vary if the key is held
// Else: jump depends on the zoom and gets bigger if the key is held
int snapToTime = GetSnapTo();
double quietSeekStepPositive = 1.0; // pixels
double audioSeekStepPositive = shift ? mSeekLong : mSeekShort;
SeekLeftOrRight
(false, shift, ctrl, keyup, snapToTime, true, false,
quietSeekStepPositive, true,
audioSeekStepPositive, false);
}
// Handle small cursor and play head movements
void AudacityProject::SeekLeftOrRight
(bool leftward, bool shift, bool ctrl, bool keyup,
int snapToTime, bool mayAccelerateQuiet, bool mayAccelerateAudio,
double quietSeekStepPositive, bool quietStepIsPixels,
double audioSeekStepPositive, bool audioStepIsPixels)
{
if (keyup)
{
if (IsAudioActive())
{
return;
}
ModifyState(false);
return;
}
// If the last adjustment was very recent, we are
// holding the key down and should move faster.
const wxLongLong curtime = ::wxGetLocalTimeMillis();
enum { MIN_INTERVAL = 50 };
const bool fast = (curtime - mLastSelectionAdjustment < MIN_INTERVAL);
// How much faster should the cursor move if shift is down?
enum { LARGER_MULTIPLIER = 4 };
int multiplier = (fast && mayAccelerateQuiet) ? LARGER_MULTIPLIER : 1;
if (leftward)
multiplier = -multiplier;
if (shift && ctrl)
{
mLastSelectionAdjustment = curtime;
// Contract selection
// Reduce and constrain (counter-intuitive)
if (leftward) {
const double t1 = mViewInfo.selectedRegion.t1();
mViewInfo.selectedRegion.setT1(
std::max(mViewInfo.selectedRegion.t0(),
snapToTime
? GridMove(t1, multiplier)
: quietStepIsPixels
? mViewInfo.OffsetTimeByPixels(
t1, int(multiplier * quietSeekStepPositive))
: t1 + multiplier * quietSeekStepPositive
));
// Make sure it's visible.
GetTrackPanel()->ScrollIntoView(mViewInfo.selectedRegion.t1());
}
else {
const double t0 = mViewInfo.selectedRegion.t0();
mViewInfo.selectedRegion.setT0(
std::min(mViewInfo.selectedRegion.t1(),
snapToTime
? GridMove(t0, multiplier)
: quietStepIsPixels
? mViewInfo.OffsetTimeByPixels(
t0, int(multiplier * quietSeekStepPositive))
: t0 + multiplier * quietSeekStepPositive
));
// Make sure new position is in view.
GetTrackPanel()->ScrollIntoView(mViewInfo.selectedRegion.t0());
}
GetTrackPanel()->Refresh(false);
}
else if (IsAudioActive()) {
#ifdef EXPERIMENTAL_IMPROVED_SEEKING
if (gAudioIO->GetLastPlaybackTime() < mLastSelectionAdjustment) {
// Allow time for the last seek to output a buffer before
// discarding samples again
// Do not advance mLastSelectionAdjustment
return;
}
#endif
mLastSelectionAdjustment = curtime;
// Ignore the multiplier for the quiet case
multiplier = (fast && mayAccelerateAudio) ? LARGER_MULTIPLIER : 1;
if (leftward)
multiplier = -multiplier;
// If playing, reposition
double seconds;
if (audioStepIsPixels) {
const double streamTime = gAudioIO->GetStreamTime();
const double newTime =
mViewInfo.OffsetTimeByPixels(streamTime, int(audioSeekStepPositive));
seconds = newTime - streamTime;
}
else
seconds = multiplier * audioSeekStepPositive;
gAudioIO->SeekStream(seconds);
return;
}
else if (shift)
{
mLastSelectionAdjustment = curtime;
// Extend selection
// Expand and constrain
if (leftward) {
const double t0 = mViewInfo.selectedRegion.t0();
mViewInfo.selectedRegion.setT0(
std::max(0.0,
snapToTime
? GridMove(t0, multiplier)
: quietStepIsPixels
? mViewInfo.OffsetTimeByPixels(
t0, int(multiplier * quietSeekStepPositive))
: t0 + multiplier * quietSeekStepPositive
));
// Make sure it's visible.
GetTrackPanel()->ScrollIntoView(mViewInfo.selectedRegion.t0());
}
else {
const double end = mTracks->GetEndTime();
const double t1 = mViewInfo.selectedRegion.t1();
mViewInfo.selectedRegion.setT1(
std::min(end,
snapToTime
? GridMove(t1, multiplier)
: quietStepIsPixels
? mViewInfo.OffsetTimeByPixels(
t1, int(multiplier * quietSeekStepPositive))
: t1 + multiplier * quietSeekStepPositive
));
// Make sure new position is in view.
GetTrackPanel()->ScrollIntoView(mViewInfo.selectedRegion.t1());
}
GetTrackPanel()->Refresh(false);
}
else
{
mLastSelectionAdjustment = curtime;
// Move the cursor
// Already in cursor mode?
if (mViewInfo.selectedRegion.isPoint())
{
// Move and constrain
const double end = mTracks->GetEndTime();
const double t0 = mViewInfo.selectedRegion.t0();
mViewInfo.selectedRegion.setT0(
std::max(0.0,
std::min(end,
snapToTime
? GridMove(t0, multiplier)
: quietStepIsPixels
? mViewInfo.OffsetTimeByPixels(
t0, int(multiplier * quietSeekStepPositive))
: t0 + multiplier * quietSeekStepPositive)),
false // do not swap selection boundaries
);
mViewInfo.selectedRegion.collapseToT0();
// Move the visual cursor, avoiding an unnecessary complete redraw
GetTrackPanel()->DrawOverlays(false);
}
else
{
// Transition to cursor mode.
if (leftward)
mViewInfo.selectedRegion.collapseToT0();
else
mViewInfo.selectedRegion.collapseToT1();
GetTrackPanel()->Refresh(false);
}
// Make sure new position is in view
GetTrackPanel()->ScrollIntoView(mViewInfo.selectedRegion.t1());
}
}
// Handles moving a selection edge with the keyboard in snap-to-time mode;
// returns the moved value.
// Will move at least minPix pixels -- set minPix positive to move forward,
// negative to move backward.
double AudacityProject::GridMove(double t, int minPix)
{
NumericConverter nc(NumericConverter::TIME, GetSelectionFormat(), t, GetRate());
// Try incrementing/decrementing the value; if we've moved far enough we're
// done
double result;
minPix >= 0 ? nc.Increment() : nc.Decrement();
result = nc.GetValue();
if (std::abs(mViewInfo.TimeToPosition(result) - mViewInfo.TimeToPosition(t))
>= abs(minPix))
return result;
// Otherwise, move minPix pixels, then snap to the time.
result = mViewInfo.OffsetTimeByPixels(t, minPix);
nc.SetValue(result);
result = nc.GetValue();
return result;
}
void AudacityProject::OnBoundaryMove(bool left, bool boundaryContract)
{
// Move the left/right selection boundary, to either expand or contract the selection
// left=true: operate on left boundary; left=false: operate on right boundary
// boundaryContract=true: contract region; boundaryContract=false: expand region.
// If the last adjustment was very recent, we are
// holding the key down and should move faster.
wxLongLong curtime = ::wxGetLocalTimeMillis();
int pixels = 1;
if( curtime - mLastSelectionAdjustment < 50 )
{
pixels = 4;
}
mLastSelectionAdjustment = curtime;
if (IsAudioActive())
{
double indicator = gAudioIO->GetStreamTime();
if (left)
mViewInfo.selectedRegion.setT0(indicator, false);
else
mViewInfo.selectedRegion.setT1(indicator);
ModifyState(false);
GetTrackPanel()->Refresh(false);
}
else
{
// BOUNDARY MOVEMENT
// Contract selection from the right to the left
if( boundaryContract )
{
if (left) {
// Reduce and constrain left boundary (counter-intuitive)
// Move the left boundary by at most the desired number of pixels,
// but not past the right
mViewInfo.selectedRegion.setT0(
std::min(mViewInfo.selectedRegion.t1(),
mViewInfo.OffsetTimeByPixels(
mViewInfo.selectedRegion.t0(),
pixels)));
// Make sure it's visible
GetTrackPanel()->ScrollIntoView(mViewInfo.selectedRegion.t0());
}
else
{
// Reduce and constrain right boundary (counter-intuitive)
// Move the right boundary by at most the desired number of pixels,
// but not past the left
mViewInfo.selectedRegion.setT1(
std::max(mViewInfo.selectedRegion.t0(),
mViewInfo.OffsetTimeByPixels(
mViewInfo.selectedRegion.t1(),
-pixels)));
// Make sure it's visible
GetTrackPanel()->ScrollIntoView(mViewInfo.selectedRegion.t1());
}
}
// BOUNDARY MOVEMENT
// Extend selection toward the left
else
{
if (left) {
// Expand and constrain left boundary
mViewInfo.selectedRegion.setT0(
std::max(0.0,
mViewInfo.OffsetTimeByPixels(
mViewInfo.selectedRegion.t0(),
-pixels)));
// Make sure it's visible
GetTrackPanel()->ScrollIntoView(mViewInfo.selectedRegion.t0());
}
else
{
// Expand and constrain right boundary
const double end = mTracks->GetEndTime();
mViewInfo.selectedRegion.setT1(
std::min(end,
mViewInfo.OffsetTimeByPixels(
mViewInfo.selectedRegion.t1(),
pixels)));
// Make sure it's visible
GetTrackPanel()->ScrollIntoView(mViewInfo.selectedRegion.t1());
}
}
GetTrackPanel()->Refresh( false );
ModifyState(false);
}
}
// Move the cursor forward or backward, while paused or while playing.
// forward=true: Move cursor forward; forward=false: Move cursor backwards
// jump=false: Move cursor determined by zoom; jump=true: Use seek times
// longjump=false: Use mSeekShort; longjump=true: Use mSeekLong
void AudacityProject::OnCursorMove(bool forward, bool jump, bool longjump )
{
// PRL: nobody calls this yet with !jump
double positiveSeekStep;
bool byPixels;
if (jump) {
if (!longjump) {
positiveSeekStep = mSeekShort;
} else {
positiveSeekStep = mSeekLong;
}
byPixels = false;
} else {
positiveSeekStep = 1.0;
byPixels = true;
}
bool mayAccelerate = !jump;
SeekLeftOrRight
(!forward, false, false, false,
0, mayAccelerate, mayAccelerate,
positiveSeekStep, byPixels,
positiveSeekStep, byPixels);
ModifyState(false);
}

View File

@ -407,6 +407,22 @@ void NextWindow();
void OnResample();
private:
void OnCursorLeft(bool shift, bool ctrl, bool keyup = false);
void OnCursorRight(bool shift, bool ctrl, bool keyup = false);
void OnCursorMove(bool forward, bool jump, bool longjump);
void OnBoundaryMove(bool left, bool boundaryContract);
// Handle small cursor and play head movements
void SeekLeftOrRight
(bool left, bool shift, bool ctrl, bool keyup,
int snapToTime, bool mayAccelerateQuiet, bool mayAccelerateAudio,
double quietSeekStepPositive, bool quietStepIsPixels,
double audioSeekStepPositive, bool audioStepIsPixels);
// Helper for moving by keyboard with snap-to-grid enabled
double GridMove(double t, int minPix);
// Make sure we return to "public" for subsequent declarations in Project.h.
public:

View File

@ -1029,6 +1029,10 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
wxCommandEventHandler(AudacityProject::OnCapture),
NULL,
this);
//Initialize the last selection adjustment time.
mLastSelectionAdjustment = ::wxGetLocalTimeMillis();
}
AudacityProject::~AudacityProject()
@ -1064,6 +1068,9 @@ void AudacityProject::UpdatePrefsVariables()
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleRate"), &mRate, AudioIO::GetOptimalSupportedSampleRate());
mDefaultFormat = (sampleFormat) gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
gPrefs->Read(wxT("/AudioIO/SeekShortPeriod"), &mSeekShort, 1.0);
gPrefs->Read(wxT("/AudioIO/SeekLongPeriod"), &mSeekLong, 15.0);
}
void AudacityProject::UpdatePrefs()

View File

@ -660,6 +660,11 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame,
// Keyboard capture
wxWindow *mKeyboardCaptureHandler;
double mSeekShort;
double mSeekLong;
wxLongLong mLastSelectionAdjustment;
// CommandManager needs to use private methods
friend class CommandManager;

View File

@ -562,9 +562,6 @@ TrackPanel::TrackPanel(wxWindow * parent, wxWindowID id,
mPrevWidth = -1;
mPrevHeight = -1;
//Initialize the last selection adjustment time.
mLastSelectionAdjustment = ::wxGetLocalTimeMillis();
// This is used to snap the cursor to the nearest track that
// lines up with it.
mSnapManager = NULL;
@ -895,10 +892,6 @@ void TrackPanel::UpdatePrefs()
gPrefs->Read(wxT("/GUI/CircularTrackNavigation"), &mCircularTrackNavigation,
false);
gPrefs->Read(wxT("/GUI/Solo"), &mSoloPref, wxT("Standard") );
gPrefs->Read(wxT("/AudioIO/SeekShortPeriod"), &mSeekShort,
1.0);
gPrefs->Read(wxT("/AudioIO/SeekLongPeriod"), &mSeekLong,
15.0);
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
bool temp = WaveTrack::mMonoAsVirtualStereo;
@ -8343,368 +8336,6 @@ void TrackPanel::ScrollIntoView(int x)
ScrollIntoView(mViewInfo->PositionToTime(x, GetLeftOffset()));
}
void TrackPanel::OnCursorLeft( bool shift, bool ctrl, bool keyup )
{
// PRL: What I found and preserved, strange though it be:
// During playback: jump depends on preferences and is independent of the zoom
// and does not vary if the key is held
// Else: jump depends on the zoom and gets bigger if the key is held
int snapToTime = GetActiveProject()->GetSnapTo();
double quietSeekStepPositive = 1.0; // pixels
double audioSeekStepPositive = shift ? mSeekLong : mSeekShort;
SeekLeftOrRight
(true, shift, ctrl, keyup, snapToTime, true, false,
quietSeekStepPositive, true,
audioSeekStepPositive, false);
}
void TrackPanel::OnCursorRight(bool shift, bool ctrl, bool keyup)
{
// PRL: What I found and preserved, strange though it be:
// During playback: jump depends on preferences and is independent of the zoom
// and does not vary if the key is held
// Else: jump depends on the zoom and gets bigger if the key is held
int snapToTime = GetActiveProject()->GetSnapTo();
double quietSeekStepPositive = 1.0; // pixels
double audioSeekStepPositive = shift ? mSeekLong : mSeekShort;
SeekLeftOrRight
(false, shift, ctrl, keyup, snapToTime, true, false,
quietSeekStepPositive, true,
audioSeekStepPositive, false);
}
// Handle small cursor and play head movements
void TrackPanel::SeekLeftOrRight
(bool leftward, bool shift, bool ctrl, bool keyup,
int snapToTime, bool mayAccelerateQuiet, bool mayAccelerateAudio,
double quietSeekStepPositive, bool quietStepIsPixels,
double audioSeekStepPositive, bool audioStepIsPixels)
{
if (keyup)
{
if (IsAudioActive())
{
return;
}
MakeParentModifyState(false);
return;
}
// If the last adjustment was very recent, we are
// holding the key down and should move faster.
const wxLongLong curtime = ::wxGetLocalTimeMillis();
enum { MIN_INTERVAL = 50 };
const bool fast = (curtime - mLastSelectionAdjustment < MIN_INTERVAL);
// How much faster should the cursor move if shift is down?
enum { LARGER_MULTIPLIER = 4 };
int multiplier = (fast && mayAccelerateQuiet) ? LARGER_MULTIPLIER : 1;
if (leftward)
multiplier = -multiplier;
if (shift && ctrl)
{
mLastSelectionAdjustment = curtime;
// Contract selection
// Reduce and constrain (counter-intuitive)
if (leftward) {
const double t1 = mViewInfo->selectedRegion.t1();
mViewInfo->selectedRegion.setT1(
std::max(mViewInfo->selectedRegion.t0(),
snapToTime
? GridMove(t1, multiplier)
: quietStepIsPixels
? mViewInfo->OffsetTimeByPixels(
t1, int(multiplier * quietSeekStepPositive))
: t1 + multiplier * quietSeekStepPositive
));
// Make sure it's visible.
ScrollIntoView(mViewInfo->selectedRegion.t1());
}
else {
const double t0 = mViewInfo->selectedRegion.t0();
mViewInfo->selectedRegion.setT0(
std::min(mViewInfo->selectedRegion.t1(),
snapToTime
? GridMove(t0, multiplier)
: quietStepIsPixels
? mViewInfo->OffsetTimeByPixels(
t0, int(multiplier * quietSeekStepPositive))
: t0 + multiplier * quietSeekStepPositive
));
// Make sure new position is in view.
ScrollIntoView(mViewInfo->selectedRegion.t0());
}
Refresh(false);
}
else if (IsAudioActive()) {
#ifdef EXPERIMENTAL_IMPROVED_SEEKING
if (gAudioIO->GetLastPlaybackTime() < mLastSelectionAdjustment) {
// Allow time for the last seek to output a buffer before
// discarding samples again
// Do not advance mLastSelectionAdjustment
return;
}
#endif
mLastSelectionAdjustment = curtime;
// Ignore the multiplier for the quiet case
multiplier = (fast && mayAccelerateAudio) ? LARGER_MULTIPLIER : 1;
if (leftward)
multiplier = -multiplier;
// If playing, reposition
double seconds;
if (audioStepIsPixels) {
const double streamTime = gAudioIO->GetStreamTime();
const double newTime =
mViewInfo->OffsetTimeByPixels(streamTime, int(audioSeekStepPositive));
seconds = newTime - streamTime;
}
else
seconds = multiplier * audioSeekStepPositive;
gAudioIO->SeekStream(seconds);
return;
}
else if (shift)
{
mLastSelectionAdjustment = curtime;
// Extend selection
// Expand and constrain
if (leftward) {
const double t0 = mViewInfo->selectedRegion.t0();
mViewInfo->selectedRegion.setT0(
std::max(0.0,
snapToTime
? GridMove(t0, multiplier)
: quietStepIsPixels
? mViewInfo->OffsetTimeByPixels(
t0, int(multiplier * quietSeekStepPositive))
: t0 + multiplier * quietSeekStepPositive
));
// Make sure it's visible.
ScrollIntoView(mViewInfo->selectedRegion.t0());
}
else {
double end = mTracks->GetEndTime();
const double t1 = mViewInfo->selectedRegion.t1();
mViewInfo->selectedRegion.setT1(
std::min(end,
snapToTime
? GridMove(t1, multiplier)
: quietStepIsPixels
? mViewInfo->OffsetTimeByPixels(
t1, int(multiplier * quietSeekStepPositive))
: t1 + multiplier * quietSeekStepPositive
));
// Make sure new position is in view.
ScrollIntoView(mViewInfo->selectedRegion.t1());
}
Refresh(false);
}
else
{
mLastSelectionAdjustment = curtime;
// Move the cursor
// Already in cursor mode?
if (mViewInfo->selectedRegion.isPoint())
{
// Move and constrain
double end = mTracks->GetEndTime();
const double t0 = mViewInfo->selectedRegion.t0();
mViewInfo->selectedRegion.setT0(
std::max(0.0,
std::min(end,
snapToTime
? GridMove(t0, multiplier)
: quietStepIsPixels
? mViewInfo->OffsetTimeByPixels(
t0, int(multiplier * quietSeekStepPositive))
: t0 + multiplier * quietSeekStepPositive)),
false // do not swap selection boundaries
);
mViewInfo->selectedRegion.collapseToT0();
// Move the visual cursor
DrawOverlays(false);
}
else
{
// Transition to cursor mode.
if (leftward)
mViewInfo->selectedRegion.collapseToT0();
else
mViewInfo->selectedRegion.collapseToT1();
Refresh(false);
}
// Make sure new position is in view
ScrollIntoView(mViewInfo->selectedRegion.t1());
}
}
// Handles moving a selection edge with the keyboard in snap-to-time mode;
// returns the moved value.
// Will move at least minPix pixels -- set minPix positive to move forward,
// negative to move backward.
double TrackPanel::GridMove(double t, int minPix)
{
NumericConverter nc(NumericConverter::TIME, GetProject()->GetSelectionFormat(), t, GetProject()->GetRate());
// Try incrementing/decrementing the value; if we've moved far enough we're
// done
double result;
minPix >= 0 ? nc.Increment() : nc.Decrement();
result = nc.GetValue();
if (std::abs(mViewInfo->TimeToPosition(result) - mViewInfo->TimeToPosition(t))
>= abs(minPix))
return result;
// Otherwise, move minPix pixels, then snap to the time.
result = mViewInfo->OffsetTimeByPixels(t, minPix);
nc.SetValue(result);
result = nc.GetValue();
return result;
}
void TrackPanel::OnBoundaryMove(bool left, bool boundaryContract)
{
// Move the left/right selection boundary, to either expand or contract the selection
// left=true: operate on left boundary; left=false: operate on right boundary
// boundaryContract=true: contract region; boundaryContract=false: expand region.
// If the last adjustment was very recent, we are
// holding the key down and should move faster.
wxLongLong curtime = ::wxGetLocalTimeMillis();
int pixels = 1;
if( curtime - mLastSelectionAdjustment < 50 )
{
pixels = 4;
}
mLastSelectionAdjustment = curtime;
if (IsAudioActive())
{
double indicator = gAudioIO->GetStreamTime();
if (left) {
mViewInfo->selectedRegion.setT0(indicator, false);
}
else
{
mViewInfo->selectedRegion.setT1(indicator);
}
MakeParentModifyState(false);
Refresh(false);
}
else
{
// BOUNDARY MOVEMENT
// Contract selection from the right to the left
if( boundaryContract )
{
if (left) {
// Reduce and constrain left boundary (counter-intuitive)
// Move the left boundary by at most the desired number of pixels,
// but not past the right
mViewInfo->selectedRegion.setT0(
std::min(mViewInfo->selectedRegion.t1(),
mViewInfo->OffsetTimeByPixels(
mViewInfo->selectedRegion.t0(),
pixels)));
// Make sure it's visible
ScrollIntoView( mViewInfo->selectedRegion.t0() );
}
else
{
// Reduce and constrain right boundary (counter-intuitive)
// Move the left boundary by at most the desired number of pixels,
// but not past the left
mViewInfo->selectedRegion.setT1(
std::max(mViewInfo->selectedRegion.t0(),
mViewInfo->OffsetTimeByPixels(
mViewInfo->selectedRegion.t1(),
-pixels)));
// Make sure it's visible
ScrollIntoView( mViewInfo->selectedRegion.t1() );
}
}
// BOUNDARY MOVEMENT
// Extend selection toward the left
else
{
if (left) {
// Expand and constrain left boundary
mViewInfo->selectedRegion.setT0(
std::max(0.0,
mViewInfo->OffsetTimeByPixels(
mViewInfo->selectedRegion.t0(),
-pixels)));
// Make sure it's visible
ScrollIntoView( mViewInfo->selectedRegion.t0() );
}
else
{
// Expand and constrain right boundary
double end = mTracks->GetEndTime();
mViewInfo->selectedRegion.setT1(
std::min(end,
mViewInfo->OffsetTimeByPixels(
mViewInfo->selectedRegion.t1(),
pixels)));
// Make sure it's visible
ScrollIntoView(mViewInfo->selectedRegion.t1());
}
}
Refresh( false );
MakeParentModifyState(false);
}
}
// Move the cursor forward or backward, while paused or while playing.
// forward=true: Move cursor forward; forward=false: Move cursor backwards
// jump=false: Move cursor determined by zoom; jump=true: Use seek times
// longjump=false: Use mSeekShort; longjump=true: Use mSeekLong
void TrackPanel::OnCursorMove(bool forward, bool jump, bool longjump )
{
// PRL: nobody calls this yet with !jump
double positiveSeekStep;
bool byPixels;
if (jump) {
if (!longjump) {
positiveSeekStep = mSeekShort;
} else {
positiveSeekStep = mSeekLong;
}
byPixels = false;
} else {
positiveSeekStep = 1.0;
byPixels = true;
}
bool mayAccelerate = !jump;
SeekLeftOrRight
(!forward, false, false, false,
0, mayAccelerate, mayAccelerate,
positiveSeekStep, byPixels,
positiveSeekStep, byPixels);
MakeParentModifyState(false);
}
//The following methods operate controls on specified tracks,
//This will pop up the track panning dialog for specified track
void TrackPanel::OnTrackPan()

View File

@ -195,10 +195,6 @@ class AUDACITY_DLL_API TrackPanel:public wxPanel {
virtual void OnLastTrack();
virtual void OnToggle();
virtual void OnCursorLeft(bool shift, bool ctrl, bool keyup = false);
virtual void OnCursorRight(bool shift, bool ctrl, bool keyup = false);
virtual void OnCursorMove(bool forward, bool jump, bool longjump);
virtual void OnBoundaryMove(bool left, bool boundaryContract);
virtual void ScrollIntoView(double pos);
virtual void ScrollIntoView(int x);
@ -351,13 +347,6 @@ protected:
Track *pTrack);
virtual void UpdateSelectionDisplay();
// Handle small cursor and play head movements
void SeekLeftOrRight
(bool left, bool shift, bool ctrl, bool keyup,
int snapToTime, bool mayAccelerateQuiet, bool mayAccelerateAudio,
double quietSeekStepPositive, bool quietStepIsPixels,
double audioSeekStepPositive, bool audioStepIsPixels);
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
public:
void SnapCenterOnce (const WaveTrack *pTrack, bool up);
@ -377,9 +366,6 @@ protected:
virtual void SelectTracksByLabel( LabelTrack *t );
virtual void SelectTrackLength(Track *t);
// Helper for moving by keyboard with snap-to-grid enabled
virtual double GridMove(double t, int minPix);
// AS: Cursor handling
virtual bool SetCursorByActivity( );
virtual bool SetCursorForCutline(WaveTrack * track, wxRect &rect, wxMouseEvent &event);
@ -566,10 +552,12 @@ protected:
virtual void DrawBordersAroundTrack(Track *t, wxDC* dc, const wxRect & rect, const int labelw, const int vrul);
virtual void DrawOutsideOfTrack (Track *t, wxDC* dc, const wxRect & rect);
public:
// Erase and redraw things like the cursor, cheaply and directly to the
// client area, without full refresh.
virtual void DrawOverlays(bool repaint);
protected:
virtual int IdOfRate( int rate );
virtual int IdOfFormat( int format );
@ -596,9 +584,6 @@ protected:
AdornedRulerPanel *mRuler;
double mSeekShort;
double mSeekLong;
TrackArtist *mTrackArtist;
class AUDACITY_DLL_API AudacityTimer:public wxTimer {
@ -637,8 +622,6 @@ protected:
int mPrevWidth;
int mPrevHeight;
wxLongLong mLastSelectionAdjustment;
SelectedRegion mInitialSelection;
// Extra indirection to avoid the stupid MSW compiler warnings! Rrrr!
std::vector<bool> *mInitialTrackSelection;