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