Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use device::Device;
- fn main() -> iced::Result {
- let device = Device::start();
- let gui_result = gui::run(device.get_tx());
- device.stop();
- gui_result
- }
- mod gui {
- use iced::{
- futures::SinkExt,
- widget::{button, column, text},
- Application, Command, Element, Settings,
- };
- use std::sync::mpsc as std_mpsc;
- pub fn run(device_tx: super::device::DeviceSender) -> iced::Result {
- Gui::run(Settings {
- id: None,
- window: Default::default(),
- flags: Flags { device_tx },
- default_font: Default::default(),
- default_text_size: 20.0,
- antialiasing: false,
- exit_on_close_request: true,
- })
- }
- struct Flags {
- device_tx: super::device::DeviceSender,
- }
- struct Gui {
- device_tx: super::device::DeviceSender,
- value: i32, // The counter value
- auto_incrementing_value: i32,
- }
- #[derive(Debug, Clone, Copy)]
- enum Message {
- IncrementPressed,
- DecrementPressed,
- AutoIncrementingValueUpdate(i32),
- }
- impl Application for Gui {
- type Message = Message;
- type Executor = iced::executor::Default;
- type Flags = Flags;
- type Theme = iced::Theme;
- fn new(flags: Self::Flags) -> (Self, Command<Message>) {
- (
- Self {
- device_tx: flags.device_tx,
- value: 0,
- auto_incrementing_value: 0,
- },
- Command::none(),
- )
- }
- fn title(&self) -> String {
- String::from("iced test")
- }
- fn view(&self) -> Element<Message> {
- // We use a column: a simple vertical layout
- column![
- // The increment button. We tell it to produce an
- // `IncrementPressed` message when pressed
- button("+").on_press(Message::IncrementPressed),
- // We show the value of the counter here
- text(self.value).size(50),
- // The decrement button. We tell it to produce a
- // `DecrementPressed` message when pressed
- button("-").on_press(Message::DecrementPressed),
- text(format!(
- "Incrementing value: {}",
- self.auto_incrementing_value
- ))
- ]
- .into()
- }
- fn subscription(&self) -> iced::Subscription<Self::Message> {
- device_tx_to_iced_subscription(self.device_tx.clone()).map(|auto_incrementing_value| {
- Message::AutoIncrementingValueUpdate(auto_incrementing_value)
- })
- }
- fn update(&mut self, message: Message) -> Command<Message> {
- match message {
- Message::IncrementPressed => {
- self.value += 1;
- }
- Message::DecrementPressed => {
- self.value -= 1;
- }
- Message::AutoIncrementingValueUpdate(value) => {
- self.auto_incrementing_value = value;
- }
- }
- Command::none()
- }
- }
- fn device_tx_to_iced_subscription(
- device_tx: super::device::DeviceSender,
- ) -> iced::Subscription<i32> {
- struct Connect;
- iced::subscription::channel(
- std::any::TypeId::of::<Connect>(),
- 100,
- move |mut output| async move {
- std::thread::spawn(move || {
- let (gui_tx, gui_rx) = std_mpsc::channel();
- if device_tx.register_gui_tx(gui_tx).is_ok() {
- while let Ok(message) = gui_rx.recv() {
- if iced::futures::executor::block_on(output.send(message)).is_err() {
- break;
- }
- }
- };
- });
- loop {
- tokio::time::sleep(tokio::time::Duration::from_secs(u64::MAX)).await;
- }
- },
- )
- }
- }
- mod device {
- use std::sync::mpsc as std_mpsc;
- use std::time::{Duration, Instant};
- pub struct Device {
- device_tx: DeviceSender,
- join_handle: std::thread::JoinHandle<()>,
- }
- impl Device {
- pub fn start() -> Self {
- let (device_tx, device_rx) = std_mpsc::channel();
- let device_tx = DeviceSender::from(device_tx);
- let join_handle = std::thread::spawn(|| Self::run(device_rx));
- Self {
- device_tx,
- join_handle,
- }
- }
- pub fn stop(self) {
- // We don't care if the device has already stopped
- let _ = self.device_tx.stop();
- self.join_handle.join().expect("Device crashed");
- }
- pub fn get_tx(&self) -> DeviceSender {
- self.device_tx.clone()
- }
- fn run(device_rx: std_mpsc::Receiver<Message>) {
- let mut gui_txs = vec![];
- let mut i = 0;
- loop {
- // Receive messages until timeout
- let timeout = Duration::from_millis(100);
- let deadline = Instant::now() + timeout;
- loop {
- match device_rx.recv_timeout(deadline - Instant::now()) {
- Ok(message) => match message {
- Message::GuiTx(gui_tx) => gui_txs.push(gui_tx),
- Message::Stop => return,
- },
- Err(std_mpsc::RecvTimeoutError::Disconnected) => return,
- Err(std_mpsc::RecvTimeoutError::Timeout) => break,
- }
- }
- // Send messages
- for gui_tx in &gui_txs {
- gui_tx.send(i).unwrap();
- }
- // Increment i so something different is sent next time
- i += 1;
- }
- }
- }
- #[derive(Clone)]
- pub struct DeviceSender {
- tx: std_mpsc::Sender<Message>,
- }
- impl DeviceSender {
- /// Registers the gui_tx with the device.
- /// If the device has stopped returns and error.
- pub fn register_gui_tx(&self, gui_tx: std_mpsc::Sender<i32>) -> Result<(), ()> {
- match self.tx.send(Message::GuiTx(gui_tx)) {
- Ok(_) => Result::Ok(()),
- Err(_) => Result::Err(()),
- }
- }
- fn from(tx: std_mpsc::Sender<Message>) -> Self {
- Self { tx }
- }
- /// Tells the device to stop.
- /// If the device is already stopped, returns an error
- fn stop(self) -> Result<(), ()> {
- match self.tx.send(Message::Stop) {
- Ok(_) => Result::Ok(()),
- Err(_) => Result::Err(()),
- }
- }
- }
- enum Message {
- GuiTx(std_mpsc::Sender<i32>),
- Stop,
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment