Audacity  2.2.2
SelectionBar.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  SelectionBar.cpp
6 
7  Copyright 2005 Dominic Mazzoni
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13 
14 *******************************************************************//****************************************************************//*******************************************************************/
27 
28 
29 #include "../Audacity.h"
30 
31 // For compilers that support precompilation, includes "wx/wx.h".
32 #include <wx/wxprec.h>
33 
34 #ifndef WX_PRECOMP
35 #include <wx/button.h>
36 #include <wx/checkbox.h>
37 #include <wx/combobox.h>
38 #include <wx/intl.h>
39 #include <wx/radiobut.h>
40 #include <wx/settings.h>
41 #include <wx/sizer.h>
42 #include <wx/valtext.h>
43 #include <wx/stattext.h>
44 #endif
45 #include <wx/statline.h>
46 
47 
48 #include "SelectionBarListener.h"
49 #include "SelectionBar.h"
50 
51 #include "../widgets/AButton.h"
52 #include "../AudioIO.h"
53 #include "../AColor.h"
54 #include "../Prefs.h"
55 #include "../Project.h"
56 #include "../Snap.h"
57 #include "../widgets/NumericTextCtrl.h"
58 #include "../AllThemeResources.h"
59 
61 
62 const static wxChar *numbers[] =
63 {
64  wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"),
65  wxT("5"), wxT("6"), wxT("7"), wxT("8"), wxT("9")
66 };
67 
68 enum {
73 
75 
81 
85 
90 
93 
94  id2,
100 };
101 
102 BEGIN_EVENT_TABLE(SelectionBar, ToolBar)
103  EVT_SIZE(SelectionBar::OnSize)
104  EVT_TEXT(StartTimeID, SelectionBar::OnChangedTime)
105  EVT_TEXT(LengthTimeID, SelectionBar::OnChangedTime)
106  EVT_TEXT(CenterTimeID, SelectionBar::OnChangedTime)
107  EVT_TEXT(EndTimeID, SelectionBar::OnChangedTime)
108  EVT_CHOICE(SnapToID, SelectionBar::OnSnapTo)
109  EVT_CHOICE(ChoiceID, SelectionBar::OnChoice )
110  EVT_COMBOBOX(RateID, SelectionBar::OnRate)
111  EVT_TEXT(RateID, SelectionBar::OnRate)
112  EVT_RADIOBUTTON(StartEndRadioID, SelectionBar::OnFieldChoice )
113  EVT_RADIOBUTTON(StartLengthRadioID, SelectionBar::OnFieldChoice )
114  EVT_RADIOBUTTON(LengthEndRadioID, SelectionBar::OnFieldChoice )
115  EVT_RADIOBUTTON(LengthCenterRadioID, SelectionBar::OnFieldChoice )
116 
118  SelTBMenuID,
119  wxEVT_COMMAND_BUTTON_CLICKED,
120  SelectionBar::OnButton )
121 // EVT_COMMAND( OnMenuId, wxEVT_COMMAND_BUTTON_CLICKED, SelectionBar::OnButton )
122  EVT_COMMAND(wxID_ANY, EVT_TIMETEXTCTRL_UPDATED, SelectionBar::OnUpdate)
123  EVT_COMMAND(wxID_ANY, EVT_CAPTURE_KEY, SelectionBar::OnCaptureKey)
125 
127 : ToolBar(SelectionBarID, _("Selection"), wxT("Selection")),
128  mListener(NULL), mRate(0.0),
129  mStart(0.0), mEnd(0.0), mLength(0.0), mCenter(0.0), mAudio(0.0),
130  mStartTime(NULL), mEndTime(NULL), mLengthTime(NULL), mCenterTime(NULL),
131  mAudioTime(NULL),
132  mChoice(NULL),
133  mDrive1( StartTimeID), mDrive2( EndTimeID ),
134  mSelectionMode(0)
135 {
136  // Make sure we have a valid rate as the NumericTextCtrl()s
137  // created in Populate()
138  // depend on it. Otherwise, division-by-zero floating point exceptions
139  // will occur.
140  // Refer to bug #462 for a scenario where the division-by-zero causes
141  // Audacity to fail.
142  mRate = (double) gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleRate"),
144 
145  // Selection mode of 0 means showing 'start' and 'end' only.
146  mSelectionMode = gPrefs->ReadLong(wxT("/SelectionToolbarMode"), 0);
147 }
148 
150 {
151 }
152 
153 void SelectionBar::Create(wxWindow * parent)
154 {
155  ToolBar::Create(parent);
156 }
157 
158 // Add Radio Button function is not used anymore.
159 // But maybe we will need it again in the future.
160 //
161 // Can't set textcolour of radio buttons.
162 // so instead if we want to them, we make the text empty and add in a wxStaticText
163 // and we can set the colour of that.
164 // Slight regression relative ot Audacity, in that this text is not
165 // clickable/active. You have to click on the actual button.
166 // And you can't tab between and hear the labels with voice over.
167 // So VI users should use blend themes (which is the default).
168 // Should not be a hardship for them, as themes make little difference
169 // for them, except Hi-Contrast, which should be used with blend thems
170 // and a windows theme that is close enough to actually blend.
171 
172 wxRadioButton * SelectionBar::AddRadioButton( const wxString & Name,
173  int id, wxSizer *pSizer, long style )
174 {
175  bool bUseNativeRadioButton = theTheme.IsUsingSystemTextColour();
176  wxRadioButton * pBtn;
177  // Safenew because the button is being create dinto this window.
178  pBtn = safenew wxRadioButton(this, id,bUseNativeRadioButton ? Name : wxT(""),
179  wxDefaultPosition, wxDefaultSize, style);
180  pBtn->SetName(Name);
181  pBtn->SetForegroundColour( theTheme.Colour( clrTrackPanelText ));
182 
183  pSizer->Add(pBtn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5);
184  // Hacky code to return a second optional value via the variable mProxy.
185  // If not NULL, we made a NEW proxy label
186  mProxy = NULL;
187  if( !bUseNativeRadioButton )
188  {
189  mProxy = safenew wxStaticText(this, -1, Name);
190  mProxy->SetForegroundColour( theTheme.Colour( clrTrackPanelText ) );
191  pSizer->Add(mProxy, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
192  }
193  return pBtn;
194 }
195 
196 auStaticText * SelectionBar::AddTitle( const wxString & Title, wxSizer * pSizer ){
197  auStaticText * pTitle = safenew auStaticText(this, Title );
198  pTitle->SetBackgroundColour( theTheme.Colour( clrMedium ));
199  pTitle->SetForegroundColour( theTheme.Colour( clrTrackPanelText ) );
200  pSizer->Add( pTitle,0, wxALIGN_CENTER_VERTICAL | wxRIGHT, (Title.Length() == 1 ) ? 0:5);
201  return pTitle;
202 }
203 
204 
205 NumericTextCtrl * SelectionBar::AddTime( const wxString Name, int id, wxSizer * pSizer ){
206  wxString formatName = mListener ? mListener->AS_GetSelectionFormat()
207  : wxString(wxEmptyString);
208  auto pCtrl = safenew NumericTextCtrl(
209  this, id, NumericConverter::TIME, formatName, 0.0, mRate);
210  pCtrl->SetName(Name);
211  pSizer->Add(pCtrl, 0, wxALIGN_TOP | wxRIGHT, 5);
212  return pCtrl;
213 }
214 
215 void SelectionBar::AddVLine( wxSizer * pSizer ){
216  pSizer->Add(safenew wxStaticLine(this, -1, wxDefaultPosition,
217  wxSize(1, toolbarSingle-10),
218  wxLI_VERTICAL),
219  0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5);
220 }
221 
223 {
224  SetBackgroundColour( theTheme.Colour( clrMedium ) );
225 
227 
228  // This will be inherited by all children:
229  SetFont(wxFont(
230 #ifdef __WXMAC__
231  12
232 #else
233  9
234 #endif
235  ,
236  wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
237 
238  wxFlexGridSizer *mainSizer;
239 
240  /* we don't actually need a control yet, but we want to use its methods
241  * to do some look-ups, so we'll have to create one. We can't make the
242  * look-ups static because they depend on translations which are done at
243  * runtime */
244 
245  // Outer sizer has space top and left.
246  // Inner sizers have space on right only.
247  // This choice makes for a nice border and internal spacing and places clear responsibility
248  // on each sizer as to what spacings it creates.
249  Add((mainSizer = safenew wxFlexGridSizer(SIZER_COLS, 1, 1)), 0, wxALIGN_TOP | wxLEFT | wxTOP, 5);
250 
251  //
252  // Top row (mostly labels)
253  //
254 
255  wxColour clrText = theTheme.Colour( clrTrackPanelText );
256  wxColour clrText2 = *wxBLUE;
257  AddTitle( _("Project Rate (Hz)"), mainSizer );
258  AddVLine( mainSizer );
259  AddTitle( _("Snap-To"), mainSizer );
260 #ifdef OPTIONS_BUTTON
261  // Not enough room to say 'Selection Options". There is a tooltip instead.
262  AddTitle( wxT(""), mainSizer );
263 #endif
264  AddVLine( mainSizer );
265  AddTitle( _("Audio Position"), mainSizer );
266  AddVLine( mainSizer );
267 
268  {
269  const wxString choices[4] = {
270  _("Start and End of Selection"),
271  _("Start and Length of Selection"),
272  _("Length and End of Selection"),
273  _("Length and Center of Selection"),
274  };
275  // The choice control now has a name.
276  // If this is less good for VI users, can go back to no name.
277  mChoice = safenew wxChoice
278  (this, ChoiceID, wxDefaultPosition, wxDefaultSize, 4, choices,
279  0, wxDefaultValidator, "Selection Type Chooser");
280  //mChoice->SetName(wxT("\a")); // stop Jaws screen reader using nearby text for name when name is empty
281  mChoice->SetSelection(0);
282 #ifdef __WXGTK__
283  // Combo boxes are taller on Linux, and if we don't do the following, the selection toolbar will
284  // be three units high.
285  wxSize sz = mChoice->GetBestSize();
286  sz.SetHeight( sz.y-4);
287  mChoice->SetMinSize( sz );
288 #endif
289  mainSizer->Add(mChoice, 0, wxALIGN_TOP | wxEXPAND | wxRIGHT, 6);
290  }
291 
292  //
293  // Botton row, (mostly time controls)
294  //
295 
296  mRateBox = safenew wxComboBox(this, RateID,
297  wxT(""),
298  wxDefaultPosition, wxSize(80, -1));
299  mRateBox->SetName(_("Project Rate (Hz)"));
300  //mRateBox->SetForegroundColour( clrText2 );
301  wxTextValidator vld(wxFILTER_INCLUDE_CHAR_LIST);
302  vld.SetIncludes(wxArrayString(10, numbers));
303  mRateBox->SetValidator(vld);
304  mRateBox->SetValue(wxString::Format(wxT("%d"), (int)mRate));
305  UpdateRates(); // Must be done _after_ setting value on mRateBox!
306 
307  // We need to capture the SetFocus and KillFocus events to set up
308  // for keyboard capture. On Windows and GTK it's easy since the
309  // combobox is presented as one control to hook into.
311 
312 #if defined(__WXMAC__)
313  // The Mac uses a standard wxTextCtrl for the edit portion and that's
314  // the control that gets the focus events. So we have to find the
315  // textctrl.
316  wxWindowList kids = mRateBox->GetChildren();
317  for (unsigned int i = 0; i < kids.GetCount(); i++) {
318  wxClassInfo *ci = kids[i]->GetClassInfo();
319  if (ci->IsKindOf(CLASSINFO(wxTextCtrl))) {
320  mRateText = kids[i];
321  break;
322  }
323  }
324 #endif
325 
326  mRateText->Bind(wxEVT_SET_FOCUS,
328  this);
329  mRateText->Bind(wxEVT_KILL_FOCUS,
331  this);
332 
333 #ifdef __WXGTK__
334  // Combo boxes are taller on Linux, and if we don't do the following, the selection toolbar will
335  // be three units high.
336  wxSize sz = mRateBox->GetBestSize();
337  sz.SetHeight( sz.y-4);
338  mRateBox->SetMinSize( sz );
339 #endif
340 
341  mainSizer->Add(mRateBox, 0, wxALIGN_TOP | wxRIGHT, 5);
342  AddVLine( mainSizer );
343 
344  mSnapTo = safenew wxChoice(this, SnapToID,
345  wxDefaultPosition, wxDefaultSize,
347 
348 #ifdef __WXGTK__
349  // Combo boxes are taller on Linux, and if we don't do the following, the selection toolbar will
350  // be three units high.
351  sz = mSnapTo->GetBestSize();
352  sz.SetHeight( sz.y-4);
353  mSnapTo->SetMinSize( sz );
354 #endif
355 
356  mainSizer->Add(mSnapTo,
357  0, wxALIGN_TOP | wxRIGHT, 5);
358  mSnapTo->SetName(_("Snap To"));
359  //mSnapTo->SetForegroundColour( clrText2 );
360  mSnapTo->SetSelection(mListener ? mListener->AS_GetSnapTo() : SNAP_OFF);
361 
362  mSnapTo->Bind(wxEVT_SET_FOCUS,
364  this);
365  mSnapTo->Bind(wxEVT_KILL_FOCUS,
367  this);
368 
369  AddVLine( mainSizer );
370 
371  mAudioTime = AddTime(_("Audio Position"), AudioTimeID, mainSizer );
372  // This vertical line is NOT just for decoration!
373  // It works around a wxWidgets-on-Windows RadioButton bug, where tabbing
374  // into the radiobutton group jumps to selecting the first item in the
375  // group even if some other item had been selected.
376  // It is an important bug to work around for sceen reader users, who use TAB
377  // a lot in navigation.
378  // More about the bug here:
379  // https://forums.wxwidgets.org/viewtopic.php?t=41120
380  AddVLine( mainSizer );
381 
382  {
383  auto hSizer = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
384 
385  mStartTime = AddTime(_("Start"), StartTimeID, hSizer.get() );
386  mLengthTime = AddTime(_("Length"), LengthTimeID, hSizer.get() );
387  mCenterTime = AddTime(_("Center"), CenterTimeID, hSizer.get() );
388  mEndTime = AddTime(_("End"), EndTimeID, hSizer.get() );
389  mainSizer->Add(hSizer.release(), 0, wxALIGN_TOP | wxRIGHT, 0);
390 
391  }
392 
393  mChoice->MoveBeforeInTabOrder( mStartTime );
394  // This shows/hides controls.
395  // Do this before layout so that we are sized right.
397  mainSizer->Layout();
399  Layout();
400 
401  SetMinSize( GetSizer()->GetMinSize() );
402 }
403 
405 {
406  mRate = (double) gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleRate"), AudioIO::GetOptimalSupportedSampleRate());
407 
408  wxCommandEvent e;
409  e.SetInt(mStartTime->GetFormatIndex());
410  OnUpdate(e);
411 
412  // Set label to pull in language change
413  SetLabel(_("Selection"));
414 
416 
417  // Give base class a chance
419 }
420 
422 {
423  mListener = l;
427 };
428 
430 {
431 #if wxUSE_TOOLTIPS
432  wxString formatName = mListener ? mListener->AS_GetSelectionFormat() : wxString(wxEmptyString);
433  mSnapTo->SetToolTip(wxString::Format(_("Snap Clicks/Selections to %s"), formatName));
434 #endif
435 }
436 
437 void SelectionBar::OnSize(wxSizeEvent &evt)
438 {
439  Refresh( true );
440 
441  evt.Skip();
442 }
443 
444 // When a control value is changed, this function is called.
445 // It determines the values for the other controls.
446 void SelectionBar::ModifySelection(int newDriver, bool done)
447 {
448  // If the user moved to a different control, then update which
449  // two controls drive the others.
450  if( newDriver != mDrive2 )
451  SetDrivers( mDrive2, newDriver);
452 
453  // Only update a value if user typed something in.
454  // The reason is the controls may be less accurate than
455  // the values.
456  if( newDriver == StartTimeID )
458  if( newDriver == EndTimeID )
459  mEnd = mEndTime->GetValue();
460  if( newDriver == LengthTimeID )
462  if( newDriver == CenterTimeID )
464 
465  int i = mDrive1 + 4 * mDrive2;
466  switch(i){
467  case StartTimeID + 4 * EndTimeID:
468  if( mEnd < mStart )
469  mStart = mEnd;
470  case StartTimeID * 4 + EndTimeID:
471  if( mStart > mEnd )
472  mEnd = mStart;
473  mLength = mEnd - mStart;
474  mCenter = (mStart+mEnd)/2.0;
475  break;
476  case StartTimeID + 4 * LengthTimeID:
477  case StartTimeID * 4 + LengthTimeID:
478  if( mLength < 0 )
479  mLength = 0;
480  mEnd = mStart+mLength;
481  mCenter = (mStart+mEnd)/2.0;
482  break;
483  case StartTimeID + 4 * CenterTimeID:
484  if( mCenter < mStart )
485  mCenter = mStart;
486  case StartTimeID * 4 + CenterTimeID:
487  if( mStart > mCenter )
488  mStart = mCenter;
489  mEnd = mCenter * 2 - mStart;
490  mLength = mStart - mEnd;
491  break;
492  case EndTimeID + 4 * LengthTimeID:
493  case EndTimeID * 4 + LengthTimeID:
494  if( mLength < 0 )
495  mLength = 0;
496  mStart = mEnd - mLength;
497  mCenter = (mStart+mEnd)/2.0;
498  break;
499  case EndTimeID + 4 * CenterTimeID:
500  if( mCenter > mEnd )
501  mCenter = mEnd;
502  case EndTimeID * 4 + CenterTimeID:
503  if( mEnd < mCenter )
504  mEnd = mCenter;
505  mStart = mCenter * 2.0 - mEnd;
506  mLength = mEnd - mStart;
507  break;
508  case LengthTimeID + 4 * CenterTimeID:
509  case LengthTimeID * 4 + CenterTimeID:
510  if( mLength < 0 )
511  mLength = 0;
512  mStart = mCenter - mLength/2.0;
513  mEnd = mCenter + mLength/2.0;
514  break;
515  default:
516  // The above should cover all legal combinations of two distinct controls.
517  wxFAIL_MSG( "Illegal sequence of selection changes");
518  }
519 
520  // Places the start-end mrkers on the track panel.
522 }
523 
524 void SelectionBar::OnChangedTime(wxCommandEvent & event)
525 {
526  ModifySelection(event.GetId(), event.GetInt() != 0);
527 }
528 
529 
530 void SelectionBar::OnTitleClicked(int newDriver)
531 {
532  // Ensure newDriver is the most recent driver.
533  if( newDriver != mDrive2 )
534  SetDrivers( mDrive2, newDriver);
535 }
536 
537 // These functions give the IDs of the associated control, NOT the ID of the title.
538 void SelectionBar::OnStartTitleClicked(wxMouseEvent & WXUNUSED(event)){ OnTitleClicked( StartTimeID );};
539 void SelectionBar::OnLengthTitleClicked(wxMouseEvent & WXUNUSED(event)){ OnTitleClicked( LengthTimeID );};
540 void SelectionBar::OnCenterTitleClicked(wxMouseEvent & WXUNUSED(event)){ OnTitleClicked( CenterTimeID );};
541 void SelectionBar::OnEndTitleClicked(wxMouseEvent & WXUNUSED(event)){ OnTitleClicked( EndTimeID );};
542 
543 void SelectionBar::OnModeDecClicked(wxMouseEvent & WXUNUSED(event)){
546 }
547 
548 void SelectionBar::OnModeIncClicked(wxMouseEvent & WXUNUSED(event)){
551 }
552 
553 void SelectionBar::OnChooserTitleClicked(wxMouseEvent & WXUNUSED(event)){
554  wxCommandEvent evt;
555  OnButton( evt );
556 }
557 
558 
559 // Called when one of the format drop downs is changed.
560 void SelectionBar::OnUpdate(wxCommandEvent &evt)
561 {
562  int index = evt.GetInt();
563  wxWindow *w = FindFocus();
565  int i;
566  int iFocus = -1;
567  for(i=0;i<5;i++)
568  if( w == *Ctrls[i] )
569  iFocus = i;
570 
571  evt.Skip(false);
572 
573  wxString format;
574 
575  // Save format name before recreating the controls so they resize properly
576  format = mStartTime->GetBuiltinName(index);
578 
580 
581  // ToolBar::ReCreateButtons() will get rid of our sizers and controls
582  // so reset pointers first.
583  for( i=0;i<5;i++)
584  *Ctrls[i]=NULL;
585 
586  mRateBox = NULL;
587  mRateText = NULL;
588 
590 
592 
593  format = mStartTime->GetBuiltinFormat(index);
594  for( i=0;i<5;i++)
595  (*Ctrls[i])->SetFormatString( format );
596 
597  if( iFocus >=0 )
598  (*Ctrls[iFocus])->SetFocus();
599  Updated();
600 }
601 
602 // The two drivers are the numbers of the two controls which drive the other ones.
603 // The user gets to see which controls are drivers and which driven.
604 void SelectionBar::SetDrivers( int driver1, int driver2 )
605 {
606  mDrive1 = driver1;
607  mDrive2 = driver2;
608 
610  wxString Text[4] = { _("Start"), _("Center"), _("Length"), _("End") };
611 
612  for(int i=0;i<4;i++){
613  int id = i + StartTimeID;
614  int fixed = (( id == mDrive2 )?mDrive1:mDrive2)-StartTimeID;
615 
616  wxString Temp = Text[i];
617  // i18n-hint: %s is replaced e.g by 'Length', to indicate that it will be calculated from other parameters.
618  wxString Format = ( (id!=mDrive1) && (id!=mDrive2 ) ) ? _("%s - driven") : "%s";
619  wxString Title= wxString::Format( Format, Temp );
620  // i18n-hint: %s1 is replaced e.g by 'Length', %s2 e.g by 'Center'.
621  wxString VoiceOverText = wxString::Format(_("Selection %s. %s won't change."), Temp, Text[fixed]);
622  // i18n-hint: %s is replaced e.g by 'Length'. This is a tooltip on a numerical control.
623  //wxString Tooltip = wxString::Format( _(" With %s fixed. (Use context menu to change format.) "), Text[fixed] );
624  if( *Ctrls[i] ){
625  (*Ctrls[i])->SetName( Temp );
626  //(*Ctrls[i])->SetToolTip( Tooltip );
627  }
628  }
629 }
630 
631 
632 // There currently is only one clickable AButton
633 // so we just do what it needs.
634 void SelectionBar::OnButton(wxCommandEvent & WXUNUSED(event))
635 {
637  if (!p) return;
638 
639  AButton * pBtn = mButtons[ SelTBMenuID-SelTBFirstButton];// use event.GetId();
640 
641  auto cleanup = finally( [&] { pBtn->InteractionOver();}
642  );
643  SetFocus();
644 
645  wxMenu Menu;
646  Menu.AppendRadioItem( 0, _("Start - End") );
647  Menu.AppendRadioItem( 1, _("Start - Length") );
648  Menu.AppendRadioItem( 2, _("Length - End") );
649  Menu.AppendRadioItem( 3, _("Length - Center") );
650  Menu.Check( mSelectionMode, true );
651  // Pop it up where the mouse is.
652  pBtn->PopupMenu(&Menu);//, wxPoint(0, 0));
653 
654  // only one radio button should be checked.
655  for( int i=0;i<4;i++)
656  if( Menu.IsChecked(i))
657  SetSelectionMode( i );
658 
660 }
661 
662 void SelectionBar::OnFieldChoice(wxCommandEvent &event)
663 {
664  int id = event.GetId();
667 }
668 
669 void SelectionBar::OnChoice(wxCommandEvent & WXUNUSED(event))
670 {
671  int mode = mChoice->GetSelection();
672  SetSelectionMode( mode );
674 }
675 
677 {
678  // We just changed the mode. Remember it.
679  gPrefs->Write(wxT("/SelectionToolbarMode"), mSelectionMode);
680  gPrefs->Flush();
681 
682  wxSize sz = GetMinSize();
683  sz.SetWidth( 10 );
684  SetMinSize( sz );
685  Fit();
686  Layout();
687  Updated();
688 }
689 
690 
692 {
693  // Only modes 0 to 3 are now supported,
694  // so fix up a mode that could have come from the config.
695  const int maxMode = 3;
696 
697  if( mode > maxMode )
698  mode = 0;
699  if( mode < 0 )
700  mode = 0;
701  mSelectionMode = mode;
702  mChoice->SetSelection( mode );
703 
704  // First decide which two controls drive the others...
705  // For example the last option is with all controls shown, and in that mode we
706  // initially have start and end driving.
707  int Drive2[] = { StartTimeID, StartTimeID, LengthTimeID, LengthTimeID,
708  StartTimeID, StartTimeID, StartTimeID, StartTimeID};
709  int Drive1[] = { EndTimeID, LengthTimeID, EndTimeID, CenterTimeID,
710  EndTimeID, LengthTimeID, EndTimeID, EndTimeID};
711 
712  SetDrivers( Drive1[mode], Drive2[mode] );
713  // Then show/hide the relevant controls.
714  ShowHideControls( mode );
715 }
716 
717 // Our mode determines which controls are visible.
719 {
720  // These
721  int masks[8]= {
722  9, 5, 12, 6, // 2 items
723  13, 7, 11,// 3 items
724  15};
725  int mask = masks[mode];
726 
728  for(int i=0;i<4;i++){
729  if( *Ctrls[i])
730  (*Ctrls[i])->Show( (mask & (1<<i))!=0 );
731  }
732 }
733 
735 {
737  double Values[5] = {mStart, mEnd, mLength, mCenter, mAudio };
738  int i;
739  for(i=0;i<5;i++)
740  if( *Ctrls[i] )
741  (*Ctrls[i])->SetValue( Values[i] );
742 }
743 
744 void SelectionBar::SetTimes(double start, double end, double audio)
745 {
746  mStart = start;
747  mEnd = end;
748  mLength = end-start;
749  mCenter = (end+start)/2.0;
750  mAudio = audio;
751 
753 }
754 
755 void SelectionBar::SetField(const wxChar *msg, int fieldNum)
756 {
757  if (fieldNum < 0 || fieldNum >= 10)
758  return;
759 
760  if (mField[fieldNum] != msg) {
761  mField[fieldNum] = msg;
762  Refresh(false);
763  }
764 }
765 
767 {
768  mSnapTo->SetSelection(snap);
769 }
770 
772 {
774 
775  wxCommandEvent e;
776  e.SetInt(mStartTime->GetFormatIndex());
777  OnUpdate(e);
778 }
779 
780 void SelectionBar::SetRate(double rate)
781 {
782  if (rate != mRate) {
783  // if the rate is actually being changed
784  mRate = rate; // update the stored rate
785  mRateBox->SetValue(wxString::Format(wxT("%d"), (int)rate));
786  // update the TimeTextCtrls if they exist
788  int i;
789  for(i=0;i<5;i++)
790  if( *Ctrls[i] )
791  (*Ctrls[i])->SetSampleRate( rate );
792  }
793 }
794 
795 void SelectionBar::OnRate(wxCommandEvent & WXUNUSED(event))
796 {
797  if (mRateBox->GetValue().ToDouble(&mRate) && // is a numeric value
798  (mRate != 0.0))
799  {
801  int i;
802  for(i=0;i<5;i++)
803  if( *Ctrls[i] )
804  (*Ctrls[i])->SetSampleRate( mRate );
806  }
807 }
808 
810 {
811  wxString oldValue = mRateBox->GetValue();
812  mRateBox->Clear();
813  for (int i = 0; i < AudioIO::NumStandardRates; i++) {
814  mRateBox->Append(wxString::Format(wxT("%d"), AudioIO::StandardRates[i]));
815  }
816  mRateBox->SetValue(oldValue);
817 }
818 
819 void SelectionBar::OnFocus(wxFocusEvent &event)
820 {
821  if (event.GetEventType() == wxEVT_KILL_FOCUS) {
823  }
824  else {
826  }
827 
828  Refresh(false);
829  event.Skip();
830 }
831 
832 void SelectionBar::OnCaptureKey(wxCommandEvent &event)
833 {
834  wxKeyEvent *kevent = (wxKeyEvent *)event.GetEventObject();
835  wxWindow *w = FindFocus();
836  int keyCode = kevent->GetKeyCode();
837 
838  // Convert numeric keypad entries.
839  if ((keyCode >= WXK_NUMPAD0) && (keyCode <= WXK_NUMPAD9)) {
840  keyCode -= WXK_NUMPAD0 - '0';
841  }
842 
843  if (keyCode >= '0' && keyCode <= '9') {
844  return;
845  }
846 
847  // UP/DOWN/LEFT/RIGHT for mRateText
848  if (w == mRateText) {
849  switch (keyCode)
850  {
851  case WXK_LEFT:
852  case WXK_RIGHT:
853  case WXK_UP:
854  case WXK_DOWN:
855  case WXK_DELETE:
856  case WXK_BACK:
857  return;
858  }
859  }
860 
861  event.Skip();
862 }
863 
864 void SelectionBar::OnSnapTo(wxCommandEvent & WXUNUSED(event))
865 {
866  mListener->AS_SetSnapTo(mSnapTo->GetSelection());
867 }
void InteractionOver()
Definition: AButton.h:131
virtual void AS_SetSnapTo(int snap)=0
virtual const wxString & AS_GetSelectionFormat()=0
void OnStartTitleClicked(wxMouseEvent &event)
static const wxChar * numbers[]
void RegenerateTooltips() override
NumericTextCtrl * AddTime(const wxString Name, int id, wxSizer *pSizer)
wxWindow * mRateText
Definition: SelectionBar.h:129
AUDACITY_DLL_API Theme theTheme
Definition: Theme.cpp:209
void SetRate(double rate)
wxComboBox * mRateBox
Definition: SelectionBar.h:127
NumericTextCtrl * mLengthTime
Definition: SelectionBar.h:122
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Definition: LabelDialog.cpp:88
virtual void UpdatePrefs()
Definition: ToolBar.cpp:540
void OnChangedTime(wxCommandEvent &evt)
Abstract base class used in importing a file.
Definition: Import.h:32
void SetSelectionFormat(const wxString &format)
wxBoxSizer * GetSizer()
Definition: ToolBar.cpp:608
void OnChooserTitleClicked(wxMouseEvent &event)
virtual int AS_GetSnapTo()=0
static void CaptureKeyboard(wxWindow *handler)
Definition: Project.cpp:5783
(not quite a Toolbar) at foot of screen for setting and viewing the selection range.
Definition: SelectionBar.h:47
wxRadioButton * AddRadioButton(const wxString &Name, int id, wxSizer *pSizer, long style)
SelectionBarListener * mListener
Definition: SelectionBar.h:105
virtual void ReCreateButtons()
Definition: ToolBar.cpp:464
void SetTimes(double start, double end, double audio)
void OnSnapTo(wxCommandEvent &event)
A parent class of SelectionBar, used to forward events to do with changes in the SelectionBar.
virtual void AS_SetRate(double rate)=0
virtual void AS_SetSelectionFormat(const wxString &format)=0
void ModifySelection(int newDriver, bool done=false)
void OnSize(wxSizeEvent &evt)
void OnFieldChoice(wxCommandEvent &event)
is like wxStaticText, except it can be themed. wxStaticText can't be.
Definition: Theme.h:177
#define toolbarSingle
Definition: ToolBar.h:54
void SetFormatString(const wxString &formatString)
EVT_COMMAND_RANGE(SelTBMenuID, SelTBMenuID, wxEVT_COMMAND_BUTTON_CLICKED, SelectionBar::OnButton) SelectionBar
wxStaticText * mProxy
Definition: SelectionBar.h:126
void Populate() override
static int GetOptimalSupportedSampleRate()
Get a supported sample rate which can be used a an optimal default.
Definition: AudioIO.cpp:3158
NumericTextCtrl * mCenterTime
Definition: SelectionBar.h:121
void OnModeIncClicked(wxMouseEvent &event)
void OnEndTitleClicked(wxMouseEvent &event)
#define safenew
Definition: Audacity.h:223
Definition: Snap.h:51
void OnButton(wxCommandEvent &event)
void SetSnapTo(int)
double mLength
Definition: SelectionBar.h:107
double mCenter
Definition: SelectionBar.h:107
void OnLengthTitleClicked(wxMouseEvent &event)
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:158
wxFileConfig * gPrefs
Definition: Prefs.cpp:72
void SelectionModeUpdated()
int format
Definition: ExportPCM.cpp:56
void UpdateRates()
void SetListener(SelectionBarListener *l)
void SetDrivers(int driver1, int driver2)
void OnTitleClicked(int newDriver)
void OnFocus(wxFocusEvent &event)
wxChoice * mSnapTo
Definition: SelectionBar.h:128
wxChoice * mChoice
Definition: SelectionBar.h:125
void Add(wxWindow *window, int proportion=0, int flag=wxALIGN_TOP, int border=0, wxObject *userData=NULL)
Definition: ToolBar.cpp:616
virtual void Create(wxWindow *parent)
Definition: ToolBar.cpp:443
bool IsUsingSystemTextColour()
Definition: Theme.h:118
virtual double AS_GetRate()=0
wxString mField[10]
Definition: SelectionBar.h:108
void OnRate(wxCommandEvent &event)
NumericTextCtrl * mAudioTime
Definition: SelectionBar.h:124
wxString GetBuiltinFormat(const int index)
void OnModeDecClicked(wxMouseEvent &event)
void ShowHideControls(int mode)
void Updated()
Definition: ToolBar.cpp:597
_("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 &)
void OnCenterTitleClicked(wxMouseEvent &event)
static void ReleaseKeyboard(wxWindow *handler)
Definition: Project.cpp:5794
IMPLEMENT_CLASS(SelectionBar, ToolBar)
void OnCaptureKey(wxCommandEvent &event)
void SetLabel(const wxString &label)
Definition: ToolBar.cpp:379
void OnUpdate(wxCommandEvent &evt)
void ValuesToControls()
static const int NumStandardRates
How many standard sample rates there are.
Definition: AudioIO.h:385
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:300
static wxArrayString GetSnapLabels()
Definition: Snap.cpp:364
void SetField(const wxChar *msg, int fieldNum)
#define SIZER_COLS
Definition: SelectionBar.h:27
wxString GetBuiltinName(const int index)
static const int StandardRates[]
Array of common audio sample rates.
Definition: AudioIO.h:383
wxColour & Colour(int iIndex)
Definition: Theme.cpp:1208
END_EVENT_TABLE()
AButton * mButtons[numSelectionBarButtons]
Definition: SelectionBar.h:131
void AddVLine(wxSizer *pSizer)
void OnChoice(wxCommandEvent &event)
void SetSelectionMode(int mode)
virtual ~SelectionBar()
Works with ToolManager and ToolDock to provide a dockable window in which buttons can be placed...
Definition: ToolBar.h:87
auStaticText * AddTitle(const wxString &Title, wxSizer *pSizer)
NumericTextCtrl * mStartTime
Definition: SelectionBar.h:120
void UpdatePrefs() override
virtual void AS_ModifySelection(double &start, double &end, bool done)=0
void Create(wxWindow *parent) override
A wxButton with mouse-over behaviour.
Definition: AButton.h:27
NumericTextCtrl * mEndTime
Definition: SelectionBar.h:123