better error handeling of tree
This commit is contained in:
parent
829e1deb6a
commit
1277870097
|
@ -1,6 +1,6 @@
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use egui::Color32;
|
use egui::Color32;
|
||||||
use std::{cmp::min, fs, io, path::Path, path::PathBuf};
|
use std::{cmp::min, fs, io, path::Path, path::PathBuf, ffi::OsStr};
|
||||||
|
|
||||||
use crate::tools;
|
use crate::tools;
|
||||||
use crate::Calcifer;
|
use crate::Calcifer;
|
||||||
|
@ -11,230 +11,231 @@ use crate::SAVE_PATH;
|
||||||
use crate::TIME_LABELS;
|
use crate::TIME_LABELS;
|
||||||
|
|
||||||
impl Calcifer {
|
impl Calcifer {
|
||||||
pub fn handle_confirm(&mut self) {
|
pub fn handle_confirm(&mut self) {
|
||||||
if self.close_tab_confirm.proceed {
|
if self.close_tab_confirm.proceed {
|
||||||
self.close_tab_confirm.close();
|
self.close_tab_confirm.close();
|
||||||
self.delete_tab(self.tab_to_close);
|
self.delete_tab(self.tab_to_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.refresh_confirm.proceed {
|
if self.refresh_confirm.proceed {
|
||||||
self.refresh_confirm.close();
|
self.refresh_confirm.close();
|
||||||
self.tabs[self.selected_tab.to_index()].refresh();
|
self.tabs[self.selected_tab.to_index()].refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_tab(&self) -> Option<PathBuf> {
|
pub fn save_tab(&self) -> Option<PathBuf> {
|
||||||
if self.tabs[self.selected_tab.to_index()]
|
if self.tabs[self.selected_tab.to_index()]
|
||||||
.path
|
.path
|
||||||
.file_name()
|
.file_name()
|
||||||
.expect("Could not get Tab Name")
|
.expect("Could not get Tab Name")
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
== "untitled"
|
== "untitled"
|
||||||
{
|
{
|
||||||
self.save_tab_as()
|
self.save_tab_as()
|
||||||
} else {
|
} else {
|
||||||
if let Err(err) = fs::write(
|
if let Err(err) = fs::write(
|
||||||
&self.tabs[self.selected_tab.to_index()].path,
|
&self.tabs[self.selected_tab.to_index()].path,
|
||||||
&self.tabs[self.selected_tab.to_index()].code,
|
&self.tabs[self.selected_tab.to_index()].code,
|
||||||
) {
|
) {
|
||||||
eprintln!("Error writing file: {}", err);
|
eprintln!("Error writing file: {}", err);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(self.tabs[self.selected_tab.to_index()].path.clone())
|
Some(self.tabs[self.selected_tab.to_index()].path.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_tab_as(&self) -> Option<PathBuf> {
|
pub fn save_tab_as(&self) -> Option<PathBuf> {
|
||||||
if let Some(path) = rfd::FileDialog::new()
|
if let Some(path) = rfd::FileDialog::new()
|
||||||
.set_directory(Path::new(&PATH_ROOT))
|
.set_directory(Path::new(&PATH_ROOT))
|
||||||
.save_file()
|
.save_file()
|
||||||
{
|
{
|
||||||
if let Err(err) = fs::write(&path, &self.tabs[self.selected_tab.to_index()].code) {
|
if let Err(err) = fs::write(&path, &self.tabs[self.selected_tab.to_index()].code) {
|
||||||
eprintln!("Error writing file: {}", err);
|
eprintln!("Error writing file: {}", err);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
return Some(path);
|
return Some(path);
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_save_file(&mut self, path_option: Option<PathBuf>) {
|
pub fn handle_save_file(&mut self, path_option: Option<PathBuf>) {
|
||||||
if let Some(path) = path_option {
|
if let Some(path) = path_option {
|
||||||
println!("File saved successfully at: {:?}", path);
|
println!("File saved successfully at: {:?}", path);
|
||||||
self.tabs[self.selected_tab.to_index()].path = path;
|
self.tabs[self.selected_tab.to_index()].path = path;
|
||||||
self.tabs[self.selected_tab.to_index()].saved = true;
|
self.tabs[self.selected_tab.to_index()].saved = true;
|
||||||
} else {
|
} else {
|
||||||
println!("File save failed.");
|
println!("File save failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_app_state(app_state: tools::AppState) -> Self {
|
pub fn from_app_state(app_state: tools::AppState) -> Self {
|
||||||
let mut new = Self {
|
let mut new = Self {
|
||||||
theme: DEFAULT_THEMES[min(app_state.theme, DEFAULT_THEMES.len() - 1)],
|
theme: DEFAULT_THEMES[min(app_state.theme, DEFAULT_THEMES.len() - 1)],
|
||||||
tabs: Vec::new(),
|
tabs: Vec::new(),
|
||||||
settings_menu: tools::settings::SettingsWindow::new(DEFAULT_THEMES[app_state.theme]),
|
settings_menu: tools::settings::SettingsWindow::new(DEFAULT_THEMES[app_state.theme]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
for path in app_state.tabs {
|
for path in app_state.tabs {
|
||||||
if path
|
if path
|
||||||
.file_name()
|
.file_name()
|
||||||
.expect("Could not get Tab Name")
|
.expect("Could not get Tab Name")
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
!= "untitled"
|
!= "untitled"
|
||||||
{
|
{
|
||||||
new.open_file(Some(&path));
|
new.open_file(Some(&path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if new.tabs == vec![] {
|
if new.tabs == vec![] {
|
||||||
new.open_file(None);
|
new.open_file(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
new
|
new
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_state(&self) {
|
pub fn save_state(&self) {
|
||||||
let mut state_theme: usize = 0;
|
let mut state_theme: usize = 0;
|
||||||
if let Some(theme) = DEFAULT_THEMES.iter().position(|&r| r == self.theme) {
|
if let Some(theme) = DEFAULT_THEMES.iter().position(|&r| r == self.theme) {
|
||||||
state_theme = theme;
|
state_theme = theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut state_tabs = vec![];
|
let mut state_tabs = vec![];
|
||||||
|
|
||||||
for tab in &self.tabs {
|
for tab in &self.tabs {
|
||||||
state_tabs.push(tab.path.clone());
|
state_tabs.push(tab.path.clone());
|
||||||
}
|
}
|
||||||
let app_state = tools::AppState {
|
let app_state = tools::AppState {
|
||||||
tabs: state_tabs,
|
tabs: state_tabs,
|
||||||
theme: state_theme,
|
theme: state_theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = tools::save_state(&app_state, SAVE_PATH);
|
let _ = tools::save_state(&app_state, SAVE_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_through_tabs(&mut self, forward: bool) {
|
pub fn move_through_tabs(&mut self, forward: bool) {
|
||||||
let new_index = if forward {
|
let new_index = if forward {
|
||||||
(self.selected_tab.to_index() + 1) % self.tabs.len()
|
(self.selected_tab.to_index() + 1) % self.tabs.len()
|
||||||
} else {
|
} else {
|
||||||
self.selected_tab
|
self.selected_tab
|
||||||
.to_index()
|
.to_index()
|
||||||
.checked_sub(1)
|
.checked_sub(1)
|
||||||
.unwrap_or(self.tabs.len() - 1)
|
.unwrap_or(self.tabs.len() - 1)
|
||||||
};
|
};
|
||||||
self.selected_tab = tools::TabNumber::from_index(new_index);
|
self.selected_tab = tools::TabNumber::from_index(new_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_files(&mut self, ui: &mut egui::Ui, path: &Path) -> io::Result<()> {
|
pub fn list_files(&mut self, ui: &mut egui::Ui, path: &Path) -> io::Result<()> {
|
||||||
if path.file_name().is_none() {
|
if path.file_name().is_none() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = path
|
let name = path
|
||||||
.file_name()
|
.file_name()
|
||||||
.unwrap_or_else(|| OsStr::new(""))
|
.unwrap_or_else(|| OsStr::new(""))
|
||||||
.to_string_lossy();
|
.to_string_lossy()
|
||||||
|
.into_owned();
|
||||||
|
|
||||||
if !path.is_dir() {
|
if !path.is_dir() {
|
||||||
if ui.button(name.to_string_lossy()).clicked() {
|
if ui.button(name).clicked() {
|
||||||
self.open_file(Some(path));
|
self.open_file(Some(path));
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
egui::CollapsingHeader::new(name.to_string_lossy()).show(ui, |ui| {
|
egui::CollapsingHeader::new(name).show(ui, |ui| {
|
||||||
match fs::read_dir(path) {
|
match fs::read_dir(path) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
ui.label(format!("Error reading directory: {}", err));
|
ui.label(format!("Error reading directory: {}", err));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Ok(entries) => {
|
Ok(entries) => {
|
||||||
let mut paths: Vec<Result<fs::DirEntry, io::Error>> = entries
|
let mut paths: Vec<Result<fs::DirEntry, io::Error>> = entries
|
||||||
.map(|r| r.map_err(|e| io::Error::new(io::ErrorKind::Other, e)))
|
.map(|r| r.map_err(|e| io::Error::new(io::ErrorKind::Other, e)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
paths.sort_by(|a, b| match (a, b) {
|
paths.sort_by(|a, b| match (a, b) {
|
||||||
(Ok(entry_a), Ok(entry_b)) => {
|
(Ok(entry_a), Ok(entry_b)) => {
|
||||||
tools::sort_directories_first(&entry_a, &entry_b)
|
tools::sort_directories_first(&entry_a, &entry_b)
|
||||||
}
|
}
|
||||||
(Err(_), Ok(_)) => std::cmp::Ordering::Greater,
|
(Err(_), Ok(_)) => std::cmp::Ordering::Greater,
|
||||||
(Ok(_), Err(_)) => std::cmp::Ordering::Less,
|
(Ok(_), Err(_)) => std::cmp::Ordering::Less,
|
||||||
(Err(_), Err(_)) => std::cmp::Ordering::Equal,
|
(Err(_), Err(_)) => std::cmp::Ordering::Equal,
|
||||||
});
|
});
|
||||||
|
|
||||||
for result in paths {
|
for result in paths {
|
||||||
match result {
|
match result {
|
||||||
Ok(entry) => {
|
Ok(entry) => {
|
||||||
let _ = self.list_files(ui, &entry.path());
|
let _ = self.list_files(ui, &entry.path());
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
ui.label(format!("Error processing directory entry: {}", err));
|
ui.label(format!("Error processing directory entry: {}", err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_file(&mut self, path_option: Option<&Path>) {
|
pub fn open_file(&mut self, path_option: Option<&Path>) {
|
||||||
if self.tabs.len() < MAX_TABS {
|
if self.tabs.len() < MAX_TABS {
|
||||||
if let Some(path) = path_option {
|
if let Some(path) = path_option {
|
||||||
self.tabs.push(tools::Tab::new(path.to_path_buf()));
|
self.tabs.push(tools::Tab::new(path.to_path_buf()));
|
||||||
} else {
|
} else {
|
||||||
self.tabs.push(tools::Tab::default());
|
self.tabs.push(tools::Tab::default());
|
||||||
}
|
}
|
||||||
self.selected_tab = tools::TabNumber::from_index(self.tabs.len() - 1);
|
self.selected_tab = tools::TabNumber::from_index(self.tabs.len() - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_tab(&mut self, index: usize) {
|
pub fn delete_tab(&mut self, index: usize) {
|
||||||
self.tabs.remove(index);
|
self.tabs.remove(index);
|
||||||
self.selected_tab = tools::TabNumber::from_index(min(index, self.tabs.len() - 1));
|
self.selected_tab = tools::TabNumber::from_index(min(index, self.tabs.len() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle(&self, ui: &mut egui::Ui, display: bool, title: &str) -> bool {
|
pub fn toggle(&self, ui: &mut egui::Ui, display: bool, title: &str) -> bool {
|
||||||
let bg_color: Color32;
|
let bg_color: Color32;
|
||||||
let text_color: Color32;
|
let text_color: Color32;
|
||||||
|
|
||||||
if display {
|
if display {
|
||||||
bg_color = Color32::from_hex(self.theme.functions)
|
bg_color = Color32::from_hex(self.theme.functions)
|
||||||
.expect("Could not convert color to hex (functions)");
|
.expect("Could not convert color to hex (functions)");
|
||||||
text_color =
|
text_color =
|
||||||
Color32::from_hex(self.theme.bg).expect("Could not convert color to hex (bg)");
|
Color32::from_hex(self.theme.bg).expect("Could not convert color to hex (bg)");
|
||||||
} else {
|
} else {
|
||||||
bg_color =
|
bg_color =
|
||||||
Color32::from_hex(self.theme.bg).expect("Could not convert color to hex (bg)");
|
Color32::from_hex(self.theme.bg).expect("Could not convert color to hex (bg)");
|
||||||
text_color = Color32::from_hex(self.theme.literals)
|
text_color = Color32::from_hex(self.theme.literals)
|
||||||
.expect("Could not convert color to hex (literals)");
|
.expect("Could not convert color to hex (literals)");
|
||||||
};
|
};
|
||||||
|
|
||||||
ui.style_mut().visuals.override_text_color = Some(text_color);
|
ui.style_mut().visuals.override_text_color = Some(text_color);
|
||||||
|
|
||||||
if ui.add(egui::Button::new(title).fill(bg_color)).clicked() {
|
if ui.add(egui::Button::new(title).fill(bg_color)).clicked() {
|
||||||
return !display;
|
return !display;
|
||||||
}
|
}
|
||||||
ui.style_mut().visuals.override_text_color = None;
|
ui.style_mut().visuals.override_text_color = None;
|
||||||
|
|
||||||
display
|
display
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn profiler(&self) -> String {
|
pub fn profiler(&self) -> String {
|
||||||
if !self.profiler_visible {
|
if !self.profiler_visible {
|
||||||
return "".to_string();
|
return "".to_string();
|
||||||
}
|
}
|
||||||
let combined_string: Vec<String> = TIME_LABELS
|
let combined_string: Vec<String> = TIME_LABELS
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(self.time_watch.clone())
|
.zip(self.time_watch.clone())
|
||||||
.map(|(s, v)| format!("{} : {:.1} ms", s, v))
|
.map(|(s, v)| format!("{} : {:.1} ms", s, v))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut result = combined_string.join(" ; ");
|
let mut result = combined_string.join(" ; ");
|
||||||
result.push_str(&format!(
|
result.push_str(&format!(
|
||||||
" total : {:.1} ms",
|
" total : {:.1} ms",
|
||||||
self.time_watch.clone().iter().sum::<f32>()
|
self.time_watch.clone().iter().sum::<f32>()
|
||||||
));
|
));
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue