Skip to content

Commit

Permalink
Merge the bold_buffer & underline_buffer into a style buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
d0rianb committed Apr 13, 2022
1 parent 4a6eb87 commit ac5af0c
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 43 deletions.
4 changes: 2 additions & 2 deletions resources/prefs.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
recent_folders:
- /Users/Dorian/Desktop/COurs ENSAM 1A/langues
- /Users/Dorian/Desktop
- /Users/Dorian/Desktop/COurs ENSAM 1A/langues
- /Users/Dorian/Desktop/COurs ENSAM 1A
- /Users/Dorian/Desktop/Code/text-editor
- /Users/Dorian/Dropbox
recent_files:
- /Users/Dorian/Desktop/test.drn
- /Users/Dorian/Desktop/COurs ENSAM 1A/langues/anglais-questions.txt
- /Users/Dorian/Desktop/nathan.drn
- /Users/Dorian/Desktop/test.drn
59 changes: 35 additions & 24 deletions src/editor.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::{cmp, env, fs};
use std::any::TypeId;
use std::cell::RefCell;
use std::rc::Rc;
use std::path::{Path, PathBuf};
Expand All @@ -23,12 +24,14 @@ use crate::cursor::{Cursor, CURSOR_OFFSET_X};
use crate::camera::Camera;
use crate::contextual_menu::{ContextualMenu, MenuItem};
use crate::{Animation, EditorEvent, FocusElement, MenuId};
use crate::style_range::StyleRange;
use crate::menu_actions::MenuAction;
use crate::font::Font;
use crate::line::Line;
use crate::range::Range;
use crate::selection::Selection;
use crate::editable::Editable;
use crate::range_trait::RangeTrait;
use crate::stats::Stats;

pub const EDITOR_PADDING: f32 = 10.;
Expand All @@ -47,12 +50,11 @@ pub struct Editor {
pub filepath: Option<String>,
pub event_sender: Option<UserEventSender<EditorEvent>>,
pub selection: Selection,
pub underline_buffer: Vec<Range>,
pub bold_buffer: Vec<Range>,
pub style_buffer: Vec<StyleRange>, // a buffer that keeps track of every style in the document
pub menu: ContextualMenu,
pub cached_prefs: Option<serde_yaml::Value>,
pub stats: Stats,
pub should_edit_file: bool, // so the input does not trigger file specific events
pub should_edit_file: bool, // so the input internal editor does not trigger file specific events
}

impl Editor {
Expand All @@ -72,8 +74,7 @@ impl Editor {
modifiers: ModifiersState::default(),
filepath: Option::None,
event_sender: Option::None,
underline_buffer: vec![],
bold_buffer: vec![],
style_buffer: vec![],
menu: ContextualMenu::new(system_font),
cached_prefs: Option::None,
offset,
Expand Down Expand Up @@ -156,7 +157,7 @@ impl Editable for Editor {
VirtualKeyCode::Delete => { self.move_cursor_relative(1, 0); self.delete_char(); },
VirtualKeyCode::Return => if self.modifiers.alt() { self.toggle_ai_contextual_menu() } else { self.new_line() },
VirtualKeyCode::Escape => self.menu.close(),
VirtualKeyCode::Tab => if self.modifiers.alt() { self.menu.open() },
VirtualKeyCode::Tab => if self.modifiers.alt() { self.menu.open() } else { self.add_text(" ") },
_ => { return; },
}
self.update_text_layout();
Expand Down Expand Up @@ -390,7 +391,7 @@ impl Editor {
self.event_sender.as_ref().unwrap().send_event(event).unwrap();
}

pub fn set_dirty(&mut self, dirty: bool) {
pub fn set_dirty(&mut self, dirty: bool) { // Sert the editor in a "unsave" state --> display a star in the title bar
let path = self.filepath.clone().unwrap_or(String::from(""));
self.send_event(EditorEvent::SetDirty(path, dirty)); // Set the editor dirty
}
Expand Down Expand Up @@ -634,35 +635,37 @@ impl Editor {
}

/// Add a range to a buffer according to the underline/bold rules
fn add_range_to_buffer(range: Range, buffer: &mut Vec<Range>) {
fn add_range_to_buffer<T: RangeTrait>(range_like: T, buffer: &mut Vec<T>) {
// switch on the type of the generic parameter to determine wether it's a simple Range or a StyledRange
let range = range_like.get_range();
if !range.is_valid() { return; }
let len = buffer.len();
for mut i in 0 .. len {
assert!(len >= 1);
i = len - 1 - i;
let buffer_range = buffer.get_mut(i).unwrap();
if range == *buffer_range { buffer.remove(i); return; }
let buffer_range = buffer.get_mut(i).unwrap().get_range();
if range == buffer_range { buffer.remove(i); return; }
else if range.include(buffer_range) { buffer.remove(i); }
else if buffer_range.include(&range) {
else if buffer_range.include(range) {
assert!(buffer_range.is_valid());
let before = Range::new(buffer_range.get_real_start().unwrap(), range.get_real_start().unwrap());
let after = Range::new(range.get_real_end().unwrap(), buffer_range.get_real_end().unwrap());
let before = T::new(buffer_range.get_real_start().unwrap(), range.get_real_start().unwrap());
let after = T::new(range.get_real_end().unwrap(), buffer_range.get_real_end().unwrap());
if before.is_valid() { buffer.push(before); }
if after.is_valid() { buffer.push(after); }
buffer.remove(i);
return;
}
}
buffer.push(range);
buffer.push(range_like); // to push the proper struct and not only the range
}

pub fn underline(&mut self) {
Self::add_range_to_buffer(self.selection.get_range(), &mut self.underline_buffer);
Self::add_range_to_buffer(StyleRange::new_underline(self.selection.get_range()), &mut self.style_buffer);
self.set_dirty(true);
}

pub fn bold(&mut self) {
Self::add_range_to_buffer(self.selection.get_range(), &mut self.bold_buffer);
Self::add_range_to_buffer(StyleRange::new_bold(self.selection.get_range()), &mut self.style_buffer);
self.set_dirty(true);
}

Expand Down Expand Up @@ -907,7 +910,10 @@ impl Editor {
let mut encode = String::new();
// Encode underline
encode.push_str("#u: ");
let underline_ranges = self.underline_buffer
let bold_buffer: Vec<Range> = self.style_buffer.iter().filter(|sr| sr.bold == true).map(|sr| sr.range).collect();
let underline_buffer: Vec<Range> = self.style_buffer.iter().filter(|sr| sr.underline == true).map(|sr| sr.range).collect();

let underline_ranges = underline_buffer
.iter()
.map(|r| r.get_id() + ",")
.filter(|id| id != "Invalid range")
Expand All @@ -916,7 +922,7 @@ impl Editor {
encode.push_str("\n");
// Encode bold
encode.push_str("#b: ");
let bold_ranges = self.bold_buffer
let bold_ranges = bold_buffer
.iter()
.map(|r| r.get_id() + ",")
.filter(|id| id != "Invalid range")
Expand Down Expand Up @@ -958,8 +964,7 @@ impl Editor {
pub fn load_txt_file(&mut self, filepath: &str) {
let valid_filepath = fs::canonicalize(filepath).expect("Invalid filepath");
self.lines = vec![Line::new(Rc::clone(&self.font))];
self.underline_buffer = vec![];
self.bold_buffer = vec![];
self.style_buffer = vec![];
self.selection.reset();
self.filepath = Some(filepath.into());
let file_content = fs::read_to_string(&valid_filepath).expect(&format!("Unable to load file to {}", filepath));
Expand Down Expand Up @@ -988,10 +993,15 @@ impl Editor {
self.lines = vec![Line::new(Rc::clone(&self.font))];
self.selection.reset();
self.filepath = Some(filepath.into());
self.style_buffer = vec![];
let file_content = fs::read_to_string(&valid_filepath).expect(&format!("Unable to load file to {}", filepath));
let content_lines = file_content.split('\n').collect();
self.underline_buffer = Range::get_ranges_from_drn_line("#u:", &content_lines);
self.bold_buffer = Range::get_ranges_from_drn_line("#b:", &content_lines);
// Handle style
let underline_buffer = Range::get_ranges_from_drn_line("#u:", &content_lines);
let bold_buffer = Range::get_ranges_from_drn_line("#b:", &content_lines);
for range in underline_buffer { self.style_buffer.push(StyleRange::new_underline(range)) }
for range in bold_buffer { self.style_buffer.push(StyleRange::new_bold(range)) }
// Handle text
for (i, line) in content_lines[2..].iter().enumerate() {
if i < self.lines.len() {
self.lines.push(Line::new(Rc::clone(&self.font)));
Expand Down Expand Up @@ -1038,7 +1048,7 @@ impl Editor {
pub fn update_text_layout(&mut self) {
let mut difference = 0;
for (i, line) in (&mut self.lines).iter_mut().enumerate() {
let diff = line.update_text_layout();
let diff = line.update_text_layout(&self.style_buffer);
if i as u32 == self.cursor.y { difference = diff; }
}
self.font.borrow_mut().style_changed = false;
Expand Down Expand Up @@ -1087,7 +1097,8 @@ impl Editor {
let line_camera = Camera::from_with_offset(&self.camera, Vector2::new(-line_offset, 0.));

// draw underline
for range in &mut self.underline_buffer {
let mut underline_buffer: Vec<Range> = self.style_buffer.iter_mut().filter(|sr| sr.underline == true).map(|sr| sr.range).collect();
for range in &mut underline_buffer {
assert!(range.is_valid());
let line = &self.lines[range.start.unwrap().y as usize];
let line_offset = line.alignment_offset;
Expand Down
2 changes: 1 addition & 1 deletion src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl Font {

pub fn layout_text(&self, text: &str, text_layout_options: TextOptions) -> Rc<FormattedTextBlock> {
let escaped_text = self.format(text)
.replace('\t', " ")// Just for rendering
.replace('\t', " ")// Just for rendering
.replace(" " ,"\u{a0}"); // Just for rendering
self.s2d_font.layout_text(&escaped_text, 2.0 * self.size as f32, text_layout_options)
}
Expand Down
4 changes: 3 additions & 1 deletion src/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ use speedy2d::color::Color;
use speedy2d::dimen::Vector2;
use speedy2d::font::{FormattedTextBlock, TextAlignment, TextOptions};
use speedy2d::Graphics2D;
use crate::style_range::StyleRange;

use crate::font::Font;
use crate::range::Range;

const INITIAL_LINE_CAPACITY: usize = 1024;

Expand Down Expand Up @@ -93,7 +95,7 @@ impl Line {
(start_index, end_index)
}

pub fn update_text_layout(&mut self) -> i32 { // return the difference of length
pub fn update_text_layout(&mut self, style_buffer: &Vec<StyleRange>) -> i32 { // return the difference of length
let string = self.get_text();
let font = self.font.borrow();
let font_formatted_string = font.format(&string);
Expand Down
4 changes: 4 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ mod menu_actions;
mod stats;
mod open_ai_wrapper;
mod loader;
mod style_range;
mod range_trait;


// Uncomment to load TESL parser
// mod tesl;

Expand Down
32 changes: 17 additions & 15 deletions src/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use speedy2d::shape::Rectangle;
use crate::camera::Camera;
use crate::font::Font;
use crate::line::Line;
use crate::range_trait::RangeTrait;

pub fn get_line_length(i: u32, lines: &[Line]) -> u32 {
if i + 1 > lines.len() as u32 { return 0; } // Prevent overflow
Expand Down Expand Up @@ -56,28 +57,30 @@ pub fn vector_min(v1: Vector2<u32>, v2: Vector2<u32>) -> Vector2<u32> {
if vector_max(v1, v2) == v2 { v1 } else { v2 }
}

impl Range {
pub fn new(start: Vector2<u32>, end: Vector2<u32>) -> Self {
impl RangeTrait for Range {
fn new(start: Vector2<u32>, end: Vector2<u32>) -> Self {
Self {
start: Some(start),
end: Some(end),
}
}

pub fn start(&mut self, position: Vector2<u32>) {
fn get_range(&self) -> &Range { &self }

fn start(&mut self, position: Vector2<u32>) {
self.start = Some(Vector2::new(position.x, position.y));
}

pub fn end(&mut self, position: Vector2<u32>) {
fn end(&mut self, position: Vector2<u32>) {
self.end = Some(Vector2::new(position.x, position.y));
}

pub fn reset(&mut self) {
fn reset(&mut self) {
self.start = Option::None;
self.end = Option::None;
}

pub fn add(&mut self, other: Range) {
fn add(&mut self, other: Range) {
if !other.is_valid() { return; }
if !self.is_valid() {
self.start(other.start.unwrap());
Expand All @@ -90,34 +93,34 @@ impl Range {
self.end(end);
}

pub fn include(&self, other: &Range) -> bool {
fn include(&self, other: &Range) -> bool {
if !self.is_valid() || !other.is_valid() { return false; }
vector_min(self.start.unwrap(), other.start.unwrap()) == self.start.unwrap()
&& vector_max(self.end.unwrap(), other.end.unwrap()) == self.end.unwrap()
}

pub fn is_valid(&self) -> bool {
fn is_valid(&self) -> bool {
self.start.is_some() && self.end.is_some() && self.start != self.end
}

pub fn get_id(&self) -> String {
fn get_id(&self) -> String {
if !self.is_valid() { return "Invalid range".to_string() }
let start = self.start.unwrap();
let end = self.end.unwrap();
format!("{}-{}-{}-{}", start.x, start.y, end.x, end.y)
}

pub fn get_real_start(&self) -> Option<Vector2<u32>> {
fn get_real_start(&self) -> Option<Vector2<u32>> {
if !self.is_valid() { return Option::None; }
Some(vector_min(self.start.unwrap(), self.end.unwrap()))
}

pub fn get_real_end(&self) -> Option<Vector2<u32>> {
fn get_real_end(&self) -> Option<Vector2<u32>> {
if !self.is_valid() { return Option::None; }
Some(vector_max(self.start.unwrap(), self.end.unwrap()))
}

pub fn get_ranges_from_drn_line(pattern: &str, lines: &Vec<&str>) -> Vec<Range> {
fn get_ranges_from_drn_line(pattern: &str, lines: &Vec<&str>) -> Vec<Range> {
let mut result = vec![];
let mut line = lines
.iter()
Expand All @@ -138,7 +141,7 @@ impl Range {
result
}

pub fn get_lines_index(&mut self, lines: &[Line]) -> Vec<(u32, u32)> {
fn get_lines_index(&mut self, lines: &[Line]) -> Vec<(u32, u32)> {
// relative index of selection starting in the self.start.y index
if !self.is_valid() { return vec![]; }
let start = self.get_real_start().unwrap();
Expand All @@ -154,7 +157,7 @@ impl Range {
result
}

pub fn _render(&mut self, font: Rc<RefCell<Font>>, lines: &[Line], camera: &Camera, graphics: &mut Graphics2D) {
fn _render(&mut self, font: Rc<RefCell<Font>>, lines: &[Line], camera: &Camera, graphics: &mut Graphics2D) {
if !self.is_valid() { return; }
let font_width = font.borrow().char_width;
let font_height = font.borrow().char_height;
Expand All @@ -173,5 +176,4 @@ impl Range {
)
}
}

}
38 changes: 38 additions & 0 deletions src/range_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use std::cell::RefCell;
use std::rc::Rc;
use speedy2d::dimen::Vector2;
use speedy2d::Graphics2D;
use crate::camera::Camera;
use crate::font::Font;
use crate::line::Line;
use crate::range::Range;

pub trait RangeTrait {
fn new(start: Vector2<u32>, end: Vector2<u32>) -> Self;

fn get_range(&self) -> &Range;

fn start(&mut self, position: Vector2<u32>);

fn end(&mut self, position: Vector2<u32>);

fn reset(&mut self);

fn add(&mut self, other: Self);

fn include(&self, other: &Self) -> bool;

fn is_valid(&self) -> bool;

fn get_id(&self) -> String;

fn get_real_start(&self) -> Option<Vector2<u32>>;

fn get_real_end(&self) -> Option<Vector2<u32>>;

fn get_ranges_from_drn_line(pattern: &str, lines: &Vec<&str>) -> Vec<Range>;

fn get_lines_index(&mut self, lines: &[Line]) -> Vec<(u32, u32)>;

fn _render(&mut self, font: Rc<RefCell<Font>>, lines: &[Line], camera: &Camera, graphics: &mut Graphics2D);
}
1 change: 1 addition & 0 deletions src/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::camera::Camera;
use crate::font::Font;
use crate::line::Line;
use crate::range::{get_line_length, Range};
use crate::range_trait::RangeTrait;

const ANIMATION_DURATION: f32 = 100.; // ms

Expand Down
Loading

0 comments on commit ac5af0c

Please sign in to comment.