In progress transfer
This commit is contained in:
141
src/app.rs
141
src/app.rs
@@ -1,8 +1,9 @@
|
|||||||
use std::fs::DirEntry;
|
use std::sync::mpsc;
|
||||||
use std::ops::DerefMut;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use egui::mutex::Mutex;
|
use crate::templates::{self, Template};
|
||||||
|
|
||||||
|
use egui::{Align, Layout};
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen_futures;
|
use wasm_bindgen_futures;
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
@@ -11,7 +12,7 @@ use web_sys;
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use smol;
|
use smol;
|
||||||
|
|
||||||
use tinytemplate;
|
use tinytemplate::TinyTemplate;
|
||||||
|
|
||||||
/// We derive Deserialize/Serialize so we can persist app state on shutdown.
|
/// We derive Deserialize/Serialize so we can persist app state on shutdown.
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
@@ -25,12 +26,20 @@ pub struct TemplateApp {
|
|||||||
|
|
||||||
#[serde(skip)] // This how you opt-out of serialization of a field
|
#[serde(skip)] // This how you opt-out of serialization of a field
|
||||||
value: f32,
|
value: f32,
|
||||||
#[serde(skip)]
|
|
||||||
templates: Vec<DirEntry>,
|
templates: HashMap<String, Template>,
|
||||||
|
active_template: String,
|
||||||
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
cont_mux: Arc<Mutex<String>>,
|
preview_text: String,
|
||||||
content: String,
|
|
||||||
|
#[serde(skip)]
|
||||||
|
messaging: (mpsc::Sender<Message>, mpsc::Receiver<Message>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Message {
|
||||||
|
AddTemplate(Template),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TemplateApp {
|
impl Default for TemplateApp {
|
||||||
@@ -40,9 +49,10 @@ impl Default for TemplateApp {
|
|||||||
init: false,
|
init: false,
|
||||||
label: "Hello World!".to_owned(),
|
label: "Hello World!".to_owned(),
|
||||||
value: 2.7,
|
value: 2.7,
|
||||||
templates: Vec::new(),
|
templates: HashMap::new(),
|
||||||
cont_mux: Arc::new(Mutex::new(String::new())),
|
active_template: "Select a template".to_string(),
|
||||||
content: "No File selected".to_string(),
|
preview_text: "No File Selected".to_string(),
|
||||||
|
messaging: mpsc::channel(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,6 +71,7 @@ impl TemplateApp {
|
|||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl eframe::App for TemplateApp {
|
impl eframe::App for TemplateApp {
|
||||||
@@ -74,12 +85,19 @@ impl eframe::App for TemplateApp {
|
|||||||
// Put your widgets into a `SidePanel`, `TopBottomPanel`, `CentralPanel`, `Window` or `Area`.
|
// Put your widgets into a `SidePanel`, `TopBottomPanel`, `CentralPanel`, `Window` or `Area`.
|
||||||
// For inspiration and more examples, go to https://emilk.github.io/egui
|
// For inspiration and more examples, go to https://emilk.github.io/egui
|
||||||
|
|
||||||
|
let is_web = cfg!(target_arch = "wasm32");
|
||||||
|
|
||||||
|
for i in self.messaging.1.try_iter() {
|
||||||
|
match i {
|
||||||
|
Message::AddTemplate(t) => add_template(&mut self.templates, t.name.clone(), t),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
||||||
// The top panel is often a good place for a menu bar:
|
// The top panel is often a good place for a menu bar:
|
||||||
|
|
||||||
egui::MenuBar::new().ui(ui, |ui| {
|
egui::MenuBar::new().ui(ui, |ui| {
|
||||||
// NOTE: no File->Quit on web pages!
|
// NOTE: no File->Quit on web pages!
|
||||||
let is_web = cfg!(target_arch = "wasm32");
|
|
||||||
if !is_web {
|
if !is_web {
|
||||||
ui.menu_button("File", |ui| {
|
ui.menu_button("File", |ui| {
|
||||||
if ui.button("Quit").clicked() {
|
if ui.button("Quit").clicked() {
|
||||||
@@ -92,40 +110,67 @@ impl eframe::App for TemplateApp {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::TopBottomPanel::bottom("bottom_panel").show(ctx, |ui| {
|
||||||
// The central panel the region left after adding TopPanel's and SidePanel's
|
|
||||||
ui.heading("eframe template");
|
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.label("Write something: ");
|
|
||||||
ui.text_edit_singleline(&mut self.label);
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.add(egui::Slider::new(&mut self.value, 0.0..=10.0).text("value"));
|
|
||||||
if ui.button("test").clicked() {
|
|
||||||
self.value += 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ui.button("rfd").clicked() {
|
|
||||||
let file = test_async(self.cont_mux.clone());
|
|
||||||
}
|
|
||||||
self.content = self.cont_mux.lock().clone();
|
|
||||||
|
|
||||||
ui.text_edit_multiline(&mut self.content);
|
|
||||||
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
ui.add(egui::github_link_file!(
|
|
||||||
"https://github.com/emilk/eframe_template/blob/main/",
|
|
||||||
"Source code."
|
|
||||||
));
|
|
||||||
|
|
||||||
|
|
||||||
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
|
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
|
||||||
powered_by_egui_and_eframe(ui);
|
powered_by_egui_and_eframe(ui);
|
||||||
egui::warn_if_debug_build(ui);
|
egui::warn_if_debug_build(ui);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
// The central panel the region left after adding TopPanel's and SidePanel's
|
||||||
|
egui::containers::Sides::new().show(ui, |ui|{
|
||||||
|
ui.with_layout(Layout::top_down(Align::LEFT), |ui| {
|
||||||
|
ui.heading("eframe template");
|
||||||
|
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("Write something: ");
|
||||||
|
ui.text_edit_singleline(&mut self.label);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ui.button("test").clicked() {
|
||||||
|
self.value += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ui.button("rfd").clicked() {
|
||||||
|
test_async(self.messaging.0.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
|
if self.templates.is_empty() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
egui::containers::ComboBox::from_label("Select a template")
|
||||||
|
.selected_text(self.active_template.clone())
|
||||||
|
.show_ui(ui, |x| {
|
||||||
|
for (name, _) in self.templates.iter() {
|
||||||
|
x.selectable_value(&mut self.active_template, name.clone(), name.clone());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
|
ui.add(egui::github_link_file!(
|
||||||
|
"https://github.com/emilk/eframe_template/blob/main/",
|
||||||
|
"Source code."
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}, |ui| {
|
||||||
|
let selected = match self.templates.get(&self.active_template.clone()) {
|
||||||
|
Some(t) => {
|
||||||
|
let text = t.text_files.iter().next();
|
||||||
|
match text {
|
||||||
|
Some(t) => t.1.clone(),
|
||||||
|
None => "No File Selected".to_string(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => "No File Selected".to_string()
|
||||||
|
};
|
||||||
|
ui.label(selected);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +188,7 @@ fn powered_by_egui_and_eframe(ui: &mut egui::Ui) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_async(test: Arc<Mutex<String>>) {
|
fn test_async(test: mpsc::Sender<Message>) {
|
||||||
// Spawn dialog on main thread
|
// Spawn dialog on main thread
|
||||||
let task = rfd::AsyncFileDialog::new().pick_file();
|
let task = rfd::AsyncFileDialog::new().pick_file();
|
||||||
|
|
||||||
@@ -154,6 +199,7 @@ fn test_async(test: Arc<Mutex<String>>) {
|
|||||||
|
|
||||||
if let Some(file) = file {
|
if let Some(file) = file {
|
||||||
// If you care about wasm support you just read() the file
|
// If you care about wasm support you just read() the file
|
||||||
|
let name = file.file_name();
|
||||||
let output = file.read().await;
|
let output = file.read().await;
|
||||||
|
|
||||||
let string_data = match String::from_utf8(output) {
|
let string_data = match String::from_utf8(output) {
|
||||||
@@ -164,9 +210,7 @@ fn test_async(test: Arc<Mutex<String>>) {
|
|||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
web_sys::console::log_1(&string_data.clone().into());
|
web_sys::console::log_1(&string_data.clone().into());
|
||||||
|
|
||||||
let mut t = test.lock();
|
let _ = test.send(Message::AddTemplate(Template::new(string_data)));
|
||||||
let a = t.deref_mut();
|
|
||||||
*a = string_data;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -183,6 +227,7 @@ fn execute<F: Future<Output = ()> + 'static>(f: F) {
|
|||||||
web_sys::console::log_1(&"Async End".into());
|
web_sys::console::log_1(&"Async End".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FileError {
|
|
||||||
Unknown,
|
fn add_template(map: &mut HashMap<String, Template>, label: String, template: Template) {
|
||||||
|
map.insert(label, template);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
#![warn(clippy::all, rust_2018_idioms)]
|
#![warn(clippy::all, rust_2018_idioms)]
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
|
mod templates;
|
||||||
|
|
||||||
pub use app::TemplateApp;
|
pub use app::TemplateApp;
|
||||||
|
|||||||
52
src/templates.rs
Normal file
52
src/templates.rs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Eq)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct Template {
|
||||||
|
pub name: String,
|
||||||
|
pub text_files: Vec<(String, String)>,
|
||||||
|
pub images: Vec<(String, Vec<u8>)>,
|
||||||
|
pub config: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Template {
|
||||||
|
pub fn new(name: String) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
text_files: Vec::new(),
|
||||||
|
images: Vec::new(),
|
||||||
|
config: String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Template {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
name: "New_Template".to_string(),
|
||||||
|
text_files: Vec::new(),
|
||||||
|
images: Vec::new(),
|
||||||
|
config: String::new() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Template {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.name == other.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<String> for Template {
|
||||||
|
fn eq(&self, other: &String) -> bool {
|
||||||
|
&self.name == other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for Template {
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.name.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user