diff --git a/src/core/app.rs b/src/core/app.rs index 0b1df0e..4d09403 100644 --- a/src/core/app.rs +++ b/src/core/app.rs @@ -8,7 +8,6 @@ use crate::panels; use crate::save_path; use crate::sub_windows; use crate::Calcifer; -use crate::MAX_TABS; use crate::TIME_LABELS; impl Calcifer { @@ -20,12 +19,12 @@ impl Calcifer { if self.refresh_confirm.proceed { self.refresh_confirm.close(); - self.tabs[self.selected_tab.to_index()].refresh(); + self.tabs[self.selected_tab].refresh(); } } pub fn save_tab(&self) -> Option { - if self.tabs[self.selected_tab.to_index()] + if self.tabs[self.selected_tab] .path .file_name() .map_or(true, |name| name.to_string_lossy() == "untitled") @@ -33,13 +32,13 @@ impl Calcifer { self.save_tab_as() } else { if let Err(err) = fs::write( - &self.tabs[self.selected_tab.to_index()].path, - &self.tabs[self.selected_tab.to_index()].code, + &self.tabs[self.selected_tab].path, + &self.tabs[self.selected_tab].code, ) { eprintln!("Error writing file: {}", err); return None; } - Some(self.tabs[self.selected_tab.to_index()].path.clone()) + Some(self.tabs[self.selected_tab].path.clone()) } } @@ -48,7 +47,7 @@ impl Calcifer { .set_directory(self.home.as_path()) .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].code) { eprintln!("Error writing file: {}", err); return None; } @@ -60,8 +59,8 @@ impl Calcifer { pub fn handle_save_file(&mut self, path_option: Option) { if let Some(path) = path_option { println!("File saved successfully at: {:?}", path); - self.tabs[self.selected_tab.to_index()].path = path; - self.tabs[self.selected_tab.to_index()].saved = true; + self.tabs[self.selected_tab].path = path; + self.tabs[self.selected_tab].saved = true; } else { println!("File save failed."); } @@ -112,38 +111,35 @@ impl Calcifer { pub fn move_through_tabs(&mut self, forward: bool) { let new_index = if forward { - (self.selected_tab.to_index() + 1) % self.tabs.len() + (self.selected_tab + 1) % self.tabs.len() } else { self.selected_tab - .to_index() .checked_sub(1) .unwrap_or(self.tabs.len() - 1) }; - self.selected_tab = panels::TabNumber::from_index(new_index); + self.selected_tab = new_index; } pub fn open_file(&mut self, path_option: Option<&Path>) { if let Some(path) = path_option { for (index, tab) in self.tabs.clone().iter().enumerate() { if tab.path == path { - self.selected_tab = panels::TabNumber::from_index(index); + self.selected_tab = index; return; } } } - if self.tabs.len() < MAX_TABS { - if let Some(path) = path_option { - self.tabs.push(panels::Tab::new(path.to_path_buf())); - } else { - self.tabs.push(panels::Tab::default()); - } - self.selected_tab = panels::TabNumber::from_index(self.tabs.len() - 1); + if let Some(path) = path_option { + self.tabs.push(panels::Tab::new(path.to_path_buf())); + } else { + self.tabs.push(panels::Tab::default()); } + self.selected_tab = self.tabs.len() - 1; } pub fn delete_tab(&mut self, index: usize) { self.tabs.remove(index); - self.selected_tab = panels::TabNumber::from_index(min(index, self.tabs.len() - 1)); + self.selected_tab = min(index, self.tabs.len() - 1); } pub fn toggle(&self, ui: &mut egui::Ui, display: bool, title: &str) -> bool { diff --git a/src/core/ui.rs b/src/core/ui.rs index 22d3f5a..dfc56a0 100644 --- a/src/core/ui.rs +++ b/src/core/ui.rs @@ -8,7 +8,6 @@ use crate::editor; use crate::panels; use crate::Calcifer; use crate::DISPLAY_PATH_DEPTH; -use crate::MAX_TABS; use crate::PROJECT_EXTENSION; use crate::RED; use crate::TERMINAL_HEIGHT; @@ -16,450 +15,410 @@ use crate::TERMINAL_RANGE; use editor::{CodeEditor, Syntax}; impl Calcifer { - pub fn draw_settings(&mut self, ctx: &egui::Context) { - egui::SidePanel::left("settings") - .resizable(false) - .exact_width(self.font_size * 1.8) - .show(ctx, |ui| { - ui.vertical(|ui| { - if ui.add(egui::Button::new("📁")).clicked() { - if let Some(path) = rfd::FileDialog::new() - .set_directory(self.home.as_path()) - .pick_file() - { - self.open_file(Some(&path)); - } - } - ui.separator(); - self.tree_visible = self.toggle(ui, self.tree_visible, "📦"); - ui.separator(); - self.terminal_visible = self.toggle(ui, self.terminal_visible, "🖵"); - ui.separator(); - self.search_menu.visible = self.toggle(ui, self.search_menu.visible, "🔍"); - ui.separator(); - self.settings_menu.visible = self.toggle(ui, self.settings_menu.visible, "⚙"); - ui.separator(); - self.shortcuts_menu.visible = self.toggle(ui, self.shortcuts_menu.visible, "⌨"); - ui.separator(); - self.profiler_visible = self.toggle(ui, self.profiler_visible, "⚡"); + pub fn draw_settings(&mut self, ctx: &egui::Context) { + egui::SidePanel::left("settings") + .resizable(false) + .exact_width(self.font_size * 1.8) + .show(ctx, |ui| { + ui.vertical(|ui| { + if ui.add(egui::Button::new("📁")).clicked() { + if let Some(path) = rfd::FileDialog::new() + .set_directory(self.home.as_path()) + .pick_file() + { + self.open_file(Some(&path)); + } + } + ui.separator(); + self.tree_visible = self.toggle(ui, self.tree_visible, "📦"); + ui.separator(); + self.terminal_visible = self.toggle(ui, self.terminal_visible, "🖵"); + ui.separator(); + self.search_menu.visible = self.toggle(ui, self.search_menu.visible, "🔍"); + ui.separator(); + self.settings_menu.visible = self.toggle(ui, self.settings_menu.visible, "⚙"); + ui.separator(); + self.shortcuts_menu.visible = self.toggle(ui, self.shortcuts_menu.visible, "⌨"); + ui.separator(); + self.profiler_visible = self.toggle(ui, self.profiler_visible, "⚡"); - if self.tabs[self.selected_tab.to_index()].language == PROJECT_EXTENSION { - ui.separator(); - self.project_content.item_window.visible = - self.toggle(ui, self.project_content.item_window.visible, "🖊"); - } - }); - }); - } + if self.tabs[self.selected_tab].language == PROJECT_EXTENSION { + ui.separator(); + self.project_content.item_window.visible = + self.toggle(ui, self.project_content.item_window.visible, "🖊"); + } + }); + }); + } - pub fn draw_tree_panel(&mut self, ctx: &egui::Context) { - if !self.tree_visible { - return; - } - if self.file_tree.is_none() { - self.file_tree = Some(panels::generate_folder_entry(self.home.as_path())); - } - let mut n_files: usize = 0; - egui::SidePanel::left("file_tree_panel").show(ctx, |ui| { - ui.horizontal(|ui| { - ui.label("Bookshelf "); - }); - ui.separator(); - ui.label(format!("{} files displayed", self.n_file_displayed)); - ui.separator(); - 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); - if update_requested { - self.file_tree = Some(panels::update_file_tree( - file_tree, - self.tree_dir_opened.clone(), - )); - } - } else { - ui.label("No book on the Bookshelf"); - } - ui.separator(); - }); - }); - self.n_file_displayed = n_files; - } + pub fn draw_tree_panel(&mut self, ctx: &egui::Context) { + if !self.tree_visible { + return; + } + if self.file_tree.is_none() { + self.file_tree = Some(panels::generate_folder_entry(self.home.as_path())); + } + let mut n_files: usize = 0; + egui::SidePanel::left("file_tree_panel").show(ctx, |ui| { + ui.horizontal(|ui| { + ui.label("Bookshelf "); + }); + ui.separator(); + ui.label(format!("{} files displayed", self.n_file_displayed)); + ui.separator(); + 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); + if update_requested { + self.file_tree = Some(panels::update_file_tree( + file_tree, + self.tree_dir_opened.clone(), + )); + } + } else { + ui.label("No book on the Bookshelf"); + } + ui.separator(); + }); + }); + self.n_file_displayed = n_files; + } - pub fn draw_bottom_tray(&mut self, ctx: &egui::Context) { - egui::TopBottomPanel::bottom("tray") - .default_height(self.font_size * 1.2) - .resizable(false) - .show(ctx, |ui| { - ui.label(self.profiler()); - }); - } + pub fn draw_bottom_tray(&mut self, ctx: &egui::Context) { + egui::TopBottomPanel::bottom("tray") + .default_height(self.font_size * 1.2) + .resizable(false) + .show(ctx, |ui| { + ui.label(self.profiler()); + }); + } - pub fn draw_terminal_panel(&mut self, ctx: &egui::Context) { - if !self.terminal_visible { - return; - } - egui::TopBottomPanel::bottom("terminal") - .default_height(TERMINAL_HEIGHT) - .height_range(Rangef::new(TERMINAL_RANGE.start, TERMINAL_RANGE.end)) - .resizable(true) - .show(ctx, |ui| { - ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| { - let command_color = core::hex_str_to_color(self.theme.functions); - let entry_color = core::hex_str_to_color(self.theme.literals); - let bg_color = core::hex_str_to_color(self.theme.bg); + pub fn draw_terminal_panel(&mut self, ctx: &egui::Context) { + if !self.terminal_visible { + return; + } + egui::TopBottomPanel::bottom("terminal") + .default_height(TERMINAL_HEIGHT) + .height_range(Rangef::new(TERMINAL_RANGE.start, TERMINAL_RANGE.end)) + .resizable(true) + .show(ctx, |ui| { + ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| { + let command_color = core::hex_str_to_color(self.theme.functions); + let entry_color = core::hex_str_to_color(self.theme.literals); + let bg_color = core::hex_str_to_color(self.theme.bg); - ui.label(""); + ui.label(""); - ui.horizontal(|ui| { - if ui.add(egui::Button::new("⟳")).clicked() { - self.command_history.retain(|e| !e.finished); - } - ui.style_mut().visuals.extreme_bg_color = bg_color; - let Self { command, .. } = self; - ui.colored_label( - command_color, - format_path(&env::current_dir().unwrap_or_else(|_| PathBuf::from("/"))), - ); - let response = ui.add( - egui::TextEdit::singleline(command) - .desired_width(f32::INFINITY) - .lock_focus(true), - ); + ui.horizontal(|ui| { + if ui.add(egui::Button::new("⟳")).clicked() { + self.command_history.retain(|e| !e.finished); + } + ui.style_mut().visuals.extreme_bg_color = bg_color; + let Self { command, .. } = self; + ui.colored_label( + command_color, + format_path(&env::current_dir().unwrap_or_else(|_| PathBuf::from("/"))), + ); + let response = ui.add( + egui::TextEdit::singleline(command) + .desired_width(f32::INFINITY) + .lock_focus(true), + ); - if response.lost_focus() && ctx.input(|i| i.key_pressed(egui::Key::Enter)) { - self.command_history - .push(panels::send_command(self.command.clone())); - self.command = "".into(); - response.request_focus(); - } - }); - ui.separator(); - egui::ScrollArea::vertical() - .stick_to_bottom(true) - .show(ui, |ui| { - ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| { - ui.separator(); - ui.spacing_mut().item_spacing.y = 0.0; - ui.style_mut().visuals.hyperlink_color = - core::hex_str_to_color(self.theme.keywords); + if response.lost_focus() && ctx.input(|i| i.key_pressed(egui::Key::Enter)) { + self.command_history + .push(panels::send_command(self.command.clone())); + self.command = "".into(); + response.request_focus(); + } + }); + ui.separator(); + egui::ScrollArea::vertical() + .stick_to_bottom(true) + .show(ui, |ui| { + ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| { + ui.separator(); + ui.spacing_mut().item_spacing.y = 0.0; + ui.style_mut().visuals.hyperlink_color = + core::hex_str_to_color(self.theme.keywords); - let mut running_command = false; + let mut running_command = false; - for entry in &mut self.command_history { - ui.label(""); - ui.horizontal(|ui| { - if !entry.finished { - running_command = true; - entry.update(); - let _ = ui.link("(⌛)"); - } else if ui.link("(🗐)").clicked() { - entry.copy_error_code(); - } - ui.colored_label( - command_color, - format!("{} {}", entry.env, entry.command), - ); - }); + for entry in &mut self.command_history { + ui.label(""); + ui.horizontal(|ui| { + if !entry.finished { + running_command = true; + entry.update(); + let _ = ui.link("(⌛)"); + } else if ui.link("(🗐)").clicked() { + entry.copy_error_code(); + } + ui.colored_label( + command_color, + format!("{} {}", entry.env, entry.command), + ); + }); - for line in &entry.result { - let color = if line.error { RED } else { entry_color }; - ui.add( - egui::Label::new( - egui::RichText::new(&line.text) - .monospace() - .color(color), - ), //.selectable(true) - ); - } - } + for line in &entry.result { + let color = if line.error { RED } else { entry_color }; + ui.add( + egui::Label::new( + egui::RichText::new(&line.text) + .monospace() + .color(color), + ), //.selectable(true) + ); + } + } - self.running_command = running_command; - }); - }); - }); - }); - } + self.running_command = running_command; + }); + }); + }); + }); + } - pub fn draw_tab_panel(&mut self, ctx: &egui::Context) { - egui::TopBottomPanel::top("tabs") - .resizable(false) - .show(ctx, |ui| { - ui.horizontal(|ui| { - ui.style_mut().visuals.selection.bg_fill = - core::hex_str_to_color(self.theme.functions); - ui.style_mut().visuals.hyperlink_color = - core::hex_str_to_color(self.theme.functions); - for (index, tab) in self.tabs.clone().iter().enumerate() { - let mut title = tab.get_name(); - if !tab.saved { - title += " ~"; - } - if self.selected_tab == panels::TabNumber::from_index(index) { - ui.style_mut().visuals.override_text_color = - Some(core::hex_str_to_color(self.theme.bg)); - } - ui.selectable_value( - &mut self.selected_tab, - panels::TabNumber::from_index(index), - title, - ); + pub fn draw_tab_panel(&mut self, ctx: &egui::Context) { + egui::TopBottomPanel::top("tabs") + .resizable(false) + .show(ctx, |ui| { + ui.painter().rect_filled( + ui.available_rect_before_wrap(), + 0.0, + core::hex_str_to_color(self.theme.bg), + ); + StripBuilder::new(ui) + .sizes(Size::remainder(), max(10, self.tabs.len() + 1)) + .sense(egui::Sense::click()) + .horizontal(|mut strip| { + for (index, tab) in self.tabs.clone().iter().enumerate() { + strip.cell(|ui| { + let mut color = core::hex_str_to_color(self.theme.comments); + if self.selected_tab == index { + ui.painter().rect_filled( + ui.available_rect_before_wrap(), + 0.0, + core::hex_str_to_color(self.theme.functions), + ); + color = core::hex_str_to_color(self.theme.bg) + } + let unsaved_indicator = if tab.saved { "" } else { "~ " }; + ui.with_layout( + egui::Layout::right_to_left(egui::Align::TOP), + |ui| { + ui.label(""); + if ui + .add( + egui::Label::new( + egui::RichText::new(" X ").color(color), + ) + .sense(egui::Sense::click()), + ) + .clicked() + && !self.close_tab_confirm.visible + { + if self.tabs.len() > 1 { + if tab.saved { + self.delete_tab(index); + } else { + self.close_tab_confirm.ask(); + self.tab_to_close = index; + } + } else { + egui::Context::send_viewport_cmd( + ctx, + egui::ViewportCommand::Close, + ); + } + } + ui.with_layout( + egui::Layout::left_to_right(egui::Align::TOP), + |ui| { + if ui + .add( + egui::Label::new( + egui::RichText::new(format!( + " {}{}", + unsaved_indicator, + tab.get_name() + )) + .color(color), + ) + .truncate(true) + .sense(egui::Sense::click()), + ) + .clicked() + { + self.selected_tab = index; + } + }, + ); + }, + ); + }); + } + strip.cell(|ui| { + if ui + .add(egui::Label::new(" +").sense(egui::Sense::click())) + .clicked() + { + self.open_file(None); + } + }); + }); + }); + } - ui.style_mut().visuals.override_text_color = None; + pub fn draw_content_panel(&mut self, ctx: &egui::Context) { + egui::CentralPanel::default().show(ctx, |ui| { + ui.horizontal(|ui| { + if ui + .add(egui::Button::new("open directory in terminal")) + .clicked() + { + let mut path = self.tabs[self.selected_tab].path.clone(); + path.pop(); + panels::send_command(format!("cd {}", path.display())); + } - if ui.link("X").clicked() && !self.close_tab_confirm.visible { - if self.tabs.len() > 1 { - if tab.saved { - self.delete_tab(index); - } else { - self.close_tab_confirm.ask(); - self.tab_to_close = index; - } - } else { - egui::Context::send_viewport_cmd(ctx, egui::ViewportCommand::Close); - } - } - ui.separator(); - } - if self.tabs.len() < MAX_TABS { - ui.selectable_value(&mut self.selected_tab, panels::TabNumber::Open, "+"); - } - if self.selected_tab == panels::TabNumber::Open { - self.open_file(None); - } - }); - }); - ctx.set_visuals(egui::Visuals::dark()); - } + ui.label("Picked file:"); + ui.monospace( + self.tabs[self.selected_tab] + .path + .to_string_lossy() + .to_string(), + ); + }); - pub fn draw_alternate_tab_panel(&mut self, ctx: &egui::Context) { - egui::TopBottomPanel::top("tabs") - .resizable(false) - .show(ctx, |ui| { - ui.painter().rect_filled( - ui.available_rect_before_wrap(), - 0.0, - core::hex_str_to_color(self.theme.bg), - ); - StripBuilder::new(ui) - .sizes(Size::remainder(), max(10, self.tabs.len() + 1)) - .sense(egui::Sense::click()) - .horizontal(|mut strip| { - for (index, tab) in self.tabs.clone().iter().enumerate() { - strip.cell(|ui| { - let mut color = core::hex_str_to_color(self.theme.comments); - if self.selected_tab == panels::TabNumber::from_index(index) { - ui.painter().rect_filled( - ui.available_rect_before_wrap(), - 0.0, - core::hex_str_to_color(self.theme.functions), - ); - color = core::hex_str_to_color(self.theme.bg) - } - let unsaved_indicator = if tab.saved { "" } else { "~ " }; - ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| { - ui.label(""); - if ui.add( - egui::Label::new( - egui::RichText::new(" X ") - .color(color), - ) - .sense(egui::Sense::click()), - ) - .clicked() && !self.close_tab_confirm.visible - { - if self.tabs.len() > 1 { - if tab.saved { - self.delete_tab(index); - } else { - self.close_tab_confirm.ask(); - self.tab_to_close = index; - } - } else { - egui::Context::send_viewport_cmd(ctx, egui::ViewportCommand::Close); - } - } - ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { - if ui.add( - egui::Label::new( - egui::RichText::new(format!( - " {}{}", - unsaved_indicator, - tab.get_name() - )) - .color(color), - ) - .truncate(true) - .sense(egui::Sense::click()), - ) - .clicked() - { - self.selected_tab = panels::TabNumber::from_index(index); - } - }); - }); - }); - } - strip.cell(|ui| { - if ui - .add(egui::Label::new(" +").sense(egui::Sense::click())) - .clicked() - { - self.open_file(None); - } - }); - }); - }); - } + ui.separator(); + if self.tabs[self.selected_tab].language == PROJECT_EXTENSION { + self.draw_project_file(ui); + } else { + self.draw_code_file(ui); + } + }); + } - pub fn draw_content_panel(&mut self, ctx: &egui::Context) { - egui::CentralPanel::default().show(ctx, |ui| { - ui.horizontal(|ui| { - if ui - .add(egui::Button::new("open directory in terminal")) - .clicked() - { - let mut path = self.tabs[self.selected_tab.to_index()].path.clone(); - path.pop(); - panels::send_command(format!("cd {}", path.display())); - } + fn draw_code_file(&mut self, ui: &mut egui::Ui) { + let current_tab = &mut self.tabs[self.selected_tab]; + let lines = current_tab.code.chars().filter(|&c| c == '\n').count() + 1; + let mut override_cursor: Option = None; - ui.label("Picked file:"); - ui.monospace( - self.tabs[self.selected_tab.to_index()] - .path - .to_string_lossy() - .to_string(), - ); - }); + if !self.search_menu.result_selected { + override_cursor = Some(CCursorRange::two( + CCursor::new(self.search_menu.get_cursor_start()), + CCursor::new(self.search_menu.get_cursor_end()), + )); + self.search_menu.result_selected = true; + } - ui.separator(); - if self.tabs[self.selected_tab.to_index()].language == PROJECT_EXTENSION { - self.draw_project_file(ui); - } else { - self.draw_code_file(ui); - } - }); - } + CodeEditor::default() + .id_source("code editor") + .with_rows(max(45, lines)) + .with_fontsize(self.font_size) + .with_theme(self.theme) + .with_syntax(to_syntax(¤t_tab.language)) + .with_numlines(true) + .show( + ui, + &mut current_tab.code, + &mut current_tab.saved, + &mut current_tab.last_cursor, + &mut current_tab.scroll_offset, + override_cursor, + ); + } - fn draw_code_file(&mut self, ui: &mut egui::Ui) { - let current_tab = &mut self.tabs[self.selected_tab.to_index()]; - let lines = current_tab.code.chars().filter(|&c| c == '\n').count() + 1; - let mut override_cursor: Option = None; + fn draw_project_file(&mut self, ui: &mut egui::Ui) { + let current_tab = &mut self.tabs[self.selected_tab]; - if !self.search_menu.result_selected { - override_cursor = Some(CCursorRange::two( - CCursor::new(self.search_menu.get_cursor_start()), - CCursor::new(self.search_menu.get_cursor_end()), - )); - self.search_menu.result_selected = true; - } + self.project_content + .update_from_code(current_tab.code.clone()); + panels::draw_project(ui, self.theme, &mut self.project_content); - CodeEditor::default() - .id_source("code editor") - .with_rows(max(45, lines)) - .with_fontsize(self.font_size) - .with_theme(self.theme) - .with_syntax(to_syntax(¤t_tab.language)) - .with_numlines(true) - .show( - ui, - &mut current_tab.code, - &mut current_tab.saved, - &mut current_tab.last_cursor, - &mut current_tab.scroll_offset, - override_cursor, - ); - } + match self.project_content.save_to_code() { + Ok(code) => current_tab.code = code, + Err(_err) => (), + } + } - fn draw_project_file(&mut self, ui: &mut egui::Ui) { - let current_tab = &mut self.tabs[self.selected_tab.to_index()]; + pub fn draw_windows(&mut self, ctx: &egui::Context) { + if self.project_content.item_window.visible { + if self.project_content.categories.len() > 1 + && !self.project_content.categories[self.project_content.selected_item.category] + .content + .is_empty() + { + self.project_content.item_window.show( + ctx, + &mut self.project_content.categories + [self.project_content.selected_item.category] + .content[self.project_content.selected_item.row], + ); + } else { + self.project_content.item_window.visible = false; + } + } + if self.search_menu.visible { + self.search_menu + .show(ctx, &mut self.tabs, &mut self.selected_tab); + } + if self.close_tab_confirm.visible { + self.close_tab_confirm.show(ctx); + } + if self.refresh_confirm.visible { + self.refresh_confirm.show(ctx); + } + if self.exit_confirm.visible { + self.exit_confirm.show(ctx); + } + if self.exit_confirm.proceed { + for tab in self.tabs.iter_mut() { + tab.saved = true; + } + egui::Context::send_viewport_cmd(ctx, egui::ViewportCommand::Close); + } + if self.shortcuts_menu.visible { + self.shortcuts_menu.show(ctx); + } + if self.settings_menu.visible { + self.settings_menu.show(ctx); + } + if self.settings_menu.updated { + self.theme = self.settings_menu.theme; + } - self.project_content - .update_from_code(current_tab.code.clone()); - panels::draw_project(ui, self.theme, &mut self.project_content); - - match self.project_content.save_to_code() { - Ok(code) => current_tab.code = code, - Err(_err) => (), - } - } - - pub fn draw_windows(&mut self, ctx: &egui::Context) { - if self.project_content.item_window.visible { - if self.project_content.categories.len() > 1 - && !self.project_content.categories[self.project_content.selected_item.category] - .content - .is_empty() - { - self.project_content.item_window.show( - ctx, - &mut self.project_content.categories - [self.project_content.selected_item.category] - .content[self.project_content.selected_item.row], - ); - } else { - self.project_content.item_window.visible = false; - } - } - if self.search_menu.visible { - self.search_menu - .show(ctx, &mut self.tabs, &mut self.selected_tab); - } - if self.close_tab_confirm.visible { - self.close_tab_confirm.show(ctx); - } - if self.refresh_confirm.visible { - self.refresh_confirm.show(ctx); - } - if self.exit_confirm.visible { - self.exit_confirm.show(ctx); - } - if self.exit_confirm.proceed { - for tab in self.tabs.iter_mut() { - tab.saved = true; - } - egui::Context::send_viewport_cmd(ctx, egui::ViewportCommand::Close); - } - if self.shortcuts_menu.visible { - self.shortcuts_menu.show(ctx); - } - if self.settings_menu.visible { - self.settings_menu.show(ctx); - } - if self.settings_menu.updated { - self.theme = self.settings_menu.theme; - } - - self.handle_confirm(); - } + self.handle_confirm(); + } } fn to_syntax(language: &str) -> Syntax { - match language { - "py" => Syntax::python(), - "rs" => Syntax::rust(), - _ => Syntax::shell(), - } + match language { + "py" => Syntax::python(), + "rs" => Syntax::rust(), + _ => Syntax::shell(), + } } pub fn format_path(path: &Path) -> String { - let components: Vec<&OsStr> = path - .components() - .rev() - .take(DISPLAY_PATH_DEPTH) - .filter_map(|component| match component { - Component::RootDir | Component::CurDir => None, - _ => Some(component.as_os_str()), - }) - .collect(); + let components: Vec<&OsStr> = path + .components() + .rev() + .take(DISPLAY_PATH_DEPTH) + .filter_map(|component| match component { + Component::RootDir | Component::CurDir => None, + _ => Some(component.as_os_str()), + }) + .collect(); - format!( - "{}>", - components - .iter() - .rev() - .map(|&c| c.to_string_lossy()) - .collect::>() - .join("/") - ) + format!( + "{}>", + components + .iter() + .rev() + .map(|&c| c.to_string_lossy()) + .collect::>() + .join("/") + ) } diff --git a/src/main.rs b/src/main.rs index 0389547..4ac61a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,7 +27,6 @@ const TIME_LABELS: [&str; 7] = [ ]; const MAX_FPS: f32 = 30.0; const DISPLAY_PATH_DEPTH: usize = 3; -const MAX_TABS: usize = 20; const MAX_PROJECT_COLUMNS: usize = 8; const RUNNING_COMMAND_REFRESH_DELAY: f32 = 0.1; @@ -59,7 +58,7 @@ fn main() -> Result<(), eframe::Error> { } struct Calcifer { - selected_tab: panels::TabNumber, + selected_tab: usize, tabs: Vec, command: String, @@ -96,7 +95,7 @@ struct Calcifer { impl Default for Calcifer { fn default() -> Self { Self { - selected_tab: panels::TabNumber::from_index(0), + selected_tab: 0, tabs: vec![panels::Tab::default()], command: String::new(), @@ -170,15 +169,15 @@ impl eframe::App for Calcifer { if ctx.input(|i| i.key_pressed(egui::Key::R) && i.modifiers.ctrl) && !self.refresh_confirm.visible { - if self.tabs[self.selected_tab.to_index()].saved { - self.tabs[self.selected_tab.to_index()].refresh(); + if self.tabs[self.selected_tab].saved { + self.tabs[self.selected_tab].refresh(); } else { self.refresh_confirm.ask(); } } if ctx.input(|i| i.key_pressed(egui::Key::Enter)) - && self.tabs[self.selected_tab.to_index()].language == PROJECT_EXTENSION + && self.tabs[self.selected_tab].language == PROJECT_EXTENSION { self.project_content.item_window.visible = true; } @@ -252,8 +251,7 @@ impl eframe::App for Calcifer { self.time_watch[3] = watch.elapsed().as_micros() as f32 / 1000.0; watch = time::Instant::now(); - //self.draw_tab_panel(ctx); - self.draw_alternate_tab_panel(ctx); + self.draw_tab_panel(ctx); self.time_watch[4] = watch.elapsed().as_micros() as f32 / 1000.0; watch = time::Instant::now(); diff --git a/src/panels/tabs.rs b/src/panels/tabs.rs index 09748b9..6c07731 100644 --- a/src/panels/tabs.rs +++ b/src/panels/tabs.rs @@ -1,30 +1,6 @@ use eframe::egui::text_edit::CCursorRange; use std::{fs::read_to_string, path::Path, path::PathBuf}; -use crate::MAX_TABS; - -#[derive(Debug, PartialEq, Eq, Clone)] -pub enum TabNumber { - Open, - Number(u8), // Using a range for numeric values -} - -impl TabNumber { - pub fn from_index(n: usize) -> TabNumber { - match n { - 0..=MAX_TABS => TabNumber::Number(n as u8), - _ => TabNumber::Number(0), - } - } - - pub fn to_index(&self) -> usize { - match self { - TabNumber::Number(n) => *n as usize, - _ => 0, - } - } -} - #[derive(Clone, PartialEq)] pub struct Tab { pub path: PathBuf, diff --git a/src/sub_windows/search.rs b/src/sub_windows/search.rs index 7911a3f..c05e15c 100644 --- a/src/sub_windows/search.rs +++ b/src/sub_windows/search.rs @@ -1,7 +1,7 @@ use eframe::egui; use std::cmp::min; -use crate::panels::{Tab, TabNumber}; +use crate::panels::Tab; use crate::RED; enum Action { @@ -12,23 +12,13 @@ enum Action { None, } -#[derive(Clone)] +#[derive(Clone, Default)] pub struct Selection { - pub tab: TabNumber, + pub tab: usize, pub start: usize, pub end: usize, } -impl Default for Selection { - fn default() -> Self { - Self { - tab: TabNumber::from_index(0), - start: 0, - end: 0, - } - } -} - pub struct SearchWindow { pub visible: bool, @@ -72,7 +62,7 @@ impl Default for SearchWindow { } impl SearchWindow { - pub fn show(&mut self, ctx: &egui::Context, tabs: &mut Vec, selected_tab: &mut TabNumber) { + pub fn show(&mut self, ctx: &egui::Context, tabs: &mut Vec, selected_tab: &mut usize) { let mut visible = self.visible; egui::Window::new("Search") .open(&mut visible) //I want it to be able to change its visibility (if user close manually) @@ -82,7 +72,7 @@ impl SearchWindow { self.visible = self.visible && visible; } - fn ui(&mut self, ui: &mut egui::Ui, tabs: &mut Vec, selected_tab: &mut TabNumber) { + fn ui(&mut self, ui: &mut egui::Ui, tabs: &mut Vec, selected_tab: &mut usize) { ui.set_min_width(250.0); let font_id = egui::TextStyle::Body.resolve(ui.style()); @@ -171,7 +161,7 @@ impl SearchWindow { self.results[self.current_result].end } - fn search(&mut self, tabs: &mut Vec, selected_tab: &mut TabNumber) { + fn search(&mut self, tabs: &mut Vec, selected_tab: &mut usize) { if self.search_text.is_empty() { return; } @@ -180,14 +170,10 @@ impl SearchWindow { if self.across_documents { for (index, tab) in tabs.iter().enumerate() { - search_results - .extend(self.match_text(tab.code.clone(), TabNumber::from_index(index))); + search_results.extend(self.match_text(tab.code.clone(), index)); } } else { - search_results.extend(self.match_text( - tabs[selected_tab.to_index()].code.clone(), - selected_tab.clone(), - )); + search_results.extend(self.match_text(tabs[*selected_tab].code.clone(), *selected_tab)); } self.searched_text = self.search_text.clone(); @@ -199,11 +185,11 @@ impl SearchWindow { } } - fn match_text(&self, tab_text: String, tab_number: TabNumber) -> Vec { + fn match_text(&self, tab_text: String, tab_number: usize) -> Vec { let matches = tab_text .match_indices(&self.search_text.clone()) .map(|(i, _)| Selection { - tab: tab_number.clone(), + tab: tab_number, start: i, end: i + self.search_text.len(), }) @@ -212,7 +198,7 @@ impl SearchWindow { matches } - fn find_result(&mut self, tabs: &mut Vec, selected_tab: &mut TabNumber, direction: i32) { + fn find_result(&mut self, tabs: &mut Vec, selected_tab: &mut usize, direction: i32) { if self.searched_text != self.search_text { self.search(tabs, &mut *selected_tab); } else if !self.results.is_empty() { @@ -220,33 +206,32 @@ impl SearchWindow { (self.current_result as i32 + direction + self.results.len() as i32) as usize % self.results.len(); self.result_selected = false; - *selected_tab = self.results[self.current_result].tab.clone(); + *selected_tab = self.results[self.current_result].tab; let target = self.results[self.current_result].start; - let code = tabs[selected_tab.to_index()].code.clone(); + let code = tabs[*selected_tab].code.clone(); let (upstream, _downstream) = code.split_at(target); let row = upstream .match_indices(&"\n".to_string()) .collect::>() .len(); - tabs[selected_tab.to_index()].scroll_offset = - self.row_height * row.saturating_sub(5) as f32; + tabs[*selected_tab].scroll_offset = self.row_height * row.saturating_sub(5) as f32; } } - fn replace(&mut self, tabs: &mut Vec, selected_tab: &mut TabNumber) { + fn replace(&mut self, tabs: &mut Vec, selected_tab: &mut usize) { self.search(tabs, &mut *selected_tab); - let mut done: Vec = vec![]; + let mut done: Vec = vec![]; for element in &self.results { if done.contains(&element.tab) { continue; } - tabs[element.tab.to_index()].code = tabs[element.tab.to_index()] + tabs[element.tab].code = tabs[element.tab] .code .replace(&self.search_text, &self.replace_text); - tabs[element.tab.to_index()].saved = false; - done.push(element.tab.clone()) + tabs[element.tab].saved = false; + done.push(element.tab) } } }