Audacity 3.2.0
NoteTrackVZoomHandle.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5NoteTrackVZoomHandle.cpp
6
7Paul Licameli split from TrackPanel.cpp
8
9**********************************************************************/
10
11
12#ifdef USE_MIDI
14
15#include "../../../ui/TrackVRulerControls.h"
16
17#include "../../../../HitTestResult.h"
18#include "../../../../NoteTrack.h"
19#include "Project.h"
20#include "ProjectHistory.h"
21#include "../../../../RefreshCode.h"
22#include "../../../../TrackArtist.h"
23#include "../../../../TrackPanelMouseEvent.h"
24#include "../../../../widgets/PopupMenuTable.h"
25#include "../../../../../images/Cursors.h"
26#include "Prefs.h"
27
28namespace
29{
30
32 {
33 public:
36 wxRect rect;
37 unsigned result;
38 int yy;
39 };
40
41 bool IsDragZooming(int zoomStart, int zoomEnd)
42 {
43 const int DragThreshold = 3;// Anything over 3 pixels is a drag, else a click.
44 bool bVZoom;
45 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
46 return bVZoom && (abs(zoomEnd - zoomStart) > DragThreshold);
47 }
48
49}
50
52
54(const std::shared_ptr<NoteTrack> &pTrack, const wxRect &rect, int y)
55 : mpTrack{ pTrack } , mZoomStart(y), mZoomEnd(y), mRect(rect)
56{
57}
58
60{
61#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
63#endif
64}
65
67{
68 static auto zoomInCursor =
69 ::MakeCursor(wxCURSOR_MAGNIFIER, ZoomInCursorXpm, 19, 15);
70 static auto zoomOutCursor =
71 ::MakeCursor(wxCURSOR_MAGNIFIER, ZoomOutCursorXpm, 19, 15);
72 static wxCursor arrowCursor{ wxCURSOR_ARROW };
73
74 bool bVZoom;
75 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
76 bVZoom &= !state.RightIsDown();
77 const auto message = bVZoom ?
78 XO("Click to vertically zoom in. Shift-click to zoom out. Drag to specify a zoom region.") :
79 XO("Right-click for menu.");
80
81 return {
82 message,
83 bVZoom ? (state.ShiftDown() ? &*zoomOutCursor : &*zoomInCursor) : &arrowCursor
84 // , message
85 };
86}
87
89(std::weak_ptr<NoteTrackVZoomHandle> &holder,
90 const wxMouseState &state,
91 const std::shared_ptr<NoteTrack> &pTrack, const wxRect &rect)
92{
93 if (pTrack) {
94 auto result = std::make_shared<NoteTrackVZoomHandle>(
95 pTrack, rect, state.m_y);
96 result = AssignUIHandlePtr(holder, result);
97 return result;
98 }
99 return {};
100}
101
103{
104}
105
107{
108 return true;
109}
110
113{
114 // change note track to zoom like audio track
115 // mpTrack->StartVScroll();
116
118}
119
121(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
122{
123 using namespace RefreshCode;
124 auto pTrack = TrackList::Get( *pProject ).Lock(mpTrack);
125 if (!pTrack)
126 return Cancelled;
127
128 const wxMouseEvent &event = evt.event;
129 mZoomEnd = event.m_y;
131 // changed Note track to work like audio track
132 // pTrack->VScroll(mZoomStart, mZoomEnd);
133 return RefreshAll;
134 }
135 return RefreshNone;
136}
137
140{
141 return HitPreview(st.state);
142}
143
144enum {
152
154
157};
159// Table class
160
162 : public PopupMenuTable
163 , private PrefsListener
164{
166 : PopupMenuTable{ "NoteTrackVRuler" }
167 {};
170
171public:
173
174protected:
175 enum {
176// Note that these can be with or without spectrum view which
177// adds a constant.
178//const int kZoom1to1 = 1;
179//const int kZoomTimes2 = 2;
180//const int kZoomDiv2 = 3;
181//const int kZoomHalfWave = 4;
182//const int kZoomInByDrag = 5;
189 };
190
191 InitMenuData *mpData {};
192 void OnZoom( int iZoomCode );
193// void OnZoomFitVertical(wxCommandEvent&){ OnZoom( kZoom1to1 );};
194 void OnZoomReset(wxCommandEvent&){ OnZoom( kZoomReset );};
195// void OnZoomDiv2Vertical(wxCommandEvent&){ OnZoom( kZoomDiv2 );};
196// void OnZoomTimes2Vertical(wxCommandEvent&){ OnZoom( kZoomTimes2 );};
197// void OnZoomHalfWave(wxCommandEvent&){ OnZoom( kZoomHalfWave );};
198 void OnZoomInVertical(wxCommandEvent&){ OnZoom( kZoomIn );};
199 void OnZoomOutVertical(wxCommandEvent&){ OnZoom( kZoomOut );};
200 void OnZoomMax(wxCommandEvent&){ OnZoom( kZoomMax );};
201 void OnUpOctave(wxCommandEvent&){ OnZoom( kUpOctave );};
202 void OnDownOctave(wxCommandEvent&){ OnZoom( kDownOctave );};
203
204private:
205 void InitUserData(void *pUserData) override;
206
207 void UpdatePrefs() override
208 {
209 // Because labels depend on advanced vertical zoom setting
211 }
212};
213
215{
216 static NoteTrackVRulerMenuTable instance;
217 return instance;
218}
219
221{
222 mpData = static_cast<InitMenuData*>(pUserData);
223}
224
226 switch( iZoomCode ){
227 case kZoomReset:
228 mpData->pTrack->ZoomAllNotes();
229 break;
230 case kZoomIn:
231 mpData->pTrack->ZoomIn(mpData->rect, mpData->yy);
232 break;
233 case kZoomOut:
234 mpData->pTrack->ZoomOut(mpData->rect, mpData->yy);
235 break;
236 case kZoomMax:
237 mpData->pTrack->ZoomMaxExtent();
238 break;
239 case kUpOctave:
240 mpData->pTrack->ShiftNoteRange(12);
241 break;
242 case kDownOctave:
243 mpData->pTrack->ShiftNoteRange(-12);
244 break;
245 }
246 AudacityProject *const project = &mpData->project;
247 ProjectHistory::Get( *project ).ModifyState(false);
248 using namespace RefreshCode;
249 mpData->result = UpdateVRuler | RefreshAll;
250}
251
252
254
255 // Accelerators only if zooming enabled.
256 bool bVZoom;
257 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
258
259 BeginSection( "Zoom" );
260 BeginSection( "Basic" );
262 MakeLabel( XXO("Zoom Reset"), bVZoom, XXO("Shift-Right-Click")),
263 POPUP_MENU_FN( OnZoomReset ) );
264 AppendItem( "Max", OnZoomMaxID, XXO("Max Zoom"), POPUP_MENU_FN( OnZoomMax ) );
266
267 BeginSection( "InOut" );
269 MakeLabel( XXO("Zoom In"), bVZoom, XXO("Left-Click/Left-Drag") ),
270 POPUP_MENU_FN( OnZoomInVertical ) );
272 MakeLabel( XXO("Zoom Out"), bVZoom, XXO("Shift-Left-Click") ),
273 POPUP_MENU_FN( OnZoomOutVertical ) );
274 EndSection();
275 EndSection();
276
277 BeginSection( "Pan" );
278 BeginSection( "Octaves" );
279 AppendItem( "Up", OnUpOctaveID, XXO("Up &Octave"), POPUP_MENU_FN( OnUpOctave) );
280 AppendItem( "Down", OnDownOctaveID, XXO("Down Octa&ve"), POPUP_MENU_FN( OnDownOctave ) );
281 EndSection();
282 EndSection();
283
285
286
287
289(const TrackPanelMouseEvent &evt, AudacityProject *pProject,
290 wxWindow *pParent)
291{
292 using namespace RefreshCode;
293 auto pTrack = TrackList::Get( *pProject ).Lock(mpTrack);
294 if (!pTrack)
295 return RefreshNone;
296
297 const wxMouseEvent &event = evt.event;
298 //const bool shiftDown = event.ShiftDown();
299 const bool rightUp = event.RightUp();
300
301
302 // Popup menu...
303 if (
304 rightUp &&
305 !(event.ShiftDown() || event.CmdDown()))
306 {
307 InitMenuData data {
308 *pProject, pTrack.get(), mRect, RefreshNone, event.m_y
309 };
310
311 PopupMenuTable *const pTable =
313 auto pMenu = PopupMenuTable::BuildMenu(pTable, &data);
314
315 pMenu->Popup( *pParent, { event.m_x, event.m_y } );
316
317 return data.result;
318 }
319
320 bool bVZoom;
321 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
322 bVZoom &= event.GetId() != kCaptureLostEventId;
323 if( !bVZoom )
324 return RefreshAll;
325
326 if (IsDragZooming(mZoomStart, mZoomEnd)) {
327 pTrack->ZoomTo(evt.rect, mZoomStart, mZoomEnd);
328 }
329 else if (event.ShiftDown() || event.RightUp()) {
330 if (event.ShiftDown() && event.RightUp()) {
331 auto oldBotNote = pTrack->GetBottomNote();
332 auto oldTopNote = pTrack->GetTopNote();
333 // Zoom out to show all notes
334 pTrack->ZoomAllNotes();
335 if (pTrack->GetBottomNote() == oldBotNote &&
336 pTrack->GetTopNote() == oldTopNote) {
337 // However if we are already showing all notes, zoom out further
338 pTrack->ZoomMaxExtent();
339 }
340 } else {
341 // Zoom out
342 pTrack->ZoomOut(evt.rect, mZoomEnd);
343 }
344 }
345 else {
346 pTrack->ZoomIn(evt.rect, mZoomEnd);
347 }
348
349 mZoomEnd = mZoomStart = 0;
350 ProjectHistory::Get( *pProject ).ModifyState(false);
351
352 return RefreshAll;
353}
354
356{
357 // Cancel is implemented! And there is no initial state to restore,
358 // so just return a code.
360}
361
364 const wxRect &rect, unsigned iPass )
365{
366 if ( iPass == TrackArtist::PassZooming ) {
367 if (!mpTrack.lock()) //? TrackList::Lock()
368 return;
369
372 ( context, rect, mZoomStart, mZoomEnd );
373 }
374}
375
378 const wxRect &rect, const wxRect &panelRect, unsigned iPass )
379{
380 if ( iPass == TrackArtist::PassZooming )
381 return TrackVRulerControls::ZoomingArea( rect, panelRect );
382 else
383 return rect;
384}
385
386#endif
wxT("CloseDown"))
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
@ OnZoomTimes2ID
@ OnZoomOutVerticalID
@ OnZoomFitVerticalID
@ OnZoomHalfWaveID
@ OnDownOctaveID
@ OnZoomInVerticalID
gPrefs Read(wxT("/GUI/VerticalZooming"), &bVZoom, false)
EndSection()
BeginSection("Zoom")
bool bVZoom
AppendItem("Reset", OnZoomResetID, MakeLabel(XXO("Zoom Reset"), bVZoom, XXO("Shift-Right-Click")), POPUP_MENU_FN(OnZoomReset))
#define END_POPUP_MENU()
#define BEGIN_POPUP_MENU(HandlerClass)
#define POPUP_MENU_FN(memFn)
FileConfig * gPrefs
Definition: Prefs.cpp:70
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
Definition: TrackPanel.cpp:185
const int DragThreshold
Definition: TrackPanel.h:59
const int kCaptureLostEventId
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
Definition: UIHandle.h:151
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:63
void OnZoomInVertical(wxCommandEvent &)
void OnDownOctave(wxCommandEvent &)
void OnZoomOutVertical(wxCommandEvent &)
void OnUpOctave(wxCommandEvent &)
void InitUserData(void *pUserData) override
Called before the menu items are appended.
void OnZoomReset(wxCommandEvent &)
void OnZoomMax(wxCommandEvent &)
static NoteTrackVRulerMenuTable & Instance()
DECLARE_POPUP_MENU(NoteTrackVRulerMenuTable)
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
NoteTrackVZoomHandle(const NoteTrackVZoomHandle &)
std::weak_ptr< NoteTrack > mpTrack
wxRect DrawingArea(TrackPanelDrawingContext &, const wxRect &rect, const wxRect &panelRect, unsigned iPass) override
static HitTestPreview HitPreview(const wxMouseState &state)
Result Cancel(AudacityProject *pProject) override
bool HandlesRightClick() override
Whether the handle has any special right-button handling.
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
void Enter(bool forward, AudacityProject *) override
static UIHandlePtr HitTest(std::weak_ptr< NoteTrackVZoomHandle > &holder, const wxMouseState &state, const std::shared_ptr< NoteTrack > &pTrack, const wxRect &rect)
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
static std::unique_ptr< PopupMenu > BuildMenu(PopupMenuTable *pTable, void *pUserData=NULL)
A listener notified of changes in preferences.
Definition: Prefs.h:556
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1603
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:486
static void DrawZooming(TrackPanelDrawingContext &context, const wxRect &rect, int zoomStart, int zoomEnd)
static wxRect ZoomingArea(const wxRect &rect, const wxRect &panelRect)
Short-lived drawing and event-handling object associated with a TrackPanelCell.
Definition: UIHandle.h:35
Result mChangeHighlight
Definition: UIHandle.h:139
unsigned Result
Definition: UIHandle.h:38
void Release(wxWindow *handler)
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
bool IsDragZooming(int zoomStart, int zoomEnd)