diff --git a/.gitignore b/.gitignore index 13b97bd..3d5399f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target -file.txt \ No newline at end of file +file.txt +file*.txt \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 4f46533..39ef6dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ -use eframe::egui; +use eframe::egui::{self, ScrollArea, TextStyle, Vec2}; use rfd::FileDialog; -mod ropeintegration; mod rope_editor; fn main() { @@ -11,7 +10,7 @@ fn main() { #[derive(Default)] struct GCodium { - text_buffer: ropeintegration::ERopey, + text_buffer: rope_editor::RopeEdit, } impl GCodium { @@ -27,9 +26,18 @@ impl eframe::App for GCodium { if ui.button("Open File").clicked() { let filepath = FileDialog::new().add_filter("text", &["txt"]).set_directory("/").pick_file().expect("File not Selected"); let file = std::fs::File::open(filepath).expect("unable to open file"); - self.text_buffer.rope = ropey::Rope::from_reader(file).expect("unable to read file to rope"); + self.text_buffer.text = ropey::Rope::from_reader(file).expect("unable to read file to rope"); } - ui.text_edit_multiline(&mut self.text_buffer); + + let text_style = TextStyle::Monospace; + let height = ui.text_style_height(&text_style).to_string(); + ui.label(height); + ScrollArea::both().auto_shrink(false).show_viewport( + ui, + |ui, viewport| { + self.text_buffer.show(ui, viewport); + } + ) }); } } diff --git a/src/rope_editor.rs b/src/rope_editor.rs index 122649e..bdc3067 100644 --- a/src/rope_editor.rs +++ b/src/rope_editor.rs @@ -1,126 +1,54 @@ -use std::{sync::Arc, usize}; +use std::borrow::Cow; -use eframe::egui::{Align2, Color32, Context, EventFilter, FontSelection, Galley, Id, Key, KeyboardShortcut, Margin, Modifiers, NumExt, Shape, TextBuffer, Ui, Vec2, WidgetWithState, text::LayoutJob, text_edit::{TextEditOutput, TextEditState}}; +use eframe::egui::{self, Align2, NumExt, Rect, Sense, TextStyle, Ui, Vec2, pos2, text_edit::TextCursorState}; +use ropey::Rope; -type LayouterFn<'t> = &'t mut dyn FnMut(&Ui, &dyn TextBuffer, f32) -> Arc; - -pub struct RopeEdit<'t> { - text: &'t mut dyn TextBuffer, - //hint_text: String, - //hint_text_font: Option, - id: Option, - id_salt: Option, - font_selection: FontSelection, - text_color: Option, - layouter: Option>, - frame: bool, - margin: Margin, - desired_width: Option, - desired_height_rows: usize, - event_filter: EventFilter, - cursor_at_end: bool, - min_size: Vec2, - align: Align2, - char_limit: usize, - return_key: Option, - background_color: Option, +#[derive(Default)] +pub struct RopeEdit { + pub text: Rope, + position: usize, } -impl WidgetWithState for RopeEdit<'_> { - type State = TextEditState; -} - -impl RopeEdit<'_> { - pub fn load_state(ctx: &Context, id: Id) -> Option { - TextEditState::load(ctx, id) - } - - pub fn store_state(ctx: &Context, id: Id, state: TextEditState) { - state.store(ctx, id); - } - - pub fn show(self, ui: &mut Ui) -> TextEditOutput { - let frame = self.frame; - let where_to_put_background = ui.painter().add(Shape::Noop); - let background_color = ui.visuals().text_edit_bg_color(); - let output = self.show_content(ui); - } - - pub fn show_content(self, ui: &mut Ui) -> TextEditOutput { - let RopeEdit { - text, - //hint_text, - //hint_text_font, - id, - id_salt, - font_selection, - text_color, - layouter, - frame, - margin, - desired_width, - desired_height_rows, - event_filter, - cursor_at_end, - min_size, - align, - char_limit, - return_key, - background_color - } = self; - - let text_color = text_color - .or(ui.visuals().override_text_color) - // .unwrap_or_else(|| ui.style().interact(&response).text_color()); // too bright - .unwrap_or_else(|| ui.visuals().widgets.inactive.text_color()); - - let font_id = font_selection.resolve(ui.style()); - let row_height = ui.fonts_mut(|f| f.row_height(&font_id)); - const MIN_WIDTH: f32 = 24.0; - let available_width = (ui.available_width() - margin.sum().x).at_least(MIN_WIDTH); - let desired_width = desired_width.unwrap_or_else(|| ui.spacing().text_edit_width); - let wrap_width = if ui.layout().horizontal_justify() { - available_width - } else { - desired_width.min(available_width) - }; - - let font_id_clone = font_id.clone(); - let mut default_layouter = move |ui: &Ui, text: &dyn TextBuffer, wrap_width: f32,| { - let layout_job = LayoutJob::simple(text, font_id_clone.clone(), text_color, wrap_width) - } - } -} - -impl<'t> RopeEdit<'t> { - pub fn new(text: &'t mut dyn TextBuffer) -> Self { - Self { - text, - //hint_text: Default::default(), - //hint_text_font: None, - id: None, - id_salt: None, - font_selection: Default::default(), - text_color: None, - layouter: None, - frame: false, - margin: Margin::symmetric(4, 2), - desired_width: None, - desired_height_rows: 4, - event_filter: EventFilter { - tab: false, - horizontal_arrows: true, - vertical_arrows: true, - ..Default::default() - }, - cursor_at_end: true, - min_size: Vec2::ZERO, - align: Align2::LEFT_TOP, - char_limit: usize::MAX, - return_key: Some(KeyboardShortcut::new(Modifiers::NONE, Key::Enter)), - background_color: None +impl RopeEdit { + pub fn new(textbuffer: Rope) -> Self { + RopeEdit { + text: textbuffer, + position: 0, } } + pub fn show(&mut self, ui: &mut Ui, viewport: Rect) -> () { + let font_id = TextStyle::Body.resolve(ui.style()); + let row_height = ui.fonts_mut(|f| f.row_height(&font_id)) + ui.spacing().item_spacing.y; + let num_rows = self.text.len_lines(); + ui.set_height(row_height * num_rows as f32); + + let first_item = (viewport.min.y / row_height).floor().at_least(0.0) as usize; + let last_item = (viewport.max.y / row_height).ceil() as usize + 1; + let last_item = last_item.at_most(num_rows); + + let mut used_rect = Rect::NOTHING; + + for i in first_item..last_item { + let x = ui.min_rect().left(); + let y = ui.min_rect().top() + i as f32 * row_height; + let text: Cow<'_, str> = self.text.get_line(i).unwrap().into(); + + let text_rect = ui.painter().text( + pos2(x, y), + Align2::LEFT_TOP, + text, + font_id.clone(), + ui.visuals().text_color(), + ); + used_rect |= text_rect; + } + + ui.allocate_rect(used_rect, Sense::HOVER); + } + + fn show_content() -> () { + //let desired_height = () + } } \ No newline at end of file diff --git a/src/ropeintegration.rs b/src/ropeintegration.rs deleted file mode 100644 index ba6dbda..0000000 --- a/src/ropeintegration.rs +++ /dev/null @@ -1,33 +0,0 @@ -use eframe::egui::{self, scroll_area::State}; -use ropey; - -#[derive(Default)] -pub struct ERopey { - pub rope: ropey::Rope, - viewbuffer: String, -} - -impl egui::widgets::TextBuffer for ERopey { - fn is_mutable(&self) -> bool { - true - } - - fn as_str(&self) -> &str { - self.rope.slice(..).as_str().unwrap() - } - - fn insert_text(&mut self, text: &str, char_index: usize) -> usize { - let first = self.rope.len_chars(); - self.rope.insert(char_index, text); - let second = self.rope.len_chars(); - second-first - } - - fn delete_char_range(&mut self, char_range: std::ops::Range) { - self.rope.remove(char_range); - } - - fn type_id(&self) -> std::any::TypeId { - std::any::TypeId::of::() - } -} \ No newline at end of file