mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-27 14:09:33 +02:00
Add support for zooming to show all notes, separate from max zoom
This is now the behavior of Zoom Reset, with Max Zoom being given the previous behavior. Shift+Right-Click alternates between the two -- it zooms to all notes, unless it currently is zoomed to all notes in which case it performs a max zoom. This fixes Bug 2093. It also fixes Bug 1815, by performing the all-notes zoom when importing a track.
This commit is contained in:
parent
567b3972b8
commit
99f4c35e18
@ -1047,6 +1047,37 @@ void NoteTrack::ZoomTo(const wxRect &rect, int start, int end)
|
|||||||
SetNoteRange(pitch1, pitch2);
|
SetNoteRange(pitch1, pitch2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NoteTrack::ZoomAllNotes()
|
||||||
|
{
|
||||||
|
Alg_iterator iterator( &GetSeq(), false );
|
||||||
|
iterator.begin();
|
||||||
|
Alg_event_ptr evt;
|
||||||
|
|
||||||
|
// Go through all of the notes, finding the minimum and maximum value pitches.
|
||||||
|
bool hasNotes = false;
|
||||||
|
int minPitch = MaxPitch;
|
||||||
|
int maxPitch = MinPitch;
|
||||||
|
|
||||||
|
while (NULL != (evt = iterator.next())) {
|
||||||
|
if (evt->is_note()) {
|
||||||
|
int pitch = (int) evt->get_pitch();
|
||||||
|
hasNotes = true;
|
||||||
|
if (pitch < minPitch)
|
||||||
|
minPitch = pitch;
|
||||||
|
if (pitch > maxPitch)
|
||||||
|
maxPitch = pitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasNotes) {
|
||||||
|
// Semi-arbitary default values:
|
||||||
|
minPitch = 48;
|
||||||
|
maxPitch = 72;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetNoteRange(minPitch, maxPitch);
|
||||||
|
}
|
||||||
|
|
||||||
NoteTrackDisplayData::NoteTrackDisplayData(const NoteTrack* track, const wxRect &r)
|
NoteTrackDisplayData::NoteTrackDisplayData(const NoteTrack* track, const wxRect &r)
|
||||||
{
|
{
|
||||||
auto span = track->GetTopNote() - track->GetBottomNote() + 1; // + 1 to make sure it includes both
|
auto span = track->GetTopNote() - track->GetBottomNote() + 1; // + 1 to make sure it includes both
|
||||||
|
@ -131,6 +131,8 @@ class AUDACITY_DLL_API NoteTrack final
|
|||||||
/// Sets the top and bottom note (both pitches) automatically, swapping them if needed.
|
/// Sets the top and bottom note (both pitches) automatically, swapping them if needed.
|
||||||
void SetNoteRange(int note1, int note2);
|
void SetNoteRange(int note1, int note2);
|
||||||
|
|
||||||
|
/// Zooms so that all notes are visible
|
||||||
|
void ZoomAllNotes();
|
||||||
/// Zooms so that the entire track is visible
|
/// Zooms so that the entire track is visible
|
||||||
void ZoomMaxExtent() { SetNoteRange(MinPitch, MaxPitch); }
|
void ZoomMaxExtent() { SetNoteRange(MinPitch, MaxPitch); }
|
||||||
/// Shifts all notes vertically by the given pitch
|
/// Shifts all notes vertically by the given pitch
|
||||||
|
@ -69,27 +69,8 @@ bool ImportMIDI(const FilePath &fName, NoteTrack * dest)
|
|||||||
wxString trackNameBase = fName.AfterLast(wxFILE_SEP_PATH).BeforeLast('.');
|
wxString trackNameBase = fName.AfterLast(wxFILE_SEP_PATH).BeforeLast('.');
|
||||||
dest->SetName(trackNameBase);
|
dest->SetName(trackNameBase);
|
||||||
mf.Close();
|
mf.Close();
|
||||||
// the mean pitch should be somewhere in the middle of the display
|
|
||||||
Alg_iterator iterator( &dest->GetSeq(), false );
|
dest->ZoomAllNotes();
|
||||||
iterator.begin();
|
|
||||||
// for every event
|
|
||||||
Alg_event_ptr evt;
|
|
||||||
int note_count = 0;
|
|
||||||
int pitch_sum = 0;
|
|
||||||
while (NULL != (evt = iterator.next())) {
|
|
||||||
// if the event is a note
|
|
||||||
if (evt->get_type() == 'n') {
|
|
||||||
Alg_note_ptr note = (Alg_note_ptr) evt;
|
|
||||||
pitch_sum += (int) note->pitch;
|
|
||||||
note_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int mean_pitch = (note_count > 0 ? pitch_sum / note_count : 60);
|
|
||||||
// initial track is about 27 half-steps high; if bottom note is C,
|
|
||||||
// then middle pitch class is D. Round mean_pitch to the nearest D:
|
|
||||||
int mid_pitch = ((mean_pitch - 2 + 6) / 12) * 12 + 2;
|
|
||||||
dest->SetBottomNote(mid_pitch - 14);
|
|
||||||
dest->SetTopNote(mid_pitch + 13);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +147,7 @@ HitTestPreview NoteTrackVZoomHandle::Preview
|
|||||||
const int kZoomIn = 6;
|
const int kZoomIn = 6;
|
||||||
const int kZoomOut = 7;
|
const int kZoomOut = 7;
|
||||||
const int kZoomReset = 8;
|
const int kZoomReset = 8;
|
||||||
|
const int kZoomMax = 9;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
OnZoomFitVerticalID = 20000,
|
OnZoomFitVerticalID = 20000,
|
||||||
@ -164,6 +165,8 @@ enum {
|
|||||||
// Reserve an ample block of ids for spectrum scale types
|
// Reserve an ample block of ids for spectrum scale types
|
||||||
OnFirstSpectrumScaleID,
|
OnFirstSpectrumScaleID,
|
||||||
OnLastSpectrumScaleID = OnFirstSpectrumScaleID + 19,
|
OnLastSpectrumScaleID = OnFirstSpectrumScaleID + 19,
|
||||||
|
|
||||||
|
OnZoomMaxID,
|
||||||
};
|
};
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Table class
|
// Table class
|
||||||
@ -187,6 +190,7 @@ protected:
|
|||||||
// void OnZoomHalfWave(wxCommandEvent&){ OnZoom( kZoomHalfWave );};
|
// void OnZoomHalfWave(wxCommandEvent&){ OnZoom( kZoomHalfWave );};
|
||||||
void OnZoomInVertical(wxCommandEvent&){ OnZoom( kZoomIn );};
|
void OnZoomInVertical(wxCommandEvent&){ OnZoom( kZoomIn );};
|
||||||
void OnZoomOutVertical(wxCommandEvent&){ OnZoom( kZoomOut );};
|
void OnZoomOutVertical(wxCommandEvent&){ OnZoom( kZoomOut );};
|
||||||
|
void OnZoomMax(wxCommandEvent&){ OnZoom( kZoomMax );};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DestroyMenu() override
|
void DestroyMenu() override
|
||||||
@ -211,7 +215,7 @@ void NoteTrackVRulerMenuTable::InitMenu(Menu *WXUNUSED(pMenu), void *pUserData)
|
|||||||
void NoteTrackVRulerMenuTable::OnZoom( int iZoomCode ){
|
void NoteTrackVRulerMenuTable::OnZoom( int iZoomCode ){
|
||||||
switch( iZoomCode ){
|
switch( iZoomCode ){
|
||||||
case kZoomReset:
|
case kZoomReset:
|
||||||
mpData->pTrack->ZoomMaxExtent();
|
mpData->pTrack->ZoomAllNotes();
|
||||||
break;
|
break;
|
||||||
case kZoomIn:
|
case kZoomIn:
|
||||||
mpData->pTrack->ZoomIn(mpData->rect, mpData->yy);
|
mpData->pTrack->ZoomIn(mpData->rect, mpData->yy);
|
||||||
@ -219,7 +223,9 @@ void NoteTrackVRulerMenuTable::OnZoom( int iZoomCode ){
|
|||||||
case kZoomOut:
|
case kZoomOut:
|
||||||
mpData->pTrack->ZoomOut(mpData->rect, mpData->yy);
|
mpData->pTrack->ZoomOut(mpData->rect, mpData->yy);
|
||||||
break;
|
break;
|
||||||
|
case kZoomMax:
|
||||||
|
mpData->pTrack->ZoomMaxExtent();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
GetActiveProject()->ModifyState(false);
|
GetActiveProject()->ModifyState(false);
|
||||||
}
|
}
|
||||||
@ -228,6 +234,7 @@ void NoteTrackVRulerMenuTable::OnZoom( int iZoomCode ){
|
|||||||
BEGIN_POPUP_MENU(NoteTrackVRulerMenuTable)
|
BEGIN_POPUP_MENU(NoteTrackVRulerMenuTable)
|
||||||
|
|
||||||
POPUP_MENU_ITEM(OnZoomResetID, _("Zoom Reset\tShift-Right-Click"), OnZoomReset)
|
POPUP_MENU_ITEM(OnZoomResetID, _("Zoom Reset\tShift-Right-Click"), OnZoomReset)
|
||||||
|
POPUP_MENU_ITEM(OnZoomMaxID, _("Max Zoom"), OnZoomMax)
|
||||||
|
|
||||||
POPUP_MENU_SEPARATOR()
|
POPUP_MENU_SEPARATOR()
|
||||||
POPUP_MENU_ITEM(OnZoomInVerticalID, _("Zoom In\tLeft-Click/Left-Drag"), OnZoomInVertical)
|
POPUP_MENU_ITEM(OnZoomInVerticalID, _("Zoom In\tLeft-Click/Left-Drag"), OnZoomInVertical)
|
||||||
@ -296,8 +303,15 @@ UIHandle::Result NoteTrackVZoomHandle::Release
|
|||||||
}
|
}
|
||||||
else if (event.ShiftDown() || event.RightUp()) {
|
else if (event.ShiftDown() || event.RightUp()) {
|
||||||
if (event.ShiftDown() && event.RightUp()) {
|
if (event.ShiftDown() && event.RightUp()) {
|
||||||
// Zoom out completely
|
auto oldBotNote = pTrack->GetBottomNote();
|
||||||
pTrack->ZoomMaxExtent();
|
auto oldTopNote = pTrack->GetTopNote();
|
||||||
|
// Zoom out to show all notes
|
||||||
|
pTrack->ZoomAllNotes();
|
||||||
|
if (pTrack->GetBottomNote() == oldBotNote &&
|
||||||
|
pTrack->GetTopNote() == oldTopNote) {
|
||||||
|
// However if we are already showing all notes, zoom out further
|
||||||
|
pTrack->ZoomMaxExtent();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Zoom out
|
// Zoom out
|
||||||
pTrack->ZoomOut(evt.rect, mZoomEnd);
|
pTrack->ZoomOut(evt.rect, mZoomEnd);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user