libsurfer/
tooltips.rs

1use egui::{Response, Ui};
2use egui_extras::{Column, TableBuilder};
3use ftr_parser::types::Transaction;
4
5use crate::{
6    transaction_container::{TransactionRef, TransactionStreamRef},
7    wave_container::{ScopeRef, VariableMeta, VariableRef, VariableRefExt},
8    wave_data::WaveData,
9};
10
11pub fn variable_tooltip_text(meta: &Option<VariableMeta>, variable: &VariableRef) -> String {
12    if let Some(meta) = meta {
13        format!(
14            "{}\nNum bits: {}\nType: {}\nDirection: {}",
15            variable.full_path_string(),
16            meta.num_bits
17                .map_or_else(|| "unknown".to_string(), |bits| bits.to_string()),
18            meta.variable_type_name
19                .clone()
20                .or_else(|| meta.variable_type.map(|t| t.to_string()))
21                .unwrap_or_else(|| "unknown".to_string()),
22            meta.direction
23                .map_or_else(|| "unknown".to_string(), |direction| format!("{direction}"))
24        )
25    } else {
26        variable.full_path_string()
27    }
28}
29
30pub fn scope_tooltip_text(wave: &WaveData, scope: &ScopeRef) -> String {
31    let other = wave.inner.as_waves().unwrap().get_scope_tooltip_data(scope);
32    if other.is_empty() {
33        format!("{scope}")
34    } else {
35        format!("{scope}\n{other}")
36    }
37}
38
39pub fn handle_transaction_tooltip(
40    response: Response,
41    waves: &WaveData,
42    gen_ref: &TransactionStreamRef,
43    tx_ref: &TransactionRef,
44) -> Response {
45    response
46        .on_hover_ui(|ui| {
47            let tx = waves
48                .inner
49                .as_transactions()
50                .unwrap()
51                .get_generator(gen_ref.gen_id.unwrap())
52                .unwrap()
53                .transactions
54                .iter()
55                .find(|transaction| transaction.get_tx_id() == tx_ref.id)
56                .unwrap();
57
58            ui.set_max_width(ui.spacing().tooltip_width);
59            ui.add(egui::Label::new(transaction_tooltip_text(waves, tx)));
60        })
61        .on_hover_ui(|ui| {
62            // Seemingly a bit redundant to determine tx twice, but since the
63            // alternative is to do it every frame for every transaction, this
64            // is most likely still a better approach.
65            // Feel free to use some Rust magic to only do it once though...
66            let tx = waves
67                .inner
68                .as_transactions()
69                .unwrap()
70                .get_generator(gen_ref.gen_id.unwrap())
71                .unwrap()
72                .transactions
73                .iter()
74                .find(|transaction| transaction.get_tx_id() == tx_ref.id)
75                .unwrap();
76
77            transaction_tooltip_table(ui, tx)
78        })
79}
80
81fn transaction_tooltip_text(waves: &WaveData, tx: &Transaction) -> String {
82    let time_scale = waves.inner.as_transactions().unwrap().inner.time_scale;
83
84    format!(
85        "tx#{}: {}{} - {}{}\nType: {}",
86        tx.event.tx_id,
87        tx.event.start_time,
88        time_scale,
89        tx.event.end_time,
90        time_scale,
91        waves
92            .inner
93            .as_transactions()
94            .unwrap()
95            .get_generator(tx.get_gen_id())
96            .unwrap()
97            .name
98            .clone(),
99    )
100}
101
102fn transaction_tooltip_table(ui: &mut Ui, tx: &Transaction) {
103    TableBuilder::new(ui)
104        .column(Column::exact(80.))
105        .column(Column::exact(80.))
106        .header(20.0, |mut header| {
107            header.col(|ui| {
108                ui.heading("Attribute");
109            });
110            header.col(|ui| {
111                ui.heading("Value");
112            });
113        })
114        .body(|body| {
115            let total_rows = tx.attributes.len();
116            let attributes = &tx.attributes;
117            body.rows(15., total_rows, |mut row| {
118                let attribute = attributes.get(row.index()).unwrap();
119                row.col(|ui| {
120                    ui.label(attribute.name.clone());
121                });
122                row.col(|ui| {
123                    ui.label(attribute.value());
124                });
125            });
126        });
127}