reworked file tree

This commit is contained in:
WanderingPenwing 2024-07-22 15:33:24 +02:00
parent 5f3b199684
commit 297f53198f
6 changed files with 97 additions and 50 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "calcifer" name = "calcifer"
version = "1.3.2" version = "1.4.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -1 +1 @@
{"categories":[{"name":"to do","content":[{"name":"bug project","description":"when switching tabs between two project file, if item window is open it crashes","id":1},{"name":"update workflow .yml","description":"make a workflow compiling the calcifer and put the linux in calcifer-{version}\nand the windows in calcifer_windows_{version}\n\nupdate nix\nupdate jiji","id":5},{"name":"open dir in tree ?","description":"// Hello there","id":2},{"name":"fix tab title","description":"// Hello there","id":2}]},{"name":"in progress","content":[{"name":"export copy paste fix","description":"// Hello there","id":1}]},{"name":"done","content":[{"name":"move .project file","description":"// Hello there","id":4},{"name":"move config","description":"config from .calcifer/save.json\nto .config/calcifer/state.json","id":1},{"name":"add id to textarea per tab","description":"to improve undo, make each code area of each tab have a unique id (no more undo into another tab)","id":1},{"name":"file tree id ?","description":"// Hello there","id":1}]},{"name":"+","content":[]}]} {"categories":[{"name":"to do","content":[{"name":"bug project","description":"when switching tabs between two project file, if item window is open it crashes","id":1},{"name":"update workflow .yml","description":"make a workflow compiling the calcifer and put the linux in calcifer-{version}\nand the windows in calcifer_windows_{version}\n\nupdate nix\nupdate jiji","id":5},{"name":"fix tab title","description":"// Hello there","id":2}]},{"name":"in progress","content":[{"name":"export copy paste fix","description":"// Hello there","id":1}]},{"name":"done","content":[{"name":"move .project file","description":"// Hello there","id":4},{"name":"move config","description":"config from .calcifer/save.json\nto .config/calcifer/state.json","id":1},{"name":"add id to textarea per tab","description":"to improve undo, make each code area of each tab have a unique id (no more undo into another tab)","id":1},{"name":"file tree id ?","description":"// Hello there","id":1},{"name":"open dir in tree ?","description":"// Hello there","id":2}]},{"name":"+","content":[]}]}

View file

@ -209,13 +209,13 @@ impl Calcifer {
if let Some(folder_content) = &file.folder_content { if let Some(folder_content) = &file.folder_content {
let mut check_for_update: bool = false; let mut check_for_update: bool = false;
let file_id = panels::get_file_id(&file); let file_path_id = panels::get_file_path_id(&file.path);
let collapsing_response = egui::CollapsingHeader::new(&file.name.clone()) let collapsing_response = egui::CollapsingHeader::new(file.name.clone())
.id_source(&file_id) .id_source(&file.id)
.default_open(self.tree_dir_opened.contains(&file_id)) .default_open(self.tree_dir_opened.contains(&file_path_id))
.show(ui, |ui| { .show(ui, |ui| {
if !self.tree_dir_opened.contains(&file_id) { if !self.tree_dir_opened.contains(&file_path_id) {
return; return;
} }
for deeper_file in folder_content { for deeper_file in folder_content {
@ -225,9 +225,9 @@ impl Calcifer {
} }
}); });
if collapsing_response.fully_closed() { if collapsing_response.fully_closed() {
self.tree_dir_opened.retain(|s| s != &file_id); self.tree_dir_opened.retain(|s| s != &file_path_id);
} else if !self.tree_dir_opened.contains(&file_id) { } else if !self.tree_dir_opened.contains(&file_path_id) {
self.tree_dir_opened.push(file_id); self.tree_dir_opened.push(file_path_id);
return !file.content_checked; return !file.content_checked;
} }
return check_for_update; return check_for_update;

View file

@ -53,19 +53,26 @@ impl Calcifer {
if !self.tree_visible { if !self.tree_visible {
return; return;
} }
let mut init_update : bool = false;
if self.file_tree.is_none() {
self.file_tree = Some(panels::generate_folder_entry(self.home.as_path()));
init_update = true
}
let mut n_files: usize = 0;
egui::SidePanel::left("file_tree_panel").show(ctx, |ui| { egui::SidePanel::left("file_tree_panel").show(ctx, |ui| {
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Bookshelf "); ui.label(format!("Bookshelf ({} files) ", self.n_file_displayed));
if ui.button("").clicked() {
self.file_tree = None;
}
if ui.button("🗙").clicked() {
self.file_tree = None;
self.tree_dir_opened = vec![];
}
}); });
ui.separator(); ui.separator();
ui.label(format!("{} files displayed", self.n_file_displayed));
ui.separator(); let mut init_update : bool = false;
if self.file_tree.is_none() {
self.file_tree = Some(panels::generate_folder_entry(self.home.as_path()));
init_update = true
}
let mut n_files: usize = 0;
egui::ScrollArea::vertical().show(ui, |ui| { egui::ScrollArea::vertical().show(ui, |ui| {
if let Some(file_tree) = self.file_tree.clone() { if let Some(file_tree) = self.file_tree.clone() {
let update_requested = self.list_files(ui, &file_tree, &mut n_files); let update_requested = self.list_files(ui, &file_tree, &mut n_files);
@ -80,8 +87,9 @@ impl Calcifer {
} }
ui.separator(); ui.separator();
}); });
self.n_file_displayed = n_files;
}); });
self.n_file_displayed = n_files;
} }
pub fn draw_bottom_tray(&mut self, ctx: &egui::Context) { pub fn draw_bottom_tray(&mut self, ctx: &egui::Context) {
@ -211,7 +219,7 @@ impl Calcifer {
if ui if ui
.add( .add(
egui::Label::new( egui::Label::new(
egui::RichText::new(" X ").color(color), egui::RichText::new(" ").color(color),
) )
.sense(egui::Sense::click()), .sense(egui::Sense::click()),
) )
@ -281,6 +289,25 @@ impl Calcifer {
path.pop(); path.pop();
panels::send_command(format!("cd {}", path.display())); panels::send_command(format!("cd {}", path.display()));
} }
if ui
.add(egui::Button::new("expand tree"))
.clicked()
{
let mut current_path = self.tabs[self.selected_tab].path.clone();
current_path.pop();
while let Some(parent) = current_path.parent() {
let dir_id = panels::get_file_path_id(&current_path);
if !self.tree_dir_opened.contains(&dir_id) {
self.tree_dir_opened.push(dir_id);
}
current_path = parent.to_path_buf();
}
self.tree_visible = true;
self.file_tree = None;
}
ui.label("Picked file:"); ui.label("Picked file:");
ui.monospace( ui.monospace(

View file

@ -211,11 +211,6 @@ impl eframe::App for Calcifer {
self.handle_save_file(self.save_tab()); self.handle_save_file(self.save_tab());
} }
if ctx.input(|i| i.key_pressed(egui::Key::T) && i.modifiers.ctrl) {
self.file_tree = None;
self.tree_dir_opened = vec![];
}
if ctx.input(|i| i.key_pressed(egui::Key::S) && i.modifiers.ctrl && i.modifiers.shift) { if ctx.input(|i| i.key_pressed(egui::Key::S) && i.modifiers.ctrl && i.modifiers.shift) {
self.handle_save_file(self.save_tab_as()); self.handle_save_file(self.save_tab_as());
} }

View file

@ -4,6 +4,11 @@ use std::{
fs, io, fs, io,
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use std::hash::DefaultHasher;
use std::time::UNIX_EPOCH;
use std::time::SystemTime;
use std::hash::Hasher;
use std::hash::Hash;
//use crate::ALLOWED_FILE_EXTENSIONS; //use crate::ALLOWED_FILE_EXTENSIONS;
@ -13,53 +18,72 @@ pub struct FileEntry {
pub path: PathBuf, pub path: PathBuf,
pub folder_content: Option<Vec<FileEntry>>, pub folder_content: Option<Vec<FileEntry>>,
pub content_checked: bool, pub content_checked: bool,
pub id: String,
} }
impl FileEntry { impl FileEntry {
pub fn new_entry(name: String, path: PathBuf) -> Self { pub fn new_entry(name: String, path: PathBuf) -> Self {
Self { Self {
name, name,
path, path: path.clone(),
folder_content: None, folder_content: None,
content_checked: true, content_checked: true,
id: Self::generate_unique_id(path),
} }
} }
pub fn end_of_branch(name: String, path: PathBuf) -> Self { pub fn end_of_branch(name: String, path: PathBuf) -> Self {
Self { Self {
name, name,
path, path: path.clone(),
folder_content: Some(vec![]), folder_content: Some(vec![]),
content_checked: false, content_checked: false,
id: Self::generate_unique_id(path),
} }
} }
fn generate_unique_id(path: PathBuf) -> String {
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
let mut hasher = DefaultHasher::new();
now.hash(&mut hasher);
let hash = hasher.finish();
format!("{}#{}", path.display(), hash)
}
} }
pub fn update_file_tree(file: FileEntry, opened_dirs: Vec<String>) -> FileEntry { pub fn update_file_tree(file: FileEntry, opened_dirs: Vec<String>) -> FileEntry {
if opened_dirs.contains(&get_file_id(&file)) { if !opened_dirs.contains(&get_file_path_id(&file.path)) {
if let Some(folder_content) = &file.folder_content { return file;
if !file.content_checked { }
return generate_folder_entry(&file.path);
} if !file.content_checked {
let updated_content: Vec<FileEntry> = folder_content let folder = generate_folder_entry(&file.path);
.iter() return update_file_tree(folder, opened_dirs);
.map(|entry| update_file_tree(entry.clone(), opened_dirs.clone())) }
.collect();
FileEntry { if file.folder_content.is_none() {
name: file.name, return file;
path: file.path, }
folder_content: Some(updated_content),
content_checked: true, let folder_content = file.folder_content.expect("should have checked if none");
}
} else { let updated_content: Vec<FileEntry> = folder_content
file .iter()
} .map(|entry| update_file_tree(entry.clone(), opened_dirs.clone()))
} else { .collect();
file FileEntry {
name: file.name,
path: file.path.clone(),
folder_content: Some(updated_content),
content_checked: true,
id: FileEntry::generate_unique_id(file.path),
} }
} }
pub fn get_file_id(file: &FileEntry) -> String { pub fn get_file_path_id(path: &PathBuf) -> String {
format!("#{}",file.path.clone().display()) format!("#{}", path.clone().display())
} }
pub fn generate_folder_entry(path: &Path) -> FileEntry { pub fn generate_folder_entry(path: &Path) -> FileEntry {
@ -106,6 +130,7 @@ pub fn generate_folder_entry(path: &Path) -> FileEntry {
path: path.to_path_buf(), path: path.to_path_buf(),
folder_content: Some(folder_content), folder_content: Some(folder_content),
content_checked: true, content_checked: true,
id: FileEntry::generate_unique_id(path.to_path_buf()),
} }
} }
} }