1 /**********************************************************************
2
3 Audacity - A Digital Audio Editor
4 Copyright 1999-2018 Audacity Team
5 License: wxWidgets
6
7 James Crook
8
9 ******************************************************************//**
10
11 \file GetInfoCommand.cpp
12 \brief Contains definitions for GetInfoCommand class.
13 This class now lists
14 - Commands
15 - Menus
16 - Tracks
17 - Clips
18 - Labels
19 - Boxes
20
21 *//*******************************************************************/
22
23
24 #include "GetInfoCommand.h"
25
26 #include "LoadCommands.h"
27 #include "Project.h"
28 #include "../ProjectWindows.h"
29 #include "CommandManager.h"
30 #include "CommandTargets.h"
31 #include "../effects/EffectManager.h"
32 #include "../widgets/Overlay.h"
33 #include "../TrackPanelAx.h"
34 #include "../TrackPanel.h"
35 #include "../WaveClip.h"
36 #include "ViewInfo.h"
37 #include "../WaveTrack.h"
38 #include "../LabelTrack.h"
39 #include "../Envelope.h"
40
41 #include "SelectCommand.h"
42 #include "../ShuttleGui.h"
43 #include "CommandContext.h"
44
45 #include "../prefs/PrefsDialog.h"
46 #include "../Shuttle.h"
47 #include "../PluginManager.h"
48 #include "../tracks/ui/TrackView.h"
49 #include "../ShuttleGui.h"
50
51 #include <wx/frame.h>
52 #include <wx/log.h>
53 #include <wx/menu.h>
54
55 const ComponentInterfaceSymbol GetInfoCommand::Symbol
56 { XO("Get Info") };
57
58 namespace{ BuiltinCommandsModule::Registration< GetInfoCommand > reg; }
59 enum {
60 kCommands,
61 //kCommandsPlus,
62 kMenus,
63 kPreferences,
64 kTracks,
65 kClips,
66 kEnvelopes,
67 kLabels,
68 kBoxes,
69 nTypes
70 };
71
72 static const EnumValueSymbol kTypes[nTypes] =
73 {
74 { XO("Commands") },
75 //{ wxT("CommandsPlus"), XO("Commands Plus") },
76 { XO("Menus") },
77 { XO("Preferences") },
78 { XO("Tracks") },
79 { XO("Clips") },
80 { XO("Envelopes") },
81 { XO("Labels") },
82 { XO("Boxes") },
83 };
84
85 enum {
86 kJson,
87 kLisp,
88 kBrief,
89 nFormats
90 };
91
92 static const EnumValueSymbol kFormats[nFormats] =
93 {
94 // These are acceptable dual purpose internal/visible names
95
96 /* i18n-hint JavaScript Object Notation */
97 { XO("JSON") },
98 /* i18n-hint name of a computer programming language */
99 { XO("LISP") },
100 { XO("Brief") }
101 };
102
103
104
DefineParams(ShuttleParams & S)105 bool GetInfoCommand::DefineParams( ShuttleParams & S ){
106 S.DefineEnum( mInfoType, wxT("Type"), 0, kTypes, nTypes );
107 S.DefineEnum( mFormat, wxT("Format"), 0, kFormats, nFormats );
108 return true;
109 }
110
PopulateOrExchange(ShuttleGui & S)111 void GetInfoCommand::PopulateOrExchange(ShuttleGui & S)
112 {
113 S.AddSpace(0, 5);
114
115 S.StartMultiColumn(2, wxALIGN_CENTER);
116 {
117 S.TieChoice( XXO("Type:"),
118 mInfoType, Msgids( kTypes, nTypes ));
119 S.TieChoice( XXO("Format:"),
120 mFormat, Msgids( kFormats, nFormats ));
121 }
122 S.EndMultiColumn();
123 }
124
Apply(const CommandContext & context)125 bool GetInfoCommand::Apply(const CommandContext &context)
126 {
127 if( mFormat == kJson )
128 return ApplyInner( context );
129
130 if( mFormat == kLisp )
131 {
132 CommandContext LispyContext(
133 context.project,
134 std::make_unique<LispifiedCommandOutputTargets>( *context.pOutput.get() )
135 );
136 return ApplyInner( LispyContext );
137 }
138
139 if( mFormat == kBrief )
140 {
141 CommandContext BriefContext(
142 context.project,
143 std::make_unique<BriefCommandOutputTargets>( *context.pOutput.get() )
144 );
145 return ApplyInner( BriefContext );
146 }
147
148 return false;
149 }
150
ApplyInner(const CommandContext & context)151 bool GetInfoCommand::ApplyInner(const CommandContext &context)
152 {
153 switch( mInfoType ){
154 // flag of 1 to include parameterless commands.
155 case kCommands : return SendCommands( context, 1 );
156 case kMenus : return SendMenus( context );
157 case kPreferences : return SendPreferences( context );
158 case kTracks : return SendTracks( context );
159 case kClips : return SendClips( context );
160 case kEnvelopes : return SendEnvelopes( context );
161 case kLabels : return SendLabels( context );
162 case kBoxes : return SendBoxes( context );
163 default:
164 context.Status( "Command options not recognised" );
165 }
166 return false;
167 }
168
SendMenus(const CommandContext & context)169 bool GetInfoCommand::SendMenus(const CommandContext &context)
170 {
171 wxMenuBar * pBar = GetProjectFrame( context.project ).GetMenuBar();
172 if(!pBar ){
173 wxLogDebug("No menus");
174 return false;
175 }
176
177 size_t cnt = pBar->GetMenuCount();
178 size_t i;
179 wxString Label;
180 context.StartArray();
181 for(i=0;i<cnt;i++)
182 {
183 Label = pBar->GetMenuLabelText( i );
184 context.StartStruct();
185 context.AddItem( 0, "depth" );
186 context.AddItem( 0, "flags" );
187 context.AddItem( Label, "label" );
188 context.AddItem( "", "accel" );
189 context.EndStruct();
190 ExploreMenu( context, pBar->GetMenu( i ), pBar->GetId(), 1 );
191 }
192 context.EndArray();
193 return true;
194 }
195
196 #include "Prefs.h"
197
198 namespace {
199
200 /**************************************************************************//**
201 \brief Shuttle that retrieves a JSON format definition of a command's parameters.
202 ********************************************************************************/
203 class ShuttleGuiGetDefinition : public ShuttleGui, public CommandMessageTargetDecorator
204 {
205 public:
206 ShuttleGuiGetDefinition(wxWindow * pParent,CommandMessageTarget & target );
207 virtual ~ShuttleGuiGetDefinition();
208
209 wxCheckBox * TieCheckBox(
210 const TranslatableString &Prompt,
211 const BoolSetting &Setting) override;
212 wxCheckBox * TieCheckBoxOnRight(
213 const TranslatableString &Prompt,
214 const BoolSetting &Setting) override;
215
216 wxChoice *TieChoice(
217 const TranslatableString &Prompt,
218 const ChoiceSetting &choiceSetting ) override;
219
220 wxChoice * TieNumberAsChoice(
221 const TranslatableString &Prompt,
222 const IntSetting &Setting,
223 const TranslatableStrings & Choices,
224 const std::vector<int> * pInternalChoices, int iNoMatchSelector ) override;
225
226 wxTextCtrl * TieTextBox(
227 const TranslatableString &Prompt,
228 const StringSetting &Setting,
229 const int nChars) override;
230 wxTextCtrl * TieIntegerTextBox(
231 const TranslatableString & Prompt,
232 const IntSetting &Setting,
233 const int nChars) override;
234 wxTextCtrl * TieNumericTextBox(
235 const TranslatableString & Prompt,
236 const DoubleSetting &Setting,
237 const int nChars) override;
238 wxSlider * TieSlider(
239 const TranslatableString & Prompt,
240 const IntSetting &Setting,
241 const int max,
242 const int min = 0) override;
243 wxSpinCtrl * TieSpinCtrl(
244 const TranslatableString &Prompt,
245 const IntSetting &Setting,
246 const int max,
247 const int min) override;
248 };
249
ShuttleGuiGetDefinition(wxWindow * pParent,CommandMessageTarget & target)250 ShuttleGuiGetDefinition::ShuttleGuiGetDefinition(
251 wxWindow * pParent,CommandMessageTarget & target )
252 : ShuttleGui( pParent, eIsGettingMetadata ),
253 CommandMessageTargetDecorator( target )
254 {
255
256 }
~ShuttleGuiGetDefinition(void)257 ShuttleGuiGetDefinition::~ShuttleGuiGetDefinition(void)
258 {
259 }
260
TieCheckBox(const TranslatableString & Prompt,const BoolSetting & Setting)261 wxCheckBox * ShuttleGuiGetDefinition::TieCheckBox(
262 const TranslatableString &Prompt,
263 const BoolSetting &Setting)
264 {
265 StartStruct();
266 AddItem( Setting.GetPath(), "id" );
267 AddItem( Prompt.Translation(), "prompt" );
268 AddItem( "bool", "type" );
269 AddBool( Setting.GetDefault(), "default" );
270 EndStruct();
271 return ShuttleGui::TieCheckBox( Prompt, Setting );
272 }
273
TieCheckBoxOnRight(const TranslatableString & Prompt,const BoolSetting & Setting)274 wxCheckBox * ShuttleGuiGetDefinition::TieCheckBoxOnRight(
275 const TranslatableString &Prompt,
276 const BoolSetting &Setting)
277 {
278 StartStruct();
279 AddItem( Setting.GetPath(), "id" );
280 AddItem( Prompt.Translation(), "prompt" );
281 AddItem( "bool", "type" );
282 AddBool( Setting.GetDefault(), "default" );
283 EndStruct();
284 return ShuttleGui::TieCheckBoxOnRight( Prompt, Setting );
285 }
286
TieChoice(const TranslatableString & Prompt,const ChoiceSetting & choiceSetting)287 wxChoice * ShuttleGuiGetDefinition::TieChoice(
288 const TranslatableString &Prompt,
289 const ChoiceSetting &choiceSetting )
290 {
291 StartStruct();
292 AddItem( choiceSetting.Key(), "id" );
293 AddItem( Prompt.Translation(), "prompt" );
294 AddItem( "enum", "type" );
295 AddItem( choiceSetting.Default().Internal(), "default" );
296 StartField( "enum" );
297 StartArray();
298 for ( const auto &choice : choiceSetting.GetSymbols().GetInternals() )
299 AddItem( choice );
300 EndArray();
301 EndField();
302 EndStruct();
303 return ShuttleGui::TieChoice( Prompt, choiceSetting );
304 }
305
TieNumberAsChoice(const TranslatableString & Prompt,const IntSetting & Setting,const TranslatableStrings & Choices,const std::vector<int> * pInternalChoices,int iNoMatchSelector)306 wxChoice * ShuttleGuiGetDefinition::TieNumberAsChoice(
307 const TranslatableString &Prompt,
308 const IntSetting &Setting,
309 const TranslatableStrings & Choices,
310 const std::vector<int> * pInternalChoices, int iNoMatchSelector)
311 {
312 // Come here for controls that present non-exhaustive choices among some
313 // numbers, with an associated control that allows arbitrary entry of an
314 // "Other..."
315 StartStruct();
316 AddItem( Setting.GetPath(), "id" );
317 AddItem( Prompt.Translation(), "prompt" );
318 AddItem( "number", "type" ); // not "enum" !
319 AddItem( Setting.GetDefault(), "default" );
320 EndStruct();
321 return ShuttleGui::TieNumberAsChoice(
322 Prompt, Setting, Choices, pInternalChoices, iNoMatchSelector );
323 }
324
TieTextBox(const TranslatableString & Prompt,const StringSetting & Setting,const int nChars)325 wxTextCtrl * ShuttleGuiGetDefinition::TieTextBox(
326 const TranslatableString &Prompt,
327 const StringSetting &Setting,
328 const int nChars)
329 {
330 StartStruct();
331 AddItem( Setting.GetPath(), "id" );
332 AddItem( Prompt.Translation(), "prompt" );
333 AddItem( "string", "type" );
334 AddItem( Setting.GetDefault(), "default" );
335 EndStruct();
336 return ShuttleGui::TieTextBox( Prompt, Setting, nChars );
337 }
338
TieIntegerTextBox(const TranslatableString & Prompt,const IntSetting & Setting,const int nChars)339 wxTextCtrl * ShuttleGuiGetDefinition::TieIntegerTextBox(
340 const TranslatableString & Prompt,
341 const IntSetting &Setting,
342 const int nChars)
343 {
344 StartStruct();
345 AddItem( Setting.GetPath(), "id" );
346 AddItem( Prompt.Translation(), "prompt" );
347 AddItem( "number", "type" );
348 AddItem( Setting.GetDefault(), "default" );
349 EndStruct();
350 return ShuttleGui::TieIntegerTextBox( Prompt, Setting, nChars );
351 }
352
TieNumericTextBox(const TranslatableString & Prompt,const DoubleSetting & Setting,const int nChars)353 wxTextCtrl * ShuttleGuiGetDefinition::TieNumericTextBox(
354 const TranslatableString & Prompt,
355 const DoubleSetting &Setting,
356 const int nChars)
357 {
358 StartStruct();
359 AddItem( Setting.GetPath(), "id" );
360 AddItem( Prompt.Translation(), "prompt" );
361 AddItem( "number", "type" );
362 AddItem( Setting.GetDefault(), "default" );
363 EndStruct();
364 return ShuttleGui::TieNumericTextBox( Prompt, Setting, nChars );
365 }
366
TieSlider(const TranslatableString & Prompt,const IntSetting & Setting,const int max,const int min)367 wxSlider * ShuttleGuiGetDefinition::TieSlider(
368 const TranslatableString & Prompt,
369 const IntSetting &Setting,
370 const int max,
371 const int min)
372 {
373 StartStruct();
374 AddItem( Setting.GetPath(), "id" );
375 AddItem( Prompt.Translation(), "prompt" );
376 AddItem( "number", "type" );
377 AddItem( Setting.GetDefault(), "default" );
378 EndStruct();
379 return ShuttleGui::TieSlider( Prompt, Setting, max, min );
380 }
381
TieSpinCtrl(const TranslatableString & Prompt,const IntSetting & Setting,const int max,const int min)382 wxSpinCtrl * ShuttleGuiGetDefinition::TieSpinCtrl(
383 const TranslatableString &Prompt,
384 const IntSetting &Setting,
385 const int max,
386 const int min)
387 {
388 StartStruct();
389 AddItem( Setting.GetPath(), "id" );
390 AddItem( Prompt.Translation(), "prompt" );
391 AddItem( "number", "type" );
392 AddItem( Setting.GetDefault(), "default" );
393 EndStruct();
394 return ShuttleGui::TieSpinCtrl( Prompt, Setting, max, min );
395 }
396
397 }
398
SendPreferences(const CommandContext & context)399 bool GetInfoCommand::SendPreferences(const CommandContext &context)
400 {
401 context.StartArray();
402 auto pWin = &GetProjectFrame( context.project );
403 GlobalPrefsDialog dialog( pWin, &context.project );
404 // wxCommandEvent Evt;
405 //dialog.Show();
406 ShuttleGuiGetDefinition S(pWin, *((context.pOutput)->mStatusTarget) );
407 dialog.ShuttleAll( S );
408 context.EndArray();
409 return true;
410 }
411
412 /**
413 Send the list of commands.
414 */
SendCommands(const CommandContext & context,int flags)415 bool GetInfoCommand::SendCommands(const CommandContext &context, int flags )
416 {
417 context.StartArray();
418 PluginManager & pm = PluginManager::Get();
419 EffectManager & em = EffectManager::Get();
420 {
421 for (auto &plug
422 : pm.PluginsOfType(PluginTypeEffect | PluginTypeAudacityCommand)) {
423 auto command = em.GetCommandIdentifier(plug.GetID());
424 if (!command.empty()){
425 em.GetCommandDefinition( plug.GetID(), context, flags );
426 }
427 }
428 }
429 context.EndArray();
430 return true;
431 }
432
SendBoxes(const CommandContext & context)433 bool GetInfoCommand::SendBoxes(const CommandContext &context)
434 {
435 //context.Status("Boxes");
436 auto pWin = &GetProjectFrame( context.project );
437
438 context.StartArray();
439 wxRect R = pWin->GetScreenRect();
440
441 //R.SetPosition( wxPoint(0,0) );
442
443 //wxString Name = pWin->GetName();
444 context.StartStruct();
445 context.AddItem( 0, "depth" );
446 context.AddItem( "Audacity Window", "name" );
447 context.StartField( "box" );
448 context.StartArray( );
449 context.AddItem( R.GetLeft() );
450 context.AddItem( R.GetTop() );
451 context.AddItem( R.GetRight() );
452 context.AddItem( R.GetBottom() );
453 context.EndArray( );
454 context.EndField();
455 context.EndStruct( );
456
457 ExploreAdornments( context, pWin->GetPosition()+wxSize( 6,-1), pWin, pWin->GetId(), 1 );
458 ExploreWindows( context, pWin->GetPosition()+wxSize( 6,-1), pWin, pWin->GetId(), 1 );
459 context.EndArray( );
460 return true;
461 }
462
SendTracks(const CommandContext & context)463 bool GetInfoCommand::SendTracks(const CommandContext & context)
464 {
465 auto &tracks = TrackList::Get( context.project );
466 context.StartArray();
467 for (auto trk : tracks.Leaders())
468 {
469 auto &trackFocus = TrackFocus::Get( context.project );
470 Track * fTrack = trackFocus.Get();
471
472 context.StartStruct();
473 context.AddItem( trk->GetName(), "name" );
474 context.AddBool( (trk == fTrack), "focused");
475 context.AddBool( trk->GetSelected(), "selected" );
476 //JKC: Possibly add later...
477 //context.AddItem( TrackView::Get( *trk ).GetHeight(), "height" );
478 trk->TypeSwitch( [&] (const WaveTrack* t ) {
479 float vzmin, vzmax;
480 t->GetDisplayBounds(&vzmin, &vzmax);
481 context.AddItem( "wave", "kind" );
482 context.AddItem( t->GetStartTime(), "start" );
483 context.AddItem( t->GetEndTime(), "end" );
484 context.AddItem( t->GetPan() , "pan");
485 context.AddItem( t->GetGain() , "gain");
486 context.AddItem( TrackList::Channels(t).size(), "channels");
487 context.AddBool( t->GetSolo(), "solo" );
488 context.AddBool( t->GetMute(), "mute");
489 context.AddItem( vzmin, "VZoomMin");
490 context.AddItem( vzmax, "VZoomMax");
491 },
492 #if defined(USE_MIDI)
493 [&](const NoteTrack *) {
494 context.AddItem( "note", "kind" );
495 },
496 #endif
497 [&](const LabelTrack *) {
498 context.AddItem( "label", "kind" );
499 },
500 [&](const TimeTrack *) {
501 context.AddItem( "time", "kind" );
502 }
503 );
504 context.EndStruct();
505 }
506 context.EndArray();
507 return true;
508 }
509
SendClips(const CommandContext & context)510 bool GetInfoCommand::SendClips(const CommandContext &context)
511 {
512 auto &tracks = TrackList::Get( context.project );
513 int i=0;
514 context.StartArray();
515 for (auto t : tracks.Leaders()) {
516 t->TypeSwitch([&](WaveTrack *waveTrack) {
517 WaveClipPointers ptrs(waveTrack->SortedClipArray());
518 for (WaveClip * pClip : ptrs) {
519 context.StartStruct();
520 context.AddItem((double)i, "track");
521 context.AddItem(pClip->GetPlayStartTime(), "start");
522 context.AddItem(pClip->GetPlayEndTime(), "end");
523 context.AddItem(pClip->GetColourIndex(), "color");
524 context.EndStruct();
525 }
526 });
527 // Per track numbering counts all tracks
528 i++;
529 }
530 context.EndArray();
531
532 return true;
533 }
534
SendEnvelopes(const CommandContext & context)535 bool GetInfoCommand::SendEnvelopes(const CommandContext &context)
536 {
537 auto &tracks = TrackList::Get( context.project );
538 int i=0;
539 int j=0;
540 context.StartArray();
541 for (auto t : tracks.Leaders()) {
542 t->TypeSwitch([&](WaveTrack *waveTrack) {
543 WaveClipPointers ptrs(waveTrack->SortedClipArray());
544 j = 0;
545 for (WaveClip * pClip : ptrs) {
546 context.StartStruct();
547 context.AddItem((double)i, "track");
548 context.AddItem((double)j, "clip");
549 context.AddItem(pClip->GetPlayStartTime(), "start");
550 Envelope * pEnv = pClip->GetEnvelope();
551 context.StartField("points");
552 context.StartArray();
553 double offset = pEnv->GetOffset();
554 for (size_t k = 0; k < pEnv->GetNumberOfPoints(); k++)
555 {
556 context.StartStruct();
557 context.AddItem((*pEnv)[k].GetT() + offset, "t");
558 context.AddItem((*pEnv)[k].GetVal(), "y");
559 context.EndStruct();
560 }
561 context.EndArray();
562 context.EndField();
563 context.AddItem(pClip->GetPlayEndTime(), "end");
564 context.EndStruct();
565 j++;
566 }
567 });
568 // Per track numbering counts all tracks
569 i++;
570 }
571 context.EndArray();
572
573 return true;
574 }
575
576
SendLabels(const CommandContext & context)577 bool GetInfoCommand::SendLabels(const CommandContext &context)
578 {
579 auto &tracks = TrackList::Get( context.project );
580 int i=0;
581 context.StartArray();
582 for (auto t : tracks.Leaders()) {
583 t->TypeSwitch( [&](LabelTrack *labelTrack) {
584 #ifdef VERBOSE_LABELS_FORMATTING
585 for (int nn = 0; nn< (int)labelTrack->mLabels.size(); nn++) {
586 const auto &label = labelTrack->mLabels[nn];
587 context.StartStruct();
588 context.AddItem( (double)i, "track" );
589 context.AddItem( label.getT0(), "start" );
590 context.AddItem( label.getT1(), "end" );
591 context.AddItem( label.title, "text" );
592 context.EndStruct();
593 }
594 #else
595 context.StartArray();
596 context.AddItem( (double)i ); // Track number.
597 context.StartArray();
598 for ( const auto &label : labelTrack->GetLabels() ) {
599 context.StartArray();
600 context.AddItem( label.getT0() ); // start
601 context.AddItem( label.getT1() ); // end
602 context.AddItem( label.title ); //text.
603 context.EndArray();
604 }
605 context.EndArray();
606 context.EndArray();
607 #endif
608 } );
609 // Per track numbering counts all tracks
610 i++;
611 }
612 context.EndArray();
613
614 return true;
615 }
616
617 /*******************************************************************
618 The various Explore functions are called from the Send functions,
619 and may be recursive. 'Send' is the top level.
620 *******************************************************************/
621
ExploreMenu(const CommandContext & context,wxMenu * pMenu,int Id,int depth)622 void GetInfoCommand::ExploreMenu( const CommandContext &context, wxMenu * pMenu, int Id, int depth ){
623 static_cast<void>(Id);//compiler food.
624 if( !pMenu )
625 return;
626
627 auto &commandManager = CommandManager::Get( context.project );
628
629 wxMenuItemList list = pMenu->GetMenuItems();
630 size_t lcnt = list.size();
631 wxMenuItem * item;
632 wxString Label;
633 wxString Accel;
634 CommandID Name;
635
636 for (size_t lndx = 0; lndx < lcnt; lndx++) {
637 item = list.Item(lndx)->GetData();
638 Label = item->GetItemLabelText();
639 Name = commandManager.GetNameFromNumericID( item->GetId() );
640 Accel = item->GetItemLabel();
641 if( Accel.Contains("\t") )
642 Accel = Accel.AfterLast('\t');
643 else
644 Accel = "";
645 if( item->IsSeparator() )
646 Label = "----";
647 int flags = 0;
648 if (item->IsSubMenu())
649 flags +=1;
650 if (item->IsCheck() && item->IsChecked())
651 flags +=2;
652
653 context.StartStruct();
654 context.AddItem( depth, "depth" );
655 context.AddItem( flags, "flags" );
656 context.AddItem( Label, "label" );
657 context.AddItem( Accel, "accel" );
658 if( !Name.empty() )
659 // using GET to expose CommandID in results of GetInfoCommand...
660 // PRL asks, is that all right?
661 context.AddItem( Name.GET(), "id" );// It is called Scripting ID outside Audacity.
662 context.EndStruct();
663
664 if (item->IsSubMenu()) {
665 pMenu = item->GetSubMenu();
666 ExploreMenu( context, pMenu, item->GetId(), depth+1 );
667 }
668 }
669 }
670
ExploreAdornments(const CommandContext & context,wxPoint WXUNUSED (P),wxWindow * pWin,int WXUNUSED (Id),int depth)671 void GetInfoCommand::ExploreAdornments( const CommandContext &context,
672 wxPoint WXUNUSED(P), wxWindow * pWin, int WXUNUSED(Id), int depth )
673 {
674 // Dang! wxMenuBar returns bogus screen rect.
675 // We're going to have to fake it instead.
676 //wxMenuBar * pBar = context.GetProject()->GetMenuBar();
677 //wxRect R = pBar->GetScreenRect();
678 //R.SetPosition( R.GetPosition() - P );
679
680 wxRect R1 = pWin->GetScreenRect();
681 wxSize s = pWin->GetWindowBorderSize();
682 wxRect R( 2,32, R1.GetWidth() - s.GetWidth() * 2 -16, 22 );
683
684 context.StartStruct();
685 context.AddItem( depth, "depth" );
686 context.AddItem( "MenuBar", "label" );
687 context.StartField( "box" );
688 context.StartArray();
689 context.AddItem( R.GetLeft() );
690 context.AddItem( R.GetTop() );
691 context.AddItem( R.GetRight() );
692 context.AddItem( R.GetBottom() );
693 context.EndArray();
694 context.EndField();
695 context.EndStruct();
696 }
697
ExploreTrackPanel(const CommandContext & context,wxPoint P,int depth)698 void GetInfoCommand::ExploreTrackPanel( const CommandContext &context,
699 wxPoint P, int depth )
700 {
701 AudacityProject * pProj = &context.project;
702 auto &tp = TrackPanel::Get( *pProj );
703 wxRect panelRect{ {}, tp.GetSize() };
704 for ( auto t : TrackList::Get( *pProj ).Any() ) {
705 auto rulers = tp.FindRulerRects(t);
706 for (auto &R : rulers) {
707 if (!R.Intersects(panelRect))
708 continue;
709 R.SetPosition( R.GetPosition() + P );
710 context.StartStruct();
711 context.AddItem( depth, "depth" );
712 context.AddItem( "VRuler", "label" );
713 context.StartField("box");
714 context.StartArray();
715 context.AddItem( R.GetLeft() );
716 context.AddItem( R.GetTop() );
717 context.AddItem( R.GetRight() );
718 context.AddItem( R.GetBottom() );
719 context.EndArray();
720 context.EndField();
721 context.EndStruct();
722 }
723 }
724 }
725
726
ExploreWindows(const CommandContext & context,wxPoint P,wxWindow * pWin,int Id,int depth)727 void GetInfoCommand::ExploreWindows( const CommandContext &context,
728 wxPoint P, wxWindow * pWin, int Id, int depth )
729 {
730 static_cast<void>(Id);//Compiler food.
731
732 if( pWin->GetName() == "Track Panel" )
733 {
734 wxRect R = pWin->GetScreenRect();
735 ExploreTrackPanel( context, R.GetPosition()-P, depth );
736 return;
737 }
738 wxWindowList list = pWin->GetChildren();
739 size_t lcnt = list.size();
740
741 for (size_t lndx = 0; lndx < lcnt; lndx++) {
742 wxWindow * item = list[lndx];
743 if( !item->IsShown() )
744 continue;
745 wxRect R = item->GetScreenRect();
746 R.SetPosition( R.GetPosition() - P );
747 wxString Name = item->GetName();
748 // Ignore staticLine and StaticBitmap.
749 if( Name.StartsWith( "static" ) )
750 continue;
751 // Ignore anonymous panels.
752 if( Name == "panel" )
753 continue;
754 if( Name.empty() )
755 Name = wxString("*") + item->GetToolTipText();
756
757 context.StartStruct();
758 context.AddItem( depth, "depth" );
759 context.AddItem( Name, "label" );
760 context.AddItem( item->GetId(), "id" );
761 context.StartField( "box" );
762 context.StartArray();
763 context.AddItem( R.GetLeft() );
764 context.AddItem( R.GetTop() );
765 context.AddItem( R.GetRight() );
766 context.AddItem( R.GetBottom() );
767 context.EndArray();
768 context.EndField();
769 context.EndStruct();
770
771 ExploreWindows( context, P, item, item->GetId(), depth+1 );
772 }
773 }
774
775