标注
AnnotationManagement trait 提供了对标注(趋势线、形状、文本标签、斐波那契工具等)进行编程式增删改查的接口,适用于任意图表视图。ChartView 实现了此 trait,标注管理代码可与任意图表视图复用。
导入
rust
use navi_chart::{
ChartView, AnnotationManagement, SystemAnnotationManagement,`n AnnotationSpec, AnnotationFlags, AnnotationKind, AnnotationPane, ControlPoint,
Stroke, Color, LineStyle, ExtendMode,
};用法
rust
use navi_chart::{AnnotationManagement, AnnotationSpec, AnnotationId};
fn add_trend_line<C>(cv: &C, t1: i64, p1: f64, t2: i64, p2: f64) -> AnnotationId
where
C: AnnotationManagement,
{
cv.add_annotation(AnnotationSpec {
kind: AnnotationKind::TrendLine {
extend: ExtendMode::None,
stroke: Stroke {
color: Color::from_rgba(41, 98, 255, 255),
width: 2.0,
style: LineStyle::Solid,
},
text: String::new(),
},
points: vec![
ControlPoint { time: t1, price: p1 },
ControlPoint { time: t2, price: p2 },
],
pane: AnnotationPane::Main,
flags: AnnotationFlags::default(), // VISIBLE | SELECTABLE,未锁定
})
}
// 两种视图类型均可使用:
let id = add_trend_line(&local_cv, t1, 150.0, t2, 165.0);
let id = add_trend_line(&remote_cv, t1, 150.0, t2, 165.0);方法参考
| 方法 | 说明 |
|---|---|
add_annotation(spec) | 添加新标注。立即重新渲染并推送 AnnotationCreated。返回稳定的非零 AnnotationId。 |
update_annotation(id, spec) | 替换已有标注的完整 spec。重新渲染并推送 AnnotationUpdated。 |
remove_annotation(id) | 按 id 移除标注。重新渲染并推送 AnnotationDeleted。 |
clear_annotations() | 移除所有标注。为每个标注推送 AnnotationDeleted。 |
annotation(id) | 按 id 返回标注引用,不存在则返回 None。 |
annotations() | 按 Z 轴顺序(从后到前)返回所有标注。 |
annotation_properties(id) | 返回标注的属性描述符列表,已按图表当前语言本地化。可用于构建样式工具栏或属性面板。标注 id 不存在时返回 None。 |
get_annotation_property(id, name) | 按路径名称读取单个属性(如 "stroke.color"、"stroke.width")。id 不存在则返回 None。 |
set_annotation_property(id, name, value) | 写入单个属性。对 VIRTUAL 属性(如 ParallelChannel 上的 "colorAll"),写入会扇出到所有底层字段。立即重新渲染。id、属性名或值类型无效时返回 Err(ChartPropertyError)——详见下方错误说明。 |
delete_selected_annotation() | 删除当前选中的标注。无选中时为空操作。推送 AnnotationDeleted。 |
bring_selected_annotation_to_front() | 将选中标注移至 Z 轴顶层。无选中时为空操作。 |
send_selected_annotation_to_back() | 将选中标注移至 Z 轴底层。无选中时为空操作。 |
toggle_selected_annotation_lock() | 切换选中标注的 locked 标志。已锁定的标注不能被用户移动或编辑。无选中时为空操作。 |
copy_selected_annotation() | 将选中标注复制到图表内部剪贴板。无选中时为空操作。 |
cut_selected_annotation() | 将选中标注复制到剪贴板后删除它。无选中时为空操作。 |
paste_annotation() | 将剪贴板中的标注粘贴为新标注(位置略有偏移)。推送 AnnotationCreated。剪贴板为空时为空操作。 |
has_clipboard_annotation() | 剪贴板中存在已复制的标注则返回 true。 |
selected_annotation_bounds() | 返回选中标注在画布像素坐标中的边界框,可用于定位浮动工具栏。无选中时返回 None。 |
selected_annotation_is_highlighter() | 选中标注为 Highlighter 笔刷时返回 true,可据此显示高亮专属工具栏。 |
dispatch_context_menu_action(action) | 对选中标注执行上下文菜单操作字符串(如 "delete"、"lock"、"bring-to-front"、"send-to-back"、"copy"、"cut"、"paste")。在用户从 context_menu_items(pos) 填充的菜单中选择项目后调用。 |
annotation_control_point_flags(id) | 按顺序返回标注 id 每个控制点的 ControlPointFlags,不存在时返回 None。构建坐标编辑 Tab 时,可根据这些标志确定哪些坐标轴被锁定。 |
set_annotation_default(tool_id, kind) | 为指定绘图工具保存每工具样式默认值。下次通过绘图流程创建该工具的标注时,将使用这些属性而非出厂默认值。 |
reset_annotation_to_default(id) | 将标注的样式属性重置为出厂默认值,并清除该工具已保存的每工具默认值。推送 AnnotationUpdated 并重新渲染。 |
关于选择相关方法的说明
delete_selected_annotation、bring_selected_annotation_to_front、send_selected_annotation_to_back、toggle_selected_annotation_lock、copy_selected_annotation、cut_selected_annotation 和 selected_annotation_bounds 均作用于当前选中的标注。无选中时均为空操作,可从工具栏按钮中无条件调用。
set_annotation_property 的错误情况
set_annotation_property 在以下情况返回 Err(ChartPropertyError):
- 标注 id 不存在。
- 该标注类型不存在该属性名称。
- 值的类型与属性类型不匹配。
示例:属性工具栏
rust
use navi_chart::{AnnotationManagement, ChartInteraction, PropertyValue, Color};
fn apply_color_from_toolbar<C>(cv: &C, color: Color)
where
C: AnnotationManagement + ChartInteraction,
{
if let Some(ChartElement::Annotation(id)) = cv.selection() {
// 优先尝试虚拟属性(扇出到所有描边)
let _ = cv.set_annotation_property(id, "colorAll", PropertyValue::Color(color))
.or_else(|_| cv.set_annotation_property(id, "stroke.color", PropertyValue::Color(color)));
}
}示例:持久化往返
rust
use navi_chart::{AnnotationManagement, Annotation, AnnotationSpec};
fn save_annotations<C>(cv: &C) -> String
where
C: AnnotationManagement,
{
let annotations: Vec<Annotation> = cv.annotations();
serde_json::to_string(&annotations).unwrap()
}
fn restore_annotations<C>(cv: &C, json: &str)
where
C: AnnotationManagement,
{
let saved: Vec<Annotation> = serde_json::from_str(json).unwrap();
cv.clear_annotations();
for ann in saved {
cv.add_annotation(ann.spec);
}
}ControlPointFlags
annotation_control_point_flags(id) 按顺序返回标注每个控制点的 ControlPointFlags。构建坐标编辑 Tab 时,可根据这些标志确定哪些轴向输入框需要隐藏。
| 标志 | 位值 | 含义 |
|---|---|---|
LOCK_BAR_INDEX | 0b0001 | 该点的 X 轴(柱索引/时间)固定,隐藏柱索引输入框。 |
LOCK_PRICE | 0b0010 | 该点的 Y 轴(价格)固定,隐藏价格输入框。 |
FOLLOW_FIRST_BAR_INDEX | 0b0100 | 绘制时,该点继承第一个控制点的 X 值。 |
FOLLOW_FIRST_PRICE | 0b1000 | 绘制时,该点继承第一个控制点的 Y 值。 |
rust
use navi_chart::{AnnotationManagement, annotation::ControlPointFlags};
fn build_coordinates_tab<C: AnnotationManagement>(cv: &C, id: AnnotationId) {
let annotation = cv.annotation(id).unwrap();
let flags_per_point = cv.annotation_control_point_flags(id).unwrap_or_default();
for (i, point) in annotation.spec.points.iter().enumerate() {
let flags = flags_per_point.get(i).copied().unwrap_or_default();
if !flags.contains(ControlPointFlags::LOCK_BAR_INDEX) {
render_bar_index_input(i, point.time);
}
if !flags.contains(ControlPointFlags::LOCK_PRICE) {
render_price_input(i, point.price);
}
}
}AnnotationKind 变体完整列表、AnnotationSpec 结构、PropertyDescriptor 字段和样式子结构的详细说明,请参阅 ChartView。