From afec8f642634d07114429071993ecf173446addc Mon Sep 17 00:00:00 2001 From: Penwing Date: Thu, 1 Feb 2024 20:46:22 +0100 Subject: [PATCH] added item window, and item movement --- src/core/ui.rs | 615 +++++++++++++------------- src/main.rs | 398 +++++++++-------- src/panels/project_mode.rs | 288 ++++++++---- src/panels/terminal/linux_terminal.rs | 292 ++++++------ src/sub_windows/mod.rs | 3 + src/sub_windows/project_item.rs | 28 ++ src/sub_windows/search.rs | 4 +- 7 files changed, 887 insertions(+), 741 deletions(-) create mode 100644 src/sub_windows/project_item.rs diff --git a/src/core/ui.rs b/src/core/ui.rs index 02cfcf9..814786d 100644 --- a/src/core/ui.rs +++ b/src/core/ui.rs @@ -15,334 +15,345 @@ 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_mode = self.toggle(ui, self.project_mode, "c"); - } - }); - }); - } + // if self.tabs[self.selected_tab.to_index()].language == PROJECT_EXTENSION { + // ui.separator(); + // self.project_mode = self.toggle(ui, self.project_mode, "c"); + // } + }); + }); + } - 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.clone(); - } + 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.clone(); + } - 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); - for entry in &mut self.command_history { - ui.label(""); - ui.horizontal(|ui| { - if !entry.finished { - 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 { + 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.label(egui::RichText::new(&line.text).monospace().color(color)); - } - } - }); - }); - }); - }); - } + for line in &entry.result { + let color = if line.error { RED } else { entry_color }; + ui.label( + egui::RichText::new(&line.text) + .monospace() + .color(color), + ); + } + } + }); + }); + }); + }); + } - 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.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, + ); - ui.style_mut().visuals.override_text_color = None; + ui.style_mut().visuals.override_text_color = None; - 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); - } - }); - }); - } + 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); + } + }); + }); + } - 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())); - } + 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())); + } - ui.label("Picked file:"); - ui.monospace( - self.tabs[self.selected_tab.to_index()] - .path - .to_string_lossy() - .to_string(), - ); - }); + ui.label("Picked file:"); + ui.monospace( + self.tabs[self.selected_tab.to_index()] + .path + .to_string_lossy() + .to_string(), + ); + }); - ui.separator(); - if self.project_mode - && self.tabs[self.selected_tab.to_index()].language == PROJECT_EXTENSION - { - self.draw_project_file(ui); - } else { - self.draw_code_file(ui); - } - }); - } + ui.separator(); + if self.project_mode + && self.tabs[self.selected_tab.to_index()].language == PROJECT_EXTENSION + { + self.draw_project_file(ui); + } else { + self.draw_code_file(ui); + } + }); + } - 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_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; - 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; - } + 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; + } - 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, - ); - } + 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_project_file(&mut self, ui: &mut egui::Ui) { - panels::draw_project(ui, self.theme.clone(), &mut self.project_content); - } + fn draw_project_file(&mut self, ui: &mut egui::Ui) { + panels::draw_project(ui, self.theme.clone(), &mut self.project_content); + } - pub fn draw_windows(&mut self, ctx: &egui::Context) { - 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; - } + pub fn draw_windows(&mut self, ctx: &egui::Context) { + if self.project_content.item_window.visible { + 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], + ); + } + 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 6047577..c11816c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,7 @@ use eframe::egui; use egui::{ - FontFamily, - FontId, - TextStyle::{Body, Button, Heading, Monospace, Small}, + FontFamily, FontId, + TextStyle::{Body, Button, Heading, Monospace, Small}, }; use homedir::get_my_home; use std::{ops::Range, path::PathBuf, sync::Arc, thread, time}; @@ -24,7 +23,7 @@ const TERMINAL_HEIGHT: f32 = 200.0; const TERMINAL_RANGE: Range = 100.0..600.0; const RED: egui::Color32 = egui::Color32::from_rgb(235, 108, 99); const TIME_LABELS: [&str; 7] = [ - "input", "settings", "tree", "terminal", "tabs", "content", "windows", + "input", "settings", "tree", "terminal", "tabs", "content", "windows", ]; const MAX_FPS: f32 = 30.0; const DISPLAY_PATH_DEPTH: usize = 3; @@ -32,248 +31,263 @@ const MAX_TABS: usize = 20; const MAX_PROJECT_COLUMNS: usize = 8; fn main() -> Result<(), eframe::Error> { - let icon_data = core::load_icon().unwrap_or_default(); + let icon_data = core::load_icon().unwrap_or_default(); - let options = eframe::NativeOptions { - viewport: egui::ViewportBuilder::default() - .with_inner_size([1200.0, 800.0]) - .with_icon(Arc::new(icon_data)), - ..Default::default() - }; + let options = eframe::NativeOptions { + viewport: egui::ViewportBuilder::default() + .with_inner_size([1200.0, 800.0]) + .with_icon(Arc::new(icon_data)), + ..Default::default() + }; - // Attempt to load previous state - let app_state: core::AppState = if save_path().exists() { - match core::load_state(save_path().as_path()) { - Ok(app_state) => app_state, - Err(_) => core::AppState::default(), - } - } else { - core::AppState::default() - }; + // Attempt to load previous state + let app_state: core::AppState = if save_path().exists() { + match core::load_state(save_path().as_path()) { + Ok(app_state) => app_state, + Err(_) => core::AppState::default(), + } + } else { + core::AppState::default() + }; - eframe::run_native( - &format!("Calcifer{}", TITLE), - options, - Box::new(move |_cc| Box::from(Calcifer::from_app_state(app_state))), - ) + eframe::run_native( + &format!("Calcifer{}", TITLE), + options, + Box::new(move |_cc| Box::from(Calcifer::from_app_state(app_state))), + ) } struct Calcifer { - selected_tab: panels::TabNumber, - tabs: Vec, + selected_tab: panels::TabNumber, + tabs: Vec, - command: String, - command_history: Vec, + command: String, + command_history: Vec, - theme: editor::ColorTheme, - font_size: f32, + theme: editor::ColorTheme, + font_size: f32, - project_mode: bool, - project_content: panels::Project, + project_mode: bool, + project_content: panels::Project, - home: PathBuf, - tree_dir_opened: Vec, - file_tree: Option, - n_file_displayed: usize, + home: PathBuf, + tree_dir_opened: Vec, + file_tree: Option, + n_file_displayed: usize, - tree_visible: bool, - profiler_visible: bool, - terminal_visible: bool, + tree_visible: bool, + profiler_visible: bool, + terminal_visible: bool, - close_tab_confirm: sub_windows::ConfirmWindow, - tab_to_close: usize, - refresh_confirm: sub_windows::ConfirmWindow, - exit_confirm: sub_windows::ConfirmWindow, + close_tab_confirm: sub_windows::ConfirmWindow, + tab_to_close: usize, + refresh_confirm: sub_windows::ConfirmWindow, + exit_confirm: sub_windows::ConfirmWindow, - search_menu: sub_windows::SearchWindow, - settings_menu: sub_windows::SettingsWindow, - shortcuts_menu: sub_windows::ShortcutsWindow, + search_menu: sub_windows::SearchWindow, + settings_menu: sub_windows::SettingsWindow, + shortcuts_menu: sub_windows::ShortcutsWindow, - time_watch: Vec, - next_frame: time::Instant, + time_watch: Vec, + next_frame: time::Instant, } impl Default for Calcifer { - fn default() -> Self { - Self { - selected_tab: panels::TabNumber::from_index(0), - tabs: vec![panels::Tab::default()], + fn default() -> Self { + Self { + selected_tab: panels::TabNumber::from_index(0), + tabs: vec![panels::Tab::default()], - command: String::new(), - command_history: Vec::new(), + command: String::new(), + command_history: Vec::new(), - theme: editor::themes::DEFAULT_THEMES[0], - font_size: 14.0, + theme: editor::themes::DEFAULT_THEMES[0], + font_size: 14.0, - project_mode: true, - project_content: panels::Project::new(), + project_mode: true, + project_content: panels::Project::new(), - home: get_my_home().unwrap().unwrap(), - tree_dir_opened: vec![], - file_tree: None, - n_file_displayed: 0, + home: get_my_home().unwrap().unwrap(), + tree_dir_opened: vec![], + file_tree: None, + n_file_displayed: 0, - tree_visible: false, - profiler_visible: false, - terminal_visible: false, + tree_visible: false, + profiler_visible: false, + terminal_visible: false, - close_tab_confirm: sub_windows::ConfirmWindow::new( - "You have some unsaved changes, Do you still want to close this document ?", - "Confirm Close", - ), - tab_to_close: 0, - refresh_confirm: sub_windows::ConfirmWindow::new( - "You have some unsaved changes, Do you still want to refresh this document ?", - "Confirm Refresh", - ), - exit_confirm: sub_windows::ConfirmWindow::new("", "Confirm Exit"), + close_tab_confirm: sub_windows::ConfirmWindow::new( + "You have some unsaved changes, Do you still want to close this document ?", + "Confirm Close", + ), + tab_to_close: 0, + refresh_confirm: sub_windows::ConfirmWindow::new( + "You have some unsaved changes, Do you still want to refresh this document ?", + "Confirm Refresh", + ), + exit_confirm: sub_windows::ConfirmWindow::new("", "Confirm Exit"), - search_menu: sub_windows::SearchWindow::default(), - settings_menu: sub_windows::SettingsWindow::new(editor::themes::DEFAULT_THEMES[0]), - shortcuts_menu: sub_windows::ShortcutsWindow::new(), + search_menu: sub_windows::SearchWindow::default(), + settings_menu: sub_windows::SettingsWindow::new(editor::themes::DEFAULT_THEMES[0]), + shortcuts_menu: sub_windows::ShortcutsWindow::new(), - time_watch: vec![0.0; TIME_LABELS.len()], - next_frame: time::Instant::now(), - } - } + time_watch: vec![0.0; TIME_LABELS.len()], + next_frame: time::Instant::now(), + } + } } impl eframe::App for Calcifer { - fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - thread::sleep(time::Duration::from_secs_f32( - ((1.0 / MAX_FPS) - self.next_frame.elapsed().as_secs_f32()).max(0.0), - )); - self.next_frame = time::Instant::now(); + fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { + thread::sleep(time::Duration::from_secs_f32( + ((1.0 / MAX_FPS) - self.next_frame.elapsed().as_secs_f32()).max(0.0), + )); + self.next_frame = time::Instant::now(); - let mut watch = time::Instant::now(); + let mut watch = time::Instant::now(); - let mut style = (*ctx.style()).clone(); - style.text_styles = [ - (Heading, FontId::new(self.font_size * 1.6, FontFamily::Proportional)), - (Body, FontId::new(self.font_size, FontFamily::Proportional)), - (Monospace, FontId::new(self.font_size, FontFamily::Monospace)), - (Button, FontId::new(self.font_size, FontFamily::Proportional)), - (Small, FontId::new(self.font_size, FontFamily::Proportional)), - ] - .into(); - ctx.set_style(style); + let mut style = (*ctx.style()).clone(); + style.text_styles = [ + ( + Heading, + FontId::new(self.font_size * 1.6, FontFamily::Proportional), + ), + (Body, FontId::new(self.font_size, FontFamily::Proportional)), + ( + Monospace, + FontId::new(self.font_size, FontFamily::Monospace), + ), + ( + Button, + FontId::new(self.font_size, FontFamily::Proportional), + ), + (Small, FontId::new(self.font_size, FontFamily::Proportional)), + ] + .into(); + ctx.set_style(style); - 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(); - } else { - self.refresh_confirm.ask(); - } - } + 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(); + } else { + self.refresh_confirm.ask(); + } + } - if ctx.input(|i| i.key_pressed(egui::Key::S) && i.modifiers.ctrl) { - self.handle_save_file(self.save_tab()); - } + if ctx.input(|i| i.key_pressed(egui::Key::Enter)) + && self.tabs[self.selected_tab.to_index()].language == PROJECT_EXTENSION + { + self.project_content.item_window.visible = true; + } - if ctx.input(|i| i.key_pressed(egui::Key::S) && i.modifiers.ctrl && i.modifiers.shift) { - self.handle_save_file(self.save_tab_as()); - } + if ctx.input(|i| i.key_pressed(egui::Key::S) && i.modifiers.ctrl) { + self.handle_save_file(self.save_tab()); + } - if ctx.input(|i| i.key_pressed(egui::Key::ArrowLeft) && i.modifiers.alt) { - self.move_through_tabs(false); - } + if ctx.input(|i| i.key_pressed(egui::Key::S) && i.modifiers.ctrl && i.modifiers.shift) { + self.handle_save_file(self.save_tab_as()); + } - if ctx.input(|i| i.key_pressed(egui::Key::ArrowRight) && i.modifiers.alt) { - self.move_through_tabs(true); - } + if ctx.input(|i| i.key_pressed(egui::Key::ArrowLeft) && i.modifiers.alt) { + self.move_through_tabs(false); + } - if ctx.input(|i| i.zoom_delta() > 1.0) { - self.font_size = (self.font_size * 1.1).min(30.0); - } + if ctx.input(|i| i.key_pressed(egui::Key::ArrowRight) && i.modifiers.alt) { + self.move_through_tabs(true); + } - if ctx.input(|i| i.zoom_delta() < 1.0) { - self.font_size = (self.font_size / 1.1).max(10.0); - } + if ctx.input(|i| i.zoom_delta() > 1.0) { + self.font_size = (self.font_size * 1.1).min(30.0); + } - if ctx.input(|i| i.key_pressed(egui::Key::F) && i.modifiers.ctrl) { - self.search_menu.visible = !self.search_menu.visible; - self.search_menu.initialized = !self.search_menu.visible; - } + if ctx.input(|i| i.zoom_delta() < 1.0) { + self.font_size = (self.font_size / 1.1).max(10.0); + } - if ctx.input(|i| i.viewport().close_requested()) { - let mut unsaved_tabs: Vec = vec![]; - for (index, tab) in self.tabs.iter().enumerate() { - if !tab.saved { - unsaved_tabs.push(index); - } - } - if !unsaved_tabs.is_empty() { - let mut unsaved_tabs_names: String = "".to_string(); - for index in unsaved_tabs.iter() { - unsaved_tabs_names.push_str(&self.tabs[*index].get_name()); - } - egui::Context::send_viewport_cmd(ctx, egui::ViewportCommand::CancelClose); - self.exit_confirm.prompt = format!( - "You have some unsaved changes :\n{}\nDo you still want to exit ?", - unsaved_tabs_names - ); - self.exit_confirm.ask(); - } - } + if ctx.input(|i| i.key_pressed(egui::Key::F) && i.modifiers.ctrl) { + self.search_menu.visible = !self.search_menu.visible; + self.search_menu.initialized = !self.search_menu.visible; + } - self.time_watch[0] = watch.elapsed().as_micros() as f32 / 1000.0; - watch = time::Instant::now(); + if ctx.input(|i| i.viewport().close_requested()) { + let mut unsaved_tabs: Vec = vec![]; + for (index, tab) in self.tabs.iter().enumerate() { + if !tab.saved { + unsaved_tabs.push(index); + } + } + if !unsaved_tabs.is_empty() { + let mut unsaved_tabs_names: String = "".to_string(); + for index in unsaved_tabs.iter() { + unsaved_tabs_names.push_str(&self.tabs[*index].get_name()); + } + egui::Context::send_viewport_cmd(ctx, egui::ViewportCommand::CancelClose); + self.exit_confirm.prompt = format!( + "You have some unsaved changes :\n{}\nDo you still want to exit ?", + unsaved_tabs_names + ); + self.exit_confirm.ask(); + } + } - self.draw_settings(ctx); + self.time_watch[0] = watch.elapsed().as_micros() as f32 / 1000.0; + watch = time::Instant::now(); - self.time_watch[1] = watch.elapsed().as_micros() as f32 / 1000.0; - watch = time::Instant::now(); + self.draw_settings(ctx); - self.draw_tree_panel(ctx); + self.time_watch[1] = watch.elapsed().as_micros() as f32 / 1000.0; + watch = time::Instant::now(); - self.time_watch[2] = watch.elapsed().as_micros() as f32 / 1000.0; - watch = time::Instant::now(); + self.draw_tree_panel(ctx); - self.draw_bottom_tray(ctx); - self.draw_terminal_panel(ctx); + self.time_watch[2] = watch.elapsed().as_micros() as f32 / 1000.0; + watch = time::Instant::now(); - self.time_watch[3] = watch.elapsed().as_micros() as f32 / 1000.0; - watch = time::Instant::now(); + self.draw_bottom_tray(ctx); + self.draw_terminal_panel(ctx); - self.draw_tab_panel(ctx); + self.time_watch[3] = watch.elapsed().as_micros() as f32 / 1000.0; + watch = time::Instant::now(); - self.time_watch[4] = watch.elapsed().as_micros() as f32 / 1000.0; - watch = time::Instant::now(); + self.draw_tab_panel(ctx); - self.draw_content_panel(ctx); + self.time_watch[4] = watch.elapsed().as_micros() as f32 / 1000.0; + watch = time::Instant::now(); - self.time_watch[5] = watch.elapsed().as_micros() as f32 / 1000.0; - watch = time::Instant::now(); + self.draw_content_panel(ctx); - self.draw_windows(ctx); + self.time_watch[5] = watch.elapsed().as_micros() as f32 / 1000.0; + watch = time::Instant::now(); - self.time_watch[6] = watch.elapsed().as_micros() as f32 / 1000.0; - } + self.draw_windows(ctx); - fn on_exit(&mut self, _gl: std::option::Option<&eframe::glow::Context>) { - self.save_state(); - } + self.time_watch[6] = watch.elapsed().as_micros() as f32 / 1000.0; + } + + fn on_exit(&mut self, _gl: std::option::Option<&eframe::glow::Context>) { + self.save_state(); + } } fn save_path() -> PathBuf { - if TITLE.is_empty() { - get_my_home() - .unwrap() - .unwrap() - .as_path() - .join(".calcifer") - .join("save.json") - .to_path_buf() - } else { - get_my_home() - .unwrap() - .unwrap() - .as_path() - .join(".calcifer") - .join("debug") - .join("save.json") - .to_path_buf() - } + if TITLE.is_empty() { + get_my_home() + .unwrap() + .unwrap() + .as_path() + .join(".calcifer") + .join("save.json") + .to_path_buf() + } else { + get_my_home() + .unwrap() + .unwrap() + .as_path() + .join(".calcifer") + .join("debug") + .join("save.json") + .to_path_buf() + } } diff --git a/src/panels/project_mode.rs b/src/panels/project_mode.rs index 209507e..ac6d1e7 100644 --- a/src/panels/project_mode.rs +++ b/src/panels/project_mode.rs @@ -1,131 +1,223 @@ use eframe::egui; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::{ + cmp::min, + sync::atomic::{AtomicUsize, Ordering}, +}; -use crate::MAX_PROJECT_COLUMNS; use crate::core::hex_str_to_color; use crate::editor::ColorTheme; +use crate::sub_windows; +use crate::MAX_PROJECT_COLUMNS; - -#[derive(Clone)] pub struct Project { - categories: Vec, - selected_item: Option<[usize; 2]>, + pub categories: Vec, + pub selected_item: Location, + pub item_window: sub_windows::ProjectItemWindow, + was_moving: bool, } impl Project { - pub fn new() -> Self { - Self { - categories: vec![Category::create()], - selected_item: None, - } - } - - fn add_category(&mut self) { - let last = self.categories.len() - 1; - self.categories[last].initialize(); - if self.categories.len() < MAX_PROJECT_COLUMNS { - self.categories.push(Category::create()); - } - } - - fn delete_category(&mut self, index: usize) { - self.categories.remove(index); - let last = self.categories.len() - 1; - if self.categories[last].name != "+" { - self.categories.push(Category::create()); - } - } + pub fn new() -> Self { + Self { + categories: vec![Category::create()], + selected_item: Location::zero(), + was_moving: false, + item_window: sub_windows::ProjectItemWindow::new(), + } + } + + fn add_category(&mut self) { + let last = self.categories.len() - 1; + self.categories[last].initialize(); + if self.categories.len() < MAX_PROJECT_COLUMNS { + self.categories.push(Category::create()); + } + } + + fn delete_category(&mut self, index: usize) { + self.categories.remove(index); + let last = self.categories.len() - 1; + if self.categories[last].name != "+" { + self.categories.push(Category::create()); + } + } } #[derive(Clone)] -struct Category { - name: String, - content: Vec, +pub struct Category { + name: String, + pub content: Vec, } impl Category { - fn create() -> Self { - Self { - name: "+".into(), - content: vec![], - } - } - - fn initialize(&mut self) { - self.name = "untitled".into(); - } + fn create() -> Self { + Self { + name: "+".into(), + content: vec![], + } + } + + fn initialize(&mut self) { + self.name = "untitled".into(); + } } - #[derive(Clone, Hash)] -struct Item { - name: String, - description: String, - id: usize, +pub struct Item { + pub name: String, + pub description: String, + id: usize, } impl Item { - fn new(name: &str) -> Self { - Self { - name: name.to_string(), - description: "".to_string(), - id: get_id(), - } - } + fn new(name: &str) -> Self { + Self { + name: name.to_string(), + description: "".to_string(), + id: get_id(), + } + } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Location { - category: usize, - row: usize, + pub category: usize, + pub row: usize, } +impl Location { + fn zero() -> Self { + Self { + category: 0, + row: 0, + } + } +} fn get_id() -> usize { - static COUNTER:AtomicUsize = AtomicUsize::new(1); - COUNTER.fetch_add(1, Ordering::Relaxed) + static COUNTER: AtomicUsize = AtomicUsize::new(1); + COUNTER.fetch_add(1, Ordering::Relaxed) } pub fn draw_project(ui: &mut egui::Ui, theme: ColorTheme, project: &mut Project) { - ui.columns(MAX_PROJECT_COLUMNS, |uis| { - for (category_index, category) in project.categories.clone().into_iter().enumerate() { - let ui = &mut uis[category_index]; + ui.columns(MAX_PROJECT_COLUMNS, |uis| { + for (category_index, category) in project.categories.clone().into_iter().enumerate() { + let ui = &mut uis[category_index]; - if category.name == "+" { - if ui.add(egui::Button::new("+")).clicked() { - project.add_category(); - } - } else { - let response = ui.add(egui::TextEdit::singleline(&mut project.categories[category_index].name).desired_width(f32::INFINITY)); - if response.lost_focus() && project.categories[category_index].name.is_empty() { - project.delete_category(category_index); - } - } - - for (item_index, item) in category.content.iter().enumerate() { - ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| { - ui.style_mut().visuals.override_text_color = Some(hex_str_to_color(theme.literals)); - if ui.add(egui::Button::new("✒")).clicked() { - println!("yes"); - } - - if project.selected_item == Some([category_index, item_index]) { - ui.style_mut().visuals.override_text_color = Some(hex_str_to_color(theme.bg)); - ui.add(egui::Button::new(item.name.clone()).fill(hex_str_to_color(theme.functions))); - } else { - ui.style_mut().visuals.override_text_color = Some(hex_str_to_color(theme.literals)); - if ui.add(egui::Button::new(item.name.clone()).fill(hex_str_to_color(theme.bg))).clicked() { - project.selected_item = Some([category_index, item_index]); - } - } - }); - } - - if category.name != "+" { - if ui.add(egui::Button::new("+")).clicked() { - project.categories[category_index].content.push(Item::new("item")); - } - } - } - }); -} \ No newline at end of file + if category.name == "+" { + if ui.add(egui::Button::new("+")).clicked() { + project.add_category(); + } + } else { + let response = ui.add( + egui::TextEdit::singleline(&mut project.categories[category_index].name) + .desired_width(f32::INFINITY), + ); + if response.lost_focus() && project.categories[category_index].name.is_empty() { + project.delete_category(category_index); + } + } + + for (item_index, item) in category.content.iter().enumerate() { + if project.selected_item + == (Location { + category: category_index, + row: item_index, + }) + { + ui.style_mut().visuals.override_text_color = Some(hex_str_to_color(theme.bg)); + ui.add( + egui::Button::new(item.name.clone()) + .fill(hex_str_to_color(theme.functions)), + ); + } else { + ui.style_mut().visuals.override_text_color = + Some(hex_str_to_color(theme.literals)); + if ui + .add(egui::Button::new(item.name.clone()).fill(hex_str_to_color(theme.bg))) + .clicked() + { + project.selected_item = Location { + category: category_index, + row: item_index, + }; + } + } + } + + if category.name != "+" { + if ui.add(egui::Button::new("+")).clicked() { + project.categories[category_index] + .content + .push(Item::new("item")); + } + } + } + }); + + let mut moved = false; + let category = project.selected_item.category.clone(); + let row = project.selected_item.row.clone(); + + if ui.input(|i| i.key_pressed(egui::Key::ArrowLeft)) && project.selected_item.category > 0 { + moved = true; + if !project.was_moving { + project.selected_item.category -= 1; + project.selected_item.row = min( + project.categories[category].content.len() - 1, + project.selected_item.row, + ); + } + } else if ui.input(|i| i.key_pressed(egui::Key::ArrowRight)) + && project.selected_item.category < project.categories.len() - 2 + { + moved = true; + if !project.was_moving { + project.selected_item.category += 1; + project.selected_item.row = min( + project.categories[category].content.len() - 1, + project.selected_item.row, + ); + } + } else if ui.input(|i| i.key_pressed(egui::Key::ArrowUp)) && project.selected_item.row > 0 { + moved = true; + if !project.was_moving { + project.selected_item.row -= 1; + } + } else if ui.input(|i| i.key_pressed(egui::Key::ArrowDown)) + && project.selected_item.row < project.categories[category].content.len() - 1 + { + moved = true; + if !project.was_moving { + project.selected_item.row += 1; + } + } else if ui.input(|i| i.key_pressed(egui::Key::ArrowLeft) && i.modifiers.shift) { + moved = true; + if !project.was_moving {} + } else if ui.input(|i| i.key_pressed(egui::Key::ArrowRight) && i.modifiers.shift) { + moved = true; + if !project.was_moving {} + } else if ui.input(|i| i.key_pressed(egui::Key::ArrowUp) && i.modifiers.shift) + && project.selected_item.row > 0 + { + moved = true; + if !project.was_moving { + let temp = project.categories[category].content[row].clone(); + project.categories[category].content[row] = + project.categories[category].content[row - 1].clone(); + project.categories[category].content[row - 1] = temp.clone(); + project.selected_item.row -= 1; + } + } else if ui.input(|i| i.key_pressed(egui::Key::ArrowDown) && i.modifiers.shift) { + moved = true; + if !project.was_moving { + let temp = project.categories[category].content[row].clone(); + project.categories[category].content[row] = + project.categories[category].content[row + 1].clone(); + project.categories[category].content[row + 1] = temp.clone(); + project.selected_item.row += 1; + } + } + + project.was_moving = moved; +} diff --git a/src/panels/terminal/linux_terminal.rs b/src/panels/terminal/linux_terminal.rs index 573d9f7..6f7833d 100644 --- a/src/panels/terminal/linux_terminal.rs +++ b/src/panels/terminal/linux_terminal.rs @@ -3,191 +3,191 @@ use crate::core::format_path; use arboard::Clipboard; use nix::fcntl::{fcntl, FcntlArg, OFlag}; use std::{ - env, - io::{BufRead, BufReader}, - os::fd::AsRawFd, - path::{Path, PathBuf}, - process::{Child, Command, Stdio}, + env, + io::{BufRead, BufReader}, + os::fd::AsRawFd, + path::{Path, PathBuf}, + process::{Child, Command, Stdio}, }; pub struct Buffer { - pub output_buffer: BufReader, - pub error_buffer: BufReader, - pub child: Child, + pub output_buffer: BufReader, + pub error_buffer: BufReader, + pub child: Child, } #[derive(Clone)] pub struct Line { - pub text: String, - pub error: bool, + pub text: String, + pub error: bool, } impl Line { - fn output(text: String) -> Self { - Self { - text: remove_line_break(text), - error: false, - } - } - fn error(text: String) -> Self { - Self { - text: remove_line_break(text), - error: true, - } - } + fn output(text: String) -> Self { + Self { + text: remove_line_break(text), + error: false, + } + } + fn error(text: String) -> Self { + Self { + text: remove_line_break(text), + error: true, + } + } } pub struct CommandEntry { - pub env: String, - pub command: String, - pub result: Vec, - pub buffer: Option, - pub finished: bool, + pub env: String, + pub command: String, + pub result: Vec, + pub buffer: Option, + pub finished: bool, } impl CommandEntry { - pub fn new(env: String, command: String) -> Self { - let (buffer, result) = match execute(command.clone()) { - Ok(command_buffer) => (Some(command_buffer), vec![]), - Err(err) => ( - None, - vec![Line::error(format!("failed to get results: {}", err))], - ), - }; + pub fn new(env: String, command: String) -> Self { + let (buffer, result) = match execute(command.clone()) { + Ok(command_buffer) => (Some(command_buffer), vec![]), + Err(err) => ( + None, + vec![Line::error(format!("failed to get results: {}", err))], + ), + }; - CommandEntry { - env, - command, - result, - buffer, - finished: false, - } - } + CommandEntry { + env, + command, + result, + buffer, + finished: false, + } + } - pub fn update(&mut self) { - if let Some(buffer) = &mut self.buffer { - let mut output = String::new(); - loop { - let _ = buffer.output_buffer.read_line(&mut output); - if !output.to_string().is_empty() { - self.result.push(Line::output(format!("{}\n", output))); - output = "".to_string() - } else { - break; - } - } + pub fn update(&mut self) { + if let Some(buffer) = &mut self.buffer { + let mut output = String::new(); + loop { + let _ = buffer.output_buffer.read_line(&mut output); + if !output.to_string().is_empty() { + self.result.push(Line::output(format!("{}\n", output))); + output = "".to_string() + } else { + break; + } + } - let mut error = String::new(); - loop { - let _ = buffer.error_buffer.read_line(&mut error); - if !error.to_string().is_empty() { - self.result.push(Line::error(format!("{}\n", error))); - error = "".to_string() - } else { - break; - } - } + let mut error = String::new(); + loop { + let _ = buffer.error_buffer.read_line(&mut error); + if !error.to_string().is_empty() { + self.result.push(Line::error(format!("{}\n", error))); + error = "".to_string() + } else { + break; + } + } - if let Ok(Some(_exit_status)) = buffer.child.try_wait() { - //self.result.push(Line::output(format!("Command finished with status: {:?}\n", exit_status))); - self.finished = true; - } - } - } + if let Ok(Some(_exit_status)) = buffer.child.try_wait() { + //self.result.push(Line::output(format!("Command finished with status: {:?}\n", exit_status))); + self.finished = true; + } + } + } - pub fn copy_error_code(&self) { - let mut txt: String = "".to_string(); - for line in self.result.iter() { - if line.error { - txt.push_str(&format!("{}\n", line.text)); - } - } - let mut _clipboard = Clipboard::new().expect("Failed to initialize clipboard"); - _clipboard.set_text(txt).unwrap(); - } + pub fn copy_error_code(&self) { + let mut txt: String = "".to_string(); + for line in self.result.iter() { + if line.error { + txt.push_str(&format!("{}\n", line.text)); + } + } + let mut _clipboard = Clipboard::new().expect("Failed to initialize clipboard"); + _clipboard.set_text(txt).unwrap(); + } } pub fn send_command(command: String) -> CommandEntry { - let env = format_path(&env::current_dir().unwrap_or_else(|_| PathBuf::from("/"))); + let env = format_path(&env::current_dir().unwrap_or_else(|_| PathBuf::from("/"))); - if command.len() < 2 { - return CommandEntry::new(env, command); - } + if command.len() < 2 { + return CommandEntry::new(env, command); + } - if &command[..2] != "cd" { - return CommandEntry::new(env, command); - } + if &command[..2] != "cd" { + return CommandEntry::new(env, command); + } - if command.len() < 4 { - let mut entry = - CommandEntry::new(env, "echo Invalid cd, should provide path >&2".to_string()); - entry.command = command; - return entry; - } + if command.len() < 4 { + let mut entry = + CommandEntry::new(env, "echo Invalid cd, should provide path >&2".to_string()); + entry.command = command; + return entry; + } - let path_append = command[3..].replace('~', "/home/penwing"); - let path = Path::new(&path_append); + let path_append = command[3..].replace('~', "/home/penwing"); + let path = Path::new(&path_append); - if format!("{}", path.display()) == "/" { - let mut entry = CommandEntry::new(env, "echo Root access denied >&2".to_string()); - entry.command = command; - return entry; - } + if format!("{}", path.display()) == "/" { + let mut entry = CommandEntry::new(env, "echo Root access denied >&2".to_string()); + entry.command = command; + return entry; + } - if env::set_current_dir(path).is_ok() { - let mut entry = CommandEntry::new(env, format!("echo Moved to : {}", path.display())); - entry.command = command; - entry - } else { - let mut entry = CommandEntry::new( - env, - format!("echo Could not find path : {} >&2", path.display()), - ); - entry.command = command; - entry - } + if env::set_current_dir(path).is_ok() { + let mut entry = CommandEntry::new(env, format!("echo Moved to : {}", path.display())); + entry.command = command; + entry + } else { + let mut entry = CommandEntry::new( + env, + format!("echo Could not find path : {} >&2", path.display()), + ); + entry.command = command; + entry + } } pub fn execute(command: String) -> Result { - let mut child = Command::new("sh") - .arg("-c") - .arg(command.clone()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn()?; + let mut child = Command::new("sh") + .arg("-c") + .arg(command.clone()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn()?; - let stdout = child - .stdout - .take() - .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "Failed to open stdout"))?; - let stderr = child - .stderr - .take() - .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "Failed to open stderr"))?; + let stdout = child + .stdout + .take() + .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "Failed to open stdout"))?; + let stderr = child + .stderr + .take() + .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "Failed to open stderr"))?; - let stdout_fd = stdout.as_raw_fd(); - let stderr_fd = stderr.as_raw_fd(); + let stdout_fd = stdout.as_raw_fd(); + let stderr_fd = stderr.as_raw_fd(); - fcntl(stdout_fd, FcntlArg::F_SETFL(OFlag::O_NONBLOCK))?; - fcntl(stderr_fd, FcntlArg::F_SETFL(OFlag::O_NONBLOCK))?; + fcntl(stdout_fd, FcntlArg::F_SETFL(OFlag::O_NONBLOCK))?; + fcntl(stderr_fd, FcntlArg::F_SETFL(OFlag::O_NONBLOCK))?; - let output_buffer = BufReader::new(stdout); - let error_buffer = BufReader::new(stderr); + let output_buffer = BufReader::new(stdout); + let error_buffer = BufReader::new(stderr); - Ok(Buffer { - output_buffer, - error_buffer, - child, - }) + Ok(Buffer { + output_buffer, + error_buffer, + child, + }) } fn remove_line_break(input: String) -> String { - let mut text = input.clone(); - while text.ends_with('\n') { - text.pop(); - if text.ends_with('\r') { - text.pop(); - } - } - text + let mut text = input.clone(); + while text.ends_with('\n') { + text.pop(); + if text.ends_with('\r') { + text.pop(); + } + } + text } diff --git a/src/sub_windows/mod.rs b/src/sub_windows/mod.rs index 4cd0309..f083ad4 100644 --- a/src/sub_windows/mod.rs +++ b/src/sub_windows/mod.rs @@ -10,3 +10,6 @@ pub use settings::*; mod shortcuts; pub use shortcuts::*; + +mod project_item; +pub use project_item::*; diff --git a/src/sub_windows/project_item.rs b/src/sub_windows/project_item.rs new file mode 100644 index 0000000..452ce1b --- /dev/null +++ b/src/sub_windows/project_item.rs @@ -0,0 +1,28 @@ +use eframe::egui; + +use crate::panels; + +pub struct ProjectItemWindow { + pub visible: bool, +} + +impl ProjectItemWindow { + pub fn new() -> Self { + Self { visible: false } + } + + pub fn show(&mut self, ctx: &egui::Context, item: &mut panels::Item) { + let mut visible = self.visible; + egui::Window::new("Project Item") + .open(&mut visible) + .vscroll(true) + .hscroll(true) + .show(ctx, |ui| self.ui(ui, item)); + self.visible = self.visible && visible; + } + + fn ui(&mut self, ui: &mut egui::Ui, item: &mut panels::Item) { + ui.set_min_width(250.0); + ui.label(item.name.clone()); + } +} diff --git a/src/sub_windows/search.rs b/src/sub_windows/search.rs index 8f4034e..7911a3f 100644 --- a/src/sub_windows/search.rs +++ b/src/sub_windows/search.rs @@ -235,9 +235,7 @@ impl SearchWindow { } fn replace(&mut self, tabs: &mut Vec, selected_tab: &mut TabNumber) { - if self.searched_text != self.search_text { - self.search(tabs, &mut *selected_tab); - } + self.search(tabs, &mut *selected_tab); let mut done: Vec = vec![]; for element in &self.results {