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:
Adrian Woźniak 2019-01-06 21:15:31 +01:00 committed by GitHub
parent 7e2218bf82
commit 0cf8629868
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 177 additions and 97 deletions

View File

@ -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

View File

@ -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
} }

View File

@ -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();
video_subsystem
.window("Rider", c.width(), c.height())
.position_centered() .position_centered()
.resizable() .resizable()
.opengl() .opengl()
.build() .build()
.unwrap(); .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
} }
} }

View File

@ -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);

View 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
} }

View File

@ -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
} }

View File

@ -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,

View File

@ -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,

View File

@ -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();

View File

@ -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![],

View File

@ -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);

View File

@ -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!()
} }

View File

@ -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)

View File

@ -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)