added themes

This commit is contained in:
Penwing 2024-01-20 15:23:57 +01:00
parent ea2c422888
commit 47e58b3e1e
5 changed files with 150 additions and 61 deletions

10
Cargo.lock generated
View file

@ -567,6 +567,7 @@ name = "calcifer"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"eframe", "eframe",
"egui_code_editor",
"egui_extras", "egui_extras",
"env_logger", "env_logger",
"rfd", "rfd",
@ -904,6 +905,15 @@ dependencies = [
"winit", "winit",
] ]
[[package]]
name = "egui_code_editor"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd3d41044cbf017fde94efde48b19637f63d94fa46dd6e41913cfeed74f023bc"
dependencies = [
"egui",
]
[[package]] [[package]]
name = "egui_extras" name = "egui_extras"
version = "0.25.0" version = "0.25.0"

View file

@ -13,4 +13,5 @@ env_logger = { version = "0.10.1", default-features = false, features = [
] } ] }
rfd = "0.12.1" rfd = "0.12.1"
egui_extras = { version = "0.25.0" } egui_extras = { version = "0.25.0" }
egui_code_editor = "0.2.3"
#syntect = "4.6" #syntect = "4.6"

View file

@ -2,7 +2,8 @@
mod tools; mod tools;
use eframe::egui; use eframe::egui;
use std::{path::Path, fs, io, env}; use egui_code_editor::{CodeEditor, ColorTheme};
use std::{path::Path, fs, io, env, cmp::max};
const TERMINAL_HEIGHT : f32 = 200.0; const TERMINAL_HEIGHT : f32 = 200.0;
const RED : egui::Color32 = egui::Color32::from_rgb(235, 108, 99); const RED : egui::Color32 = egui::Color32::from_rgb(235, 108, 99);
@ -20,54 +21,81 @@ fn main() -> Result<(), eframe::Error> {
eframe::run_native( eframe::run_native(
"Calcifer", "Calcifer",
options, options,
Box::new(|_cc| Box::<MyApp>::default()), Box::new(|_cc| Box::<Calcifer>::default()),
) )
} }
struct MyApp { struct Calcifer {
picked_path: Option<String>,
language: String,
code: String,
selected_tab : tools::TabNumber, selected_tab : tools::TabNumber,
tabs: Vec<tools::Tab>, tabs: Vec<tools::Tab>,
command: String, command: String,
command_history: Vec<tools::CommandEntry>, command_history: Vec<tools::CommandEntry>,
theme: ColorTheme,
} }
impl Default for MyApp { impl Default for Calcifer {
fn default() -> Self { fn default() -> Self {
Self { Self {
picked_path: None, selected_tab : tools::TabNumber::Zero,
tabs: vec![ tools::Tab {
path: "untitled".into(),
code: "// Hello there, Master".into(),
language: "rs".into(), language: "rs".into(),
code: "// write here".into(), }],
selected_tab : tools::TabNumber::None,
tabs: Vec::new(),
command: "".into(), command: "".into(),
command_history: Vec::new(), command_history: Vec::new(),
theme: tools::themes::CustomColorTheme::fire()
} }
} }
} }
impl eframe::App for MyApp { impl eframe::App for Calcifer {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
self.draw_settings(ctx);
self.draw_tree_panel(ctx); self.draw_tree_panel(ctx);
self.draw_terminal_panel(ctx); self.draw_terminal_panel(ctx);
self.draw_tab_panel(ctx); self.draw_tab_panel(ctx);
self.draw_code_panel(ctx); self.draw_content_panel(ctx);
} }
} }
impl MyApp { impl Calcifer {
fn draw_settings(&mut self, ctx: &egui::Context) {
egui::TopBottomPanel::top("settings")
.resizable(false)
.show(ctx, |ui| {
ui.horizontal(|ui| {
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);
ui.selectable_value(&mut self.theme, ColorTheme::SONOKAI, "Sonokai");
ui.selectable_value(&mut self.theme, ColorTheme::AYU_DARK, "Ayu Dark");
ui.selectable_value(&mut self.theme, ColorTheme::AYU_MIRAGE, "Ayu Mirage");
ui.selectable_value(&mut self.theme, ColorTheme::GITHUB_DARK, "Github Dark");
ui.selectable_value(&mut self.theme, ColorTheme::GRUVBOX, "Gruvbox");
ui.selectable_value(&mut self.theme, tools::themes::CustomColorTheme::fire(), "Fire");
});
});
});
}
fn draw_tree_panel(&mut self, ctx: &egui::Context) { fn draw_tree_panel(&mut self, ctx: &egui::Context) {
egui::SidePanel::left("file_tree_panel").show(ctx, |ui| { egui::SidePanel::left("file_tree_panel").show(ctx, |ui| {
ui.heading("Bookshelf"); ui.heading("Bookshelf");
if ui.add(egui::Button::new("open file")).clicked() {
if let Some(path) = rfd::FileDialog::new().pick_file() {
self.selected_tab = self.open_file(&path);
}
}
ui.separator(); ui.separator();
let _ = self.list_files(ui, Path::new("/home/penwing/Documents/")); let _ = self.list_files(ui, Path::new("/home/penwing/Documents/"));
ui.separator(); ui.separator();
//~ tools::test(&self);
}); });
} }
@ -79,6 +107,7 @@ impl MyApp {
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| { ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
ui.label(""); ui.label("");
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.style_mut().visuals.extreme_bg_color = egui::Color32::from_hex("#101010").expect("Could not convert color");
let Self { command, .. } = self; let Self { command, .. } = self;
ui.label(format!("{}>", env::current_dir().expect("Could not find Shell Environnment").file_name().expect("Could not get Shell Environnment Name").to_string_lossy().to_string())); ui.label(format!("{}>", env::current_dir().expect("Could not find Shell Environnment").file_name().expect("Could not get Shell Environnment Name").to_string_lossy().to_string()));
let response = ui.add(egui::TextEdit::singleline(command).desired_width(f32::INFINITY).lock_focus(true)); let response = ui.add(egui::TextEdit::singleline(command).desired_width(f32::INFINITY).lock_focus(true));
@ -95,7 +124,6 @@ impl MyApp {
ui.separator(); ui.separator();
ui.horizontal_wrapped(|ui| { ui.horizontal_wrapped(|ui| {
ui.spacing_mut().item_spacing.y = 0.0; ui.spacing_mut().item_spacing.y = 0.0;
//ui.label(self.command_history.clone());
for entry in &self.command_history { for entry in &self.command_history {
ui.label(format!("{}> {}", entry.env, entry.command)); ui.label(format!("{}> {}", entry.env, entry.command));
ui.end_row(); ui.end_row();
@ -121,51 +149,45 @@ impl MyApp {
.show(ctx, |ui| { .show(ctx, |ui| {
ui.horizontal(|ui| { ui.horizontal(|ui| {
for (index, tab) in self.tabs.iter().enumerate() { for (index, tab) in self.tabs.iter().enumerate() {
ui.selectable_value(&mut self.selected_tab, tools::TabNumber::get_from_n(index), tab.get_name()); ui.selectable_value(&mut self.selected_tab, tools::TabNumber::from_n(index), tab.get_name());
} }
if tools::TabNumber::get_from_n(self.tabs.len()) != tools::TabNumber::None { if tools::TabNumber::from_n(self.tabs.len()) != tools::TabNumber::None {
ui.selectable_value(&mut self.selected_tab, tools::TabNumber::Open, "+"); ui.selectable_value(&mut self.selected_tab, tools::TabNumber::Open, "+");
} }
if self.selected_tab == tools::TabNumber::Open { if self.selected_tab == tools::TabNumber::Open {
if let Some(path) = rfd::FileDialog::new().pick_file() { self.selected_tab = self.new_tab();
self.selected_tab = self.open_file(&path);
} else {
self.selected_tab = tools::TabNumber::None;
}
} }
}); });
}); });
} }
fn draw_code_panel(&mut self, ctx: &egui::Context) { fn draw_content_panel(&mut self, ctx: &egui::Context) {
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
if let Some(picked_path) = &self.picked_path {
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Picked file:"); ui.label("Picked file:");
ui.monospace(picked_path); ui.monospace(self.tabs[self.selected_tab.to_n()].path.to_string_lossy().to_string());
});
if self.selected_tab == tools::TabNumber::None {
return
}
self.draw_code_file(ui);
}); });
} }
let Self { language, code, .. } = self; fn draw_code_file(&mut self, ui: &mut egui::Ui) {
let theme = egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx()); let lines = self.tabs[self.selected_tab.to_n()].code.chars().filter(|&c| c == '\n').count() + 1;
let mut layouter = |ui: &egui::Ui, string: &str, wrap_width: f32| {
let mut layout_job = egui_extras::syntax_highlighting::highlight(ui.ctx(), &theme, string, language);
layout_job.wrap.max_width = wrap_width;
ui.fonts(|f| f.layout_job(layout_job))
};
egui::ScrollArea::vertical().show(ui, |ui| { egui::ScrollArea::vertical().show(ui, |ui| {
ui.add( CodeEditor::default()
egui::TextEdit::multiline(code) .id_source("code editor")
.font(egui::FontId::monospace(60.0)) // for cursor height .with_rows(max(80, lines))
.code_editor() .with_fontsize(14.0)
.lock_focus(true) .with_theme(self.theme)
.desired_rows(80) .with_syntax(tools::to_syntax(&self.tabs[self.selected_tab.to_n()].language))
.lock_focus(true) .with_numlines(true)
.desired_width(f32::INFINITY) .show(ui, &mut self.tabs[self.selected_tab.to_n()].code);
.layouter(&mut layouter),
);
});
}); });
} }
@ -195,22 +217,28 @@ impl MyApp {
} }
fn open_file(&mut self, path: &Path) -> tools::TabNumber { fn open_file(&mut self, path: &Path) -> tools::TabNumber {
if tools::TabNumber::get_from_n(self.tabs.len()) == tools::TabNumber::None { if tools::TabNumber::from_n(self.tabs.len()) == tools::TabNumber::None {
return tools::TabNumber::None return tools::TabNumber::None
} }
self.picked_path = Some(path.display().to_string());
let file_path = Path::new(self.picked_path.as_deref().unwrap_or_default());
self.code = fs::read_to_string(file_path).expect("Not able to read the file");
self.language = file_path.to_str().unwrap().split('.').last().unwrap().into();
let new_tab = tools::Tab { let new_tab = tools::Tab {
path: path.into(), path: path.into(),
code: fs::read_to_string(file_path).expect("Not able to read the file"), code: fs::read_to_string(path).expect("Not able to read the file"),
language: file_path.to_str().unwrap().split('.').last().unwrap().into(), language: path.to_str().unwrap().split('.').last().unwrap().into(),
}; };
self.tabs.push(new_tab); self.tabs.push(new_tab);
return tools::TabNumber::get_from_n(self.tabs.len() - 1) return tools::TabNumber::from_n(self.tabs.len() - 1)
}
fn new_tab(&mut self) -> tools::TabNumber {
let new_tab = tools::Tab {
path: "untitled".into(),
code: "// Hello there, Master".into(),
language: "rs".into(),
};
self.tabs.push(new_tab);
return tools::TabNumber::from_n(self.tabs.len() - 1)
} }
} }

View file

@ -1,8 +1,10 @@
//use eframe::egui; //use eframe::egui;
//use std::io; //use std::io;
use std::{process::Command, cmp::Ordering, env, path::PathBuf}; use std::{process::Command, cmp::Ordering, env, path::PathBuf};
use egui_code_editor::Syntax;
//use std::fs; //use std::fs;
pub mod themes;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum TabNumber { pub enum TabNumber {
@ -20,7 +22,7 @@ pub enum TabNumber {
impl TabNumber { impl TabNumber {
pub fn get_from_n( n: usize) -> TabNumber { pub fn from_n(n : usize) -> TabNumber {
match n { match n {
0 => TabNumber::Zero, 0 => TabNumber::Zero,
1 => TabNumber::One, 1 => TabNumber::One,
@ -33,6 +35,19 @@ impl TabNumber {
_ => TabNumber::None, _ => TabNumber::None,
} }
} }
pub fn to_n(&self) -> usize {
match self {
TabNumber::Zero => 0,
TabNumber::One => 1,
TabNumber::Two => 2,
TabNumber::Three => 3,
TabNumber::Four => 4,
TabNumber::Five => 5,
TabNumber::Six => 6,
TabNumber::Seven => 7,
_ => 0,
}
}
} }
@ -75,6 +90,15 @@ pub fn loaded() {
} }
pub fn to_syntax(language : &str) -> Syntax {
match language {
"py" => Syntax::python(),
"rs" => Syntax::rust(),
_ => Syntax::shell(),
}
}
pub fn run_command(cmd : String) -> CommandEntry { pub fn run_command(cmd : String) -> CommandEntry {
let mut entry = CommandEntry::default(); let mut entry = CommandEntry::default();
let output = Command::new("sh") let output = Command::new("sh")

26
src/tools/themes.rs Normal file
View file

@ -0,0 +1,26 @@
use egui_code_editor::ColorTheme;
pub struct CustomColorTheme;
impl CustomColorTheme {
pub fn fire() -> ColorTheme {
let mut theme = ColorTheme::GRUVBOX; // Or any other theme you want to modify
theme.name = "Fire";
theme.dark = true;
theme.bg = "#101010";
theme.cursor = "#fafafa"; // foreground
theme.selection = "#fa8d3e"; // orange
theme.comments = "#828c9a"; // gray
theme.functions = "#ffaa33"; // yellow
theme.keywords = "#fa8d3e"; // orange
theme.literals = "#5c6166"; // foreground
theme.numerics = "#aa1010"; // magenta
theme.punctuation = "#fafafa"; // foreground
theme.strs = "#fa8d3e"; // green
theme.types = "#fa8d3e"; // blue
theme.special = "#f07171"; // red
theme
}
}