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
28#include <wx/event.h>
29
30namespace
31{
32
34 {
35 public:
38 wxRect rect;
39 unsigned result;
40 int yy;
41 };
42
43 bool IsDragZooming(int zoomStart, int zoomEnd)
44 {
45 const int DragThreshold = 3;// Anything over 3 pixels is a drag, else a click.
46 bool bVZoom;
47 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
48 return bVZoom && (abs(zoomEnd - zoomStart) > DragThreshold);
49 }
50
51}
52
54
56(const std::shared_ptr<NoteTrack> &pTrack, const wxRect &rect, int y)
57 : mpTrack{ pTrack } , mZoomStart(y), mZoomEnd(y), mRect(rect)
58{
59}
60
62{
63#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
65#endif
66}
67
69{
70 static auto zoomInCursor =
71 ::MakeCursor(wxCURSOR_MAGNIFIER, ZoomInCursorXpm, 19, 15);
72 static auto zoomOutCursor =
73 ::MakeCursor(wxCURSOR_MAGNIFIER, ZoomOutCursorXpm, 19, 15);
74 static wxCursor arrowCursor{ wxCURSOR_ARROW };
75
76 bool bVZoom;
77 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
78 bVZoom &= !state.RightIsDown();
79 const auto message = bVZoom ?
80 XO("Click to vertically zoom in. Shift-click to zoom out. Drag to specify a zoom region.") :
81 XO("Right-click for menu.");
82
83 return {
84 message,
85 bVZoom ? (state.ShiftDown() ? &*zoomOutCursor : &*zoomInCursor) : &arrowCursor
86 // , message
87 };
88}
89
91(std::weak_ptr<NoteTrackVZoomHandle> &holder,
92 const wxMouseState &state,
93 const std::shared_ptr<NoteTrack> &pTrack, const wxRect &rect)
94{
95 if (pTrack) {
96 auto result = std::make_shared<NoteTrackVZoomHandle>(
97 pTrack, rect, state.m_y);
98 result = AssignUIHandlePtr(holder, result);
99 return result;
100 }
101 return {};
102}
103
105{
106}
107
109{
110 return true;
111}
112
115{
116 // change note track to zoom like audio track
117 // mpTrack->StartVScroll();
118
120}
121
123(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
124{
125 using namespace RefreshCode;
126 auto pTrack = TrackList::Get( *pProject ).Lock(mpTrack);
127 if (!pTrack)
128 return Cancelled;
129
130 const wxMouseEvent &event = evt.event;
131 mZoomEnd = event.m_y;
133 // changed Note track to work like audio track
134 // pTrack->VScroll(mZoomStart, mZoomEnd);
135 return RefreshAll;
136 }
137 return RefreshNone;
138}
139
142{
143 return HitPreview(st.state);
144}
145
146enum {
154
156
159};
161// Table class
162
164 : public PopupMenuTable
165 , private PrefsListener
166{
168 : PopupMenuTable{ "NoteTrackVRuler" }
169 {};
172
173public:
175
176protected:
177 enum {
178// Note that these can be with or without spectrum view which
179// adds a constant.
180//const int kZoom1to1 = 1;
181//const int kZoomTimes2 = 2;
182//const int kZoomDiv2 = 3;
183//const int kZoomHalfWave = 4;
184//const int kZoomInByDrag = 5;
191 };
192
193 InitMenuData *mpData {};
194 void OnZoom( int iZoomCode );
195// void OnZoomFitVertical(wxCommandEvent&){ OnZoom( kZoom1to1 );};
196 void OnZoomReset(wxCommandEvent&){ OnZoom( kZoomReset );};
197// void OnZoomDiv2Vertical(wxCommandEvent&){ OnZoom( kZoomDiv2 );};
198// void OnZoomTimes2Vertical(wxCommandEvent&){ OnZoom( kZoomTimes2 );};
199// void OnZoomHalfWave(wxCommandEvent&){ OnZoom( kZoomHalfWave );};
200 void OnZoomInVertical(wxCommandEvent&){ OnZoom( kZoomIn );};
201 void OnZoomOutVertical(wxCommandEvent&){ OnZoom( kZoomOut );};
202 void OnZoomMax(wxCommandEvent&){ OnZoom( kZoomMax );};
203 void OnUpOctave(wxCommandEvent&){ OnZoom( kUpOctave );};
204 void OnDownOctave(wxCommandEvent&){ OnZoom( kDownOctave );};
205
206private:
207 void InitUserData(void *pUserData) override;
208
209 void UpdatePrefs() override
210 {
211 // Because labels depend on advanced vertical zoom setting
213 }
214};
215
217{
218 static NoteTrackVRulerMenuTable instance;
219 return instance;
220}
221
223{
224 mpData = static_cast<InitMenuData*>(pUserData);
225}
226
228 switch( iZoomCode ){
229 case kZoomReset:
230 mpData->pTrack->ZoomAllNotes();
231 break;
232 case kZoomIn:
233 mpData->pTrack->ZoomIn(mpData->rect, mpData->yy);
234 break;
235 case kZoomOut:
236 mpData->pTrack->ZoomOut(mpData->rect, mpData->yy);
237 break;
238 case kZoomMax:
239 mpData->pTrack->ZoomMaxExtent();
240 break;
241 case kUpOctave:
242 mpData->pTrack->ShiftNoteRange(12);
243 break;
244 case kDownOctave:
245 mpData->pTrack->ShiftNoteRange(-12);
246 break;
247 }
248 AudacityProject *const project = &mpData->project;
249 ProjectHistory::Get( *project ).ModifyState(false);
250 using namespace RefreshCode;
251 mpData->result = UpdateVRuler | RefreshAll;
252}
253
254
256
257 // Accelerators only if zooming enabled.
258 bool bVZoom;
259 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
260
261 BeginSection( "Zoom" );
262 BeginSection( "Basic" );
264 MakeLabel( XXO("Zoom Reset"), bVZoom, XXO("Shift-Right-Click")),
265 POPUP_MENU_FN( OnZoomReset ) );
266 AppendItem( "Max", OnZoomMaxID, XXO("Max Zoom"), POPUP_MENU_FN( OnZoomMax ) );
268
269 BeginSection( "InOut" );
271 MakeLabel( XXO("Zoom In"), bVZoom, XXO("Left-Click/Left-Drag") ),
272 POPUP_MENU_FN( OnZoomInVertical ) );
274 MakeLabel( XXO("Zoom Out"), bVZoom, XXO("Shift-Left-Click") ),
275 POPUP_MENU_FN( OnZoomOutVertical ) );
276 EndSection();
277 EndSection();
278
279 BeginSection( "Pan" );
280 BeginSection( "Octaves" );
281 AppendItem( "Up", OnUpOctaveID, XXO("Up &Octave"), POPUP_MENU_FN( OnUpOctave) );
282 AppendItem( "Down", OnDownOctaveID, XXO("Down Octa&ve"), POPUP_MENU_FN( OnDownOctave ) );
283 EndSection();
284 EndSection();
285
287
288
289
291(const TrackPanelMouseEvent &evt, AudacityProject *pProject,
292 wxWindow *pParent)
293{
294 using namespace RefreshCode;
295 auto pTrack = TrackList::Get( *pProject ).Lock(mpTrack);
296 if (!pTrack)
297 return RefreshNone;
298
299 const wxMouseEvent &event = evt.event;
300 //const bool shiftDown = event.ShiftDown();
301 const bool rightUp = event.RightUp();
302
303
304 // Popup menu...
305 if (
306 rightUp &&
307 !(event.ShiftDown() || event.CmdDown()))
308 {
309 InitMenuData data {
310 *pProject, pTrack.get(), mRect, RefreshNone, event.m_y
311 };
312
313 PopupMenuTable *const pTable =
315 auto pMenu = PopupMenuTable::BuildMenu(pTable, &data);
316
317 pMenu->Popup( *pParent, { event.m_x, event.m_y } );
318
319 return data.result;
320 }
321
322 bool bVZoom;
323 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
324 bVZoom &= event.GetId() != kCaptureLostEventId;
325 if( !bVZoom )
326 return RefreshAll;
327
328 if (IsDragZooming(mZoomStart, mZoomEnd)) {
329 pTrack->ZoomTo(evt.rect, mZoomStart, mZoomEnd);
330 }
331 else if (event.ShiftDown() || event.RightUp()) {
332 if (event.ShiftDown() && event.RightUp()) {
333 auto oldBotNote = pTrack->GetBottomNote();
334 auto oldTopNote = pTrack->GetTopNote();
335 // Zoom out to show all notes
336 pTrack->ZoomAllNotes();
337 if (pTrack->GetBottomNote() == oldBotNote &&
338 pTrack->GetTopNote() == oldTopNote) {
339 // However if we are already showing all notes, zoom out further
340 pTrack->ZoomMaxExtent();
341 }
342 } else {
343 // Zoom out
344 pTrack->ZoomOut(evt.rect, mZoomEnd);
345 }
346 }
347 else {
348 pTrack->ZoomIn(evt.rect, mZoomEnd);
349 }
350
351 mZoomEnd = mZoomStart = 0;
352 ProjectHistory::Get( *pProject ).ModifyState(false);
353
354 return RefreshAll;
355}
356
358{
359 // Cancel is implemented! And there is no initial state to restore,
360 // so just return a code.
362}
363
366 const wxRect &rect, unsigned iPass )
367{
368 if ( iPass == TrackArtist::PassZooming ) {
369 if (!mpTrack.lock()) //? TrackList::Lock()
370 return;
371
374 ( context, rect, mZoomStart, mZoomEnd );
375 }
376}
377
380 const wxRect &rect, const wxRect &panelRect, unsigned iPass )
381{
382 if ( iPass == TrackArtist::PassZooming )
383 return TrackVRulerControls::ZoomingArea( rect, panelRect );
384 else
385 return rect;
386}
387
388#endif
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
gPrefs Read(wxT("/GUI/VerticalZooming"), &bVZoom, false)
EndSection()
BeginSection("Zoom")
bool bVZoom
@ OnZoomTimes2ID
@ OnZoomOutVerticalID
@ OnZoomFitVerticalID
@ OnZoomHalfWaveID
@ OnDownOctaveID
@ OnZoomInVerticalID
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:71
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:89
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:543
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1601
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)