Audacity 3.2.0
ViewMenus.cpp
Go to the documentation of this file.
1#include "../CommonCommandFlags.h"
2#include "../Menus.h"
3#include "Prefs.h"
4#include "Project.h"
5#include "ProjectHistory.h"
6#include "../ProjectSettings.h"
7#include "../ProjectWindow.h"
8#include "Track.h"
9#include "../TrackInfo.h"
10#include "../TrackPanel.h"
11#include "UndoManager.h"
12#include "ViewInfo.h"
13#include "../commands/CommandContext.h"
14#include "../commands/CommandManager.h"
15#include "../prefs/GUIPrefs.h"
16#include "../prefs/TracksPrefs.h"
17#include "../tracks/ui/TrackView.h"
18
19
20#include <wx/app.h>
21#include <wx/scrolbar.h>
22
23// private helper classes and functions
24namespace {
25
26double GetZoomOfSelection( const AudacityProject &project )
27{
28 auto &viewInfo = ViewInfo::Get( project );
29 auto &window = ProjectWindow::Get( project );
30
31 const double lowerBound =
32 std::max(viewInfo.selectedRegion.t0(),
33 window.ScrollingLowerBoundTime());
34 const double denom =
35 viewInfo.selectedRegion.t1() - lowerBound;
36 if (denom <= 0.0)
37 return viewInfo.GetZoom();
38
39 // LL: The "-1" is just a hack to get around an issue where zooming to
40 // selection doesn't actually get the entire selected region within the
41 // visible area. This causes a problem with scrolling at end of playback
42 // where the selected region may be scrolled off the left of the screen.
43 // I know this isn't right, but until the real rounding or 1-off issue is
44 // found, this will have to work.
45 // PRL: Did I fix this? I am not sure, so I leave the hack in place.
46 // Fixes might have resulted from commits
47 // 1b8f44d0537d987c59653b11ed75a842b48896ea and
48 // e7c7bb84a966c3b3cc4b3a9717d5f247f25e7296
49 auto width = viewInfo.GetTracksUsableWidth();
50 return (width - 1) / denom;
51}
52
53double GetZoomOfPreset( const AudacityProject &project, int preset )
54{
55
56 // Sets a limit on how far we will zoom out as a factor over zoom to fit.
57 const double maxZoomOutFactor = 4.0;
58 // Sets how many pixels we allow for one uint, such as seconds.
59 const double pixelsPerUnit = 5.0;
60
61 double result = 1.0;
62 auto &window = ProjectWindow::Get( project );
63 double zoomToFit = window.GetZoomOfToFit();
64 using namespace WaveTrackViewConstants;
65 switch( preset ){
66 default:
67 case kZoomDefault:
68 result = ZoomInfo::GetDefaultZoom();
69 break;
70 case kZoomToFit:
71 result = zoomToFit;
72 break;
74 result = GetZoomOfSelection( project );
75 break;
76 case kZoomMinutes:
77 result = pixelsPerUnit * 1.0/60;
78 break;
79 case kZoomSeconds:
80 result = pixelsPerUnit * 1.0;
81 break;
82 case kZoom5ths:
83 result = pixelsPerUnit * 5.0;
84 break;
85 case kZoom10ths:
86 result = pixelsPerUnit * 10.0;
87 break;
88 case kZoom20ths:
89 result = pixelsPerUnit * 20.0;
90 break;
91 case kZoom50ths:
92 result = pixelsPerUnit * 50.0;
93 break;
94 case kZoom100ths:
95 result = pixelsPerUnit * 100.0;
96 break;
97 case kZoom500ths:
98 result = pixelsPerUnit * 500.0;
99 break;
101 result = pixelsPerUnit * 1000.0;
102 break;
103 case kZoomSamples:
104 result = 44100.0;
105 break;
106 case kZoom4To1:
107 result = 44100.0 * 4;
108 break;
109 case kMaxZoom:
110 result = ZoomInfo::GetMaxZoom();
111 break;
112 };
113 if( result < (zoomToFit/maxZoomOutFactor) )
114 result = zoomToFit / maxZoomOutFactor;
115 return result;
116}
117
118}
119
120namespace {
122{
123 auto &viewInfo = ViewInfo::Get( project );
124 auto &tracks = TrackList::Get( project );
125
126 // Only nonminimized audio tracks will be resized
127 auto range = tracks.Any<AudioTrack>()
128 - [](const Track *pTrack){
129 return TrackView::Get( *pTrack ).GetMinimized(); };
130 auto count = range.size();
131 if (count == 0)
132 return;
133
134 // Find total height to apportion
135 auto height = viewInfo.GetHeight();
136 height -= 28;
137
138 // The height of minimized and non-audio tracks cannot be apportioned
139 height -=
140 tracks.Any().sum( TrackView::GetTrackHeight )
141 - range.sum( TrackView::GetTrackHeight );
142
143 // Give each resized track the average of the remaining height
144 // Bug 2803: Cast count to int, because otherwise the result of
145 // division will be unsigned too, and will be a very large number
146 // if height was negative!
147 height = height / (int)count;
148 // Use max() so that we don't set a negative height when there is
149 // not enough room.
150 height = std::max( (int)TrackInfo::MinimumTrackHeight(), height );
151
152 for (auto t : range)
153 TrackView::Get( *t ).SetExpandedHeight(height);
154}
155}
156
157namespace ViewActions {
158
159// Menu handler functions
160
161struct Handler final
162 : CommandHandlerObject // MUST be the first base class!
164{
165
166void OnZoomIn(const CommandContext &context)
167{
168 auto &project = context.project;
169 auto &trackPanel = TrackPanel::Get( project );
170 auto &window = ProjectWindow::Get( project );
171 window.ZoomInByFactor( 2.0 );
172 trackPanel.Refresh(false);
173}
174
175void OnZoomNormal(const CommandContext &context)
176{
177 auto &project = context.project;
178 auto &trackPanel = TrackPanel::Get( project );
179 auto &window = ProjectWindow::Get( project );
180
181 window.Zoom(ZoomInfo::GetDefaultZoom());
182 trackPanel.Refresh(false);
183}
184
185void OnZoomOut(const CommandContext &context)
186{
187 auto &project = context.project;
188 auto &window = ProjectWindow::Get( project );
189 window.ZoomOutByFactor( 1 /2.0 );
190}
191
192void OnZoomSel(const CommandContext &context)
193{
194 auto &project = context.project;
195 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
196 auto &window = ProjectWindow::Get( project );
197
198 window.Zoom( GetZoomOfSelection( project ) );
199 window.TP_ScrollWindow(selectedRegion.t0());
200}
201
202void OnZoomToggle(const CommandContext &context)
203{
204 auto &project = context.project;
205 auto &viewInfo = ViewInfo::Get( project );
206 auto &trackPanel = TrackPanel::Get( project );
207 auto &window = ProjectWindow::Get( project );
208
209// const double origLeft = viewInfo.h;
210// const double origWidth = viewInfo.GetScreenEndTime() - origLeft;
211
212 // Choose the zoom that is most different to the current zoom.
213 double Zoom1 = GetZoomOfPreset( project, TracksPrefs::Zoom1Choice() );
214 double Zoom2 = GetZoomOfPreset( project, TracksPrefs::Zoom2Choice() );
215 double Z = viewInfo.GetZoom();// Current Zoom.
216 double ChosenZoom =
217 fabs(log(Zoom1 / Z)) > fabs(log( Z / Zoom2)) ? Zoom1:Zoom2;
218
219 window.Zoom(ChosenZoom);
220 trackPanel.Refresh(false);
221// const double newWidth = GetScreenEndTime() - viewInfo.h;
222// const double newh = origLeft + (origWidth - newWidth) / 2;
223// TP_ScrollWindow(newh);
224}
225
226void OnZoomFit(const CommandContext &context)
227{
228 auto &project = context.project;
229 auto &window = ProjectWindow::Get( project );
230 window.DoZoomFit();
231}
232
233void OnZoomFitV(const CommandContext &context)
234{
235 auto &project = context.project;
236 auto &window = ProjectWindow::Get( project );
237
238 DoZoomFitV(project);
239
240 window.GetVerticalScrollBar().SetThumbPosition(0);
241 ProjectHistory::Get( project ).ModifyState(true);
242}
243
244void OnAdvancedVZoom(const CommandContext &context)
245{
246 auto &project = context.project;
247 auto &commandManager = CommandManager::Get( project );
248
249 bool checked = !gPrefs->Read(wxT("/GUI/VerticalZooming"), 0L);
250 gPrefs->Write(wxT("/GUI/VerticalZooming"), checked);
251 gPrefs->Flush();
252 commandManager.Check(wxT("AdvancedVZoom"), checked);
254}
255
257{
258 auto &project = context.project;
259 auto &tracks = TrackList::Get( project );
260 auto &window = ProjectWindow::Get( project );
261
262 for (auto t : tracks.Any())
263 TrackView::Get( *t ).SetMinimized(true);
264
265 ProjectHistory::Get( project ).ModifyState(true);
266}
267
269{
270 auto &project = context.project;
271 auto &tracks = TrackList::Get( project );
272 auto &window = ProjectWindow::Get( project );
273
274 for (auto t : tracks.Any())
275 TrackView::Get( *t ).SetMinimized(false);
276
277 ProjectHistory::Get( project ).ModifyState(true);
278}
279
280void OnGoSelStart(const CommandContext &context)
281{
282 auto &project = context.project;
283 auto &viewInfo = ViewInfo::Get( project );
284 auto &selectedRegion = viewInfo.selectedRegion;
285 auto &window = ProjectWindow::Get( project );
286
287 if (selectedRegion.isPoint())
288 return;
289
290 window.TP_ScrollWindow(
291 selectedRegion.t0() - ((viewInfo.GetScreenEndTime() - viewInfo.h) / 2));
292}
293
294void OnGoSelEnd(const CommandContext &context)
295{
296 auto &project = context.project;
297 auto &viewInfo = ViewInfo::Get( project );
298 auto &selectedRegion = viewInfo.selectedRegion;
299 auto &window = ProjectWindow::Get( project );
300
301 if (selectedRegion.isPoint())
302 return;
303
304 window.TP_ScrollWindow(
305 selectedRegion.t1() - ((viewInfo.GetScreenEndTime() - viewInfo.h) / 2));
306}
307
309{
310 auto &project = context.project;
311 auto &commandManager = CommandManager::Get( project );
312
313 bool checked = !gPrefs->Read(wxT("/GUI/ShowExtraMenus"), 0L);
314 gPrefs->Write(wxT("/GUI/ShowExtraMenus"), checked);
315 gPrefs->Flush();
316 commandManager.Check(wxT("ShowExtraMenus"), checked);
318}
319
320void OnShowClipping(const CommandContext &context)
321{
322 auto &project = context.project;
323 auto &commandManager = CommandManager::Get( project );
324 auto &trackPanel = TrackPanel::Get( project );
325
326 bool checked = !gPrefs->Read(wxT("/GUI/ShowClipping"), 0L);
327 gPrefs->Write(wxT("/GUI/ShowClipping"), checked);
328 gPrefs->Flush();
329 commandManager.Check(wxT("ShowClipping"), checked);
330
332
333 trackPanel.Refresh(false);
334}
335
337{
338 auto &project = context.project;
339 auto &commandManager = CommandManager::Get( project );
340 auto &trackPanel = TrackPanel::Get( project );
341
342 bool checked = !gPrefs->Read(wxT("/GUI/ShowTrackNameInWaveform"), 0L);
343 gPrefs->Write(wxT("/GUI/ShowTrackNameInWaveform"), checked);
344 gPrefs->Flush();
345 commandManager.Check(wxT("ShowTrackNameInWaveform"), checked);
346
348
349 trackPanel.Refresh(false);
350}
351
352// Not a menu item, but a listener for events
354{
355 if (message.type == UndoRedoMessage::Pushed) {
356 const auto &settings = ProjectSettings::Get( mProject );
357 if (settings.GetTracksFitVerticallyZoomed())
359 }
360}
361
363 : mProject{ project }
364{
367}
368
369Handler( const Handler & ) PROHIBITED;
370Handler &operator=( const Handler & ) PROHIBITED;
371
374
375}; // struct Handler
376
377} // namespace
378
379// Handler needs a back-reference to the project, so needs a factory registered
380// with AudacityProject.
382 []( AudacityProject &project ) {
383 return std::make_unique< ViewActions::Handler >( project ); } };
384
386 return project.AttachedObjects::Get< ViewActions::Handler >( key );
387};
388
389// Menu definitions
390
391#define FN(X) (& ViewActions::Handler :: X)
392
393// Under /MenuBar
394namespace {
395using namespace MenuTable;
397{
399
400 static BaseItemSharedPtr menu{
402 Menu( wxT("View"), XXO("&View"),
403 Section( "Basic",
404 Menu( wxT("Zoom"), XXO("&Zoom"),
405 Section( "",
406 Command( wxT("ZoomIn"), XXO("Zoom &In"), FN(OnZoomIn),
407 ZoomInAvailableFlag(), wxT("Ctrl+1") ),
408 Command( wxT("ZoomNormal"), XXO("Zoom &Normal"), FN(OnZoomNormal),
409 TracksExistFlag(), wxT("Ctrl+2") ),
410 Command( wxT("ZoomOut"), XXO("Zoom &Out"), FN(OnZoomOut),
411 ZoomOutAvailableFlag(), wxT("Ctrl+3") ),
412 Command( wxT("ZoomSel"), XXO("&Zoom to Selection"), FN(OnZoomSel),
413 TimeSelectedFlag(), wxT("Ctrl+E") ),
414 Command( wxT("ZoomToggle"), XXO("Zoom &Toggle"), FN(OnZoomToggle),
415 TracksExistFlag(), wxT("Shift+Z") )
416 ),
417 Section( "",
418 Command( wxT("AdvancedVZoom"), XXO("Advanced &Vertical Zooming"),
419 FN(OnAdvancedVZoom), AlwaysEnabledFlag,
420 Options{}.CheckTest( wxT("/GUI/VerticalZooming"), false ) )
421 )
422 ),
423
424 Menu( wxT("TrackSize"), XXO("T&rack Size"),
425 Command( wxT("FitInWindow"), XXO("&Fit to Width"), FN(OnZoomFit),
426 TracksExistFlag(), wxT("Ctrl+F") ),
427 Command( wxT("FitV"), XXO("Fit to &Height"), FN(OnZoomFitV),
428 TracksExistFlag(), wxT("Ctrl+Shift+F") ),
429 Command( wxT("CollapseAllTracks"), XXO("&Collapse All Tracks"),
430 FN(OnCollapseAllTracks), TracksExistFlag(), wxT("Ctrl+Shift+C") ),
431 Command( wxT("ExpandAllTracks"), XXO("E&xpand Collapsed Tracks"),
432 FN(OnExpandAllTracks), TracksExistFlag(), wxT("Ctrl+Shift+X") )
433 ),
434
435 Menu( wxT("SkipTo"), XXO("Sk&ip to"),
436 Command( wxT("SkipSelStart"), XXO("Selection Sta&rt"),
437 FN(OnGoSelStart), TimeSelectedFlag(),
438 Options{ wxT("Ctrl+["), XO("Skip to Selection Start") } ),
439 Command( wxT("SkipSelEnd"), XXO("Selection En&d"), FN(OnGoSelEnd),
441 Options{ wxT("Ctrl+]"), XO("Skip to Selection End") } )
442 )
443 ),
444
445 Section( "Windows" ),
446
447 Section( "Other",
448 Command( wxT("ShowExtraMenus"), XXO("&Extra Menus (on/off)"),
449 FN(OnShowExtraMenus), AlwaysEnabledFlag,
450 Options{}.CheckTest( wxT("/GUI/ShowExtraMenus"), false ) ),
451 Command( wxT("ShowTrackNameInWaveform"), XXO("Track &Name (on/off)"),
452 FN(OnShowNameOverlay), AlwaysEnabledFlag,
453 Options{}.CheckTest( wxT("/GUI/ShowTrackNameInWaveform"), false ) ),
454 Command( wxT("ShowClipping"), XXO("&Show Clipping (on/off)"),
455 FN(OnShowClipping), AlwaysEnabledFlag,
456 Options{}.CheckTest( wxT("/GUI/ShowClipping"), false ) )
457 )
458 ) ) };
459 return menu;
460
461}
462
464 wxT(""),
465 Shared( ViewMenu() )
466};
467}
468
469#undef FN
wxT("CloseDown"))
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:35
wxEvtHandler CommandHandlerObject
const ReservedCommandFlag & ZoomInAvailableFlag()
const ReservedCommandFlag & ZoomOutAvailableFlag()
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & TracksExistFlag()
int ShowTrackNameInWaveformPrefsID()
Definition: GUIPrefs.cpp:253
int ShowClippingPrefsID()
Definition: GUIPrefs.cpp:247
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
FileConfig * gPrefs
Definition: Prefs.cpp:71
EffectReverbSettings preset
Definition: Reverb.cpp:46
declares abstract base class Track, TrackList, and iterators over TrackList
static Settings & settings()
Definition: TrackInfo.cpp:87
static const AudacityProject::AttachedObjects::RegisteredFactory key
Definition: ViewMenus.cpp:381
#define FN(X)
Definition: ViewMenus.cpp:391
static CommandHandlerObject & findCommandHandler(AudacityProject &project)
Definition: ViewMenus.cpp:385
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:89
Track subclass holding data representing sound (as notes, or samples, or ...)
Definition: Track.h:897
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:266
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
static CommandManager & Get(AudacityProject &project)
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
static void RebuildAllMenuBars()
Definition: Menus.cpp:687
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
Definition: Observer.h:199
A move-only handle representing a connection to a Publisher.
Definition: Observer.h:70
static void Broadcast(int id=0)
Call this static function to notify all PrefsListener objects.
Definition: Prefs.cpp:98
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
static ProjectSettings & Get(AudacityProject &project)
static ProjectWindow & Get(AudacityProject &project)
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:225
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:486
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:230
void SetMinimized(bool minimized)
Definition: TrackView.cpp:93
bool GetMinimized() const
Definition: TrackView.h:52
void SetExpandedHeight(int height)
Definition: TrackView.cpp:172
static int GetTrackHeight(const Track *pTrack)
Definition: TrackView.cpp:29
static TrackView & Get(Track &)
Definition: TrackView.cpp:69
static WaveTrackViewConstants::ZoomPresets Zoom1Choice()
static WaveTrackViewConstants::ZoomPresets Zoom2Choice()
static UndoManager & Get(AudacityProject &project)
Definition: UndoManager.cpp:67
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:216
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
static double GetDefaultZoom()
Definition: ZoomInfo.h:123
static double GetMaxZoom()
Definition: ZoomInfo.cpp:83
std::unique_ptr< MenuItem > Menu(const Identifier &internalName, const TranslatableString &title, Args &&... args)
std::unique_ptr< MenuPart > Section(const Identifier &internalName, Args &&... args)
std::unique_ptr< CommandItem > Command(const CommandID &name, const TranslatableString &label_in, void(Handler::*pmf)(const CommandContext &), CommandFlag flags, const CommandManager::Options &options={}, CommandHandlerFinder finder=FinderScope::DefaultFinder())
std::shared_ptr< BaseItem > BaseItemSharedPtr
Definition: Registry.h:72
AUDACITY_DLL_API unsigned MinimumTrackHeight()
Definition: TrackInfo.cpp:196
std::vector< CommandFlagOptions > & Options()
Definition: Menus.cpp:535
double GetZoomOfPreset(const AudacityProject &project, int preset)
Definition: ViewMenus.cpp:53
void DoZoomFitV(AudacityProject &project)
Definition: ViewMenus.cpp:121
double GetZoomOfSelection(const AudacityProject &project)
Definition: ViewMenus.cpp:26
A convenient default parameter for class template Site.
Definition: ClientData.h:28
Type of message published by UndoManager.
Definition: UndoManager.h:61
enum UndoRedoMessage::Type type
void OnCollapseAllTracks(const CommandContext &context)
Definition: ViewMenus.cpp:256
void OnExpandAllTracks(const CommandContext &context)
Definition: ViewMenus.cpp:268
Handler & operator=(const Handler &) PROHIBITED
Handler(const Handler &) PROHIBITED
void OnGoSelStart(const CommandContext &context)
Definition: ViewMenus.cpp:280
void OnUndoPushed(UndoRedoMessage message)
Definition: ViewMenus.cpp:353
Handler(AudacityProject &project)
Definition: ViewMenus.cpp:362
void OnGoSelEnd(const CommandContext &context)
Definition: ViewMenus.cpp:294
AudacityProject & mProject
Definition: ViewMenus.cpp:373
void OnZoomFit(const CommandContext &context)
Definition: ViewMenus.cpp:226
void OnZoomFitV(const CommandContext &context)
Definition: ViewMenus.cpp:233
void OnZoomIn(const CommandContext &context)
Definition: ViewMenus.cpp:166
void OnShowClipping(const CommandContext &context)
Definition: ViewMenus.cpp:320
void OnZoomOut(const CommandContext &context)
Definition: ViewMenus.cpp:185
void OnZoomToggle(const CommandContext &context)
Definition: ViewMenus.cpp:202
Observer::Subscription mUndoSubscription
Definition: ViewMenus.cpp:372
void OnAdvancedVZoom(const CommandContext &context)
Definition: ViewMenus.cpp:244
void OnShowExtraMenus(const CommandContext &context)
Definition: ViewMenus.cpp:308
void OnShowNameOverlay(const CommandContext &context)
Definition: ViewMenus.cpp:336
void OnZoomNormal(const CommandContext &context)
Definition: ViewMenus.cpp:175
void OnZoomSel(const CommandContext &context)
Definition: ViewMenus.cpp:192