Audacity 3.2.0
ToolManager.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 ToolManager.cpp
6
7 Dominic Mazzoni
8 Shane T. Mueller
9 Leland Lucius
10
11 See ToolManager.h for details.
12
13*******************************************************************//*******************************************************************//**********************************************************************/
26
27
28#include "ToolManager.h"
29
30#include "../commands/CommandContext.h"
31
32// For compilers that support precompilation, includes "wx/wx.h".
33#include <wx/wxprec.h>
34
35#ifndef WX_PRECOMP
36#include <wx/dcclient.h>
37#include <wx/defs.h>
38#include <wx/frame.h>
39#include <wx/gdicmn.h>
40#include <wx/region.h>
41#include <wx/settings.h>
42#include <wx/sizer.h>
43#include <wx/sysopt.h>
44#include <wx/utils.h>
45#include <wx/window.h>
46#endif /* */
47
48#include <wx/minifram.h>
49#include <wx/popupwin.h>
50
51#include "AColor.h"
52#include "AllThemeResources.h"
53#include "ImageManipulation.h"
54#include "Menus.h"
55#include "Prefs.h"
56#include "Project.h"
57#include "ProjectWindows.h"
58#include "SyncLock.h"
59#include "widgets/AButton.h"
60#include "widgets/ASlider.h"
62#include "widgets/Grabber.h"
63
67#define sizerW 11
68
69//
70// Constructor
71//
73 ( AudacityProject *parent, ToolManager *manager, ToolBar *bar, wxPoint pos )
74 : wxFrame( FindProjectFrame( parent ),
75 bar->GetId(),
76 wxEmptyString,
77 pos,
78 wxDefaultSize,
79 wxNO_BORDER |
80 wxFRAME_NO_TASKBAR |
81#if !defined(__WXMAC__) // bug1358
82 wxFRAME_TOOL_WINDOW |
83#endif
84 wxFRAME_FLOAT_ON_PARENT )
85 , mParent{ parent }
86{
87 int width = bar->GetSize().x;
88 int border = 1;
89
90 // Save parameters
92 mBar = bar;
93
94 // Transfer the bar to the ferry
95 bar->Reparent(this);
96
97 // Bug 2120 (comment 6 residual): No need to set a minimum size
98 // if the toolbar is not resizable. On GTK, setting a minimum
99 // size will prevent the frame from shrinking if the toolbar gets
100 // reconfigured and needs to resize smaller.
101 if (bar->IsResizable())
102 {
103 SetMinSize(bar->GetDockedSize());
104 }
105
106 {
107 // We use a sizer to maintain proper spacing
108 auto s = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
109
110 // Add the bar to the sizer
111 s->Add(bar, 1, wxEXPAND | wxALL, border);
112
113 // Add space for the resize grabber
114 if (bar->IsResizable())
115 {
116 s->Add(sizerW, 1);
117 width += sizerW;
118 }
119
120 SetSize(width + 2 * ToolBarFloatMargin,
121 bar->GetDockedSize().y + 2 * ToolBarFloatMargin);
122
123 // Attach the sizer and resize the window to fit
124 SetSizer(s.release());
125 }
126
127 Layout();
128
129 // Inform toolbar of change
130 bar->SetDocked( NULL, true );
131
132 // Make sure resizable floaters don't get any smaller than initial size
133 if( bar->IsResizable() )
134 {
135 // Calc the minimum size of the frame
136 mMinSize = bar->GetMinSize() + ( GetSize() - bar->GetSize() );
137 }
138}
139
141{
142 if(HasCapture())
143 ReleaseMouse();
144}
145
147{
148 // Pass it on to the manager since it isn't in the handling hierarchy
149 mManager->ProcessEvent( event );
150}
151
152// The current size determines the min size for resizing...
153// the 'lock in' is at that aspect ratio.
155{
156 mBar = pBar;
157
158 wxSize sz = mBar->GetSize();
159 SetClientSize( sz );
160 int yDesiredMin = 26;
161 int y = sz.GetHeight();
162 if (y > yDesiredMin) {
163 sz.SetWidth((sz.GetWidth() * yDesiredMin) / y);
164 sz.SetHeight( yDesiredMin );
165 }
166 mMinSize = sz -wxSize( 10, 0);
167}
168
169void ToolFrame::OnToolBarUpdate( wxCommandEvent & event )
170{
171 // Resize floater window to exactly contain toolbar
172 // use actual size rather than minimum size.
173 if (mBar)
174 mBar->GetParent()->SetClientSize( mBar->GetSize() );// ->GetMinSize() );
175
176 // Allow it to propagate to our parent
177 event.Skip();
178}
179
180void ToolFrame::OnPaint( wxPaintEvent & WXUNUSED(event) )
181{
182 wxPaintDC dc( this );
183 wxSize sz = GetSize();
184 wxRect r;
185
186 dc.SetPen( theTheme.Colour( clrTrackPanelText ) );
187 dc.SetBackground( wxBrush( theTheme.Colour( clrMedium ) ) );
188 dc.Clear();
189 dc.SetBrush( *wxTRANSPARENT_BRUSH );
190 dc.DrawRectangle( 0, 0, sz.GetWidth(), sz.GetHeight() );
191
192 if( mBar && mBar->IsResizable() )
193 {
194 r.x = sz.x - sizerW - 2,
195 r.y = sz.y - sizerW - 2;
196 r.width = sizerW + 2;
197 r.height = sizerW + 2;
198
199 AColor::Line(dc, r.GetLeft(), r.GetBottom(), r.GetRight(), r.GetTop() );
200 AColor::Line(dc, r.GetLeft() + 3, r.GetBottom(), r.GetRight(), r.GetTop() + 3 );
201 AColor::Line(dc, r.GetLeft() + 6, r.GetBottom(), r.GetRight(), r.GetTop() + 6 );
202 AColor::Line(dc, r.GetLeft() + 9, r.GetBottom(), r.GetRight(), r.GetTop() + 9 );
203 }
204
205}
206
207void ToolFrame::OnMotion( wxMouseEvent & event )
208{
209 // Don't do anything if we're docked or not resizeable
210 if( !mBar || mBar->IsDocked() || !mBar->IsResizable() )
211 {
212 return;
213 }
214
215 // Retrieve the mouse position
216 wxPoint pos = ClientToScreen( event.GetPosition() );
217 if( HasCapture() && event.Dragging() )
218 {
219 wxRect rect = GetRect();
220
221 rect.SetBottomRight( pos );
222
223 // Keep it within max size, if specified
224 wxSize maxsz = mBar->GetMaxSize();
225 if (maxsz != wxDefaultSize)
226 {
227 if (maxsz.x != wxDefaultCoord && rect.width > maxsz.x)
228 {
229 rect.width = maxsz.x;
230 }
231 if (maxsz.y != wxDefaultCoord && rect.height > maxsz.y)
232 {
233 rect.height = maxsz.y;
234 }
235 }
236
237 if( rect.width < mMinSize.x )
238 {
239 rect.width = mMinSize.x;
240 }
241
242 if( rect.height < mMinSize.y )
243 {
244 rect.height = mMinSize.y;
245 }
246
247 Resize( rect.GetSize() );
248 }
249 else if( HasCapture() && event.LeftUp() )
250 {
251 ReleaseMouse();
252 }
253 else if( !HasCapture() )
254 {
255 wxRect rect = GetRect();
256 wxRect r;
257
258 r.x = rect.GetRight() - sizerW - 2,
259 r.y = rect.GetBottom() - sizerW - 2;
260 r.width = sizerW + 2;
261 r.height = sizerW + 2;
262
263 // Is left click within resize grabber?
264 if( r.Contains( pos ) && !event.Leaving() )
265 {
266 mOrigSize = GetSize();
267
268 SetCursor( wxCURSOR_SIZENWSE );
269 if( event.LeftDown() )
270 {
271 CaptureMouse();
272 }
273 }
274 else
275 {
276 SetCursor( wxCURSOR_ARROW );
277 }
278 }
279}
280
281void ToolFrame::OnCaptureLost( wxMouseCaptureLostEvent & WXUNUSED(event) )
282{
283 if( HasCapture() )
284 {
285 ReleaseMouse();
286 }
287}
288
289void ToolFrame::OnClose( wxCloseEvent & event )
290{
291 event.Veto();
292}
293
294void ToolFrame::OnKeyDown( wxKeyEvent &event )
295{
296 event.Skip();
297 if( HasCapture() && event.GetKeyCode() == WXK_ESCAPE ) {
298 Resize( mOrigSize );
299 ReleaseMouse();
300 }
301}
302
303void ToolFrame::Resize( const wxSize &size )
304{
305 SetMinSize( size );
306 SetSize( size );
307 Layout();
308 Refresh( false );
309}
310
312
313BEGIN_EVENT_TABLE( ToolFrame, wxFrame )
315 EVT_PAINT( ToolFrame::OnPaint )
316 EVT_MOUSE_EVENTS( ToolFrame::OnMotion )
317 EVT_MOUSE_CAPTURE_LOST( ToolFrame::OnCaptureLost )
318 EVT_CLOSE( ToolFrame::OnClose )
319 EVT_COMMAND( wxID_ANY, EVT_TOOLBAR_UPDATED, ToolFrame::OnToolBarUpdate )
320 EVT_KEY_DOWN( ToolFrame::OnKeyDown )
322
324
328
329BEGIN_EVENT_TABLE( ToolManager, wxEvtHandler )
330 EVT_GRABBER( wxID_ANY, ToolManager::OnGrabber )
331 EVT_TIMER( wxID_ANY, ToolManager::OnTimer )
333
334static const AudacityProject::AttachedObjects::RegisteredFactory key{
335 []( AudacityProject &parent ){
336 return std::make_shared< ToolManager >( &parent ); }
337};
338
340{
341 return project.AttachedObjects::Get< ToolManager >( key );
342}
343
345{
346 return Get( const_cast< AudacityProject & >( project ) );
347}
348
349//
350// Constructor
351//
353: wxEvtHandler()
354{
355 wxPoint pt[ 3 ];
356
357#if defined(__WXMAC__)
358 // Save original transition
359 mTransition = wxSystemOptions::GetOptionInt( wxMAC_WINDOW_PLAIN_TRANSITION );
360#endif
361
362 // Initialize everything
363 mParent = parent;
364 mLastPos.x = mBarPos.x = -1;
365 mLastPos.y = mBarPos.y = -1;
366 mDragWindow = NULL;
367 mDragDock = NULL;
368 mDragBar = NULL;
369
370 // Create the down arrow
371 pt[ 0 ].x = 0;
372 pt[ 0 ].y = 0;
373 pt[ 1 ].x = 9;
374 pt[ 1 ].y = 9;
375 pt[ 2 ].x = 18;
376 pt[ 2 ].y = 0;
377
378 // Create the shaped region
379 mDown = std::make_unique<wxRegion>( 3, &pt[0] );
380
381 // Create the down arrow
382 pt[ 0 ].x = 9;
383 pt[ 0 ].y = 0;
384 pt[ 1 ].x = 0;
385 pt[ 1 ].y = 9;
386 pt[ 2 ].x = 9;
387 pt[ 2 ].y = 18;
388
389 // Create the shaped region
390 mLeft = std::make_unique<wxRegion>( 3, &pt[0] );
391
392 // Create the indicator frame
393 // parent is null but FramePtr ensures destruction
394 mIndicator = FramePtr{ safenew wxFrame( NULL,
395 wxID_ANY,
396 wxEmptyString,
397 wxDefaultPosition,
398 wxSize( 32, 32 ),
399 wxFRAME_TOOL_WINDOW |
400 wxFRAME_SHAPED |
401 wxNO_BORDER |
402 wxFRAME_NO_TASKBAR |
403 wxSTAY_ON_TOP )
404 };
405
406 // Hook the creation event...only needed on GTK, but doesn't hurt for all
407 mIndicator->Bind( wxEVT_CREATE,
409 this );
410
411 // Hook the paint event...needed for all
412 mIndicator->Bind( wxEVT_PAINT,
414 this );
415
416 // It's a little shy
417 mIndicator->Hide();
418}
419
421{
422 auto parent = mParent;
423 auto &window = GetProjectFrame( *parent );
424
425 // Hook the parents mouse events...using the parent helps greatly
426 // under GTK
427 window.Bind( wxEVT_LEFT_UP,
429 this );
430 window.Bind( wxEVT_MOTION,
432 this );
433 window.Bind( wxEVT_MOUSE_CAPTURE_LOST,
435 this );
436
437 wxWindow *topDockParent = TopPanelHook::Call( window );
438 wxASSERT(topDockParent);
439
440 // Create the top and bottom docks
441 mTopDock = safenew ToolDock( this, topDockParent, TopDockID );
442 mBotDock = safenew ToolDock( this, &window, BotDockID );
443
444 // Create all of the toolbars
445 // All have the project as parent window
446 wxASSERT(parent);
447
448 for (const auto &factory : RegisteredToolbarFactory::GetFactories()) {
449 if (factory) {
450 auto bar = factory( *parent );
451 if (bar) {
452 auto &slot = mBars[bar->GetSection()];
453 if (slot) {
454 // Oh no, name collision of registered toolbars
455 assert(false);
456 bar->Destroy();
457 continue;
458 }
459 slot = std::move(bar);
460 }
461 }
462 else
463 wxASSERT( false );
464 }
465
467 ForEach([ii = 0](ToolBar *bar) mutable { bar->SetIndex(ii++); });
468
469 // We own the timer
470 mTimer.SetOwner( this );
471
472 // Process the toolbar config settings
473 ReadConfig();
474
475 wxEvtHandler::AddFilter(this);
476
479}
480
481//
482// Destructor
483//
484
486{
487 if ( mTopDock || mBotDock ) { // destroy at most once
488 wxEvtHandler::RemoveFilter(this);
489
490 // Save the toolbar states
491 WriteConfig();
492
493 // This function causes the toolbars to be destroyed, so
494 // clear the configuration of the ToolDocks which refer to
495 // these toolbars. This change was needed to stop Audacity
496 // crashing when running with Jaws on Windows 10 1703.
499
500 mTopDock = mBotDock = nullptr; // indicate that it has been destroyed
501
502 for (auto &pair : mBars)
503 pair.second.reset();
504
505 mIndicator.reset();
506 }
507}
508
510{
511 Destroy();
512}
513
514// This table describes the default configuration of the toolbars as
515// a "tree" and must be kept in pre-order traversal.
516
517// In fact this tree is more of a broom -- nothing properly branches except
518// at the root.
519
520// "Root" corresponds to left edge of the main window, and successive siblings
521// go from top to bottom. But in practice layout may wrap this abstract
522// configuration if the window size is narrow.
523
524static struct DefaultConfigEntry {
527 Identifier below; // preceding sibling
528} DefaultConfigTable [] = {
529 // Top dock row, may wrap
530 { wxT("Control"), {}, {} },
531 { wxT("Tools"), wxT("Control"), {} },
532 { wxT("Edit"), wxT("Tools"), {} },
533 { wxT("CutCopyPaste"), wxT("Edit"), {} },
534 { wxT("Audio Setup"), wxT("CutCopyPaste"), {} },
535#ifdef HAS_AUDIOCOM_UPLOAD
536 { wxT("Share Audio"), wxT("Audio Setup"), {} },
537 { wxT("RecordMeter"), wxT("Share Audio"), {} },
538#else
539 { wxT("RecordMeter"), wxT("Audio Setup"), {} },
540#endif
541 { wxT("PlayMeter"), wxT("RecordMeter"), {} },
542
543 // start another top dock row
544 { wxT("Scrub"), {}, wxT("Control") },
545 { wxT("Device"), wxT("Scrub"), wxT("Control") },
546
547 // Hidden by default in top dock
548 { wxT("CombinedMeter"), {}, {} },
549
550 // Bottom dock
551 { wxT("TimeSignature"), {}, {}, },
552 { wxT("Snapping"), wxT("TimeSignature"), {}, },
553 { wxT("Time"), wxT("Snapping"), {} },
554 { wxT("Selection"), wxT("Time"), {} },
555
556// DA: Transcription Toolbar not docked, by default.
557#ifdef EXPERIMENTAL_DA
558 { wxT("Transcription"), {}, {} },
559#else
560 { wxT("Transcription"), wxT("Selection"), {} },
561#endif
562
563 // Hidden by default in bottom dock
564 { wxT("SpectralSelection"), {}, {} },
566
567// Static member function.
569{
570 auto &project = context.project;
571 auto &toolManager = ToolManager::Get( project );
572
573 toolManager.Reset();
574 Get(project).ModifyToolbarMenus(project);
575}
576
577
579{
580 // Disconnect all docked bars
581 for ( const auto &entry : DefaultConfigTable )
582 {
583 const auto &ndx = entry.barID;
584 ToolBar *bar = GetToolBar(ndx);
585 if (!bar)
586 continue;
587
589 (entry.rightOf == Identifier{}) ? nullptr : GetToolBar(entry.rightOf),
590 (entry.below == Identifier{}) ? nullptr : GetToolBar(entry.below)
591 };
592
593 bar->SetSize( 20,20 );
594
595 wxWindow *floater;
596 ToolDock *dock;
597 bool expose = true;
598
599 // Disconnect the bar
600 if( bar->IsDocked() )
601 {
602 bar->GetDock()->Undock( bar );
603 floater = NULL;
604 }
605 else
606 {
607 floater = bar->GetParent();
608 }
609
610 // Decide which dock.
611 dock = (bar->DefaultDockID() == ToolBar::TopDockID)
612 ? mTopDock : mBotDock;
613
614 // PRL: Destroy the tool frame before recreating buttons.
615 // This fixes some subtle sizing problems on macOs.
616 bar->Reparent( dock );
617 //OK (and good) to DELETE floater, as bar is no longer in it.
618 if( floater )
619 floater->Destroy();
620
621 // Recreate bar buttons (and resize it)
622 bar->SetToDefaultSize();
623 bar->ReCreateButtons();
625
626#if 0
627 if( bar->IsResizable() )
628 {
629 bar->SetSize(bar->GetBestFittingSize());
630 }
631#endif
632
633 // Hide some bars.
634 expose = bar->ShownByDefault() || bar->HideAfterReset();
635
636 // Next condition will always (?) be true, as the reset configuration is
637 // with no floating toolbars.
638 if( dock != NULL )
639 {
640 // when we dock, we reparent, so bar is no longer a child of floater.
641 dock->Dock( bar, false, position );
642 Expose( bar->GetSection(), expose );
643 }
644 else
645 {
646 // The (tool)bar has a dragger window round it, the floater.
647 // in turn floater will have mParent (the entire App) as its
648 // parent.
649
650 // Maybe construct a NEW floater
651 // this happens if we have just been bounced out of a dock.
652 if( floater == NULL ) {
653 wxASSERT(mParent);
654 floater = safenew ToolFrame( mParent, this, bar, wxPoint(-1,-1) );
655 bar->Reparent( floater );
656 }
657
658 // This bar is undocked and invisible.
659 // We are doing a reset toolbars, so even the invisible undocked bars should
660 // be moved somewhere sensible. Put bar near center of window.
661 // If there were multiple hidden toobars the * 10 adjustment means
662 // they won't overlap too much.
663 floater->CentreOnParent( );
664 const auto index = bar->GetIndex();
665 floater->Move(
666 floater->GetPosition() + wxSize{ index * 10 - 200, index * 10 });
667 bar->SetDocked( NULL, false );
668 Expose( bar->GetSection(), false );
669 }
670 }
671
672 ForEach([this](auto bar){
673 if (bar && bar->HideAfterReset())
674 Expose(bar->GetSection(), false);
675 });
676 // TODO:??
677 // If audio was playing, we stopped the VU meters,
678 // It would be nice to show them again, but hardly essential as
679 // they will show up again on the next play.
680 // SetVUMeters(AudacityProject *p);
681 Updated();
682}
683
685{
686 ForEach([](auto bar){
687 if (bar)
688 bar->RegenerateTooltips();
689 });
690}
691
692int ToolManager::FilterEvent(wxEvent &event)
693{
694 // Snoop the global event stream for changes of focused window. Remember
695 // the last one of our own that is not a grabber.
696
697 if (event.GetEventType() == wxEVT_KILL_FOCUS) {
698 auto &focusEvent = static_cast<wxFocusEvent&>(event);
699 auto window = focusEvent.GetWindow();
700 auto top = wxGetTopLevelParent(window);
701 if(auto toolFrame = dynamic_cast<ToolFrame*>(top))
702 top = toolFrame->GetParent();
703 // window is that which will GET the focus
704 if ( window &&
705 !dynamic_cast<Grabber*>( window ) &&
706 !dynamic_cast<ToolFrame*>( window ) &&
707 top == FindProjectFrame( mParent ) )
708 // Note this is a dangle-proof wxWindowRef:
709 mLastFocus = window;
710 }
711
712 return Event_Skip;
713}
714
715//
716// Read the toolbar states
717//
719{
720 wxString oldpath = gPrefs->GetPath();
721 std::vector<Identifier> unordered[ DockCount ];
722 std::vector<ToolBar*> dockedAndHidden;
723 std::map<Identifier, bool> show;
724 std::map<Identifier, int> width;
725 std::map<Identifier, int> height;
726 int x, y;
727 int dock;
728 bool someFound { false };
729
730#if defined(__WXMAC__)
731 // Disable window animation
732 wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, 1 );
733#endif
734
735 // Change to the bar root
736 gPrefs->SetPath( wxT("/GUI/ToolBars") );
737
738 ToolBarConfiguration::Legacy topLegacy, botLegacy;
739
740 int vMajor, vMinor, vMicro;
741 gPrefs->GetVersionKeysInit(vMajor, vMinor, vMicro);
742 bool useLegacyDock = false;
743 // note that vMajor, vMinor, and vMicro will all be zero if either it's a new audacity.cfg file
744 // or the version is less than 1.3.13 (when there were no version keys according to the comments in
745 // InitPreferences()). So for new audacity.cfg
746 // file useLegacyDock will be true, but this doesn't matter as there are no Dock or DockV2 keys in the file yet.
747 if (vMajor <= 1 ||
748 (vMajor == 2 && (vMinor <= 1 || (vMinor == 2 && vMicro <= 1)))) // version <= 2.2.1
749 useLegacyDock = true;
750
751
752 // Load and apply settings for each bar
753 ForEach([&](ToolBar *bar){
754 //wxPoint Center = mParent->GetPosition() + (mParent->GetSize() * 0.33);
755 //wxPoint Center(
756 // wxSystemSettings::GetMetric( wxSYS_SCREEN_X ) /2 ,
757 // wxSystemSettings::GetMetric( wxSYS_SCREEN_Y ) /2 );
758
759 // Change to the bar subkey
760 auto ndx = bar->GetSection();
761 gPrefs->SetPath( ndx.GET() );
762
763 const bool bShownByDefault = bar->ShownByDefault();
764 const int defaultDock = bar->DefaultDockID();
765
766 // Read in all the settings
767
768 if (useLegacyDock)
769 gPrefs->Read( wxT("Dock"), &dock, -1); // legacy version of DockV2
770 else
771 gPrefs->Read( wxT("DockV2"), &dock, -1);
772
773 const bool found = (dock != -1);
774 if (found)
775 someFound = true;
776 if (!found)
777 dock = defaultDock;
778
779 ToolDock *d;
781 switch(dock)
782 {
783 case TopDockID: d = mTopDock; pLegacy = &topLegacy; break;
784 case BotDockID: d = mBotDock; pLegacy = &botLegacy; break;
785 default: d = nullptr; pLegacy = nullptr; break;
786 }
787
788 bool ordered = ToolBarConfiguration::Read(
789 d ? &d->GetConfiguration() : nullptr,
790 pLegacy,
791 bar, show[ ndx ], bShownByDefault)
792 && found;
793
794 gPrefs->Read( wxT("X"), &x, -1 );
795 gPrefs->Read( wxT("Y"), &y, -1 );
796 gPrefs->Read( wxT("W"), &width[ ndx ], -1 );
797 gPrefs->Read( wxT("H"), &height[ ndx ], -1 );
798
799 bar->SetVisible( show[ ndx ] );
800
801 // Docked or floating?
802 if( dock )
803 {
804 // Default to top dock if the ID isn't valid
805 if( dock < NoDockID || dock > DockCount ) {
806 dock = TopDockID;
807 }
808
809 // Create the bar with the correct parent
810 if( dock == TopDockID )
811 {
812 bar->Create( mTopDock );
813 }
814 else
815 {
816 bar->Create( mBotDock );
817 }
818
819 // Set the width and height
820 if( width[ ndx ] != -1 && height[ ndx ] != -1 )
821 {
822 wxSize sz( width[ ndx ], height[ ndx ] );
823 bar->SetSize( sz );
824 bar->ResizingDone();
825 }
826
827 // Set the width
828 if( width[ ndx ] >= bar->GetSize().x )
829 {
830 wxSize sz( width[ ndx ], bar->GetSize().y );
831 bar->SetSize( sz );
832 bar->Layout();
833 }
834
835 // make a note of docked and hidden toolbars
836 if (!show[ndx])
837 dockedAndHidden.push_back(bar);
838
839 if (!ordered)
840 {
841 // These must go at the end
842 unordered[ dock - 1 ].push_back( ndx );
843 }
844 }
845 else
846 {
847 // Create the bar (with the top dock being temporary parent)
848 bar->Create( mTopDock );
849
850 // Construct a NEW floater
851 wxASSERT(mParent);
852 ToolFrame *f = safenew ToolFrame( mParent, this, bar, wxPoint( x, y ) );
853
854 // Set the width and height
855 if( width[ ndx ] != -1 && height[ ndx ] != -1 )
856 {
857 wxSize sz( width[ ndx ], height[ ndx ] );
858 f->SetSizeHints( sz );
859 f->SetSize( sz );
860 f->Layout();
861 if( (x!=-1) && (y!=-1) )
862 bar->SetPositioned();
863 }
864
865 // Required on Linux Xfce
866 wxSize msz(width[ndx],height[ndx]-1);
867 bar->GetParent()->SetMinSize(msz);
868
869 // Inform toolbar of change
870 bar->SetDocked( NULL, false );
871
872 // Show or hide it
873 Expose( bar->GetSection(), show[ ndx ] );
874 }
875
876 // Change back to the bar root
877 //gPrefs->SetPath( wxT("..") ); <-- Causes a warning...
878 // May or may not have gone into a subdirectory,
879 // so use an absolute path.
880 gPrefs->SetPath( wxT("/GUI/ToolBars") );
881 });
882
883 mTopDock->GetConfiguration().PostRead(topLegacy);
884 mBotDock->GetConfiguration().PostRead(botLegacy);
885
886 // Add all toolbars to their target dock
887 for( dock = 0; dock < DockCount; dock++ )
888 {
889 ToolDock *d = ( dock + 1 == TopDockID ? mTopDock : mBotDock );
890
891 d->LoadConfig();
892
893 // Add all unordered toolbars
894 for( int ord = 0; ord < (int) unordered[ dock ].size(); ord++ )
895 {
896 ToolBar *t = mBars[unordered[dock][ord]].get();
897
898 // Dock it
899 d->Dock( t, false );
900
901 // Show or hide the bar
902 Expose( t->GetSection(), show[ t->GetSection() ] );
903 }
904 }
905
906 // hidden docked toolbars
907 for (auto bar : dockedAndHidden) {
908 bar->SetVisible(false );
909 bar->GetDock()->Dock(bar, false);
910 bar->Expose(false);
911 }
912
913 // Restore original config path
914 gPrefs->SetPath( oldpath );
915
916#if defined(__WXMAC__)
917 // Reinstate original transition
918 wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, mTransition );
919#endif
920
921 // Setup the neighbors according to the
922 // default config
923
924 for (const auto& entry : DefaultConfigTable)
925 {
926 const auto &ndx = entry.barID;
927 const auto bar = GetToolBar(ndx);
928 bar->SetPreferredNeighbors(entry.rightOf, entry.below);
929 }
930
931 if (!someFound)
932 Reset();
933}
934
935//
936// Save the toolbar states
937//
939{
940 if( !gPrefs )
941 {
942 return;
943 }
944
945 wxString oldpath = gPrefs->GetPath();
946 int ndx;
947
948 // Change to the bar root
949 gPrefs->SetPath( wxT("/GUI/ToolBars") );
950
951 // Save state of each bar
952 ForEach([this](ToolBar *bar){
953 // Change to the bar subkey
954 gPrefs->SetPath( bar->GetSection().GET() );
955
956 // Search both docks for toolbar order
957 bool to = mTopDock->GetConfiguration().Contains( bar );
958 bool bo = mBotDock->GetConfiguration().Contains( bar );
959
960 // Save
961 // Note that DockV2 was introduced in 2.2.2 to fix bug #1554. Dock is retained so that
962 // the toolbar layout is not changed when opening a version before 2.2.2, and in particular
963 // its value is compatible with versions 2.1.3 to 2.2.1 which have this bug.
964 ToolDock* dock = bar->GetDock(); // dock for both shown and hidden toolbars
965 gPrefs->Write( wxT("DockV2"), static_cast<int>(dock == mTopDock ? TopDockID : dock == mBotDock ? BotDockID : NoDockID ));
966
967 gPrefs->Write( wxT("Dock"), static_cast<int>( to ? TopDockID : bo ? BotDockID : NoDockID));
968
969 dock = to ? mTopDock : bo ? mBotDock : nullptr; // dock for shown toolbars
971 (dock ? &dock->GetConfiguration() : nullptr, bar);
972
973 wxPoint pos( -1, -1 );
974 wxSize sz = bar->GetSize();
975 if( !bar->IsDocked() && bar->IsPositioned() )
976 {
977 pos = bar->GetParent()->GetPosition();
978 sz = bar->GetParent()->GetSize();
979 }
980 gPrefs->Write( wxT("X"), pos.x );
981 gPrefs->Write( wxT("Y"), pos.y );
982 gPrefs->Write( wxT("W"), sz.x );
983 gPrefs->Write( wxT("H"), sz.y );
984
985 // Change back to the bar root
986 gPrefs->SetPath( wxT("..") );
987 });
988
989 // Restore original config path
990 gPrefs->SetPath( oldpath );
991 gPrefs->Flush();
992}
993
994//
995// Return a pointer to the specified toolbar or nullptr
996//
998{
999 auto end = mBars.end(), iter = mBars.find(type);
1000 return (iter == end) ? nullptr : iter->second.get();
1001}
1002
1003//
1004// Return a pointer to the top dock
1005//
1007{
1008 return mTopDock;
1009}
1010
1012{
1013 return mTopDock;
1014}
1015
1016//
1017// Return a pointer to the bottom dock
1018//
1020{
1021 return mBotDock;
1022}
1023
1025{
1026 return mBotDock;
1027}
1028
1029//
1030// Queues an EVT_TOOLBAR_UPDATED command event to notify any
1031// interest parties of an updated toolbar or dock layout
1032//
1034{
1035 // Queue an update event
1036 wxCommandEvent e( EVT_TOOLBAR_UPDATED );
1037 GetProjectFrame( *mParent ).GetEventHandler()->AddPendingEvent( e );
1038}
1039
1040//
1041// Return docked state of specified toolbar
1042//
1044{
1045 if (auto pBar = GetToolBar(type))
1046 return pBar->IsDocked();
1047 return false;
1048}
1049
1050//
1051// Returns the visibility of the specified toolbar
1052//
1054{
1055 if (auto pBar = GetToolBar(type))
1056 return pBar->IsVisible();
1057 return false;
1058
1059#if 0
1060 // If toolbar is floating
1061 if( !t->IsDocked() )
1062 {
1063 // Must return state of floater window
1064 return t->GetParent()->IsShown();
1065 }
1066
1067 // Return state of docked toolbar
1068 return t->IsShown();
1069#endif
1070}
1071
1072//
1073// Toggles the visible/hidden state of a toolbar
1074//
1076{
1077 Expose( type, !mBars[type]->IsVisible() );
1078 Updated();
1079}
1080
1081//
1082// Set the visible/hidden state of a toolbar
1083//
1084void ToolManager::Expose( Identifier type, bool show )
1085{
1086 ToolBar *t = mBars[type].get();
1087
1088 // Handle docked and floaters differently
1089 if( t->IsDocked() )
1090 {
1091 t->GetDock()->Expose( t->GetSection(), show );
1092 }
1093 else
1094 {
1095 t->Expose( show );
1096 }
1097}
1098
1099//
1100// Ask both docks to (re)layout their bars
1101//
1103{
1104 // Update the layout
1105 if (mTopDock)
1106 {
1108 }
1109
1110 if (mBotDock)
1111 {
1113 }
1114}
1115
1116//
1117// Handle toolbar dragging
1118//
1119void ToolManager::OnMouse( wxMouseEvent & event )
1120{
1121 // Go ahead and set the event to propagate
1122 event.Skip();
1123
1124 // Can't do anything if we're not dragging. This also prevents
1125 // us from intercepting events that don't belong to us from the
1126 // parent since we're Connect()ed to a couple.
1127 if( !mClicked )
1128 {
1129 return;
1130 }
1131
1132#if defined(__WXMAC__)
1133 // Disable window animation
1134 wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, 1 );
1135#endif
1136
1137 // Retrieve the event position
1138 wxPoint pos =
1139 ( (wxWindow *)event.GetEventObject() )->ClientToScreen( event.GetPosition() ) - mDragOffset;
1140
1141
1142 if( !event.LeftIsDown() )
1143 {
1144 // Button was released...finish the drag
1145 // Transition the bar to a dock
1146 if (!mDidDrag) {
1147 if (mPrevDock)
1149 DoneDragging();
1150 return;
1151 }
1152 else if( mDragDock && !event.ShiftDown() )
1153 {
1154 // Trip over...everyone ashore that's going ashore...
1156 Updated();
1158
1159 // Done with the floater
1160 mDragWindow->Destroy();
1161 mDragWindow = nullptr;
1162 mDragBar->Refresh(false);
1163 }
1164 else
1165 {
1166 // Calling SetDocked() to force the grabber button to popup
1167 mDragBar->SetDocked( NULL, false );
1168 }
1169
1170 DoneDragging();
1171 }
1172 else if( event.Dragging() && pos != mLastPos )
1173 {
1174 if (!mDidDrag) {
1175 // Must set the bar afloat if it's currently docked
1176 mDidDrag = true;
1177 wxPoint mp = event.GetPosition();
1178 mp = GetProjectFrame( *mParent ).ClientToScreen(mp);
1179 if (!mDragWindow) {
1180 // We no longer have control
1181 if (mPrevDock)
1183 UndockBar(mp);
1184 // Rearrange the remaining toolbars before trying to re-insert this one.
1186 }
1187 }
1188
1189 // Make toolbar follow the mouse
1190 mDragWindow->Move( pos );
1191
1192 // Remember to prevent excessive movement
1193 mLastPos = pos;
1194
1195 // Calc the top dock hittest rectangle
1196 wxRect tr = mTopDock->GetRect();
1197 tr.SetBottom( tr.GetBottom() + 10 );
1198 tr.SetPosition( mTopDock->GetParent()->ClientToScreen( tr.GetPosition() ) );
1199
1200 // Calc the bottom dock hittest rectangle
1201 wxRect br = mBotDock->GetRect();
1202 br.SetTop( br.GetTop() - 10 );
1203 br.SetBottom( br.GetBottom() + 20 );
1204 br.SetPosition( mBotDock->GetParent()->ClientToScreen( br.GetPosition() ) );
1205
1206
1207 // Add half the bar height. We could use the actual bar height, but that would be confusing as a
1208 // bar removed at a place might not dock back there if just let go.
1209 // Also add 5 pixels in horizontal direction, so that a click without a move (or a very small move)
1210 // lands back where we started.
1211 pos += wxPoint( 5, 20 );
1212
1213
1214 // To find which dock, rather than test against pos, test against the whole dragger rect.
1215 // This means it is enough to overlap the dock to dock with it.
1216 wxRect barRect = mDragWindow->GetRect();
1217 ToolDock *dock = NULL;
1218 if( tr.Intersects( barRect ) )
1219 dock = mTopDock;
1220 else if( br.Intersects( barRect ) )
1221 dock = mBotDock;
1222
1223 // Looks like we have a winner...
1224 if( dock )
1225 {
1226 wxPoint p;
1227 wxRect r;
1228
1229 // Calculate where the bar would be placed
1230 mDragBefore = dock->PositionBar( mDragBar, pos, r );
1231
1232 // If different than the last time, the indicator must be moved
1233 if( r != mBarPos )
1234 {
1235 wxRect dr = dock->GetRect();
1236
1237 // Hide the indicator before changing the shape
1238 mIndicator->Hide();
1239
1240 // Decide which direction the arrow should point
1241 if( r.GetTop() >= dr.GetHeight() )
1242 {
1243 const auto &box = mDown->GetBox();
1244 p.x = dr.GetLeft() + ( dr.GetWidth() / 2 )
1245 - (box.GetWidth() / 2);
1246 p.y = dr.GetBottom() - box.GetHeight();
1247 mCurrent = mDown.get();
1248 }
1249 else
1250 {
1251 // r is the rectangle of the toolbar being dragged.
1252 // A tall undocked toolbar will become at most 2 tbs
1253 // high when docked, so the triangular drop indicator
1254 // needs to use that height, h, not the bar height
1255 // for calculating where to be drawn.
1256 const int tbs = toolbarSingle + toolbarGap;
1257 int h = wxMin(r.GetHeight(), 2*tbs-1);
1258 p.x = dr.GetLeft() + r.GetLeft();
1259 p.y = dr.GetTop() + r.GetTop() +
1260 ( ( h - mLeft->GetBox().GetHeight() ) / 2 );
1261 mCurrent = mLeft.get();
1262 }
1263
1264 // Change the shape while hidden and then show it if okay
1265 mIndicator->SetShape( *mCurrent );
1266 if( !event.ShiftDown() )
1267 {
1268 mIndicator->Show();
1269 mIndicator->Update();
1270 }
1271
1272 // Move it into position
1273 // LL: Do this after the Show() since KDE doesn't move the window
1274 // if it's not shown. (Do it outside if the previous IF as well)
1275 mIndicator->Move( dock->GetParent()->ClientToScreen( p ) );
1276
1277 // Remember for next go round
1278 mBarPos = r;
1279 }
1280 }
1281 else
1282 {
1283 // Hide the indicator if it's still shown
1284 if( mBarPos.x != -1 )
1285 {
1286 // Hide any
1287 mIndicator->Hide();
1288 mBarPos.x = -1;
1289 mBarPos.y = -1;
1290 }
1291 }
1292
1293 // Remember to which dock the drag bar belongs.
1294 mDragDock = dock;
1295 }
1296
1297#if defined(__WXMAC__)
1298 // Reinstate original transition
1299 wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, mTransition );
1300#endif
1301}
1302
1303//
1304// Deal with NEW capture lost event
1305//
1306void ToolManager::OnCaptureLost( wxMouseCaptureLostEvent & event )
1307{
1308 // Can't do anything if we're not dragging. This also prevents
1309 // us from intercepting events that don't belong to us from the
1310 // parent since we're Connect()ed to a couple.
1311 if( !mDragWindow )
1312 {
1313 event.Skip();
1314 return;
1315 }
1316
1317 // Simulate button up
1318 wxMouseEvent e(wxEVT_LEFT_UP);
1319 e.SetEventObject(mParent);
1320 OnMouse(e);
1321}
1322
1324{
1326}
1327
1328//
1329// Watch for shift key changes
1330//
1331void ToolManager::OnTimer( wxTimerEvent & event )
1332{
1333 // Go ahead and set the event to propagate
1334 event.Skip();
1335
1336 // Can't do anything if we're not dragging. This also prevents
1337 // us from intercepting events that don't belong to us from the
1338 // parent since we're Connect()ed to a couple.
1339 if( !mDragWindow )
1340 {
1341 return;
1342 }
1343
1344 bool state = wxGetKeyState( WXK_SHIFT );
1345 if( mLastState != state )
1346 {
1347 mLastState = state;
1348
1349#if defined(__WXMAC__)
1350 // Disable window animation
1351 wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, 1 );
1352#endif
1353
1354 mIndicator->Show( !state );
1355
1356#if defined(__WXMAC__)
1357 // Disable window animation
1358 wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, mTransition );
1359#endif
1360 }
1361
1362 return;
1363}
1364
1365//
1366// Handle Indicator paint events
1367//
1368// Really only needed for the Mac since SetBackgroundColour()
1369// doesn't seem to work with shaped frames.
1370//
1371void ToolManager::OnIndicatorPaint( wxPaintEvent & event )
1372{
1373 // TODO: Better to use a bitmap than a triangular region.
1374 wxWindow *w = (wxWindow *)event.GetEventObject();
1375 wxPaintDC dc( w );
1376 // TODO: Better (faster) to use the existing spare brush.
1377 wxBrush brush( theTheme.Colour( clrTrackPanelText ) );
1378 dc.SetBackground( brush );
1379 dc.Clear();
1380}
1381
1382//
1383// Handle Indicator creation event
1384//
1385// Without this, the initial Indicator window will be a solid blue square
1386// until the next time it changes.
1387//
1388void ToolManager::OnIndicatorCreate( wxWindowCreateEvent & event )
1389{
1390#if defined(__WXGTK__)
1391 mIndicator->SetShape( *mCurrent );
1392#endif
1393 event.Skip();
1394}
1395
1396void ToolManager::UndockBar( wxPoint mp )
1397{
1398#if defined(__WXMAC__)
1399 // Disable window animation
1400 wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, 1 );
1401#endif
1402
1403 // Adjust the starting position
1404 mp -= mDragOffset;
1405
1406 // Inform toolbar of change
1407 mDragBar->SetDocked( NULL, true );
1409
1410 // Construct a NEW floater
1411 wxASSERT(mParent);
1413 mDragWindow->SetLayoutDirection(wxLayout_LeftToRight);
1414 // Make sure the ferry is visible
1415 mDragWindow->Show();
1416
1417 // Notify parent of change
1418 Updated();
1419
1420#if defined(__WXMAC__)
1421 // Reinstate original transition
1422 wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, mTransition );
1423#endif
1424}
1425
1426//
1427// Transition a toolbar from float to dragging
1428//
1430{
1431 // No need to propagate any further
1432 event.Skip( false );
1433
1434 if(event.IsEscaping())
1435 return HandleEscapeKey();
1436
1437 // Remember which bar we're dragging
1438 mDragBar = GetToolBar(event.BarId());
1439
1440 // Remember state, in case of ESCape key later
1441 if (mDragBar->IsDocked()) {
1442 mPrevDock = dynamic_cast<ToolDock*>(mDragBar->GetParent());
1443 wxASSERT(mPrevDock);
1446 }
1447 else
1448 mPrevPosition = mDragBar->GetParent()->GetPosition();
1449
1450 // Calculate the drag offset
1451 wxPoint mp = event.GetPosition();
1452 mDragOffset = mp -
1453 mDragBar->GetParent()->ClientToScreen( mDragBar->GetPosition() ) +
1454 wxPoint( 1, 1 );
1455
1456 mClicked = true;
1457 if( mPrevDock )
1458 {
1459 mDragWindow = nullptr;
1460 }
1461 else
1462 {
1463 mDragWindow = (ToolFrame *) mDragBar->GetParent();
1464 }
1465
1466 // We want all mouse events from this point on
1467 auto &window = GetProjectFrame( *mParent );
1468 if( !window.HasCapture() )
1469 window.CaptureMouse();
1470
1471 // Start monitoring shift key changes
1472 mLastState = wxGetKeyState( WXK_SHIFT );
1473 mTimer.Start( 100 );
1474}
1475
1476
1478{
1479 if (mDragBar) {
1480 if(mPrevDock) {
1481 // Sheriff John Stone,
1482 // Why don't you leave me alone?
1483 // Well, I feel so break up
1484 // I want to go home.
1486 mPrevDock->Dock( mDragBar, true, mPrevSlot );
1487 Updated();
1488
1489 // Done with the floater
1491 mDragWindow->Destroy();
1492 mDragWindow = nullptr;
1493 mDragBar->Refresh(false);
1494 }
1495 else {
1496 // Floater remains, and returns to where it begain
1497 auto parent = mDragBar->GetParent();
1498 parent->SetPosition(mPrevPosition);
1499 mDragBar->SetDocked(NULL, false);
1500 }
1501
1502 DoneDragging();
1503 }
1504}
1505
1507{
1508 // Done dragging - ensure grabber button isn't pushed
1509 if( mDragBar )
1510 {
1511 mDragBar->SetDocked( mDragBar->GetDock(), false );
1512 }
1513
1514 // Release capture
1515 auto &window = GetProjectFrame( *mParent );
1516 if( window.HasCapture() )
1517 {
1518 window.ReleaseMouse();
1519 }
1520
1521 // Hide the indicator
1522 mIndicator->Hide();
1523
1524 mDragWindow = NULL;
1525 mDragDock = NULL;
1526 mDragBar = NULL;
1527 mPrevDock = NULL;
1530 mLastPos.x = mBarPos.x = -1;
1531 mLastPos.y = mBarPos.y = -1;
1532 mTimer.Stop();
1533 mDidDrag = false;
1534 mClicked = false;
1535
1536 RestoreFocus();
1537}
1538
1540{
1541 if (mLastFocus) {
1542 auto temp1 = AButton::TemporarilyAllowFocus();
1543 auto temp2 = ASlider::TemporarilyAllowFocus();
1545 mLastFocus->SetFocus();
1546 return true;
1547 }
1548 return false;
1549}
1550
1552{
1553 for (auto pProject : AllProjects{}) {
1554 auto &project = *pProject;
1555 ModifyToolbarMenus(project);
1556 }
1557}
1558
1559#include "../commands/CommandManager.h"
1561{
1562 // Refreshes can occur during shutdown and the toolmanager may already
1563 // be deleted, so protect against it.
1564 auto &toolManager = ToolManager::Get( project );
1565
1566 // Now, go through each toolbar, and call EnableDisableButtons()
1567 toolManager.ForEach([](auto bar){
1568 if (bar)
1569 bar->EnableDisableButtons();
1570 });
1571
1572 // These don't really belong here, but it's easier and especially so for
1573 // the Edit toolbar and the sync-lock menu item.
1574 bool active = SyncLockTracks.Read();
1575 SyncLockState::Get(project).SetSyncLock(active);
1576
1577 CommandManager::Get( project ).UpdateCheckmarks( project );
1578}
1579
1581 Identifier id, const CommandID &name, const TranslatableString &label_in,
1582 const Registry::OrderingHint &hint,
1583 std::vector< Identifier > excludeIDs
1584) : mId{ id }
1585 , mAttachedItem{
1586 Registry::Placement{ wxT("View/Other/Toolbars/Toolbars/Other"), hint },
1587 ( MenuTable::FinderScope(
1589 { return *this; } ),
1590 MenuTable::Command( name, label_in,
1594 auto &toolManager = ToolManager::Get( project );
1595 return toolManager.IsVisible( id ); } ) ) ) }
1596 , mExcludeIds{ std::move( excludeIDs ) }
1597{}
1598
1600{
1601 auto &project = context.project;
1602 auto &toolManager = ToolManager::Get( project );
1603
1604 if( !toolManager.IsVisible( mId ) )
1605 {
1606 for ( const auto excludedID : mExcludeIds )
1607 toolManager.Expose( excludedID, false );
1608 }
1609
1610 toolManager.ShowHide(mId);
1611 ToolManager::Get(project).ModifyToolbarMenus(project);
1612}
wxT("CloseDown"))
END_EVENT_TABLE()
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:34
wxEvtHandler CommandHandlerObject
const TranslatableString name
Definition: Distortion.cpp:76
#define EVT_GRABBER(id, fn)
Definition: Grabber.h:97
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Definition: LabelDialog.cpp:89
#define safenew
Definition: MemoryX.h:10
FileConfig * gPrefs
Definition: Prefs.cpp:70
static ProjectFileIORegistry::AttributeWriterEntry entry
wxFrame * FindProjectFrame(AudacityProject *project)
Get a pointer to the window associated with a project, or null if the given pointer is null,...
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
accessors for certain important windows associated with each project
static const AttachedProjectObjects::RegisteredFactory manager
BoolSetting SyncLockTracks
Definition: SyncLock.cpp:172
THEME_API Theme theTheme
Definition: Theme.cpp:82
#define toolbarSingle
Definition: ToolBar.h:59
@ ToolBarFloatMargin
Definition: ToolBar.h:67
#define toolbarGap
Definition: ToolBar.h:64
@ BotDockID
Definition: ToolDock.h:44
@ DockCount
Definition: ToolDock.h:45
@ TopDockID
Definition: ToolDock.h:43
@ NoDockID
Definition: ToolDock.h:42
static const AudacityProject::AttachedObjects::RegisteredFactory key
Methods for ToolManager.
#define sizerW
Methods for ToolFrame.
Definition: ToolManager.cpp:67
IMPLEMENT_CLASS(ToolFrame, wxFrame)
static struct DefaultConfigEntry DefaultConfigTable[]
int id
static TempAllowFocus TemporarilyAllowFocus()
Definition: AButton.cpp:658
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:187
static TempAllowFocus TemporarilyAllowFocus()
Definition: ASlider.cpp:1894
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
void UpdateCheckmarks(AudacityProject &project)
static CommandManager & Get(AudacityProject &project)
void GetVersionKeysInit(int &major, int &minor, int &micro) const
Definition: FileConfig.h:56
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
virtual const wxString & GetPath() const wxOVERRIDE
Definition: FileConfig.cpp:98
virtual void SetPath(const wxString &strPath) wxOVERRIDE
Definition: FileConfig.cpp:93
static result_type Call(Arguments &&...arguments)
Null check of the installed function is done for you.
Grabber Class.
Definition: Grabber.h:48
bool IsEscaping() const
Definition: Grabber.h:75
Identifier BarId() const
Definition: Grabber.h:77
The widget to the left of a ToolBar that allows it to be dragged around to NEW positions.
Definition: Grabber.h:107
An explicitly nonlocalized string, not meant for the user to see.
Definition: Identifier.h:22
const wxString & GET() const
Explicit conversion to wxString, meant to be ugly-looking and demanding of a comment why it's correct...
Definition: Identifier.h:66
static MenuManager & Get(AudacityProject &project)
Definition: Menus.cpp:69
static TempAllowFocus TemporarilyAllowFocus()
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
Definition: Observer.h:199
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:200
void SetSyncLock(bool flag)
Definition: SyncLock.cpp:48
static SyncLockState & Get(AudacityProject &project)
Definition: SyncLock.cpp:26
wxColour & Colour(int iIndex)
static bool Read(ToolBarConfiguration *pConfiguration, Legacy *pLegacy, ToolBar *bar, bool &visible, bool defaultVisible)
Definition: ToolDock.cpp:281
static const Position UnspecifiedPosition
Definition: ToolDock.h:106
bool Contains(const ToolBar *bar) const
Definition: ToolDock.h:235
static void Write(const ToolBarConfiguration *pConfiguration, const ToolBar *bar)
Definition: ToolDock.cpp:355
void PostRead(Legacy &legacy)
Definition: ToolDock.cpp:334
Position Find(const ToolBar *bar) const
Definition: ToolDock.cpp:87
void Remove(const ToolBar *bar)
Definition: ToolDock.cpp:224
Works with ToolManager and ToolDock to provide a dockable window in which buttons can be placed.
Definition: ToolBar.h:74
void SetIndex(int index)
Set a value used for computing cascading positions of undocked bars.
Definition: ToolBar.h:114
virtual void EnableDisableButtons()=0
bool IsDocked() const
Definition: ToolBar.cpp:433
@ TopDockID
Definition: ToolBar.h:93
virtual void SetDocked(ToolDock *dock, bool pushed)
Definition: ToolBar.cpp:661
virtual void ReCreateButtons()
Definition: ToolBar.cpp:533
void SetVisible(bool bVisible)
Definition: ToolBar.cpp:446
bool IsResizable() const
Definition: ToolBar.cpp:425
int GetIndex() const
Get a value used for computing cascading positions of undocked bars.
Definition: ToolBar.h:112
virtual void ResizingDone()
Definition: ToolBar.h:197
ToolDock * GetDock()
Definition: ToolBar.cpp:647
bool IsPositioned()
Definition: ToolBar.h:138
void SetPositioned()
Definition: ToolBar.h:140
Identifier GetSection()
Definition: ToolBar.cpp:400
virtual bool Expose(bool show=true)
Definition: ToolBar.cpp:459
virtual void SetToDefaultSize()
Definition: ToolBar.cpp:513
virtual bool HideAfterReset() const
Default implementation returns false.
Definition: ToolBar.cpp:370
void SetPreferredNeighbors(Identifier left, Identifier top={})
Definition: ToolBar.cpp:652
virtual bool ShownByDefault() const
Whether the toolbar should be shown by default. Default implementation returns true.
Definition: ToolBar.cpp:365
virtual void Create(wxWindow *parent)
Definition: ToolBar.cpp:492
virtual wxSize GetDockedSize()
Definition: ToolBar.h:146
virtual DockID DefaultDockID() const
Which dock the toolbar defaults into. Default implementation chooses the top dock.
Definition: ToolBar.cpp:375
A dynamic panel where a ToolBar can be docked.
Definition: ToolDock.h:292
void Expose(Identifier type, bool show)
Definition: ToolDock.cpp:858
void Undock(ToolBar *bar)
Definition: ToolDock.cpp:426
void RestoreConfiguration(ToolBarConfiguration &backup)
Definition: ToolDock.cpp:848
void LoadConfig()
Definition: ToolDock.cpp:466
void WrapConfiguration(ToolBarConfiguration &backup)
Definition: ToolDock.cpp:841
ToolBarConfiguration & GetConfiguration()
Definition: ToolDock.h:311
ToolBarConfiguration::Position PositionBar(ToolBar *t, const wxPoint &pos, wxRect &rect)
Definition: ToolDock.cpp:744
void LayoutToolBars()
Definition: ToolDock.cpp:687
void Dock(ToolBar *bar, bool deflate, ToolBarConfiguration::Position ndx=ToolBarConfiguration::UnspecifiedPosition)
Definition: ToolDock.cpp:438
class ToolFrame
Definition: ToolManager.h:190
ToolFrame(AudacityProject *parent, ToolManager *manager, ToolBar *bar, wxPoint pos)
Definition: ToolManager.cpp:73
wxSize mOrigSize
Definition: ToolManager.h:236
ToolBar * mBar
Definition: ToolManager.h:234
void OnMotion(wxMouseEvent &event)
wxSize mMinSize
Definition: ToolManager.h:235
ToolManager * mManager
Definition: ToolManager.h:233
void Resize(const wxSize &size)
void OnClose(wxCloseEvent &event)
void OnGrabber(GrabberEvent &event)
void OnPaint(wxPaintEvent &WXUNUSED(event))
void OnCaptureLost(wxMouseCaptureLostEvent &WXUNUSED(event))
void LockInMinSize(ToolBar *pBar)
void ClearBar()
Definition: ToolManager.h:198
void OnToolBarUpdate(wxCommandEvent &event)
void OnKeyDown(wxKeyEvent &event)
class ToolManager
Definition: ToolManager.h:56
static ToolManager & Get(AudacityProject &project)
void OnIndicatorCreate(wxWindowCreateEvent &event)
bool IsDocked(Identifier type) const
bool mLastState
Definition: ToolManager.h:158
ToolDock * GetBotDock()
void OnMenuUpdate(struct MenuUpdateMessage)
ToolBar * mDragBar
Definition: ToolManager.h:145
static void OnResetToolBars(const CommandContext &context)
void OnGrabber(GrabberEvent &event)
void ReadConfig()
void OnCaptureLost(wxMouseCaptureLostEvent &event)
ToolDock * mTopDock
Definition: ToolManager.h:164
void OnTimer(wxTimerEvent &event)
void Expose(Identifier type, bool show)
bool mTransition
Definition: ToolManager.h:161
void ShowHide(Identifier type)
std::map< Identifier, ToolBar::Holder > mBars
map not unordered_map, for the promise made by ForEach
Definition: ToolManager.h:168
void CreateWindows()
wxPoint mPrevPosition
Definition: ToolManager.h:170
wxTimer mTimer
Definition: ToolManager.h:157
ToolDock * GetTopDock()
ToolFrame * mDragWindow
Definition: ToolManager.h:143
void WriteConfig()
int FilterEvent(wxEvent &event) override
std::unique_ptr< wxRegion > mLeft
Definition: ToolManager.h:154
void RegenerateTooltips()
void UndockBar(wxPoint mp)
Observer::Subscription mMenuManagerSubscription
Definition: ToolManager.h:139
void LayoutToolBars()
void Destroy()
AudacityProject * mParent
Definition: ToolManager.h:140
void OnIndicatorPaint(wxPaintEvent &event)
void HandleEscapeKey()
ToolBarConfiguration mPrevConfiguration
Definition: ToolManager.h:174
std::unique_ptr< wxRegion > mDown
Definition: ToolManager.h:154
ToolDock * mPrevDock
Definition: ToolManager.h:171
static void ModifyToolbarMenus(AudacityProject &project)
ToolBarConfiguration::Position mPrevSlot
Definition: ToolManager.h:173
void DoneDragging()
void ForEach(F &&fun)
Visit bars, lexicographically by their textual ids.
Definition: ToolManager.h:103
ToolDock * mDragDock
Definition: ToolManager.h:144
void OnMouse(wxMouseEvent &event)
ToolBarConfiguration::Position mDragBefore
Definition: ToolManager.h:147
bool RestoreFocus()
Destroy_ptr< wxFrame > FramePtr
Definition: ToolManager.h:152
wxRegion * mCurrent
Definition: ToolManager.h:155
wxRect mBarPos
Definition: ToolManager.h:150
ToolDock * mBotDock
Definition: ToolManager.h:165
static void ModifyAllProjectToolbarMenus()
wxWindowRef mLastFocus
Definition: ToolManager.h:141
ToolManager(AudacityProject *parent)
ToolBar * GetToolBar(const Identifier &type) const
wxPoint mDragOffset
Definition: ToolManager.h:146
FramePtr mIndicator
Definition: ToolManager.h:153
wxPoint mLastPos
Definition: ToolManager.h:149
bool IsVisible(Identifier type) const
Holds a msgid for the translation catalog; may also bind format arguments.
constexpr auto Command
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
Definition: Menus.h:35
static RegisteredToolbarFactory factory
void OnShowToolBar(const CommandContext &context)
const std::vector< Identifier > mExcludeIds
Definition: ToolManager.h:259
const Identifier mId
Definition: ToolManager.h:257
AttachedToolBarMenuItem(Identifier id, const CommandID &name, const TranslatableString &label_in, const Registry::OrderingHint &hint={}, std::vector< Identifier > excludeIds={})
Options && CheckTest(const CheckFn &fn) &&
Identifier rightOf
Identifier barID
Identifier below
Sent when menus update (such as for changing enablement of items)
Definition: Menus.h:74
static const Functions & GetFactories()
Definition: ToolBar.cpp:1047