1 /**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 ToolBar.cpp
6
7 Dominic Mazzoni
8 Shane T. Mueller
9 Leland Lucius
10
11 See ToolBar.h for details.
12
13 *******************************************************************//**
14
15 \file ToolBar.cpp
16
17 Implements ToolBar
18
19 *//*******************************************************************//**
20
21 \class ToolBar
22 \brief Works with ToolManager and ToolDock to provide a dockable window
23 in which buttons can be placed.
24
25 *//**********************************************************************/
26
27
28 #include "ToolBar.h"
29
30 // For compilers that support precompilation, includes "wx/wx.h".
31 #include <wx/wxprec.h>
32
33 #include <wx/setup.h> // for wxUSE_* macros
34
35 #ifndef WX_PRECOMP
36 #include <wx/dcclient.h>
37 #include <wx/defs.h>
38 #include <wx/gdicmn.h>
39 #include <wx/image.h>
40 #include <wx/intl.h>
41 #include <wx/settings.h>
42 #include <wx/sizer.h>
43 #include <wx/sysopt.h>
44 #include <wx/window.h>
45 #endif /* */
46
47 #include "ToolDock.h"
48
49 #include "AllThemeResources.h"
50 #include "AColor.h"
51 #include "ImageManipulation.h"
52 #include "Project.h"
53 #include "../commands/CommandManager.h"
54 #include "../widgets/AButton.h"
55 #include "../widgets/Grabber.h"
56 #include "Prefs.h"
57
58 ////////////////////////////////////////////////////////////
59 /// ToolBarResizer
60 ////////////////////////////////////////////////////////////
61
62 //
63 // Width of the resize grab area
64 //
65 #define RWIDTH 4
66
67 /// \brief a wxWindow that provides the resizer for a toolbar on the
68 /// right hand side. Responsible for drawing the resizer appearance,
69 /// resizing mouse events and constraining the resizing.
70 class ToolBarResizer final : public wxWindow
71 {
72 public:
73 ToolBarResizer(ToolBar *mBar);
74 virtual ~ToolBarResizer();
75
76 // We don't need or want to accept focus.
77 // Note that AcceptsFocusFromKeyboard() is overridden rather than
78 // AcceptsFocus(), so that resize can be cancelled by ESC
AcceptsFocusFromKeyboard() const79 bool AcceptsFocusFromKeyboard() const override {return false;}
80
81 private:
82 void OnErase(wxEraseEvent & event);
83 void OnPaint(wxPaintEvent & event);
84 void OnLeftDown(wxMouseEvent & event);
85 void OnLeftUp(wxMouseEvent & event);
86 void OnEnter(wxMouseEvent & event);
87 void OnLeave(wxMouseEvent & event);
88 void OnMotion(wxMouseEvent & event);
89 void ResizeBar(const wxSize &size);
90 void OnCaptureLost(wxMouseCaptureLostEvent & event);
91 void OnKeyDown(wxKeyEvent &event);
92
93 private:
94 ToolBar *mBar;
95 wxPoint mResizeOffset;
96 wxSize mOrigSize;
97 wxWindowRef mOrigFocus{};
98
99 DECLARE_EVENT_TABLE()
100 };
101
102 //
103 // Event table
104 //
105 BEGIN_EVENT_TABLE( ToolBarResizer, wxWindow )
106 EVT_ERASE_BACKGROUND( ToolBarResizer::OnErase )
107 EVT_PAINT( ToolBarResizer::OnPaint )
108 EVT_LEFT_DOWN( ToolBarResizer::OnLeftDown )
109 EVT_LEFT_UP( ToolBarResizer::OnLeftUp )
110 EVT_ENTER_WINDOW( ToolBarResizer::OnEnter )
111 EVT_LEAVE_WINDOW( ToolBarResizer::OnLeave )
112 EVT_MOTION( ToolBarResizer::OnMotion )
113 EVT_MOUSE_CAPTURE_LOST( ToolBarResizer::OnCaptureLost )
114 EVT_KEY_DOWN( ToolBarResizer::OnKeyDown )
115 END_EVENT_TABLE();
116
ToolBarResizer(ToolBar * bar)117 ToolBarResizer::ToolBarResizer(ToolBar *bar)
118 : wxWindow(bar, wxID_ANY, wxDefaultPosition, wxSize(RWIDTH, -1))
119 {
120 mBar = bar;
121 SetCursor( wxCURSOR_SIZEWE );
122 }
123
~ToolBarResizer()124 ToolBarResizer::~ToolBarResizer()
125 {
126 if(HasCapture())
127 ReleaseMouse();
128 }
129
130 //
131 // Handle background erasure
132 //
OnErase(wxEraseEvent & WXUNUSED (event))133 void ToolBarResizer::OnErase( wxEraseEvent & WXUNUSED(event) )
134 {
135 // Ignore it to prevent flashing
136 }
137
138 //
139 // This draws the background of a toolbar
140 //
OnPaint(wxPaintEvent & event)141 void ToolBarResizer::OnPaint( wxPaintEvent & event )
142 {
143 wxPaintDC dc( (wxWindow *) event.GetEventObject() );
144
145 // Start with a clean background
146 //
147 // Under GTK, we specifically set the toolbar background to the background
148 // colour in the system theme.
149 #if defined( __WXGTK__ )
150 // dc.SetBackground( wxBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BACKGROUND ) ) );
151 #endif
152 dc.SetBackground( wxBrush( theTheme.Colour( clrMedium ) ) );
153 dc.Clear();
154
155 wxSize sz = GetSize();
156
157 AColor::Dark( &dc, false );
158 AColor::Line(dc, sz.x - 4, 0, sz.x - 4, sz.y );
159 AColor::Line(dc, sz.x - 1, 0, sz.x - 1, sz.y );
160 }
161
162 //
163 // Handle toolbar resizing
164 //
OnLeftDown(wxMouseEvent & event)165 void ToolBarResizer::OnLeftDown( wxMouseEvent & event )
166 {
167 // Go ahead and set the event to propagate
168 event.Skip();
169
170 // Retrieve the mouse position
171 // Bug 1896: This is at time of processing the event, rather than at time
172 // of generation of event. Works around event.GetPosition() giving
173 // incorrect values if position of resizer is changing.
174 mResizeOffset = wxGetMousePosition()-mBar->GetRect().GetBottomRight();
175
176 mOrigSize = mBar->GetSize();
177
178 // We want all of the mouse events
179 if( !HasCapture() )
180 CaptureMouse();
181 }
182
OnLeftUp(wxMouseEvent & event)183 void ToolBarResizer::OnLeftUp( wxMouseEvent & event )
184 {
185 // Go ahead and set the event to propagate
186 event.Skip();
187
188 if( HasCapture() )
189 {
190 ReleaseMouse();
191 if (mOrigFocus)
192 mOrigFocus->SetFocus();
193 mOrigFocus = nullptr;
194 mBar->ResizingDone();
195 }
196 }
197
OnEnter(wxMouseEvent &)198 void ToolBarResizer::OnEnter( wxMouseEvent & /*event*/ )
199 {
200 // Bug 1201: On Mac, unsetting and re-setting the tooltip may be needed
201 // to make it pop up when we want it.
202 const auto text = GetToolTipText();
203 UnsetToolTip();
204 SetToolTip(text);
205 if (!mOrigFocus)
206 mOrigFocus = FindFocus();
207 }
208
OnLeave(wxMouseEvent &)209 void ToolBarResizer::OnLeave( wxMouseEvent & /*event*/ )
210 {
211 if (!GetCapture())
212 mOrigFocus = nullptr;
213 }
214
OnMotion(wxMouseEvent & event)215 void ToolBarResizer::OnMotion( wxMouseEvent & event )
216 {
217 // Go ahead and set the event to propagate
218 event.Skip();
219
220 if( HasCapture() && event.Dragging() )
221 {
222 // Retrieve the mouse position
223 // Bug 1896: This is at time of processing the event, rather than at time
224 // of generation of event. Works around event.GetPosition() giving
225 // incorrect values if position of resizer is changing.
226 wxPoint pos = wxGetMousePosition();
227
228 wxRect r = mBar->GetRect();
229 wxSize minsz = mBar->GetMinSize();
230 wxSize maxsz = mBar->GetMaxSize();
231 wxSize psz = mBar->GetParent()->GetClientSize();
232
233 // Adjust the size based on updated mouse position.
234 r.width = ( pos.x - mResizeOffset.x ) - r.x;
235
236 // Keep it within max size, if specified
237 if( maxsz != wxDefaultSize )
238 {
239 if( r.width > maxsz.x )
240 {
241 r.width = maxsz.x;
242 }
243 if( r.height > maxsz.y )
244 {
245 r.height = maxsz.y;
246 }
247 }
248
249 // Constrain
250 if( r.width < minsz.x )
251 {
252 // Don't allow resizing to go too small
253 r.width = minsz.x;
254 }
255 else if( r.GetRight() > psz.x - 3 )
256 {
257 // Don't allow resizing to go too large
258 //
259 // The 3 magic pixels are because I'm too chicken to change the
260 // calculations in ToolDock::LayoutToolBars() even though I'm
261 // the one that set them up. :-)
262 r.SetRight( psz.x - 3 );
263 }
264
265 ResizeBar( r.GetSize() );
266 }
267 }
268
ResizeBar(const wxSize & size)269 void ToolBarResizer::ResizeBar(const wxSize &size)
270 {
271 mBar->SetSize( size );
272
273 // Tell everyone we've changed sizes
274 mBar->Updated();
275
276 // Refresh our world
277 mBar->GetParent()->Refresh();
278 mBar->GetParent()->Update();
279 }
280
OnCaptureLost(wxMouseCaptureLostEvent & WXUNUSED (event))281 void ToolBarResizer::OnCaptureLost( wxMouseCaptureLostEvent & WXUNUSED(event) )
282 {
283 if( HasCapture() )
284 {
285 ReleaseMouse();
286 if (mOrigFocus)
287 mOrigFocus->SetFocus();
288 mOrigFocus = nullptr;
289 }
290 }
291
OnKeyDown(wxKeyEvent & event)292 void ToolBarResizer::OnKeyDown(wxKeyEvent &event)
293 {
294 event.Skip();
295 if (HasCapture() && WXK_ESCAPE == event.GetKeyCode()) {
296 ResizeBar( mOrigSize );
297 ReleaseMouse();
298 if (mOrigFocus)
299 mOrigFocus->SetFocus();
300 mOrigFocus = nullptr;
301 }
302 }
303
304 ////////////////////////////////////////////////////////////
305 /// Methods for ToolBar
306 ////////////////////////////////////////////////////////////
307
308 //
309 // Define class to RTTI
310 //
311 IMPLEMENT_CLASS( ToolBar, wxPanelWrapper );
312
313 //
314 // Custom event
315 //
316 DEFINE_EVENT_TYPE(EVT_TOOLBAR_UPDATED)
317
318 //
319 // Event table
320 //
BEGIN_EVENT_TABLE(ToolBar,wxPanelWrapper)321 BEGIN_EVENT_TABLE( ToolBar, wxPanelWrapper )
322 EVT_PAINT( ToolBar::OnPaint )
323 EVT_ERASE_BACKGROUND( ToolBar::OnErase )
324 EVT_MOUSE_EVENTS( ToolBar::OnMouseEvents )
325 END_EVENT_TABLE()
326
327 //
328 // Constructor
329 //
330 ToolBar::ToolBar( AudacityProject &project,
331 int type,
332 const TranslatableString &label,
333 const wxString §ion,
334 bool resizable )
335 : wxPanelWrapper()
336 , mProject{ project }
337 {
338 // Save parameters
339 mType = type;
340 mLabel = label;
341 mSection = section;
342 mResizable = resizable;
343
344 // Initialize everything
345 mParent = NULL;
346 mHSizer = NULL;
347 mVisible = false;
348 mPositioned = false;
349
350 mGrabber = NULL;
351 mResizer = NULL;
352 SetId(mType);
353 }
354
355 //
356 // Destructor
357 //
~ToolBar()358 ToolBar::~ToolBar()
359 {
360 }
361
362 //
363 // Returns the toolbar title
364 //
GetTitle()365 TranslatableString ToolBar::GetTitle()
366 {
367 /* i18n-hint: %s will be replaced by the name of the kind of toolbar.*/
368 return XO("Audacity %s Toolbar").Format( GetLabel() );
369 }
370
371 //
372 // Returns the toolbar label
373 //
GetLabel()374 TranslatableString ToolBar::GetLabel()
375 {
376 return mLabel;
377 }
378
379 //
380 // Returns the toolbar preferences section
381 //
GetSection()382 wxString ToolBar::GetSection()
383 {
384 return mSection;
385 }
386
387 //
388 // Returns the toolbar type
389 //
GetType()390 int ToolBar::GetType()
391 {
392 return mType;
393 }
394
395 //
396 // Set the toolbar label
397 //
SetLabel(const wxString & label)398 void ToolBar::SetLabel(const wxString & label)
399 {
400 // Probably shouldn't reach this overload, but perhaps virtual function
401 // dispatch will take us here from a pointer to the wxPanel base class
402 mLabel = Verbatim( label );
403 }
404
SetLabel(const TranslatableString & label)405 void ToolBar::SetLabel(const TranslatableString & label)
406 {
407 // Only this overload is publicly accessible when you have a pointer to
408 // Toolbar or a subclass of it
409 mLabel = label;
410 }
411
412 //
413 // Returns whether the toolbar is resizable or not
414 //
IsResizable() const415 bool ToolBar::IsResizable() const
416 {
417 return mResizable;
418 }
419
420 //
421 // Returns the dock state of the toolbar
422 //
IsDocked() const423 bool ToolBar::IsDocked() const
424 {
425 return const_cast<ToolBar*>(this)->GetDock() != nullptr;
426 }
427
428 //
429 // Returns the visibility of the toolbar
430 //
IsVisible() const431 bool ToolBar::IsVisible() const
432 {
433 return mVisible;
434 }
435
SetVisible(bool bVisible)436 void ToolBar::SetVisible( bool bVisible )
437 {
438 mVisible = bVisible;
439 }
440
441 //
442 // Show or hide the toolbar
443 //
Expose(bool show)444 bool ToolBar::Expose( bool show )
445 {
446 bool was = mVisible;
447
448 SetVisible( show );
449
450 if( IsDocked() )
451 {
452 Show( show );
453 if( show )
454 {
455 Refresh();
456 }
457 }
458 else
459 {
460 wxWindow * pParent = GetParent();
461 if( !IsPositioned() && show ){
462 SetPositioned();
463 pParent->CentreOnParent();
464 pParent->Move( pParent->GetPosition() + wxSize( mType*10, mType*10 ));
465 }
466 pParent->Show( show );
467 }
468
469 return was;
470 }
471
472 //
473 // Initialize the toolbar
474 //
Create(wxWindow * parent)475 void ToolBar::Create( wxWindow *parent )
476 {
477 // Save parameters
478 mParent = parent;
479
480 // Create the window and label it
481 wxPanelWrapper::Create( mParent,
482 mType,
483 wxDefaultPosition,
484 wxDefaultSize,
485 wxNO_BORDER | wxTAB_TRAVERSAL,
486 GetTitle() );
487 wxPanelWrapper::SetLabel( GetLabel() );
488
489 // Go do the rest of the creation
490 ReCreateButtons();
491
492 // ToolManager depends on this appearing to be visible for proper dock construction
493 mVisible = true;
494 }
495
SetToDefaultSize()496 void ToolBar::SetToDefaultSize(){
497 wxSize sz;
498 sz.SetHeight( -1 );
499 sz.SetWidth( GetInitialWidth());
500 SetSize( sz );
501 }
502
GetSmartDockedSize()503 wxSize ToolBar::GetSmartDockedSize()
504 {
505 const int tbs = toolbarSingle + toolbarGap;
506 wxSize sz = GetSize();
507 // 46 is the size where we switch from expanded to compact.
508 if( sz.y < 46 )
509 sz.y = tbs-1;
510 else
511 sz.y = 2 * tbs -1;
512 return sz;
513 }
514
515
ReCreateButtons()516 void ToolBar::ReCreateButtons()
517 {
518 wxSize sz3 = GetSize();
519 //wxLogDebug( "x:%i y:%i",sz3.x, sz3.y);
520
521 // SetSizer(NULL) detaches mHSizer and deletes it.
522 // Do not use Detach() here, as that attempts to detach mHSizer from itself!
523 SetSizer( NULL );
524
525 // Get rid of any children we may have
526 DestroyChildren();
527 mGrabber = NULL;
528 mResizer = NULL;
529 SetLayoutDirection(wxLayout_LeftToRight);
530
531 // Refresh the background before populating
532 if (!IsDocked())
533 {
534 GetParent()->Refresh();
535 }
536
537 {
538 // Create the main sizer
539 auto ms = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
540
541 // Create the grabber and add it to the main sizer
542 mGrabber = safenew Grabber(this, mType);
543 ms->Add(mGrabber, 0, wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP | wxRIGHT, 1);
544
545 // Use a box sizer for laying out controls
546 ms->Add((mHSizer = safenew wxBoxSizer(wxHORIZONTAL)), 1, wxEXPAND);
547
548 // Go add all the rest of the gadgets
549 Populate();
550
551 // Add some space for the resize border
552 if (IsResizable())
553 {
554 // Create the resizer and add it to the main sizer
555 mResizer = safenew ToolBarResizer(this);
556 ms->Add(mResizer, 0, wxEXPAND | wxALIGN_TOP | wxLEFT, 1);
557 mResizer->SetToolTip(_("Click and drag to resize toolbar"));
558 }
559
560 // Set dock after possibly creating resizer.
561 // (Re)Establish dock state
562 SetDocked(GetDock(), false);
563
564 // Set the sizer
565 SetSizerAndFit(ms.release());
566 }
567
568 // Recalculate the height to be a multiple of toolbarSingle
569 const int tbs = toolbarSingle + toolbarGap;
570 wxSize sz = GetSize();
571 sz.y = ( ( ( sz.y + tbs -1) / tbs ) * tbs ) - 1;
572
573 // Set the true AND minimum sizes and do final layout
574 if(IsResizable())
575 {
576 // JKC we're going to allow all resizable toolbars to be resized
577 // to 1 unit high, typically 27 pixels.
578 wxSize sz2 = sz;
579 sz2.SetWidth(GetMinToolbarWidth());
580 sz2.y = tbs -1;
581 SetMinSize(sz2);
582
583 // sz2 is now the minimum size.
584 // sz3 is the size we were.
585
586 // We're recreating buttons, and we want to preserve original size.
587 // But not if that makes the size too small.
588
589 // Size at least as big as minimum.
590 if( sz3.y < sz2.y )
591 sz3.y = sz2.y;
592 if( sz3.x < sz2.x )
593 sz3.x = sz2.x;
594 SetSize(sz3);
595 }
596 else
597 {
598 SetInitialSize(sz);
599 }
600 Layout();
601 }
602
603 // The application preferences have changed, so update any elements that may
604 // depend on them.
UpdatePrefs()605 void ToolBar::UpdatePrefs()
606 {
607 #if wxUSE_TOOLTIPS
608 // Change the tooltip of the grabber
609 if ( mGrabber )
610 {
611 mGrabber->SetToolTip( GetTitle() );
612 }
613
614 // Change the tooltip of the resizer
615 if ( mResizer )
616 {
617 mResizer->SetToolTip( _("Click and drag to resize toolbar") );
618 wxSizeEvent e;
619 GetParent()->GetEventHandler()->AddPendingEvent( e );
620 GetParent()->Refresh();
621 }
622 #endif
623
624 return;
625 }
626
627 //
628 // Return the pointer to the ToolBock where this bar lives
629 //
GetDock()630 ToolDock *ToolBar::GetDock()
631 {
632 return dynamic_cast<ToolDock*>(GetParent());
633 }
634
635 //
636 // Toggle the docked/floating state
637 //
SetDocked(ToolDock * dock,bool pushed)638 void ToolBar::SetDocked( ToolDock *dock, bool pushed )
639 {
640 // Remember it
641 // mDock = dock;
642
643 // Change the tooltip of the grabber
644 #if wxUSE_TOOLTIPS
645 mGrabber->SetToolTip( GetTitle() );
646 #endif
647
648 // Set the grabber button state
649 mGrabber->PushButton( pushed );
650
651 if (mResizer)
652 {
653 mResizer->Show(dock != NULL);
654 Layout();
655 }
656 }
657
658 //
659 // Notify parent of changes
660 //
Updated()661 void ToolBar::Updated()
662 {
663 if( IsDocked() )
664 GetDock()->Updated();
665 else
666 // Bug 2120. Changing the choice also changes the size of the toolbar so
667 // we need to update the client size, even if undocked.
668 // If modifying/improving this, remember to test both changing the choice,
669 // and clicking on the choice but not actually changing it.
670 GetParent()->SetClientSize( GetSize() + wxSize( 2,2));
671 //wxCommandEvent e( EVT_TOOLBAR_UPDATED, GetId() );
672 //GetParent()->GetEventHandler()->AddPendingEvent( e );
673 }
674
675 //
676 // Returns a pointer to the main sizer
677 //
GetSizer()678 wxBoxSizer *ToolBar::GetSizer()
679 {
680 return mHSizer;
681 }
682
683 //
684 // Add a window to the main sizer
685 //
Add(wxWindow * window,int proportion,int flag,int border,wxObject * userData)686 void ToolBar::Add( wxWindow *window,
687 int proportion,
688 int flag,
689 int border,
690 wxObject* userData )
691 {
692 mHSizer->Add( window,
693 proportion,
694 flag,
695 border,
696 userData );
697 }
698
699 //
700 // Add a child sizer to the main sizer
701 //
Add(wxSizer * sizer,int proportion,int flag,int border,wxObject * userData)702 void ToolBar::Add( wxSizer *sizer,
703 int proportion,
704 int flag,
705 int border,
706 wxObject* userData )
707 {
708 mHSizer->Add( sizer,
709 proportion,
710 flag,
711 border,
712 userData );
713 }
714
715 //
716 // Add some space to the main sizer
717 //
Add(int width,int height,int proportion,int flag,int border,wxObject * userData)718 void ToolBar::Add( int width,
719 int height,
720 int proportion,
721 int flag,
722 int border,
723 wxObject* userData )
724 {
725 mHSizer->Add( width,
726 height,
727 proportion,
728 flag,
729 border,
730 userData );
731 }
732
733 //
734 // Adds a spacer to the main sizer
735 //
AddSpacer(int size)736 void ToolBar::AddSpacer( int size )
737 {
738 mHSizer->AddSpacer( size );
739 }
740
741 //
742 // Adds a strechable spacer to the main sizer
743 //
AddStretchSpacer(int prop)744 void ToolBar::AddStretchSpacer( int prop )
745 {
746 mHSizer->AddStretchSpacer( prop );
747 }
748
749 //
750 // Detach a window from the main sizer
751 //
Detach(wxWindow * window)752 void ToolBar::Detach( wxWindow *window )
753 {
754 mHSizer->Detach( window );
755 }
756
757 //
758 // Detach a child sizer from the main sizer
759 //
Detach(wxSizer * sizer)760 void ToolBar::Detach( wxSizer *sizer )
761 {
762 mHSizer->Detach( sizer );
763 }
764
MakeMacRecoloredImage(teBmps eBmpOut,teBmps eBmpIn)765 void ToolBar::MakeMacRecoloredImage(teBmps eBmpOut, teBmps eBmpIn )
766 {
767 theTheme.ReplaceImage( eBmpOut, &theTheme.Image( eBmpIn ));
768 }
769
MakeRecoloredImage(teBmps eBmpOut,teBmps eBmpIn)770 void ToolBar::MakeRecoloredImage( teBmps eBmpOut, teBmps eBmpIn )
771 {
772 // Don't recolour the buttons...
773 MakeMacRecoloredImage( eBmpOut, eBmpIn );
774 }
775
MakeButtonBackgroundsLarge()776 void ToolBar:: MakeButtonBackgroundsLarge()
777 {
778
779 bool bUseAqua = false;
780
781 #ifdef EXPERIMENTAL_THEME_PREFS
782 gPrefs->Read( wxT("/GUI/ShowMac"), &bUseAqua, false);
783 #endif
784
785 #ifdef USE_AQUA_THEME
786 bUseAqua = !bUseAqua;
787 #endif
788
789 if( bUseAqua ){
790 MakeMacRecoloredImage( bmpRecoloredUpLarge, bmpMacUpButton );
791 MakeMacRecoloredImage( bmpRecoloredDownLarge, bmpMacDownButton );
792 MakeMacRecoloredImage( bmpRecoloredUpHiliteLarge, bmpMacHiliteUpButton );
793 MakeMacRecoloredImage( bmpRecoloredHiliteLarge, bmpMacHiliteButton );
794 } else {
795 MakeRecoloredImage( bmpRecoloredUpLarge, bmpUpButtonLarge );
796 MakeRecoloredImage( bmpRecoloredDownLarge, bmpDownButtonLarge );
797 MakeRecoloredImage( bmpRecoloredUpHiliteLarge, bmpHiliteUpButtonLarge );
798 MakeRecoloredImage( bmpRecoloredHiliteLarge, bmpHiliteButtonLarge );
799 }
800 }
801
MakeButtonBackgroundsSmall()802 void ToolBar::MakeButtonBackgroundsSmall()
803 {
804
805 bool bUseAqua = false;
806
807 #ifdef EXPERIMENTAL_THEME_PREFS
808 gPrefs->Read( wxT("/GUI/ShowMac"), &bUseAqua, false);
809 #endif
810
811 #ifdef USE_AQUA_THEME
812 bUseAqua = !bUseAqua;
813 #endif
814
815 if( bUseAqua ){
816 MakeMacRecoloredImage( bmpRecoloredUpSmall, bmpMacUpButtonSmall );
817 MakeMacRecoloredImage( bmpRecoloredDownSmall, bmpMacDownButtonSmall );
818 MakeMacRecoloredImage( bmpRecoloredUpHiliteSmall, bmpMacHiliteUpButtonSmall );
819 MakeMacRecoloredImage( bmpRecoloredHiliteSmall, bmpMacHiliteButtonSmall );
820 } else {
821 MakeRecoloredImage( bmpRecoloredUpSmall, bmpUpButtonSmall );
822 MakeRecoloredImage( bmpRecoloredDownSmall, bmpDownButtonSmall );
823 MakeRecoloredImage( bmpRecoloredUpHiliteSmall, bmpHiliteUpButtonSmall );
824 MakeRecoloredImage( bmpRecoloredHiliteSmall, bmpHiliteButtonSmall );
825 }
826 }
827
828 /// Makes a button and its four different state bitmaps
829 /// @param parent Parent window for the button.
830 /// @param eUp Background for when button is Up.
831 /// @param eDown Background for when button is Down.
832 /// @param eHilite Background for when button is Hilit.
833 /// @param eStandardUp Foreground when enabled, up.
834 /// @param eStandardDown Foreground when enabled, down.
835 /// @param eDisabled Foreground when disabled.
836 /// @param id Windows Id.
837 /// @param placement Placement position
838 /// @param processdownevents true iff button handles down events.
839 /// @param size Size of the background.
MakeButton(wxWindow * parent,teBmps eUp,teBmps eDown,teBmps eHilite,teBmps eDownHi,teBmps eStandardUp,teBmps eStandardDown,teBmps eDisabled,wxWindowID id,wxPoint placement,bool processdownevents,wxSize size)840 AButton * ToolBar::MakeButton(wxWindow *parent,
841 teBmps eUp,
842 teBmps eDown,
843 teBmps eHilite,
844 teBmps eDownHi,
845 teBmps eStandardUp,
846 teBmps eStandardDown,
847 teBmps eDisabled,
848 wxWindowID id,
849 wxPoint placement,
850 bool processdownevents,
851 wxSize size)
852 {
853 // wxMax to cater for case of image being bigger than the button.
854 int xoff = wxMax( 0, (size.GetWidth() - theTheme.Image(eStandardUp).GetWidth())/2);
855 int yoff = wxMax( 0, (size.GetHeight() - theTheme.Image(eStandardUp).GetHeight())/2);
856
857 typedef std::unique_ptr<wxImage> wxImagePtr;
858 wxImagePtr up2 (OverlayImage(eUp, eStandardUp, xoff, yoff));
859 wxImagePtr hilite2 (OverlayImage(eHilite, eStandardUp, xoff, yoff));
860 wxImagePtr down2 (OverlayImage(eDown, eStandardDown, xoff + 1, yoff + 1));
861 wxImagePtr downHi2 (OverlayImage(eDownHi, eStandardDown, xoff + 1, yoff + 1));
862 wxImagePtr disable2 (OverlayImage(eUp, eDisabled, xoff, yoff));
863
864 wxASSERT(parent); // to justify safenew
865 AButton * button =
866 safenew AButton(parent, id, placement, size, *up2, *hilite2, *down2, *downHi2,
867 *disable2, processdownevents);
868
869 return button;
870 }
871
872 //static
MakeAlternateImages(AButton & button,int idx,teBmps eUp,teBmps eDown,teBmps eHilite,teBmps eDownHi,teBmps eStandardUp,teBmps eStandardDown,teBmps eDisabled,wxSize size)873 void ToolBar::MakeAlternateImages(AButton &button, int idx,
874 teBmps eUp,
875 teBmps eDown,
876 teBmps eHilite,
877 teBmps eDownHi,
878 teBmps eStandardUp,
879 teBmps eStandardDown,
880 teBmps eDisabled,
881 wxSize size)
882 {
883 // wxMax to cater for case of image being bigger than the button.
884 int xoff = wxMax( 0, (size.GetWidth() - theTheme.Image(eStandardUp).GetWidth())/2);
885 int yoff = wxMax( 0, (size.GetHeight() - theTheme.Image(eStandardUp).GetHeight())/2);
886
887 typedef std::unique_ptr<wxImage> wxImagePtr;
888 wxImagePtr up (OverlayImage(eUp, eStandardUp, xoff, yoff));
889 wxImagePtr hilite (OverlayImage(eHilite, eStandardUp, xoff, yoff));
890 wxImagePtr down (OverlayImage(eDown, eStandardDown, xoff + 1, yoff + 1));
891 wxImagePtr downHi (OverlayImage(eDownHi, eStandardDown, xoff + 1, yoff + 1));
892 wxImagePtr disable (OverlayImage(eUp, eDisabled, xoff, yoff));
893
894 button.SetAlternateImages(idx, *up, *hilite, *down, *downHi, *disable);
895 }
896
SetButtonToolTip(AudacityProject & theProject,AButton & button,const ComponentInterfaceSymbol commands[],size_t nCommands)897 void ToolBar::SetButtonToolTip
898 (AudacityProject &theProject,
899 AButton &button, const ComponentInterfaceSymbol commands[], size_t nCommands)
900 {
901 TranslatableString result;
902 const auto project = &theProject;
903 const auto commandManager =
904 project ? &CommandManager::Get( *project ) : nullptr;
905 if (commandManager)
906 result =
907 commandManager->DescribeCommandsAndShortcuts(commands, nCommands);
908 button.SetToolTip( result );
909 }
910
911 //
912 // This changes the state a button (from up to down or vice versa)
913 //
SetButton(bool down,AButton * button)914 void ToolBar::SetButton( bool down, AButton * button )
915 {
916 if( down )
917 {
918 button->PushDown();
919 }
920 else
921 {
922 button->PopUp();
923 }
924 }
925
926 //
927 // Handle background erasure
928 //
OnErase(wxEraseEvent & WXUNUSED (event))929 void ToolBar::OnErase( wxEraseEvent & WXUNUSED(event) )
930 {
931 // Ignore it to prevent flashing
932 }
933
934 //
935 // This draws the background of a toolbar
936 //
OnPaint(wxPaintEvent & WXUNUSED (event))937 void ToolBar::OnPaint( wxPaintEvent & WXUNUSED(event) )
938 {
939 wxPaintDC dc( this );
940
941 // Themed background colour.
942 dc.SetBackground( wxBrush( theTheme.Colour( clrMedium ) ) );
943 dc.Clear();
944
945 Repaint( &dc );
946 }
947
OnMouseEvents(wxMouseEvent & event)948 void ToolBar::OnMouseEvents(wxMouseEvent &event)
949 {
950 // Do this hack so scrubber can detect mouse drags anywhere
951 event.ResumePropagation(wxEVENT_PROPAGATE_MAX);
952 event.Skip();
953 }
954
GetResizeGrabberWidth()955 int ToolBar::GetResizeGrabberWidth()
956 {
957 return RWIDTH;
958 }
959
960 namespace {
961
GetFunctions()962 RegisteredToolbarFactory::Functions &GetFunctions()
963 {
964 static RegisteredToolbarFactory::Functions factories( ToolBarCount );
965 return factories;
966 }
967
968 }
969
RegisteredToolbarFactory(int id,const Function & function)970 RegisteredToolbarFactory::RegisteredToolbarFactory(
971 int id, const Function &function)
972 {
973 wxASSERT( id >= 0 && id < ToolBarCount );
974 GetFunctions()[ id ] = function;
975 }
976
GetFactories()977 auto RegisteredToolbarFactory::GetFactories() -> const Functions&
978 {
979 return GetFunctions();
980 }
981