better ui organisation
This commit is contained in:
parent
d53edc92e9
commit
fcb1b7abba
|
@ -4,55 +4,34 @@ use std::{env, path::Path, cmp::max};
|
|||
|
||||
use crate::tools;
|
||||
use crate::Calcifer;
|
||||
use crate::TIME_LABELS;
|
||||
use crate::PATH_ROOT;
|
||||
use crate::MAX_TABS;
|
||||
|
||||
pub mod code_editor;
|
||||
use code_editor::CodeEditor;
|
||||
use code_editor::themes::DEFAULT_THEMES;
|
||||
|
||||
mod app_base;
|
||||
|
||||
|
||||
impl Calcifer {
|
||||
pub fn draw_settings(&mut self, ctx: &egui::Context) {
|
||||
egui::TopBottomPanel::top("settings")
|
||||
egui::SidePanel::left("settings")
|
||||
.resizable(false)
|
||||
.exact_width(self.font_size * 1.8)
|
||||
.show(ctx, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.add(egui::Button::new("open file")).clicked() {
|
||||
ui.vertical(|ui| {
|
||||
if ui.add(egui::Button::new("📁")).clicked() {
|
||||
if let Some(path) = rfd::FileDialog::new().set_directory(Path::new(&PATH_ROOT)).pick_file() {
|
||||
self.open_file(Some(&path));
|
||||
}
|
||||
}
|
||||
ui.separator();
|
||||
|
||||
ui.label("Theme ");
|
||||
egui::ComboBox::from_label("")
|
||||
.selected_text(format!("{}", self.theme.name))
|
||||
.show_ui(ui, |ui| {
|
||||
ui.style_mut().wrap = Some(false);
|
||||
ui.set_min_width(60.0);
|
||||
for theme in DEFAULT_THEMES {
|
||||
ui.selectable_value(&mut self.theme, theme, theme.name);
|
||||
}
|
||||
});
|
||||
|
||||
self.tree_display = self.toggle(ui, self.tree_display, "🗐");
|
||||
ui.separator();
|
||||
self.tree_display = self.toggle(ui, self.tree_display, "Tree");
|
||||
self.settings_menu.visible = self.toggle(ui, self.settings_menu.visible, "⚙");
|
||||
ui.separator();
|
||||
self.debug_display = self.toggle(ui, self.debug_display, "Debug");
|
||||
self.profiler_menu.visible = self.toggle(ui, self.profiler_menu.visible, "🗠");
|
||||
ui.separator();
|
||||
|
||||
if self.debug_display {
|
||||
let combined_string: Vec<String> = TIME_LABELS.into_iter().zip(self.time_watch.clone().into_iter())
|
||||
.map(|(s, v)| format!("{} : {:.1} ms", s, v)).collect();
|
||||
|
||||
let mut result = combined_string.join(" ; ");
|
||||
result.push_str(&format!(" total : {:.1}", self.time_watch.clone().iter().sum::<f32>()));
|
||||
ui.label(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -202,4 +181,27 @@ impl Calcifer {
|
|||
.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);
|
||||
}
|
||||
|
||||
pub fn draw_windows(&mut self, ctx: &egui::Context) {
|
||||
if self.search.visible {
|
||||
self.search.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.profiler_menu.visible {
|
||||
self.profiler_menu.show(ctx, self.time_watch.clone());
|
||||
}
|
||||
if self.settings_menu.visible {
|
||||
self.settings_menu.show(ctx);
|
||||
}
|
||||
if self.settings_menu.updated {
|
||||
self.theme = self.settings_menu.theme.clone();
|
||||
}
|
||||
|
||||
self.handle_confirm();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::{path::PathBuf, fs, path::Path, cmp::min, io};
|
||||
use eframe::egui;
|
||||
use egui::Color32;
|
||||
|
||||
use crate::Calcifer;
|
||||
use crate::tools;
|
||||
|
@ -62,6 +63,7 @@ impl Calcifer {
|
|||
let mut new = Self {
|
||||
theme: DEFAULT_THEMES[min(app_state.theme, DEFAULT_THEMES.len() - 1)],
|
||||
tabs: Vec::new(),
|
||||
settings_menu: tools::settings::SettingsWindow::new(DEFAULT_THEMES[app_state.theme]),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -150,13 +152,13 @@ impl Calcifer {
|
|||
|
||||
|
||||
pub fn toggle(&self, ui: &mut egui::Ui, display : bool, title : &str) -> bool {
|
||||
let text = if display.clone() {
|
||||
format!("hide {}", title)
|
||||
let color = if display.clone() {
|
||||
Color32::from_hex(self.theme.functions).expect("Could not convert color to hex (functions)")
|
||||
} else {
|
||||
format!("show {}", title)
|
||||
Color32::from_hex(self.theme.bg).expect("Could not convert color to hex (bg)")
|
||||
};
|
||||
|
||||
if ui.add(egui::Button::new(text)).clicked() {
|
||||
if ui.add(egui::Button::new(title).fill(color)).clicked() {
|
||||
return !display
|
||||
}
|
||||
return display
|
||||
|
|
66
src/main.rs
66
src/main.rs
|
@ -4,6 +4,9 @@ mod calcifer;
|
|||
use eframe::egui;
|
||||
use calcifer::code_editor::ColorTheme;
|
||||
use std::{path::Path, sync::Arc, time, thread};
|
||||
use egui::FontFamily::Proportional;
|
||||
use egui::FontId;
|
||||
use egui::TextStyle::{Small, Button, Body, Heading, Monospace};
|
||||
|
||||
use calcifer::code_editor::themes::DEFAULT_THEMES;
|
||||
|
||||
|
@ -24,7 +27,7 @@ use build::TITLE;
|
|||
|
||||
const TERMINAL_HEIGHT : f32 = 200.0;
|
||||
const RED : egui::Color32 = egui::Color32::from_rgb(235, 108, 99);
|
||||
const TIME_LABELS : [&str; 5] = ["settings", "tree", "terminal", "tabs", "content"];
|
||||
const TIME_LABELS : [&str; 7] = ["input", "settings", "tree", "terminal", "tabs", "content", "windows"];
|
||||
const MAX_FPS : f32 = 30.0;
|
||||
const PATH_ROOT : &str = "/home/penwing/Documents/";
|
||||
const DISPLAY_PATH_DEPTH : usize = 3;
|
||||
|
@ -68,18 +71,19 @@ struct Calcifer {
|
|||
|
||||
theme: ColorTheme,
|
||||
font_size: f32,
|
||||
|
||||
search: tools::search::SearchWindow,
|
||||
|
||||
debug_display: bool,
|
||||
time_watch: Vec<f32>,
|
||||
next_frame: time::Instant,
|
||||
|
||||
tree_display: bool,
|
||||
|
||||
close_tab_confirm: tools::confirm::ConfirmWindow,
|
||||
tab_to_close: usize,
|
||||
refresh_confirm: tools::confirm::ConfirmWindow,
|
||||
|
||||
search: tools::search::SearchWindow,
|
||||
settings_menu: tools::settings::SettingsWindow,
|
||||
profiler_menu: tools::profiler::ProfilerWindow,
|
||||
|
||||
time_watch: Vec<f32>,
|
||||
next_frame: time::Instant,
|
||||
}
|
||||
|
||||
|
||||
|
@ -94,18 +98,19 @@ impl Default for Calcifer {
|
|||
|
||||
theme: DEFAULT_THEMES[0],
|
||||
font_size: 14.0,
|
||||
|
||||
search: tools::search::SearchWindow::default(),
|
||||
|
||||
debug_display: false,
|
||||
time_watch: vec![0.0; TIME_LABELS.len()],
|
||||
next_frame: time::Instant::now(),
|
||||
|
||||
tree_display: false,
|
||||
|
||||
close_tab_confirm: tools::confirm::ConfirmWindow::new("You have some unsaved changes, Do you still want to close this document ?", "Confirm Close"),
|
||||
tab_to_close: 0,
|
||||
refresh_confirm: tools::confirm::ConfirmWindow::new("You have some unsaved changes, Do you still want to refresh this document ?", "Confirm Refresh"),
|
||||
|
||||
search: tools::search::SearchWindow::default(),
|
||||
settings_menu: tools::settings::SettingsWindow::new(DEFAULT_THEMES[0]),
|
||||
profiler_menu: tools::profiler::ProfilerWindow::new(),
|
||||
|
||||
time_watch: vec![0.0; TIME_LABELS.len()],
|
||||
next_frame: time::Instant::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,6 +123,17 @@ impl eframe::App for Calcifer {
|
|||
|
||||
let mut watch = time::Instant::now();
|
||||
|
||||
let mut style = (*ctx.style()).clone();
|
||||
style.text_styles = [
|
||||
(Heading, FontId::new(self.font_size * 1.6, Proportional)),
|
||||
(Body, FontId::new(self.font_size, Proportional)),
|
||||
(Monospace, FontId::new(self.font_size, Proportional)),
|
||||
(Button, FontId::new(self.font_size, Proportional)),
|
||||
(Small, FontId::new(self.font_size, Proportional)),
|
||||
]
|
||||
.into();
|
||||
ctx.set_style(style);
|
||||
|
||||
if ctx.input( |i| i.key_pressed(egui::Key::T) && i.modifiers.ctrl) && !self.refresh_confirm.visible {
|
||||
if self.tabs[self.selected_tab.to_index()].saved {
|
||||
self.tabs[self.selected_tab.to_index()].refresh();
|
||||
|
@ -155,35 +171,37 @@ impl eframe::App for Calcifer {
|
|||
self.search.initialized = !self.search.visible.clone();
|
||||
}
|
||||
|
||||
self.draw_settings(ctx);
|
||||
|
||||
self.time_watch[0] = watch.elapsed().as_micros() as f32 / 1000.0;
|
||||
watch = time::Instant::now();
|
||||
|
||||
self.draw_tree_panel(ctx);
|
||||
self.draw_settings(ctx);
|
||||
|
||||
self.time_watch[1] = watch.elapsed().as_micros() as f32 / 1000.0;
|
||||
watch = time::Instant::now();
|
||||
|
||||
self.draw_terminal_panel(ctx);
|
||||
self.draw_tree_panel(ctx);
|
||||
|
||||
self.time_watch[2] = watch.elapsed().as_micros() as f32 / 1000.0;
|
||||
watch = time::Instant::now();
|
||||
|
||||
self.draw_tab_panel(ctx);
|
||||
self.draw_terminal_panel(ctx);
|
||||
|
||||
self.time_watch[3] = watch.elapsed().as_micros() as f32 / 1000.0;
|
||||
watch = time::Instant::now();
|
||||
|
||||
self.draw_content_panel(ctx);
|
||||
self.draw_tab_panel(ctx);
|
||||
|
||||
self.time_watch[4] = watch.elapsed().as_micros() as f32 / 1000.0;
|
||||
|
||||
self.search.show(ctx, &mut self.tabs, &mut self.selected_tab);
|
||||
self.close_tab_confirm.show(ctx, &mut self.tabs, &mut self.selected_tab);
|
||||
self.refresh_confirm.show(ctx, &mut self.tabs, &mut self.selected_tab);
|
||||
watch = time::Instant::now();
|
||||
|
||||
self.handle_confirm();
|
||||
self.draw_content_panel(ctx);
|
||||
|
||||
self.time_watch[5] = watch.elapsed().as_micros() as f32 / 1000.0;
|
||||
watch = time::Instant::now();
|
||||
|
||||
self.draw_windows(ctx);
|
||||
|
||||
self.time_watch[6] = watch.elapsed().as_micros() as f32 / 1000.0;
|
||||
}
|
||||
|
||||
fn on_exit(&mut self, _gl : std::option::Option<&eframe::glow::Context>) {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use eframe::egui;
|
||||
use crate::tools::{Tab, TabNumber};
|
||||
|
||||
|
||||
pub struct ConfirmWindow {
|
||||
|
@ -21,18 +20,18 @@ impl ConfirmWindow {
|
|||
}
|
||||
|
||||
|
||||
pub fn show(&mut self, ctx: &egui::Context, tabs: &mut Vec<Tab>, selected_tab: &mut TabNumber) {
|
||||
pub fn show(&mut self, ctx: &egui::Context) {
|
||||
let mut visible = self.visible.clone();
|
||||
egui::Window::new(self.id.clone())
|
||||
.open(&mut visible) //I want it to be able to change its visibility (if user close manually)
|
||||
.vscroll(true)
|
||||
.hscroll(true)
|
||||
.show(ctx, |ui| self.ui(ui, tabs, selected_tab)); //but I want to edit the rest of the parameters and maybe close automatically
|
||||
.show(ctx, |ui| self.ui(ui)); //but I want to edit the rest of the parameters and maybe close automatically
|
||||
self.visible = self.visible.clone() && visible;
|
||||
}
|
||||
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _tabs: &mut Vec<Tab>, _selected_tab: &mut TabNumber) {
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
ui.set_min_width(250.0);
|
||||
ui.label(self.prompt.clone());
|
||||
ui.vertical_centered(|ui| {
|
||||
|
|
|
@ -8,6 +8,8 @@ use toml::Value;
|
|||
//my tools;
|
||||
pub mod search;
|
||||
pub mod confirm;
|
||||
pub mod settings;
|
||||
pub mod profiler;
|
||||
|
||||
pub mod terminal;
|
||||
pub use terminal::*;
|
||||
|
@ -27,16 +29,16 @@ pub fn save_state(state: &AppState, file_path: &str) -> Result<(), std::io::Erro
|
|||
let serialized_state = serde_json::to_string(state)?;
|
||||
|
||||
if let Some(parent_dir) = Path::new(file_path).parent() {
|
||||
fs::create_dir_all(parent_dir)?;
|
||||
}
|
||||
fs::create_dir_all(parent_dir)?;
|
||||
}
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(file_path)?;
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(file_path)?;
|
||||
|
||||
file.write_all(serialized_state.as_bytes())?;
|
||||
file.write_all(serialized_state.as_bytes())?;
|
||||
|
||||
println!("Saved state at {}", file_path);
|
||||
|
||||
|
@ -110,21 +112,21 @@ pub fn format_path(path: &Path) -> String {
|
|||
}
|
||||
|
||||
pub fn version() -> String {
|
||||
// Read the contents of the Cargo.toml file
|
||||
let toml_content = fs::read_to_string("Cargo.toml").expect("Failed to read Cargo.toml");
|
||||
// Read the contents of the Cargo.toml file
|
||||
let toml_content = fs::read_to_string("Cargo.toml").expect("Failed to read Cargo.toml");
|
||||
|
||||
// Parse the TOML content
|
||||
let toml: Value = toml::from_str(&toml_content).expect("Failed to parse TOML");
|
||||
// Parse the TOML content
|
||||
let toml: Value = toml::from_str(&toml_content).expect("Failed to parse TOML");
|
||||
|
||||
// Extract version information
|
||||
if let Some(package) = toml.get("package") {
|
||||
if let Some(version) = package.get("version") {
|
||||
if let Some(version_string) = version.as_str() {
|
||||
println!("Version: {}", version_string);
|
||||
return version_string.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
// Extract version information
|
||||
if let Some(package) = toml.get("package") {
|
||||
if let Some(version) = package.get("version") {
|
||||
if let Some(version_string) = version.as_str() {
|
||||
println!("Version: {}", version_string);
|
||||
return version_string.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
return "".to_string()
|
||||
}
|
||||
|
||||
|
|
38
src/tools/profiler.rs
Normal file
38
src/tools/profiler.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
use eframe::egui;
|
||||
use crate::TIME_LABELS;
|
||||
|
||||
|
||||
pub struct ProfilerWindow {
|
||||
pub visible: bool,
|
||||
}
|
||||
|
||||
|
||||
impl ProfilerWindow {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
visible: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn show(&mut self, ctx: &egui::Context, time_watch: Vec<f32>) {
|
||||
let mut visible = self.visible.clone();
|
||||
egui::Window::new("Profiler")
|
||||
.open(&mut visible) //I want it to be able to change its visibility (if user close manually)
|
||||
.vscroll(true)
|
||||
.hscroll(true)
|
||||
.show(ctx, |ui| self.ui(ui, time_watch)); //but I want to edit the rest of the parameters and maybe close automatically
|
||||
self.visible = self.visible.clone() && visible;
|
||||
}
|
||||
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui, time_watch: Vec<f32>) {
|
||||
ui.set_min_width(100.0);
|
||||
|
||||
for (index, entry) in TIME_LABELS.iter().enumerate() {
|
||||
ui.label(format!("{} : {:.1} ms", entry, time_watch[index]));
|
||||
}
|
||||
ui.separator();
|
||||
ui.label(&format!("total : {:.1} ms", time_watch.clone().iter().sum::<f32>()));
|
||||
}
|
||||
}
|
54
src/tools/settings.rs
Normal file
54
src/tools/settings.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use eframe::egui;
|
||||
use crate::ColorTheme;
|
||||
use crate::DEFAULT_THEMES;
|
||||
|
||||
|
||||
pub struct SettingsWindow {
|
||||
pub visible: bool,
|
||||
pub updated: bool,
|
||||
pub theme: ColorTheme,
|
||||
}
|
||||
|
||||
|
||||
impl SettingsWindow {
|
||||
pub fn new(theme : ColorTheme) -> Self {
|
||||
Self {
|
||||
visible: false,
|
||||
updated: false,
|
||||
theme,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn show(&mut self, ctx: &egui::Context) {
|
||||
let mut visible = self.visible.clone();
|
||||
egui::Window::new("Settings")
|
||||
.open(&mut visible) //I want it to be able to change its visibility (if user close manually)
|
||||
.vscroll(true)
|
||||
.hscroll(true)
|
||||
.show(ctx, |ui| self.ui(ui)); //but I want to edit the rest of the parameters and maybe close automatically
|
||||
self.visible = self.visible.clone() && visible;
|
||||
}
|
||||
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
ui.set_min_width(250.0);
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Theme ");
|
||||
|
||||
let previous_theme = self.theme.clone();
|
||||
egui::ComboBox::from_label("")
|
||||
.selected_text(format!("{}", self.theme.name))
|
||||
.show_ui(ui, |ui| {
|
||||
ui.style_mut().wrap = Some(false);
|
||||
ui.set_min_width(60.0);
|
||||
for theme in DEFAULT_THEMES {
|
||||
ui.selectable_value(&mut self.theme, theme, theme.name);
|
||||
}
|
||||
});
|
||||
if self.theme != previous_theme {
|
||||
self.updated = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue