Audacity 3.2.0
ScreenshotCommand.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity - A Digital Audio Editor
4 Copyright 1999-2018 Audacity Team
5 License: GPL v2 or later - see LICENSE.txt
6
7 Dominic Mazzoni
8 Dan Horgan
9 James Crook
10
11******************************************************************//*******************************************************************/
19
20
21#include "ScreenshotCommand.h"
22
23#include <mutex>
24#include <thread>
25
26#include "LoadCommands.h"
27#include "Project.h"
28#include <wx/app.h>
29#include <wx/toplevel.h>
30#include <wx/dcscreen.h>
31#include <wx/dcmemory.h>
32#include <wx/settings.h>
33#include <wx/bitmap.h>
34#include <wx/valgen.h>
35
36#include "../AdornedRulerPanel.h"
37#include "../TrackPanel.h"
38#include "../toolbars/ToolManager.h"
39#include "Prefs.h"
40#include "../ProjectWindow.h"
41#include "../Shuttle.h"
42#include "../ShuttleGui.h"
43#include "Track.h"
44#include "../widgets/VetoDialogHook.h"
45#include "CommandContext.h"
46#include "CommandManager.h"
47#include "CommandDispatch.h"
48
50{ XO("Screenshot") };
51
53
54
55static const EnumValueSymbol
57{
58 { XO("Window") },
59 { wxT("FullWindow"), XO("Full Window") },
60 { wxT("WindowPlus"), XO("Window Plus") },
61 { XO("Fullscreen") },
62 { XO("Toolbars") },
63 { XO("Effects") },
64 { XO("Scriptables") },
65 { XO("Preferences") },
66 { XO("Selectionbar") },
67 { wxT("SpectralSelection"), XO("Spectral Selection") },
68 { XO("Timer") },
69 { XO("Tools") },
70 { XO("Transport") },
71 { XO("Meter") },
72 { wxT("PlayMeter"), XO("Play Meter") },
73 { wxT("RecordMeter"), XO("Record Meter") },
74 { XO("Edit") },
75 { XO("Device") },
76 { XO("Scrub") },
77 { XO("Play-at-Speed") },
78 { XO("Trackpanel") },
79 { XO("Ruler") },
80 { XO("Tracks") },
81 { wxT("FirstTrack"), XO("First Track") },
82 { wxT("FirstTwoTracks"), XO("First Two Tracks") },
83 { wxT("FirstThreeTracks"), XO("First Three Tracks") },
84 { wxT("FirstFourTracks"), XO("First Four Tracks") },
85 { wxT("SecondTrack"), XO("Second Track") },
86 { wxT("TracksPlus"), XO("Tracks Plus") },
87 { wxT("FirstTrackPlus"), XO("First Track Plus") },
88 { wxT("AllTracks"), XO("All Tracks") },
89 { wxT("AllTracksPlus"), XO("All Tracks Plus") },
90};
91
92
93static const EnumValueSymbol
95{
96 // These are acceptable dual purpose internal/visible names
97 { XO("Blue") },
98 /* i18n-hint: This really means the color, not as in "white noise" */
99 { XC("White", "color") },
100 { XO("None") },
101};
102
103
105{
106 mbBringToTop=true;
107 mIgnore=NULL;
108
109 static VetoDialogHook::Scope scope{ MayCapture };
110}
111
112template<bool Const>
114 S.Define( mPath, wxT("Path"), wxString{});
115 S.DefineEnum( mWhat, wxT("CaptureWhat"), kwindow,kCaptureWhatStrings, nCaptureWhats );
116 S.DefineEnum( mBack, wxT("Background"), kNone, kBackgroundStrings, nBackgrounds );
117 S.Define( mbBringToTop, wxT("ToTop"), true );
118 return true;
119};
120
122 { return VisitSettings<false>(S); }
123
125 { return VisitSettings<true>(S); }
126
128{
129 S.AddSpace(0, 5);
130
131 S.StartMultiColumn(2, wxALIGN_CENTER);
132 {
133 S.TieTextBox( XXO("Path:"), mPath);
134 S.TieChoice( XXO("Capture What:"),
136 S.TieChoice( XXO("Background:"),
138 S.TieCheckBox( XXO("Bring To Top"), mbBringToTop);
139 }
140 S.EndMultiColumn();
141}
142
143// static member variable.
144void (*ScreenshotCommand::mIdleHandler)(wxIdleEvent& event) = NULL;
146// This static variable is used to get from an idle event to the screenshot
147// command that caused the idle event interception to be set up.
149
150// IdleHandler is expected to be called from EVT_IDLE when a dialog has been
151// fully created. Usually the dialog will have been created by invoking
152// an effects gui.
153void IdleHandler(wxIdleEvent& event){
154 event.Skip();
155 wxWindow * pWin = dynamic_cast<wxWindow*>(event.GetEventObject());
156 wxASSERT( pWin );
157 pWin->Unbind(wxEVT_IDLE, IdleHandler);
159 // We have the relevant window, so go and capture it.
162}
163
165{
167 pIdleHandlerProject = &project;
168}
169
171{
172 wxWindow *front = NULL;
173 wxWindow *proj = wxGetTopLevelParent( ProjectWindow::Find( project ) );
174
175 for (auto & win : wxTopLevelWindows)
176 {
177 win = wxGetTopLevelParent(win);
178 if (win != mIgnore && win != proj && win->IsShown()) {
179 front = win;
180 break;
181 }
182 }
183
184 if (!front || !front->IsTopLevel()) {
185 return (wxTopLevelWindow *)proj;
186 }
187
188 return (wxTopLevelWindow *)front;
189}
190
192{
193 wxRect r;
194
195 r.x = 16;
196 r.y = 16;
197 r.width = r.x * 2;
198 r.height = r.y * 2;
199
200 return r;
201}
202
203static void Yield()
204{
205 using namespace std::chrono;
206 int cnt;
207 for (cnt = 10; cnt && !wxTheApp->Yield(true); cnt--)
208 std::this_thread::sleep_for(10ms);
209 std::this_thread::sleep_for(200ms);
210 for (cnt = 10; cnt && !wxTheApp->Yield(true); cnt--)
211 std::this_thread::sleep_for(10ms);
212}
213
215 const CommandContext & context,
216 const wxString &filename,
217 wxWindow *window, wxRect r,
218 bool bg)
219{
220 int width = r.width;
221 int height = r.height;
222 if( r.width == 0 )
223 return false;
224 if (window ) {
225 wxWindow * win = window;
226 wxTopLevelWindow * top_win= nullptr;
227 if( !window->IsTopLevel())
228 win = wxGetTopLevelParent(window);
229 top_win = dynamic_cast<wxTopLevelWindow*>( win );
230 if( (!bHasBringToTop || mbBringToTop) && (!top_win || !top_win->IsActive()) ){
231 win->Raise();
232 Yield();
233 }
234 }
235
236
237 int screenW, screenH;
238 wxDisplaySize(&screenW, &screenH);
239 // Bug 1378 workaround.
240 // wx 3.0.2 has a bug in Blit from ScreenDC where in default mode
241 // much is drawn transparent - including for example black text!
242 // Forcing 24 bit here is a workaround.
243 wxBitmap full(screenW, screenH, 24);
244
245 wxScreenDC screenDC;
246 wxMemoryDC fullDC;
247
248#if defined(__WXMAC__) && !wxCHECK_VERSION(3, 0, 0)
249 full = DoGetAsBitmap(NULL);
250#else
251 // We grab the whole screen image since there seems to be a problem with
252 // using non-zero source coordinates on OSX. (as of wx2.8.9)
253 fullDC.SelectObject(full);
254 fullDC.Blit(0, 0, screenW, screenH, &screenDC, 0, 0);
255 fullDC.SelectObject(wxNullBitmap);
256#endif
257
258 //wxRect r(x, y, width, height);
259
260
261 // Convert to screen coordinates if needed
262 if (window && window->GetParent() && !window->IsTopLevel()) {
263 r.SetPosition(window->GetParent()->ClientToScreen(r.GetPosition()));
264 }
265
266 // Ensure within bounds (x/y are negative on Windows when maximized)
267 r.Intersect(wxRect(0, 0, screenW, screenH));
268
269 // Extract the actual image
270 wxBitmap part = full.GetSubBitmap(r);
271
272 // Add a background
273 if (bg && mBackground) {
274 wxRect b = GetBackgroundRect();
275
276 wxBitmap back(width + b.width, height + b.height);
277 fullDC.SelectObject(back);
278
279 fullDC.SetBackground(wxBrush(mBackColor, wxBRUSHSTYLE_SOLID));
280 fullDC.Clear();
281
282 fullDC.DrawBitmap(part, b.x, b.y);
283 fullDC.SelectObject(wxNullBitmap);
284
285 part = back;
286 }
287
288 // Save the final image
289 wxImage image = part.ConvertToImage();
290 ::wxBell();
291
292 if (image.SaveFile(filename)) {
293 // flush
294 context.Status( wxString::Format( _("Saved %s"), filename ), true );
295 }
296 else {
297 context.Error(
298 wxString::Format( _("Error trying to save file: %s"), filename ) );
299 return false;
300 }
301 return true;
302}
303
305 const CommandContext & context,
306 ToolManager *man, int type, const wxString &name)
307{
308 bool visible = man->IsVisible(type);
309 if (!visible) {
310 man->ShowHide(type);
311 Yield();
312 }
313
314 wxWindow *w = man->GetToolBar(type);
315 int x = 0, y = 0;
316 int width, height;
317
318 w->ClientToScreen(&x, &y);
319 w->GetParent()->ScreenToClient(&x, &y);
320 w->GetClientSize(&width, &height);
321
322 bool result = Capture(context, name, w, wxRect(x, y, width, height));
323
324 if (!visible) {
325 man->ShowHide(type);
326 if (mIgnore)
327 mIgnore->Raise();
328 }
329 return result;
330}
331
333 const CommandContext & context,
334 wxWindow *win, const wxString &FileName)
335{
336 int x = 0, y = 0;
337 int width, height;
338
339 win->ClientToScreen(&x, &y);
340 win->GetParent()->ScreenToClient(&x, &y);
341 win->GetClientSize(&width, &height);
342
343 return Capture(context, FileName, win, wxRect(x, y, width, height));
344}
345
346// Handed a dialog, which it is given the option to capture.
347bool ScreenshotCommand::MayCapture( wxDialog * pDlg )
348{
349 if( mIdleHandler == NULL )
350 return false;
351 pDlg->Bind( wxEVT_IDLE, mIdleHandler );
352 mIdleHandler = NULL;
353 pDlg->ShowModal();
354 return true;
355}
356
358 const CommandContext & context,
359 wxWindow * pWin )
360{
361 using namespace std::chrono;
362 wxDialog * pDlg = dynamic_cast<wxDialog*>(pWin);
363 if( !pDlg ){
364 wxLogDebug("Event from bogus dlg" );
365 return;
366 }
367
368 wxPoint Pos = pDlg->GetScreenPosition();
369 wxSize Siz = pDlg->GetSize();
370 wxString Title = pDlg->GetTitle();
371
372 // Remove '/' from "Sliding Time Scale/Pitch Shift..."
373 // and any other effects that have illegal filename characters.
374 Title.Replace( "/", "" );
375 Title.Replace( ":", "" );
376 wxString Name = mDirToWriteTo + Title + ".png";
377
378 wxLogDebug("Taking screenshot of window %s (%i,%i,%i,%i)", Name,
379 Pos.x, Pos.y, Siz.x, Siz.y );
380 // This delay is needed, as dialogs take a moment or two to fade in.
381 std::this_thread::sleep_for(400ms);
382 // JKC: The border of 7 pixels was determined from a trial capture and then measuring
383 // in the GIMP. I'm unsure where the border comes from.
384 Capture( context, Name, pDlg, wxRect((int)Pos.x+7, (int)Pos.y, (int)Siz.x-14, (int)Siz.y-7) );
385
386 // We've captured the dialog, so now dismiss the dialog.
387 wxCommandEvent Evt( wxEVT_BUTTON, wxID_CANCEL );
388 pDlg->GetEventHandler()->AddPendingEvent( Evt );
389}
390
392 const CommandContext & context,
393 AudacityProject * pProject, const wxString &FileName )
394{
395 using namespace std::chrono;
396 (void)&FileName;//compiler food.
397 (void)&context;
398 CommandManager &commandManager = CommandManager::Get( *pProject );
399
400 // Yucky static variables. Is there a better way? The problem is that we need the
401 // idle callback to know more about what to do.
402#ifdef __WXMSW__
403 mDirToWriteTo = FileName.BeforeLast('\\') + "\\";
404#else
405 mDirToWriteTo = FileName.BeforeLast('/') + "/";
406#endif
407 mpShooter = this;
408 const int nPrefsPages = 19;
409
410 for( int i=0;i<nPrefsPages;i++){
411 // The handler is cleared each time it is used.
412 SetIdleHandler( context.project );
413 gPrefs->Write(wxT("/Prefs/PrefsCategory"), (long)i);
414 gPrefs->Flush();
415 CommandID Command{ wxT("Preferences") };
416 const CommandContext projectContext( *pProject );
417 if( !::HandleTextualCommand( commandManager,
418 Command, projectContext, AlwaysEnabledFlag, true ) )
419 {
420 // using GET in a log message for devs' eyes only
421 wxLogDebug("Command %s not found", Command.GET() );
422 }
423 // This sleep is not needed, but gives user a chance to see the
424 // dialogs as they whizz by.
425 std::this_thread::sleep_for(200ms);
426 }
427}
428
430 const CommandContext & context,
431 AudacityProject * pProject, const wxString &FileName )
432{
433 (void)pProject;
434 (void)&FileName;//compiler food.
435 (void)&context;
436#define TRICKY_CAPTURE
437#define CAPTURE_NYQUIST_TOO
438 // Commented out the effects that don't have dialogs.
439 // Also any problematic ones,
440 CaptureCommands( context, {
441#ifdef TRICKY_CAPTURE
442 //"Contrast...", // renamed
443 "ContrastAnalyser",
444 //"Plot Spectrum...", // renamed
445 "PlotSpectrum",
446
447 "Auto Duck...", // needs a track below.
448 //"Spectral Edit Multi Tool",
449 "Spectral Edit Parametric EQ...", // Needs a spectral selection.
450 "Spectral Edit Shelves...",
451
452 //"Noise Reduction...", // Exits twice...
453 //"SC4...", //Has 'Close' rather than 'Cancel'.
454#endif
455 "Amplify...",
456 "Bass and Treble...",
457 "Change Pitch...",
458 "Change Speed...",
459 "Change Tempo...",
460 "Click Removal...",
461 "Compressor...",
462 "Distortion...",
463 "Echo...",
464 //"Equalization...",
465 "Filter Curve EQ...",
466 "Graphic EQ...",
467 //"Fade In",
468 //"Fade Out",
469 //"Invert",
470 "Normalize...",
471 "Paulstretch...",
472 "Phaser...",
473 //"Repair",
474 "Repeat...",
475 "Reverb...",
476 //"Reverse",
477 "Sliding Stretch...",
478 "Truncate Silence...",
479 "Wahwah...",
480 // Sole LADSPA effect...
481#ifdef CAPTURE_NYQUIST_TOO
482 "Adjustable Fade...",
483 "Clip Fix...",
484 //"Crossfade Clips",
485 "Crossfade Tracks...",
486 "Delay...",
487 "High Pass Filter...",
488 "Limiter...",
489 "Low Pass Filter...",
490 "Notch Filter...",
491 "Nyquist Effects Prompt...",
492 //"Studio Fade Out",
493 "Tremolo...",
494 "Vocal Reduction and Isolation...",
495 "Vocal Remover...",
496 "Vocoder...",
497#endif
498 // Generators.....
499 "Chirp...",
500 "DTMF Tones...",
501 "Noise...",
502 "Silence...",
503 "Tone...",
504#ifdef CAPTURE_NYQUIST_TOO
505 "Pluck...",
506 "Rhythm Track...",
507 "Risset Drum...",
508 "Sample Data Import...",
509#endif
510 // Analyzers...
511 "Find Clipping...",
512#ifdef CAPTURE_NYQUIST_TOO
513 "Beat Finder...",
514 "Label Sounds...",
515 "Regular Interval Labels...",
516 "Sample Data Export...",
517#endif
518 } );
519}
520
522 const CommandContext & context,
523 AudacityProject * pProject, const wxString &FileName )
524{
525 (void)pProject;
526 (void)&FileName;//compiler food.
527 (void)&context;
528
529 CaptureCommands( context, {
530 "SelectTime",
531 "SelectFrequencies",
532 "SelectTracks",
533 "SetTrackStatus",
534 "SetTrackAudio",
535 "SetTrackVisuals",
536 "GetPreference",
537 "SetPreference",
538 "SetClip",
539 "SetEnvelope",
540 "SetLabel",
541 "SetProject",
542
543 "Select",
544 "SetTrack",
545 "GetInfo",
546 "Message",
547 "Help", // Help on individual commands
548 "Import2",
549 "Export2",
550 "OpenProject2",
551 "SaveProject2",
552 "Drag",
553 "CompareAudio",
554 "Screenshot",
555 } );
556
557}
558
559
561 const CommandContext & context, const wxArrayStringEx & Commands )
562{
563 using namespace std::chrono;
564 AudacityProject * pProject = &context.project;
566 wxString Str;
567 // Yucky static variables. Is there a better way? The problem is that we need the
568 // idle callback to know more about what to do.
569#ifdef __WXMSW__
570 mDirToWriteTo = mFileName.BeforeLast('\\') + "\\";
571#else
572 mDirToWriteTo = mFileName.BeforeLast('/') + "/";
573#endif
574 mpShooter = this;
575
576 for( size_t i=0;i<Commands.size();i++){
577 // The handler is cleared each time it is used.
578 SetIdleHandler( context.project );
579 Str = Commands[i];
580 const CommandContext projectContext( *pProject );
581 if( !manager.HandleTextualCommand( Str, projectContext, AlwaysEnabledFlag, true ) )
582 {
583 wxLogDebug("Command %s not found", Str);
584 }
585 // This particular sleep is not needed, but gives user a chance to see the
586 // dialogs as they whizz by.
587 std::this_thread::sleep_for(200ms);
588 }
589}
590
591wxString ScreenshotCommand::MakeFileName(const wxString &path, const wxString &basename)
592{
593 // If the path is a full file name, then use it.
594 if( path.EndsWith( ".png" ) )
595 return path;
596
597 // Otherwise make up a file name that has not been used already.
598 wxFileName prefixPath;
599 prefixPath.AssignDir(path);
600 wxString prefix = prefixPath.GetPath
601 (wxPATH_GET_VOLUME|wxPATH_GET_SEPARATOR);
602
603 wxString filename;
604 int i = 0;
605 do {
606 filename.Printf(wxT("%s%s%03d.png"),
607 prefix, basename, i);
608 i++;
609 } while (::wxFileExists(filename));
610
611 return filename;
612}
613
615{
616 // Read the parameters that were passed in
619
620 // Build a suitable filename
622 kCaptureWhatStrings[ mCaptureMode ].Translation() );
623
624 if (mBack == kBlue)
625 {
626 mBackground = true;
627 mBackColor = wxColour(51, 102, 153);
628 }
629 else if (mBack == kWhite)
630 {
631 mBackground = true;
632 mBackColor = wxColour(255, 255, 255);
633 }
634 else
635 {
636 mBackground = false;
637 }
638
639}
640
641wxRect ScreenshotCommand::GetWindowRect(wxTopLevelWindow *w){
642 int x = 0, y = 0;
643 int width, height;
644
645 w->ClientToScreen(&x, &y);
646 w->GetClientSize(&width, &height);
647 return wxRect( x,y,width,height);
648}
649
650wxRect ScreenshotCommand::GetFullWindowRect(wxTopLevelWindow *w){
651
652 wxRect r = w->GetRect();
653 r.SetPosition(w->GetScreenPosition());
654 r = w->GetScreenRect();
655
656#if defined(__WXGTK__)
657 // In wxGTK, we need to include decoration sizes
658 r.width += (wxSystemSettings::GetMetric(wxSYS_BORDER_X, w) * 2);
659 r.height += wxSystemSettings::GetMetric(wxSYS_CAPTION_Y, w) +
660 wxSystemSettings::GetMetric(wxSYS_BORDER_Y, w);
661#endif
663 {
664 // background colour not selected but we want a background
665 wxRect b = GetBackgroundRect();
666 r.x = (r.x - b.x) >= 0 ? (r.x - b.x): 0;
667 r.y = (r.y - b.y) >= 0 ? (r.y - b.y): 0;
668 r.width += b.width;
669 r.height += b.height;
670 }
671
672 return r;
673}
674
676 int width, height;
677 wxDisplaySize(&width, &height);
678
679 return wxRect( 0,0,width,height);
680}
681
683 //AdornedRulerPanel *ruler = panel->mRuler;
684
685 int h = panel->GetRuler()->GetRulerHeight();
686 int x = 0, y = -h;
687 int width, height;
688
689 panel->ClientToScreen(&x, &y);
690 panel->GetParent()->ScreenToClient(&x, &y);
691 panel->GetClientSize(&width, &height);
692 return wxRect(x, y, width, height + h);
693}
694
696 int x = 0, y = 0;
697 int width, height;
698
699 ruler->ClientToScreen(&x, &y);
700 ruler->GetParent()->ScreenToClient(&x, &y);
701 ruler->GetClientSize(&width, &height);
702 height = ruler->GetRulerHeight();
703 return wxRect( x, y, width, height);
704}
705
707 int x = 0, y = 0;
708 int width, height;
709
710 panel->ClientToScreen(&x, &y);
711 panel->GetParent()->ScreenToClient(&x, &y);
712 panel->GetClientSize(&width, &height);
713
714 return wxRect( x, y, width, height);
715}
716
718 auto FindRectangle = []( TrackPanel &panel, Track &t )
719 {
720 wxRect rect = panel.FindFocusedTrackRect( &t );
721
722 // Reposition it relative to parent of panel
723 rect.SetPosition(
724 panel.GetParent()->ScreenToClient(
725 panel.ClientToScreen(
726 rect.GetPosition())));
727
728 return rect;
729 };
730
731 int count = 0;
732 for (auto t : TrackList::Get( *pProj ).Leaders()) {
733 count += 1;
734 if( count > n )
735 {
736 wxRect r = FindRectangle( *panel, *t );
737 return r;
738 }
739 }
740 return wxRect( 0,0,0,0);
741}
742
743wxString ScreenshotCommand::WindowFileName(AudacityProject * proj, wxTopLevelWindow *w){
744 if (w != ProjectWindow::Find( proj ) && !w->GetTitle().empty()) {
746 kCaptureWhatStrings[ mCaptureMode ].Translation() +
747 (wxT("-") + w->GetTitle() + wxT("-")));
748 }
749 return mFileName;
750}
751
753{
755 //Don't reset the toolbars to a known state.
756 //We will be capturing variations of them.
757 //ToolManager::Get( context.project ).Reset();
758
759 wxTopLevelWindow *w = GetFrontWindow(&context.project);
760 if (!w)
761 return false;
762
763 TrackPanel *panel = &TrackPanel::Get( context.project );
764 AdornedRulerPanel *ruler = panel->GetRuler();
765
766 int nTracks = TrackList::Get( context.project ).size();
767
768 int x1,y1,x2,y2;
769 w->ClientToScreen(&x1, &y1);
770 panel->ClientToScreen(&x2, &y2);
771
772 wxPoint p( x2-x1, y2-y1);
773
774 auto &toolManager = ToolManager::Get( context.project );
775
776 switch (mCaptureMode) {
777 case kwindow:
778 return Capture(context, WindowFileName( &context.project, w ) , w, GetWindowRect(w));
779 case kfullwindow:
780 case kwindowplus:
781 return Capture(context, WindowFileName( &context.project, w ) , w, GetFullWindowRect(w));
782 case kfullscreen:
783 return Capture(context, mFileName, w,GetScreenRect());
784 case ktoolbars:
785 return CaptureDock(context, toolManager.GetTopDock(), mFileName);
786 case kscriptables:
787 CaptureScriptables(context, &context.project, mFileName);
788 break;
789 case keffects:
790 CaptureEffects(context, &context.project, mFileName);
791 break;
792 case kpreferences:
793 CapturePreferences(context, &context.project, mFileName);
794 break;
795 case kselectionbar:
796 return CaptureToolbar(context, &toolManager, SelectionBarID, mFileName);
798 return CaptureToolbar(context, &toolManager, SpectralSelectionBarID, mFileName);
799 case ktimer:
800 return CaptureToolbar(context, &toolManager, TimeBarID, mFileName);
801 case ktools:
802 return CaptureToolbar(context, &toolManager, ToolsBarID, mFileName);
803 case ktransport:
804 return CaptureToolbar(context, &toolManager, TransportBarID, mFileName);
805 case kmeter:
806 return CaptureToolbar(context, &toolManager, MeterBarID, mFileName);
807 case krecordmeter:
808 return CaptureToolbar(context, &toolManager, RecordMeterBarID, mFileName);
809 case kplaymeter:
810 return CaptureToolbar(context, &toolManager, PlayMeterBarID, mFileName);
811 case kedit:
812 return CaptureToolbar(context, &toolManager, EditBarID, mFileName);
813 case kdevice:
814 return CaptureToolbar(context, &toolManager, DeviceBarID, mFileName);
815 case ktranscription:
816 return CaptureToolbar(context, &toolManager, TranscriptionBarID, mFileName);
817 case kscrub:
818 return CaptureToolbar(context, &toolManager, ScrubbingBarID, mFileName);
819 case ktrackpanel:
820 return Capture(context, mFileName, panel, GetPanelRect(panel));
821 case kruler:
822 return Capture(context, mFileName, ruler, GetRulerRect(ruler) );
823 case ktracks:
824 return Capture(context, mFileName, panel, GetTracksRect(panel));
825 case kfirsttrack:
826 return Capture(context, mFileName, panel, GetTrackRect( &context.project, panel, 0 ) );
827 case ksecondtrack:
828 return Capture(context, mFileName, panel, GetTrackRect( &context.project, panel, 1 ) );
829 case ktracksplus:
830 { wxRect r = GetTracksRect(panel);
831 r.SetTop( r.GetTop() - ruler->GetRulerHeight() );
832 r.SetHeight( r.GetHeight() + ruler->GetRulerHeight() );
833 return Capture(context, mFileName, panel, r);
834 }
835 case kfirsttrackplus:
836 { wxRect r = GetTrackRect(&context.project, panel, 0 );
837 r.SetTop( r.GetTop() - ruler->GetRulerHeight() );
838 r.SetHeight( r.GetHeight() + ruler->GetRulerHeight() );
839 return Capture(context, mFileName, panel, r );
840 }
841 case kfirsttwotracks:
842 { wxRect r = GetTrackRect( &context.project, panel, 0 );
843 r = r.Union( GetTrackRect( &context.project, panel, 1 ));
844 return Capture(context, mFileName, panel, r );
845 }
847 { wxRect r = GetTrackRect( &context.project, panel, 0 );
848 r = r.Union( GetTrackRect( &context.project, panel, 2 ));
849 return Capture(context, mFileName, panel, r );
850 }
851 case kfirstfourtracks:
852 { wxRect r = GetTrackRect( &context.project, panel, 0 );
853 r = r.Union( GetTrackRect( &context.project, panel, 3 ));
854 return Capture(context, mFileName, panel, r );
855 }
856 case kalltracks:
857 { wxRect r = GetTrackRect( &context.project, panel, 0 );
858 r = r.Union( GetTrackRect( &context.project, panel, nTracks-1 ));
859 return Capture(context, mFileName, panel, r );
860 }
861 case kalltracksplus:
862 { wxRect r = GetTrackRect( &context.project, panel, 0 );
863 r.SetTop( r.GetTop() - ruler->GetRulerHeight() );
864 r.SetHeight( r.GetHeight() + ruler->GetRulerHeight() );
865 r = r.Union( GetTrackRect( &context.project, panel, nTracks-1 ));
866 return Capture(context, mFileName, panel, r );
867 }
868 default:
869 return false;
870 }
871
872 return true;
873}
wxImage(22, 22)
wxT("CloseDown"))
bool HandleTextualCommand(CommandManager &commandManager, const CommandID &Str, const CommandContext &context, CommandFlag flags, bool alwaysEnabled)
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:35
static TransactionScope::Factory::Scope scope
const TranslatableString name
Definition: Distortion.cpp:82
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
#define XC(s, c)
Definition: Internat.h:37
#define _(s)
Definition: Internat.h:75
FileConfig * gPrefs
Definition: Prefs.cpp:71
static const AttachedProjectObjects::RegisteredFactory manager
static AudacityProject * pIdleHandlerProject
static const EnumValueSymbol kBackgroundStrings[ScreenshotCommand::nBackgrounds]
static const EnumValueSymbol kCaptureWhatStrings[ScreenshotCommand::nCaptureWhats]
void IdleHandler(wxIdleEvent &event)
static void Yield()
TranslatableStrings Msgids(const EnumValueSymbol strings[], size_t nStrings)
Convenience function often useful when adding choice controls.
#define S(N)
Definition: ToChars.cpp:64
@ ScrubbingBarID
Definition: ToolBar.h:79
@ RecordMeterBarID
Definition: ToolBar.h:75
@ PlayMeterBarID
Definition: ToolBar.h:76
@ DeviceBarID
Definition: ToolBar.h:80
@ SelectionBarID
Definition: ToolBar.h:81
@ TranscriptionBarID
Definition: ToolBar.h:78
@ TimeBarID
Definition: ToolBar.h:89
@ TransportBarID
Definition: ToolBar.h:72
@ MeterBarID
Definition: ToolBar.h:74
@ ToolsBarID
Definition: ToolBar.h:73
@ EditBarID
Definition: ToolBar.h:77
declares abstract base class Track, TrackList, and iterators over TrackList
This is an Audacity Specific ruler panel which additionally has border, selection markers,...
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:89
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
virtual void Error(const wxString &message) const
virtual void Status(const wxString &message, bool bFlush=false) const
AudacityProject & project
CommandManager implements a system for organizing all user-callable commands.
static CommandManager & Get(AudacityProject &project)
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
static ProjectWindow * Find(AudacityProject *pProject)
Implements a command for capturing various areas of the screen or project window. It's one big if-els...
static ScreenshotCommand * mpShooter
static bool MayCapture(wxDialog *pDlg)
bool CaptureToolbar(const CommandContext &Context, ToolManager *man, int type, const wxString &name)
wxRect GetTracksRect(TrackPanel *panel)
void CaptureScriptables(const CommandContext &Context, AudacityProject *pProject, const wxString &fileName)
void CaptureWindowOnIdle(const CommandContext &context, wxWindow *pWin)
static void SetIdleHandler(AudacityProject &project)
static void(* mIdleHandler)(wxIdleEvent &event)
wxRect GetRulerRect(AdornedRulerPanel *ruler)
bool VisitSettings(SettingsVisitorBase< Const > &S)
void PopulateOrExchange(ShuttleGui &S) override
bool Capture(const CommandContext &Context, const wxString &basename, wxWindow *window, wxRect rect, bool bg=false)
wxString WindowFileName(AudacityProject *proj, wxTopLevelWindow *w)
wxString MakeFileName(const wxString &path, const wxString &basename)
wxTopLevelWindow * GetFrontWindow(AudacityProject *project)
wxRect GetPanelRect(TrackPanel *panel)
wxRect GetTrackRect(AudacityProject *pProj, TrackPanel *panel, int n)
bool CaptureDock(const CommandContext &Context, wxWindow *win, const wxString &fileName)
void CaptureEffects(const CommandContext &Context, AudacityProject *pProject, const wxString &fileName)
wxRect GetWindowRect(wxTopLevelWindow *w)
void CapturePreferences(const CommandContext &Context, AudacityProject *pProject, const wxString &fileName)
wxRect GetFullWindowRect(wxTopLevelWindow *w)
bool Apply(const CommandContext &context) override
static const ComponentInterfaceSymbol Symbol
void CaptureCommands(const CommandContext &Context, const wxArrayStringEx &Commands)
Visitor of effect or command parameters. This is a base class with lots of virtual functions that do ...
Definition: Shuttle.h:115
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
class ToolManager
Definition: ToolManager.h:55
static ToolManager & Get(AudacityProject &project)
void ShowHide(int type)
bool IsVisible(int type)
ToolBar * GetToolBar(int type) const
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:225
auto Leaders() -> TrackIterRange< TrackType >
Definition: Track.h:1471
size_t size() const
Definition: Track.cpp:1014
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:486
The TrackPanel class coordinates updates and operations on the main part of the screen which contains...
Definition: TrackPanel.h:65
AdornedRulerPanel * GetRuler()
Definition: TrackPanel.h:172
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:230
wxRect FindFocusedTrackRect(const Track *target)
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
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())
BuiltinCommandsModule::Registration< ScreenshotCommand > reg