openpine_vm/visuals/
table.rs

1use serde::{Deserialize, Serialize};
2
3use crate::visuals::{Color, FontFamily, HorizontalAlign, Position, TextFormatting, VerticalAlign};
4
5/// A single cell in a [`Table`].
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct TableCell {
8    /// Cell text.
9    pub text: String,
10    /// Cell width.
11    pub width: f32,
12    /// Cell height.
13    pub height: f32,
14    /// Text color.
15    pub text_color: Option<Color>,
16    /// Horizontal text alignment.
17    pub text_halign: HorizontalAlign,
18    /// Vertical text alignment.
19    pub text_valign: VerticalAlign,
20    /// Text size in points.
21    pub text_size: u32,
22    /// Cell background color.
23    pub background_color: Option<Color>,
24    /// Optional tooltip shown on hover.
25    pub tooltip: Option<String>,
26    /// Font family used to render [`Self::text`].
27    pub text_font_family: FontFamily,
28    /// Text formatting (e.g. bold/italic).
29    pub text_formatting: TextFormatting,
30    /// Number of columns spanned by this cell.
31    pub colspan: usize,
32    /// Number of rows spanned by this cell.
33    pub rowspan: usize,
34}
35
36/// A table visual primitive.
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct Table {
39    /// Table anchor position on the chart.
40    pub position: Position,
41    pub(crate) num_columns: usize,
42    pub(crate) cells: Vec<TableCell>,
43    /// Table background color.
44    pub background_color: Option<Color>,
45    /// Table frame color.
46    pub frame_color: Option<Color>,
47    /// Table frame width in pixels.
48    pub frame_width: i32,
49    /// Table border color.
50    pub border_color: Option<Color>,
51    /// Table border width in pixels.
52    pub border_width: i32,
53    /// Whether to force drawing on the chart overlay.
54    pub force_overlay: bool,
55}
56
57impl Table {
58    /// Returns the number of columns.
59    #[inline]
60    pub fn num_columns(&self) -> usize {
61        self.num_columns
62    }
63
64    /// Returns the number of rows.
65    #[inline]
66    pub fn num_rows(&self) -> usize {
67        if self.num_columns == 0 {
68            0
69        } else {
70            self.cells.len() / self.num_columns
71        }
72    }
73
74    /// Returns a reference to the cell at `row`/`col`.
75    #[inline]
76    pub fn cell(&self, row: usize, col: usize) -> &TableCell {
77        &self.cells[(row * self.num_columns) + col]
78    }
79
80    /// Returns the cell at `row`/`col`, or `None` if out of bounds.
81    #[inline]
82    pub fn cell_opt(&self, row: usize, col: usize) -> Option<&TableCell> {
83        if col >= self.num_columns {
84            return None;
85        }
86        let idx = (row * self.num_columns) + col;
87        self.cells.get(idx)
88    }
89
90    #[inline]
91    pub(crate) fn cell_mut(&mut self, row: usize, col: usize) -> &mut TableCell {
92        &mut self.cells[row * self.num_columns + col]
93    }
94}