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