Guest User

Untitled

a guest
Jun 11th, 2023
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 7.13 KB | Source Code | 0 0
  1. use device::Device;
  2.  
  3. fn main() -> iced::Result {
  4.     let device = Device::start();
  5.     let gui_result = gui::run(device.get_tx());
  6.     device.stop();
  7.     gui_result
  8. }
  9.  
  10. mod gui {
  11.     use iced::{
  12.         futures::SinkExt,
  13.         widget::{button, column, text},
  14.         Application, Command, Element, Settings,
  15.     };
  16.     use std::sync::mpsc as std_mpsc;
  17.  
  18.     pub fn run(device_tx: super::device::DeviceSender) -> iced::Result {
  19.         Gui::run(Settings {
  20.             id: None,
  21.             window: Default::default(),
  22.             flags: Flags { device_tx },
  23.             default_font: Default::default(),
  24.             default_text_size: 20.0,
  25.             antialiasing: false,
  26.             exit_on_close_request: true,
  27.         })
  28.     }
  29.  
  30.     struct Flags {
  31.         device_tx: super::device::DeviceSender,
  32.     }
  33.  
  34.     struct Gui {
  35.         device_tx: super::device::DeviceSender,
  36.         value: i32, // The counter value
  37.         auto_incrementing_value: i32,
  38.     }
  39.  
  40.     #[derive(Debug, Clone, Copy)]
  41.     enum Message {
  42.         IncrementPressed,
  43.         DecrementPressed,
  44.         AutoIncrementingValueUpdate(i32),
  45.     }
  46.  
  47.     impl Application for Gui {
  48.         type Message = Message;
  49.         type Executor = iced::executor::Default;
  50.         type Flags = Flags;
  51.         type Theme = iced::Theme;
  52.  
  53.         fn new(flags: Self::Flags) -> (Self, Command<Message>) {
  54.             (
  55.                 Self {
  56.                     device_tx: flags.device_tx,
  57.                     value: 0,
  58.                     auto_incrementing_value: 0,
  59.                 },
  60.                 Command::none(),
  61.             )
  62.         }
  63.  
  64.         fn title(&self) -> String {
  65.             String::from("iced test")
  66.         }
  67.  
  68.         fn view(&self) -> Element<Message> {
  69.             // We use a column: a simple vertical layout
  70.             column![
  71.                 // The increment button. We tell it to produce an
  72.                 // `IncrementPressed` message when pressed
  73.                 button("+").on_press(Message::IncrementPressed),
  74.                 // We show the value of the counter here
  75.                 text(self.value).size(50),
  76.                 // The decrement button. We tell it to produce a
  77.                 // `DecrementPressed` message when pressed
  78.                 button("-").on_press(Message::DecrementPressed),
  79.                 text(format!(
  80.                     "Incrementing value: {}",
  81.                     self.auto_incrementing_value
  82.                 ))
  83.             ]
  84.             .into()
  85.         }
  86.  
  87.         fn subscription(&self) -> iced::Subscription<Self::Message> {
  88.             device_tx_to_iced_subscription(self.device_tx.clone()).map(|auto_incrementing_value| {
  89.                 Message::AutoIncrementingValueUpdate(auto_incrementing_value)
  90.             })
  91.         }
  92.  
  93.         fn update(&mut self, message: Message) -> Command<Message> {
  94.             match message {
  95.                 Message::IncrementPressed => {
  96.                     self.value += 1;
  97.                 }
  98.                 Message::DecrementPressed => {
  99.                     self.value -= 1;
  100.                 }
  101.                 Message::AutoIncrementingValueUpdate(value) => {
  102.                     self.auto_incrementing_value = value;
  103.                 }
  104.             }
  105.  
  106.             Command::none()
  107.         }
  108.     }
  109.  
  110.     fn device_tx_to_iced_subscription(
  111.         device_tx: super::device::DeviceSender,
  112.     ) -> iced::Subscription<i32> {
  113.         struct Connect;
  114.         iced::subscription::channel(
  115.             std::any::TypeId::of::<Connect>(),
  116.             100,
  117.             move |mut output| async move {
  118.                 std::thread::spawn(move || {
  119.                     let (gui_tx, gui_rx) = std_mpsc::channel();
  120.                     if device_tx.register_gui_tx(gui_tx).is_ok() {
  121.                         while let Ok(message) = gui_rx.recv() {
  122.                             if iced::futures::executor::block_on(output.send(message)).is_err() {
  123.                                 break;
  124.                             }
  125.                         }
  126.                     };
  127.                 });
  128.                 loop {
  129.                     tokio::time::sleep(tokio::time::Duration::from_secs(u64::MAX)).await;
  130.                 }
  131.             },
  132.         )
  133.     }
  134. }
  135.  
  136. mod device {
  137.     use std::sync::mpsc as std_mpsc;
  138.     use std::time::{Duration, Instant};
  139.  
  140.     pub struct Device {
  141.         device_tx: DeviceSender,
  142.         join_handle: std::thread::JoinHandle<()>,
  143.     }
  144.  
  145.     impl Device {
  146.         pub fn start() -> Self {
  147.             let (device_tx, device_rx) = std_mpsc::channel();
  148.             let device_tx = DeviceSender::from(device_tx);
  149.  
  150.             let join_handle = std::thread::spawn(|| Self::run(device_rx));
  151.  
  152.             Self {
  153.                 device_tx,
  154.                 join_handle,
  155.             }
  156.         }
  157.  
  158.         pub fn stop(self) {
  159.             // We don't care if the device has already stopped
  160.             let _ = self.device_tx.stop();
  161.  
  162.             self.join_handle.join().expect("Device crashed");
  163.         }
  164.  
  165.         pub fn get_tx(&self) -> DeviceSender {
  166.             self.device_tx.clone()
  167.         }
  168.  
  169.         fn run(device_rx: std_mpsc::Receiver<Message>) {
  170.             let mut gui_txs = vec![];
  171.             let mut i = 0;
  172.             loop {
  173.                 // Receive messages until timeout
  174.                 let timeout = Duration::from_millis(100);
  175.                 let deadline = Instant::now() + timeout;
  176.                 loop {
  177.                     match device_rx.recv_timeout(deadline - Instant::now()) {
  178.                         Ok(message) => match message {
  179.                             Message::GuiTx(gui_tx) => gui_txs.push(gui_tx),
  180.                             Message::Stop => return,
  181.                         },
  182.                         Err(std_mpsc::RecvTimeoutError::Disconnected) => return,
  183.                         Err(std_mpsc::RecvTimeoutError::Timeout) => break,
  184.                     }
  185.                 }
  186.  
  187.                 // Send messages
  188.                 for gui_tx in &gui_txs {
  189.                     gui_tx.send(i).unwrap();
  190.                 }
  191.  
  192.                 // Increment i so something different is sent next time
  193.                 i += 1;
  194.             }
  195.         }
  196.     }
  197.  
  198.     #[derive(Clone)]
  199.     pub struct DeviceSender {
  200.         tx: std_mpsc::Sender<Message>,
  201.     }
  202.  
  203.     impl DeviceSender {
  204.         /// Registers the gui_tx with the device.
  205.         /// If the device has stopped returns and error.
  206.         pub fn register_gui_tx(&self, gui_tx: std_mpsc::Sender<i32>) -> Result<(), ()> {
  207.             match self.tx.send(Message::GuiTx(gui_tx)) {
  208.                 Ok(_) => Result::Ok(()),
  209.                 Err(_) => Result::Err(()),
  210.             }
  211.         }
  212.  
  213.         fn from(tx: std_mpsc::Sender<Message>) -> Self {
  214.             Self { tx }
  215.         }
  216.  
  217.         /// Tells the device to stop.
  218.         /// If the device is already stopped, returns an error
  219.         fn stop(self) -> Result<(), ()> {
  220.             match self.tx.send(Message::Stop) {
  221.                 Ok(_) => Result::Ok(()),
  222.                 Err(_) => Result::Err(()),
  223.             }
  224.         }
  225.     }
  226.  
  227.     enum Message {
  228.         GuiTx(std_mpsc::Sender<i32>),
  229.         Stop,
  230.     }
  231. }
  232.  
Advertisement
Add Comment
Please, Sign In to add comment