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
15
16#include "../../../ui/ChannelVRulerControls.h"
17
18#include "../../../../HitTestResult.h"
19#include "NoteTrack.h"
20#include "Project.h"
21#include "ProjectHistory.h"
22#include "../../../../RefreshCode.h"
23#include "../../../../TrackArtist.h"
24#include "../../../../TrackPanelMouseEvent.h"
25#include "../../../../widgets/PopupMenuTable.h"
26#include "../../../../../images/Cursors.h"
27#include "Prefs.h"
28
29namespace
30{
31
33 {
34 public:
37 wxRect rect;
38 unsigned result;
39 int yy;
40 };
41
42 bool IsDragZooming(int zoomStart, int zoomEnd)
43 {
44 const int DragThreshold = 3;// Anything over 3 pixels is a drag, else a click.
45 bool bVZoom;
46 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
47 return bVZoom && (abs(zoomEnd - zoomStart) > DragThreshold);
48 }
49
50}
51
53
55(const std::shared_ptr<NoteTrack> &pTrack, const wxRect &rect, int y)
56 : mpTrack{ pTrack } , mZoomStart(y), mZoomEnd(y), mRect(rect)
57{
58}
59
61{
62#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
64#endif
65}
66
68{
69 static auto zoomInCursor =
70 ::MakeCursor(wxCURSOR_MAGNIFIER, ZoomInCursorXpm, 19, 15);
71 static auto zoomOutCursor =
72 ::MakeCursor(wxCURSOR_MAGNIFIER, ZoomOutCursorXpm, 19, 15);
73 static wxCursor arrowCursor{ wxCURSOR_ARROW };
74
75 bool bVZoom;
76 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
77 bVZoom &= !state.RightIsDown();
78 const auto message = bVZoom ?
79 XO("Click to vertically zoom in. Shift-click to zoom out. Drag to specify a zoom region.") :
80 XO("Right-click for menu.");
81
82 return {
83 message,
84 bVZoom ? (state.ShiftDown() ? &*zoomOutCursor : &*zoomInCursor) : &arrowCursor
85 // , message
86 };
87}
88
90(std::weak_ptr<NoteTrackVZoomHandle> &holder,
91 const wxMouseState &state,
92 const std::shared_ptr<NoteTrack> &pTrack, const wxRect &rect)
93{
94 if (pTrack) {
95 auto result = std::make_shared<NoteTrackVZoomHandle>(
96 pTrack, rect, state.m_y);
97 result = AssignUIHandlePtr(holder, result);
98 return result;
99 }
100 return {};
101}
102
104{
105}
106
107std::shared_ptr<const Channel> NoteTrackVZoomHandle::FindChannel() const
108{
109 return mpTrack.lock();
110}
111
113{
114 return true;
115}
116
119{
120 // change note track to zoom like audio track
121 // mpTrack->StartVScroll();
122
124}
125
127(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
128{
129 using namespace RefreshCode;
130 auto pTrack = TrackList::Get( *pProject ).Lock(mpTrack);
131 if (!pTrack)
132 return Cancelled;
133
134 const wxMouseEvent &event = evt.event;
135 mZoomEnd = event.m_y;
137 // changed Note track to work like audio track
138 // pTrack->VScroll(mZoomStart, mZoomEnd);
139 return RefreshAll;
140 }
141 return RefreshNone;
142}
143
146{
147 return HitPreview(st.state);
148}
149
150enum {
158
160
163};
165// Table class
166
168 : public PopupMenuTable
169 , private PrefsListener
170{
172 : PopupMenuTable{ "NoteTrackVRuler" }
173 {};
176
177public:
179
180protected:
181 enum {
182// Note that these can be with or without spectrum view which
183// adds a constant.
184//const int kZoom1to1 = 1;
185//const int kZoomTimes2 = 2;
186//const int kZoomDiv2 = 3;
187//const int kZoomHalfWave = 4;
188//const int kZoomInByDrag = 5;
195 };
196
197 InitMenuData *mpData {};
198 void OnZoom( int iZoomCode );
199// void OnZoomFitVertical(wxCommandEvent&){ OnZoom( kZoom1to1 );};
200 void OnZoomReset(wxCommandEvent&){ OnZoom( kZoomReset );};
201// void OnZoomDiv2Vertical(wxCommandEvent&){ OnZoom( kZoomDiv2 );};
202// void OnZoomTimes2Vertical(wxCommandEvent&){ OnZoom( kZoomTimes2 );};
203// void OnZoomHalfWave(wxCommandEvent&){ OnZoom( kZoomHalfWave );};
204 void OnZoomInVertical(wxCommandEvent&){ OnZoom( kZoomIn );};
205 void OnZoomOutVertical(wxCommandEvent&){ OnZoom( kZoomOut );};
206 void OnZoomMax(wxCommandEvent&){ OnZoom( kZoomMax );};
207 void OnUpOctave(wxCommandEvent&){ OnZoom( kUpOctave );};
208 void OnDownOctave(wxCommandEvent&){ OnZoom( kDownOctave );};
209
210private:
211 void InitUserData(void *pUserData) override;
212
213 void UpdatePrefs() override
214 {
215 // Because labels depend on advanced vertical zoom setting
217 }
218};
219
221{
222 static NoteTrackVRulerMenuTable instance;
223 return instance;
224}
225
227{
228 mpData = static_cast<InitMenuData*>(pUserData);
229}
230
232 auto &data = NoteTrackRange::Get(*mpData->pTrack);
233 switch( iZoomCode ){
234 case kZoomReset:
235 data.ZoomAllNotes(&mpData->pTrack->GetSeq());
236 break;
237 case kZoomIn:
238 NoteTrackDisplayData{ *mpData->pTrack, mpData->rect }.ZoomIn(mpData->yy);
239 break;
240 case kZoomOut:
241 NoteTrackDisplayData{ *mpData->pTrack, mpData->rect }.ZoomOut(mpData->yy);
242 break;
243 case kZoomMax:
244 data.ZoomMaxExtent();
245 break;
246 case kUpOctave:
247 data.ShiftNoteRange(12);
248 break;
249 case kDownOctave:
250 data.ShiftNoteRange(-12);
251 break;
252 }
253 AudacityProject *const project = &mpData->project;
254 ProjectHistory::Get( *project ).ModifyState(false);
255 using namespace RefreshCode;
256 mpData->result = UpdateVRuler | RefreshAll;
257}
258
259
261
262 // Accelerators only if zooming enabled.
263 bool bVZoom;
264 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
265
266 BeginSection( "Zoom" );
267 BeginSection( "Basic" );
269 MakeLabel( XXO("Zoom Reset"), bVZoom, XXO("Shift-Right-Click")),
270 POPUP_MENU_FN( OnZoomReset ) );
271 AppendItem( "Max", OnZoomMaxID, XXO("Max Zoom"), POPUP_MENU_FN( OnZoomMax ) );
273
274 BeginSection( "InOut" );
276 MakeLabel( XXO("Zoom In"), bVZoom, XXO("Left-Click/Left-Drag") ),
277 POPUP_MENU_FN( OnZoomInVertical ) );
279 MakeLabel( XXO("Zoom Out"), bVZoom, XXO("Shift-Left-Click") ),
280 POPUP_MENU_FN( OnZoomOutVertical ) );
281 EndSection();
282 EndSection();
283
284 BeginSection( "Pan" );
285 BeginSection( "Octaves" );
286 AppendItem( "Up", OnUpOctaveID, XXO("Up &Octave"), POPUP_MENU_FN( OnUpOctave) );
287 AppendItem( "Down", OnDownOctaveID, XXO("Down Octa&ve"), POPUP_MENU_FN( OnDownOctave ) );
288 EndSection();
289 EndSection();
290
292
293
294
296(const TrackPanelMouseEvent &evt, AudacityProject *pProject,
297 wxWindow *pParent)
298{
299 using namespace RefreshCode;
300 auto pTrack = TrackList::Get( *pProject ).Lock(mpTrack);
301 if (!pTrack)
302 return RefreshNone;
303
304 const wxMouseEvent &event = evt.event;
305 //const bool shiftDown = event.ShiftDown();
306 const bool rightUp = event.RightUp();
307
308
309 // Popup menu...
310 if (
311 rightUp &&
312 !(event.ShiftDown() || event.CmdDown()))
313 {
314 InitMenuData data {
315 *pProject, pTrack.get(), mRect, RefreshNone, event.m_y
316 };
317
318 PopupMenuTable *const pTable =
320 auto pMenu = PopupMenuTable::BuildMenu(pTable, &data);
321
322 pMenu->Popup( *pParent, { event.m_x, event.m_y } );
323
324 return data.result;
325 }
326
327 bool bVZoom;
328 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
329 bVZoom &= event.GetId() != kCaptureLostEventId;
330 if( !bVZoom )
331 return RefreshAll;
332
333 NoteTrackDisplayData data{ *pTrack, evt.rect };
334 if (IsDragZooming(mZoomStart, mZoomEnd)) {
335 data.ZoomTo(mZoomStart, mZoomEnd);
336 }
337 else if (event.ShiftDown() || event.RightUp()) {
338 if (event.ShiftDown() && event.RightUp()) {
339 auto &data = NoteTrackRange::Get(*pTrack);
340 auto oldBotNote = data.GetBottomNote();
341 auto oldTopNote = data.GetTopNote();
342 // Zoom out to show all notes
343 data.ZoomAllNotes(&pTrack->GetSeq());
344 if (data.GetBottomNote() == oldBotNote &&
345 data.GetTopNote() == oldTopNote) {
346 // However if we are already showing all notes, zoom out further
347 data.ZoomMaxExtent();
348 }
349 } else {
350 // Zoom out
351 data.ZoomOut(mZoomEnd);
352 }
353 }
354 else {
355 data.ZoomIn(mZoomEnd);
356 }
357
358 mZoomEnd = mZoomStart = 0;
359 ProjectHistory::Get( *pProject ).ModifyState(false);
360
361 return RefreshAll;
362}
363
365{
366 // Cancel is implemented! And there is no initial state to restore,
367 // so just return a code.
369}
370
373 const wxRect &rect, unsigned iPass )
374{
375 if ( iPass == TrackArtist::PassZooming ) {
376 if (!mpTrack.lock()) //? TrackList::Lock()
377 return;
378
381 context, rect, mZoomStart, mZoomEnd);
382 }
383}
384
387 const wxRect &rect, const wxRect &panelRect, unsigned iPass )
388{
389 if ( iPass == TrackArtist::PassZooming )
390 return ChannelVRulerControls::ZoomingArea(rect, panelRect);
391 else
392 return rect;
393}
394
395#endif
wxT("CloseDown"))
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
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))
@ OnZoomTimes2ID
@ OnZoomOutVerticalID
@ OnZoomFitVerticalID
@ OnZoomHalfWaveID
@ OnDownOctaveID
@ OnZoomInVerticalID
#define END_POPUP_MENU()
#define BEGIN_POPUP_MENU(HandlerClass)
#define POPUP_MENU_FN(memFn)
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
const auto project
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
Definition: TrackPanel.cpp:188
const int DragThreshold
Definition: TrackPanel.h:57
const int kCaptureLostEventId
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
Definition: UIHandle.h:159
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static wxRect ZoomingArea(const wxRect &rect, const wxRect &panelRect)
static void DrawZooming(TrackPanelDrawingContext &context, const wxRect &rect, int zoomStart, int zoomEnd)
Temporary data used to display a note track.
void ZoomTo(int start, int end)
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:86
static NoteTrackRange & Get(const NoteTrack &track)
Allow mutative access to attached data of a const track.
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
std::shared_ptr< const Channel > FindChannel() const override
static std::unique_ptr< PopupMenu > BuildMenu(PopupMenuTable *pTable, void *pUserData=NULL)
A listener notified of changes in preferences.
Definition: Prefs.h:561
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1228
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:347
Short-lived drawing and event-handling object associated with a TrackPanelCell.
Definition: UIHandle.h:36
Result mChangeHighlight
Definition: UIHandle.h:147
unsigned Result
Definition: UIHandle.h:39
virtual bool Read(const wxString &key, bool *value) const =0
void Release(wxWindow *handler)
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
bool IsDragZooming(int zoomStart, int zoomEnd)