Audacity  2.2.2
NoteTrackVZoomHandle.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 NoteTrackVZoomHandle.cpp
6 
7 Paul Licameli split from TrackPanel.cpp
8 
9 **********************************************************************/
10 
11 #include "../../../../Audacity.h"
12 
13 #ifdef USE_MIDI
14 
15 #include "NoteTrackVZoomHandle.h"
16 #include "../../../../Experimental.h"
18 
19 #include "../../../../HitTestResult.h"
20 #include "../../../../NoteTrack.h"
21 #include "../../../../Project.h"
22 #include "../../../../RefreshCode.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 
30 namespace
31 {
32 
33  struct InitMenuData
34  {
35  public:
36  NoteTrack *pTrack;
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 
67 HitTestPreview NoteTrackVZoomHandle::HitPreview(const wxMouseState &state)
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  _("Click to vertically zoom in. Shift-click to zoom out. Drag to specify a zoom region.") :
80  _("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 
109 {
110  // change note track to zoom like audio track
111  // mpTrack->StartVScroll();
112 
114 }
115 
117 (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
118 {
119  using namespace RefreshCode;
120  auto pTrack = pProject->GetTracks()->Lock(mpTrack);
121  if (!pTrack)
122  return Cancelled;
123 
124  const wxMouseEvent &event = evt.event;
125  mZoomEnd = event.m_y;
126  if (IsDragZooming(mZoomStart, mZoomEnd)) {
127  // changed Note track to work like audio track
128  // pTrack->VScroll(mZoomStart, mZoomEnd);
129  return RefreshAll;
130  }
131  return RefreshNone;
132 }
133 
135 (const TrackPanelMouseState &st, const AudacityProject *)
136 {
137  return HitPreview(st.state);
138 }
139 
140 // Note that these can be with or without spectrum view which
141 // adds a constant.
142 //const int kZoom1to1 = 1;
143 //const int kZoomTimes2 = 2;
144 //const int kZoomDiv2 = 3;
145 //const int kZoomHalfWave = 4;
146 //const int kZoomInByDrag = 5;
147 const int kZoomIn = 6;
148 const int kZoomOut = 7;
149 const int kZoomReset = 8;
150 
151 enum {
152  OnZoomFitVerticalID = 20000,
154  OnZoomDiv2ID,
159 
160  // Reserve an ample block of ids for waveform scale types
162  OnLastWaveformScaleID = OnFirstWaveformScaleID + 9,
163 
164  // Reserve an ample block of ids for spectrum scale types
166  OnLastSpectrumScaleID = OnFirstSpectrumScaleID + 19,
167 };
169 // Table class
170 
171 class NoteTrackVRulerMenuTable : public PopupMenuTable
172 {
173  NoteTrackVRulerMenuTable(){};
174  virtual ~NoteTrackVRulerMenuTable() {}
175  DECLARE_POPUP_MENU(NoteTrackVRulerMenuTable);
176 
177 public:
178  static NoteTrackVRulerMenuTable &Instance();
179 
180 protected:
181  InitMenuData *mpData {};
182  void OnZoom( int iZoomCode );
183 // void OnZoomFitVertical(wxCommandEvent&){ OnZoom( kZoom1to1 );};
184  void OnZoomReset(wxCommandEvent&){ OnZoom( kZoomReset );};
185 // void OnZoomDiv2Vertical(wxCommandEvent&){ OnZoom( kZoomDiv2 );};
186 // void OnZoomTimes2Vertical(wxCommandEvent&){ OnZoom( kZoomTimes2 );};
187 // void OnZoomHalfWave(wxCommandEvent&){ OnZoom( kZoomHalfWave );};
188  void OnZoomInVertical(wxCommandEvent&){ OnZoom( kZoomIn );};
189  void OnZoomOutVertical(wxCommandEvent&){ OnZoom( kZoomOut );};
190 
191 private:
192  void DestroyMenu() override
193  {
194  mpData = nullptr;
195  }
196 
197  virtual void InitMenu(Menu *pMenu, void *pUserData) override;
198 
199  void OnWaveformScaleType(wxCommandEvent &evt);
200 };
201 
202 NoteTrackVRulerMenuTable &NoteTrackVRulerMenuTable::Instance()
203 {
204  static NoteTrackVRulerMenuTable instance;
205  return instance;
206 }
207 
208 void NoteTrackVRulerMenuTable::InitMenu(Menu *WXUNUSED(pMenu), void *pUserData)
209 {
210  mpData = static_cast<InitMenuData*>(pUserData);
211 }
212 
213 void NoteTrackVRulerMenuTable::OnZoom( int iZoomCode ){
214  switch( iZoomCode ){
215  case kZoomReset:
216  mpData->pTrack->SetBottomNote(0);
217  mpData->pTrack->SetPitchHeight(mpData->rect.height, 1);
218  break;
219  case kZoomIn:
220  mpData->pTrack->ZoomIn(mpData->rect, mpData->yy);
221  break;
222  case kZoomOut:
223  mpData->pTrack->ZoomOut(mpData->rect, mpData->yy);
224  break;
225 
226  }
227 }
228 
229 
230 BEGIN_POPUP_MENU(NoteTrackVRulerMenuTable)
231 
232  POPUP_MENU_ITEM(OnZoomResetID, _("Zoom Reset\tShift-Right-Click"), OnZoomReset)
233 
235  POPUP_MENU_ITEM(OnZoomInVerticalID, _("Zoom In\tLeft-Click/Left-Drag"), OnZoomInVertical)
236  POPUP_MENU_ITEM(OnZoomOutVerticalID, _("Zoom Out\tShift-Left-Click"), OnZoomOutVertical)
237 
239 
240 
241 
243 (const TrackPanelMouseEvent &evt, AudacityProject *pProject,
244  wxWindow *pParent)
245 {
246  using namespace RefreshCode;
247  auto pTrack = pProject->GetTracks()->Lock(mpTrack);
248  if (!pTrack)
249  return RefreshNone;
250 
251  const wxMouseEvent &event = evt.event;
252  //const bool shiftDown = event.ShiftDown();
253  const bool rightUp = event.RightUp();
254 
255 
256  bool bVZoom;
257  gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
258 
259  // Popup menu...
260  if (
261  rightUp &&
262  !(event.ShiftDown() || event.CmdDown()))
263  {
264  InitMenuData data {
265  pTrack.get(), mRect, RefreshCode::RefreshNone, event.m_y
266  };
267 
268  PopupMenuTable *const pTable =
269  (PopupMenuTable *) &NoteTrackVRulerMenuTable::Instance();
270  std::unique_ptr<PopupMenuTable::Menu>
271  pMenu(PopupMenuTable::BuildMenu(pParent, pTable, &data));
272 
273  // Accelerators only if zooming enabled.
274  if( !bVZoom )
275  {
276  wxMenuItemList & L = pMenu->GetMenuItems();
277  // let's iterate over the list in STL syntax
278  wxMenuItemList::iterator iter;
279  for (iter = L.begin(); iter != L.end(); ++iter)
280  {
281  wxMenuItem *pItem = *iter;
282  // Remove accelerator, if any.
283  pItem->SetItemLabel( (pItem->GetItemLabel() + "\t" ).BeforeFirst('\t') );
284  }
285  }
286 
287  pParent->PopupMenu(pMenu.get(), event.m_x, event.m_y);
288 
289  return data.result;
290  }
291 
292  bVZoom &= event.GetId() != kCaptureLostEventId;
293  if( !bVZoom )
294  return RefreshAll;
295 
296  if (IsDragZooming(mZoomStart, mZoomEnd)) {
297  pTrack->ZoomTo(evt.rect, mZoomStart, mZoomEnd);
298  }
299  else if (event.ShiftDown() || event.RightUp()) {
300  if (event.ShiftDown() && event.RightUp()) {
301  // Zoom out completely
302  pTrack->SetBottomNote(0);
303  pTrack->SetPitchHeight(evt.rect.height, 1);
304  } else {
305  // Zoom out
306  pTrack->ZoomOut(evt.rect, mZoomEnd);
307  }
308  }
309  else {
310  pTrack->ZoomIn(evt.rect, mZoomEnd);
311  }
312 
313  mZoomEnd = mZoomStart = 0;
314  pProject->ModifyState(true);
315 
316  return RefreshAll;
317 }
318 
320 {
321  // Cancel is implemented! And there is no initial state to restore,
322  // so just return a code.
324 }
325 
327 (DrawingPass pass, wxDC * dc, const wxRegion &, const wxRect &panelRect)
328 {
329  if (!mpTrack.lock()) //? TrackList::Lock()
330  return;
331 
332  if ( pass == UIHandle::Cells &&
333  IsDragZooming( mZoomStart, mZoomEnd ) )
335  ( dc, mRect, panelRect, mZoomStart, mZoomEnd );
336 }
337 
338 #endif
void Enter(bool forward) override
#define POPUP_MENU_SEPARATOR()
AudacityPrefs * gPrefs
Definition: Prefs.cpp:73
NoteTrackVZoomHandle(const NoteTrackVZoomHandle &)
const int DragThreshold
Definition: TrackPanel.h:242
#define END_POPUP_MENU()
std::weak_ptr< NoteTrack > mpTrack
Result mChangeHighlight
Definition: UIHandle.h:150
static UIHandlePtr HitTest(std::weak_ptr< NoteTrackVZoomHandle > &holder, const wxMouseState &state, const std::shared_ptr< NoteTrack > &pTrack, const wxRect &rect)
static HitTestPreview HitPreview(const wxMouseState &state)
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:176
const int kZoomOut
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
unsigned Result
Definition: UIHandle.h:37
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
static std::unique_ptr< Menu > BuildMenu(wxEvtHandler *pParent, PopupMenuTable *pTable, void *pUserData=NULL)
#define DECLARE_POPUP_MENU(HandlerClass)
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:733
std::shared_ptr< UIHandle > UIHandlePtr
Definition: TrackPanel.h:59
Result Cancel(AudacityProject *pProject) override
HitTestPreview Preview(const TrackPanelMouseState &state, const AudacityProject *pProject) override
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
void DrawExtras(DrawingPass pass, wxDC *dc, const wxRegion &updateRegion, const wxRect &panelRect) override
POPUP_MENU_ITEM(OnMoveUpID, _("Move Track &Up")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveUp")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveDownID
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
Definition: TrackPanel.cpp:274
const int kZoomReset
const int kCaptureLostEventId
TrackList * GetTracks()
Definition: Project.h:192
virtual ~NoteTrackVZoomHandle()
const int kZoomIn
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
Definition: UIHandle.h:162
static void DrawZooming(wxDC *dc, const wxRect &cellRect, const wxRect &panelRect, int zoomStart, int zoomEnd)
DrawingPass
Definition: UIHandle.h:43
BEGIN_POPUP_MENU(SpectrumVRulerMenuTable)
A Track that is used for Midi notes. (Somewhat old code).