Start handle window resize (#12)
* Start handle window resize * Save new window size, resize menu and file editor * Add clipping for performaance, fix editor height and width * Update readme
This commit is contained in:
parent
7e2218bf82
commit
0cf8629868
@ -19,7 +19,7 @@ Text editor in rust
|
|||||||
* [ ] Config edit menu
|
* [ ] Config edit menu
|
||||||
* [ ] Project tree
|
* [ ] Project tree
|
||||||
* [ ] Cover `rider` with tests
|
* [ ] Cover `rider` with tests
|
||||||
* [ ] Handle resize window
|
* [x] Handle resize window
|
||||||
|
|
||||||
### v1.1
|
### v1.1
|
||||||
|
|
||||||
|
@ -14,29 +14,21 @@ use sdl2::rect::{Point, Rect};
|
|||||||
use sdl2::VideoSubsystem as VS;
|
use sdl2::VideoSubsystem as VS;
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::*;
|
||||||
|
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
menu_bar: MenuBar,
|
menu_bar: MenuBar,
|
||||||
files: Vec<EditorFile>,
|
files: Vec<EditorFile>,
|
||||||
config: Rc<Config>,
|
config: Arc<RwLock<Config>>,
|
||||||
file_editor: FileEditor,
|
file_editor: FileEditor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
pub fn new(config: Rc<Config>) -> Self {
|
pub fn new(config: Arc<RwLock<Config>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
menu_bar: MenuBar::new(config.clone()),
|
menu_bar: MenuBar::new(Arc::clone(&config)),
|
||||||
files: vec![],
|
files: vec![],
|
||||||
file_editor: FileEditor::new(
|
file_editor: FileEditor::new(Arc::clone(&config)),
|
||||||
Rect::new(
|
|
||||||
config.editor_left_margin(),
|
|
||||||
config.editor_top_margin(),
|
|
||||||
config.width() - config.editor_left_margin() as u32,
|
|
||||||
config.height() - config.editor_top_margin() as u32,
|
|
||||||
),
|
|
||||||
config.clone(),
|
|
||||||
),
|
|
||||||
config,
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,7 +48,7 @@ impl AppState {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config(&self) -> &Rc<Config> {
|
pub fn config(&self) -> &Arc<RwLock<Config>> {
|
||||||
&self.config
|
&self.config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,10 +6,11 @@ use crate::ui::caret::{CaretPosition, MoveDirection};
|
|||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::*;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use sdl2::event::Event;
|
use sdl2::event::*;
|
||||||
use sdl2::hint;
|
use sdl2::hint;
|
||||||
use sdl2::keyboard::{Keycode, Mod};
|
use sdl2::keyboard::{Keycode, Mod};
|
||||||
use sdl2::mouse::*;
|
use sdl2::mouse::*;
|
||||||
@ -41,6 +42,7 @@ pub enum UpdateResult {
|
|||||||
MoveCaretUp,
|
MoveCaretUp,
|
||||||
MoveCaretDown,
|
MoveCaretDown,
|
||||||
Scroll { x: i32, y: i32 },
|
Scroll { x: i32, y: i32 },
|
||||||
|
WindowResize { width: i32, height: i32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Task {
|
pub enum Task {
|
||||||
@ -48,7 +50,7 @@ pub enum Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Application {
|
pub struct Application {
|
||||||
config: Rc<Config>,
|
config: Arc<RwLock<Config>>,
|
||||||
clear_color: Color,
|
clear_color: Color,
|
||||||
sdl_context: Sdl,
|
sdl_context: Sdl,
|
||||||
canvas: WindowCanvas,
|
canvas: WindowCanvas,
|
||||||
@ -58,7 +60,7 @@ pub struct Application {
|
|||||||
|
|
||||||
impl Application {
|
impl Application {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let config = Rc::new(Config::new());
|
let config = Arc::new(RwLock::new(Config::new()));
|
||||||
let sdl_context = sdl2::init().unwrap();
|
let sdl_context = sdl2::init().unwrap();
|
||||||
|
|
||||||
hint::set("SDL_GL_MULTISAMPLEBUFFERS", "1");
|
hint::set("SDL_GL_MULTISAMPLEBUFFERS", "1");
|
||||||
@ -69,26 +71,30 @@ impl Application {
|
|||||||
|
|
||||||
let video_subsystem = sdl_context.video().unwrap();
|
let video_subsystem = sdl_context.video().unwrap();
|
||||||
|
|
||||||
let mut window: Window = video_subsystem
|
let mut window: Window = {
|
||||||
.window("Rider", config.width(), config.height())
|
let c = config.read().unwrap();
|
||||||
.position_centered()
|
video_subsystem
|
||||||
.resizable()
|
.window("Rider", c.width(), c.height())
|
||||||
.opengl()
|
.position_centered()
|
||||||
.build()
|
.resizable()
|
||||||
.unwrap();
|
.opengl()
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
let icon_bytes = include_bytes!("../../assets/gear-64x64.bmp").clone();
|
let icon_bytes = include_bytes!("../../assets/gear-64x64.bmp").clone();
|
||||||
let mut rw = RWops::from_bytes(&icon_bytes).unwrap();
|
let mut rw = RWops::from_bytes(&icon_bytes).unwrap();
|
||||||
let mut icon = Surface::load_bmp_rw(&mut rw).unwrap();
|
let mut icon = Surface::load_bmp_rw(&mut rw).unwrap();
|
||||||
window.set_icon(&mut icon);
|
window.set_icon(&mut icon);
|
||||||
|
|
||||||
let canvas = window.into_canvas().accelerated().build().unwrap();
|
let canvas = window.into_canvas().accelerated().build().unwrap();
|
||||||
|
let clear_color: Color = { config.read().unwrap().theme().background().into() };
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
sdl_context,
|
sdl_context,
|
||||||
video_subsystem,
|
video_subsystem,
|
||||||
canvas,
|
canvas,
|
||||||
tasks: vec![],
|
tasks: vec![],
|
||||||
clear_color: config.theme().background().into(),
|
clear_color,
|
||||||
config,
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,8 +109,8 @@ impl Application {
|
|||||||
let font_context = sdl2::ttf::init().unwrap();
|
let font_context = sdl2::ttf::init().unwrap();
|
||||||
let texture_creator = self.canvas.texture_creator();
|
let texture_creator = self.canvas.texture_creator();
|
||||||
let sleep_time = Duration::new(0, 1_000_000_000u32 / 60);
|
let sleep_time = Duration::new(0, 1_000_000_000u32 / 60);
|
||||||
let mut app_state = AppState::new(self.config.clone());
|
let mut app_state = AppState::new(Arc::clone(&self.config));
|
||||||
let mut renderer = Renderer::new(self.config.clone(), &font_context, &texture_creator);
|
let mut renderer = Renderer::new(Arc::clone(&self.config), &font_context, &texture_creator);
|
||||||
app_state.prepare_ui(&mut renderer);
|
app_state.prepare_ui(&mut renderer);
|
||||||
|
|
||||||
'running: loop {
|
'running: loop {
|
||||||
@ -143,6 +149,15 @@ impl Application {
|
|||||||
UpdateResult::Scroll { x, y } => {
|
UpdateResult::Scroll { x, y } => {
|
||||||
app_state.file_editor_mut().scroll_to(x, y);
|
app_state.file_editor_mut().scroll_to(x, y);
|
||||||
}
|
}
|
||||||
|
UpdateResult::WindowResize { width, height } => {
|
||||||
|
let mut c = app_state.config().write().unwrap();
|
||||||
|
if width > 0 {
|
||||||
|
c.set_width(width as u32);
|
||||||
|
}
|
||||||
|
if height > 0 {
|
||||||
|
c.set_height(height as u32);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for task in self.tasks.iter() {
|
for task in self.tasks.iter() {
|
||||||
match task {
|
match task {
|
||||||
@ -222,13 +237,22 @@ impl Application {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Event::Window {
|
||||||
|
win_event: WindowEvent::Resized(w, h),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
return UpdateResult::WindowResize {
|
||||||
|
width: w,
|
||||||
|
height: h,
|
||||||
|
};
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UpdateResult::NoOp
|
UpdateResult::NoOp
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config(&self) -> &Rc<Config> {
|
pub fn config(&self) -> &Arc<RwLock<Config>> {
|
||||||
&self.config
|
&self.config
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ use crate::app::*;
|
|||||||
use crate::renderer::Renderer;
|
use crate::renderer::Renderer;
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
use sdl2::rect::*;
|
use sdl2::rect::*;
|
||||||
|
use std::sync::*;
|
||||||
|
|
||||||
fn current_file_path(file_editor: &mut FileEditor) -> String {
|
fn current_file_path(file_editor: &mut FileEditor) -> String {
|
||||||
file_editor
|
file_editor
|
||||||
@ -119,7 +120,7 @@ pub fn insert_new_line(file_editor: &mut FileEditor, renderer: &mut Renderer) {
|
|||||||
buffer.insert(position.text_position(), '\n');
|
buffer.insert(position.text_position(), '\n');
|
||||||
if let Some(rect) = get_text_character_rect('\n', renderer) {
|
if let Some(rect) = get_text_character_rect('\n', renderer) {
|
||||||
pos = Point::new(
|
pos = Point::new(
|
||||||
file_editor.config().editor_left_margin(),
|
file_editor.config().read().unwrap().editor_left_margin(),
|
||||||
pos.y() + rect.height() as i32,
|
pos.y() + rect.height() as i32,
|
||||||
);
|
);
|
||||||
position = position.moved(0, 1, 0);
|
position = position.moved(0, 1, 0);
|
||||||
@ -129,7 +130,7 @@ pub fn insert_new_line(file_editor: &mut FileEditor, renderer: &mut Renderer) {
|
|||||||
let mut new_file = EditorFile::new(
|
let mut new_file = EditorFile::new(
|
||||||
current_file_path(file_editor),
|
current_file_path(file_editor),
|
||||||
buffer,
|
buffer,
|
||||||
file_editor.config().clone(),
|
Arc::clone(file_editor.config()),
|
||||||
);
|
);
|
||||||
new_file.prepare_ui(renderer);
|
new_file.prepare_ui(renderer);
|
||||||
file_editor.replace_current_file(new_file);
|
file_editor.replace_current_file(new_file);
|
||||||
|
@ -91,10 +91,18 @@ impl Config {
|
|||||||
self.width
|
self.width
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_width(&mut self, w: u32) {
|
||||||
|
self.width = w;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn height(&self) -> u32 {
|
pub fn height(&self) -> u32 {
|
||||||
self.height
|
self.height
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_height(&mut self, h: u32) {
|
||||||
|
self.height = h;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn editor_config(&self) -> &EditorConfig {
|
pub fn editor_config(&self) -> &EditorConfig {
|
||||||
&self.editor_config
|
&self.editor_config
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,12 @@ use sdl2::render::{Texture, TextureCreator};
|
|||||||
use sdl2::ttf::Sdl2TtfContext;
|
use sdl2::ttf::Sdl2TtfContext;
|
||||||
use sdl2::video::WindowContext;
|
use sdl2::video::WindowContext;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::*;
|
||||||
|
|
||||||
pub mod managers;
|
pub mod managers;
|
||||||
|
|
||||||
pub struct Renderer<'a> {
|
pub struct Renderer<'a> {
|
||||||
config: Rc<Config>,
|
config: Arc<RwLock<Config>>,
|
||||||
font_manager: FontManager<'a>,
|
font_manager: FontManager<'a>,
|
||||||
texture_manager: TextureManager<'a, WindowContext>,
|
texture_manager: TextureManager<'a, WindowContext>,
|
||||||
scroll: Point,
|
scroll: Point,
|
||||||
@ -19,7 +20,7 @@ pub struct Renderer<'a> {
|
|||||||
|
|
||||||
impl<'a> Renderer<'a> {
|
impl<'a> Renderer<'a> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
config: Rc<Config>,
|
config: Arc<RwLock<Config>>,
|
||||||
font_context: &'a Sdl2TtfContext,
|
font_context: &'a Sdl2TtfContext,
|
||||||
texture_creator: &'a TextureCreator<WindowContext>,
|
texture_creator: &'a TextureCreator<WindowContext>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -31,7 +32,7 @@ impl<'a> Renderer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config(&self) -> &Rc<Config> {
|
pub fn config(&self) -> &Arc<RwLock<Config>> {
|
||||||
&self.config
|
&self.config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ use sdl2::rect::{Point, Rect};
|
|||||||
use sdl2::render::Texture;
|
use sdl2::render::Texture;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum CaretState {
|
pub enum CaretState {
|
||||||
@ -126,9 +127,10 @@ pub struct Caret {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Caret {
|
impl Caret {
|
||||||
pub fn new(config: Rc<Config>) -> Self {
|
pub fn new(config: Arc<RwLock<Config>>) -> Self {
|
||||||
let bright = config.theme().caret().bright().color().into();
|
let read_config = config.read().unwrap();
|
||||||
let blur = config.theme().caret().blur().color().into();
|
let bright = read_config.theme().caret().bright().color().into();
|
||||||
|
let blur = read_config.theme().caret().blur().color().into();
|
||||||
Self {
|
Self {
|
||||||
state: CaretState::Bright,
|
state: CaretState::Bright,
|
||||||
blink_delay: 0,
|
blink_delay: 0,
|
||||||
|
@ -15,26 +15,34 @@ pub struct EditorFile {
|
|||||||
sections: Vec<EditorFileSection>,
|
sections: Vec<EditorFileSection>,
|
||||||
render_position: Rect,
|
render_position: Rect,
|
||||||
buffer: String,
|
buffer: String,
|
||||||
config: Rc<Config>,
|
config: Arc<RwLock<Config>>,
|
||||||
line_height: u32,
|
line_height: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditorFile {
|
impl EditorFile {
|
||||||
pub fn new(path: String, buffer: String, config: Rc<Config>) -> Self {
|
pub fn new(path: String, buffer: String, config: Arc<RwLock<Config>>) -> Self {
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
let ext = Path::new(&path)
|
let ext = Path::new(&path)
|
||||||
.extension()
|
.extension()
|
||||||
.and_then(|p| p.to_str())
|
.and_then(|p| p.to_str())
|
||||||
.map_or("txt", |s| s)
|
.map_or("txt", |s| s)
|
||||||
.to_string();
|
.to_string();
|
||||||
let sections = vec![EditorFileSection::new(buffer.clone(), ext, config.clone())];
|
let sections = vec![EditorFileSection::new(
|
||||||
let x = config.editor_left_margin();
|
buffer.clone(),
|
||||||
let y = config.editor_top_margin();
|
ext,
|
||||||
|
Arc::clone(&config),
|
||||||
|
)];
|
||||||
|
let render_position = {
|
||||||
|
let c = config.read().unwrap();
|
||||||
|
let x = c.editor_left_margin();
|
||||||
|
let y = c.editor_top_margin();
|
||||||
|
Rect::new(x, y, 0, 0)
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
path,
|
path,
|
||||||
sections,
|
sections,
|
||||||
render_position: Rect::new(x, y, 0, 0),
|
render_position,
|
||||||
buffer,
|
buffer,
|
||||||
config,
|
config,
|
||||||
line_height: 0,
|
line_height: 0,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::*;
|
||||||
|
|
||||||
use crate::app::{UpdateResult as UR, WindowCanvas as WC};
|
use crate::app::{UpdateResult as UR, WindowCanvas as WC};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
@ -14,18 +15,21 @@ use crate::ui::*;
|
|||||||
pub struct EditorFileSection {
|
pub struct EditorFileSection {
|
||||||
tokens: Vec<EditorFileToken>,
|
tokens: Vec<EditorFileToken>,
|
||||||
language: Language,
|
language: Language,
|
||||||
config: Rc<Config>,
|
config: Arc<RwLock<Config>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditorFileSection {
|
impl EditorFileSection {
|
||||||
pub fn new(buffer: String, ext: String, config: Rc<Config>) -> Self {
|
pub fn new(buffer: String, ext: String, config: Arc<RwLock<Config>>) -> Self {
|
||||||
use crate::lexer;
|
use crate::lexer;
|
||||||
|
|
||||||
let language = config
|
let language = config
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
.extensions_mapping()
|
.extensions_mapping()
|
||||||
.get(ext.as_str())
|
.get(ext.as_str())
|
||||||
.unwrap_or(&Language::PlainText);
|
.unwrap_or(&Language::PlainText)
|
||||||
let lexer_tokens = lexer::parse(buffer.clone(), language);
|
.clone();
|
||||||
|
let lexer_tokens = lexer::parse(buffer.clone(), &language);
|
||||||
|
|
||||||
let mut tokens: Vec<EditorFileToken> = vec![];
|
let mut tokens: Vec<EditorFileToken> = vec![];
|
||||||
let mut iterator = lexer_tokens.iter().peekable();
|
let mut iterator = lexer_tokens.iter().peekable();
|
||||||
|
@ -9,20 +9,22 @@ use sdl2::rect::{Point, Rect};
|
|||||||
use sdl2::render::Texture;
|
use sdl2::render::Texture;
|
||||||
use sdl2::ttf::Font;
|
use sdl2::ttf::Font;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::*;
|
||||||
|
|
||||||
impl TokenType {
|
impl TokenType {
|
||||||
pub fn to_color(&self, config: &Rc<Config>) -> Color {
|
pub fn to_color(&self, config: &Arc<RwLock<Config>>) -> Color {
|
||||||
let config = config.theme().code_highlighting();
|
let config = config.read().unwrap();
|
||||||
|
let ch = config.theme().code_highlighting();
|
||||||
match self {
|
match self {
|
||||||
&TokenType::Whitespace { .. } => config.whitespace().color().into(),
|
&TokenType::Whitespace { .. } => ch.whitespace().color().into(),
|
||||||
&TokenType::Keyword { .. } => config.keyword().color().into(),
|
&TokenType::Keyword { .. } => ch.keyword().color().into(),
|
||||||
&TokenType::String { .. } => config.string().color().into(),
|
&TokenType::String { .. } => ch.string().color().into(),
|
||||||
&TokenType::Number { .. } => config.number().color().into(),
|
&TokenType::Number { .. } => ch.number().color().into(),
|
||||||
&TokenType::Identifier { .. } => config.identifier().color().into(),
|
&TokenType::Identifier { .. } => ch.identifier().color().into(),
|
||||||
&TokenType::Literal { .. } => config.literal().color().into(),
|
&TokenType::Literal { .. } => ch.literal().color().into(),
|
||||||
&TokenType::Comment { .. } => config.comment().color().into(),
|
&TokenType::Comment { .. } => ch.comment().color().into(),
|
||||||
&TokenType::Operator { .. } => config.operator().color().into(),
|
&TokenType::Operator { .. } => ch.operator().color().into(),
|
||||||
&TokenType::Separator { .. } => config.separator().color().into(),
|
&TokenType::Separator { .. } => ch.separator().color().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -32,11 +34,11 @@ pub struct EditorFileToken {
|
|||||||
last_in_line: bool,
|
last_in_line: bool,
|
||||||
characters: Vec<TextCharacter>,
|
characters: Vec<TextCharacter>,
|
||||||
token_type: Rc<TokenType>,
|
token_type: Rc<TokenType>,
|
||||||
config: Rc<Config>,
|
config: Arc<RwLock<Config>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditorFileToken {
|
impl EditorFileToken {
|
||||||
pub fn new(token_type: &TokenType, last_in_line: bool, config: Rc<Config>) -> Self {
|
pub fn new(token_type: &TokenType, last_in_line: bool, config: Arc<RwLock<Config>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
last_in_line,
|
last_in_line,
|
||||||
characters: vec![],
|
characters: vec![],
|
||||||
|
@ -2,6 +2,7 @@ use sdl2::rect::*;
|
|||||||
use std::borrow::*;
|
use std::borrow::*;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::*;
|
||||||
|
|
||||||
use crate::app::*;
|
use crate::app::*;
|
||||||
use crate::app::{UpdateResult as UR, WindowCanvas as WS};
|
use crate::app::{UpdateResult as UR, WindowCanvas as WS};
|
||||||
@ -12,21 +13,30 @@ pub struct FileEditor {
|
|||||||
scroll: Point,
|
scroll: Point,
|
||||||
caret: Caret,
|
caret: Caret,
|
||||||
file: Option<EditorFile>,
|
file: Option<EditorFile>,
|
||||||
config: Rc<Config>,
|
config: Arc<RwLock<Config>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileEditor {
|
impl FileEditor {
|
||||||
pub fn new(dest: Rect, config: Rc<Config>) -> Self {
|
pub fn new(config: Arc<RwLock<Config>>) -> Self {
|
||||||
|
let dest = {
|
||||||
|
let c = config.read().unwrap();
|
||||||
|
Rect::new(
|
||||||
|
c.editor_left_margin(),
|
||||||
|
c.editor_top_margin(),
|
||||||
|
c.width() - c.editor_left_margin() as u32,
|
||||||
|
c.height() - c.editor_top_margin() as u32,
|
||||||
|
)
|
||||||
|
};
|
||||||
Self {
|
Self {
|
||||||
dest,
|
dest,
|
||||||
scroll: Point::new(0, 0),
|
scroll: Point::new(0, 0),
|
||||||
caret: Caret::new(config.clone()),
|
caret: Caret::new(Arc::clone(&config)),
|
||||||
file: None,
|
file: None,
|
||||||
config,
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config(&self) -> &Rc<Config> {
|
pub fn config(&self) -> &Arc<RwLock<Config>> {
|
||||||
&self.config
|
&self.config
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,10 +106,11 @@ impl FileEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn scroll_to(&mut self, x: i32, y: i32) {
|
pub fn scroll_to(&mut self, x: i32, y: i32) {
|
||||||
|
let read_config = self.config.read().unwrap();
|
||||||
self.scroll = self.scroll
|
self.scroll = self.scroll
|
||||||
+ Point::new(
|
+ Point::new(
|
||||||
self.config.scroll_speed() * x,
|
read_config.scroll_speed() * x,
|
||||||
self.config.scroll_speed() * y,
|
read_config.scroll_speed() * y,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +167,7 @@ impl FileEditor {
|
|||||||
|
|
||||||
impl Render for FileEditor {
|
impl Render for FileEditor {
|
||||||
fn render(&self, canvas: &mut WS, renderer: &mut Renderer, _parent: Parent) -> UR {
|
fn render(&self, canvas: &mut WS, renderer: &mut Renderer, _parent: Parent) -> UR {
|
||||||
|
canvas.set_clip_rect(self.dest.clone());
|
||||||
match self.file() {
|
match self.file() {
|
||||||
Some(file) => file.render(canvas, renderer, Some(self)),
|
Some(file) => file.render(canvas, renderer, Some(self)),
|
||||||
_ => UR::NoOp,
|
_ => UR::NoOp,
|
||||||
@ -170,6 +182,13 @@ impl Render for FileEditor {
|
|||||||
|
|
||||||
impl Update for FileEditor {
|
impl Update for FileEditor {
|
||||||
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR {
|
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR {
|
||||||
|
{
|
||||||
|
let config = self.config.read().unwrap();
|
||||||
|
self.dest
|
||||||
|
.set_width(config.width() - config.editor_left_margin() as u32);
|
||||||
|
self.dest
|
||||||
|
.set_height(config.height() - config.editor_top_margin() as u32);
|
||||||
|
}
|
||||||
self.caret.update(ticks, context);
|
self.caret.update(ticks, context);
|
||||||
match self.file_mut() {
|
match self.file_mut() {
|
||||||
Some(file) => file.update(ticks, context),
|
Some(file) => file.update(ticks, context),
|
||||||
@ -220,11 +239,12 @@ mod tests {
|
|||||||
use sdl2::*;
|
use sdl2::*;
|
||||||
use std::borrow::*;
|
use std::borrow::*;
|
||||||
use std::rc::*;
|
use std::rc::*;
|
||||||
|
use std::sync::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn replace_file() {
|
fn replace_file() {
|
||||||
let config = Rc::new(Config::new());
|
let config = Arc::new(RwLock::new(Config::new()));
|
||||||
let mut editor = FileEditor::new(Rect::new(0, 0, 100, 100), config.clone());
|
let mut editor = FileEditor::new(Arc::clone(&config));
|
||||||
let first_file =
|
let first_file =
|
||||||
EditorFile::new("./foo.txt".to_string(), "foo".to_string(), config.clone());
|
EditorFile::new("./foo.txt".to_string(), "foo".to_string(), config.clone());
|
||||||
let second_file =
|
let second_file =
|
||||||
@ -239,7 +259,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn add_text() {
|
fn add_text() {
|
||||||
let config = Rc::new(Config::new());
|
let config = Arc::new(RwLock::new(Config::new()));
|
||||||
let sdl_context = sdl2::init().unwrap();
|
let sdl_context = sdl2::init().unwrap();
|
||||||
let video_subsystem = sdl_context.video().unwrap();
|
let video_subsystem = sdl_context.video().unwrap();
|
||||||
let window = video_subsystem
|
let window = video_subsystem
|
||||||
@ -253,7 +273,7 @@ mod tests {
|
|||||||
let texture_creator = canvas.texture_creator();
|
let texture_creator = canvas.texture_creator();
|
||||||
let mut renderer = Renderer::new(config.clone(), &font_context, &texture_creator);
|
let mut renderer = Renderer::new(config.clone(), &font_context, &texture_creator);
|
||||||
|
|
||||||
let mut editor = FileEditor::new(Rect::new(0, 0, 100, 100), config.clone());
|
let mut editor = FileEditor::new(Arc::clone(&config));
|
||||||
let mut file = EditorFile::new("./foo.txt".to_string(), "foo".to_string(), config.clone());
|
let mut file = EditorFile::new("./foo.txt".to_string(), "foo".to_string(), config.clone());
|
||||||
file.prepare_ui(&mut renderer);
|
file.prepare_ui(&mut renderer);
|
||||||
assert_eq!(editor.open_file(file).is_none(), true);
|
assert_eq!(editor.open_file(file).is_none(), true);
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
use crate::app::{UpdateResult, WindowCanvas};
|
use crate::app::{UpdateResult as UR, WindowCanvas as WC};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::renderer::Renderer;
|
use crate::renderer::Renderer;
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
use sdl2::pixels::Color;
|
use sdl2::pixels::Color;
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::*;
|
||||||
|
|
||||||
pub struct MenuBar {
|
pub struct MenuBar {
|
||||||
border_color: Color,
|
border_color: Color,
|
||||||
background_color: Color,
|
background_color: Color,
|
||||||
dest: Rect,
|
dest: Rect,
|
||||||
config: Rc<Config>,
|
config: Arc<RwLock<Config>>,
|
||||||
pending: bool,
|
pending: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MenuBar {
|
impl MenuBar {
|
||||||
pub fn new(config: Rc<Config>) -> Self {
|
pub fn new(config: Arc<RwLock<Config>>) -> Self {
|
||||||
|
let background_color = { config.read().unwrap().theme().background().into() };
|
||||||
Self {
|
Self {
|
||||||
border_color: Color::RGB(10, 10, 10),
|
border_color: Color::RGB(10, 10, 10),
|
||||||
background_color: config.theme().background().into(),
|
background_color,
|
||||||
dest: Rect::new(0, 0, 0, 0),
|
dest: Rect::new(0, 0, 0, 0),
|
||||||
config,
|
config,
|
||||||
pending: true,
|
pending: true,
|
||||||
@ -35,12 +37,8 @@ impl MenuBar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Render for MenuBar {
|
impl Render for MenuBar {
|
||||||
fn render(
|
fn render(&self, canvas: &mut WC, _renderer: &mut Renderer, parent: Parent) -> UR {
|
||||||
&self,
|
canvas.set_clip_rect(self.dest.clone());
|
||||||
canvas: &mut WindowCanvas,
|
|
||||||
_renderer: &mut Renderer,
|
|
||||||
parent: Parent,
|
|
||||||
) -> UpdateResult {
|
|
||||||
canvas.set_draw_color(self.background_color.clone());
|
canvas.set_draw_color(self.background_color.clone());
|
||||||
canvas
|
canvas
|
||||||
.fill_rect(match parent {
|
.fill_rect(match parent {
|
||||||
@ -57,28 +55,30 @@ impl Render for MenuBar {
|
|||||||
})
|
})
|
||||||
.unwrap_or_else(|_| panic!("Failed to draw main menu background"));
|
.unwrap_or_else(|_| panic!("Failed to draw main menu background"));
|
||||||
|
|
||||||
UpdateResult::NoOp
|
UR::NoOp
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_ui(&mut self, _renderer: &mut Renderer) {
|
fn prepare_ui(&mut self, _renderer: &mut Renderer) {
|
||||||
if !self.pending {
|
if !self.pending {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let width = self.config.width();
|
let width = self.config.read().unwrap().width();
|
||||||
let height = self.config.menu_height() as u32;
|
let height = self.config.read().unwrap().menu_height() as u32;
|
||||||
self.dest = Rect::new(0, 0, width, height);
|
self.dest = Rect::new(0, 0, width, height);
|
||||||
self.pending = false;
|
self.pending = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Update for MenuBar {
|
impl Update for MenuBar {
|
||||||
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UpdateResult {
|
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR {
|
||||||
UpdateResult::NoOp
|
let config = self.config.read().unwrap();
|
||||||
|
self.dest.set_width(config.width());
|
||||||
|
UR::NoOp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClickHandler for MenuBar {
|
impl ClickHandler for MenuBar {
|
||||||
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UpdateResult {
|
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UR {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +39,22 @@ pub fn is_in_rect(point: &Point, rect: &Rect) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_text_character_rect(c: char, renderer: &mut Renderer) -> Option<Rect> {
|
pub fn get_text_character_rect(c: char, renderer: &mut Renderer) -> Option<Rect> {
|
||||||
let config = renderer.config().editor_config();
|
let font_details = FontDetails::new(
|
||||||
let font_details =
|
renderer
|
||||||
FontDetails::new(config.font_path().as_str(), config.character_size().clone());
|
.config()
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.editor_config()
|
||||||
|
.font_path()
|
||||||
|
.as_str(),
|
||||||
|
renderer
|
||||||
|
.config()
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.editor_config()
|
||||||
|
.character_size()
|
||||||
|
.clone(),
|
||||||
|
);
|
||||||
let font = renderer
|
let font = renderer
|
||||||
.font_manager()
|
.font_manager()
|
||||||
.load(&font_details)
|
.load(&font_details)
|
||||||
|
@ -11,6 +11,7 @@ use sdl2::rect::{Point, Rect};
|
|||||||
use sdl2::render::Texture;
|
use sdl2::render::Texture;
|
||||||
use sdl2::ttf::Font;
|
use sdl2::ttf::Font;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct TextCharacter {
|
pub struct TextCharacter {
|
||||||
@ -21,7 +22,7 @@ pub struct TextCharacter {
|
|||||||
source: Rect,
|
source: Rect,
|
||||||
dest: Rect,
|
dest: Rect,
|
||||||
color: Color,
|
color: Color,
|
||||||
config: Rc<Config>,
|
config: Arc<RwLock<Config>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextCharacter {
|
impl TextCharacter {
|
||||||
@ -31,7 +32,7 @@ impl TextCharacter {
|
|||||||
line: usize,
|
line: usize,
|
||||||
last_in_line: bool,
|
last_in_line: bool,
|
||||||
color: Color,
|
color: Color,
|
||||||
config: Rc<Config>,
|
config: Arc<RwLock<Config>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
text_character,
|
text_character,
|
||||||
@ -105,9 +106,11 @@ impl Render for TextCharacter {
|
|||||||
return UR::NoOp;
|
return UR::NoOp;
|
||||||
}
|
}
|
||||||
|
|
||||||
let config = renderer.config().editor_config();
|
let font_details = {
|
||||||
let font_details =
|
let config = renderer.config().read().unwrap();
|
||||||
FontDetails::new(config.font_path().as_str(), config.character_size().clone());
|
let ec = config.editor_config();
|
||||||
|
FontDetails::new(ec.font_path().as_str(), ec.character_size().clone())
|
||||||
|
};
|
||||||
let font = renderer
|
let font = renderer
|
||||||
.font_manager()
|
.font_manager()
|
||||||
.load(&font_details)
|
.load(&font_details)
|
||||||
@ -133,9 +136,11 @@ impl Render for TextCharacter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_ui(&mut self, renderer: &mut Renderer) {
|
fn prepare_ui(&mut self, renderer: &mut Renderer) {
|
||||||
let config = renderer.config().editor_config();
|
let font_details = {
|
||||||
let font_details =
|
let config = renderer.config().read().unwrap();
|
||||||
FontDetails::new(config.font_path().as_str(), config.character_size().clone());
|
let ec = config.editor_config();
|
||||||
|
FontDetails::new(ec.font_path().as_str(), ec.character_size().clone())
|
||||||
|
};
|
||||||
let font = renderer
|
let font = renderer
|
||||||
.font_manager()
|
.font_manager()
|
||||||
.load(&font_details)
|
.load(&font_details)
|
||||||
|
Loading…
Reference in New Issue
Block a user