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