Skip to content

Commit

Permalink
Fonctionnal one liner editor with minimum functionalities
Browse files Browse the repository at this point in the history
  • Loading branch information
d0rianb committed Dec 16, 2021
1 parent 60c9c1a commit 617d9c7
Show file tree
Hide file tree
Showing 8 changed files with 1,899 additions and 0 deletions.
1,706 changes: 1,706 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

Binary file added resources/font/CloisterBlack.ttf
Binary file not shown.
Binary file added resources/font/CourierRegular.ttf
Binary file not shown.
Binary file added resources/font/Roboto-Regular.ttf
Binary file not shown.
52 changes: 52 additions & 0 deletions src/cursor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use speedy2d::color::Color;
use speedy2d::dimen::Vector2;
use speedy2d::Graphics2D;
use speedy2d::shape::Rectangle;

use std::cmp;

use crate::font::Font;

const EDITOR_PADDING: u32 = 5;
const CURSOR_WIDTH: f32 = 3.0;
const CURSOR_OFFSET_X: f32 = 5.0;
const OFFSET: Vector2<u32> = Vector2 { x: EDITOR_PADDING, y: EDITOR_PADDING };

pub fn _clamp<T: Ord>(min: T, x: T, max: T) -> T {
return cmp::max(min, cmp::min(x, max));
}

pub(crate) struct Cursor {
pub x: u32,
pub y: u32,
pub font: Font,
}

impl Cursor {
pub fn move_relative(&mut self, rel_x: i32, rel_y: i32) {
self.x = cmp::max(0, self.x as i32 + rel_x) as u32;
self.y = cmp::max(0, self.y as i32 + rel_y) as u32;
}

pub fn move_to(&mut self, x: u32, y: u32) {
self.x = (x as f32 / self.font.char_width) as u32 + OFFSET.x;
self.y = (y as f32 / self.font.char_height) as u32 + OFFSET.y;
// transition(x, y);
}

pub fn computed_x(&self) -> f32 { self.x as f32 * self.font.char_width }
pub fn computed_y(&self) -> f32 { self.y as f32 * self.font.char_height }

fn _transition(&mut self, x: u32, y: u32) {}

fn get_rectangle(&self) -> Rectangle<f32> {
Rectangle::new(
Vector2::new(self.computed_x() + CURSOR_OFFSET_X, self.computed_y()),
Vector2::new((self.computed_x() + CURSOR_OFFSET_X + CURSOR_WIDTH) as f32, self.computed_y() + self.font.char_height)
)
}

pub fn render(&self, graphics: &mut Graphics2D) {
graphics.draw_rectangle(self.get_rectangle(), Color::BLACK);
}
}
61 changes: 61 additions & 0 deletions src/editor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use std::rc::Rc;
use speedy2d::color::Color;
use speedy2d::dimen::Vector2;
use speedy2d::font::{FormattedTextBlock};
use speedy2d::Graphics2D;
use crate::cursor::Cursor;
use crate::font::Font;

const FONT_SIZE: u32 = 16;
const EDITOR_PADDING: u32 = 5;

pub(crate) struct Editor {
pub buffer: Vec<String>,
pub cursor: Cursor,
pub font: Font,
previous_string: String,
formatted_text_block: Rc<FormattedTextBlock>
}

impl Editor {
pub fn new() -> Editor {
let font = Font::new("resources/font/CourierRegular.ttf");
Editor {
buffer: Vec::with_capacity(2048),
cursor: Cursor { x: 0, y: 0, font: font.clone() },
formatted_text_block: font.layout_text(""),
previous_string: String::new(),
font,
}
}

pub fn move_cursor_relative(&mut self, rel_x: i32, rel_y: i32) {
if self.cursor.x as i32 + rel_x <= self.buffer.len() as i32 {
self.cursor.move_relative(rel_x, rel_y);
}
}

pub fn add_char(&mut self, c: String) {
self.buffer.insert(self.cursor.x as usize, c);
self.move_cursor_relative(1, 0);
}

pub fn delete_char(&mut self) {
if self.buffer.len() == 0 { return };
self.buffer.remove(self.cursor.x as usize - 1);
self.move_cursor_relative(-1, 0);
}

pub fn update(&mut self) {
let string = self.buffer.clone().join("");
if string != self.previous_string {
self.formatted_text_block = self.font.layout_text(&string);
self.previous_string = string;
}
}

pub fn render(&mut self, graphics: &mut Graphics2D) {
graphics.draw_text(Vector2::new(EDITOR_PADDING as f32, EDITOR_PADDING as f32), Color::BLACK, &self.formatted_text_block);
self.cursor.render(graphics);
}
}
31 changes: 31 additions & 0 deletions src/font.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use std::fs;
use std::rc::Rc;
use speedy2d::font::{Font as S2DFont, FormattedTextBlock, TextLayout, TextOptions};

const FONT_SIZE: u32 = 16;

#[derive(Debug, Clone)]
pub(crate) struct Font {
pub name: String,
pub char_width: f32,
pub char_height: f32,
pub s2d_font: S2DFont
}

impl Font {
pub fn new(src: &str) -> Self {
let font_file_content = fs::read(src).unwrap();
let s2d_font = S2DFont::new(&font_file_content).unwrap();
let font_layout = s2d_font.layout_text("a", 2.0*FONT_SIZE as f32, TextOptions::default());
Self {
name: src.to_string(),
char_width: font_layout.width().round(),
char_height: font_layout.height().round(),
s2d_font
}
}

pub fn layout_text(&self, text: &str) -> Rc<FormattedTextBlock> {
self.s2d_font.layout_text(text, 2.0*FONT_SIZE as f32, TextOptions::default())
}
}
49 changes: 49 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
mod editor;
mod cursor;
mod font;
use editor::Editor;

use speedy2d::color::Color;
use speedy2d::{Graphics2D, Window};
use speedy2d::dimen::Vector2;
use speedy2d::window::{KeyScancode, ModifiersState, MouseButton, VirtualKeyCode, WindowHandler, WindowHelper, WindowStartupInfo};

struct EditorMyWindowHandler {
editor: Editor
}

impl WindowHandler for EditorMyWindowHandler {

fn on_draw(&mut self, helper: &mut WindowHelper, graphics: &mut Graphics2D) {
graphics.clear_screen(Color::WHITE);
self.editor.render(graphics);
helper.request_redraw();
}

fn on_key_down(&mut self, helper: &mut WindowHelper, virtual_key_code: Option<VirtualKeyCode>, scancode: KeyScancode) {
match virtual_key_code {
Some(VirtualKeyCode::Right) => self.editor.move_cursor_relative(1, 0),
Some(VirtualKeyCode::Left) => self.editor.move_cursor_relative(-1, 0),
_ => ()
}
}

fn on_keyboard_char(&mut self, helper: &mut WindowHelper, unicode_codepoint: char) {
match unicode_codepoint {
'\u{7f}' => self.editor.delete_char(),
'\t' => (),
'\r' => (),
_ => self.editor.add_char(unicode_codepoint.to_string())
}
self.editor.update();
}

fn on_keyboard_modifiers_changed(&mut self, helper: &mut WindowHelper, state: ModifiersState) {
}
}

fn main() {
let window = Window::new_centered("Editor", (1200, 800)).unwrap();
let editor = Editor::new();
window.run_loop(EditorMyWindowHandler { editor });
}

0 comments on commit 617d9c7

Please sign in to comment.