Guest User

Untitled

a guest
Jun 11th, 2023
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 7.28 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| {
  118.                 let device_tx = device_tx.clone();
  119.                 async move {
  120.                     std::thread::spawn(move || {
  121.                         let (gui_tx, gui_rx) = std_mpsc::channel();
  122.                         if device_tx.register_gui_tx(gui_tx).is_ok() {
  123.                             while let Ok(message) = gui_rx.recv() {
  124.                                 if iced::futures::executor::block_on(output.send(message)).is_err() {
  125.                                     break;
  126.                                 }
  127.                             }
  128.                         };
  129.                     });
  130.                     loop {
  131.                         tokio::time::sleep(tokio::time::Duration::from_secs(u64::MAX)).await;
  132.                     }
  133.                 }
  134.             },
  135.         )
  136.     }
  137. }
  138.  
  139. mod device {
  140.     use std::sync::mpsc as std_mpsc;
  141.     use std::time::{Duration, Instant};
  142.  
  143.     pub struct Device {
  144.         device_tx: DeviceSender,
  145.         join_handle: std::thread::JoinHandle<()>,
  146.     }
  147.  
  148.     impl Device {
  149.         pub fn start() -> Self {
  150.             let (device_tx, device_rx) = std_mpsc::sync_channel(100);
  151.             let device_tx = DeviceSender::from(device_tx);
  152.  
  153.             let join_handle = std::thread::spawn(|| Self::run(device_rx));
  154.  
  155.             Self {
  156.                 device_tx,
  157.                 join_handle,
  158.             }
  159.         }
  160.  
  161.         pub fn stop(self) {
  162.             // We don't care if the device has already stopped
  163.             let _ = self.device_tx.stop();
  164.  
  165.             self.join_handle.join().expect("Device crashed");
  166.         }
  167.  
  168.         pub fn get_tx(&self) -> DeviceSender {
  169.             self.device_tx.clone()
  170.         }
  171.  
  172.         fn run(device_rx: std_mpsc::Receiver<Message>) {
  173.             let mut gui_txs = vec![];
  174.             let mut i = 0;
  175.             loop {
  176.                 // Receive messages until timeout
  177.                 let timeout = Duration::from_millis(100);
  178.                 let deadline = Instant::now() + timeout;
  179.                 loop {
  180.                     match device_rx.recv_timeout(deadline - Instant::now()) {
  181.                         Ok(message) => match message {
  182.                             Message::GuiTx(gui_tx) => gui_txs.push(gui_tx),
  183.                             Message::Stop => return,
  184.                         },
  185.                         Err(std_mpsc::RecvTimeoutError::Disconnected) => return,
  186.                         Err(std_mpsc::RecvTimeoutError::Timeout) => break,
  187.                     }
  188.                 }
  189.  
  190.                 // Send messages
  191.                 for gui_tx in &gui_txs {
  192.                     gui_tx.send(i).unwrap();
  193.                 }
  194.  
  195.                 // Increment i so something different is sent next time
  196.                 i += 1;
  197.             }
  198.         }
  199.     }
  200.  
  201.     #[derive(Clone)]
  202.     pub struct DeviceSender {
  203.         tx: std_mpsc::SyncSender<Message>,
  204.     }
  205.  
  206.     impl DeviceSender {
  207.         /// Registers the gui_tx with the device.
  208.         /// If the device has stopped returns and error.
  209.         pub fn register_gui_tx(&self, gui_tx: std_mpsc::Sender<i32>) -> Result<(), ()> {
  210.             match self.tx.send(Message::GuiTx(gui_tx)) {
  211.                 Ok(_) => Result::Ok(()),
  212.                 Err(_) => Result::Err(()),
  213.             }
  214.         }
  215.  
  216.         fn from(tx: std_mpsc::SyncSender<Message>) -> Self {
  217.             Self { tx }
  218.         }
  219.  
  220.         /// Tells the device to stop.
  221.         /// If the device is already stopped, returns an error
  222.         fn stop(self) -> Result<(), ()> {
  223.             match self.tx.send(Message::Stop) {
  224.                 Ok(_) => Result::Ok(()),
  225.                 Err(_) => Result::Err(()),
  226.             }
  227.         }
  228.     }
  229.  
  230.     enum Message {
  231.         GuiTx(std_mpsc::Sender<i32>),
  232.         Stop,
  233.     }
  234. }
  235.  
Advertisement
Add Comment
Please, Sign In to add comment