Audacity  3.0.3
TimeToolBar.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  TimeToolBar.cpp
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  *//*******************************************************************/
13 
14 
15 
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include <wx/wxprec.h>
18 
19 #include <wx/setup.h> // for wxUSE_* macros
20 
21 #ifndef WX_PRECOMP
22 #include <wx/intl.h>
23 #include <wx/sizer.h>
24 #endif
25 
26 #include "TimeToolBar.h"
27 #include "SelectionBarListener.h"
28 #include "ToolManager.h"
29 
30 #include "../AudioIO.h"
31 #include "Project.h"
32 #include "../ProjectAudioIO.h"
33 #include "ProjectRate.h"
34 #include "../ProjectSettings.h"
35 #include "ViewInfo.h"
36 
38 
39 // Having a fixed ID for the Audio Position is helpful for
40 // the Jaws screen reader script for Audacity.
41 enum {
44 };
45 
46 BEGIN_EVENT_TABLE(TimeToolBar, ToolBar)
47  EVT_COMMAND(AudioPositionID, EVT_TIMETEXTCTRL_UPDATED, TimeToolBar::OnUpdate)
48  EVT_SIZE(TimeToolBar::OnSize)
49  EVT_IDLE(TimeToolBar::OnIdle)
51 
53 : ToolBar(project, TimeBarID, XO("Time"), wxT("Time"), true),
54  mListener(NULL),
55  mAudioTime(NULL)
56 {
57  project.Bind(EVT_PROJECT_RATE_CHANGE, &TimeToolBar::OnRateChanged, this);
58 }
59 
61 {
62 }
63 
65 {
66  auto &toolManager = ToolManager::Get(project);
67  return *static_cast<TimeToolBar*>(toolManager.GetToolBar(TimeBarID));
68 }
69 
71 {
72  return Get(const_cast<AudacityProject&>(project)) ;
73 }
74 
76 {
77  const auto &settings = ProjectSettings::Get(mProject);
78 
79  // Get the default sample rate
80  auto rate = ProjectRate::Get(mProject).GetRate();
81 
82  // Get the default time format
83  auto format = settings.GetAudioTimeFormat();
84 
85  // Create the read-only time control
87  mAudioTime->SetName(XO("Audio Position"));
88  mAudioTime->SetReadOnly(true);
89 
90  // Add it to the toolbar
91  Add(mAudioTime, 0, wxALIGN_CENTER, 0);
92 
93  // Calculate the width to height ratio
94  wxSize digitSize = mAudioTime->GetDigitSize();
95  mDigitRatio = (float)digitSize.x / digitSize.y;
96 
97  // During initialization, we need to bypass some resizing to prevent the "best size"
98  // from being used as we want to ensure the saved size is used instead. See SetDocked()
99  // and OnUpdate() for more info.
100  mSettingInitialSize = true;
101 
102  // Establish initial resizing limits
103 // SetResizingLimits();
104 }
105 
107 {
108  // Since the language may have changed, we need to force an update to accommodate
109  // different length text
110  wxCommandEvent e;
111  e.SetInt(mAudioTime->GetFormatIndex());
112  OnUpdate(e);
113 
114  // Language may have changed so reset label
115  SetLabel(XO("Time"));
116 
117  // Give the toolbar a chance
119 }
120 
122 {
123  // Reset
124  SetMaxSize(wxDefaultSize);
125  SetMinSize(wxDefaultSize);
126 
127  // Set the default time format
129 
130  // Set the default size
131  SetSize(GetInitialWidth(), 48);
132 
133  // Inform others the toobar has changed
134  Updated();
135 }
136 
138 {
139  wxSize sz = GetSize();
140 
141  // Anything less than a single height bar becomes single height
142  if (sz.y <= toolbarSingle) {
143  sz.y = toolbarSingle;
144  }
145  // Otherwise it will be a double height bar
146  else {
147  sz.y = 2 * toolbarSingle + toolbarGap;
148  }
149 
150  return sz;
151 }
152 
153 void TimeToolBar::SetDocked(ToolDock *dock, bool pushed)
154 {
155  // It's important to call this FIRST since it unhides the resizer control.
156  // Not doing so causes the calculated best size to be off by the width
157  // of the resizer.
158  ToolBar::SetDocked(dock, pushed);
159 
160  // Recalculate the min and max limits
162 
163  // When moving from floater to dock, fit to toolbar since the resizer will
164  // be mispositioned
165  if (dock) {
166  // During initialization, the desired size is already set, so do not
167  // override it with the "best size". See OnUpdate for further info.
168  if (!mSettingInitialSize) {
169  // Fit() while retaining height
170  SetSize(GetBestSize().x, GetSize().y);
171 
172  // Inform others the toolbar has changed
173  Updated();
174  }
175  }
176 }
177 
179 {
180  // Remember the listener
181  mListener = l;
182 
183  // Get (and set) the saved time format
185 
186  // During initialization, if the saved format is the same as the default,
187  // OnUpdate() will not be called and need it to set the initial size.
188  if (mSettingInitialSize) {
189  wxCommandEvent e;
190  e.SetInt(mAudioTime->GetFormatIndex());
191  OnUpdate(e);
192  }
193 }
194 
196 {
197  // Set the format if it's different from previous
199  // Simulate an update since the format has changed.
200  wxCommandEvent e;
201  e.SetInt(mAudioTime->GetFormatIndex());
202  OnUpdate(e);
203  }
204 }
205 
206 // The intention of this is to get the resize handle in the
207 // correct position, after we've let go in dragging.
209 {
210  // Fit() while retaining height
211  SetSize(GetBestSize().x, GetSize().y);
212 
213  // Inform others the toobar has changed
214  Updated();
215 }
216 
218 {
219  // Reset limits
220  SetMinSize(wxDefaultSize);
221  SetMaxSize(wxDefaultSize);
222 
223  // If docked we use the current bar height since it's always a single or double height
224  // toolbar. For floaters, single height toolbar is the minimum height.
225  int minH = IsDocked() ? GetSize().y : toolbarSingle;
226 
227  // Get the content size given the smallest digit height we allow
228  wxSize minSize = ComputeSizing(minDigitH);
229 
230  // Account for any borders added by the window manager
231  minSize.x += (mAudioTime->GetSize().x - mAudioTime->GetClientSize().x);
232 
233  // Calculate the space used by other controls and sizer borders with this toolbar
234  wxSize outer = (GetSize() - GetSizer()->GetSize());
235 
236  // And account for them in the width
237  minSize.x += outer.x;
238 
239  // Override the height
240  minSize.y = minH;
241 
242  // Get the maximum digit height we can use. This is restricted to the toolbar's
243  // current height minus any control borders
244  int digH = minH - (mAudioTime->GetSize().y - mAudioTime->GetClientSize().y);
245 
246  // Get the content size using the digit height, if docked. Otherwise use the
247  // maximum digit height we allow.
248  wxSize maxSize = ComputeSizing(IsDocked() ? digH : maxDigitH);
249 
250  // Account for the other controls and sizer borders within this toolbar
251  maxSize.x += outer.x;
252 
253  // Account for any borders added by the window manager and +1 to keep toolbar
254  // from dropping to next smaller size when grabbing the resizer.
255  maxSize.x += (mAudioTime->GetSize().x - mAudioTime->GetClientSize().x) + 1;
256 
257  // Override the height
258  maxSize.y = IsDocked() ? minH : wxDefaultCoord;
259 
260  // And finally set them both
261  SetMinSize(minSize);
262  SetMaxSize(maxSize);
263 }
264 
265 // Called when the project rate changes
266 void TimeToolBar::OnRateChanged(wxEvent &evt)
267 {
268  evt.Skip();
269 
270  if (mAudioTime) {
272  }
273 }
274 
275 // Called when the format drop downs is changed.
276 // This causes recreation of the toolbar contents.
277 void TimeToolBar::OnUpdate(wxCommandEvent &evt)
278 {
279  evt.Skip(false);
280 
281  // Reset to allow resizing to work
282  SetMinSize(wxDefaultSize);
283  SetMaxSize(wxDefaultSize);
284 
285  // Save format name before recreating the controls so they resize properly
286  if (mListener) {
288  }
289 
290  // During initialization, the desired size will have already been set at this point
291  // and the "best" size" would override it, so we simply send a size event to force
292  // the content to fit inside the toolbar.
293  if (mSettingInitialSize) {
294  mSettingInitialSize = false;
295  SendSizeEvent();
296  }
297  // Otherwise we want the toolbar to resize to fit around the content
298  else {
299  // Fit() while retaining height
300  SetSize(GetBestSize().x, GetSize().y);
301  }
302 
303  // Go set the new size limits
305 
306  // Inform others the toobar has changed
307  Updated();
308 }
309 
310 void TimeToolBar::OnSize(wxSizeEvent &evt)
311 {
312  evt.Skip();
313 
314  // Can fire before we're ready
315  if (!mAudioTime) {
316  return;
317  }
318 
319  // Make sure everything is where it's supposed to be
320  Layout();
321 
322  // Get the sizer's size and remove any borders the time control might have.
323  wxSize sizerBR = GetSizer()->GetSize() - (mAudioTime->GetSize() - mAudioTime->GetClientSize());
324 
325  // Get the content size of the time control. This can be different than the
326  // control itself due to borders and sizer enduced changes.
327  wxSize timeBR = mAudioTime->GetDimensions();
328 
329  // Get the current digit box height
330  int h = mAudioTime->GetDigitSize().y;
331 
332  // Increase current size to find the best fit within the new size
333  if (sizerBR.x >= timeBR.x && sizerBR.y >= timeBR.y) {
334  do {
335  h++;
336  timeBR = ComputeSizing(h);
337  } while (h < maxDigitH && sizerBR.x >= timeBR.x && sizerBR.y >= timeBR.y);
338  h--;
339  }
340  // In all other cases, we need to decrease current size to fit within new size
341  else if (sizerBR.x < timeBR.x || sizerBR.y < timeBR.y) {
342  do {
343  h--;
344  timeBR = ComputeSizing(h);
345  } while (h >= minDigitH && (sizerBR.x < timeBR.x || sizerBR.y < timeBR.y));
346  }
347 
348  if (h != mAudioTime->GetDigitSize().y) {
350  }
351 
352  // Redraw the display immediately to smooth out resizing
353  Update();
354 }
355 
356 void TimeToolBar::OnIdle(wxIdleEvent &evt)
357 {
358  evt.Skip();
359 
360  double audioTime;
361 
362  auto &projectAudioIO = ProjectAudioIO::Get(mProject);
363  if (projectAudioIO.IsAudioActive()) {
364  auto gAudioIO = AudioIO::Get();
365  audioTime = gAudioIO->GetStreamTime();
366  }
367  else {
368  const auto &playRegion = ViewInfo::Get(mProject).playRegion;
369  audioTime = playRegion.GetStart();
370  }
371 
372  mAudioTime->SetValue(wxMax(0.0, audioTime));
373 }
374 
376 {
377  TimeBarID,
378  []( AudacityProject &project )
379  {
380  return ToolBar::Holder{ safenew TimeToolBar{ project } };
381  }
382 };
383 
384 namespace {
386 {
387  TimeBarID,
388  wxT("ShowTimeTB"),
389  /* i18n-hint: Clicking this menu item shows the toolbar
390  for viewing actual time of the cursor */
391  XXO("&Time Toolbar"),
392  {
394  "ShowSelectionTB"
395  }
396 };
397 }
398 
toolbarGap
#define toolbarGap
Definition: ToolBar.h:64
TimeBarID
@ TimeBarID
Definition: ToolBar.h:86
ViewInfo::Get
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:161
ToolDock
A dynamic panel where a ToolBar can be docked.
Definition: ToolDock.h:290
TimeToolBar::mSettingInitialSize
bool mSettingInitialSize
Definition: TimeToolBar.h:57
ToolManager.h
TimeToolBar::mDigitRatio
float mDigitRatio
Definition: TimeToolBar.h:56
outer
static const wxPoint2DDouble outer[]
Definition: ASlider.cpp:395
TimeToolBar::mListener
TimeToolBarListener * mListener
Definition: TimeToolBar.h:54
anonymous_namespace{TimeToolBar.cpp}::sAttachment
AttachedToolBarMenuItem sAttachment
Definition: TimeToolBar.cpp:386
EVT_COMMAND
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Definition: LabelDialog.cpp:92
Project.h
ViewInfo::playRegion
PlayRegion playRegion
Definition: ViewInfo.h:197
ProjectRate::Get
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:42
TimeToolBar::Populate
void Populate() override
Definition: TimeToolBar.cpp:75
NumericTextCtrl::SetFormatString
bool SetFormatString(const FormatStrings &formatString)
Definition: NumericTextCtrl.cpp:1449
ToolBar::mProject
AudacityProject & mProject
Definition: ToolBar.h:235
ToolBar::SetLabel
void SetLabel(const wxString &label) override
Definition: ToolBar.cpp:398
ToolManager::Get
static ToolManager & Get(AudacityProject &project)
Definition: ToolManager.cpp:356
PlayRegion::GetStart
double GetStart() const
Definition: ViewInfo.h:134
TimeToolBar::OnRateChanged
void OnRateChanged(wxEvent &evt)
Definition: TimeToolBar.cpp:266
TimeToolBar::OnSize
void OnSize(wxSizeEvent &evt)
Definition: TimeToolBar.cpp:310
NumericTextCtrl::SetName
void SetName(const TranslatableString &name)
Definition: NumericTextCtrl.cpp:1420
NumericTextCtrl::GetDigitSize
wxSize GetDigitSize()
Definition: NumericTextCtrl.h:232
XO
#define XO(s)
Definition: Internat.h:31
ToolBar::GetSizer
wxBoxSizer * GetSizer()
Definition: ToolBar.cpp:678
ProjectSettings::Get
static ProjectSettings & Get(AudacityProject &project)
Definition: ProjectSettings.cpp:41
Registry::OrderingHint::After
@ After
Definition: Registry.h:29
ToolBar::Holder
wxWindowPtr< ToolBar > Holder
Definition: ToolBar.h:102
NumericTextCtrl::SetDigitSize
void SetDigitSize(int width, int height)
Definition: NumericTextCtrl.cpp:1479
TimeToolBar::GetDockedSize
wxSize GetDockedSize() override
Definition: TimeToolBar.cpp:137
TimeToolBar::SetDocked
void SetDocked(ToolDock *dock, bool pushed) override
Definition: TimeToolBar.cpp:153
ProjectAudioIO::Get
static ProjectAudioIO & Get(AudacityProject &project)
Definition: ProjectAudioIO.cpp:22
NumericConverter::GetFormatIndex
int GetFormatIndex()
Definition: NumericTextCtrl.cpp:1178
NumericTextCtrl
Definition: NumericTextCtrl.h:172
NumericTextCtrl::SetValue
void SetValue(double newValue)
Definition: NumericTextCtrl.cpp:1472
AttachedToolBarMenuItem
Definition: ToolManager.h:224
ComponentInterfaceSymbol
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Definition: ComponentInterfaceSymbol.h:27
TimeToolBar::ComputeSizing
wxSize ComputeSizing(int digitH)
Definition: TimeToolBar.h:68
TimeToolBar::SetToDefaultSize
void SetToDefaultSize() override
Definition: TimeToolBar.cpp:121
XXO
#define XXO(s)
Definition: Internat.h:44
NumericTextCtrl::SetSampleRate
void SetSampleRate(double sampleRate)
Definition: NumericTextCtrl.cpp:1463
NumericConverter::GetBuiltinFormat
FormatStrings GetBuiltinFormat(const int index)
Definition: NumericTextCtrl.cpp:1207
TimeToolBar::OnIdle
void OnIdle(wxIdleEvent &evt)
Definition: TimeToolBar.cpp:356
TimeToolBar::GetInitialWidth
int GetInitialWidth() override
Resizable toolbars should implement these.
Definition: TimeToolBar.h:36
anonymous_namespace{TimeTrack.cpp}::GetRate
double GetRate()
Definition: TimeTrack.cpp:175
ToolBar::UpdatePrefs
void UpdatePrefs() override
Definition: ToolBar.cpp:605
NumericConverter::TIME
@ TIME
Definition: NumericTextCtrl.h:52
SelectionBarListener.h
format
int format
Definition: ExportPCM.cpp:56
TimeToolBarListener
Definition: SelectionBarListener.h:35
NumericTextCtrl::SetReadOnly
void SetReadOnly(bool readOnly=true)
Definition: NumericTextCtrl.cpp:1487
IMPLEMENT_CLASS
IMPLEMENT_CLASS(TimeToolBar, ToolBar)
ProjectRate::GetRate
double GetRate() const
Definition: ProjectRate.cpp:68
TimeToolBarListener::TT_SetAudioTimeFormat
virtual void TT_SetAudioTimeFormat(const NumericFormatSymbol &format)=0
NumericConverter::HoursMinsSecondsFormat
static NumericFormatSymbol HoursMinsSecondsFormat()
Definition: NumericTextCtrl.cpp:694
TimeToolBar::Get
static TimeToolBar & Get(AudacityProject &project)
Definition: TimeToolBar.cpp:64
ViewInfo.h
ToolBar::IsDocked
bool IsDocked() const
Definition: ToolBar.cpp:423
TimeToolBar.h
TimeToolBar::ResizingDone
void ResizingDone() override
Definition: TimeToolBar.cpp:208
TimeToolBar::mAudioTime
NumericTextCtrl * mAudioTime
Definition: TimeToolBar.h:55
NumericTextCtrl::GetDimensions
wxSize GetDimensions()
Definition: NumericTextCtrl.h:231
TimeToolBar::SetAudioTimeFormat
void SetAudioTimeFormat(const NumericFormatSymbol &format)
Definition: TimeToolBar.cpp:195
RegisteredToolbarFactory
Definition: ToolBar.h:261
TimeToolBar::minDigitH
static const int minDigitH
Definition: TimeToolBar.h:59
NumericConverter::GetBuiltinName
NumericFormatSymbol GetBuiltinName(const int index)
Definition: NumericTextCtrl.cpp:1199
AudioPositionID
@ AudioPositionID
Definition: TimeToolBar.cpp:43
TimeToolBar
Definition: TimeToolBar.h:23
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:92
TimeBarFirstID
@ TimeBarFirstID
Definition: TimeToolBar.cpp:42
TimeToolBar::SetListener
void SetListener(TimeToolBarListener *l)
Definition: TimeToolBar.cpp:178
TimeToolBar::OnUpdate
void OnUpdate(wxCommandEvent &evt)
Definition: TimeToolBar.cpp:277
ProjectRate.h
an object holding per-project preferred sample rate
ToolBar
Works with ToolManager and ToolDock to provide a dockable window in which buttons can be placed.
Definition: ToolBar.h:98
TimeToolBar::maxDigitH
static const int maxDigitH
Definition: TimeToolBar.h:60
TimeToolBar::UpdatePrefs
void UpdatePrefs() override
Definition: TimeToolBar.cpp:106
ToolBar::SetDocked
virtual void SetDocked(ToolDock *dock, bool pushed)
Definition: ToolBar.cpp:638
ToolBar::Updated
void Updated()
Definition: ToolBar.cpp:661
AudioIO::Get
static AudioIO * Get()
Definition: AudioIO.cpp:606
TimeToolBar::SetResizingLimits
void SetResizingLimits()
Definition: TimeToolBar.cpp:217
safenew
#define safenew
Definition: MemoryX.h:10
settings
static Settings & settings()
Definition: TrackInfo.cpp:86
TimeToolBar::~TimeToolBar
virtual ~TimeToolBar()
Definition: TimeToolBar.cpp:60
toolbarSingle
#define toolbarSingle
Definition: ToolBar.h:59
END_EVENT_TABLE
END_EVENT_TABLE()
ToolBar::Add
void Add(wxWindow *window, int proportion=0, int flag=wxALIGN_TOP, int border=0, wxObject *userData=NULL)
Definition: ToolBar.cpp:686
TimeToolBarListener::TT_GetAudioTimeFormat
virtual const NumericFormatSymbol & TT_GetAudioTimeFormat()=0
factory
static RegisteredToolbarFactory factory
Definition: TimeToolBar.cpp:376