Skip to content

Commit

Permalink
Add stats & refactor menu action
Browse files Browse the repository at this point in the history
  • Loading branch information
d0rianb committed Jan 26, 2022
1 parent a3b8ebc commit 7300030
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 76 deletions.
31 changes: 31 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ yaml-rust = "0.4"
regex = "1"
strum = "0.23"
strum_macros = "0.23"
ifmt = "0.3.3"

[profile.release]
debug = false
Expand Down
1 change: 0 additions & 1 deletion new-file.txt
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@

22 changes: 13 additions & 9 deletions src/contextual_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use std::rc::Rc;

use speedy2d::color::Color;
use speedy2d::dimen::Vector2;
use speedy2d::font::FormattedTextBlock;
use speedy2d::font::{FormattedTextBlock, TextAlignment, TextOptions};
use speedy2d::Graphics2D;
use speedy2d::window::{ModifiersState, UserEventSender, VirtualKeyCode};

use crate::{Editable, EditorEvent, FocusElement, MenuAction, MenuId};
use crate::{Editable, EditorEvent, FocusElement, MenuId};
use crate::menu_actions::MenuAction;
use crate::animation::{Animation, EasingFunction};
use crate::FocusElement::{Editor, Menu};
use crate::font::Font;
use crate::input::{Input, Validator};
use crate::render_helper::{draw_rounded_rectangle, draw_rounded_rectangle_with_border};
Expand Down Expand Up @@ -73,7 +73,7 @@ impl ContextualMenu {
focus_index: -1,
system_font: font,
formatted_items: vec![],
previous_focus: Editor,
previous_focus: FocusElement::Editor,
event_sender: Option::None,
size_animation: Vector2::new(Option::None, Option::None),
focus_y_animation: Option::None
Expand Down Expand Up @@ -124,6 +124,10 @@ impl ContextualMenu {
}

pub fn handle_key(&mut self, keycode: VirtualKeyCode, modifiers: ModifiersState) {
if self.get_focused_item().action == MenuAction::Information { // Handle informative toggle
if keycode == VirtualKeyCode::Escape || (modifiers.logo() && keycode == VirtualKeyCode::I) { self.close() }
else { return; }
}
match keycode {
VirtualKeyCode::Up => self.move_up(),
VirtualKeyCode::Down => self.move_down(),
Expand Down Expand Up @@ -212,7 +216,7 @@ impl ContextualMenu {

pub fn focus(&mut self) {
self.focus_index = 0;
self.event_sender.as_ref().unwrap().send_event(EditorEvent::Focus(Menu(self.id))).unwrap();
self.event_sender.as_ref().unwrap().send_event(EditorEvent::Focus(FocusElement::Menu(self.id))).unwrap();
self.set_focus(0);
}

Expand Down Expand Up @@ -252,7 +256,7 @@ impl ContextualMenu {
break;
}
}
sub_menu.previous_focus = Menu(id);
sub_menu.previous_focus = FocusElement::Menu(id);
sub_menu.id = sub_menu_id;
sub_menu.define_id();
}
Expand Down Expand Up @@ -292,7 +296,7 @@ impl ContextualMenu {
self.focus();
}

fn width(&self) -> f32 { self.formatted_items.iter().map(|ftb| ftb.width()).max_by(|x, y| x.abs().partial_cmp(&y.abs()).unwrap()).unwrap_or(0.) + 2. * 4. * ITEM_PADDING}
fn width(&self) -> f32 { self.formatted_items.iter().map(|ftb| ftb.width()).max_by(|x, y| x.abs().partial_cmp(&y.abs()).unwrap()).unwrap_or(0.) + 8. * ITEM_PADDING}

fn height(&self) -> f32 { (self.formatted_items.iter().map(|ftb| ftb.height()).max_by(|x, y| x.abs().partial_cmp(&y.abs()).unwrap()).unwrap_or(0.) + ITEM_PADDING) * self.items.len() as f32 + ITEM_PADDING}

Expand All @@ -307,7 +311,7 @@ impl ContextualMenu {
pub fn update_content(&mut self) {
self.formatted_items = self.items
.iter()
.map(|item| self.system_font.borrow().layout_text(&item.title))
.map(|item| self.system_font.borrow().layout_text(&item.title, TextOptions::default().with_wrap_to_width(400., TextAlignment::Left)))
.collect();
}

Expand All @@ -326,7 +330,7 @@ impl ContextualMenu {
draw_rounded_rectangle_with_border(menu_origin.x, menu_origin.y, width, height, 8., BORDER_WIDTH, Color::from_int_rgba(250, 250, 250, 250), graphics);
for (i, item) in self.items.iter_mut().enumerate() {
// draw highlight
if i == self.focus_index as usize {
if i == self.focus_index as usize && item.action != MenuAction::Information {
let computed_i = if let Some(animated_i) = &self.focus_y_animation { animated_i.value } else { i as f32 };
draw_rounded_rectangle(menu_origin.x, menu_origin.y + item_height * computed_i, width, item_height + ITEM_PADDING, 10., highlight_color, graphics);
if let Some(sub_menu) = &mut item.sub_menu {
Expand Down
65 changes: 49 additions & 16 deletions src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ use clipboard::ClipboardProvider;
use clipboard::ClipboardContext;
use lazy_static::lazy_static;
use regex::Regex;
use ifmt::iformat;

extern crate yaml_rust;
use yaml_rust::{Yaml, YamlLoader};

use crate::cursor::{Cursor, CURSOR_OFFSET_X};
use crate::camera::Camera;
use crate::contextual_menu::{ContextualMenu, MenuItem};
use crate::{Animation, EditorEvent, MenuAction, MenuId};
use crate::{Animation, EditorEvent, FocusElement, MenuId};
use crate::menu_actions::MenuAction;
use crate::font::Font;
use crate::line::Line;
use crate::range::Range;
Expand Down Expand Up @@ -170,7 +172,7 @@ impl Editable for Editor {
}

if self.modifiers.alt() { // Move to the previous/next word
let (start, end) = self.lines[self.cursor.y as usize].get_next_jump(self.cursor.x, rel_x);
let (start, end) = self.lines[self.cursor.y as usize].get_next_jump(self.cursor.x);
if rel_x < 0 && start != self.cursor.x {
new_x = start as i32;
} else if rel_x > 0 && end != self.cursor.x {
Expand Down Expand Up @@ -230,6 +232,7 @@ impl Editable for Editor {
fn shortcut(&mut self, c: char) {
match c {
's' => self.save(),
'S' => self.toggle_save_popup(),
'o' => self.load(),
'u' => self.underline(),
'c' => self.copy(),
Expand All @@ -245,6 +248,8 @@ impl Editable for Editor {
'-' => self.decrease_font_size(),
// 'n' => self.contextual_submenu_test(),
'n' => self.new_file_popup(),
'N' => self.new_file("new-file.txt"),
'i' => self.toggle_stats_popup(),
_ => {}
}
}
Expand Down Expand Up @@ -428,7 +433,7 @@ impl Editor {
self.lines.insert(index, new_line);
// Pattern matching for new line
if index == 1 {
self.cursor.move_to(0, self.cursor.y + 1);
self.move_cursor(Vector2::new(0, self.cursor.y + 1));
return;
}
let line_before_buffer= self.lines.get(index - 1).unwrap().buffer.clone();
Expand All @@ -440,10 +445,10 @@ impl Editor {
if text.trim_start().starts_with('-') && text.trim().len() > 1 {
let new_text = " ".repeat(nb_whitespace) + "- ";
last_line.add_text(&new_text);
self.cursor.move_to(nb_whitespace as u32 + 2, self.cursor.y + 1);
self.move_cursor(Vector2::new(nb_whitespace as u32 + 2, self.cursor.y + 1));
self.menu.open_with(vec![MenuItem::new("Annuler", MenuAction::CancelChip) ]);
} else {
self.cursor.move_to(0, self.cursor.y + 1);
self.move_cursor(Vector2::new(0, self.cursor.y + 1));
}
}

Expand Down Expand Up @@ -555,6 +560,23 @@ impl Editor {
self.event_sender.as_ref().unwrap().send_event(EditorEvent::Redraw).unwrap();
}

fn get_stats(&self) -> Vec<String> {
let words_count = self.lines.iter().fold(0, |acc, line| acc + line.get_word_count());
let char_count = self.lines.iter().fold(0, |acc, line| acc + line.buffer.len());
vec![
iformat!("Nombre de mots: {words_count}").into(),
iformat!("Nombre de caractères: {char_count}").into(),
iformat!("Nombre de lignes: {self.lines.len()}").into(),
iformat!("Position du curseur: ({self.cursor.x}, {self.cursor.y})").into(),
]
}

fn toggle_stats_popup(&mut self) {
if self.menu.is_visible { return self.menu.close(); }
self.menu.open_with(self.get_stats().iter().map(|s| MenuItem::new(s, MenuAction::Information)).collect());
self.event_sender.as_ref().unwrap().send_event(EditorEvent::Focus(FocusElement::Editor)).unwrap();
}

fn get_prefs_key(&self, key: &str) -> Yaml {
lazy_static! {
static ref PREFS_PATH: &'static Path = Path::new("./resources/prefs.yaml");
Expand Down Expand Up @@ -617,19 +639,23 @@ impl Editor {
if let Some(f) = self.filepath.clone() {
self.save_to_file(&f);
} else {
let mut path_items = vec![];
for (name, path) in self.get_recent_paths() {
path_items.push(MenuItem::new(&name, MenuAction::SaveWithInput(path)));
}
let path_submenu = ContextualMenu::new_with_items(self.system_font.clone(), self.event_sender.clone().unwrap(), path_items);
let mut file_items = vec![MenuItem::new_with_submenu("Save to >".into(), path_submenu)];
for (name, path) in self.get_recent_files() {
file_items.push(MenuItem::new(&name, MenuAction::Save(path)));
}
self.menu.open_with(file_items);
self.toggle_save_popup()
}
}

fn toggle_save_popup(&mut self) {
let mut path_items = vec![];
for (name, path) in self.get_recent_paths() {
path_items.push(MenuItem::new(&name, MenuAction::SaveWithInput(path)));
}
let path_submenu = ContextualMenu::new_with_items(self.system_font.clone(), self.event_sender.clone().unwrap(), path_items);
let mut file_items = vec![MenuItem::new_with_submenu("Save to >".into(), path_submenu)];
for (name, path) in self.get_recent_files() {
file_items.push(MenuItem::new(&name, MenuAction::Save(path)));
}
self.menu.open_with(file_items);
}

/// Save to a specific file
pub fn save_to_file(&mut self, filepath: &str) {
let path = Path::new(filepath);
Expand Down Expand Up @@ -676,7 +702,7 @@ impl Editor {
self.lines[i].add_text(line);
}
let mut i : usize = self.lines.len() - 1;
while i >= 0 && self.lines[i].is_empty() { // Remove the empty lines at the end of the file
while i > 0 && self.lines[i].is_empty() { // Remove the empty lines at the end of the file
self.lines.pop();
i -= 1;
}
Expand All @@ -695,6 +721,12 @@ impl Editor {
animations
}

fn update_stats(&mut self) {
if self.menu.is_visible && self.menu.get_focused_item().action == MenuAction::Information {
self.menu.set_items(self.get_stats().iter().map(|s| MenuItem::new(s, MenuAction::Information)).collect());
}
}

pub fn update_text_layout(&mut self) {
let mut difference = 0;
for (i, line) in (&mut self.lines).iter_mut().enumerate() {
Expand All @@ -703,6 +735,7 @@ impl Editor {
}
self.font.borrow_mut().style_changed = false;
self.cursor.move_to((self.cursor.x as i32 - difference) as u32, self.cursor.y);
self.update_stats();
}

pub fn update(&mut self, dt: f32) {
Expand Down
3 changes: 1 addition & 2 deletions src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ impl Font {
.replace(">=" ,"\u{2265}")
}

pub fn layout_text(&self, text: &str) -> Rc<FormattedTextBlock> {
let text_layout_options = TextOptions::default();
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(" " ,"\u{a0}"); // Just for rendering
Expand Down
3 changes: 2 additions & 1 deletion src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use speedy2d::Graphics2D;
use speedy2d::shape::Rectangle;
use speedy2d::window::{UserEventSender, VirtualKeyCode};

use crate::{Animation, Editable, Editor, EditorEvent, FocusElement, MenuAction, MenuActionFn, MenuId};
use crate::{Animation, Editable, Editor, EditorEvent, FocusElement, MenuId};
use crate::menu_actions::{MenuAction, MenuActionFn};
use crate::animation::EasingFunction;
use crate::camera::Camera;
use crate::render_helper::draw_rounded_rectangle_with_border;
Expand Down
11 changes: 6 additions & 5 deletions src/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ use std::cell::RefCell;

use speedy2d::color::Color;
use speedy2d::dimen::Vector2;
use speedy2d::font::{FormattedTextBlock, TextAlignment};
use speedy2d::font::{FormattedTextBlock, TextAlignment, TextOptions};
use speedy2d::Graphics2D;
use crate::cursor::Cursor;

use crate::font::Font;

Expand All @@ -25,7 +24,7 @@ pub struct Line {

impl Line {
pub fn new(font: Rc<RefCell<Font>>) -> Self {
let formatted_text_block = font.borrow().layout_text("");
let formatted_text_block = font.borrow().layout_text("", TextOptions::default());
Line {
buffer: Vec::with_capacity(INITIAL_LINE_CAPACITY),
previous_string: String::new(),
Expand Down Expand Up @@ -66,6 +65,8 @@ impl Line {
self.buffer.join("")
}

pub fn get_word_count(&self) -> u32 { self.buffer.join("").split(" ").filter(|w| *w != "").count() as u32 }

pub fn get_word_at(&self, index: u32) -> (u32, u32) {
let mut start_index = index;
let mut end_index = index;
Expand All @@ -79,7 +80,7 @@ impl Line {
(start_index, end_index)
}

pub fn get_next_jump(&self, index: u32, dir: i32) -> (u32, u32) {
pub fn get_next_jump(&self, index: u32) -> (u32, u32) {
let mut start_index = index;
let mut end_index = index;
let char_jump_list = [' ', '_', '-'];
Expand Down Expand Up @@ -107,7 +108,7 @@ impl Line {
diff -= self.buffer.len() as i32;
}
if font_formatted_string != self.previous_string || font.style_changed{
self.formatted_text_block = font.layout_text(&font_formatted_string);
self.formatted_text_block = font.layout_text(&font_formatted_string, TextOptions::default());
self.previous_string = font_formatted_string;
}
diff
Expand Down
Loading

0 comments on commit 7300030

Please sign in to comment.