Audacity 3.2.0
Public Member Functions | Protected Member Functions | Protected Attributes | Private Member Functions | List of all members
NumericConverter Class Reference

NumericConverter provides the advanced formatting control used in the selection bar of Audacity. More...

#include <NumericConverter.h>

Inheritance diagram for NumericConverter:
[legend]
Collaboration diagram for NumericConverter:
[legend]

Public Member Functions

 NumericConverter (const FormatterContext &context, NumericConverterType type, const NumericFormatID &formatName={}, double value=0.0f)
 
virtual ~NumericConverter ()
 
virtual void ValueToControls ()
 
virtual void ValueToControls (double rawValue, bool nearest=true)
 
virtual void ControlsToValue ()
 
bool SetTypeAndFormatName (const NumericConverterType &type, const NumericFormatID &formatName)
 
bool SetFormatName (const NumericFormatID &formatName)
 
NumericFormatID GetFormatName () const
 
bool SetCustomFormat (const TranslatableString &customFormat)
 
void SetValue (double newValue)
 
void SetMinValue (double minValue)
 
void ResetMinValue ()
 
void SetMaxValue (double maxValue)
 
void ResetMaxValue ()
 
double GetValue ()
 
wxString GetString ()
 
void UpdateFormatToFit (double value)
 
void Adjust (int steps, int dir, int focusedDigit)
 
void Increment (int focusedDigit=-1)
 
void Decrement (int focusedDigit=-1)
 
- Public Member Functions inherited from Observer::Publisher< FormatChangedToFitValueMessage >
 Publisher (ExceptionPolicy *pPolicy=nullptr, Alloc a={})
 Constructor supporting type-erased custom allocation/deletion. More...
 
 Publisher (Publisher &&)=default
 
Publisheroperator= (Publisher &&)=default
 
Subscription Subscribe (Callback callback)
 Connect a callback to the Publisher; later-connected are called earlier. More...
 
Subscription Subscribe (Object &obj, Return(Object::*callback)(Args...))
 Overload of Subscribe takes an object and pointer-to-member-function. More...
 

Protected Member Functions

bool UpdateFormatter ()
 
virtual void OnFormatUpdated (bool resetFocus)
 
- Protected Member Functions inherited from Observer::Publisher< FormatChangedToFitValueMessage >
CallbackReturn Publish (const FormatChangedToFitValueMessage &message)
 Send a message to connected callbacks. More...
 

Protected Attributes

FormatterContext mContext
 
NumericConverterType mType
 
double mMinValue { 0.0 }
 
double mMaxValue { std::numeric_limits<double>::max() }
 
double mInvalidValue { -1 }
 
double mValue { mInvalidValue }
 
std::unique_ptr< NumericConverterFormattermFormatter
 
NumericFormatID mFormatID
 
TranslatableString mCustomFormat
 
wxString mValueString
 
std::vector< wxString > mFieldValueStrings
 
Observer::Subscription mFormatUpdatedSubscription
 

Private Member Functions

bool ParseFormatString (const TranslatableString &untranslatedFormat)
 
int GetSafeFocusedDigit (int focusedDigit) const noexcept
 

Additional Inherited Members

- Public Types inherited from Observer::Publisher< FormatChangedToFitValueMessage >
using message_type = FormatChangedToFitValueMessage
 
using CallbackReturn = std::conditional_t< true, void, bool >
 
using Callback = std::function< CallbackReturn(const FormatChangedToFitValueMessage &) >
 Type of functions that can be connected to the Publisher. More...
 
- Static Public Attributes inherited from Observer::Publisher< FormatChangedToFitValueMessage >
static constexpr bool notifies_all
 

Detailed Description

NumericConverter provides the advanced formatting control used in the selection bar of Audacity.

NumericConverter has all the time conversion and snapping functionality that used to live in NumericTextCtrl. The idea is to have a GUI-less class which can do the conversions, so that we can use it in sanpping without having a window created each time.

NumericConverter

Any negative value given to the converter is considered invalid and all digit positions of the resulting string will be filled with hyphens. Otherwise:

The NumericConverter makes use of a format string to specify the exact way that a single value is split into several fields, such as the hh:mm:ss format. The advantage of this format string is that it is very small and compact, but human-readable and somewhat intuitive, so that it's easy to add NEW layouts in the future. It's also designed to make it easier to add i18n support, since the way that numbers are displayed in different languages could conceivably vary a lot.

The number to be formatted may be expressed in seconds, so the format string can specify the relationship of each field to the number of seconds.

The class is also reused to format some non-time values such as frequency and log of frequency.

Let's start by considering an example: here's the format string that prints an integer number of seconds in the hour minute second h:m:s format:

:60:60

The "*" is a wildcard, saying that the leftmost field can contain numbers of arbitrary magnitude. The next character, ':', since it is not a digit or a wildcard, is interpreted as a delimiter, and will be displayed between those fields. The next number, 60, indicates that the range of the next field (minutes) is 60. Then there's another ':' delimiter, and finally the last field (seconds) is 60. So, if you give it a number like 3758 it is formatted as:

3758 seconds, "*:60:60" -> "1:2:38"

Note that 3758 = 1*60*60 + 2*60 + 38.

When NumericConverter formats an integer, you can think of its process as working from right to left. Given the value "3758", it fills in the seconds by dividing by 60, sticking the remainder in the seconds field and then passing the quotient to the next field to the left.

In order to format a field with leading zeros, simply add a leading zero to that field, like this:

3758 seconds, "*:060:060" -> "1:02:38"

In order to format fractions, simply include a field delimiter ending with a decimal point. If the delimiter is simply '.' with nothing else, then the '.' is actually displayed. Otherwise the '.' is dropped, and the other characters in the delimiter are displayed instead.

Here's how we'd display hours, minutes, and seconds with three decimal places after the seconds:

3758.5 seconds, "*:060:060.01000" -> "1:02:38.500"

Similarly, here's how we'd display the fractional part of seconds as film frames (24 per second) instead of milliseconds:

3758.5 seconds, "*:060:060 and .24 frames" -> "1:02:38 and 12 frames"

Note that the decimal '.' is associated with the delimiter, not with the 24.

Additionally, the special character '#' can be used in place of a number to represent the current sample rate. Use '0#' to add leading zeros to that field. For example:

3758.5 seconds, "*:060:060+.#samples" -> "1:02:38+22050samples"

(Almost) Finally, there is a rule that allows you to change the units into something other than seconds. To do this, put a "|" character on the far right, followed by a number specifying the scaling factor. As an exception to previous rules, decimal points are allowed in the final scaling factor - the period is not interpreted as it would be before the "|" character. (This is fine, because all previous fields must be integers to make sense.) Anyway, if you include a scaling factor after a "|", the number will be multiplied by this factor before it is formatted. For example, to express the current time in NTSC frames (~29.97 fps), you could use the following formatting:

3758.5 seconds, "*.01000 frames|29.97002997" -> "112642.358 frames"

Finally there is a further special character that can be used after a "|" and that is "N". This applies special rule for NTSC drop-frame timecode.

Summary of format string rules:

Constructor & Destructor Documentation

◆ NumericConverter()

NumericConverter::NumericConverter ( const FormatterContext context,
NumericConverterType  type,
const NumericFormatID formatName = {},
double  value = 0.0f 
)

Definition at line 47 of file NumericConverter.cpp.

50 : mContext { context }
51 , mType { std::move(type) }
52{
55
56 SetFormatName(formatName);
57 SetValue(value);
58}
NumericConverterType mType
void SetValue(double newValue)
FormatterContext mContext
bool SetFormatName(const NumericFormatID &formatName)

References ResetMaxValue(), ResetMinValue(), SetFormatName(), and SetValue().

Here is the call graph for this function:

◆ ~NumericConverter()

NumericConverter::~NumericConverter ( )
virtual

Definition at line 69 of file NumericConverter.cpp.

70{
71}

Member Function Documentation

◆ Adjust()

void NumericConverter::Adjust ( int  steps,
int  dir,
int  focusedDigit 
)

Definition at line 271 of file NumericConverter.cpp.

272{
273 if (!mFormatter || mFormatter->GetDigitInfos().empty())
274 return;
275 // It is possible and "valid" for steps to be zero if a
276 // high precision device is being used and wxWidgets supports
277 // reporting a higher precision...Mac wx3 does.
278 if (steps == 0)
279 return;
280
281 focusedDigit = GetSafeFocusedDigit(focusedDigit);
282
283 wxASSERT(dir == -1 || dir == 1);
284 wxASSERT(steps > 0);
285 if (steps < 0)
286 steps = -steps;
287
288 while (steps != 0)
289 {
290 mValue = mFormatter->SingleStep(mValue, focusedDigit, dir > 0);
291 steps--;
292 }
293
294 mValue = std::clamp(mValue, mMinValue, mMaxValue);
295
297}
virtual void ValueToControls()
std::unique_ptr< NumericConverterFormatter > mFormatter
int GetSafeFocusedDigit(int focusedDigit) const noexcept

References GetSafeFocusedDigit(), mFormatter, mMaxValue, mMinValue, mValue, and ValueToControls().

Referenced by Decrement(), Increment(), NumericTextCtrl::OnKeyDown(), and NumericTextCtrl::OnMouse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ControlsToValue()

void NumericConverter::ControlsToValue ( )
virtual

Reimplemented in NumericTextCtrl.

Definition at line 90 of file NumericConverter.cpp.

91{
92 if (!mFormatter)
93 {
95 return;
96 }
97
98 auto result = mFormatter->StringToValue(mValueString);
99
100 mValue = result.has_value() ?
101 std::clamp(*result, mMinValue, mMaxValue) :
103}

References mFormatter, mInvalidValue, mMaxValue, mMinValue, mValue, and mValueString.

Referenced by NumericTextCtrl::ControlsToValue(), GetValue(), OnFormatUpdated(), and SetValue().

Here is the caller graph for this function:

◆ Decrement()

void NumericConverter::Decrement ( int  focusedDigit = -1)

Definition at line 225 of file NumericConverter.cpp.

226{
227 Adjust(1, -1, focusedDigit);
228}
void Adjust(int steps, int dir, int focusedDigit)

References Adjust().

Here is the call graph for this function:

◆ GetFormatName()

NumericFormatID NumericConverter::GetFormatName ( ) const

Definition at line 137 of file NumericConverter.cpp.

138{
139 return mFormatID;
140}
NumericFormatID mFormatID

References mFormatID.

Referenced by TimeToolBar::Populate(), SpectralSelectionBar::SetBandwidthSelectionFormatName(), SpectralSelectionBar::SetFrequencySelectionFormatName(), SpectralSelectionBar::UpdatePrefs(), and TimeToolBar::UpdatePrefs().

Here is the caller graph for this function:

◆ GetSafeFocusedDigit()

int NumericConverter::GetSafeFocusedDigit ( int  focusedDigit) const
privatenoexcept

Definition at line 211 of file NumericConverter.cpp.

212{
213 if (focusedDigit < 0)
214 return int(mFormatter->GetDigitInfos().size() - 1);
215 else
216 return std::clamp<int>(
217 focusedDigit, 0, mFormatter->GetDigitInfos().size() - 1);
218}

Referenced by Adjust().

Here is the caller graph for this function:

◆ GetString()

wxString NumericConverter::GetString ( )

Definition at line 200 of file NumericConverter.cpp.

201{
203 return mValueString;
204}

References mValueString, and ValueToControls().

Referenced by EffectRepeat::DisplayNewTime(), and NumericRenderer::Draw().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetValue()

double NumericConverter::GetValue ( )

◆ Increment()

void NumericConverter::Increment ( int  focusedDigit = -1)

Definition at line 220 of file NumericConverter.cpp.

221{
222 Adjust(1, 1, focusedDigit);
223}

References Adjust().

Here is the call graph for this function:

◆ OnFormatUpdated()

void NumericConverter::OnFormatUpdated ( bool  resetFocus)
protectedvirtual

Reimplemented in NumericTextCtrl.

Definition at line 262 of file NumericConverter.cpp.

263{
264 if (!mFormatter)
265 return;
266
269}

References ControlsToValue(), mFormatter, and ValueToControls().

Referenced by NumericTextCtrl::OnFormatUpdated(), and UpdateFormatter().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ParseFormatString()

bool NumericConverter::ParseFormatString ( const TranslatableString untranslatedFormat)
private

Definition at line 60 of file NumericConverter.cpp.

62{
64 mContext, mType, untranslatedFormat);
65
66 return mFormatter != nullptr;
67}
std::unique_ptr< NumericConverterFormatter > CreateParsedNumericConverterFormatter(const FormatterContext &context, NumericConverterType type, const TranslatableString &format)

References CreateParsedNumericConverterFormatter(), mContext, mFormatter, and mType.

Referenced by SetCustomFormat(), and UpdateFormatter().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ResetMaxValue()

void NumericConverter::ResetMaxValue ( )

Definition at line 189 of file NumericConverter.cpp.

190{
191 mMaxValue = std::numeric_limits<double>::max();
192}

References mMaxValue.

Referenced by NumericConverter(), and SpectralSelectionBar::SetBounds().

Here is the caller graph for this function:

◆ ResetMinValue()

void NumericConverter::ResetMinValue ( )

Definition at line 174 of file NumericConverter.cpp.

175{
176 mMinValue = 0.0;
177}

References mMinValue.

Referenced by NumericConverter(), and SpectralSelectionBar::SetBounds().

Here is the caller graph for this function:

◆ SetCustomFormat()

bool NumericConverter::SetCustomFormat ( const TranslatableString customFormat)

Definition at line 142 of file NumericConverter.cpp.

143{
144 if (mCustomFormat == customFormat)
145 return false;
146
147 if (!ParseFormatString(customFormat))
148 return false;
149
150 mFormatID = {};
151 mCustomFormat = customFormat;
152
154
155 return true;
156}
bool ParseFormatString(const TranslatableString &untranslatedFormat)
TranslatableString mCustomFormat

References mCustomFormat, mFormatID, ParseFormatString(), and UpdateFormatter().

Referenced by NumericTextCtrl::SetCustomFormat().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetFormatName()

bool NumericConverter::SetFormatName ( const NumericFormatID formatName)

Definition at line 118 of file NumericConverter.cpp.

119{
120 if (mFormatID == formatName && !formatName.empty())
121 return false;
122
123 const auto newFormat =
125
126 if (mFormatID == newFormat)
127 return false;
128
129 mFormatID = newFormat;
130 mCustomFormat = {};
131
133
134 return true;
135}
const wxString & Internal() const
bool empty() const
Definition: Identifier.h:61
NUMERIC_FORMATS_API NumericFormatSymbol Lookup(const FormatterContext &context, const NumericConverterType &type, const NumericFormatID &formatIdentifier)
Looks up the format, returns Default for the type if the format is not registered.

References Identifier::empty(), ComponentInterfaceSymbol::Internal(), NumericConverterFormats::Lookup(), mContext, mCustomFormat, mFormatID, mType, and UpdateFormatter().

Referenced by NumericConverter(), NumericTextCtrl::SetFormatName(), and SetTypeAndFormatName().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetMaxValue()

void NumericConverter::SetMaxValue ( double  maxValue)

Definition at line 179 of file NumericConverter.cpp.

180{
181 mMaxValue = maxValue;
182 if (mMinValue > maxValue) {
183 mMinValue = maxValue;
184 }
185 if (mValue > maxValue)
186 SetValue(maxValue);
187}

References mMaxValue, mMinValue, mValue, and SetValue().

Referenced by SpectralSelectionBar::SetBounds().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetMinValue()

void NumericConverter::SetMinValue ( double  minValue)

Definition at line 165 of file NumericConverter.cpp.

166{
167 mMinValue = minValue;
168 if (mMaxValue < minValue)
169 mMaxValue = minValue;
170 if (mValue < minValue)
171 SetValue(minValue);
172}

References mMaxValue, mMinValue, mValue, and SetValue().

Referenced by SpectralSelectionBar::SetBounds().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetTypeAndFormatName()

bool NumericConverter::SetTypeAndFormatName ( const NumericConverterType type,
const NumericFormatID formatName 
)

Definition at line 105 of file NumericConverter.cpp.

106{
107 if (mType != type)
108 {
109 // Ensure that the format change will happen,
110 // duration formats lists matches the time list
111 mFormatID = {};
112 mType = type;
113 }
114
115 return SetFormatName(formatName);
116}

References mFormatID, mType, and SetFormatName().

Referenced by NumericTextCtrl::SetTypeAndFormatName().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetValue()

void NumericConverter::SetValue ( double  newValue)

Definition at line 158 of file NumericConverter.cpp.

159{
160 mValue = newValue;
163}

References ControlsToValue(), mValue, and ValueToControls().

Referenced by EffectRepeat::DisplayNewTime(), NumericConverter(), SetMaxValue(), SetMinValue(), and NumericTextCtrl::SetValue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateFormatter()

bool NumericConverter::UpdateFormatter ( )
protected

Definition at line 230 of file NumericConverter.cpp.

231{
232 if (!mFormatID.empty())
233 {
235
236 if (formatterItem == nullptr)
237 {
238 assert(formatterItem != nullptr);
239 return false;
240 }
241
242 mFormatter = formatterItem->factory->Create(mContext);
243 }
244 else if (!mCustomFormat.empty ())
245 {
247 }
248
249 if (mFormatter)
250 {
252 mFormatter->Subscribe([this](const auto& msg) {
253 OnFormatUpdated(false);
254 Publish({ msg.value });
255 });
256 }
257
258 OnFormatUpdated(true);
259 return mFormatter != nullptr;
260}
virtual void OnFormatUpdated(bool resetFocus)
Observer::Subscription mFormatUpdatedSubscription
CallbackReturn Publish(const FormatChangedToFitValueMessage &message)
Send a message to connected callbacks.
Definition: Observer.h:207
static const NumericConverterRegistryItem * Find(const FormatterContext &context, const NumericConverterType &type, const NumericFormatID &symbol)

References Identifier::empty(), TranslatableString::empty(), NumericConverterRegistry::Find(), mContext, mCustomFormat, mFormatID, mFormatter, mFormatUpdatedSubscription, mType, OnFormatUpdated(), ParseFormatString(), and Observer::Publisher< FormatChangedToFitValueMessage >::Publish().

Referenced by SetCustomFormat(), and SetFormatName().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateFormatToFit()

void NumericConverter::UpdateFormatToFit ( double  value)

Definition at line 206 of file NumericConverter.cpp.

207{
208 mFormatter->UpdateFormatForValue(value, false);
209}

References mFormatter.

Referenced by ValueToControls().

Here is the caller graph for this function:

◆ ValueToControls() [1/2]

void NumericConverter::ValueToControls ( )
virtual

Reimplemented in NumericTextCtrl.

Definition at line 73 of file NumericConverter.cpp.

74{
76}

References mValue, and ValueToControls().

Referenced by Adjust(), GetString(), OnFormatUpdated(), SetValue(), ValueToControls(), and NumericTextCtrl::ValueToControls().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ValueToControls() [2/2]

void NumericConverter::ValueToControls ( double  rawValue,
bool  nearest = true 
)
virtual

Definition at line 78 of file NumericConverter.cpp.

79{
80 if (!mFormatter)
81 return;
82
83 UpdateFormatToFit(rawValue);
84 auto result = mFormatter->ValueToString(rawValue, nearest);
85
86 mValueString = std::move(result.valueString);
87 mFieldValueStrings = std::move(result.fieldValueStrings);
88}
std::vector< wxString > mFieldValueStrings
void UpdateFormatToFit(double value)

References mFieldValueStrings, mFormatter, mValueString, and UpdateFormatToFit().

Here is the call graph for this function:

Member Data Documentation

◆ mContext

FormatterContext NumericConverter::mContext
protected

◆ mCustomFormat

TranslatableString NumericConverter::mCustomFormat
protected

Definition at line 100 of file NumericConverter.h.

Referenced by SetCustomFormat(), SetFormatName(), and UpdateFormatter().

◆ mFieldValueStrings

std::vector<wxString> NumericConverter::mFieldValueStrings
protected

Definition at line 104 of file NumericConverter.h.

Referenced by ValueToControls().

◆ mFormatID

NumericFormatID NumericConverter::mFormatID
protected

◆ mFormatter

std::unique_ptr<NumericConverterFormatter> NumericConverter::mFormatter
protected

◆ mFormatUpdatedSubscription

Observer::Subscription NumericConverter::mFormatUpdatedSubscription
protected

Definition at line 106 of file NumericConverter.h.

Referenced by UpdateFormatter().

◆ mInvalidValue

double NumericConverter::mInvalidValue { -1 }
protected

◆ mMaxValue

double NumericConverter::mMaxValue { std::numeric_limits<double>::max() }
protected

◆ mMinValue

double NumericConverter::mMinValue { 0.0 }
protected

◆ mType

NumericConverterType NumericConverter::mType
protected

◆ mValue

double NumericConverter::mValue { mInvalidValue }
protected

◆ mValueString

wxString NumericConverter::mValueString
protected

The documentation for this class was generated from the following files: