mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
done with UI refactor, adjusted colors to roc logo
This commit is contained in:
parent
774f723980
commit
7853c41944
30 changed files with 2719 additions and 3173 deletions
|
@ -1,6 +1,8 @@
|
||||||
use crate::ui::colors::ColorTup;
|
use crate::graphics::colors as gr_colors;
|
||||||
|
use crate::graphics::colors::ColorTup;
|
||||||
pub const TXT_COLOR: ColorTup = (1.0, 1.0, 1.0, 1.0);
|
use crate::ui::colors as ui_colors;
|
||||||
pub const CODE_COLOR: ColorTup = (0.21, 0.55, 0.83, 1.0);
|
|
||||||
pub const BG_COLOR: ColorTup = (0.11, 0.11, 0.13, 1.0);
|
|
||||||
|
|
||||||
|
pub const BG_COL: ColorTup = (0.17, 0.17, 0.19, 1.0);
|
||||||
|
pub const EQUALS_SYNTAX_COL: ColorTup = (0.043, 0.0196, 0.102, 1.0);
|
||||||
|
pub const STRING_SYNTAX_COL: ColorTup = ui_colors::LIGHT_BRAND_COL;
|
||||||
|
pub const CODE_COLOR: ColorTup = gr_colors::WHITE;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use colored::*;
|
use colored::*;
|
||||||
use snafu::{Backtrace, ErrorCompat, Snafu, ResultExt, NoneError};
|
use snafu::{Backtrace, ErrorCompat, NoneError, ResultExt, Snafu};
|
||||||
|
|
||||||
//import errors as follows:
|
//import errors as follows:
|
||||||
// `use crate::error::OutOfBounds;`
|
// `use crate::error::OutOfBounds;`
|
||||||
|
@ -35,10 +35,7 @@ pub enum EdError {
|
||||||
},
|
},
|
||||||
|
|
||||||
#[snafu(display("UIError: {}", msg))]
|
#[snafu(display("UIError: {}", msg))]
|
||||||
UIErrorBacktrace {
|
UIErrorBacktrace { msg: String, backtrace: Backtrace },
|
||||||
msg: String,
|
|
||||||
backtrace: Backtrace,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type EdResult<T, E = EdError> = std::result::Result<T, E>;
|
pub type EdResult<T, E = EdError> = std::result::Result<T, E>;
|
||||||
|
@ -113,9 +110,7 @@ impl From<UIError> for EdError {
|
||||||
let msg = format!("{}", ui_err);
|
let msg = format!("{}", ui_err);
|
||||||
|
|
||||||
// hack to handle EdError derive
|
// hack to handle EdError derive
|
||||||
let dummy_res: Result<(), NoneError> = Err(NoneError{});
|
let dummy_res: Result<(), NoneError> = Err(NoneError {});
|
||||||
dummy_res.context(UIErrorBacktrace {
|
dummy_res.context(UIErrorBacktrace { msg }).unwrap_err()
|
||||||
msg,
|
|
||||||
}).unwrap_err()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::editor::ed_error::EdResult;
|
use crate::editor::ed_error::EdResult;
|
||||||
use crate::editor::mvc::app_model::AppModel;
|
use crate::editor::mvc::app_model::AppModel;
|
||||||
use crate::editor::mvc::app_update::{handle_copy, handle_cut, handle_paste, pass_keydown_to_focused};
|
use crate::editor::mvc::app_update::{
|
||||||
|
handle_copy, handle_cut, handle_paste, pass_keydown_to_focused,
|
||||||
|
};
|
||||||
use winit::event::VirtualKeyCode::*;
|
use winit::event::VirtualKeyCode::*;
|
||||||
use winit::event::{ElementState, ModifiersState, VirtualKeyCode};
|
use winit::event::{ElementState, ModifiersState, VirtualKeyCode};
|
||||||
|
|
||||||
|
@ -15,7 +17,9 @@ pub fn handle_keydown(
|
||||||
}
|
}
|
||||||
|
|
||||||
match virtual_keycode {
|
match virtual_keycode {
|
||||||
Left | Up | Right | Down => pass_keydown_to_focused(&modifiers, virtual_keycode, app_model)?,
|
Left | Up | Right | Down => {
|
||||||
|
pass_keydown_to_focused(&modifiers, virtual_keycode, app_model)?
|
||||||
|
}
|
||||||
|
|
||||||
Copy => handle_copy(app_model)?,
|
Copy => handle_copy(app_model)?,
|
||||||
Paste => handle_paste(app_model)?,
|
Paste => handle_paste(app_model)?,
|
||||||
|
|
|
@ -1,43 +1,30 @@
|
||||||
|
use super::keyboard_input;
|
||||||
|
use crate::editor::colors::BG_COL;
|
||||||
|
use crate::editor::colors::CODE_COLOR;
|
||||||
use crate::editor::ed_error::{print_err, print_ui_err};
|
use crate::editor::ed_error::{print_err, print_ui_err};
|
||||||
use crate::ui::{
|
use crate::editor::mvc::{app_model::AppModel, app_update, ed_model, ed_model::EdModel, ed_view};
|
||||||
ui_error::UIResult,
|
use crate::graphics::colors::to_wgpu_color;
|
||||||
text::text_pos::{TextPos},
|
use crate::graphics::primitives::text::{
|
||||||
text::lines::{Lines},
|
build_glyph_brush, example_code_glyph_rect, queue_code_text_draw, queue_text_draw, Text,
|
||||||
colors::{CODE_COLOR, TXT_COLOR},
|
|
||||||
};
|
};
|
||||||
use crate::graphics::{
|
use crate::graphics::{
|
||||||
lowlevel::buffer::create_rect_buffers,
|
lowlevel::buffer::create_rect_buffers, lowlevel::ortho::update_ortho_buffer,
|
||||||
lowlevel::ortho::update_ortho_buffer,
|
lowlevel::pipelines, style::CODE_FONT_SIZE, style::CODE_TXT_XY,
|
||||||
lowlevel::pipelines,
|
|
||||||
style::CODE_FONT_SIZE,
|
|
||||||
style::CODE_TXT_XY,
|
|
||||||
};
|
};
|
||||||
use crate::graphics::primitives::text::{
|
use crate::ui::{
|
||||||
build_glyph_brush, example_code_glyph_rect, queue_code_text_draw, queue_text_draw,
|
colors::TXT_COLOR, text::lines::Lines, text::text_pos::TextPos, ui_error::UIResult,
|
||||||
Text,
|
|
||||||
};
|
};
|
||||||
use crate::editor::mvc::{
|
|
||||||
app_update, ed_model, ed_view,
|
|
||||||
app_model::AppModel,
|
|
||||||
ed_model::EdModel,
|
|
||||||
};
|
|
||||||
use super::keyboard_input;
|
|
||||||
//use crate::resources::strings::NOTHING_OPENED;
|
//use crate::resources::strings::NOTHING_OPENED;
|
||||||
use super::util::slice_get;
|
use super::util::slice_get;
|
||||||
use crate::lang::{pool::Pool, scope::Scope};
|
use crate::lang::{pool::Pool, scope::Scope};
|
||||||
|
use bumpalo::Bump;
|
||||||
|
use cgmath::Vector2;
|
||||||
use pipelines::RectResources;
|
use pipelines::RectResources;
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use roc_module::symbol::{IdentIds, ModuleIds};
|
use roc_module::symbol::{IdentIds, ModuleIds};
|
||||||
use roc_region::all::Region;
|
use roc_region::all::Region;
|
||||||
use roc_types::subs::VarStore;
|
use roc_types::subs::VarStore;
|
||||||
use bumpalo::Bump;
|
use std::{error::Error, io, path::Path};
|
||||||
use cgmath::Vector2;
|
|
||||||
use std::{
|
|
||||||
io,
|
|
||||||
error::Error,
|
|
||||||
path::Path,
|
|
||||||
};
|
|
||||||
use wgpu::{CommandEncoder, RenderPass, TextureView};
|
use wgpu::{CommandEncoder, RenderPass, TextureView};
|
||||||
use wgpu_glyph::GlyphBrush;
|
use wgpu_glyph::GlyphBrush;
|
||||||
use winit::{
|
use winit::{
|
||||||
|
@ -388,17 +375,14 @@ fn begin_render_pass<'a>(
|
||||||
encoder: &'a mut CommandEncoder,
|
encoder: &'a mut CommandEncoder,
|
||||||
texture_view: &'a TextureView,
|
texture_view: &'a TextureView,
|
||||||
) -> RenderPass<'a> {
|
) -> RenderPass<'a> {
|
||||||
|
let bg_color = to_wgpu_color(BG_COL);
|
||||||
|
|
||||||
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||||
attachment: texture_view,
|
attachment: texture_view,
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
ops: wgpu::Operations {
|
ops: wgpu::Operations {
|
||||||
load: wgpu::LoadOp::Clear(wgpu::Color {
|
load: wgpu::LoadOp::Clear(bg_color),
|
||||||
r: 0.1,
|
|
||||||
g: 0.2,
|
|
||||||
b: 0.3,
|
|
||||||
a: 1.0,
|
|
||||||
}),
|
|
||||||
store: true,
|
store: true,
|
||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
mod colors;
|
||||||
pub mod main;
|
|
||||||
pub mod mvc;
|
|
||||||
mod ed_error;
|
mod ed_error;
|
||||||
mod keyboard_input;
|
mod keyboard_input;
|
||||||
|
pub mod main;
|
||||||
|
mod mvc;
|
||||||
mod render_ast;
|
mod render_ast;
|
||||||
mod colors;
|
pub mod syntax_highlight;
|
||||||
mod util;
|
mod util; // TODO remove pub once we have ast based syntax highlighting
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use super::ed_model::EdModel;
|
use super::ed_model::EdModel;
|
||||||
use crate::editor::ed_error::{
|
use crate::editor::ed_error::{
|
||||||
print_err,
|
print_err,
|
||||||
EdResult,
|
|
||||||
EdError::{ClipboardInitFailed, ClipboardReadFailed, ClipboardWriteFailed},
|
EdError::{ClipboardInitFailed, ClipboardReadFailed, ClipboardWriteFailed},
|
||||||
|
EdResult,
|
||||||
};
|
};
|
||||||
use copypasta::{ClipboardContext, ClipboardProvider};
|
use copypasta::{ClipboardContext, ClipboardProvider};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
use super::app_model;
|
use super::app_model;
|
||||||
use super::app_model::AppModel;
|
use super::app_model::AppModel;
|
||||||
use super::ed_update;
|
use crate::editor::ed_error::EdResult;
|
||||||
use winit::event::{ModifiersState, VirtualKeyCode};
|
|
||||||
use crate::ui::text::{
|
use crate::ui::text::{
|
||||||
lines::{SelectableLines, MutSelectableLines},
|
lines::{MutSelectableLines, SelectableLines},
|
||||||
text_pos::TextPos,
|
text_pos::TextPos,
|
||||||
};
|
};
|
||||||
use crate::ui::ui_error::UIResult;
|
use crate::ui::ui_error::UIResult;
|
||||||
use crate::editor::ed_error::EdResult;
|
use winit::event::{ModifiersState, VirtualKeyCode};
|
||||||
|
|
||||||
pub fn handle_copy(app_model: &mut AppModel) -> EdResult<()> {
|
pub fn handle_copy(app_model: &mut AppModel) -> EdResult<()> {
|
||||||
if let Some(ref mut ed_model) = app_model.ed_model_opt {
|
if let Some(ref mut ed_model) = app_model.ed_model_opt {
|
||||||
|
@ -41,48 +40,32 @@ pub fn handle_paste(app_model: &mut AppModel) -> EdResult<()> {
|
||||||
let start_caret_pos = selection.start_pos;
|
let start_caret_pos = selection.start_pos;
|
||||||
ed_model.text.del_selection()?;
|
ed_model.text.del_selection()?;
|
||||||
|
|
||||||
ed_model
|
ed_model.text.insert_str(&clipboard_content)?;
|
||||||
.text
|
|
||||||
.insert_str(&clipboard_content)?;
|
|
||||||
|
|
||||||
if clipboard_nr_lines > 0 {
|
if clipboard_nr_lines > 0 {
|
||||||
ed_model
|
ed_model.text.set_caret(TextPos {
|
||||||
.text
|
line: start_caret_pos.line + clipboard_nr_lines,
|
||||||
.set_caret( TextPos {
|
column: last_line_nr_chars,
|
||||||
line: start_caret_pos.line + clipboard_nr_lines,
|
})
|
||||||
column: last_line_nr_chars,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
ed_model
|
ed_model.text.set_caret(TextPos {
|
||||||
.text
|
line: start_caret_pos.line,
|
||||||
.set_caret( TextPos {
|
column: start_caret_pos.column + last_line_nr_chars,
|
||||||
line: start_caret_pos.line,
|
})
|
||||||
column: start_caret_pos.column + last_line_nr_chars,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ed_model
|
ed_model.text.insert_str(&clipboard_content)?;
|
||||||
.text
|
|
||||||
.insert_str(&clipboard_content)?;
|
|
||||||
|
|
||||||
if clipboard_nr_lines > 0 {
|
if clipboard_nr_lines > 0 {
|
||||||
ed_model
|
ed_model.text.set_caret(TextPos {
|
||||||
.text
|
line: old_caret_pos.line + clipboard_nr_lines,
|
||||||
.set_caret(
|
column: last_line_nr_chars,
|
||||||
TextPos {
|
})
|
||||||
line: old_caret_pos.line + clipboard_nr_lines,
|
|
||||||
column: last_line_nr_chars,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
ed_model
|
ed_model.text.set_caret(TextPos {
|
||||||
.text
|
line: old_caret_pos.line,
|
||||||
.set_caret(
|
column: old_caret_pos.column + last_line_nr_chars,
|
||||||
TextPos {
|
})
|
||||||
line: old_caret_pos.line,
|
|
||||||
column: old_caret_pos.column + last_line_nr_chars,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +98,7 @@ pub fn pass_keydown_to_focused(
|
||||||
) -> UIResult<()> {
|
) -> UIResult<()> {
|
||||||
if let Some(ref mut ed_model) = app_model.ed_model_opt {
|
if let Some(ref mut ed_model) = app_model.ed_model_opt {
|
||||||
if ed_model.has_focus {
|
if ed_model.has_focus {
|
||||||
ed_update::handle_key_down(modifiers, virtual_keycode, ed_model)?;
|
ed_model.text.handle_key_down(modifiers, virtual_keycode)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,20 +108,20 @@ pub fn pass_keydown_to_focused(
|
||||||
pub fn handle_new_char(received_char: &char, app_model: &mut AppModel) -> EdResult<()> {
|
pub fn handle_new_char(received_char: &char, app_model: &mut AppModel) -> EdResult<()> {
|
||||||
if let Some(ref mut ed_model) = app_model.ed_model_opt {
|
if let Some(ref mut ed_model) = app_model.ed_model_opt {
|
||||||
if ed_model.has_focus {
|
if ed_model.has_focus {
|
||||||
ed_update::handle_new_char(received_char, ed_model)?;
|
ed_model.text.handle_new_char(received_char)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod test_app_update {
|
pub mod test_app_update {
|
||||||
use crate::editor::mvc::app_model;
|
use crate::editor::mvc::app_model;
|
||||||
use crate::editor::mvc::app_model::{AppModel, Clipboard};
|
use crate::editor::mvc::app_model::{AppModel, Clipboard};
|
||||||
use crate::editor::mvc::app_update::{handle_copy, handle_cut, handle_paste};
|
use crate::editor::mvc::app_update::{handle_copy, handle_cut, handle_paste};
|
||||||
use crate::editor::mvc::ed_model::{EdModel};
|
use crate::editor::mvc::ed_model::{EdModel};
|
||||||
use crate::editor::mvc::ed_update::test_ed_update::gen_big_text;
|
|
||||||
use crate::ui::text::{
|
use crate::ui::text::{
|
||||||
big_selectable_text::BigSelectableText,
|
big_selectable_text::BigSelectableText,
|
||||||
selection::test_selection::{all_lines_vec, convert_selection_to_dsl},
|
selection::test_selection::{all_lines_vec, convert_selection_to_dsl},
|
||||||
|
@ -288,4 +271,4 @@ pub mod test_app_update {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use crate::graphics::primitives::rect::Rect;
|
use crate::graphics::primitives::rect::Rect;
|
||||||
use crate::ui::text::{
|
use crate::ui::text::big_selectable_text::{from_path, BigSelectableText};
|
||||||
big_selectable_text::{BigSelectableText, from_path},
|
|
||||||
};
|
|
||||||
use crate::ui::ui_error::UIResult;
|
use crate::ui::ui_error::UIResult;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
|
|
@ -1,427 +0,0 @@
|
||||||
use super::ed_model::EdModel;
|
|
||||||
use crate::ui::text::{
|
|
||||||
text_pos::TextPos,
|
|
||||||
selection::{RawSelection, Selection, validate_selection},
|
|
||||||
big_selectable_text::BigSelectableText,
|
|
||||||
lines::{Lines, SelectableLines, MutSelectableLines},
|
|
||||||
caret_w_select::CaretWSelect,
|
|
||||||
};
|
|
||||||
use crate::ui::ui_error::UIResult;
|
|
||||||
use crate::editor::ed_error::EdResult;
|
|
||||||
use crate::editor::util::is_newline;
|
|
||||||
use std::cmp::{max, min};
|
|
||||||
use winit::event::VirtualKeyCode::*;
|
|
||||||
use winit::event::{ModifiersState, VirtualKeyCode};
|
|
||||||
|
|
||||||
pub type MoveCaretFun =
|
|
||||||
fn(bool, &BigSelectableText) -> UIResult<CaretWSelect>;
|
|
||||||
|
|
||||||
fn validate_sel_opt(start_pos: TextPos, end_pos: TextPos) -> UIResult<Option<Selection>> {
|
|
||||||
Ok(
|
|
||||||
Some(
|
|
||||||
validate_selection(start_pos, end_pos)?
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_arrow(move_caret_fun: MoveCaretFun, modifiers: &ModifiersState, ed_model: &mut EdModel) -> UIResult<()> {
|
|
||||||
let new_caret_w_select = move_caret_fun(
|
|
||||||
modifiers.shift(),
|
|
||||||
&ed_model.text,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
ed_model.text.caret_w_select = new_caret_w_select;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO move this to impl EdModel
|
|
||||||
pub fn handle_select_all(ed_model: &mut EdModel) -> UIResult<()> {
|
|
||||||
if ed_model.text.nr_of_chars() > 0 {
|
|
||||||
let last_pos = ed_model.text.last_text_pos();
|
|
||||||
|
|
||||||
ed_model.text.set_raw_sel(
|
|
||||||
RawSelection {
|
|
||||||
start_pos: TextPos { line: 0, column: 0 },
|
|
||||||
end_pos: last_pos,
|
|
||||||
}
|
|
||||||
)?;
|
|
||||||
|
|
||||||
ed_model.text.set_caret(last_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult<()> {
|
|
||||||
let old_caret_pos = ed_model.text.caret_w_select.caret_pos;
|
|
||||||
|
|
||||||
// TODO move this to ui folder
|
|
||||||
|
|
||||||
match received_char {
|
|
||||||
'\u{8}' | '\u{7f}' => {
|
|
||||||
// On Linux, '\u{8}' is backspace,
|
|
||||||
// on macOS '\u{7f}'.
|
|
||||||
|
|
||||||
if ed_model.text.is_selection_active() {
|
|
||||||
ed_model.text.del_selection()?;
|
|
||||||
} else {
|
|
||||||
ed_model.text.pop_char();
|
|
||||||
}
|
|
||||||
|
|
||||||
ed_model.text.set_sel_none();
|
|
||||||
}
|
|
||||||
ch if is_newline(ch) => {
|
|
||||||
if ed_model.text.is_selection_active() {
|
|
||||||
ed_model.text.del_selection()?;
|
|
||||||
ed_model.text.insert_char(&'\n')?;
|
|
||||||
} else {
|
|
||||||
ed_model.text.insert_char(&'\n')?;
|
|
||||||
|
|
||||||
ed_model.text.set_caret(TextPos {
|
|
||||||
line: old_caret_pos.line + 1,
|
|
||||||
column: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ed_model.text.set_sel_none();
|
|
||||||
}
|
|
||||||
'\u{1}' // Ctrl + A
|
|
||||||
| '\u{3}' // Ctrl + C
|
|
||||||
| '\u{16}' // Ctrl + V
|
|
||||||
| '\u{18}' // Ctrl + X
|
|
||||||
| '\u{e000}'..='\u{f8ff}' // http://www.unicode.org/faq/private_use.html
|
|
||||||
| '\u{f0000}'..='\u{ffffd}' // ^
|
|
||||||
| '\u{100000}'..='\u{10fffd}' // ^
|
|
||||||
=> {
|
|
||||||
// chars that can be ignored
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
if ed_model.text.is_selection_active() {
|
|
||||||
ed_model.text.del_selection()?;
|
|
||||||
ed_model
|
|
||||||
.text
|
|
||||||
.insert_char(received_char)?;
|
|
||||||
|
|
||||||
ed_model.text.set_caret(
|
|
||||||
move_caret_right(false, &ed_model.text)?.caret_pos
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ed_model
|
|
||||||
.text
|
|
||||||
.insert_char(received_char)?;
|
|
||||||
|
|
||||||
ed_model.text.set_caret(
|
|
||||||
TextPos {
|
|
||||||
line: old_caret_pos.line,
|
|
||||||
column: old_caret_pos.column + 1,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ed_model.text.set_sel_none();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle_key_down(
|
|
||||||
modifiers: &ModifiersState,
|
|
||||||
virtual_keycode: VirtualKeyCode,
|
|
||||||
ed_model: &mut EdModel,
|
|
||||||
) -> UIResult<()> {
|
|
||||||
match virtual_keycode {
|
|
||||||
Left => handle_arrow(move_caret_left, modifiers, ed_model),
|
|
||||||
Up => handle_arrow(move_caret_up, modifiers, ed_model),
|
|
||||||
Right => handle_arrow(move_caret_right, modifiers, ed_model),
|
|
||||||
Down => handle_arrow(move_caret_down, modifiers, ed_model),
|
|
||||||
|
|
||||||
A => {
|
|
||||||
if modifiers.ctrl() {
|
|
||||||
handle_select_all(ed_model)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Home => {
|
|
||||||
let curr_line_nr = ed_model.text.caret_w_select.caret_pos.line;
|
|
||||||
// TODO no unwrap
|
|
||||||
let curr_line_str = ed_model.text.get_line(curr_line_nr).unwrap();
|
|
||||||
let line_char_iter = curr_line_str.chars();
|
|
||||||
|
|
||||||
let mut first_no_space_char_col = 0;
|
|
||||||
let mut non_space_found = false;
|
|
||||||
|
|
||||||
for c in line_char_iter {
|
|
||||||
if !c.is_whitespace() {
|
|
||||||
non_space_found = true;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
first_no_space_char_col += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !non_space_found {
|
|
||||||
first_no_space_char_col = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ed_model.text.caret_w_select.move_caret_w_mods(
|
|
||||||
TextPos {
|
|
||||||
line: ed_model.text.caret_w_select.caret_pos.line,
|
|
||||||
column: first_no_space_char_col
|
|
||||||
},
|
|
||||||
modifiers
|
|
||||||
)
|
|
||||||
}
|
|
||||||
End => {
|
|
||||||
let curr_line = ed_model.text.caret_w_select.caret_pos.line;
|
|
||||||
// TODO no unwrap
|
|
||||||
let new_col =
|
|
||||||
max(
|
|
||||||
0,
|
|
||||||
ed_model.text.line_len(curr_line).unwrap() - 1
|
|
||||||
);
|
|
||||||
|
|
||||||
let new_pos =
|
|
||||||
TextPos {
|
|
||||||
line: curr_line,
|
|
||||||
column: new_col
|
|
||||||
};
|
|
||||||
|
|
||||||
ed_model.text.caret_w_select.move_caret_w_mods(new_pos, modifiers)
|
|
||||||
}
|
|
||||||
_ => Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
pub mod test_ed_update {
|
|
||||||
use crate::editor::mvc::app_update::test_app_update::mock_app_model;
|
|
||||||
use crate::editor::mvc::ed_update::{handle_new_char, handle_select_all};
|
|
||||||
use crate::ui::text::{
|
|
||||||
big_selectable_text::BigSelectableText,
|
|
||||||
};
|
|
||||||
use crate::ui::text::selection::test_selection::{
|
|
||||||
all_lines_vec, convert_dsl_to_selection, convert_selection_to_dsl, big_text_from_dsl_str,
|
|
||||||
};
|
|
||||||
use bumpalo::Bump;
|
|
||||||
|
|
||||||
pub fn gen_big_text(
|
|
||||||
lines: &[&str],
|
|
||||||
) -> Result<BigSelectableText, String> {
|
|
||||||
let lines_string_slice: Vec<String> = lines.iter().map(|l| l.to_string()).collect();
|
|
||||||
let mut big_text = big_text_from_dsl_str(&lines_string_slice);
|
|
||||||
let caret_w_select = convert_dsl_to_selection(&lines_string_slice).unwrap();
|
|
||||||
|
|
||||||
big_text.caret_w_select = caret_w_select;
|
|
||||||
|
|
||||||
Ok(big_text)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_insert(
|
|
||||||
pre_lines_str: &[&str],
|
|
||||||
expected_post_lines_str: &[&str],
|
|
||||||
new_char: char,
|
|
||||||
arena: &Bump,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let pre_big_text = gen_big_text(pre_lines_str)?;
|
|
||||||
|
|
||||||
let app_model = mock_app_model(pre_big_text, None);
|
|
||||||
let mut ed_model = app_model.ed_model_opt.unwrap();
|
|
||||||
|
|
||||||
if let Err(e) = handle_new_char(&new_char, &mut ed_model) {
|
|
||||||
return Err(e.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut actual_lines = all_lines_vec(&ed_model.text);
|
|
||||||
let dsl_slice = convert_selection_to_dsl(
|
|
||||||
ed_model.text.caret_w_select,
|
|
||||||
&mut actual_lines,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(dsl_slice, expected_post_lines_str);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn insert_new_char_simple() -> Result<(), String> {
|
|
||||||
let arena = &Bump::new();
|
|
||||||
|
|
||||||
assert_insert(&["|"], &["a|"], 'a', arena)?;
|
|
||||||
assert_insert(&["|"], &[" |"], ' ', arena)?;
|
|
||||||
assert_insert(&["a|"], &["aa|"], 'a', arena)?;
|
|
||||||
assert_insert(&["a|"], &["a |"], ' ', arena)?;
|
|
||||||
assert_insert(&["a|\n", ""], &["ab|\n", ""], 'b', arena)?;
|
|
||||||
assert_insert(&["a|\n", ""], &["ab|\n", ""], 'b', arena)?;
|
|
||||||
assert_insert(&["a\n", "|"], &["a\n", "b|"], 'b', arena)?;
|
|
||||||
assert_insert(&["a\n", "b\n", "c|"], &["a\n", "b\n", "cd|"], 'd', arena)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn insert_new_char_mid() -> Result<(), String> {
|
|
||||||
let arena = &Bump::new();
|
|
||||||
|
|
||||||
assert_insert(&["ab|d"], &["abc|d"], 'c', arena)?;
|
|
||||||
assert_insert(&["a|cd"], &["ab|cd"], 'b', arena)?;
|
|
||||||
assert_insert(&["abc\n", "|e"], &["abc\n", "d|e"], 'd', arena)?;
|
|
||||||
assert_insert(&["abc\n", "def\n", "| "], &["abc\n", "def\n", "g| "], 'g', arena)?;
|
|
||||||
assert_insert(&["abc\n", "def\n", "| "], &["abc\n", "def\n", " | "], ' ', arena)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn simple_backspace() -> Result<(), String> {
|
|
||||||
let arena = &Bump::new();
|
|
||||||
|
|
||||||
assert_insert(&["|"], &["|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&[" |"], &["|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["a|"], &["|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["ab|"], &["a|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["a|\n", ""], &["|\n", ""], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["ab|\n", ""], &["a|\n", ""], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["a\n", "|"], &["a|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["a\n", "b\n", "c|"], &["a\n", "b\n", "|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["a\n", "b\n", "|"], &["a\n", "b|"], '\u{8}', arena)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn selection_backspace() -> Result<(), String> {
|
|
||||||
let arena = &Bump::new();
|
|
||||||
|
|
||||||
assert_insert(&["[a]|"], &["|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["a[a]|"], &["a|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["[aa]|"], &["|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["a[b c]|"], &["a|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["[abc]|\n", ""], &["|\n", ""], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["a\n", "[abc]|"], &["a\n", "|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["[a\n", "abc]|"], &["|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["a[b\n", "cdef ghij]|"], &["a|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["[a\n", "b\n", "c]|"], &["|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(&["a\n", "[b\n", "]|"], &["a\n", "|"], '\u{8}', arena)?;
|
|
||||||
assert_insert(
|
|
||||||
&["abc\n", "d[ef\n", "ghi]|\n", "jkl"],
|
|
||||||
&["abc\n", "d|\n", "jkl"],
|
|
||||||
'\u{8}',
|
|
||||||
arena,
|
|
||||||
)?;
|
|
||||||
assert_insert(
|
|
||||||
&["abc\n", "[def\n", "ghi]|\n", "jkl"],
|
|
||||||
&["abc\n", "|\n", "jkl"],
|
|
||||||
'\u{8}',
|
|
||||||
arena,
|
|
||||||
)?;
|
|
||||||
assert_insert(
|
|
||||||
&["abc\n", "\n", "[def\n", "ghi]|\n", "jkl"],
|
|
||||||
&["abc\n", "\n", "|\n", "jkl"],
|
|
||||||
'\u{8}',
|
|
||||||
arena,
|
|
||||||
)?;
|
|
||||||
assert_insert(
|
|
||||||
&["[abc\n", "\n", "def\n", "ghi\n", "jkl]|"],
|
|
||||||
&["|"],
|
|
||||||
'\u{8}',
|
|
||||||
arena,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn insert_with_selection() -> Result<(), String> {
|
|
||||||
let arena = &Bump::new();
|
|
||||||
|
|
||||||
assert_insert(&["[a]|"], &["z|"], 'z', arena)?;
|
|
||||||
assert_insert(&["a[a]|"], &["az|"], 'z', arena)?;
|
|
||||||
assert_insert(&["[aa]|"], &["z|"], 'z', arena)?;
|
|
||||||
assert_insert(&["a[b c]|"], &["az|"], 'z', arena)?;
|
|
||||||
assert_insert(&["[abc]|\n", ""], &["z|\n", ""], 'z', arena)?;
|
|
||||||
assert_insert(&["a\n", "[abc]|"], &["a\n", "z|"], 'z', arena)?;
|
|
||||||
assert_insert(&["[a\n", "abc]|"], &["z|"], 'z', arena)?;
|
|
||||||
assert_insert(&["a[b\n", "cdef ghij]|"], &["az|"], 'z', arena)?;
|
|
||||||
assert_insert(&["[a\n", "b\n", "c]|"], &["z|"], 'z', arena)?;
|
|
||||||
assert_insert(&["a\n", "[b\n", "]|"], &["a\n", "z|"], 'z', arena)?;
|
|
||||||
assert_insert(
|
|
||||||
&["abc\n", "d[ef\n", "ghi]|\n", "jkl"],
|
|
||||||
&["abc\n", "dz|\n", "jkl"],
|
|
||||||
'z',
|
|
||||||
arena,
|
|
||||||
)?;
|
|
||||||
assert_insert(
|
|
||||||
&["abc\n", "[def\n", "ghi]|\n", "jkl"],
|
|
||||||
&["abc\n", "z|\n", "jkl"],
|
|
||||||
'z',
|
|
||||||
arena,
|
|
||||||
)?;
|
|
||||||
assert_insert(
|
|
||||||
&["abc\n", "\n", "[def\n", "ghi]|\n", "jkl"],
|
|
||||||
&["abc\n", "\n", "z|\n", "jkl"],
|
|
||||||
'z',
|
|
||||||
arena,
|
|
||||||
)?;
|
|
||||||
assert_insert(&["[abc\n", "\n", "def\n", "ghi\n", "jkl]|"], &["z|"], 'z', arena)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_select_all(
|
|
||||||
pre_lines_str: &[&str],
|
|
||||||
expected_post_lines_str: &[&str],
|
|
||||||
arena: &Bump,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let pre_big_text = gen_big_text(pre_lines_str)?;
|
|
||||||
|
|
||||||
let app_model = mock_app_model(pre_big_text, None);
|
|
||||||
let mut ed_model = app_model.ed_model_opt.unwrap();
|
|
||||||
|
|
||||||
handle_select_all(&mut ed_model).unwrap();
|
|
||||||
|
|
||||||
let mut big_text_lines = all_lines_vec(&ed_model.text);
|
|
||||||
let post_lines_str = convert_selection_to_dsl(
|
|
||||||
ed_model.text.caret_w_select,
|
|
||||||
&mut big_text_lines,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
assert_eq!(post_lines_str, expected_post_lines_str);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn select_all() -> Result<(), String> {
|
|
||||||
let arena = &Bump::new();
|
|
||||||
|
|
||||||
assert_select_all(&["|"], &["|"], arena)?;
|
|
||||||
assert_select_all(&["|a"], &["[a]|"], arena)?;
|
|
||||||
assert_select_all(&["a|"], &["[a]|"], arena)?;
|
|
||||||
assert_select_all(&["abc d|ef ghi"], &["[abc def ghi]|"], arena)?;
|
|
||||||
assert_select_all(&["[a]|"], &["[a]|"], arena)?;
|
|
||||||
assert_select_all(&["|[a]"], &["[a]|"], arena)?;
|
|
||||||
assert_select_all(&["|[abc def ghi]"], &["[abc def ghi]|"], arena)?;
|
|
||||||
assert_select_all(&["a\n", "[b\n", "]|"], &["[a\n", "b\n", "]|"], arena)?;
|
|
||||||
assert_select_all(&["a\n", "[b]|\n", ""], &["[a\n", "b\n", "]|"], arena)?;
|
|
||||||
assert_select_all(&["a\n", "|[b\n", "]"], &["[a\n", "b\n", "]|"], arena)?;
|
|
||||||
assert_select_all(
|
|
||||||
&["abc\n", "def\n", "gh|i\n", "jkl"],
|
|
||||||
&["[abc\n", "def\n", "ghi\n", "jkl]|"],
|
|
||||||
arena,
|
|
||||||
)?;
|
|
||||||
assert_select_all(
|
|
||||||
&["|[abc\n", "def\n", "ghi\n", "jkl]"],
|
|
||||||
&["[abc\n", "def\n", "ghi\n", "jkl]|"],
|
|
||||||
arena,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO hometest
|
|
||||||
|
|
||||||
// TODO endtest
|
|
||||||
}
|
|
|
@ -1,12 +1,9 @@
|
||||||
use super::ed_model::{EdModel};
|
use super::ed_model::EdModel;
|
||||||
use crate::ui::ui_error::{MissingGlyphDims};
|
|
||||||
use crate::ui::ui_error::UIResult;
|
|
||||||
use crate::ui::colors::CARET_COLOR;
|
|
||||||
use crate::graphics::primitives::rect::Rect;
|
use crate::graphics::primitives::rect::Rect;
|
||||||
use crate::ui::text::{
|
use crate::ui::colors::CARET_COLOR;
|
||||||
selection::create_selection_rects,
|
use crate::ui::text::{selection::create_selection_rects, text_pos::TextPos};
|
||||||
text_pos::TextPos,
|
use crate::ui::ui_error::MissingGlyphDims;
|
||||||
};
|
use crate::ui::ui_error::UIResult;
|
||||||
use bumpalo::collections::Vec as BumpVec;
|
use bumpalo::collections::Vec as BumpVec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use snafu::ensure;
|
use snafu::ensure;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
pub mod app_model;
|
pub mod app_model;
|
||||||
pub mod app_update;
|
pub mod app_update;
|
||||||
pub mod ed_model;
|
pub mod ed_model;
|
||||||
pub mod ed_update;
|
|
||||||
pub mod ed_view;
|
pub mod ed_view;
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
use cgmath::Vector2;
|
use crate::editor::colors::CODE_COLOR;
|
||||||
use wgpu_glyph::GlyphBrush;
|
|
||||||
use winit::dpi::PhysicalSize;
|
|
||||||
use crate::ui::colors::CODE_COLOR;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
graphics::{
|
graphics::{
|
||||||
primitives::text::{queue_code_text_draw, Text},
|
primitives::text::{queue_code_text_draw, Text},
|
||||||
|
@ -9,6 +6,9 @@ use crate::{
|
||||||
},
|
},
|
||||||
lang::{ast::Expr2, expr::Env},
|
lang::{ast::Expr2, expr::Env},
|
||||||
};
|
};
|
||||||
|
use cgmath::Vector2;
|
||||||
|
use wgpu_glyph::GlyphBrush;
|
||||||
|
use winit::dpi::PhysicalSize;
|
||||||
|
|
||||||
pub fn render_expr2<'a>(
|
pub fn render_expr2<'a>(
|
||||||
env: &mut Env<'a>,
|
env: &mut Env<'a>,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::ui::colors;
|
use crate::editor::colors as ed_colors;
|
||||||
use colors::ColorTup;
|
use crate::graphics::colors as gr_colors;
|
||||||
use crate::graphics::primitives;
|
use crate::graphics::primitives;
|
||||||
|
use gr_colors::ColorTup;
|
||||||
|
|
||||||
//TODO optimize memory allocation
|
//TODO optimize memory allocation
|
||||||
//TODO this is a demo function, the AST should be used for highlighting, see #904.
|
//TODO this is a demo function, the AST should be used for highlighting, see #904.
|
||||||
|
@ -10,16 +11,16 @@ pub fn highlight_code(
|
||||||
) {
|
) {
|
||||||
let split_code = split_inclusive(&code_text.text);
|
let split_code = split_inclusive(&code_text.text);
|
||||||
|
|
||||||
let mut active_color = colors::WHITE;
|
let mut active_color = gr_colors::WHITE;
|
||||||
let mut same_type_str = String::new();
|
let mut same_type_str = String::new();
|
||||||
|
|
||||||
for token_seq in split_code {
|
for token_seq in split_code {
|
||||||
let new_word_color = if token_seq.contains(&'\"'.to_string()) {
|
let new_word_color = if token_seq.contains(&'\"'.to_string()) {
|
||||||
colors::CODE_COLOR
|
ed_colors::STRING_SYNTAX_COL
|
||||||
} else if token_seq.contains(&'='.to_string()) {
|
} else if token_seq.contains(&'='.to_string()) {
|
||||||
colors::BLACK
|
ed_colors::EQUALS_SYNTAX_COL
|
||||||
} else {
|
} else {
|
||||||
colors::WHITE
|
gr_colors::WHITE
|
||||||
};
|
};
|
||||||
|
|
||||||
if new_word_color != active_color {
|
if new_word_color != active_color {
|
|
@ -1,14 +1,7 @@
|
||||||
|
|
||||||
use super::ed_error::{EdResult, OutOfBounds};
|
use super::ed_error::{EdResult, OutOfBounds};
|
||||||
use snafu::OptionExt;
|
use snafu::OptionExt;
|
||||||
use std::slice::SliceIndex;
|
use std::slice::SliceIndex;
|
||||||
|
|
||||||
pub fn is_newline(char_ref: &char) -> bool {
|
|
||||||
let newline_codes = vec!['\u{d}', '\n'];
|
|
||||||
|
|
||||||
newline_codes.contains(char_ref)
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace vec methods that return Option with ones that return Result and proper Error
|
// replace vec methods that return Option with ones that return Result and proper Error
|
||||||
pub fn slice_get<T>(index: usize, slice: &[T]) -> EdResult<&<usize as SliceIndex<[T]>>::Output> {
|
pub fn slice_get<T>(index: usize, slice: &[T]) -> EdResult<&<usize as SliceIndex<[T]>>::Output> {
|
||||||
let elt_ref = slice.get(index).context(OutOfBounds {
|
let elt_ref = slice.get(index).context(OutOfBounds {
|
||||||
|
|
15
editor/src/graphics/colors.rs
Normal file
15
editor/src/graphics/colors.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
pub type ColorTup = (f32, f32, f32, f32);
|
||||||
|
pub const WHITE: ColorTup = (1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
pub fn to_wgpu_color((r, g, b, a): ColorTup) -> wgpu::Color {
|
||||||
|
wgpu::Color {
|
||||||
|
r: r as f64,
|
||||||
|
g: g as f64,
|
||||||
|
b: b as f64,
|
||||||
|
a: a as f64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_slice((r, g, b, a): ColorTup) -> [f32; 4] {
|
||||||
|
[r, g, b, a]
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
// Adapted from https://github.com/sotrh/learn-wgpu
|
// Adapted from https://github.com/sotrh/learn-wgpu
|
||||||
// by Benjamin Hansen, licensed under the MIT license
|
// by Benjamin Hansen, licensed under the MIT license
|
||||||
use super::vertex::Vertex;
|
use super::vertex::Vertex;
|
||||||
use crate::ui::colors::to_slice;
|
use crate::graphics::colors::to_slice;
|
||||||
use crate::graphics::primitives::rect::Rect;
|
use crate::graphics::primitives::rect::Rect;
|
||||||
use bumpalo::collections::Vec as BumpVec;
|
use bumpalo::collections::Vec as BumpVec;
|
||||||
use wgpu::util::{BufferInitDescriptor, DeviceExt};
|
use wgpu::util::{BufferInitDescriptor, DeviceExt};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
pub mod colors;
|
||||||
pub mod lowlevel;
|
pub mod lowlevel;
|
||||||
pub mod primitives;
|
pub mod primitives;
|
||||||
pub mod style;
|
pub mod style;
|
||||||
mod syntax_highlight;
|
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
// by Benjamin Hansen, licensed under the MIT license
|
// by Benjamin Hansen, licensed under the MIT license
|
||||||
|
|
||||||
use super::rect::Rect;
|
use super::rect::Rect;
|
||||||
use crate::ui::colors;
|
use crate::editor::syntax_highlight;
|
||||||
|
use crate::graphics::colors;
|
||||||
|
use crate::graphics::colors::ColorTup;
|
||||||
use crate::graphics::style::{CODE_FONT_SIZE, CODE_TXT_XY};
|
use crate::graphics::style::{CODE_FONT_SIZE, CODE_TXT_XY};
|
||||||
use crate::graphics::syntax_highlight;
|
|
||||||
use ab_glyph::{FontArc, Glyph, InvalidFont};
|
use ab_glyph::{FontArc, Glyph, InvalidFont};
|
||||||
use cgmath::{Vector2, Vector4};
|
use cgmath::{Vector2, Vector4};
|
||||||
use colors::{ColorTup, CODE_COLOR, WHITE};
|
|
||||||
use wgpu_glyph::{ab_glyph, GlyphBrush, GlyphBrushBuilder, GlyphCruncher, Section};
|
use wgpu_glyph::{ab_glyph, GlyphBrush, GlyphBrushBuilder, GlyphCruncher, Section};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -40,7 +40,7 @@ pub fn example_code_glyph_rect(glyph_brush: &mut GlyphBrush<()>) -> Rect {
|
||||||
let code_text = Text {
|
let code_text = Text {
|
||||||
position: CODE_TXT_XY.into(),
|
position: CODE_TXT_XY.into(),
|
||||||
area_bounds: (std::f32::INFINITY, std::f32::INFINITY).into(),
|
area_bounds: (std::f32::INFINITY, std::f32::INFINITY).into(),
|
||||||
color: CODE_COLOR.into(),
|
color: (1.0, 1.0, 1.0, 1.0).into(),
|
||||||
text: "a",
|
text: "a",
|
||||||
size: CODE_FONT_SIZE,
|
size: CODE_FONT_SIZE,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -145,7 +145,7 @@ fn glyph_to_rect(glyph: &wgpu_glyph::SectionGlyph) -> Rect {
|
||||||
top_left_coords: [position.x, top_y].into(),
|
top_left_coords: [position.x, top_y].into(),
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
color: WHITE,
|
color: colors::WHITE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,9 +98,9 @@ impl<'a> File<'a> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_file {
|
mod test_file {
|
||||||
|
use crate::lang::roc_file;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use crate::lang::roc_file;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read_and_fmt_simple_roc_module() {
|
fn read_and_fmt_simple_roc_module() {
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
|
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
|
||||||
#![allow(clippy::large_enum_variant)]
|
#![allow(clippy::large_enum_variant)]
|
||||||
|
|
||||||
|
#[cfg_attr(test, macro_use)]
|
||||||
|
extern crate indoc;
|
||||||
extern crate pest;
|
extern crate pest;
|
||||||
#[cfg_attr(test, macro_use)]
|
#[cfg_attr(test, macro_use)]
|
||||||
extern crate pest_derive;
|
extern crate pest_derive;
|
||||||
#[cfg_attr(test, macro_use)]
|
|
||||||
extern crate indoc;
|
|
||||||
|
|
||||||
mod graphics;
|
|
||||||
mod lang;
|
|
||||||
mod editor;
|
mod editor;
|
||||||
|
mod graphics;
|
||||||
|
pub mod lang; //TODO remove pub for unused warnings
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -18,4 +18,4 @@ use std::path::Path;
|
||||||
|
|
||||||
pub fn launch(filepaths: &[&Path]) -> io::Result<()> {
|
pub fn launch(filepaths: &[&Path]) -> io::Result<()> {
|
||||||
editor::main::launch(filepaths)
|
editor::main::launch(filepaths)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,8 @@
|
||||||
pub type ColorTup = (f32, f32, f32, f32);
|
use crate::graphics::colors as gr_colors;
|
||||||
pub const WHITE: ColorTup = (1.0, 1.0, 1.0, 1.0);
|
use gr_colors::ColorTup;
|
||||||
pub const BLACK: ColorTup = (0.0, 0.0, 0.0, 1.0);
|
|
||||||
|
pub const LIGHT_BRAND_COL: ColorTup = (0.506, 0.337, 0.902, 1.0);
|
||||||
|
//pub const DARK_BRAND_COL: ColorTup = (0.380, 0.169, 0.871, 1.0);
|
||||||
pub const TXT_COLOR: ColorTup = (1.0, 1.0, 1.0, 1.0);
|
pub const TXT_COLOR: ColorTup = (1.0, 1.0, 1.0, 1.0);
|
||||||
pub const CODE_COLOR: ColorTup = (0.21, 0.55, 0.83, 1.0);
|
pub const CARET_COLOR: ColorTup = gr_colors::WHITE;
|
||||||
pub const CARET_COLOR: ColorTup = WHITE;
|
|
||||||
pub const SELECT_COLOR: ColorTup = (0.45, 0.61, 1.0, 1.0);
|
pub const SELECT_COLOR: ColorTup = (0.45, 0.61, 1.0, 1.0);
|
||||||
pub const BG_COLOR: ColorTup = (0.11, 0.11, 0.13, 1.0);
|
|
||||||
|
|
||||||
pub fn to_wgpu_color((r, g, b, a): ColorTup) -> wgpu::Color {
|
|
||||||
wgpu::Color {
|
|
||||||
r: r as f64,
|
|
||||||
g: g as f64,
|
|
||||||
b: b as f64,
|
|
||||||
a: a as f64,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_slice((r, g, b, a): ColorTup) -> [f32; 4] {
|
|
||||||
[r, g, b, a]
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod ui_error;
|
|
||||||
pub mod colors;
|
pub mod colors;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
mod util;
|
pub mod ui_error;
|
||||||
|
mod util;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,8 @@
|
||||||
|
|
||||||
use crate::ui::ui_error::UIResult;
|
|
||||||
use super::text_pos::TextPos;
|
|
||||||
use super::selection::{Selection};
|
|
||||||
use winit::event::{ModifiersState};
|
|
||||||
use super::selection::validate_selection;
|
use super::selection::validate_selection;
|
||||||
|
use super::selection::Selection;
|
||||||
|
use super::text_pos::TextPos;
|
||||||
|
use crate::ui::ui_error::UIResult;
|
||||||
|
use winit::event::ModifiersState;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct CaretWSelect {
|
pub struct CaretWSelect {
|
||||||
|
@ -12,29 +10,20 @@ pub struct CaretWSelect {
|
||||||
pub selection_opt: Option<Selection>,
|
pub selection_opt: Option<Selection>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn mk_some_sel(start_pos: TextPos, end_pos: TextPos) -> UIResult<Option<Selection>> {
|
fn mk_some_sel(start_pos: TextPos, end_pos: TextPos) -> UIResult<Option<Selection>> {
|
||||||
Ok(
|
Ok(Some(validate_selection(start_pos, end_pos)?))
|
||||||
Some(
|
|
||||||
validate_selection(start_pos, end_pos)?
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CaretWSelect {
|
impl Default for CaretWSelect {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
caret_pos: TextPos {
|
caret_pos: TextPos { line: 0, column: 0 },
|
||||||
line: 0,
|
selection_opt: None,
|
||||||
column: 0
|
|
||||||
},
|
|
||||||
selection_opt: None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CaretWSelect {
|
impl CaretWSelect {
|
||||||
|
|
||||||
pub fn new(caret_pos: TextPos, selection_opt: Option<Selection>) -> Self {
|
pub fn new(caret_pos: TextPos, selection_opt: Option<Selection>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
caret_pos,
|
caret_pos,
|
||||||
|
@ -44,72 +33,46 @@ impl CaretWSelect {
|
||||||
|
|
||||||
pub fn move_caret_w_mods(&mut self, new_pos: TextPos, mods: &ModifiersState) -> UIResult<()> {
|
pub fn move_caret_w_mods(&mut self, new_pos: TextPos, mods: &ModifiersState) -> UIResult<()> {
|
||||||
let caret_pos = self.caret_pos;
|
let caret_pos = self.caret_pos;
|
||||||
|
|
||||||
// one does not simply move the caret
|
// one does not simply move the caret
|
||||||
let valid_sel_opt =
|
let valid_sel_opt = if new_pos != caret_pos {
|
||||||
if new_pos != caret_pos {
|
if mods.shift() {
|
||||||
if mods.shift() {
|
if let Some(old_sel) = self.selection_opt {
|
||||||
if let Some(old_sel) = self.selection_opt {
|
if new_pos < old_sel.start_pos {
|
||||||
if new_pos < old_sel.start_pos {
|
if caret_pos > old_sel.start_pos {
|
||||||
if caret_pos > old_sel.start_pos {
|
mk_some_sel(new_pos, old_sel.start_pos)?
|
||||||
mk_some_sel(
|
|
||||||
new_pos,
|
|
||||||
old_sel.start_pos
|
|
||||||
)?
|
|
||||||
} else {
|
|
||||||
mk_some_sel(
|
|
||||||
new_pos,
|
|
||||||
old_sel.end_pos
|
|
||||||
)?
|
|
||||||
}
|
|
||||||
} else if new_pos > old_sel.end_pos {
|
|
||||||
if caret_pos < old_sel.end_pos {
|
|
||||||
mk_some_sel(
|
|
||||||
old_sel.end_pos,
|
|
||||||
new_pos
|
|
||||||
)?
|
|
||||||
} else {
|
|
||||||
mk_some_sel(
|
|
||||||
old_sel.start_pos,
|
|
||||||
new_pos
|
|
||||||
)?
|
|
||||||
}
|
|
||||||
} else if new_pos > caret_pos {
|
|
||||||
mk_some_sel(
|
|
||||||
new_pos,
|
|
||||||
old_sel.end_pos
|
|
||||||
)?
|
|
||||||
} else if new_pos < caret_pos {
|
|
||||||
mk_some_sel(
|
|
||||||
old_sel.start_pos,
|
|
||||||
new_pos
|
|
||||||
)?
|
|
||||||
} else {
|
} else {
|
||||||
// TODO should this return none?
|
mk_some_sel(new_pos, old_sel.end_pos)?
|
||||||
None
|
|
||||||
}
|
}
|
||||||
} else if new_pos < self.caret_pos {
|
} else if new_pos > old_sel.end_pos {
|
||||||
mk_some_sel(
|
if caret_pos < old_sel.end_pos {
|
||||||
new_pos,
|
mk_some_sel(old_sel.end_pos, new_pos)?
|
||||||
caret_pos
|
} else {
|
||||||
)?
|
mk_some_sel(old_sel.start_pos, new_pos)?
|
||||||
|
}
|
||||||
|
} else if new_pos > caret_pos {
|
||||||
|
mk_some_sel(new_pos, old_sel.end_pos)?
|
||||||
|
} else if new_pos < caret_pos {
|
||||||
|
mk_some_sel(old_sel.start_pos, new_pos)?
|
||||||
} else {
|
} else {
|
||||||
mk_some_sel(
|
// TODO should this return none?
|
||||||
caret_pos,
|
None
|
||||||
new_pos
|
|
||||||
)?
|
|
||||||
}
|
}
|
||||||
|
} else if new_pos < self.caret_pos {
|
||||||
|
mk_some_sel(new_pos, caret_pos)?
|
||||||
} else {
|
} else {
|
||||||
None
|
mk_some_sel(caret_pos, new_pos)?
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.selection_opt
|
None
|
||||||
};
|
}
|
||||||
|
} else {
|
||||||
|
self.selection_opt
|
||||||
|
};
|
||||||
|
|
||||||
self.caret_pos = new_pos;
|
self.caret_pos = new_pos;
|
||||||
self.selection_opt = valid_sel_opt;
|
self.selection_opt = valid_sel_opt;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
// Adapted from https://github.com/cessen/ropey by Nathan Vegdahl, licensed under the MIT license
|
// Adapted from https://github.com/cessen/ropey by Nathan Vegdahl, licensed under the MIT license
|
||||||
|
|
||||||
use crate::ui::ui_error::{
|
|
||||||
UIResult,
|
|
||||||
};
|
|
||||||
use crate::ui::text::{
|
use crate::ui::text::{
|
||||||
text_pos::{TextPos},
|
selection::{RawSelection, Selection},
|
||||||
selection::{Selection, RawSelection},
|
text_pos::TextPos,
|
||||||
caret_w_select::CaretWSelect,
|
|
||||||
};
|
};
|
||||||
|
use crate::ui::ui_error::UIResult;
|
||||||
use bumpalo::collections::String as BumpString;
|
use bumpalo::collections::String as BumpString;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
use winit::event::{ModifiersState, VirtualKeyCode};
|
||||||
|
|
||||||
pub trait Lines {
|
pub trait Lines {
|
||||||
fn get_line(&self, line_nr: usize) -> UIResult<&str>;
|
fn get_line(&self, line_nr: usize) -> UIResult<&str>;
|
||||||
|
@ -29,13 +27,13 @@ pub trait SelectableLines {
|
||||||
|
|
||||||
fn set_caret(&mut self, caret_pos: TextPos);
|
fn set_caret(&mut self, caret_pos: TextPos);
|
||||||
|
|
||||||
fn move_caret_left(&mut self, shift_pressed: bool) -> UIResult<CaretWSelect>;
|
fn move_caret_left(&mut self, shift_pressed: bool) -> UIResult<()>;
|
||||||
|
|
||||||
fn move_caret_right(&mut self, shift_pressed: bool) -> UIResult<CaretWSelect>;
|
fn move_caret_right(&mut self, shift_pressed: bool) -> UIResult<()>;
|
||||||
|
|
||||||
fn move_caret_up(&mut self, shift_pressed: bool) -> UIResult<CaretWSelect>;
|
fn move_caret_up(&mut self, shift_pressed: bool) -> UIResult<()>;
|
||||||
|
|
||||||
fn move_caret_down(&mut self, shift_pressed: bool) -> UIResult<CaretWSelect>;
|
fn move_caret_down(&mut self, shift_pressed: bool) -> UIResult<()>;
|
||||||
|
|
||||||
fn get_selection(&self) -> Option<Selection>;
|
fn get_selection(&self) -> Option<Selection>;
|
||||||
|
|
||||||
|
@ -47,15 +45,26 @@ pub trait SelectableLines {
|
||||||
|
|
||||||
fn set_sel_none(&mut self);
|
fn set_sel_none(&mut self);
|
||||||
|
|
||||||
|
fn select_all(&mut self) -> UIResult<()>;
|
||||||
|
|
||||||
fn last_text_pos(&self) -> TextPos;
|
fn last_text_pos(&self) -> TextPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MutSelectableLines {
|
pub trait MutSelectableLines {
|
||||||
fn insert_char(&mut self, new_char: &char) -> UIResult<()>;
|
fn insert_char(&mut self, new_char: &char) -> UIResult<()>;
|
||||||
|
|
||||||
|
// could be for insertion, backspace, del...
|
||||||
|
fn handle_new_char(&mut self, received_char: &char) -> UIResult<()>;
|
||||||
|
|
||||||
fn insert_str(&mut self, new_str: &str) -> UIResult<()>;
|
fn insert_str(&mut self, new_str: &str) -> UIResult<()>;
|
||||||
|
|
||||||
fn pop_char(&mut self);
|
fn pop_char(&mut self) -> UIResult<()>;
|
||||||
|
|
||||||
fn del_selection(&mut self) -> UIResult<()>;
|
fn del_selection(&mut self) -> UIResult<()>;
|
||||||
|
|
||||||
|
fn handle_key_down(
|
||||||
|
&mut self,
|
||||||
|
modifiers: &ModifiersState,
|
||||||
|
virtual_keycode: VirtualKeyCode,
|
||||||
|
) -> UIResult<()>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
pub mod big_selectable_text;
|
||||||
pub mod caret_w_select;
|
pub mod caret_w_select;
|
||||||
|
pub mod lines;
|
||||||
pub mod selection;
|
pub mod selection;
|
||||||
pub mod text_pos;
|
pub mod text_pos;
|
||||||
pub mod big_selectable_text;
|
|
||||||
pub mod lines;
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
@ -25,4 +24,4 @@ impl PartialEq for TextPos {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for TextPos {}
|
impl Eq for TextPos {}
|
||||||
|
|
|
@ -47,4 +47,4 @@ impl From<UIError> for String {
|
||||||
fn from(ui_error: UIError) -> Self {
|
fn from(ui_error: UIError) -> Self {
|
||||||
format!("{}", ui_error)
|
format!("{}", ui_error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,5 @@
|
||||||
|
pub fn is_newline(char_ref: &char) -> bool {
|
||||||
|
let newline_codes = vec!['\u{d}', '\n'];
|
||||||
|
|
||||||
use super::ui_error::{UIResult, OutOfBounds};
|
newline_codes.contains(char_ref)
|
||||||
use snafu::OptionExt;
|
}
|
||||||
use std::slice::SliceIndex;
|
|
||||||
|
|
||||||
// replace vec methods that return Option with ones that return Result and proper Error
|
|
||||||
pub fn slice_get<T>(index: usize, slice: &[T]) -> UIResult<&<usize as SliceIndex<[T]>>::Output> {
|
|
||||||
let elt_ref = slice.get(index).context(OutOfBounds {
|
|
||||||
index,
|
|
||||||
collection_name: "Slice",
|
|
||||||
len: slice.len(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(elt_ref)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue