Audacity 3.2.0
ASlider.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 ASlider.cpp
6
7 Dominic Mazzoni
8
9*******************************************************************//*******************************************************************/
30
31
32
33#include "ASlider.h"
34
35#include <math.h>
36
37#include <wx/setup.h> // for wxUSE_* macros
38#include <wx/defs.h>
39#include <wx/dcbuffer.h>
40#include <wx/frame.h>
41#include <wx/graphics.h>
42#include <wx/panel.h>
43#include <wx/tooltip.h>
44#include <wx/debug.h>
45#include <wx/textctrl.h>
46#include <wx/valtext.h>
47#include <wx/statline.h>
48#include <wx/settings.h>
49#include <wx/popupwin.h>
50#include <wx/window.h>
51
52#include "AColor.h"
53#include "ImageManipulation.h"
54#include "Project.h"
55#include "ProjectStatus.h"
56#include "../ProjectWindowBase.h"
57#include "ShuttleGui.h"
58#include "Theme.h"
59#include "valnum.h"
60
61#include "AllThemeResources.h"
62
63#if wxUSE_ACCESSIBILITY
64#include "WindowAccessible.h"
65
66class AUDACITY_DLL_API ASliderAx final : public WindowAccessible
67{
68public:
69 ASliderAx(wxWindow * window);
70
71 virtual ~ ASliderAx();
72
73 // Retrieves the address of an IDispatch interface for the specified child.
74 // All objects must support this property.
75 wxAccStatus GetChild(int childId, wxAccessible** child) override;
76
77 // Gets the number of children.
78 wxAccStatus GetChildCount(int* childCount) override;
79
80 // Gets the default action for this object (0) or > 0 (the action for a child).
81 // Return wxACC_OK even if there is no action. actionName is the action, or the empty
82 // string if there is no action.
83 // The retrieved string describes the action that is performed on an object,
84 // not what the object does as a result. For example, a toolbar button that prints
85 // a document has a default action of "Press" rather than "Prints the current document."
86 wxAccStatus GetDefaultAction(int childId, wxString *actionName) override;
87
88 // Returns the description for this object or a child.
89 wxAccStatus GetDescription(int childId, wxString *description) override;
90
91 // Gets the window with the keyboard focus.
92 // If childId is 0 and child is NULL, no object in
93 // this subhierarchy has the focus.
94 // If this object has the focus, child should be 'this'.
95 wxAccStatus GetFocus(int *childId, wxAccessible **child) override;
96
97 // Returns help text for this object or a child, similar to tooltip text.
98 wxAccStatus GetHelpText(int childId, wxString *helpText) override;
99
100 // Returns the keyboard shortcut for this object or child.
101 // Return e.g. ALT+K
102 wxAccStatus GetKeyboardShortcut(int childId, wxString *shortcut) override;
103
104 // Returns the rectangle for this object (id = 0) or a child element (id > 0).
105 // rect is in screen coordinates.
106 wxAccStatus GetLocation(wxRect& rect, int elementId) override;
107
108 // Gets the name of the specified object.
109 wxAccStatus GetName(int childId, wxString *name) override;
110
111 // Returns a role constant.
112 wxAccStatus GetRole(int childId, wxAccRole *role) override;
113
114 // Gets a variant representing the selected children
115 // of this object.
116 // Acceptable values:
117 // - a null variant (IsNull() returns TRUE)
118 // - a list variant (GetType() == wxT("list"))
119 // - an integer representing the selected child element,
120 // or 0 if this object is selected (GetType() == wxT("long"))
121 // - a "void*" pointer to a wxAccessible child object
122 wxAccStatus GetSelections(wxVariant *selections) override;
123
124 // Returns a state constant.
125 wxAccStatus GetState(int childId, long* state) override;
126
127 // Returns a localized string representing the value for the object
128 // or child.
129 wxAccStatus GetValue(int childId, wxString* strValue) override;
130
131};
132
133#endif // wxUSE_ACCESSIBILITY
134#if defined __WXMSW__
135const int sliderFontSize = 10;
136#else
137const int sliderFontSize = 12;
138#endif
139
140#define OPTIONAL_SLIDER_TICKS
141
142//
143// TipWindow
144//
145
146class TipWindow final : public wxFrame
147{
148 public:
149 TipWindow(wxWindow *parent, const TranslatableStrings & labels);
150 virtual ~TipWindow() {}
151
152 wxSize GetSize() const;
153 void SetPos(const wxPoint & pos);
154 void SetLabel(const TranslatableString & label);
155
156private:
157 void OnPaint(wxPaintEvent & event);
158
159private:
163 wxFont mFont;
164
165 DECLARE_EVENT_TABLE()
166};
167
168BEGIN_EVENT_TABLE(TipWindow, wxFrame)
169 EVT_PAINT(TipWindow::OnPaint)
171
172TipWindow::TipWindow(wxWindow *parent, const TranslatableStrings & labels)
173: wxFrame(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
174 wxFRAME_SHAPED | wxNO_BORDER | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT )
175{
176 SetBackgroundStyle(wxBG_STYLE_PAINT);
177 SetBackgroundColour(wxTransparentColour);
178
179 mFont.SetPointSize(sliderFontSize);
180 mFont.SetFamily(wxFONTFAMILY_SWISS);
181 mFont.SetStyle(wxFONTSTYLE_NORMAL);
182 mFont.SetWeight(wxFONTWEIGHT_NORMAL);
183
184 mWidth = mHeight = 0;
185 for ( const auto &label : labels ) {
186 int width, height;
187 GetTextExtent(label.Translation(), &width, &height, NULL, NULL, &mFont);
188 mWidth = std::max( mWidth, width );
189 mHeight = std::max( mHeight, height );
190 }
191
192 // Pad to allow for curved corners
193 mWidth += 8;
194 mHeight += 8;
195
196#if defined(__WXMAC__)
197 // Use a bitmap region to set the shape since just adding an unfilled path
198 // will make the window transparent
199 wxBitmap shape(mWidth, mHeight);
200 wxMemoryDC dc(shape);
201
202 dc.SetPen(*wxBLACK_PEN);
203 dc.SetBrush(*wxBLACK_BRUSH);
204 dc.DrawRoundedRectangle(0, 0, mWidth, mHeight, 5);
205 dc.SelectObject(wxNullBitmap);
206
207 SetShape(wxRegion(shape, *wxWHITE));
208#else
209 wxGraphicsPath path = wxGraphicsRenderer::GetDefaultRenderer()->CreatePath();
210 path.AddRoundedRectangle(0, 0, mWidth, mHeight, 5);
211 SetShape(path);
212#endif
213}
214
215wxSize TipWindow::GetSize() const
216{
217 return wxSize(mWidth, mHeight);
218}
219
220void TipWindow::SetPos(const wxPoint & pos)
221{
222 SetSize(pos.x, pos.y, mWidth, mHeight);
223}
224
226{
227 mLabel = label;
228}
229
230void TipWindow::OnPaint(wxPaintEvent & WXUNUSED(event))
231{
232 wxAutoBufferedPaintDC dc(this);
233
234 dc.SetPen(*wxBLACK_PEN);
235 dc.SetBrush(AColor::tooltipBrush);
236 dc.DrawRoundedRectangle(0, 0, mWidth, mHeight, 5);
237
238 dc.SetFont(mFont);
239 dc.SetTextForeground(AColor::tooltipPen.GetColour());
240
241 int textWidth, textHeight;
242 const auto visibleLabel = mLabel.Translation();
243 dc.GetTextExtent(visibleLabel, &textWidth, &textHeight);
244 dc.DrawText(visibleLabel, (mWidth - textWidth) / 2, (mHeight - textHeight) / 2);
245}
246
247//
248// SliderDialog
249//
250
251BEGIN_EVENT_TABLE(SliderDialog, wxDialogWrapper)
252 EVT_TEXT( wxID_ANY, SliderDialog::OnTextChange )
253 EVT_SLIDER(wxID_ANY,SliderDialog::OnSlider)
255
256SliderDialog::SliderDialog(wxWindow * parent, wxWindowID id,
258 wxPoint position,
259 wxSize size,
260 int style,
261 float value,
262 float line,
263 float page,
264 LWSlider * pSource):
265 wxDialogWrapper(parent,id,title,position),
266 mStyle(style)
267{
268 SetName();
269 mpOrigin = pSource;
270 mValue = mpOrigin->Get(false);
271
272 auto prec = 2;
273 auto trailing = NumValidatorStyle::TWO_TRAILING_ZEROES;
274 if (style == DB_SLIDER)
275 {
276 prec = 1;
277 trailing = NumValidatorStyle::ONE_TRAILING_ZERO;
278 }
279
280 ShuttleGui S(this, eIsCreating);
281
282 S.StartVerticalLay();
283 {
284 if (style == PAN_SLIDER)
285 {
286 mTextCtrl = S
287 .Validator<IntegerValidator<float>>(
288 &mValue, NumValidatorStyle::DEFAULT, -100.0, 100.0)
289 .AddTextBox({}, wxEmptyString, 15);
290 }
291 else if (style == VEL_SLIDER)
292 {
293 mTextCtrl = S
294 .Validator<IntegerValidator<float>>(
295 &mValue, NumValidatorStyle::DEFAULT, -50.0, 50.0)
296 .AddTextBox({}, wxEmptyString, 15);
297 }
298 else if(style == PERCENT_SLIDER)
299 {
300 mTextCtrl = S
301 .Validator<IntegerValidator<float>>(
302 &mValue, NumValidatorStyle::DEFAULT, 0.0, 100.0)
303 .AddTextBox({}, wxEmptyString, 15);
304 }
305 else
306 {
307 mTextCtrl = S
308 .Validator<FloatingPointValidator<float>>(
309 prec, &mValue, trailing, mpOrigin->GetMinValue(), mpOrigin->GetMaxValue())
310 .AddTextBox({}, wxEmptyString, 15);
311 }
312 mSlider = safenew ASlider(S.GetParent(),
313 wxID_ANY,
314 title,
315 wxDefaultPosition,
316 size,
318 .Style( style ).Line( line ).Page( page ).Popup( false) );
319 S.Position(wxEXPAND)
320 .AddWindow(mSlider);
321 }
322 S.EndVerticalLay();
323
324 S.AddStandardButtons(eOkButton | eCancelButton);
325
326 Fit();
327
328 mSlider->Set(value);
329}
330
332{
333}
334
336{
337 float value = mSlider->Get(false);
339 ? value * 100.0
340 : value;
341 mTextCtrl->GetValidator()->TransferToWindow();
342 mTextCtrl->SetSelection(-1, -1);
343 if (mpOrigin) {
344 mpOrigin->Set(value);
345 mpOrigin->SendUpdate(value);
346 }
347
348 return true;
349}
350
352{
353 if (mTextCtrl->GetValidator()->TransferFromWindow())
354 {
355 float value = mValue;
356 if (mStyle == DB_SLIDER)
357 value = DB_TO_LINEAR(value);
358 else if (mStyle == PAN_SLIDER || mStyle == PERCENT_SLIDER)
359 value /= 100.0;
360 mSlider->Set(value);
361 if (mpOrigin) {
362 mpOrigin->Set(value);
363 mpOrigin->SendUpdate(value);
364 }
365 }
366
367 return true;
368}
369
370void SliderDialog::OnSlider(wxCommandEvent & event)
371{
373 event.Skip(false);
374}
375
376void SliderDialog::OnTextChange(wxCommandEvent & event)
377{
378 if (mTextCtrl->GetValidator()->TransferFromWindow())
379 {
381 }
382 event.Skip(false);
383}
384
386{
387 return mSlider->Get(false);
388}
389
390//
391// LWSlider
392//
393
394// Define the thumb outline
395static const wxPoint2DDouble outer[] =
396{
397 wxPoint2DDouble( 2, 0 ),
398 wxPoint2DDouble( 8, 0 ),
399 wxPoint2DDouble( 10, 2 ),
400 wxPoint2DDouble( 10, 8 ),
401 wxPoint2DDouble( 5, 13 ),
402 wxPoint2DDouble( 0, 8 ),
403 wxPoint2DDouble( 0, 2 ),
404 wxPoint2DDouble( 2, 0 )
405};
406
407// Define the left and top interior components when enabled
408static const wxPoint2DDouble enabledLeftBegin[] =
409{
410 wxPoint2DDouble( 2, 1 ),
411 wxPoint2DDouble( 1, 2 ),
412 wxPoint2DDouble( 1, 8 ),
413 wxPoint2DDouble( 4, 4 ),
414 wxPoint2DDouble( 4, 7 )
415};
416static const wxPoint2DDouble enabledLeftEnd[] =
417{
418 wxPoint2DDouble( 8, 1 ),
419 wxPoint2DDouble( 1, 8 ),
420 wxPoint2DDouble( 5, 12 ),
421 wxPoint2DDouble( 6, 4 ),
422 wxPoint2DDouble( 6, 7 )
423};
424
425// Define right and bottom interior components when enabled
426static const wxPoint2DDouble enabledRightBegin[] =
427{
428 wxPoint2DDouble( 9, 2 ),
429 wxPoint2DDouble( 9, 8 ),
430 wxPoint2DDouble( 4, 5 ),
431 wxPoint2DDouble( 4, 8 ),
432};
433static const wxPoint2DDouble enabledRightEnd[] =
434{
435 wxPoint2DDouble( 9, 8 ),
436 wxPoint2DDouble( 6, 11 ),
437 wxPoint2DDouble( 6, 5 ),
438 wxPoint2DDouble( 6, 8 )
439};
440
441// Define the interior stripes when disabled
442static const wxPoint2DDouble disabledStripesBegin[] =
443{
444 wxPoint2DDouble( 3, 2 ),
445 wxPoint2DDouble( 5, 2 ),
446 wxPoint2DDouble( 7, 2 ),
447 wxPoint2DDouble( 2, 3 ),
448 wxPoint2DDouble( 2, 5 ),
449 wxPoint2DDouble( 2, 7 ),
450};
451static const wxPoint2DDouble disabledStripesEnd[] =
452{
453 wxPoint2DDouble( 8, 7 ),
454 wxPoint2DDouble( 8, 5 ),
455 wxPoint2DDouble( 8, 3 ),
456 wxPoint2DDouble( 7, 8 ),
457 wxPoint2DDouble( 6, 9 ),
458 wxPoint2DDouble( 5, 10 ),
459};
460
461// Define the right and bottom interior components when disabled
462static const wxPoint2DDouble disabledRightBegin[] =
463{
464 wxPoint2DDouble( 9, 2 ),
465 wxPoint2DDouble( 9, 8 ),
466};
467static const wxPoint2DDouble disabledRightEnd[] =
468{
469 wxPoint2DDouble( 9, 8 ),
470 wxPoint2DDouble( 6, 11 ),
471};
472
473// Construct customizable slider
474LWSlider::LWSlider(wxWindow * parent,
476 const wxPoint &pos,
477 const wxSize &size,
478 float minValue,
479 float maxValue,
480 float stepValue,
481 bool canUseShift,
482 int style,
483 bool showlabels /* = true */,
484 bool drawticks /* = true */,
485 bool drawtrack /* = true */,
486 bool alwayshidetip /* = false */,
487 bool heavyweight /* = false */,
488 bool popup /* = true */,
489 int orientation /* = wxHORIZONTAL */) // wxHORIZONTAL or wxVERTICAL. wxVERTICAL is currently only for DB_SLIDER.
490{
491 Init(parent, name, pos, size, minValue, maxValue, stepValue,
492 canUseShift, style, showlabels, drawticks, drawtrack,
493 alwayshidetip, heavyweight, popup, 1.0, orientation);
494}
495
496// Construct predefined slider
497LWSlider::LWSlider(wxWindow *parent,
499 const wxPoint &pos,
500 const wxSize &size,
501 int style,
502 bool showlabels /* = true */,
503 bool drawticks /* = true */,
504 bool drawtrack /* = true */,
505 bool alwayshidetip /* = false */,
506 bool heavyweight /* = false */,
507 bool popup /* = true */,
508 int orientation /* = wxHORIZONTAL */) // wxHORIZONTAL or wxVERTICAL. wxVERTICAL is currently only for DB_SLIDER.
509{
510 wxString leftLabel, rightLabel;
511
512 float minValue, maxValue, stepValue;
513 float speed = 1.0;
514
515 switch(style)
516 {
517 case PAN_SLIDER:
518 minValue = -1.0f;
519 maxValue = +1.0f;
520 stepValue = 0.1f;
521 orientation = wxHORIZONTAL; //v Vertical PAN_SLIDER currently not handled, forced to horizontal.
522 break;
523 case DB_SLIDER:
524 minValue = -36.0f;
525 //if (orientation == wxHORIZONTAL)
526 maxValue = 36.0f;
527 //else
528 //maxValue = 36.0f; // for MixerBoard //v Previously was 6dB for MixerBoard, but identical for now.
529 stepValue = 1.0f;
530 speed = 0.5;
531 break;
532 case FRAC_SLIDER:
533 case PERCENT_SLIDER:
534 minValue = 0.0f;
535 maxValue = 1.0f;
536 stepValue = STEP_CONTINUOUS;
537 break;
538 case SPEED_SLIDER:
539 minValue = 0.01f;
540 maxValue = 3.0f;
541 stepValue = STEP_CONTINUOUS;
542 break;
543#ifdef EXPERIMENTAL_MIDI_OUT
544 case VEL_SLIDER:
545 minValue = VEL_MIN;
546 maxValue = VEL_MAX;
547 stepValue = 1.0f;
548 speed = 0.5;
549 break;
550#endif
551 default:
552 minValue = 0.0f;
553 maxValue = 1.0f;
554 stepValue = 0.0f;
555 wxASSERT(false); // undefined style
556 }
557
558 Init(parent, name, pos, size, minValue, maxValue, stepValue,
559 true, style, showlabels, drawticks, drawtrack, alwayshidetip,
560 heavyweight, popup, speed, orientation);
561}
562
563void LWSlider::Init(wxWindow * parent,
565 const wxPoint &pos,
566 const wxSize &size,
567 float minValue,
568 float maxValue,
569 float stepValue,
570 bool canUseShift,
571 int style,
572 bool showlabels,
573 bool drawticks,
574 bool drawtrack,
575 bool alwayshidetip,
576 bool heavyweight,
577 bool popup,
578 float speed,
579 int orientation /* = wxHORIZONTAL */) // wxHORIZONTAL or wxVERTICAL. wxVERTICAL is currently only for DB_SLIDER.
580{
581 mEnabled = true;
582 mName = name;
583 mStyle = style;
584 mOrientation = orientation;
585 mIsDragging = false;
586 mParent = parent;
587 mShowLabels = showlabels;
588 mDrawTicks = drawticks;
589 mDrawTrack = drawtrack;
590 mAlwaysHideTip = alwayshidetip;
591 mHW = heavyweight;
592 mPopup = popup;
593 mSpeed = speed;
594 mID = wxID_ANY;
595 mMinValue = minValue;
596 mMaxValue = maxValue;
597 mStepValue = stepValue;
598 mCanUseShift = canUseShift;
599 mCurrentValue = 0.0f;
600 mDefaultValue = 0.0f;
601 mDefaultShortcut = false;
602 mBitmap = nullptr;
603 mThumbBitmap = nullptr;
604 mThumbBitmapHilited = nullptr;
605 mScrollLine = 1.0f;
606 mScrollPage = 5.0f;
607
609
610 Move(pos);
611
612 CreatePopWin();
613}
614
616{
617}
618
619wxWindowID LWSlider::GetId()
620{
621 return mID;
622}
623
624void LWSlider::SetId(wxWindowID id)
625{
626 mID = id;
627}
628
630{
631 mName = name;
632 if(mTipPanel)
633 {
634 mTipPanel->Destroy();
635 mTipPanel = nullptr;
636 }
637 CreatePopWin();
638}
639
641{
642 SetDefaultShortcut(true);
643 mDefaultValue = value;
644}
645
647{
648 mDefaultShortcut = value;
649}
650
651void LWSlider::GetScroll(float & line, float & page)
652{
653 line = mScrollLine;
654 page = mScrollPage;
655}
656
657void LWSlider::SetScroll(float line, float page)
658{
659 mScrollLine = line;
660 mScrollPage = page;
661}
662
663void LWSlider::Move(const wxPoint &newpos)
664{
665 mLeft = newpos.x;
666 mTop = newpos.y;
667}
668
669void LWSlider::AdjustSize(const wxSize & sz)
670{
671 mWidth = sz.GetWidth();
672 mHeight = sz.GetHeight();
673
674 if( mBitmap ){
675 mBitmap.reset();
676 }
677 mThumbWidth = 11;
678 mThumbHeight = 20;
679
680 if (mShowLabels || mDrawTicks)
681 {
682 if (mOrientation == wxHORIZONTAL)
683 {
684 mCenterY = mHeight - 9;
685 }
686 else
687 {
688 mCenterX = mWidth - 9;
689 }
690 }
691 else
692 {
693 if (mOrientation == wxHORIZONTAL)
694 {
695 mCenterY = mHeight / 2;
696 }
697 else
698 {
699 mCenterX = mWidth / 2;
700 }
701 }
702
703 if (mOrientation == wxHORIZONTAL)
704 {
706 mRightX = mWidth - mThumbWidth/2 - 1;
708 }
709 else
710 {
711 mTopY = mThumbWidth/2;
712 mBottomY = mHeight - mThumbWidth/2 - 1;
714 }
715
716 Refresh();
717}
718
719void LWSlider::OnPaint(wxDC &dc, bool highlight)
720{
721 // The dc will be a paint DC
723 {
724 DrawToBitmap(dc);
725 }
726
727 //thumbPos should be in pixels
728 int thumbPos = ValueToPosition(mCurrentValue);
729 int thumbOrtho; // position in axis orthogonal to mOrientation
730 if (mOrientation == wxHORIZONTAL){
731 thumbOrtho = mCenterY - (mThumbHeight/2);
732 thumbPos += 1-mThumbWidth/2;
733 }
734 else{
735 thumbOrtho = mCenterX - (mThumbWidth/2);
736 thumbPos += 8-mThumbHeight/2;
737 }
738
739 // Draw the background.
740 // If we are lightweight, this has already been done for us.
741 if( mHW ){
742 dc.SetBackground( *wxTRANSPARENT_BRUSH );
743 dc.Clear();
744 }
745
746 dc.DrawBitmap(*mBitmap, mLeft, mTop, true);
747 const auto &thumbBitmap =
748 highlight ? *mThumbBitmapHilited : *mThumbBitmap;
749 if (mOrientation == wxHORIZONTAL)
750 {
751 dc.DrawBitmap(thumbBitmap, mLeft+thumbPos, mTop+thumbOrtho, true);
752 }
753 else
754 {
755 // TODO: Don't use pixel-count hack in positioning.
756 dc.DrawBitmap(thumbBitmap, mLeft+thumbOrtho-5, mTop+thumbPos, true);
757 }
758
759 if (mTipPanel)
760 {
761 mTipPanel->Update();
762 }
763}
764
765void LWSlider::OnSize( wxSizeEvent & event )
766{
767 AdjustSize(event.GetSize());
768
769 Refresh();
770}
771
772// This function only uses the paintDC to determine what kind of bitmap
773// to draw to and nothing else. It does not draw to the paintDC.
774void LWSlider::DrawToBitmap(wxDC & paintDC)
775{
776 // Get correctly oriented thumb.
777 if (mOrientation == wxVERTICAL){
778 mThumbBitmap = std::make_unique<wxBitmap>(wxBitmap( theTheme.Bitmap( bmpSliderThumbRotated )));
779 mThumbBitmapHilited = std::make_unique<wxBitmap>(wxBitmap( theTheme.Bitmap( bmpSliderThumbRotatedHilited )));
780 }
781 else {
782 mThumbBitmap = std::make_unique<wxBitmap>(wxBitmap( theTheme.Bitmap( bmpSliderThumb )));
783 mThumbBitmapHilited = std::make_unique<wxBitmap>(wxBitmap( theTheme.Bitmap( bmpSliderThumbHilited )));
784 }
785
786 // Now the background bitmap
787 mBitmap = std::make_unique<wxBitmap>();
788 mBitmap->Create(mWidth, mHeight, paintDC);
789
790#if defined(__WXMAC__)
791 mBitmap->UseAlpha();
792#endif
793
794 // Set up the memory DC
795 // We draw to it, not the paintDC.
796 wxMemoryDC dc;
797 dc.SelectObject(*mBitmap);
798
799 dc.SetBackground(wxBrush(mParent->GetBackgroundColour()));
800 dc.Clear();
801
802 // Draw the line along which the thumb moves.
803 AColor::UseThemeColour(&dc, clrSliderMain );
804
805 if (mDrawTrack)
806 {
807 if (mOrientation == wxHORIZONTAL)
808 {
811 }
812 else
813 {
816 }
817 }
818
819 if (mShowLabels)
820 {
821 // Draw +/- or L/R first. We need to draw these before the tick marks.
822 if (mStyle == PAN_SLIDER)
823 {
824 //VJ Vertical PAN_SLIDER currently not handled, forced to horizontal.
825
826 // sliderFontSize is for the tooltip.
827 // we need something smaller here...
828 wxFont labelFont(7, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
829 dc.SetFont(labelFont);
830
831 // Color
832 dc.SetTextForeground(theTheme.Colour(clrTrackPanelText));
833
834 /* i18n-hint: One-letter abbreviation for Left, in the Pan slider */
835 dc.DrawText(_("L"), mLeftX, 0);
836
837 /* i18n-hint: One-letter abbreviation for Right, in the Pan slider */
838 dc.DrawText(_("R"), mRightX - dc.GetTextExtent(_("R")).GetWidth(), 0);
839 }
840 else
841 {
842 // draw the '-' and the '+'
843 // These are drawn with lines, rather tha nwith a font.
844 AColor::UseThemeColour(&dc, clrTrackPanelText);
845
846 if (mOrientation == wxHORIZONTAL)
847 {
849 AColor::Line(dc, mRightX-5, mCenterY-10, mRightX-1, mCenterY-10);
851 }
852 else
853 {
854 // Vertical DB_SLIDER is for gain slider in MixerBoard.
855 // We use a Ruler instead of marks & ticks.
856 // Draw '+' and '-' only for other vertical sliders.
857 if (mStyle != DB_SLIDER)
858 {
860 AColor::Line(dc, mCenterX-12, mTopY+3, mCenterX-8, mTopY+3);
861 AColor::Line(dc, mCenterX-10, mTopY, mCenterX-10, mTopY+5);
862 }
863 }
864 }
865 }
866
867 // Use special colour to indicate no ticks.
868 wxColour TickColour = theTheme.Colour( clrSliderLight );
869 bool bTicks = TickColour != wxColour(60,60,60);
870
871 if( mDrawTicks && bTicks ) {
872 // tick marks
873 int divs = 10;
874 double upp;
875 if (mOrientation == wxHORIZONTAL)
876 {
877 // Bug #2446 - A bit of a hack, but it should suffice.
878 divs = (mWidth - 1) / 10;
879 upp = divs / (double)(mWidthX-1);
880 }
881 else
882 {
883 if (mStyle == DB_SLIDER)
884 divs = mMaxValue - mMinValue + 1;
885 upp = divs / (double)(mHeightY-1);
886 }
887#ifdef OPTIONAL_SLIDER_TICKS
888 double d = 0.0;
889 int int_d = -1;
890 const int kMax = (mOrientation == wxHORIZONTAL) ? mWidthX : mHeightY;
891 for(int p = 0; p <= kMax; p++)
892 {
893 if (((int)d) > int_d)
894 {
895 int_d = (int)d;
896 int tickLength = ((int_d == 0) || (int_d == divs)) ? 5: 3; // longer ticks at extremes
897 AColor::UseThemeColour(&dc, clrSliderLight );
898
899 if (mOrientation == wxHORIZONTAL)
900 {
901 AColor::Line(dc, mLeftX+p, mCenterY-tickLength, mLeftX+p, mCenterY-1); // ticks above
902 }
903 else
904 {
905 AColor::Line(dc, mCenterX-tickLength, mTopY+p, mCenterX-1, mTopY+p); // ticks at left
906 }
907
908 AColor::UseThemeColour(&dc, clrSliderDark );
909
910 if (mOrientation == wxHORIZONTAL)
911 {
912 AColor::Line(dc, mLeftX+p+1, mCenterY-tickLength+1, mLeftX+p+1, mCenterY-1); // ticks above
913 }
914 else
915 {
916 AColor::Line(dc, mCenterX-tickLength+1, mTopY+p+1, mCenterX-1, mTopY+p+1); // ticks at left
917 }
918 }
919 d += upp;
920 }
921#endif
922 }
923
924 dc.SelectObject(wxNullBitmap);
925
926 // safenew, because SetMask takes ownership
927 // We always mask. If we are HeavyWeight, the ASlider draws the
928 // background.
929 if( !mHW )
930 {
931 mBitmap->SetMask(safenew wxMask(*mBitmap, dc.GetBackground().GetColour()));
932 }
933}
934
936{
937 mTipTemplate = tip;
938}
939
940void LWSlider::ShowTip(bool show)
941{
942 if(!mTipPanel)
943 return;
944
945 if(show)
946 {
947 mTipPanel->SetLabel(GetTip(mCurrentValue));
949 mTipPanel->ShowWithoutActivating();
950 }
951 else
952 mTipPanel->Hide();
953}
954
956{
957 if(mTipPanel || mAlwaysHideTip || mParent == nullptr)
958 return;
959
961 mTipPanel->Hide();
962}
963
965{
966 if (mTipPanel)
967 {
968 wxSize sz = mTipPanel->GetSize();
969 wxPoint pt;
970
971 if (mOrientation == wxHORIZONTAL)
972 {
973 pt.x = mLeft + ((mWidth - sz.x) / 2);
974 pt.y = mTop + mHeight + 1;
975 }
976 else
977 {
978 pt.x = mLeft + mWidth + 1;
979 pt.y = mTop + ((mHeight - sz.y) / 2);
980 }
981
982 mTipPanel->SetPos(mParent->ClientToScreen(pt));
983 }
984}
985
987{
988 if (!mTipPanel)
989 {
990 return;
991 }
992
993 mTipPanel->SetLabel(GetTip(mCurrentValue));
994 mTipPanel->Refresh();
995}
996
998{
1000
1001 if (mTipTemplate.empty())
1002 {
1004
1005 switch(mStyle)
1006 {
1007 case FRAC_SLIDER:
1008 val = Verbatim("%.2f").Format( value );
1009 break;
1010 case PERCENT_SLIDER:
1011 val = Verbatim("%.0f%%").Format(value * 100.0f);
1012 break;
1013
1014 case DB_SLIDER:
1015 /* i18n-hint dB abbreviates decibels */
1016 val = XO("%+.1f dB").Format( value );
1017 break;
1018
1019 case PAN_SLIDER:
1020 if (value == 0.0)
1021 {
1022 val = XO("Center");
1023 }
1024 else
1025 {
1026 const auto v = 100.0f * fabsf(value);
1027 if (value < 0.0)
1028 /* i18n-hint: Stereo pan setting */
1029 val = XO("%.0f%% Left").Format( v );
1030 else
1031 /* i18n-hint: Stereo pan setting */
1032 val = XO("%.0f%% Right").Format( v );
1033 }
1034 break;
1035
1036 case SPEED_SLIDER:
1037 /* i18n-hint: "x" suggests a multiplicative factor */
1038 val = XO("%.2fx").Format( value );
1039 break;
1040
1041#ifdef EXPERIMENTAL_MIDI_OUT
1042 case VEL_SLIDER:
1043 if (value > 0.0f)
1044 // Signed
1045 val = Verbatim("%+d").Format( (int) value );
1046 else
1047 // Zero, or signed negative
1048 val = Verbatim("%d").Format( (int) value );
1049 break;
1050#endif
1051 }
1052
1053 if(!mName.empty())
1054 {
1055 /* i18n-hint: An item name followed by a value, with appropriate separating punctuation */
1056 label = XO("%s: %s").Format( mName, val );
1057 }
1058 else
1059 label = val;
1060 }
1061 else
1062 {
1064 label.Format( value );
1065 }
1066
1067 return label;
1068}
1069
1071{
1072 TranslatableStrings results;
1073
1074 if (mTipTemplate.empty())
1075 {
1076 wxString val;
1077
1078 switch(mStyle)
1079 {
1080 case FRAC_SLIDER:
1081 results.push_back( GetTip( -1.99f ) );
1082 results.push_back( GetTip( +1.99f ) );
1083 break;
1084
1085 case PERCENT_SLIDER:
1086 results.push_back(GetTip(1.0f));
1087
1088 case DB_SLIDER:
1089 results.push_back( GetTip( -99.9f ) );
1090 results.push_back( GetTip( +99.9f ) );
1091 break;
1092
1093 case PAN_SLIDER:
1094 // Don't assume we know which of "Left", "Right", or "Center"
1095 // is the longest string, when localized
1096 results.push_back( GetTip( 0.f ) );
1097 results.push_back( GetTip( +1.f ) );
1098 results.push_back( GetTip( -1.f ) );
1099 break;
1100
1101 case SPEED_SLIDER:
1102 results.push_back( GetTip( 9.99f ) );
1103 break;
1104
1105#ifdef EXPERIMENTAL_MIDI_OUT
1106 case VEL_SLIDER:
1107 results.push_back( GetTip( 999.f ) );
1108 break;
1109#endif
1110 }
1111 }
1112 else
1113 {
1114 results.push_back( GetTip( floor(mMaxValue - mMinValue) + 0.999 ) );
1115 }
1116
1117 return results;
1118}
1119
1121{
1122 return DoShowDialog( mParent->ClientToScreen(wxPoint( mLeft, mTop ) ) );
1123}
1124
1125bool LWSlider::ShowDialog(wxPoint pos)
1126{
1127 return DoShowDialog( pos );
1128}
1129
1130bool LWSlider::DoShowDialog(wxPoint pos)
1131{
1132 float value = mCurrentValue;
1133 bool changed = false;
1134
1135 SliderDialog dlg( NULL,
1136 wxID_ANY,
1137 mName,
1138 pos,
1139 // Bug 2087. wxMin takes care of case where
1140 // slider is vertical (tall and narrow)
1141 wxSize( mWidth, wxMin( mWidth, mHeight) ),
1142 mStyle,
1143 Get(),
1146 this);
1147 if (pos == wxPoint(-1, -1)) {
1148 dlg.Center();
1149 }
1150
1151 changed = (dlg.ShowModal() == wxID_OK);
1152 if( changed )
1153 value = dlg.Get();
1154
1155 // We now expect the pop up dialog to be
1156 // sending updates as we go.
1157 // So this code is needed to possibly restore the old
1158 // value, on a cancel.
1159 if (mCurrentValue != value) {
1160 mCurrentValue = value;
1161 SendUpdate(value);
1162 }
1163
1164 return changed;
1165}
1166
1167void LWSlider::OnMouseEvent(wxMouseEvent & event)
1168{
1169 if (event.Entering())
1170 {
1171 // Display the tooltip in the status bar
1172 auto tip = GetTip(mCurrentValue);
1173 auto pProject = FindProjectFromWindow( mParent );
1174 if (pProject)
1175 ProjectStatus::Get( *pProject ).Set( tip );
1176 Refresh();
1177 }
1178 else if (event.Leaving())
1179 {
1180 if (!mIsDragging)
1181 {
1182 ShowTip(false);
1183 }
1184 auto pProject = FindProjectFromWindow( mParent );
1185 if (pProject)
1186 ProjectStatus::Get( *pProject ).Set({});
1187 Refresh();
1188 }
1189
1190 // Events other than mouse-overs are ignored when we are disabled
1191 if (!mEnabled)
1192 return;
1193
1194 // Windows sends a right button mouse event when you press the context menu
1195 // key, so ignore it.
1196 if ((event.RightDown() && !event.RightIsDown()) ||
1197 (event.RightUp() && event.GetPosition() == wxPoint(-1, -1)))
1198 {
1199 event.Skip(false);
1200 return;
1201 }
1202
1203 float prevValue = mCurrentValue;
1204
1205 // Figure out the thumb position
1206 wxRect r;
1207 if (mOrientation == wxHORIZONTAL)
1208 {
1210 r.y = mTop + (mCenterY - (mThumbHeight / 2));
1211 }
1212 else
1213 {
1214 r.x = mLeft + (mCenterX - (mThumbWidth / 2));
1216 }
1217 r.width = mThumbWidth;
1218 r.height = mThumbHeight;
1219
1220 wxRect tolerantThumbRect = r;
1221 tolerantThumbRect.Inflate(3, 3);
1222
1223 // Should probably use a right click instead/also
1224 if( event.ButtonDClick() && mPopup )
1225 {
1226 //On a double-click, we should pop up a dialog.
1227 DoShowDialog(mParent->ClientToScreen(wxPoint(event.m_x,event.m_y)));
1228 }
1229 else if( event.ButtonDown() )
1230 {
1231 if( mDefaultShortcut && event.ControlDown() )
1232 {
1234 }
1235
1236 if( event.RightDown() ) {
1237 mParent->SetFocus();
1238 }
1239
1240 // Thumb clicked?
1241 //
1242 // Do not change position until first drag. This helps
1243 // with unintended value changes.
1244 if( tolerantThumbRect.Contains( event.GetPosition() ) )
1245 {
1246 // Remember mouse position and current value
1247 mClickPos = (mOrientation == wxHORIZONTAL) ? event.m_x : event.m_y;
1249
1250 mIsDragging = true;
1251 }
1252 // Clicked to set location?
1253 else
1254 {
1257 (mOrientation == wxHORIZONTAL) ? event.m_x : event.m_y,
1258 event.ShiftDown());
1259 }
1260
1261 if (!mParent->HasCapture()) {
1262 mParent->CaptureMouse();
1263 }
1264
1265 ShowTip(true);
1266 }
1267 else if( event.ButtonUp() )
1268 {
1269 mIsDragging = false;
1270 if (mParent->HasCapture())
1271 mParent->ReleaseMouse();
1272
1273 ShowTip(false);
1274 }
1275 else if (event.Dragging() && mIsDragging)
1276 {
1277 if (mOrientation == wxHORIZONTAL)
1278 {
1279 if (event.m_y < (r.y - 2 * r.height) ||
1280 event.m_y > (r.y + 3 * r.height)) {
1281 // If the mouse y coordinate is relatively far from the slider,
1282 // snap back to the original position
1284 }
1285 else {
1286 // Otherwise, move the slider to the right position based
1287 // on the mouse position
1288 mCurrentValue = DragPositionToValue(event.m_x, event.ShiftDown());
1289 }
1290 }
1291 else // (mOrientation == wxVERTICAL)
1292 {
1293 if (event.m_x < (r.x - 2 * r.width) ||
1294 event.m_x > (r.x + 3 * r.width)) {
1295 // If the mouse x coordinate is relatively far from the slider,
1296 // snap back to the original position
1298 }
1299 else {
1300 // Otherwise, move the slider to the right position based
1301 // on the mouse position
1302 mCurrentValue = DragPositionToValue(event.m_y, event.ShiftDown());
1303 }
1304 }
1305 }
1306 else if( event.m_wheelRotation != 0 )
1307 {
1308 //Calculate the number of steps in a given direction this event
1309 //represents (allows for two or more clicks on a single event.)
1310 double steps = event.m_wheelRotation /
1311 (event.m_wheelDelta > 0 ? (double)event.m_wheelDelta : 120.0);
1312
1313 if( steps < 0.0 )
1314 {
1315 Decrease( (float)-steps );
1316 }
1317 else
1318 {
1319 Increase( (float)steps );
1320 }
1322 }
1323
1324 if( prevValue != mCurrentValue )
1326}
1327
1328void LWSlider::OnKeyDown(wxKeyEvent & event)
1329{
1330 if (mEnabled)
1331 {
1332 switch( event.GetKeyCode() )
1333 {
1334 case WXK_TAB:
1335 mParent->Navigate(event.ShiftDown()
1336 ? wxNavigationKeyEvent::IsBackward
1337 : wxNavigationKeyEvent::IsForward);
1338 break;
1339
1340 case WXK_RIGHT:
1341 case WXK_UP:
1344 ShowTip(true);
1345 break;
1346
1347 case WXK_LEFT:
1348 case WXK_DOWN:
1351 ShowTip(true);
1352 break;
1353
1354 case WXK_PAGEUP:
1357 ShowTip(true);
1358 break;
1359
1360 case WXK_PAGEDOWN:
1363 ShowTip(true);
1364 break;
1365
1366 case WXK_HOME:
1368 ShowTip(true);
1369 break;
1370
1371 case WXK_END:
1373 ShowTip(true);
1374 break;
1375
1376 case WXK_RETURN:
1377 case WXK_NUMPAD_ENTER:
1378 {
1379 wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(mParent), wxTopLevelWindow);
1380 wxWindow *def = tlw->GetDefaultItem();
1381 if (def && def->IsEnabled()) {
1382 wxCommandEvent cevent(wxEVT_COMMAND_BUTTON_CLICKED,
1383 def->GetId());
1384 cevent.SetEventObject( def );
1385 mParent->GetEventHandler()->ProcessEvent(cevent);
1386 }
1387 }
1388
1389 default:
1390 // Allow it to propagate
1391 event.Skip();
1392 break;
1393 }
1394 }
1395 else
1396 {
1397 event.Skip();
1398 }
1399}
1400
1401void LWSlider::SetParent(wxWindow* parent)
1402{
1403 mParent = parent;
1404 //VS: create pop win if there is no one, don't re-parent
1405 //as it seem to be a workaround for DC drawing purposes
1406 //(see `WaveTrackControls::GainSlider`)
1407 CreatePopWin();
1408}
1409
1410void LWSlider::SendUpdate( float newValue )
1411{
1412 mCurrentValue = newValue;
1413
1414 FormatPopWin();
1415
1416 Refresh();
1417
1418 // Update the project's status bar as well
1419 if (mTipPanel) {
1420 auto tip = GetTip(mCurrentValue);
1421 auto pProject = FindProjectFromWindow( mParent );
1422 if (pProject)
1423 ProjectStatus::Get( *pProject ).Set( tip );
1424 }
1425
1426 wxCommandEvent e( wxEVT_COMMAND_SLIDER_UPDATED, mID );
1427 int intValue = (int)( ( mCurrentValue - mMinValue ) * 1000.0f /
1428 ( mMaxValue - mMinValue ) );
1429 e.SetInt( intValue );
1430 mParent->GetEventHandler()->ProcessEvent(e);
1431}
1432
1434{
1435 switch(mStyle)
1436 {
1437 case FRAC_SLIDER:
1438 return wxString::Format(wxT("%.0f"), mCurrentValue * 100);
1439 case PERCENT_SLIDER:
1440 return wxString::Format(wxT("%.0f%%"), mCurrentValue * 100.0f);
1441 case DB_SLIDER:
1442 return wxString::Format(wxT("%.0f"), mCurrentValue);
1443 case PAN_SLIDER:
1444 return wxString::Format(wxT("%.0f"), mCurrentValue * 100);
1445 case SPEED_SLIDER:
1446 return wxString::Format(wxT("%.0f"), mCurrentValue * 100 );
1447#ifdef EXPERIMENTAL_MIDI_OUT
1448 case VEL_SLIDER:
1449 return wxString::Format(wxT("%.0f"), mCurrentValue);
1450#endif
1451 default:
1452 return {};
1453 }
1454}
1455
1457{
1458 ShowTip(false);
1459}
1460
1461
1463{
1464 float fRange = mMaxValue - mMinValue;
1465 if (mOrientation == wxHORIZONTAL)
1466 return (int)rint((val - mMinValue) * mWidthX / fRange);
1467 else
1468 // low values at bottom
1469 return (int)rint((mMaxValue - val) * mHeightY / fRange);
1470}
1471
1472void LWSlider::SetSpeed(float speed)
1473{
1474 mSpeed = speed;
1475}
1476
1477// Given the mouse slider coordinate in fromPos, compute the NEW value
1478// of the slider when clicking to set a NEW position.
1479float LWSlider::ClickPositionToValue(int fromPos, bool shiftDown)
1480{
1481 int nSpan;
1482 int pos;
1483 if (mOrientation == wxHORIZONTAL)
1484 {
1485 pos = (fromPos - mLeft - (mThumbWidth / 2));
1486 nSpan = mWidthX;
1487 }
1488 else
1489 {
1490 // wxVERTICAL => Low values at bottom.
1491 pos = mBottomY - fromPos;
1492 nSpan = mHeightY;
1493 }
1494
1495 // MM: Special cases: If position is at the very left or the
1496 // very right (or top/bottom for wxVERTICAL), set minimum/maximum value without other checks
1497 if (pos <= 0)
1498 return mMinValue;
1499 if (pos >= nSpan)
1500 return mMaxValue;
1501
1502 float val = (pos / (float)nSpan)
1504
1505 if (val < mMinValue)
1506 val = mMinValue;
1507 if (val > mMaxValue)
1508 val = mMaxValue;
1509
1510 if (!(mCanUseShift && shiftDown) && mStepValue != STEP_CONTINUOUS)
1511 {
1512 // MM: If shift is not down, or we don't allow usage
1513 // of shift key at all, trim value to steps of
1514 // provided size.
1515 val = (int)(val / mStepValue + 0.5 * (val>0?1.0f:-1.0f)) * mStepValue;
1516 }
1517
1518 return val;
1519}
1520
1521// Given the mouse slider coordinate in fromPos, compute the NEW value
1522// of the slider during a drag.
1523float LWSlider::DragPositionToValue(int fromPos, bool shiftDown)
1524{
1525 int delta = (fromPos - mClickPos);
1526
1527 float speed = mSpeed;
1528 // Precision enhancement for Shift drags
1529 if (mCanUseShift && shiftDown)
1530 speed *= 0.4f;
1531
1532 // wxVERTICAL => Low values at bottom, so throw in the minus sign here with -mHeightY.
1533 float denominator = (mOrientation == wxHORIZONTAL) ? mWidthX : -mHeightY;
1534 float val = mClickValue +
1535 speed * (delta / denominator) * (mMaxValue - mMinValue);
1536
1537 if (val < mMinValue)
1538 val = mMinValue;
1539 if (val > mMaxValue)
1540 val = mMaxValue;
1541
1542 if (!(mCanUseShift && shiftDown) && mStepValue != STEP_CONTINUOUS)
1543 {
1544 // MM: If shift is not down, or we don't allow usage
1545 // of shift key at all, and the slider has not continuous values,
1546 // trim value to steps of provided size.
1547 val = (int)(val / mStepValue + 0.5 * (val>0?1.0f:-1.0f)) * mStepValue;
1548 }
1549
1550 return val;
1551}
1552
1553float LWSlider::Get( bool convert )
1554{
1555 if (mStyle == DB_SLIDER)
1556 return (convert ? DB_TO_LINEAR(mCurrentValue) : mCurrentValue);
1557 else
1558 return mCurrentValue;
1559}
1560
1561void LWSlider::Set(float value)
1562{
1563 if (mIsDragging)
1564 return;
1565 if (mStyle == DB_SLIDER)
1566 mCurrentValue = LINEAR_TO_DB(value);
1567 else
1568 mCurrentValue = value;
1569
1574
1575 Refresh();
1576}
1577
1578void LWSlider::Increase(float steps)
1579{
1580 float stepValue = mStepValue;
1581
1582 if ( stepValue == 0.0 )
1583 {
1584 stepValue = ( mMaxValue - mMinValue ) / 10.0;
1585 }
1586
1587 mCurrentValue += ( steps * stepValue );
1588
1589 if ( mCurrentValue < mMinValue )
1590 {
1592 }
1593 else if ( mCurrentValue > mMaxValue )
1594 {
1596 }
1597
1598 Refresh();
1599}
1600
1601void LWSlider::Decrease(float steps)
1602{
1603 float stepValue = mStepValue;
1604
1605 if ( stepValue == 0.0 )
1606 {
1607 stepValue = ( mMaxValue - mMinValue ) / 10.0;
1608 }
1609
1610 mCurrentValue -= ( steps * stepValue );
1611
1612 if ( mCurrentValue < mMinValue )
1613 {
1615 }
1616 else if ( mCurrentValue > mMaxValue )
1617 {
1619 }
1620
1621 Refresh();
1622}
1623
1625{
1626 if (mHW)
1627 mParent->Refresh(false);
1628}
1629
1631{
1632 mBitmap.reset();
1633 mThumbBitmap.reset();
1634 mThumbBitmapHilited.reset();
1635
1636 Refresh();
1637}
1638
1640{
1641 return mEnabled;
1642}
1643
1644void LWSlider::SetEnabled(bool enabled)
1645{
1646 mEnabled = enabled;
1647
1648 mThumbBitmap.reset();
1649 mThumbBitmapHilited.reset();
1650
1651 Refresh();
1652}
1653
1655{
1656 return mMinValue;
1657}
1658
1660{
1661 return mMaxValue;
1662}
1663
1664//
1665// ASlider
1666//
1667
1668BEGIN_EVENT_TABLE(ASlider, wxPanel)
1669 EVT_KEY_DOWN(ASlider::OnKeyDown)
1670 EVT_MOUSE_EVENTS(ASlider::OnMouseEvent)
1671 EVT_MOUSE_CAPTURE_LOST(ASlider::OnCaptureLost)
1672 EVT_PAINT(ASlider::OnPaint)
1673 EVT_SIZE(ASlider::OnSize)
1674 EVT_ERASE_BACKGROUND(ASlider::OnErase)
1675 EVT_SLIDER(wxID_ANY, ASlider::OnSlider)
1676 EVT_SET_FOCUS(ASlider::OnSetFocus)
1677 EVT_KILL_FOCUS(ASlider::OnKillFocus)
1678 EVT_TIMER(wxID_ANY, ASlider::OnTimer)
1680
1681ASlider::ASlider( wxWindow * parent,
1682 wxWindowID id,
1683 const TranslatableString &name,
1684 const wxPoint & pos,
1685 const wxSize & size,
1686 const Options &options)
1687: wxPanel( parent, id, pos, size, wxWANTS_CHARS )
1688{
1689 //wxColour Col(parent->GetBackgroundColour());
1690 //SetBackgroundColour( Col );
1691 SetBackgroundColour( theTheme.Colour( clrMedium ) );
1692 mLWSlider = std::make_unique<LWSlider>( this,
1693 name,
1694 wxPoint(0,0),
1695 size,
1696 options.style,
1697 options.showLabels,
1698 options.drawTicks,
1699 options.drawTrack,
1700 options.alwaysHideTip,
1701 true, // ASlider is always a heavyweight LWSlider
1702 options.popup,
1703 options.orientation);
1704 mLWSlider->mStepValue = options.stepValue;
1705 mLWSlider->SetId( id );
1706 SetName( name.Translation() );
1707
1708 mSliderIsFocused = false;
1709 mStyle = options.style;
1710
1711 mTimer.SetOwner(this);
1712
1713#if wxUSE_ACCESSIBILITY
1714 SetAccessible( safenew ASliderAx( this ) );
1715#endif
1716
1717 mLWSlider->SetScroll( options.line, options.page );
1718}
1719
1720
1722{
1723 if(HasCapture())
1724 ReleaseMouse();
1725}
1726
1727bool ASlider::SetBackgroundColour(const wxColour& colour)
1728{
1729 auto res = wxPanel::SetBackgroundColour(colour);
1730
1731 if (res && mLWSlider)
1732 {
1733 mLWSlider->Redraw();
1734 }
1735
1736 return res;
1737}
1738
1739void ASlider::OnSlider(wxCommandEvent &event)
1740{
1741
1742 if ( event.GetId() == mLWSlider->GetId() )
1743 {
1744#if wxUSE_ACCESSIBILITY
1745 GetAccessible()->NotifyEvent( wxACC_EVENT_OBJECT_VALUECHANGE,
1746 this,
1747 wxOBJID_CLIENT,
1748 wxACC_SELF );
1749#endif
1750 }
1751
1752 event.Skip();
1753}
1754
1755void ASlider::OnSize(wxSizeEvent &event)
1756{
1757 mLWSlider->OnSize( event );
1758}
1759
1760void ASlider::OnErase(wxEraseEvent & WXUNUSED(event))
1761{
1762 // Ignore it to prevent flashing
1763}
1764
1765void ASlider::OnPaint(wxPaintEvent & WXUNUSED(event))
1766{
1767 wxBufferedPaintDC dc(this);
1768
1769 bool highlighted =
1770 GetClientRect().Contains(
1771 ScreenToClient(
1772 ::wxGetMousePosition() ) );
1773 mLWSlider->OnPaint(dc, highlighted);
1774
1775 if ( mSliderIsFocused )
1776 {
1777 wxRect r( 0, 0, mLWSlider->mWidth, mLWSlider->mHeight );
1778
1779 r.Deflate( 1, 1 );
1780
1781 AColor::DrawFocus( dc, r );
1782 }
1783}
1784
1785void ASlider::OnMouseEvent(wxMouseEvent &event)
1786{
1787 if (event.Entering())
1788 {
1789 mTimer.StartOnce(1000);
1790 }
1791 else if (event.Leaving())
1792 {
1793 mTimer.Stop();
1794 }
1795
1796 mLWSlider->OnMouseEvent(event);
1797}
1798
1799void ASlider::OnCaptureLost(wxMouseCaptureLostEvent & WXUNUSED(event))
1800{
1801 wxMouseEvent e(wxEVT_LEFT_UP);
1802 mLWSlider->OnMouseEvent(e);
1803}
1804
1805void ASlider::OnKeyDown(wxKeyEvent &event)
1806{
1807 mLWSlider->OnKeyDown(event);
1808}
1809
1810void ASlider::OnSetFocus(wxFocusEvent & WXUNUSED(event))
1811{
1812 mSliderIsFocused = true;
1813 Refresh();
1814}
1815
1816void ASlider::OnKillFocus(wxFocusEvent & WXUNUSED(event))
1817{
1818 mLWSlider->OnKillFocus();
1819 mSliderIsFocused = false;
1820 Refresh();
1821}
1822
1823void ASlider::OnTimer(wxTimerEvent & WXUNUSED(event))
1824{
1825 mLWSlider->ShowTip(true);
1826}
1827
1828void ASlider::GetScroll(float & line, float & page)
1829{
1830 mLWSlider->GetScroll(line, page);
1831}
1832
1833void ASlider::SetScroll(float line, float page)
1834{
1835 mLWSlider->SetScroll(line, page);
1836}
1837
1839{
1840 mLWSlider->SetToolTipTemplate(tip);
1841}
1842
1843float ASlider::Get( bool convert )
1844{
1845 return mLWSlider->Get( convert );
1846}
1847
1848void ASlider::Set(float value)
1849{
1850 mLWSlider->Set(value);
1851}
1852
1853void ASlider::Increase(float steps)
1854{
1855 mLWSlider->Increase(steps);
1856}
1857
1858void ASlider::Decrease(float steps)
1859{
1860 mLWSlider->Decrease(steps);
1861}
1862
1863bool ASlider::ShowDialog(wxPoint pos)
1864{
1865 return mLWSlider->ShowDialog(pos);
1866}
1867
1868void ASlider::SetSpeed(float speed)
1869{
1870 mLWSlider->SetSpeed(speed);
1871}
1872
1873bool ASlider::Enable(bool enable)
1874{
1875 if (mLWSlider->GetEnabled() == enable)
1876 return false;
1877
1878 mLWSlider->SetEnabled(enable);
1879
1880 wxWindow::Enable(enable);
1881
1882 return true;
1883}
1884
1886{
1887 return mLWSlider->GetEnabled();
1888}
1889
1890bool ASlider::s_AcceptsFocus{ false };
1891
1893 s_AcceptsFocus = true;
1894 return TempAllowFocus{ &s_AcceptsFocus };
1895}
1896
1897// This compensates for a but in wxWidgets 3.0.2 for mac:
1898// Couldn't set focus from keyboard when AcceptsFocus returns false;
1899// this bypasses that limitation
1901{
1902 auto temp = TemporarilyAllowFocus();
1903 SetFocus();
1904}
1905
1906#if wxUSE_ACCESSIBILITY
1907
1908ASliderAx::ASliderAx( wxWindow * window ) :
1909 WindowAccessible( window )
1910{
1911}
1912
1913ASliderAx::~ASliderAx()
1914{
1915}
1916
1917// Retrieves the address of an IDispatch interface for the specified child.
1918// All objects must support this property.
1919wxAccStatus ASliderAx::GetChild( int childId, wxAccessible** child )
1920{
1921 if ( childId == wxACC_SELF )
1922 {
1923 *child = this;
1924 }
1925 else
1926 {
1927 *child = NULL;
1928 }
1929
1930 return wxACC_OK;
1931}
1932
1933// Gets the number of children.
1934wxAccStatus ASliderAx::GetChildCount(int* childCount)
1935{
1936 *childCount = 3;
1937
1938 return wxACC_OK;
1939}
1940
1941// Gets the default action for this object (0) or > 0 (the action for a child).
1942// Return wxACC_OK even if there is no action. actionName is the action, or the empty
1943// string if there is no action.
1944// The retrieved string describes the action that is performed on an object,
1945// not what the object does as a result. For example, a toolbar button that prints
1946// a document has a default action of "Press" rather than "Prints the current document."
1947wxAccStatus ASliderAx::GetDefaultAction( int WXUNUSED(childId), wxString *actionName )
1948{
1949 actionName->clear();
1950
1951 return wxACC_OK;
1952}
1953
1954// Returns the description for this object or a child.
1955wxAccStatus ASliderAx::GetDescription( int WXUNUSED(childId), wxString *description )
1956{
1957 description->clear();
1958
1959 return wxACC_OK;
1960}
1961
1962// Gets the window with the keyboard focus.
1963// If childId is 0 and child is NULL, no object in
1964// this subhierarchy has the focus.
1965// If this object has the focus, child should be 'this'.
1966wxAccStatus ASliderAx::GetFocus(int* childId, wxAccessible** child)
1967{
1968 *childId = 0;
1969 *child = this;
1970
1971 return wxACC_OK;
1972}
1973
1974// Returns help text for this object or a child, similar to tooltip text.
1975wxAccStatus ASliderAx::GetHelpText( int WXUNUSED(childId), wxString *helpText )
1976{
1977 helpText->clear();
1978
1979 return wxACC_OK;
1980}
1981
1982// Returns the keyboard shortcut for this object or child.
1983// Return e.g. ALT+K
1984wxAccStatus ASliderAx::GetKeyboardShortcut( int WXUNUSED(childId), wxString *shortcut )
1985{
1986 shortcut->clear();
1987
1988 return wxACC_OK;
1989}
1990
1991// Returns the rectangle for this object (id = 0) or a child element (id > 0).
1992// rect is in screen coordinates.
1993wxAccStatus ASliderAx::GetLocation( wxRect& rect, int WXUNUSED(elementId) )
1994{
1995 ASlider *as = wxDynamicCast( GetWindow(), ASlider );
1996
1997 rect = as->GetRect();
1998 rect.SetPosition( as->GetParent()->ClientToScreen( rect.GetPosition() ) );
1999
2000 return wxACC_OK;
2001}
2002
2003// Gets the name of the specified object.
2004wxAccStatus ASliderAx::GetName(int WXUNUSED(childId), wxString* name)
2005{
2006 ASlider *as = wxDynamicCast( GetWindow(), ASlider );
2007
2008 *name = as->GetName();
2009
2010 return wxACC_OK;
2011}
2012
2013// Returns a role constant.
2014wxAccStatus ASliderAx::GetRole(int childId, wxAccRole* role)
2015{
2016 switch( childId )
2017 {
2018 case 0:
2019 *role = wxROLE_SYSTEM_SLIDER;
2020 break;
2021
2022 case 1:
2023 case 3:
2024 *role = wxROLE_SYSTEM_PUSHBUTTON;
2025 break;
2026
2027 case 2:
2028 *role = wxROLE_SYSTEM_INDICATOR;
2029 break;
2030 }
2031
2032 return wxACC_OK;
2033}
2034
2035// Gets a variant representing the selected children
2036// of this object.
2037// Acceptable values:
2038// - a null variant (IsNull() returns TRUE)
2039// - a list variant (GetType() == wxT("list"))
2040// - an integer representing the selected child element,
2041// or 0 if this object is selected (GetType() == wxT("long"))
2042// - a "void*" pointer to a wxAccessible child object
2043wxAccStatus ASliderAx::GetSelections( wxVariant * WXUNUSED(selections) )
2044{
2045 return wxACC_NOT_IMPLEMENTED;
2046}
2047
2048// Returns a state constant.
2049wxAccStatus ASliderAx::GetState(int childId, long* state)
2050{
2051 ASlider *as = wxDynamicCast( GetWindow(), ASlider );
2052
2053 switch( childId )
2054 {
2055 case 0:
2056 *state = wxACC_STATE_SYSTEM_FOCUSABLE;
2057 break;
2058
2059 case 1:
2060 if ( as->mLWSlider->mCurrentValue == as->mLWSlider->mMinValue )
2061 {
2062 *state = wxACC_STATE_SYSTEM_INVISIBLE;
2063 }
2064 break;
2065
2066 case 3:
2067 if ( as->mLWSlider->mCurrentValue == as->mLWSlider->mMaxValue )
2068 {
2069 *state = wxACC_STATE_SYSTEM_INVISIBLE;
2070 }
2071 break;
2072 }
2073
2074 // Do not use mSliderIsFocused is not set until after this method
2075 // is called.
2076 *state |= ( as == wxWindow::FindFocus() ? wxACC_STATE_SYSTEM_FOCUSED : 0 );
2077
2078 return wxACC_OK;
2079}
2080
2081// Returns a localized string representing the value for the object
2082// or child.
2083wxAccStatus ASliderAx::GetValue(int childId, wxString* strValue)
2084{
2085 ASlider *as = wxDynamicCast( GetWindow(), ASlider );
2086
2087 if ( childId == 0 )
2088 {
2089 *strValue = as->mLWSlider->GetStringValue();
2090 return wxACC_OK;
2091 }
2092 return wxACC_NOT_SUPPORTED;
2093}
2094
2095#endif
const int sliderFontSize
Definition: ASlider.cpp:135
static const wxPoint2DDouble enabledLeftEnd[]
Definition: ASlider.cpp:416
static const wxPoint2DDouble disabledRightEnd[]
Definition: ASlider.cpp:467
static const wxPoint2DDouble enabledLeftBegin[]
Definition: ASlider.cpp:408
END_EVENT_TABLE()
static const wxPoint2DDouble disabledRightBegin[]
Definition: ASlider.cpp:462
static const wxPoint2DDouble disabledStripesBegin[]
Definition: ASlider.cpp:442
static const wxPoint2DDouble enabledRightBegin[]
Definition: ASlider.cpp:426
static const wxPoint2DDouble enabledRightEnd[]
Definition: ASlider.cpp:433
static const wxPoint2DDouble disabledStripesEnd[]
Definition: ASlider.cpp:451
static const wxPoint2DDouble outer[]
Definition: ASlider.cpp:395
#define VEL_SLIDER
Definition: ASlider.h:37
#define DB_SLIDER
Definition: ASlider.h:33
#define FRAC_SLIDER
Definition: ASlider.h:32
#define STEP_CONTINUOUS
Definition: ASlider.h:54
#define PERCENT_SLIDER
Definition: ASlider.h:39
#define SPEED_SLIDER
Definition: ASlider.h:35
#define PAN_SLIDER
Definition: ASlider.h:34
#define VEL_MAX
Definition: ASlider.h:48
#define VEL_MIN
Definition: ASlider.h:47
wxEVT_COMMAND_BUTTON_CLICKED
wxT("CloseDown"))
const TranslatableString name
Definition: Distortion.cpp:76
XO("Cut/Copy/Paste")
#define _(s)
Definition: Internat.h:73
#define safenew
Definition: MemoryX.h:9
#define LINEAR_TO_DB(x)
Definition: MemoryX.h:336
#define DB_TO_LINEAR(x)
Definition: MemoryX.h:335
static const auto title
AudacityProject * FindProjectFromWindow(wxWindow *pWindow)
@ eIsCreating
Definition: ShuttleGui.h:37
@ eOkButton
Definition: ShuttleGui.h:599
@ eCancelButton
Definition: ShuttleGui.h:600
TranslatableString label
Definition: TagsEditor.cpp:165
THEME_API Theme theTheme
Definition: Theme.cpp:82
#define S(N)
Definition: ToChars.cpp:64
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
std::vector< TranslatableString > TranslatableStrings
int id
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:187
static wxPen tooltipPen
Definition: AColor.h:132
static wxBrush tooltipBrush
Definition: AColor.h:133
static void UseThemeColour(wxDC *dc, int iBrush, int iPen=-1, int alpha=255)
Definition: AColor.cpp:372
static void DrawFocus(wxDC &dc, wxRect &r)
Definition: AColor.cpp:235
ASlider is a custom slider, allowing for a slicker look and feel.
Definition: ASlider.h:260
static TempAllowFocus TemporarilyAllowFocus()
Definition: ASlider.cpp:1892
void OnSetFocus(wxFocusEvent &event)
Definition: ASlider.cpp:1810
void Set(float value)
Definition: ASlider.cpp:1848
void SetFocusFromKbd() override
Definition: ASlider.cpp:1900
void SetSpeed(float speed)
Definition: ASlider.cpp:1868
void GetScroll(float &line, float &page)
Definition: ASlider.cpp:1828
bool ShowDialog(wxPoint pos=wxPoint(-1, -1))
Definition: ASlider.cpp:1863
std::unique_ptr< LWSlider > mLWSlider
Definition: ASlider.h:348
void OnKeyDown(wxKeyEvent &event)
Definition: ASlider.cpp:1805
bool IsEnabled() const
Definition: ASlider.cpp:1885
void OnTimer(wxTimerEvent &event)
Definition: ASlider.cpp:1823
std::unique_ptr< bool, Resetter > TempAllowFocus
Definition: ASlider.h:342
void OnKillFocus(wxFocusEvent &event)
Definition: ASlider.cpp:1816
void Increase(float steps)
Definition: ASlider.cpp:1853
void OnCaptureLost(wxMouseCaptureLostEvent &event)
Definition: ASlider.cpp:1799
virtual ~ASlider()
Definition: ASlider.cpp:1721
void Decrease(float steps)
Definition: ASlider.cpp:1858
void OnSlider(wxCommandEvent &event)
Definition: ASlider.cpp:1739
void SetToolTipTemplate(const TranslatableString &tip)
Definition: ASlider.cpp:1838
void OnMouseEvent(wxMouseEvent &event)
Definition: ASlider.cpp:1785
static bool s_AcceptsFocus
Definition: ASlider.h:340
bool Enable(bool enable=true) override
Definition: ASlider.cpp:1873
void OnPaint(wxPaintEvent &event)
Definition: ASlider.cpp:1765
bool mSliderIsFocused
Definition: ASlider.h:349
bool SetBackgroundColour(const wxColour &colour) override
Definition: ASlider.cpp:1727
wxTimer mTimer
Definition: ASlider.h:350
void OnErase(wxEraseEvent &event)
Definition: ASlider.cpp:1760
void SetScroll(float line, float page)
Definition: ASlider.cpp:1833
void OnSize(wxSizeEvent &event)
Definition: ASlider.cpp:1755
float Get(bool convert=true)
Definition: ASlider.cpp:1843
Lightweight version of ASlider. In other words it does not have a window permanently associated with ...
Definition: ASlider.h:64
void Set(float value)
Definition: ASlider.cpp:1561
void DrawToBitmap(wxDC &dc)
Definition: ASlider.cpp:774
void OnPaint(wxDC &dc, bool highlighted)
Definition: ASlider.cpp:719
float mCurrentValue
Definition: ASlider.h:238
int mCenterX
Definition: ASlider.h:217
float mDefaultValue
Definition: ASlider.h:241
int mLeft
Definition: ASlider.h:203
float mMinValue
Definition: ASlider.h:230
int mThumbWidth
Definition: ASlider.h:224
bool mCanUseShift
Definition: ASlider.h:243
void OnKillFocus()
Definition: ASlider.cpp:1456
float GetMinValue() const
Definition: ASlider.cpp:1654
std::unique_ptr< wxBitmap > mThumbBitmap
Definition: ASlider.h:252
float mClickValue
Definition: ASlider.h:227
void SetEnabled(bool enabled)
Definition: ASlider.cpp:1644
void Init(wxWindow *parent, const TranslatableString &name, const wxPoint &pos, const wxSize &size, float minValue, float maxValue, float stepValue, bool canUseShift, int style, bool showlabels, bool drawticks, bool drawtrack, bool alwayshidetip, bool heavyweight, bool popup, float speed, int orientation=wxHORIZONTAL)
Definition: ASlider.cpp:563
bool mPopup
Definition: ASlider.h:201
int mHeightY
Definition: ASlider.h:221
void Redraw()
Definition: ASlider.cpp:1630
bool mAlwaysHideTip
Definition: ASlider.h:198
float mMaxValue
Definition: ASlider.h:231
void ShowTip(bool show)
Definition: ASlider.cpp:940
TranslatableString mTipTemplate
Definition: ASlider.h:248
bool mShowLabels
Definition: ASlider.h:194
void Refresh()
Definition: ASlider.cpp:1624
void OnMouseEvent(wxMouseEvent &event)
Definition: ASlider.cpp:1167
void Decrease(float steps)
Definition: ASlider.cpp:1601
int mTopY
Definition: ASlider.h:219
TranslatableString mName
Definition: ASlider.h:254
void CreatePopWin()
Definition: ASlider.cpp:955
void AdjustSize(const wxSize &sz)
Definition: ASlider.cpp:669
void Increase(float steps)
Definition: ASlider.cpp:1578
float Get(bool convert=true)
Definition: ASlider.cpp:1553
void SetDefaultValue(float value)
Definition: ASlider.cpp:640
wxString GetStringValue() const
Definition: ASlider.cpp:1433
void OnKeyDown(wxKeyEvent &event)
Definition: ASlider.cpp:1328
int ValueToPosition(float val)
Definition: ASlider.cpp:1462
int mBottomY
Definition: ASlider.h:220
TranslatableStrings GetWidestTips() const
Definition: ASlider.cpp:1070
int mLeftX
Definition: ASlider.h:212
int mCenterY
Definition: ASlider.h:210
int mStyle
Definition: ASlider.h:191
int mHeight
Definition: ASlider.h:207
bool mEnabled
Definition: ASlider.h:256
wxWindow * mParent
Definition: ASlider.h:189
std::unique_ptr< wxBitmap > mBitmap
Definition: ASlider.h:252
void GetScroll(float &line, float &page)
Definition: ASlider.cpp:651
void SetSpeed(float speed)
Definition: ASlider.cpp:1472
wxWindowID mID
Definition: ASlider.h:245
wxWindowID GetId()
Definition: ASlider.cpp:619
bool mIsDragging
Definition: ASlider.h:250
bool GetEnabled() const
Definition: ASlider.cpp:1639
void SetDefaultShortcut(bool value)
Definition: ASlider.cpp:646
int mRightX
Definition: ASlider.h:213
std::unique_ptr< wxBitmap > mThumbBitmapHilited
Definition: ASlider.h:252
float GetMaxValue() const
Definition: ASlider.cpp:1659
void SendUpdate(float newValue)
Definition: ASlider.cpp:1410
int mOrientation
Definition: ASlider.h:192
int mTop
Definition: ASlider.h:204
void SetName(const TranslatableString &name)
Definition: ASlider.cpp:629
float DragPositionToValue(int fromPos, bool shiftDown)
Definition: ASlider.cpp:1523
void SetScroll(float line, float page)
Definition: ASlider.cpp:657
bool DoShowDialog(wxPoint pos)
Definition: ASlider.cpp:1130
virtual ~LWSlider()
Definition: ASlider.cpp:615
void OnSize(wxSizeEvent &event)
Definition: ASlider.cpp:765
void SetId(wxWindowID id)
Definition: ASlider.cpp:624
bool mDrawTicks
Definition: ASlider.h:195
void SetToolTipTemplate(const TranslatableString &tip)
Definition: ASlider.cpp:935
float mSpeed
Definition: ASlider.h:233
bool ShowDialog()
Definition: ASlider.cpp:1120
bool mDefaultShortcut
Definition: ASlider.h:240
float mStepValue
Definition: ASlider.h:232
float mScrollPage
Definition: ASlider.h:236
void Move(const wxPoint &newpos)
Definition: ASlider.cpp:663
float mScrollLine
Definition: ASlider.h:235
bool mHW
Definition: ASlider.h:200
int mWidth
Definition: ASlider.h:206
int mWidthX
Definition: ASlider.h:214
bool mDrawTrack
Definition: ASlider.h:196
void FormatPopWin()
Definition: ASlider.cpp:986
void SetPopWinPosition()
Definition: ASlider.cpp:964
void SetParent(wxWindow *parent)
Definition: ASlider.cpp:1401
LWSlider(wxWindow *parent, const TranslatableString &name, const wxPoint &pos, const wxSize &size, float minValue, float maxValue, float stepValue, bool canUseShift, int style, bool showlabels=true, bool drawticks=true, bool drawtrack=true, bool alwayshidetip=false, bool heavyweight=false, bool popup=true, int orientation=wxHORIZONTAL)
Definition: ASlider.cpp:474
int mThumbHeight
Definition: ASlider.h:225
float ClickPositionToValue(int fromPos, bool shiftDown)
Definition: ASlider.cpp:1479
wxWeakRef< TipWindow > mTipPanel
Definition: ASlider.h:247
int mClickPos
Definition: ASlider.h:228
TranslatableString GetTip(float value) const
Definition: ASlider.cpp:997
static ProjectStatus & Get(AudacityProject &project)
void Set(const TranslatableString &msg, StatusBarField field=mainStatusBarField)
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:630
Pop up dialog used with an LWSlider.
Definition: ASlider.h:368
bool TransferDataFromWindow() override
Definition: ASlider.cpp:351
float mValue
Definition: ASlider.h:394
LWSlider * mpOrigin
Definition: ASlider.h:393
int mStyle
Definition: ASlider.h:392
void OnSlider(wxCommandEvent &event)
Definition: ASlider.cpp:370
float Get()
Definition: ASlider.cpp:385
void OnTextChange(wxCommandEvent &event)
Definition: ASlider.cpp:376
wxTextCtrl * mTextCtrl
Definition: ASlider.h:391
ASlider * mSlider
Definition: ASlider.h:390
bool TransferDataToWindow() override
Definition: ASlider.cpp:335
wxColour & Colour(int iIndex)
wxBitmap & Bitmap(int iIndex)
A wxPopupWindow used to give the numerical value of an LWSlider or ASlider.
Definition: ASlider.cpp:147
void OnPaint(wxPaintEvent &event)
Definition: ASlider.cpp:230
int mHeight
Definition: ASlider.cpp:162
virtual ~TipWindow()
Definition: ASlider.cpp:150
TipWindow(wxWindow *parent, const TranslatableStrings &labels)
Definition: ASlider.cpp:172
wxFont mFont
Definition: ASlider.cpp:163
int mWidth
Definition: ASlider.cpp:161
void SetLabel(const TranslatableString &label)
Definition: ASlider.cpp:225
TranslatableString mLabel
Definition: ASlider.cpp:160
void SetPos(const wxPoint &pos)
Definition: ASlider.cpp:220
wxSize GetSize() const
Definition: ASlider.cpp:215
Holds a msgid for the translation catalog; may also bind format arguments.
wxString Translation() const
TranslatableString & Format(Args &&...args) &
Capture variadic format arguments (by copy) when there is no plural.
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
void SetFocus(const WindowPlacement &focus)
Set the window that accepts keyboard input.
Definition: BasicUI.h:382
std::unique_ptr< WindowPlacement > FindFocus()
Find the window that is accepting keyboard input, if any.
Definition: BasicUI.h:373
__finl float __vecc rint(float a)
Options & Style(int s)
Definition: ASlider.h:280
Options & Page(float p)
Definition: ASlider.h:292
Options & Line(float l)
Definition: ASlider.h:291
Options & Popup(bool p)
Definition: ASlider.h:287