egui: replace FileSender/FileReceiver with FileHandler

This commit is contained in:
Alain Emilia Anna Zscheile 2024-09-29 14:29:18 +02:00
parent f21808776e
commit 1a46504dd5
6 changed files with 93 additions and 75 deletions

View File

@ -18,7 +18,7 @@ use crate::{
activity::{ActivityStatus, ActivityStepperWithStatus}, activity::{ActivityStatus, ActivityStepperWithStatus},
config::Config, config::Config,
error_dialog::ErrorDialog, error_dialog::ErrorDialog,
file_receiver::FileReceiver, file_handler::FileHandlerData,
layers::Layers, layers::Layers,
menu_bar::MenuBar, menu_bar::MenuBar,
overlay::Overlay, overlay::Overlay,
@ -37,8 +37,14 @@ pub struct App {
maybe_activity: Option<ActivityStepperWithStatus>, maybe_activity: Option<ActivityStepperWithStatus>,
content_channel: (Sender<String>, Receiver<String>), content_channel: (
history_channel: (Sender<String>, Receiver<String>), Sender<std::io::Result<FileHandlerData>>,
Receiver<std::io::Result<FileHandlerData>>,
),
history_channel: (
Sender<std::io::Result<FileHandlerData>>,
Receiver<std::io::Result<FileHandlerData>>,
),
viewport: Viewport, viewport: Viewport,
@ -101,21 +107,25 @@ impl App {
} }
fn update_state(&mut self) -> bool { fn update_state(&mut self) -> bool {
let mut content_file_receiver = FileReceiver::new(&self.content_channel.1); if let Ok(data) = self.content_channel.1.try_recv() {
match data {
if let Some(input) = content_file_receiver.try_recv() { Ok(data) => match self.load_specctra_dsn(data) {
match self.load_specctra_dsn(input) {
Ok(()) => {} Ok(()) => {}
Err(err) => { Err(err) => {
self.error_dialog.push_error("tr-module-specctra-dsn-file-loader", err); self.error_dialog.push_error("tr-module-specctra-dsn-file-loader", err);
} }
},
Err(err) => {
self.error_dialog.push_error(
"tr-module-specctra-dsn-file-loader",
format!("{}; {}", self.translator.text("tr-error_unable-to-read-file"), err),
);
}
} }
} }
if let Some(invoker) = self.arc_mutex_maybe_invoker.lock().unwrap().as_mut() { if let Some(invoker) = self.arc_mutex_maybe_invoker.lock().unwrap().as_mut() {
let mut history_file_receiver = FileReceiver::new(&self.history_channel.1); if let Ok(input) = self.history_channel.1.try_recv() {
if let Some(input) = history_file_receiver.try_recv() {
let tr = &self.translator; let tr = &self.translator;
match input { match input {
Ok(bufread) => match serde_json::from_reader(bufread) { Ok(bufread) => match serde_json::from_reader(bufread) {
@ -151,12 +161,8 @@ impl App {
false false
} }
fn load_specctra_dsn<I: std::io::BufRead>( fn load_specctra_dsn(&mut self, bufread: FileHandlerData) -> Result<(), String> {
&mut self,
input: std::io::Result<I>,
) -> Result<(), String> {
let tr = &self.translator; let tr = &self.translator;
let bufread = input.map_err(|err| format!("{}; {}", tr.text("tr-error_unable-to-read-file"), err))?;
let design = SpecctraDesign::load(bufread) let design = SpecctraDesign::load(bufread)
.map_err(|err| format!("{}; {}", tr.text("tr-error_failed-to-parse-as-specctra-dsn"), err))?; .map_err(|err| format!("{}; {}", tr.text("tr-error_failed-to-parse-as-specctra-dsn"), err))?;
let board = design.make_board(); let board = design.make_board();

View File

@ -0,0 +1,64 @@
use std::io;
use std::sync::mpsc::{SendError, Sender};
#[repr(transparent)]
pub enum FileHandlerData {
#[cfg(not(target_arch = "wasm32"))]
File(io::BufReader<std::fs::File>),
#[cfg(target_arch = "wasm32")]
Contents(io::Cursor<Vec<u8>>),
}
macro_rules! fhd_forward {
(match $self:expr => $fname:ident($($arg:expr,)*)) => {{
match $self {
#[cfg(not(target_arch = "wasm32"))]
FileHandlerData::File(brf) => brf.$fname($($arg,)*),
#[cfg(target_arch = "wasm32")]
FileHandlerData::Contents(curs) => curs.$fname($($arg,)*),
}
}};
(fn $fname:ident(&mut self $(,$arg:ident : $argty:ty)*)) => {
#[inline]
fn $fname(&mut self $(,$arg : $argty)*) {
fhd_forward!(match self => $fname($($arg,)*))
}
};
(fn $fname:ident(&mut self $(,$arg:ident : $argty:ty)*) -> $ret:ty) => {
#[inline]
fn $fname(&mut self $(,$arg : $argty)*) -> $ret {
fhd_forward!(match self => $fname($($arg,)*))
}
}
}
impl io::Read for FileHandlerData {
fhd_forward!(fn read(&mut self, buf: &mut [u8]) -> io::Result<usize>);
fhd_forward!(fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize>);
fhd_forward!(fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize>);
}
impl io::BufRead for FileHandlerData {
fhd_forward!(fn fill_buf(&mut self) -> io::Result<&[u8]>);
fhd_forward!(fn consume(&mut self, amt: usize));
}
pub async fn push_file_to_read(
file_handle: &rfd::FileHandle,
sender: Sender<std::io::Result<FileHandlerData>>,
) {
let _ = sender.send(handle_text(&file_handle).await);
}
async fn handle_text(file_handle: &rfd::FileHandle) -> std::io::Result<FileHandlerData> {
#[cfg(not(target_arch = "wasm32"))]
let res = FileHandlerData::File(io::BufReader::new(std::fs::File::open(file_handle.path())?));
#[cfg(target_arch = "wasm32")]
let res = FileHandlerData::Contents(io::Cursor::new(file_handle.read().await));
Ok(res)
}

View File

@ -1,22 +0,0 @@
use std::io::{BufReader, Cursor};
use std::sync::mpsc::Receiver;
pub struct FileReceiver<'a> {
receiver: &'a Receiver<String>,
}
impl<'a> FileReceiver<'a> {
pub fn new(receiver: &'a Receiver<String>) -> Self {
Self { receiver }
}
#[cfg(not(target_arch = "wasm32"))]
pub fn try_recv(&mut self) -> Option<Result<BufReader<std::fs::File>, std::io::Error>> {
Some(std::fs::File::open(self.receiver.try_recv().ok()?).map(std::io::BufReader::new))
}
#[cfg(target_arch = "wasm32")]
pub fn try_recv(&mut self) -> Option<Result<Cursor<Vec<u8>>, std::io::Error>> {
Some(Ok(Cursor::new(self.receiver.try_recv().ok()?.into())))
}
}

View File

@ -1,27 +0,0 @@
use std::sync::mpsc::{SendError, Sender};
pub struct FileSender {
sender: Sender<String>,
}
impl FileSender {
pub fn new(sender: Sender<String>) -> Self {
Self { sender }
}
pub async fn send(&self, file_handle: rfd::FileHandle) -> Result<(), SendError<String>> {
self.sender.send(self.handle_text(&file_handle).await)
}
#[cfg(not(target_arch = "wasm32"))]
async fn handle_text(&self, file_handle: &rfd::FileHandle) -> String {
file_handle.path().to_str().unwrap().to_string()
}
#[cfg(target_arch = "wasm32")]
async fn handle_text(&self, file_handle: &rfd::FileHandle) -> String {
std::str::from_utf8(&file_handle.read().await)
.unwrap()
.to_string()
}
}

View File

@ -5,8 +5,7 @@ mod activity;
mod app; mod app;
mod config; mod config;
mod error_dialog; mod error_dialog;
mod file_receiver; mod file_handler;
mod file_sender;
mod layers; mod layers;
mod menu_bar; mod menu_bar;
mod overlay; mod overlay;

View File

@ -18,7 +18,7 @@ use crate::{
action::{Action, Switch, Trigger}, action::{Action, Switch, Trigger},
activity::{ActivityStatus, ActivityStepperWithStatus}, activity::{ActivityStatus, ActivityStepperWithStatus},
app::execute, app::execute,
file_sender::FileSender, file_handler::{push_file_to_read, FileHandlerData},
overlay::Overlay, overlay::Overlay,
translator::Translator, translator::Translator,
viewport::Viewport, viewport::Viewport,
@ -59,8 +59,8 @@ impl MenuBar {
&mut self, &mut self,
ctx: &egui::Context, ctx: &egui::Context,
tr: &Translator, tr: &Translator,
content_sender: Sender<String>, content_sender: Sender<std::io::Result<FileHandlerData>>,
history_sender: Sender<String>, history_sender: Sender<std::io::Result<FileHandlerData>>,
arc_mutex_maybe_invoker: Arc<Mutex<Option<Invoker<SpecctraMesadata>>>>, arc_mutex_maybe_invoker: Arc<Mutex<Option<Invoker<SpecctraMesadata>>>>,
maybe_activity: &mut Option<ActivityStepperWithStatus>, maybe_activity: &mut Option<ActivityStepperWithStatus>,
viewport: &mut Viewport, viewport: &mut Viewport,
@ -239,8 +239,7 @@ impl MenuBar {
execute(async move { execute(async move {
if let Some(file_handle) = task.await { if let Some(file_handle) = task.await {
let file_sender = FileSender::new(content_sender); push_file_to_read(&file_handle, content_sender).await;
file_sender.send(file_handle).await;
ctx.request_repaint(); ctx.request_repaint();
} }
}); });
@ -279,8 +278,7 @@ impl MenuBar {
execute(async move { execute(async move {
if let Some(file_handle) = task.await { if let Some(file_handle) = task.await {
let file_sender = FileSender::new(history_sender); push_file_to_read(&file_handle, history_sender).await;
file_sender.send(file_handle).await;
ctx.request_repaint(); ctx.request_repaint();
} }
}); });