Changed to use show_viewport

This commit is contained in:
2026-01-12 00:45:41 -06:00
parent de7c5bdcc4
commit 10502834f3
4 changed files with 60 additions and 156 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
/target /target
file.txt file.txt
file*.txt

View File

@@ -1,7 +1,6 @@
use eframe::egui; use eframe::egui::{self, ScrollArea, TextStyle, Vec2};
use rfd::FileDialog; use rfd::FileDialog;
mod ropeintegration;
mod rope_editor; mod rope_editor;
fn main() { fn main() {
@@ -11,7 +10,7 @@ fn main() {
#[derive(Default)] #[derive(Default)]
struct GCodium { struct GCodium {
text_buffer: ropeintegration::ERopey, text_buffer: rope_editor::RopeEdit,
} }
impl GCodium { impl GCodium {
@@ -27,9 +26,18 @@ impl eframe::App for GCodium {
if ui.button("Open File").clicked() { if ui.button("Open File").clicked() {
let filepath = FileDialog::new().add_filter("text", &["txt"]).set_directory("/").pick_file().expect("File not Selected"); 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"); 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);
}
)
}); });
} }
} }

View File

@@ -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<Galley>; #[derive(Default)]
pub struct RopeEdit {
pub struct RopeEdit<'t> { pub text: Rope,
text: &'t mut dyn TextBuffer, position: usize,
//hint_text: String,
//hint_text_font: Option<FontSelection>,
id: Option<Id>,
id_salt: Option<Id>,
font_selection: FontSelection,
text_color: Option<Color32>,
layouter: Option<LayouterFn<'t>>,
frame: bool,
margin: Margin,
desired_width: Option<f32>,
desired_height_rows: usize,
event_filter: EventFilter,
cursor_at_end: bool,
min_size: Vec2,
align: Align2,
char_limit: usize,
return_key: Option<KeyboardShortcut>,
background_color: Option<Color32>,
} }
impl WidgetWithState for RopeEdit<'_> { impl RopeEdit {
type State = TextEditState; pub fn new(textbuffer: Rope) -> Self {
} RopeEdit {
text: textbuffer,
impl RopeEdit<'_> { position: 0,
pub fn load_state(ctx: &Context, id: Id) -> Option<TextEditState> {
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
} }
} }
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 = ()
}
} }

View File

@@ -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<usize>) {
self.rope.remove(char_range);
}
fn type_id(&self) -> std::any::TypeId {
std::any::TypeId::of::<Self>()
}
}