Changed to use show_viewport
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
/target
|
/target
|
||||||
file.txt
|
file.txt
|
||||||
|
file*.txt
|
||||||
18
src/main.rs
18
src/main.rs
@@ -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);
|
||||||
|
}
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
pub fn show(&mut self, ui: &mut Ui, viewport: Rect) -> () {
|
||||||
state.store(ctx, id);
|
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();
|
||||||
|
|
||||||
pub fn show(self, ui: &mut Ui) -> TextEditOutput {
|
ui.set_height(row_height * num_rows as f32);
|
||||||
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 first_item = (viewport.min.y / row_height).floor().at_least(0.0) as usize;
|
||||||
let RopeEdit {
|
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,
|
text,
|
||||||
//hint_text,
|
font_id.clone(),
|
||||||
//hint_text_font,
|
ui.visuals().text_color(),
|
||||||
id,
|
);
|
||||||
id_salt,
|
used_rect |= text_rect;
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui.allocate_rect(used_rect, Sense::HOVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_content() -> () {
|
||||||
|
//let desired_height = ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user