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 "../../../../prefs/WaveformSettings.h"
24
26 const std::shared_ptr<WaveChannel> &pChannel, const wxRect &rect, int y)
27 : mpChannel{ pChannel } , mZoomStart(y), mZoomEnd(y), mRect(rect)
28{
29}
30
32
33std::shared_ptr<const Track> WaveformVZoomHandle::FindTrack() const
34{
35 return TrackFromChannel(mpChannel.lock());
36}
37
39{
40#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
42#endif
43}
44
46{
47 return true;
48}
49
52{
54}
55
57 const TrackPanelMouseEvent &evt, AudacityProject *pProject)
58{
59 using namespace RefreshCode;
60 const auto pChannel = mpChannel.lock();
61 if (!pChannel)
62 return Cancelled;
63 return WaveChannelVZoomHandle::DoDrag(evt, pProject, mZoomStart, mZoomEnd, false);
64}
65
68{
70}
71
73 const TrackPanelMouseEvent &evt, AudacityProject *pProject,
74 wxWindow *pParent)
75{
76 const auto pChannel = mpChannel.lock();
77 if (!pChannel)
80 evt, pProject, pParent, *pChannel, mRect,
83}
84
86{
87 // Cancel is implemented! And there is no initial state to restore,
88 // so just return a code.
90}
91
94 const wxRect &rect, unsigned iPass )
95{
96 const auto pChannel = mpChannel.lock();
97 if (!pChannel)
98 return;
100 context, rect, iPass, mZoomStart, mZoomEnd, false);
101}
102
105 const wxRect &rect, const wxRect &panelRect, unsigned iPass )
106{
107 return WaveChannelVZoomHandle::DoDrawingArea(rect, panelRect, iPass);
108}
109
110// ZoomKind says how to zoom.
111// If ZoomStart and ZoomEnd are not equal, this may override
112// the zoomKind and cause a drag-zoom-in.
114 AudacityProject *pProject,
115 WaveChannel &wc,
117 const wxRect &rect, int zoomStart, int zoomEnd,
118 bool fixedMousePoint)
119{
120 using namespace WaveChannelViewConstants;
121 static const float ZOOMLIMIT = 0.001f;
122
123 int height = rect.height;
124 int ypos = rect.y;
125
126 // Ensure start and end are in order (swap if not).
127 if (zoomEnd < zoomStart)
128 std::swap( zoomStart, zoomEnd );
129
130 float min, max, minBand = 0;
131 const double rate = wc.GetRate();
132 const float halfrate = rate / 2;
133 float maxFreq = 8000.0;
134
135
136 float top=2.0;
137 float half=0.5;
138 auto &cache = WaveformScale::Get(wc);
139
140 {
141 cache.GetDisplayBounds(min, max);
142 auto &waveSettings = WaveformSettings::Get(wc);
143 const bool linear = waveSettings.isLinear();
144 if( !linear ){
145 top = (LINEAR_TO_DB(2.0) + waveSettings.dBRange) / waveSettings.dBRange;
146 half = (LINEAR_TO_DB(0.5) + waveSettings.dBRange) / waveSettings.dBRange;
147 }
148 }
149
150
151 // Compute min and max.
152 switch(ZoomKind)
153 {
154 default:
155 // If we have covered all the cases, this won't happen.
156 // In release builds Audacity will ignore the zoom.
157 wxFAIL_MSG("Zooming Case not implemented by Audacity");
158 break;
159 case kZoomReset:
160 case kZoom1to1:
161 {
162 // Zoom out full
163 min = -1.0;
164 max = 1.0;
165 }
166 break;
167 case kZoomHalfWave:
168 {
169 // Zoom to show fractionally more than the top half of the wave.
170 min = -0.01f;
171 max = 1.0;
172 }
173 break;
174 case kZoomInByDrag:
175 {
176 const float tmin = min, tmax = max;
177 const float p1 = (zoomStart - ypos) / (float)height;
178 const float p2 = (zoomEnd - ypos) / (float)height;
179 max = (tmax * (1.0 - p1) + tmin * p1);
180 min = (tmax * (1.0 - p2) + tmin * p2);
181
182 // Waveform view - allow zooming down to a range of ZOOMLIMIT
183 if (max - min < ZOOMLIMIT) { // if user attempts to go smaller...
184 float c = (min + max) / 2; // ...set centre of view to centre of dragged area and top/bottom to ZOOMLIMIT/2 above/below
185 min = c - ZOOMLIMIT / 2.0;
186 max = c + ZOOMLIMIT / 2.0;
187 }
188 }
189 break;
190 case kZoomIn:
191 {
192 const float zoomFactor = 0.5f;
193 const float currentRange = max - min;
194 const float nextRange = std::max(zoomFactor * currentRange, ZOOMLIMIT);
195
196 const float center = min + (currentRange / 2.0);
197 min = center - (nextRange / 2.0);
198 max = center + (nextRange / 2.0);
199 }
200 break;
201 case kZoomOut:
202 {
203 const float zoomFactor = 2.0f;
204 const float currentRange = max - min;
205 const float nextRange = zoomFactor * currentRange;
206
207 const float center = min + (currentRange / 2.0);
208 min = std::max(-top, center - (0.5f * nextRange));
209 max = std::min(top, center + (0.5f * nextRange));
210 }
211 break;
212 }
213
214 // Now actually apply the zoom.
215 cache.SetDisplayBounds(min, max);
216
217 zoomEnd = zoomStart = 0;
218 if( pProject )
219 ProjectHistory::Get( *pProject ).ModifyState(true);
220}
221
223// Table class
224
226{
227 static WaveformVRulerMenuTable instance;
228 return instance;
229}
230
232 // this generates the linear(amp), log(dB), linear(dB) entries
233 const auto & names = WaveformSettings::GetScaleNames();
234 for (int ii = 0, nn = names.size(); ii < nn; ++ii) {
236 OnFirstWaveformScaleID + ii, names[ii].Msgid(),
237 POPUP_MENU_FN( OnWaveformScaleType ),
238 []( PopupMenuHandler &handler, wxMenu &menu, int id ){
239 const auto pData =
240 static_cast< WaveformVRulerMenuTable& >( handler ).mpData;
241 if (id ==
243 static_cast<int>(WaveformSettings::Get(pData->wc).scaleType))
244 menu.Check(id, true);
245 }
246 );
247 }
248
249 BeginSection( "Zoom" );
250 BeginSection( "Basic" );
251 AppendItem( "In", OnZoomInVerticalID, XXO("Zoom In"), POPUP_MENU_FN( OnZoomInVertical ) );
252 AppendItem( "Out", OnZoomOutVerticalID, XXO("Zoom Out"), POPUP_MENU_FN( OnZoomOutVertical ) );
253 AppendItem( "Reset", OnZoomFitVerticalID, XXO("Reset Zoom"), POPUP_MENU_FN( OnZoomReset ) );
255
256 BeginSection( "InOut" );
257 AppendItem( "HalfWave", OnZoomHalfWaveID, XXO("Half Wave"), POPUP_MENU_FN( OnZoomHalfWave ) );
258 EndSection();
259 EndSection();
260
262
263void WaveformVRulerMenuTable::OnWaveformScaleType(wxCommandEvent &evt)
264{
265 // Assume linked track is wave or null
266 const WaveformSettings::ScaleType newScaleType =
268 std::max(0,
270 evt.GetId() - OnFirstWaveformScaleID
271 )));
272
273 auto &scaleType = WaveformSettings::Get(mpData->wc).scaleType;
274 if (scaleType != newScaleType) {
275 scaleType = newScaleType;
276
277 AudacityProject *const project = &mpData->project;
278 ProjectHistory::Get( *project ).ModifyState(true);
279
280 using namespace RefreshCode;
281 mpData->result = UpdateVRuler | RefreshAll;
282 }
283}
@ 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:793
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:628