標注
AnnotationManagement trait 提供了對標注(趨勢線、形狀、文本標籤、斐波那契工具等)進行編程式增刪改查的接口,適用於任意圖表視圖。ChartView 實現了此 trait,標注管理代碼可與任意圖表視圖復用。
導入
rust
use navi_chart::{
ChartView, AnnotationManagement,
AnnotationSpec, 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。