PixelUI separates numeric presentation from component drawing. The numeric APIs below provide validated ranges, allocation-free formatting, bindings, and edit transactions.
Range and normalization
1 | NumericRange range; |
| API | Signature | Description |
|---|---|---|
| Constructor | constexpr NumericRange() |
Creates the default range [0, 100] with step 1. |
| Static factory | static constexpr bool tryCreate(int32_t minimum, int32_t maximum, int32_t step, NumericRange& output) |
Validates minimum <= maximum and step > 0. On success, writes the range to output and returns true. |
| Getter | constexpr int32_t minimum() const |
Returns the lower bound. |
| Getter | constexpr int32_t maximum() const |
Returns the upper bound. |
| Getter | constexpr int32_t step() const |
Returns the step size. |
| Constraint | constexpr int32_t clamp(int32_t value) const |
Clamps a value to the closed interval [minimum, maximum]. |
| State query | constexpr bool canIncrement(int32_t value) const |
Reports whether the clamped value is below the upper bound. |
| State query | constexpr bool canDecrement(int32_t value) const |
Reports whether the clamped value is above the lower bound. |
| Arithmetic | constexpr int32_t incremented(int32_t value) const |
Adds one step with overflow protection and upper-bound saturation. |
| Arithmetic | constexpr int32_t decremented(int32_t value) const |
Subtracts one step with overflow protection and lower-bound saturation. |
| Free function | constexpr uint32_t normalizeToExtent(const NumericRange& range, int32_t value, uint32_t extent) |
Maps the value’s position in the range to [0, extent] with nearest-integer rounding. |
clamp(), canIncrement(), canDecrement(), incremented(), and decremented() are saturating. An uneven final step lands directly on the boundary. normalizeToExtent(range, value, pixels) maps a clamped value to an integer pixel extent with nearest-integer rounding. These operations are safe across the full INT32_MIN to INT32_MAX range.
tryCreate() returns false for minimum > maximum or step <= 0. Check the result before retaining or passing the range.
Formatting
NumericFormatter formats the value supplied to each call. Built-in policies cover integers, zero padding, scaled integers, suffixes, and percentages:
1 | IntegerFormat padded{3, nullptr}; |
Formatting is allocation-free. format() returns false when the formatter is invalid or the destination is too small; a non-empty destination is reset to an empty string on failure. Use FixedBufferWriter::appendInteger() to compose text such as current/total.
The formatter stores only a function pointer and a non-owning context pointer. Every referenced format object, suffix string, percentage range, or custom context must outlive all calls through that formatter. A local formatter is safe for immediate formatting; a formatter retained by a Widget or queued Popup must refer to static storage or persistent App members.
Declare retained dependencies before their formatter so reverse member destruction keeps them alive:
1 | NumericRange temperatureRange_{}; |
Formatter API
| Module / class | Signature | Description |
|---|---|---|
FixedBufferWriter |
FixedBufferWriter(char* buffer, size_t capacity) |
Binds an externally owned fixed buffer and its total capacity. |
bool append(const char* text) |
Appends a null-terminated string. Returns false and records failure when capacity is insufficient. |
|
bool appendCharacter(char character) |
Appends one character. | |
bool appendInteger(int32_t value, uint8_t minimumDigits = 1U) |
Appends a signed 32-bit integer with optional leading-zero padding. | |
bool appendUnsigned(uint32_t value, uint8_t minimumDigits = 1U) |
Appends an unsigned 32-bit integer with optional leading-zero padding. | |
bool finish() |
Writes the terminating \0 and returns true when the complete operation succeeded. |
|
bool valid() const |
Reports whether all writes have remained within the buffer. | |
size_t size() const |
Returns the number of written characters, excluding the terminating \0. |
|
NumericFormatter |
static constexpr NumericFormatter custom(const void* context, FormatFunction function) |
Creates a formatter from a context pointer and formatting function. |
static constexpr NumericFormatter integer() |
Creates the default integer formatter. | |
static constexpr NumericFormatter integer(const IntegerFormat& format) |
Creates an integer formatter from the supplied configuration. | |
static constexpr NumericFormatter scaled(const ScaledIntegerFormat& format) |
Creates a fixed-point formatter with scale and fractional digits. | |
static constexpr NumericFormatter percentage(const PercentageFormat& format) |
Creates a percentage formatter based on a NumericRange. |
|
bool format(int32_t value, char* buffer, size_t bufferSize) const |
Formats value into the destination buffer. |
|
constexpr bool valid() const |
Reports whether a formatting function is bound. | |
constexpr const void* context() const |
Returns the bound context pointer. | |
constexpr FormatFunction function() const |
Returns the bound formatting function. |
Format configuration
| Structure | Field | Type | Default | Description |
|---|---|---|---|---|
IntegerFormat |
minimumDigits |
uint8_t |
1U |
Minimum digit count, padded with leading zeros. |
suffix |
const char* |
nullptr |
Optional suffix such as "px" or "ms". |
|
ScaledIntegerFormat |
scale |
uint32_t |
1U |
Scale factor; for example, 100 formats 1234 as 12.34. |
fractionalDigits |
uint8_t |
0U |
Number of fractional digits. | |
minimumIntegerDigits |
uint8_t |
1U |
Minimum integer-part digit count, padded with leading zeros. | |
suffix |
const char* |
nullptr |
Optional suffix. | |
PercentageFormat |
range |
const NumericRange* |
nullptr |
Range used for percentage normalization. |
suffix |
const char* |
"%" |
Percentage suffix. |
Binding and edit session
ValueEditorBinding defines a non-owning read, write, and notification boundary. ValueEditSession stores the transaction’s original value, draft value, and editing policy.
1 | static void changed(void* context, int32_t value) { |
With CommitOnConfirm, draft changes remain inside the session until commit() writes and notifies; cancel() discards the draft. With Live, each successful setDraftValue() writes and notifies immediately; cancel() restores the original value and notifies that restoration. A session constructed from an initial integer has no external binding but follows the same draft/commit/cancel path.
| Operation | CommitOnConfirm |
Live |
|---|---|---|
setDraftValue(value) |
Update only the draft | Write, notify, then update the draft |
commit() |
Write and notify if changed; make draft the new original | Make the current draft the new original |
cancel() |
Discard the draft | Restore and notify the original value if changed |
All three operations return false when the session is invalid or a required write fails. A failed write preserves the current transaction state; the caller should keep the editor open or restore its visible controls from draftValue().
Binding value and changed contexts are non-owning and must outlive the session and every operation performed through it. A Popup request that copies the binding extends this requirement through both its pending and active lifetime.
Scaled integer formatting function
| Signature | Description |
|---|---|
bool formatScaledInteger(char* buffer, size_t bufferSize, int32_t raw, uint32_t scale, uint8_t fractionalDigits, const char* suffix = nullptr) |
Formats the fixed-point value raw with the supplied scale, fractional digit count, and optional suffix. |
PixelUIValue::Binding API
| Signature | Description |
|---|---|
constexpr Binding() |
Creates an empty binding. |
static constexpr Binding custom(const void* object, FormatFunction formatter, const char* suffix = nullptr) |
Binds an object pointer, custom formatter, and optional suffix. |
static constexpr Binding integer(const int32_t& value, const char* suffix = nullptr) |
Binds an int32_t value for integer formatting. |
template <uint8_t FractionalDigits, int32_t Scale> static constexpr Binding decimal(const ScaledInt32<Scale>& value, const char* suffix = nullptr) |
Binds a ScaledInt32<Scale> value with up to nine fractional digits. |
bool format(char* buffer, size_t bufferSize) const |
Formats the bound value into buffer; failures clear a non-empty destination and return false. |
constexpr const void* object() const |
Returns the bound object pointer. |
constexpr FormatFunction formatter() const |
Returns the formatting function. |
constexpr const char* suffix() const |
Returns the suffix pointer. |
Component examples
NumScrollusesNumericRangefor stepping andNumericFormatterfor labels. Configure it withsetRange(min, max, step)orsetRange(range), followed bysetFormatter(formatter). Configure zero padding through the formatter.PopupProgressmaps LEFT/RIGHT throughrange.step(), normalizes only the bar geometry, and delegates displayed text to the formatter.PopupValueDigitsuses aValueEditSession; construction leaves the external value unchanged. SELECT on a digit finishes that digit’s local edit while keeping the session open for other digits. The OK button commits the whole session; CANCEL or BACK cancels it.



