Audacity  3.0.3
WaveformVZoomHandle.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 WaveformVZoomHandle.cpp
6 
7 Paul Licameli split from WaveTrackVZoomHandle.cpp
8 
9 **********************************************************************/
10 
11 
12 #include "WaveformVZoomHandle.h"
13 
14 #include "WaveTrackVZoomHandle.h"
15 
16 #include "../../../../HitTestResult.h"
17 #include "NumberScale.h"
18 #include "Prefs.h"
19 #include "../../../../ProjectHistory.h"
20 #include "../../../../RefreshCode.h"
21 #include "../../../../TrackPanelMouseEvent.h"
22 #include "../../../../WaveTrack.h"
23 #include "../../../../prefs/WaveformSettings.h"
24 
26  const std::shared_ptr<WaveTrack> &pTrack, const wxRect &rect, int y)
27  : mpTrack{ pTrack } , mZoomStart(y), mZoomEnd(y), mRect(rect)
28 {
29 }
30 
32 
34 {
35 #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
37 #endif
38 }
39 
41 {
42  return true;
43 }
44 
47 {
49 }
50 
52 (const TrackPanelMouseEvent &evt, AudacityProject *pProject)
53 {
54  using namespace RefreshCode;
55  auto pTrack = TrackList::Get( *pProject ).Lock(mpTrack);
56  if (!pTrack)
57  return Cancelled;
58  return WaveTrackVZoomHandle::DoDrag( evt, pProject, mZoomStart, mZoomEnd );
59 }
60 
63 {
65 }
66 
68 (const TrackPanelMouseEvent &evt, AudacityProject *pProject,
69  wxWindow *pParent)
70 {
71  auto pTrack = TrackList::Get( *pProject ).Lock(mpTrack);
73  evt, pProject, pParent, pTrack.get(), mRect,
76 }
77 
79 {
80  // Cancel is implemented! And there is no initial state to restore,
81  // so just return a code.
83 }
84 
86  TrackPanelDrawingContext &context,
87  const wxRect &rect, unsigned iPass )
88 {
89  if (!mpTrack.lock()) //? TrackList::Lock()
90  return;
92  context, rect, iPass, mZoomStart, mZoomEnd );
93 }
94 
97  const wxRect &rect, const wxRect &panelRect, unsigned iPass )
98 {
99  return WaveTrackVZoomHandle::DoDrawingArea( rect, panelRect, iPass );
100 }
101 
102 // ZoomKind says how to zoom.
103 // If ZoomStart and ZoomEnd are not equal, this may override
104 // the zoomKind and cause a drag-zoom-in.
106  AudacityProject *pProject,
107  WaveTrack *pTrack,
109  const wxRect &rect, int zoomStart, int zoomEnd,
110  bool fixedMousePoint)
111 {
112  using namespace WaveTrackViewConstants;
113  static const float ZOOMLIMIT = 0.001f;
114 
115  int height = rect.height;
116  int ypos = rect.y;
117 
118  // Ensure start and end are in order (swap if not).
119  if (zoomEnd < zoomStart)
120  std::swap( zoomStart, zoomEnd );
121 
122  float min, max, minBand = 0;
123  const double rate = pTrack->GetRate();
124  const float halfrate = rate / 2;
125  float maxFreq = 8000.0;
126 
127  bool bDragZoom = WaveTrackVZoomHandle::IsDragZooming(zoomStart, zoomEnd);
128 
129  // Possibly override the zoom kind.
130  if( bDragZoom )
131  ZoomKind = kZoomInByDrag;
132 
133  float top=2.0;
134  float half=0.5;
135 
136  {
137  pTrack->GetDisplayBounds(&min, &max);
138  const WaveformSettings &waveSettings = pTrack->GetWaveformSettings();
139  const bool linear = waveSettings.isLinear();
140  if( !linear ){
141  top = (LINEAR_TO_DB(2.0) + waveSettings.dBRange) / waveSettings.dBRange;
142  half = (LINEAR_TO_DB(0.5) + waveSettings.dBRange) / waveSettings.dBRange;
143  }
144  }
145 
146 
147  // Compute min and max.
148  switch(ZoomKind)
149  {
150  default:
151  // If we have covered all the cases, this won't happen.
152  // In release builds Audacity will ignore the zoom.
153  wxFAIL_MSG("Zooming Case not implemented by Audacity");
154  break;
155  case kZoomReset:
156  case kZoom1to1:
157  {
158  // Zoom out full
159  min = -1.0;
160  max = 1.0;
161  }
162  break;
163  case kZoomDiv2:
164  {
165  // Zoom out even more than full :-)
166  // -2.0..+2.0 (or logarithmic equivalent)
167  min = -top;
168  max = top;
169  }
170  break;
171  case kZoomTimes2:
172  {
173  // Zoom in to -0.5..+0.5
174  min = -half;
175  max = half;
176  }
177  break;
178  case kZoomHalfWave:
179  {
180  // Zoom to show fractionally more than the top half of the wave.
181  min = -0.01f;
182  max = 1.0;
183  }
184  break;
185  case kZoomInByDrag:
186  {
187  const float tmin = min, tmax = max;
188  const float p1 = (zoomStart - ypos) / (float)height;
189  const float p2 = (zoomEnd - ypos) / (float)height;
190  max = (tmax * (1.0 - p1) + tmin * p1);
191  min = (tmax * (1.0 - p2) + tmin * p2);
192 
193  // Waveform view - allow zooming down to a range of ZOOMLIMIT
194  if (max - min < ZOOMLIMIT) { // if user attempts to go smaller...
195  float c = (min + max) / 2; // ...set centre of view to centre of dragged area and top/bottom to ZOOMLIMIT/2 above/below
196  min = c - ZOOMLIMIT / 2.0;
197  max = c + ZOOMLIMIT / 2.0;
198  }
199  }
200  break;
201  case kZoomIn:
202  {
203  // Enforce maximum vertical zoom
204  const float oldRange = max - min;
205  const float l = std::max(ZOOMLIMIT, 0.5f * oldRange);
206  const float ratio = l / (max - min);
207 
208  const float p1 = (zoomStart - ypos) / (float)height;
209  float c = (max * (1.0 - p1) + min * p1);
210  if (fixedMousePoint)
211  min = c - ratio * (1.0f - p1) * oldRange,
212  max = c + ratio * p1 * oldRange;
213  else
214  min = c - 0.5 * l,
215  max = c + 0.5 * l;
216  }
217  break;
218  case kZoomOut:
219  {
220  // Zoom out
221  if (min <= -1.0 && max >= 1.0) {
222  min = -top;
223  max = top;
224  }
225  else {
226  // limit to +/- 1 range unless already outside that range...
227  float minRange = (min < -1) ? -top : -1.0;
228  float maxRange = (max > 1) ? top : 1.0;
229  // and enforce vertical zoom limits.
230  const float p1 = (zoomStart - ypos) / (float)height;
231  if (fixedMousePoint) {
232  const float oldRange = max - min;
233  const float c = (max * (1.0 - p1) + min * p1);
234  min = std::min(maxRange - ZOOMLIMIT,
235  std::max(minRange, c - 2 * (1.0f - p1) * oldRange));
236  max = std::max(minRange + ZOOMLIMIT,
237  std::min(maxRange, c + 2 * p1 * oldRange));
238  }
239  else {
240  const float c = p1 * min + (1 - p1) * max;
241  const float l = (max - min);
242  min = std::min(maxRange - ZOOMLIMIT,
243  std::max(minRange, c - l));
244  max = std::max(minRange + ZOOMLIMIT,
245  std::min(maxRange, c + l));
246  }
247  }
248  }
249  break;
250  }
251 
252  // Now actually apply the zoom.
253  for (auto channel : TrackList::Channels(pTrack))
254  channel->SetDisplayBounds(min, max);
255 
256  zoomEnd = zoomStart = 0;
257  if( pProject )
258  ProjectHistory::Get( *pProject ).ModifyState(true);
259 }
260 
262 // Table class
263 
265 {
266  static WaveformVRulerMenuTable instance;
267  return instance;
268 }
269 
271  // Accelerators only if zooming enabled.
272  bool bVZoom;
273  gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
274 
275  BeginSection( "Scales" );
276  {
277  const auto & names = WaveformSettings::GetScaleNames();
278  for (int ii = 0, nn = names.size(); ii < nn; ++ii) {
280  OnFirstWaveformScaleID + ii, names[ii].Msgid(),
281  POPUP_MENU_FN( OnWaveformScaleType ),
282  []( PopupMenuHandler &handler, wxMenu &menu, int id ){
283  const auto pData =
284  static_cast< WaveformVRulerMenuTable& >( handler ).mpData;
285  WaveTrack *const wt = pData->pTrack;
286  if ( id ==
288  (int)(wt->GetWaveformSettings().scaleType) )
289  menu.Check(id, true);
290  }
291  );
292  }
293  }
295 
296  BeginSection( "Zoom" );
297  BeginSection( "Basic" );
299  MakeLabel( XXO("Zoom Reset"), bVZoom, XXO("Shift-Right-Click") ),
300  POPUP_MENU_FN( OnZoomReset ) );
301  AppendItem( "TimesHalf", OnZoomDiv2ID, XXO("Zoom x1/2"),
302  POPUP_MENU_FN( OnZoomDiv2Vertical ) );
303  AppendItem( "TimesTwo", OnZoomTimes2ID, XXO("Zoom x2"), POPUP_MENU_FN( OnZoomTimes2Vertical ) );
304 
305  #ifdef EXPERIMENTAL_HALF_WAVE
306  AppendItem( "HalfWave", OnZoomHalfWaveID, XXO("Half Wave"), POPUP_MENU_FN( OnZoomHalfWave ) );
307  #endif
308  EndSection();
309 
310  BeginSection( "InOut" );
312  MakeLabel( XXO("Zoom In"), bVZoom, XXO("Left-Click/Left-Drag") ),
313  POPUP_MENU_FN( OnZoomInVertical ) );
315  MakeLabel( XXO("Zoom Out"), bVZoom, XXO("Shift-Left-Click") ),
316  POPUP_MENU_FN( OnZoomOutVertical ) );
317  EndSection();
318  EndSection();
319 
321 
322 void WaveformVRulerMenuTable::OnWaveformScaleType(wxCommandEvent &evt)
323 {
324  WaveTrack *const wt = mpData->pTrack;
325  // Assume linked track is wave or null
326  const WaveformSettings::ScaleType newScaleType =
328  std::max(0,
330  evt.GetId() - OnFirstWaveformScaleID
331  )));
332 
333  if (wt->GetWaveformSettings().scaleType != newScaleType) {
334  for (auto channel : TrackList::Channels(wt)) {
335  channel->GetWaveformSettings().scaleType = newScaleType;
336  }
337 
338  AudacityProject *const project = &mpData->project;
339  ProjectHistory::Get( *project ).ModifyState(true);
340 
341  using namespace RefreshCode;
342  mpData->result = UpdateVRuler | RefreshAll;
343  }
344 }
WaveformVZoomHandle::mZoomStart
int mZoomStart
Definition: WaveformVZoomHandle.h:72
WaveformSettings::isLinear
bool isLinear() const
Definition: WaveformSettings.h:71
WaveformVZoomHandle::Enter
void Enter(bool forward, AudacityProject *) override
Definition: WaveformVZoomHandle.cpp:33
OnZoomDiv2ID
@ OnZoomDiv2ID
Definition: NoteTrackVZoomHandle.cpp:149
WaveformSettings::scaleType
ScaleType scaleType
Definition: WaveformSettings.h:67
ProjectHistory::ModifyState
void ModifyState(bool bWantsAutoSave)
Definition: ProjectHistory.cpp:124
AppendItem
AppendItem("Reset", OnZoomFitVerticalID, MakeLabel(XXO("Zoom Reset"), bVZoom, XXO("Shift-Right-Click")), POPUP_MENU_FN(OnZoomReset))
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:69
BeginSection
BeginSection("Scales")
RefreshCode::RefreshAll
@ RefreshAll
Definition: RefreshCode.h:26
AppendRadioItem
AppendRadioItem("Instrument1", OnInstrument1ID, GetWaveColorStr(0), POPUP_MENU_FN(OnWaveColorChange), fn)
NumberScale.h
RefreshCode::RefreshNone
@ RefreshNone
Definition: RefreshCode.h:21
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
WaveTrackViewConstants::kZoomTimes2
@ kZoomTimes2
Definition: WaveTrackViewConstants.h:73
OnZoomHalfWaveID
@ OnZoomHalfWaveID
Definition: NoteTrackVZoomHandle.cpp:151
TrackList::Lock
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1542
bVZoom
bool bVZoom
Definition: WaveformVZoomHandle.cpp:272
WaveformVZoomHandle::mRect
wxRect mRect
Definition: WaveformVZoomHandle.h:73
PopupMenuTable
Definition: PopupMenuTable.h:115
WaveTrackVZoomHandle::DoRelease
AUDACITY_DLL_API Result DoRelease(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent, WaveTrack *pTrack, const wxRect &mRect, DoZoomFunction doZoom, PopupMenuTable &table, int zoomStart, int zoomEnd)
Definition: WaveTrackVZoomHandle.cpp:97
WaveformSettings::ScaleType
int ScaleType
Definition: WaveformSettings.h:57
WaveformVZoomHandle::Cancel
Result Cancel(AudacityProject *pProject) override
Definition: WaveformVZoomHandle.cpp:78
WaveTrackViewConstants
Definition: WaveTrackView.h:17
TrackPanelDrawingContext
Definition: TrackPanelDrawingContext.h:22
TrackList::Channels
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1484
WaveformVZoomHandle::HandlesRightClick
bool HandlesRightClick() override
Whether the handle has any special right-button handling.
Definition: WaveformVZoomHandle.cpp:40
WaveTrackVZoomHandle::DoDrawingArea
AUDACITY_DLL_API wxRect DoDrawingArea(const wxRect &rect, const wxRect &panelRect, unsigned iPass)
Definition: WaveTrackVZoomHandle.cpp:161
OnFirstWaveformScaleID
@ OnFirstWaveformScaleID
Definition: WaveTrackVZoomHandle.h:117
WaveTrackViewConstants::kZoom1to1
@ kZoom1to1
Definition: WaveTrackViewConstants.h:72
RefreshCode::Cancelled
@ Cancelled
Definition: RefreshCode.h:23
WaveTrackVZoomHandle::DoDrag
AUDACITY_DLL_API Result DoDrag(const TrackPanelMouseEvent &event, AudacityProject *pProject, int zoomStart, int &zoomEnd)
Definition: WaveTrackVZoomHandle.cpp:82
WaveTrackViewConstants::ZoomActions
ZoomActions
Definition: WaveTrackViewConstants.h:69
WaveformVZoomHandle::Draw
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: WaveformVZoomHandle.cpp:85
WaveTrackVZoomHandle::DoDraw
AUDACITY_DLL_API void DoDraw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass, int zoomStart, int zoomEnd)
Definition: WaveTrackVZoomHandle.cpp:150
WaveTrackViewConstants::kZoomDiv2
@ kZoomDiv2
Definition: WaveTrackViewConstants.h:74
EndSection
EndSection()
WaveformVZoomHandle.h
WaveTrackVZoomHandle::HitPreview
AUDACITY_DLL_API HitTestPreview HitPreview(const wxMouseState &state)
Definition: WaveTrackVZoomHandle.cpp:61
OnZoomFitVerticalID
@ OnZoomFitVerticalID
Definition: NoteTrackVZoomHandle.cpp:147
WaveTrackVZoomHandle::IsDragZooming
AUDACITY_DLL_API bool IsDragZooming(int zoomStart, int zoomEnd)
Definition: WaveTrackVZoomHandle.cpp:24
WaveformVRulerMenuTable::Instance
static PopupMenuTable & Instance()
Definition: WaveformVZoomHandle.cpp:264
XXO
#define XXO(s)
Definition: Internat.h:44
UIHandle::mChangeHighlight
Result mChangeHighlight
Definition: UIHandle.h:139
WaveformVZoomHandle::DoZoom
static void DoZoom(AudacityProject *pProject, WaveTrack *pTrack, WaveTrackViewConstants::ZoomActions ZoomKind, const wxRect &rect, int zoomStart, int zoomEnd, bool fixedMousePoint)
Definition: WaveformVZoomHandle.cpp:105
WaveformSettings::GetScaleNames
static const EnumValueSymbols & GetScaleNames()
Definition: WaveformSettings.cpp:162
WaveformVZoomHandle::Drag
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: WaveformVZoomHandle.cpp:52
WaveformVZoomHandle::mpTrack
std::weak_ptr< WaveTrack > mpTrack
Definition: WaveformVZoomHandle.h:70
UIHandle::Result
unsigned Result
Definition: UIHandle.h:38
WaveformVRulerMenuTable
Definition: WaveformVZoomHandle.h:79
HitTestPreview
Definition: HitTestResult.h:20
WaveformVZoomHandle::~WaveformVZoomHandle
~WaveformVZoomHandle() override
RefreshCode::UpdateVRuler
@ UpdateVRuler
Definition: RefreshCode.h:30
WaveTrackViewConstants::kZoomIn
@ kZoomIn
Definition: WaveTrackViewConstants.h:77
anonymous_namespace{NoteTrack.cpp}::swap
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:735
WaveTrack::GetWaveformSettings
const WaveformSettings & GetWaveformSettings() const
Definition: WaveTrack.cpp:811
RefreshCode::RefreshCell
@ RefreshCell
Definition: RefreshCode.h:24
WaveTrackViewConstants::kZoomInByDrag
@ kZoomInByDrag
Definition: WaveTrackViewConstants.h:76
POPUP_MENU_FN
#define POPUP_MENU_FN(memFn)
Definition: PopupMenuTable.h:324
WaveTrackViewConstants::kZoomReset
@ kZoomReset
Definition: WaveTrackViewConstants.h:79
Read
gPrefs Read(wxT("/GUI/VerticalZooming"), &bVZoom, false)
WaveformVZoomHandle::DrawingArea
wxRect DrawingArea(TrackPanelDrawingContext &, const wxRect &rect, const wxRect &panelRect, unsigned iPass) override
Definition: WaveformVZoomHandle.cpp:95
WaveformVZoomHandle::Preview
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Definition: WaveformVZoomHandle.cpp:62
BEGIN_POPUP_MENU
#define BEGIN_POPUP_MENU(HandlerClass)
Definition: PopupMenuTable.h:316
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:506
PopupMenuHandler
Definition: PopupMenuTable.h:85
OnZoomOutVerticalID
@ OnZoomOutVerticalID
Definition: NoteTrackVZoomHandle.cpp:153
names
static TranslatableStrings names
Definition: Tags.cpp:744
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:92
WaveformSettings::stNumScaleTypes
@ stNumScaleTypes
Definition: WaveformSettings.h:62
WaveformVZoomHandle::WaveformVZoomHandle
WaveformVZoomHandle(const WaveformVZoomHandle &)
WaveformSettings::dBRange
int dBRange
Definition: WaveformSettings.h:68
TrackPanelMouseEvent
Definition: TrackPanelMouseEvent.h:46
WaveformSettings
Waveform settings, either for one track or as defaults.
Definition: WaveformSettings.h:19
TrackPanelMouseState
Definition: TrackPanelMouseEvent.h:28
WaveTrackViewConstants::kZoomOut
@ kZoomOut
Definition: WaveTrackViewConstants.h:78
ExceptionType::Internal
@ Internal
Indicates internal failure from Audacity.
LINEAR_TO_DB
#define LINEAR_TO_DB(x)
Definition: MemoryX.h:631
Prefs.h
WaveTrack::GetDisplayBounds
void GetDisplayBounds(float *min, float *max) const
Definition: WaveTrack.cpp:320
WaveformVZoomHandle::mZoomEnd
int mZoomEnd
Definition: WaveformVZoomHandle.h:72
OnZoomTimes2ID
@ OnZoomTimes2ID
Definition: NoteTrackVZoomHandle.cpp:150
WaveformVZoomHandle::Release
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
Definition: WaveformVZoomHandle.cpp:68
RefreshCode
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
WaveTrackViewConstants::kZoomHalfWave
@ kZoomHalfWave
Definition: WaveTrackViewConstants.h:75
OnZoomInVerticalID
@ OnZoomInVerticalID
Definition: NoteTrackVZoomHandle.cpp:152
WaveformVZoomHandle::Click
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: WaveformVZoomHandle.cpp:46
TrackPanelMouseState::state
wxMouseState & state
Definition: TrackPanelMouseEvent.h:38
ProjectHistory::Get
static ProjectHistory & Get(AudacityProject &project)
Definition: ProjectHistory.cpp:26
END_POPUP_MENU
#define END_POPUP_MENU()
Definition: PopupMenuTable.h:331
WaveTrackVZoomHandle.h
WaveTrack::GetRate
double GetRate() const
Definition: WaveTrack.cpp:457