From 99f4c35e184040657af14f1b2f172cec98f5a6c1 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sun, 14 Jan 2018 12:08:54 -0800 Subject: [PATCH] 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. --- src/NoteTrack.cpp | 31 +++++++++++++++++++ src/NoteTrack.h | 2 ++ src/import/ImportMIDI.cpp | 23 ++------------ .../notetrack/ui/NoteTrackVZoomHandle.cpp | 22 ++++++++++--- 4 files changed, 53 insertions(+), 25 deletions(-) diff --git a/src/NoteTrack.cpp b/src/NoteTrack.cpp index c3709c186..a9be052d8 100644 --- a/src/NoteTrack.cpp +++ b/src/NoteTrack.cpp @@ -1047,6 +1047,37 @@ void NoteTrack::ZoomTo(const wxRect &rect, int start, int end) 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) { auto span = track->GetTopNote() - track->GetBottomNote() + 1; // + 1 to make sure it includes both diff --git a/src/NoteTrack.h b/src/NoteTrack.h index 07541b5a6..3ea8d6c37 100644 --- a/src/NoteTrack.h +++ b/src/NoteTrack.h @@ -131,6 +131,8 @@ class AUDACITY_DLL_API NoteTrack final /// Sets the top and bottom note (both pitches) automatically, swapping them if needed. void SetNoteRange(int note1, int note2); + /// Zooms so that all notes are visible + void ZoomAllNotes(); /// Zooms so that the entire track is visible void ZoomMaxExtent() { SetNoteRange(MinPitch, MaxPitch); } /// Shifts all notes vertically by the given pitch diff --git a/src/import/ImportMIDI.cpp b/src/import/ImportMIDI.cpp index a2f6492b4..88518270b 100644 --- a/src/import/ImportMIDI.cpp +++ b/src/import/ImportMIDI.cpp @@ -69,27 +69,8 @@ bool ImportMIDI(const FilePath &fName, NoteTrack * dest) wxString trackNameBase = fName.AfterLast(wxFILE_SEP_PATH).BeforeLast('.'); dest->SetName(trackNameBase); mf.Close(); - // the mean pitch should be somewhere in the middle of the display - Alg_iterator iterator( &dest->GetSeq(), false ); - 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); + + dest->ZoomAllNotes(); return true; } diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.cpp index 70099500d..2d74773e0 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.cpp @@ -147,6 +147,7 @@ HitTestPreview NoteTrackVZoomHandle::Preview const int kZoomIn = 6; const int kZoomOut = 7; const int kZoomReset = 8; +const int kZoomMax = 9; enum { OnZoomFitVerticalID = 20000, @@ -164,6 +165,8 @@ enum { // Reserve an ample block of ids for spectrum scale types OnFirstSpectrumScaleID, OnLastSpectrumScaleID = OnFirstSpectrumScaleID + 19, + + OnZoomMaxID, }; /////////////////////////////////////////////////////////////////////////////// // Table class @@ -187,6 +190,7 @@ protected: // void OnZoomHalfWave(wxCommandEvent&){ OnZoom( kZoomHalfWave );}; void OnZoomInVertical(wxCommandEvent&){ OnZoom( kZoomIn );}; void OnZoomOutVertical(wxCommandEvent&){ OnZoom( kZoomOut );}; + void OnZoomMax(wxCommandEvent&){ OnZoom( kZoomMax );}; private: void DestroyMenu() override @@ -211,7 +215,7 @@ void NoteTrackVRulerMenuTable::InitMenu(Menu *WXUNUSED(pMenu), void *pUserData) void NoteTrackVRulerMenuTable::OnZoom( int iZoomCode ){ switch( iZoomCode ){ case kZoomReset: - mpData->pTrack->ZoomMaxExtent(); + mpData->pTrack->ZoomAllNotes(); break; case kZoomIn: mpData->pTrack->ZoomIn(mpData->rect, mpData->yy); @@ -219,7 +223,9 @@ void NoteTrackVRulerMenuTable::OnZoom( int iZoomCode ){ case kZoomOut: mpData->pTrack->ZoomOut(mpData->rect, mpData->yy); break; - + case kZoomMax: + mpData->pTrack->ZoomMaxExtent(); + break; } GetActiveProject()->ModifyState(false); } @@ -228,6 +234,7 @@ void NoteTrackVRulerMenuTable::OnZoom( int iZoomCode ){ BEGIN_POPUP_MENU(NoteTrackVRulerMenuTable) POPUP_MENU_ITEM(OnZoomResetID, _("Zoom Reset\tShift-Right-Click"), OnZoomReset) + POPUP_MENU_ITEM(OnZoomMaxID, _("Max Zoom"), OnZoomMax) POPUP_MENU_SEPARATOR() 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()) { if (event.ShiftDown() && event.RightUp()) { - // Zoom out completely - pTrack->ZoomMaxExtent(); + auto oldBotNote = pTrack->GetBottomNote(); + 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 { // Zoom out pTrack->ZoomOut(evt.rect, mZoomEnd);