pub struct EventKind(pub u64);Expand description
Bitflags describing the categories an event belongs to.
A single PlotEvent may have several bits set. For example a
“click that set a measurement point” would have both CLICK and
MEASUREMENT_POINT set.
Tuple Fields§
§0: u64Implementations§
Source§impl EventKind
impl EventKind
Sourcepub const DOUBLE_CLICK: Self
pub const DOUBLE_CLICK: Self
A double-click on a scope plot (the second click is also a CLICK).
Sourcepub const CLICK_ON_TRACE: Self
pub const CLICK_ON_TRACE: Self
A click that landed on (or snapped to) a specific curve/trace.
Sourcepub const MEASUREMENT_POINT: Self
pub const MEASUREMENT_POINT: Self
A measurement marker point was set (P1 or P2).
Sourcepub const MEASUREMENT_COMPLETE: Self
pub const MEASUREMENT_COMPLETE: Self
A full measurement (both P1 and P2) is now available.
Sourcepub const MEASUREMENT_CLEARED: Self
pub const MEASUREMENT_CLEARED: Self
A measurement was cleared.
Sourcepub const TRACE_SHOWN: Self
pub const TRACE_SHOWN: Self
A trace was shown.
Sourcepub const TRACE_HIDDEN: Self
pub const TRACE_HIDDEN: Self
A trace was hidden.
Sourcepub const TRACE_COLOR_CHANGED: Self
pub const TRACE_COLOR_CHANGED: Self
A trace colour was changed.
Sourcepub const MATH_TRACE_ADDED: Self
pub const MATH_TRACE_ADDED: Self
A math trace was added.
Sourcepub const MATH_TRACE_REMOVED: Self
pub const MATH_TRACE_REMOVED: Self
A math trace was removed.
Sourcepub const FIT_TO_VIEW: Self
pub const FIT_TO_VIEW: Self
The view was fit-to-data (auto-fit or button).
Sourcepub const DATA_UPDATED: Self
pub const DATA_UPDATED: Self
New data points were received for one or more traces.
Sourcepub const DATA_CLEARED: Self
pub const DATA_CLEARED: Self
All trace data was cleared.
Sourcepub const THRESHOLD_EXCEEDED: Self
pub const THRESHOLD_EXCEEDED: Self
A threshold event was detected (threshold exceeded condition met).
Sourcepub const THRESHOLD_ADDED: Self
pub const THRESHOLD_ADDED: Self
A threshold definition was added.
Sourcepub const THRESHOLD_REMOVED: Self
pub const THRESHOLD_REMOVED: Self
A threshold definition was removed.
Sourcepub const KEY_PRESSED: Self
pub const KEY_PRESSED: Self
A keyboard key was pressed inside the plot area.
Sourcepub const SCREENSHOT: Self
pub const SCREENSHOT: Self
A screenshot was taken.
Sourcepub const SCOPE_ADDED: Self
pub const SCOPE_ADDED: Self
A scope was added.
Sourcepub const SCOPE_REMOVED: Self
pub const SCOPE_REMOVED: Self
A scope was removed.
Sourcepub const TRIGGER_FIRED: Self
pub const TRIGGER_FIRED: Self
A trigger fired.
Sourcepub const TRACE_OFFSET_CHANGED: Self
pub const TRACE_OFFSET_CHANGED: Self
A trace Y-offset was changed.
Sourcepub const Y_LOG_CHANGED: Self
pub const Y_LOG_CHANGED: Self
Y-axis log mode was toggled.
Sourcepub const Y_UNIT_CHANGED: Self
pub const Y_UNIT_CHANGED: Self
Y-axis unit was changed.
Sourcepub const fn contains(self, other: Self) -> bool
pub const fn contains(self, other: Self) -> bool
Check whether self contains all bits in other.
Examples found in repository?
23fn main() -> eframe::Result<()> {
24 // Subscribe to ALL events.
25 let event_ctrl = EventController::new();
26 let rx = event_ctrl.subscribe(EventFilter::all());
27
28 // Background thread: pretty-print every event.
29 std::thread::spawn(move || {
30 while let Ok(evt) = rx.recv() {
31 let k = evt.kinds;
32
33 // ── Click / Double-click ──────────────────────────────────────
34 if k.contains(EventKind::CLICK) || k.contains(EventKind::DOUBLE_CLICK) {
35 let label = if k.contains(EventKind::DOUBLE_CLICK) {
36 "DOUBLE_CLICK"
37 } else {
38 "CLICK"
39 };
40 if let Some(c) = &evt.click {
41 // coordinates are optional but should exist for click events
42 let (px, py) = if let Some(p) = c.plot_pos {
43 (p.x, p.y)
44 } else {
45 (f64::NAN, f64::NAN)
46 };
47 let (sx, sy) = if let Some(s) = c.screen_pos {
48 (s.x, s.y)
49 } else {
50 (f32::NAN, f32::NAN)
51 };
52 println!(
53 "[{label}] plot=({:.4},{:.4}) screen=({:.1},{:.1}) scope={}",
54 px,
55 py,
56 sx,
57 sy,
58 c.scope_id.map_or("?".into(), |id| id.to_string()),
59 );
60 } else {
61 println!("[{label}]");
62 }
63 }
64
65 // ── Pause / Resume ────────────────────────────────────────────
66 if k.contains(EventKind::PAUSE) || k.contains(EventKind::RESUME) {
67 let label = if k.contains(EventKind::RESUME) {
68 "RESUME"
69 } else {
70 "PAUSE"
71 };
72 if let Some(p) = &evt.pause {
73 println!("[{label}] scope={}", p.scope_id.unwrap_or(0));
74 } else {
75 println!("[{label}]");
76 }
77 }
78
79 // ── Zoom / Pan / Fit-to-View ──────────────────────────────────
80 if k.contains(EventKind::ZOOM)
81 || k.contains(EventKind::PAN)
82 || k.contains(EventKind::FIT_TO_VIEW)
83 {
84 let label = if k.contains(EventKind::FIT_TO_VIEW) {
85 "FIT_TO_VIEW"
86 } else if k.contains(EventKind::ZOOM) {
87 "ZOOM"
88 } else {
89 "PAN"
90 };
91 if let Some(v) = &evt.view_change {
92 println!(
93 "[{label}] x={:?} y={:?} scope={}",
94 v.x_range,
95 v.y_range,
96 v.scope_id.map_or("?".into(), |id| id.to_string()),
97 );
98 } else {
99 println!("[{label}]");
100 }
101 }
102
103 // ── Measurement ───────────────────────────────────────────────
104 if k.contains(EventKind::MEASUREMENT_POINT) {
105 let complete = k.contains(EventKind::MEASUREMENT_COMPLETE);
106 if let Some(m) = &evt.measurement {
107 println!(
108 "[MEASUREMENT{}] name={:?} point=({:.4},{:.4}) p1={:?} p2={:?} slope={:?} dist={:?}",
109 if complete { " COMPLETE" } else { "" },
110 m.measurement_name,
111 m.point[0], m.point[1],
112 m.p1, m.p2, m.slope, m.distance,
113 );
114 }
115 }
116 if k.contains(EventKind::MEASUREMENT_CLEARED) {
117 println!("[MEASUREMENT_CLEARED]");
118 }
119
120 // ── Resize ────────────────────────────────────────────────────
121 if k.contains(EventKind::RESIZE) {
122 if let Some(r) = &evt.resize {
123 println!("[RESIZE] {}×{}", r.width as u32, r.height as u32);
124 }
125 }
126
127 // ── Key press ─────────────────────────────────────────────────
128 if k.contains(EventKind::KEY_PRESSED) {
129 if let Some(kp) = &evt.key_press {
130 println!(
131 "[KEY] {:?} ctrl={} alt={} shift={} cmd={}",
132 kp.key,
133 kp.modifiers.ctrl,
134 kp.modifiers.alt,
135 kp.modifiers.shift,
136 kp.modifiers.command,
137 );
138 }
139 }
140
141 // ── Data update ───────────────────────────────────────────────
142 if k.contains(EventKind::DATA_UPDATED) {
143 if let Some(d) = &evt.data_update {
144 println!("[DATA_UPDATED] traces={:?}", d.traces);
145 }
146 }
147
148 // ── Trace visibility / colour / offset ────────────────────────
149 if k.contains(EventKind::TRACE_SHOWN) || k.contains(EventKind::TRACE_HIDDEN) {
150 if let Some(t) = &evt.trace {
151 println!(
152 "[TRACE_{}] {:?} visible={:?}",
153 if k.contains(EventKind::TRACE_SHOWN) {
154 "SHOWN"
155 } else {
156 "HIDDEN"
157 },
158 t.trace.0,
159 t.visible,
160 );
161 }
162 }
163 if k.contains(EventKind::TRACE_COLOR_CHANGED) {
164 if let Some(t) = &evt.trace {
165 println!("[TRACE_COLOR] {:?} rgb={:?}", t.trace.0, t.color_rgb);
166 }
167 }
168 if k.contains(EventKind::TRACE_OFFSET_CHANGED) {
169 if let Some(t) = &evt.trace {
170 println!("[TRACE_OFFSET] {:?} offset={:?}", t.trace.0, t.offset);
171 }
172 }
173
174 // ── Math trace ────────────────────────────────────────────────
175 if k.contains(EventKind::MATH_TRACE_ADDED) {
176 if let Some(m) = &evt.math_trace {
177 println!("[MATH_TRACE_ADDED] {:?} formula={:?}", m.name, m.formula);
178 }
179 }
180 if k.contains(EventKind::MATH_TRACE_REMOVED) {
181 if let Some(m) = &evt.math_trace {
182 println!("[MATH_TRACE_REMOVED] {:?}", m.name);
183 }
184 }
185
186 // ── Threshold ─────────────────────────────────────────────────
187 if k.contains(EventKind::THRESHOLD_EXCEEDED) {
188 if let Some(t) = &evt.threshold {
189 println!(
190 "[THRESHOLD_EXCEEDED] {:?} trace={:?} area={:?}",
191 t.threshold_name, t.trace, t.area,
192 );
193 }
194 }
195 if k.contains(EventKind::THRESHOLD_REMOVED) {
196 if let Some(t) = &evt.threshold {
197 println!("[THRESHOLD_REMOVED] {:?}", t.threshold_name);
198 }
199 }
200
201 // ── Export / Screenshot ───────────────────────────────────────
202 if k.contains(EventKind::EXPORT) || k.contains(EventKind::SCREENSHOT) {
203 let label = if k.contains(EventKind::SCREENSHOT) {
204 "SCREENSHOT"
205 } else {
206 "EXPORT"
207 };
208 if let Some(e) = &evt.export {
209 println!("[{label}] format={:?} path={:?}", e.format, e.path);
210 }
211 }
212
213 // ── Scope management ──────────────────────────────────────────
214 if k.contains(EventKind::SCOPE_ADDED) {
215 if let Some(s) = &evt.scope_manage {
216 println!("[SCOPE_ADDED] id={}", s.scope_id);
217 }
218 }
219 if k.contains(EventKind::SCOPE_REMOVED) {
220 if let Some(s) = &evt.scope_manage {
221 println!("[SCOPE_REMOVED] id={}", s.scope_id);
222 }
223 }
224 }
225 println!("[event] channel closed");
226 });
227
228 // Set up a sine + cosine trace so there is data to interact with.
229 let (sink, data_rx) = channel_plot();
230 let t_sin = sink.create_trace("sin", Some("Sine"));
231 let t_cos = sink.create_trace("cos", Some("Cosine"));
232
233 std::thread::spawn(move || {
234 let dt = Duration::from_millis(1);
235 loop {
236 let t_s = SystemTime::now()
237 .duration_since(UNIX_EPOCH)
238 .map(|d| d.as_secs_f64())
239 .unwrap_or(0.0);
240 let _ = sink.send_point(
241 &t_sin,
242 PlotPoint {
243 x: t_s,
244 y: (2.0 * std::f64::consts::PI * 2.0 * t_s).sin(),
245 },
246 );
247 let _ = sink.send_point(
248 &t_cos,
249 PlotPoint {
250 x: t_s,
251 y: (2.0 * std::f64::consts::PI * 2.0 * t_s).cos(),
252 },
253 );
254 std::thread::sleep(dt);
255 }
256 });
257
258 let mut cfg = LivePlotConfig::default();
259 cfg.controllers.event = Some(event_ctrl);
260
261 run_liveplot(data_rx, cfg)
262}Sourcepub const fn intersects(self, other: Self) -> bool
pub const fn intersects(self, other: Self) -> bool
Check whether self intersects with other (at least one bit in common).
Trait Implementations§
Source§impl BitOrAssign for EventKind
impl BitOrAssign for EventKind
Source§fn bitor_assign(&mut self, rhs: Self)
fn bitor_assign(&mut self, rhs: Self)
|= operation. Read moreimpl Copy for EventKind
impl Eq for EventKind
impl StructuralPartialEq for EventKind
Auto Trait Implementations§
impl Freeze for EventKind
impl RefUnwindSafe for EventKind
impl Send for EventKind
impl Sync for EventKind
impl Unpin for EventKind
impl UnsafeUnpin for EventKind
impl UnwindSafe for EventKind
Blanket Implementations§
impl<T> AsId for T
impl<T> AsIdSalt for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> DragDropItem for Twhere
T: AsId,
impl<T> DragDropItem for Twhere
T: AsId,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more