Audacity 3.2.0
WaveformVZoomHandle.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5WaveformVZoomHandle.cpp
6
7Paul Licameli split from WaveChannelVZoomHandle.cpp
8
9**********************************************************************/
10
11
12#include "WaveformVZoomHandle.h"
13
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 "WaveformSettings.h"
24#include "prefs/WaveformScale.h"
25
27 const std::shared_ptr<WaveChannel> &pChannel, const wxRect &rect, int y)
28 : mpChannel{ pChannel } , mZoomStart(y), mZoomEnd(y), mRect(rect)
29{
30}
31
33
34std::shared_ptr<const Track> WaveformVZoomHandle::FindTrack() const
35{
36 return TrackFromChannel(mpChannel.lock());
37}
38
40{
41#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
43#endif
44}
45
47{
48 return true;
49}
50
53{
55}
56
58 const TrackPanelMouseEvent &evt, AudacityProject *pProject)
59{
60 using namespace RefreshCode;
61 const auto pChannel = mpChannel.lock();
62 if (!pChannel)
63 return Cancelled;
64 return WaveChannelVZoomHandle::DoDrag(evt, pProject, mZoomStart, mZoomEnd, false);
65}
66
69{
71}
72
74 const TrackPanelMouseEvent &evt, AudacityProject *pProject,
75 wxWindow *pParent)
76{
77 const auto pChannel = mpChannel.lock();
78 if (!pChannel)
81 evt, pProject, pParent, *pChannel, mRect,
84}
85
87{
88 // Cancel is implemented! And there is no initial state to restore,
89 // so just return a code.
91}
92
95 const wxRect &rect, unsigned iPass )
96{
97 const auto pChannel = mpChannel.lock();
98 if (!pChannel)
99 return;
101 context, rect, iPass, mZoomStart, mZoomEnd, false);
102}
103
106 const wxRect &rect, const wxRect &panelRect, unsigned iPass )
107{
108 return WaveChannelVZoomHandle::DoDrawingArea(rect, panelRect, iPass);
109}
110
111// ZoomKind says how to zoom.
112// If ZoomStart and ZoomEnd are not equal, this may override
113// the zoomKind and cause a drag-zoom-in.
115 AudacityProject *pProject,
116 WaveChannel &wc,
118 const wxRect &rect, int zoomStart, int zoomEnd,
119 bool fixedMousePoint)
120{
121 using namespace WaveChannelViewConstants;
122 static const float ZOOMLIMIT = 0.001f;
123
124 int height = rect.height;
125 int ypos = rect.y;
126
127 // Ensure start and end are in order (swap if not).
128 if (zoomEnd < zoomStart)
129 std::swap( zoomStart, zoomEnd );
130
131 float min, max, minBand = 0;
132 const double rate = wc.GetRate();
133 const float halfrate = rate / 2;
134 float maxFreq = 8000.0;
135
136
137 float top=2.0;
138 float half=0.5;
139 auto &cache = WaveformScale::Get(wc);
140
141 {
142 cache.GetDisplayBounds(min, max);
143 auto &waveSettings = WaveformSettings::Get(wc);
144 const bool linear = waveSettings.isLinear();
145 if( !linear ){
146 top = (LINEAR_TO_DB(2.0) + waveSettings.dBRange) / waveSettings.dBRange;
147 half = (LINEAR_TO_DB(0.5) + waveSettings.dBRange) / waveSettings.dBRange;
148 }
149 }
150
151
152 // Compute min and max.
153 switch(ZoomKind)
154 {
155 default:
156 // If we have covered all the cases, this won't happen.
157 // In release builds Audacity will ignore the zoom.
158 wxFAIL_MSG("Zooming Case not implemented by Audacity");
159 break;
160 case kZoomReset:
161 case kZoom1to1:
162 {
163 // Zoom out full
164 min = -1.0;
165 max = 1.0;
166 }
167 break;
168 case kZoomHalfWave:
169 {
170 // Zoom to show fractionally more than the top half of the wave.
171 min = -0.01f;
172 max = 1.0;
173 }
174 break;
175 case kZoomInByDrag:
176 {
177 const float tmin = min, tmax = max;
178 const float p1 = (zoomStart - ypos) / (float)height;
179 const float p2 = (zoomEnd - ypos) / (float)height;
180 max = (tmax * (1.0 - p1) + tmin * p1);
181 min = (tmax * (1.0 - p2) + tmin * p2);
182
183 // Waveform view - allow zooming down to a range of ZOOMLIMIT
184 if (max - min < ZOOMLIMIT) { // if user attempts to go smaller...
185 float c = (min + max) / 2; // ...set centre of view to centre of dragged area and top/bottom to ZOOMLIMIT/2 above/below
186 min = c - ZOOMLIMIT / 2.0;
187 max = c + ZOOMLIMIT / 2.0;
188 }
189 }
190 break;
191 case kZoomIn:
192 {
193 const float zoomFactor = 0.5f;
194 const float currentRange = max - min;
195 const float nextRange = std::max(zoomFactor * currentRange, ZOOMLIMIT);
196
197 const float center = min + (currentRange / 2.0);
198 min = center - (nextRange / 2.0);
199 max = center + (nextRange / 2.0);
200 }
201 break;
202 case kZoomOut:
203 {
204 const float zoomFactor = 2.0f;
205 const float currentRange = max - min;
206 const float nextRange = zoomFactor * currentRange;
207
208 const float center = min + (currentRange / 2.0);
209 min = std::max(-top, center - (0.5f * nextRange));
210 max = std::min(top, center + (0.5f * nextRange));
211 }
212 break;
213 }
214
215 // Now actually apply the zoom.
216 cache.SetDisplayBounds(min, max);
217
218 zoomEnd = zoomStart = 0;
219 if( pProject )
220 ProjectHistory::Get( *pProject ).ModifyState(true);
221}
222
224// Table class
225
227{
228 static WaveformVRulerMenuTable instance;
229 return instance;
230}
231
233 // this generates the linear(amp), log(dB), linear(dB) entries
234 const auto & names = WaveformSettings::GetScaleNames();
235 for (int ii = 0, nn = names.size(); ii < nn; ++ii) {
237 OnFirstWaveformScaleID + ii, names[ii].Msgid(),
238 POPUP_MENU_FN( OnWaveformScaleType ),
239 []( PopupMenuHandler &handler, wxMenu &menu, int id ){
240 const auto pData =
241 static_cast< WaveformVRulerMenuTable& >( handler ).mpData;
242 if (id ==
244 static_cast<int>(WaveformSettings::Get(pData->wc).scaleType))
245 menu.Check(id, true);
246 }
247 );
248 }
249
250 BeginSection( "Zoom" );
251 BeginSection( "Basic" );
252 AppendItem( "In", OnZoomInVerticalID, XXO("Zoom In"), POPUP_MENU_FN( OnZoomInVertical ) );
253 AppendItem( "Out", OnZoomOutVerticalID, XXO("Zoom Out"), POPUP_MENU_FN( OnZoomOutVertical ) );
254 AppendItem( "Reset", OnZoomFitVerticalID, XXO("Reset Zoom"), POPUP_MENU_FN( OnZoomReset ) );
256
257 BeginSection( "InOut" );
258 AppendItem( "HalfWave", OnZoomHalfWaveID, XXO("Half Wave"), POPUP_MENU_FN( OnZoomHalfWave ) );
259 EndSection();
260 EndSection();
261
263
264void WaveformVRulerMenuTable::OnWaveformScaleType(wxCommandEvent &evt)
265{
266 // Assume linked track is wave or null
267 const WaveformSettings::ScaleType newScaleType =
269 std::max(0,
271 evt.GetId() - OnFirstWaveformScaleID
272 )));
273
274 auto &scaleType = WaveformSettings::Get(mpData->wc).scaleType;
275 if (scaleType != newScaleType) {
276 scaleType = newScaleType;
277
278 AudacityProject *const project = &mpData->project;
279 ProjectHistory::Get( *project ).ModifyState(true);
280
281 using namespace RefreshCode;
282 mpData->result = UpdateVRuler | RefreshAll;
283 }
284}
@ Internal
Indicates internal failure from Audacity.
int min(int a, int b)
XXO("&Cut/Copy/Paste Toolbar")
#define LINEAR_TO_DB(x)
Definition: MemoryX.h:339
@ OnZoomOutVerticalID
@ OnZoomFitVerticalID
@ OnZoomHalfWaveID
@ OnZoomInVerticalID
#define END_POPUP_MENU()
#define BEGIN_POPUP_MENU(HandlerClass)
#define POPUP_MENU_FN(memFn)
const auto project
@ OnFirstWaveformScaleID
EndSection()
BeginSection("Zoom")
for(int ii=0, nn=names.size();ii< nn;++ii)
AppendItem("In", OnZoomInVerticalID, XXO("Zoom In"), POPUP_MENU_FN(OnZoomInVertical))
const auto & names
AppendRadioItem("Instrument1", OnInstrument1ID, GetWaveColorStr(0), POPUP_MENU_FN(OnWaveColorChange), fn)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
static std::shared_ptr< const Track > TrackFromChannel(const std::shared_ptr< const Channel > &pChannel)
A frequent convenience in the definition of UIHandles.
Definition: UIHandle.cpp:63
Result mChangeHighlight
Definition: UIHandle.h:152
unsigned Result
Definition: UIHandle.h:40
double GetRate() const override
Definition: WaveTrack.cpp:816
static WaveformScale & Get(const WaveTrack &track)
Mutative access to attachment even if the track argument is const.
Waveform settings, either for one track or as defaults.
static WaveformSettings & Get(const WaveTrack &track)
static PopupMenuTable & Instance()
void Enter(bool forward, AudacityProject *) override
~WaveformVZoomHandle() override
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
wxRect DrawingArea(TrackPanelDrawingContext &, const wxRect &rect, const wxRect &panelRect, unsigned iPass) override
std::shared_ptr< const Track > FindTrack() const override
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
std::weak_ptr< WaveChannel > mpChannel
static void DoZoom(AudacityProject *pProject, WaveChannel &wc, WaveChannelViewConstants::ZoomActions ZoomKind, const wxRect &rect, int zoomStart, int zoomEnd, bool fixedMousePoint)
WaveformVZoomHandle(const WaveformVZoomHandle &)
Result Cancel(AudacityProject *pProject) override
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
bool HandlesRightClick() override
Whether the handle has any special right-button handling.
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
AUDACITY_DLL_API Result DoRelease(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent, WaveChannel &wc, const wxRect &mRect, DoZoomFunction doZoom, PopupMenuTable &table, int zoomStart, int zoomEnd)
AUDACITY_DLL_API HitTestPreview HitPreview(const bool bVZoom)
AUDACITY_DLL_API void DoDraw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass, int zoomStart, int zoomEnd, bool hasDragZoom)
AUDACITY_DLL_API wxRect DoDrawingArea(const wxRect &rect, const wxRect &panelRect, unsigned iPass)
AUDACITY_DLL_API Result DoDrag(const TrackPanelMouseEvent &event, AudacityProject *pProject, int zoomStart, int &zoomEnd, bool hasDragZoom)
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:634