Numeric Values / 通用数值工具

数值显示格式和组件绘制在 UI 框架中是分立的。

你可以使用下面所列举的 UI 框架里提供的一些数值有关 API 来轻松完成与数值显示有关的任务。

范围与归一化 Numeric Range

1
2
3
4
NumericRange range;
if (!NumericRange::tryCreate(-40, 120, 5, range)) {
// minimum > maximum,或 step <= 0
}
函数 / API 类型 API 签名 作用说明
构造函数 constexpr NumericRange() 创建默认区间对象(范围 [0, 100],步长 1)。
静态工厂 static constexpr bool tryCreate(int32_t minimum, int32_t maximum, int32_t step, NumericRange& output) 校验参数($min \le max$ 且 $step > 0$),成功则写入 output 并返回 true,失败返回 false
Getter constexpr int32_t minimum() const 获取区间的下限值(minimum_)。
Getter constexpr int32_t maximum() const 获取区间的上限值(maximum_)。
Getter constexpr int32_t step() const 获取区间的变化步长(step_)。
数值约束 constexpr int32_t clamp(int32_t value) const 将输入数值强制限制在 $[minimum, maximum]$ 闭区间内。
状态检查 constexpr bool canIncrement(int32_t value) const 检查 value(经 clamp 后)是否小于上限(能否继续递增)。
状态检查 constexpr bool canDecrement(int32_t value) const 检查 value(经 clamp 后)是否大于下限(能否继续递减)。
数值运算 constexpr int32_t incremented(int32_t value) const 计算 value 增加一个步长后的值,防溢出且最高不超过上限。
数值运算 constexpr int32_t decremented(int32_t value) const 计算 value 减少一个步长后的值,防溢出且最低不低于下限。
全局函数 constexpr uint32_t normalizeToExtent(const NumericRange& range, int32_t value, uint32_t extent) valuerange 中的位置,四舍五入线性映射到 $[0, extent]$ 区间。

clamp()canIncrement()canDecrement()incremented()decremented() 都采用饱和语义。step 不能整除范围时直接落到边界。normalizeToExtent(range, value, pixels) 把 clamp 后的值映射为整数像素长度,舍入规则是最接近整数。

tryCreate()minimum > maximumstep <= 0 时返回 false

数据格式化

NumericFormatter 格式化调用时传入的值,内置策略包括普通整数、补零、缩放整数、后缀和百分比:

1
2
3
4
5
6
7
8
IntegerFormat padded{3, nullptr};
NumericFormatter digits = NumericFormatter::integer(padded); // -7 -> "-007"

ScaledIntegerFormat volts{10, 1, 1, " V"};
NumericFormatter voltage = NumericFormatter::scaled(volts); // -7 -> "-0.7 V"

PercentageFormat percentage{&range, "%"};
NumericFormatter percent = NumericFormatter::percentage(percentage);

格式化过程不动态分配内存。Formatter 无效或目标缓冲区不足时,format() 返回 false;只要缓冲区非空,失败后首字节会被置为 \0。拼接 current/total 这类文本时使用 FixedBufferWriter::appendInteger(),不要另写一套整数转换。

Formatter 只保存函数指针和非拥有 context 指针。它引用的 format 配置、suffix 字符串、百分比 range 或自定义 context,必须比所有 format() 调用活得更久。局部 Formatter 可用于立即格式化;被 Widget 保存或随 Popup 排队的 Formatter 必须引用静态存储或持久的 App 成员。

持久依赖应声明在 Formatter 之前,确保成员按反向顺序析构时依赖仍然有效:

1
2
3
4
NumericRange temperatureRange_{};
ScaledIntegerFormat temperatureFormat_{10, 1, 1, " C"};
NumericFormatter temperatureFormatter_ =
NumericFormatter::scaled(temperatureFormat_);

1. API 接口汇总表(静态工厂与成员函数)

模块 / 类 接口签名 作用说明
FixedBufferWriter FixedBufferWriter(char* buffer, size_t capacity) 构造函数。绑定外部固定缓冲区与总容量(不持有内存所有权)。
bool append(const char* text) 追加以 \0 结尾的字符串。空间不足则标记失败并返回 false
bool appendCharacter(char character) 追加单个字符。
bool appendInteger(int32_t value, uint8_t minimumDigits = 1U) 追加有符号 32 位整数,支持设置最少数字位数(前导零补齐)。
bool appendUnsigned(uint32_t value, uint8_t minimumDigits = 1U) 追加无符号 32 位整数,支持设置最少数字位数(前导零补齐)。
bool finish() 写入字符串结束符 \0 封口。若成功且未溢出则返回 true
bool valid() const 检查写入器当前状态是否合法(未发生溢出或越界错误)。
size_t size() const 获取当前已写入的字符数(不包含封口符 \0)。
NumericFormatter static constexpr NumericFormatter custom(const void* context, FormatFunction function) 静态工厂。创建自定义格式化器,传入自定义上下文与格式化函数指针。
static constexpr NumericFormatter integer() 静态工厂。创建默认整数格式化器(无后缀,无前导零)。
static constexpr NumericFormatter integer(const IntegerFormat& format) 静态工厂。创建带参数配置的整数格式化器。
static constexpr NumericFormatter scaled(const ScaledIntegerFormat& format) 静态工厂。创建带缩放因子与小数位的定点数格式化器。
static constexpr NumericFormatter percentage(const PercentageFormat& format) 静态工厂。基于 NumericRange 计算百分比的格式化器。
bool format(int32_t value, char* buffer, size_t bufferSize) const 执行格式化。将 value 格式化并写入到目标 buffer 中。
constexpr bool valid() const 检查格式化器是否有效(即是否绑定了合法的格式化函数)。
constexpr const void* context() const 获取当前绑定的上下文指针。
constexpr FormatFunction function() const 获取当前绑定的格式化函数指针。

2. 配置结构体字段

结构体 成员字段 数据类型 默认值 作用说明
IntegerFormat minimumDigits uint8_t 1U 最少数字位数(不足时自动补前导零)。
suffix const char* nullptr 后缀字符串(如 "px", "ms")。
ScaledIntegerFormat scale uint32_t 1U 缩放比例因子(如 100 表示将 1234 格式化为 12.34)。
fractionalDigits uint8_t 0U 保留的小位数。
minimumIntegerDigits uint8_t 1U 整数部分的最少位数(前导零补齐)。
suffix const char* nullptr 后缀字符串。
PercentageFormat range const NumericRange* nullptr 指向区间对象的指针,用于归一化计算百分比。
suffix const char* "%" 百分比后缀。

数值 Binding 与编辑事务

ValueEditorBinding 非拥有的定义 read/write/notify 边界。

ValueEditSession 才保存 original value、draft value 和编辑策略。

1
2
3
4
5
6
7
static void changed(void* context, int32_t value) {
static_cast<Settings*>(context)->brightness = value;
}

ValueEditorBinding binding =
ValueEditorBinding::reference(brightness_, &changed, this);
ValueEditSession edit(binding, ValueEditPolicy::CommitOnConfirm);

CommitOnConfirm 下,draft 只存在 Session 中;commit() 才写回并通知,cancel() 直接丢弃 draft。Live 下,每次成功的 setDraftValue() 都立即写回并通知;cancel() 会恢复 original value,并通知这次恢复。只用初始整数构造的 Session 没有外部 Binding,但仍走相同的 draft/commit/cancel 路径。

操作 CommitOnConfirm Live
setDraftValue(value) 只更新 draft 先写回、通知,再更新 draft
commit() 值有变化时写回并通知;把 draft 设为新的 original 把当前 draft 设为新的 original
cancel() 丢弃 draft 值有变化时恢复并通知 original value

Session 无效或必要写入失败时,这三个操作都会返回 false。写入失败不会推进事务状态;调用者应保持编辑器打开,或用 draftValue() 恢复可见控件。

Binding 的 value context 和 changed context 都是非拥有的,必须覆盖 Session 及其全部操作的寿命。Popup 请求复制 Binding 后,这项要求会延长到 pending 排队期和 active 显示期全部结束。

1. Namespace Function

接口签名 作用说明
bool formatScaledInteger(char* buffer, size_t bufferSize, int32_t raw, uint32_t scale, uint8_t fractionalDigits, const char* suffix = nullptr) 底层格式化工具函数。将定点数原始值 raw 结合 scale 缩放因子格式化为带指定小数位数(fractionalDigits)和可选后缀(suffix)的字符串,写入指定缓冲区。

2. API 接口 (PixelUIValue::Binding 静态工厂与成员函数)

接口签名 作用说明
constexpr Binding() 默认构造函数。创建一个空绑定对象(未关联数据对象与格式化函数)。
static constexpr Binding custom(const void* object, FormatFunction formatter, const char* suffix = nullptr) 静态工厂。创建自定义绑定对象,显式传入绑定的对象指针、自定义格式化函数及可选后缀。
static constexpr Binding integer(const int32_t& value, const char* suffix = nullptr) 静态工厂。绑定一个 int32_t 变量引用,生成以整数形式格式化该变量的绑定对象。
template <uint8_t FractionalDigits, int32_t Scale> static constexpr Binding decimal(const ScaledInt32<Scale>& value, const char* suffix = nullptr) 静态工厂模板。绑定一个 ScaledInt32<Scale> 定点数变量引用,生成带指定小数位数(FractionalDigits <= 9)的格式化绑定对象。
bool format(char* buffer, size_t bufferSize) const 执行格式化。调用绑定的格式化函数将关联数据格式化至 buffer。若失败或无效,自动清空缓冲区(置 \0)并返回 false
constexpr const void* object() const Getter。获取绑定的目标对象指针(object_)。
constexpr FormatFunction formatter() const Getter。获取绑定的格式化函数指针(formatter_)。
constexpr const char* suffix() const Getter。获取绑定的后缀字符串指针(suffix_)。

组件中有对这些功能的利用,可作为示例学习

  • NumScrollNumericRange 步进,用 NumericFormatter 生成文字。使用 setRange(min, max, step)setRange(range),再用 setFormatter(formatter) 配置显示。
  • PopupProgress 的 LEFT/RIGHT 使用 range.step(),进度条几何单独做整数归一化,显示文字完全由 Formatter 决定。
  • PopupValueDigits 使用 ValueEditSession;构造不会修改外部值。数字位上的 SELECT 只结束该位的局部编辑,之后仍可修改其他位。OK 提交整个 Session;CANCEL 或 BACK 取消。