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]
name = "calcifer"
version = "1.3.2"
version = "1.4.0"
edition = "2021"
# 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 {
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())
.id_source(&file_id)
.default_open(self.tree_dir_opened.contains(&file_id))
let collapsing_response = egui::CollapsingHeader::new(file.name.clone())
.id_source(&file.id)
.default_open(self.tree_dir_opened.contains(&file_path_id))
.show(ui, |ui| {
if !self.tree_dir_opened.contains(&file_id) {
if !self.tree_dir_opened.contains(&file_path_id) {
return;
}
for deeper_file in folder_content {
@ -225,9 +225,9 @@ impl Calcifer {
}
});
if collapsing_response.fully_closed() {
self.tree_dir_opened.retain(|s| s != &file_id);
} else if !self.tree_dir_opened.contains(&file_id) {
self.tree_dir_opened.push(file_id);
self.tree_dir_opened.retain(|s| s != &file_path_id);
} else if !self.tree_dir_opened.contains(&file_path_id) {
self.tree_dir_opened.push(file_path_id);
return !file.content_checked;
}
return check_for_update;

View file

@ -53,19 +53,26 @@ impl Calcifer {
if !self.tree_visible {
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| {
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.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| {
if let Some(file_tree) = self.file_tree.clone() {
let update_requested = self.list_files(ui, &file_tree, &mut n_files);
@ -80,8 +87,9 @@ impl Calcifer {
}
ui.separator();
});
self.n_file_displayed = n_files;
});
self.n_file_displayed = n_files;
}
pub fn draw_bottom_tray(&mut self, ctx: &egui::Context) {
@ -211,7 +219,7 @@ impl Calcifer {
if ui
.add(
egui::Label::new(
egui::RichText::new(" X ").color(color),
egui::RichText::new(" ").color(color),
)
.sense(egui::Sense::click()),
)
@ -282,6 +290,25 @@ impl Calcifer {
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.monospace(
self.tabs[self.selected_tab]

View file

@ -211,11 +211,6 @@ impl eframe::App for Calcifer {
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) {
self.handle_save_file(self.save_tab_as());
}

View file

@ -4,6 +4,11 @@ use std::{
fs, io,
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;
@ -13,53 +18,72 @@ pub struct FileEntry {
pub path: PathBuf,
pub folder_content: Option<Vec<FileEntry>>,
pub content_checked: bool,
pub id: String,
}
impl FileEntry {
pub fn new_entry(name: String, path: PathBuf) -> Self {
Self {
name,
path,
path: path.clone(),
folder_content: None,
content_checked: true,
id: Self::generate_unique_id(path),
}
}
pub fn end_of_branch(name: String, path: PathBuf) -> Self {
Self {
name,
path,
path: path.clone(),
folder_content: Some(vec![]),
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 {
if opened_dirs.contains(&get_file_id(&file)) {
if let Some(folder_content) = &file.folder_content {
if !file.content_checked {
return generate_folder_entry(&file.path);
}
let updated_content: Vec<FileEntry> = folder_content
.iter()
.map(|entry| update_file_tree(entry.clone(), opened_dirs.clone()))
.collect();
FileEntry {
name: file.name,
path: file.path,
folder_content: Some(updated_content),
content_checked: true,
}
} else {
file
}
} else {
file
if !opened_dirs.contains(&get_file_path_id(&file.path)) {
return file;
}
if !file.content_checked {
let folder = generate_folder_entry(&file.path);
return update_file_tree(folder, opened_dirs);
}
if file.folder_content.is_none() {
return file;
}
let folder_content = file.folder_content.expect("should have checked if none");
let updated_content: Vec<FileEntry> = folder_content
.iter()
.map(|entry| update_file_tree(entry.clone(), opened_dirs.clone()))
.collect();
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 {
format!("#{}",file.path.clone().display())
pub fn get_file_path_id(path: &PathBuf) -> String {
format!("#{}", path.clone().display())
}
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(),
folder_content: Some(folder_content),
content_checked: true,
id: FileEntry::generate_unique_id(path.to_path_buf()),
}
}
}