1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
use rvariant::Variant;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum CellKind {
/// Column is stored and processed by backend in a defined data structure.
/// Renaming, changing type and removing is not permitted.
Static(StaticCellKind),
/// Type, name, description and other parameters are stored globally and can be reused.
/// Global parameter's name and type can be changed through other tool, but not from TableViewer's.
/// Can be removed.
Global,
/// Column exists only in the context of a particular table, even if it's name is the same.
/// Name and type can be freely changed. Can be removed.
Adhoc,
// needed?
// Calculated with an expression from other cells around
}
impl CellKind {
pub const GLOBAL_DOC: &'static str = "Global parameter, can be used everywhere, same type is enforced\nand you can add short names and other metadata";
pub const ADHOC_DOC: &'static str =
"Adhoc parameter, can be removed or edited without any side-effects";
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum StaticCellKind {
/// Column's cells simply store data with a specified type.
Plain,
/// Changing cell value will cause some other cells to change as well.
/// e.g. kind column that chooses what parameters are available or not.
/// Must be soft-committed? in online mode even if local edit mode is enabled, in order to receive
/// updated cells types / values.
CausesSideEffects,
/// Cells values are auto generated by backend, thus they are also read only.
AutoGenerated,
}
impl StaticCellKind {
pub const PLAIN_DOC: &'static str =
"Parameter stored in a proper data structure and processed by the system";
pub const CAUSES_SIDE_EFFECTS_DOC: &'static str =
"Changing this parameter will cause others to recalculate\nor cause other side effects";
pub const AUTO_GENERATED_DOC: &'static str =
"This columns is not actually stored, but calculated from other local or global data";
}
/// row, col
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CellCoord(pub u32, pub u32);
pub enum TableCellRef<'a> {
Never,
Empty,
Available {
value: &'a Variant,
/// true if cell contains uncommitted data
is_dirty: bool,
/// Cell was modified locally and then remotely as well
in_conflict: bool,
},
}
impl<'a> TableCellRef<'a> {
pub fn get_ref(&self) -> Option<&Variant> {
if let TableCellRef::Available { value, .. } = self {
Some(value)
} else {
None
}
}
pub fn get_if_str(&self) -> Option<&str> {
if let TableCellRef::Available { value, .. } = self {
if let Variant::Str(s) = value {
Some(s.as_str())
} else {
None
}
} else {
None
}
}
pub fn get_if_string(&self) -> Option<String> {
if let TableCellRef::Available { value, .. } = self {
if let Variant::Str(s) = value {
Some(s.clone())
} else {
None
}
} else {
None
}
}
pub fn get_if_u32(&self) -> Option<u32> {
if let TableCellRef::Available { value, .. } = self {
if let Variant::U32(x) = value {
Some(*x)
} else {
None
}
} else {
None
}
}
pub fn get_if_enum(&self, enum_uid: u32) -> Option<u32> {
if let TableCellRef::Available { value, .. } = self {
if let Variant::Enum {
enum_uid: uid,
discriminant,
} = value
{
if *uid == enum_uid {
Some(*discriminant)
} else {
None
}
} else {
None
}
} else {
None
}
}
pub fn is_empty(&self) -> bool {
matches!(self, TableCellRef::Empty)
}
}
pub enum TableCell {
Never,
Available {
value: Variant,
/// true if cell contains uncommitted data
is_dirty: bool,
/// Cell was modified locally and then remotely as well
in_conflict: bool,
},
}
impl TableCell {
pub fn new(value: Variant) -> Self {
TableCell::Available {
value,
is_dirty: false,
in_conflict: false,
}
}
pub fn as_ref(&self) -> TableCellRef {
match self {
TableCell::Never => TableCellRef::Never,
TableCell::Available {
value,
is_dirty,
in_conflict,
} => TableCellRef::Available {
value: &value,
is_dirty: *is_dirty,
in_conflict: *in_conflict,
},
}
}
}