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