Skip to content

標注

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_annotationbring_selected_annotation_to_frontsend_selected_annotation_to_backtoggle_selected_annotation_lockcopy_selected_annotationcut_selected_annotationselected_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_INDEX0b0001該點的 X 軸(柱索引/時間)固定,隱藏柱索引輸入框。
LOCK_PRICE0b0010該點的 Y 軸(價格)固定,隱藏價格輸入框。
FOLLOW_FIRST_BAR_INDEX0b0100繪製時,該點繼承第一個控制點的 X 值。
FOLLOW_FIRST_PRICE0b1000繪製時,該點繼承第一個控制點的 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

基於 MIT 許可證發佈。