cog_task/action/core/
counter.rs

1use crate::action::{Action, Props, StatefulAction, VISUAL};
2use crate::comm::{QWriter, Signal};
3use crate::gui::{style_ui, Style};
4use crate::resource::{IoManager, ResourceManager};
5use crate::server::{AsyncSignal, Config, State, SyncSignal};
6use eframe::egui;
7use egui_extras::{Size, StripBuilder};
8use eyre::Result;
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Deserialize, Serialize)]
12#[serde(deny_unknown_fields)]
13pub struct Counter(#[serde(default = "defaults::from")] u32);
14
15stateful!(Counter { count: u32 });
16
17mod defaults {
18    #[inline(always)]
19    pub fn from() -> u32 {
20        3
21    }
22}
23
24impl From<u32> for Counter {
25    fn from(i: u32) -> Self {
26        Self(i)
27    }
28}
29
30impl Action for Counter {
31    fn stateful(
32        &self,
33        _io: &IoManager,
34        _res: &ResourceManager,
35        _config: &Config,
36        _sync_writer: &QWriter<SyncSignal>,
37        _async_writer: &QWriter<AsyncSignal>,
38    ) -> Result<Box<dyn StatefulAction>> {
39        Ok(Box::new(StatefulCounter {
40            done: false,
41            count: self.0,
42        }))
43    }
44}
45
46impl StatefulAction for StatefulCounter {
47    impl_stateful!();
48
49    #[inline(always)]
50    fn props(&self) -> Props {
51        VISUAL.into()
52    }
53
54    fn start(
55        &mut self,
56        sync_writer: &mut QWriter<SyncSignal>,
57        _async_writer: &mut QWriter<AsyncSignal>,
58        _state: &State,
59    ) -> Result<Signal> {
60        if self.count == 0 {
61            self.done = true;
62            sync_writer.push(SyncSignal::UpdateGraph);
63        } else {
64            sync_writer.push(SyncSignal::Repaint);
65        }
66
67        Ok(Signal::none())
68    }
69
70    fn show(
71        &mut self,
72        ui: &mut egui::Ui,
73        sync_writer: &mut QWriter<SyncSignal>,
74        _async_writer: &mut QWriter<AsyncSignal>,
75        _state: &State,
76    ) -> Result<()> {
77        enum Interaction {
78            None,
79            Decrement,
80        }
81
82        let mut interaction = Interaction::None;
83
84        let button = egui::Button::new(format!("Click me {} more times", self.count));
85
86        StripBuilder::new(ui)
87            .size(Size::remainder())
88            .size(Size::exact(420.0))
89            .size(Size::remainder())
90            .horizontal(|mut strip| {
91                strip.empty();
92                strip.strip(|builder| {
93                    builder
94                        .size(Size::remainder())
95                        .size(Size::exact(80.0))
96                        .size(Size::remainder())
97                        .vertical(|mut strip| {
98                            strip.empty();
99                            strip.cell(|ui| {
100                                ui.centered_and_justified(|ui| {
101                                    style_ui(ui, Style::SelectButton);
102                                    if ui.add(button).clicked() {
103                                        interaction = Interaction::Decrement;
104                                    }
105                                });
106                            });
107                            strip.empty();
108                        });
109                });
110                strip.empty();
111            });
112
113        match interaction {
114            Interaction::None => {}
115            Interaction::Decrement => {
116                self.count = self.count.saturating_sub(1);
117                if self.count == 0 {
118                    self.done = true;
119                    sync_writer.push(SyncSignal::UpdateGraph);
120                }
121            }
122        }
123
124        Ok(())
125    }
126
127    fn debug(&self) -> Vec<(&str, String)> {
128        <dyn StatefulAction>::debug(self)
129            .into_iter()
130            .chain([("count", format!("{:?}", self.count))])
131            .collect()
132    }
133}