1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-25 17:08:07 +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:
Pokechu22 2018-01-14 12:08:54 -08:00 committed by James Crook
parent 567b3972b8
commit 99f4c35e18
4 changed files with 53 additions and 25 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);