Add settings icon

This commit is contained in:
Adrian Woźniak 2019-05-31 20:49:38 +02:00
parent 02f271a5c1
commit bdf2c0c954
18 changed files with 232 additions and 46 deletions

View File

@ -32,7 +32,7 @@ impl Config {
Self { Self {
width: 1024, width: 1024,
height: 860, height: 860,
menu_height: 60, menu_height: 40,
theme: Theme::default(), theme: Theme::default(),
editor_config, editor_config,
extensions_mapping, extensions_mapping,

View File

@ -151,11 +151,9 @@ impl Application {
UpdateResult::DeleteBack => { UpdateResult::DeleteBack => {
app_state.file_editor_mut().delete_back(&mut renderer); app_state.file_editor_mut().delete_back(&mut renderer);
} }
UpdateResult::Input(text) => { UpdateResult::Input(text) => app_state
app_state .file_editor_mut()
.file_editor_mut() .insert_text(text.clone(), &mut renderer),
.insert_text(text.clone(), &mut renderer);
}
UpdateResult::InsertNewLine => { UpdateResult::InsertNewLine => {
app_state.file_editor_mut().insert_new_line(&mut renderer); app_state.file_editor_mut().insert_new_line(&mut renderer);
} }
@ -174,20 +172,18 @@ impl Application {
UpdateResult::Scroll { x, y } => { UpdateResult::Scroll { x, y } => {
app_state.scroll_by(-x.clone(), -y.clone()); app_state.scroll_by(-x.clone(), -y.clone());
} }
UpdateResult::WindowResize { width, height } => { UpdateResult::WindowResize { width, height } => app_state
app_state .config()
.config() .write()
.write() .map(|ref mut c| {
.map(|ref mut c| { if *width > 0 {
if *width > 0 { c.set_width(*width as u32);
c.set_width(*width as u32); }
} if *height > 0 {
if *height > 0 { c.set_height(*height as u32);
c.set_height(*height as u32); }
} })
}) .unwrap_or_else(|_| println!("Failed to update window size")),
.unwrap_or_else(|_| println!("Failed to update window size"));
}
UpdateResult::RefreshFsTree => unimplemented!(), UpdateResult::RefreshFsTree => unimplemented!(),
UpdateResult::OpenFile(file_path) => { UpdateResult::OpenFile(file_path) => {
app_state.open_file(file_path.clone(), &mut renderer); app_state.open_file(file_path.clone(), &mut renderer);
@ -206,11 +202,9 @@ impl Application {
UpdateResult::MouseDragStart(_point) => (), UpdateResult::MouseDragStart(_point) => (),
UpdateResult::MouseDragStop(_point) => (), UpdateResult::MouseDragStop(_point) => (),
UpdateResult::FileDropped(_path) => (), UpdateResult::FileDropped(_path) => (),
UpdateResult::SaveCurrentFile => { UpdateResult::SaveCurrentFile => app_state
app_state .save_file()
.save_file() .unwrap_or_else(|e| eprintln!("Failed to save {:?}", e)),
.unwrap_or_else(|e| eprintln!("Failed to save {:?}", e));
}
} }
} }
self.tasks = new_tasks; self.tasks = new_tasks;

View File

@ -6,7 +6,7 @@ use sdl2::pixels::Color;
use sdl2::rect::{Point, Rect}; use sdl2::rect::{Point, Rect};
const SAVE_BUTTON_OFFSET_LEFT: i32 = 16; const SAVE_BUTTON_OFFSET_LEFT: i32 = 16;
const SAVE_BUTTON_OFFSET_TOP: i32 = 16; const SAVE_BUTTON_OFFSET_TOP: i32 = 10;
pub struct MenuBar { pub struct MenuBar {
border_color: Color, border_color: Color,
@ -14,6 +14,7 @@ pub struct MenuBar {
dest: Rect, dest: Rect,
config: ConfigAccess, config: ConfigAccess,
save_button: SaveButton, save_button: SaveButton,
settings_button: SettingsButton,
} }
impl MenuBar { impl MenuBar {
@ -32,6 +33,7 @@ impl MenuBar {
background_color, background_color,
dest: Rect::new(0, 0, w as u32, h as u32), dest: Rect::new(0, 0, w as u32, h as u32),
save_button: SaveButton::new(config.clone()), save_button: SaveButton::new(config.clone()),
settings_button: SettingsButton::new(config.clone()),
config, config,
} }
} }
@ -75,6 +77,11 @@ impl MenuBar {
relative_position.offset(SAVE_BUTTON_OFFSET_LEFT, SAVE_BUTTON_OFFSET_TOP), relative_position.offset(SAVE_BUTTON_OFFSET_LEFT, SAVE_BUTTON_OFFSET_TOP),
); );
self.save_button.render(canvas, renderer, &context); self.save_button.render(canvas, renderer, &context);
let context = RenderContext::RelativePosition(
relative_position.offset(SAVE_BUTTON_OFFSET_LEFT * 2, SAVE_BUTTON_OFFSET_TOP),
);
self.settings_button.render(canvas, renderer, &context);
} }
pub fn prepare_ui(&mut self) { pub fn prepare_ui(&mut self) {
@ -85,9 +92,12 @@ impl MenuBar {
} }
impl Update for MenuBar { impl Update for MenuBar {
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR { fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR {
let config = self.config.read().unwrap(); if let Ok(config) = self.config.read() {
self.dest.set_width(config.width()); self.dest.set_width(config.width());
self.save_button.update(ticks, context);
self.settings_button.update(ticks, context);
}
UR::NoOp UR::NoOp
} }
} }
@ -106,15 +116,21 @@ impl ClickHandler for MenuBar {
if self.save_button.is_left_click_target(point, &context) { if self.save_button.is_left_click_target(point, &context) {
return self.save_button.on_left_click(point, &context); return self.save_button.on_left_click(point, &context);
} }
let context = UpdateContext::ParentPosition(
relative_position.offset(SAVE_BUTTON_OFFSET_LEFT * 2, SAVE_BUTTON_OFFSET_TOP),
);
if self.settings_button.is_left_click_target(point, &context) {
return self.settings_button.on_left_click(point, &context);
}
UR::NoOp UR::NoOp
} }
fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool { fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
let rect = match *context { match *context {
UpdateContext::ParentPosition(p) => move_render_point(p.clone(), &self.dest), UpdateContext::ParentPosition(p) => move_render_point(p.clone(), &self.dest),
_ => self.dest(), _ => self.dest,
}; }
rect.contains_point(point.clone()) .contains_point(point.clone())
} }
} }

View File

@ -17,6 +17,7 @@ pub mod modal;
pub mod project_tree; pub mod project_tree;
pub mod save_button; pub mod save_button;
pub mod scroll_bar; pub mod scroll_bar;
pub mod settings_button;
pub mod text_character; pub mod text_character;
pub use crate::ui::caret::*; pub use crate::ui::caret::*;
@ -28,6 +29,7 @@ pub use crate::ui::modal::*;
pub use crate::ui::project_tree::*; pub use crate::ui::project_tree::*;
pub use crate::ui::save_button::*; pub use crate::ui::save_button::*;
pub use crate::ui::scroll_bar::*; pub use crate::ui::scroll_bar::*;
pub use crate::ui::settings_button::*;
pub use crate::ui::text_character::*; pub use crate::ui::text_character::*;
#[derive(Debug)] #[derive(Debug)]

View File

@ -5,10 +5,10 @@ use crate::ui::{
}; };
use sdl2::rect::{Point, Rect}; use sdl2::rect::{Point, Rect};
const ICON_DEST_WIDTH: u32 = 32; const ICON_DEST_WIDTH: u32 = 16;
const ICON_DEST_HEIGHT: u32 = 32; const ICON_DEST_HEIGHT: u32 = 16;
const ICON_SRC_WIDTH: u32 = 64; const ICON_SRC_WIDTH: u32 = 32;
const ICON_SRC_HEIGHT: u32 = 64; const ICON_SRC_HEIGHT: u32 = 32;
pub struct SaveButton { pub struct SaveButton {
source: Rect, source: Rect,
@ -36,7 +36,10 @@ impl SaveButton {
_ => self.dest.clone(), _ => self.dest.clone(),
}; };
canvas.set_clipping(dest.clone()); let mut clipping = dest.clone();
clipping.set_width(clipping.width() + ICON_DEST_WIDTH);
clipping.set_height(clipping.height() + ICON_DEST_HEIGHT);
canvas.set_clipping(clipping);
let save_texture_path = { let save_texture_path = {
let c = self.config.read().unwrap(); let c = self.config.read().unwrap();
let mut themes_dir = c.directories().themes_dir.clone(); let mut themes_dir = c.directories().themes_dir.clone();

View File

@ -0,0 +1,109 @@
use crate::app::{ConfigAccess, ConfigHolder, UpdateResult as UR};
use crate::renderer::Renderer;
use crate::ui::{
move_render_point, CanvasAccess, ClickHandler, RenderBox, RenderContext, Update, UpdateContext,
};
use sdl2::rect::{Point, Rect};
const ICON_DEST_WIDTH: u32 = 16;
const ICON_DEST_HEIGHT: u32 = 16;
const ICON_SRC_WIDTH: u32 = 16;
const ICON_SRC_HEIGHT: u32 = 16;
pub struct SettingsButton {
source: Rect,
dest: Rect,
config: ConfigAccess,
}
impl SettingsButton {
pub fn new(config: ConfigAccess) -> Self {
Self {
dest: Rect::new(0, 0, ICON_DEST_WIDTH, ICON_DEST_HEIGHT),
source: Rect::new(0, 0, ICON_SRC_WIDTH, ICON_SRC_HEIGHT),
config,
}
}
pub fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
where
C: CanvasAccess,
R: Renderer,
{
use std::borrow::*;
let mut dest = match context {
&RenderContext::RelativePosition(p) => move_render_point(p.clone(), &self.dest),
_ => self.dest.clone(),
};
let mut clipping = dest.clone();
clipping.set_width(clipping.width() + ICON_DEST_WIDTH);
clipping.set_height(clipping.height() + ICON_DEST_HEIGHT);
canvas.set_clipping(clipping);
let settings_texture_path = {
let c = self.config.read().unwrap();
let mut themes_dir = c.directories().themes_dir.clone();
let path = c.theme().images().settings_icon();
themes_dir.push(path);
themes_dir.to_str().unwrap().to_owned()
};
let maybe_tex = renderer.load_image(settings_texture_path.clone());
if let Ok(texture) = maybe_tex {
dest.set_width(ICON_DEST_WIDTH);
dest.set_height(ICON_DEST_HEIGHT);
canvas
.render_image(texture, self.source.clone(), dest.clone())
.unwrap_or_else(|_| panic!("Failed to draw directory entry texture"));
}
}
pub fn prepare_ui<'l, T>(&mut self, _renderer: &mut T)
where
T: ConfigHolder + Renderer,
{
}
pub fn source(&self) -> &Rect {
&self.source
}
pub fn set_dest(&mut self, rect: &Rect) {
self.dest = rect.clone();
}
pub fn set_source(&mut self, rect: &Rect) {
self.source = rect.clone();
}
}
impl Update for SettingsButton {
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR {
let config = self.config.read().unwrap();
self.dest.set_width(config.width());
UR::NoOp
}
}
impl ClickHandler for SettingsButton {
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UR {
UR::NoOp
}
fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
match *context {
UpdateContext::ParentPosition(p) => move_render_point(p.clone(), &self.dest),
_ => self.dest(),
}
.contains_point(point.clone())
}
}
impl RenderBox for SettingsButton {
fn render_start_point(&self) -> Point {
self.dest.top_left()
}
fn dest(&self) -> Rect {
self.dest
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 866 B

After

Width:  |  Height:  |  Size: 866 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 929 B

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 856 B

View File

@ -21,6 +21,18 @@ fn create_default_file_icon(dir: &PathBuf) -> std::io::Result<()> {
Ok(()) Ok(())
} }
fn create_default_save_icon(dir: &PathBuf) -> std::io::Result<()> {
let blob = include_bytes!("../assets/themes/default/images/save-32x32.png");
write_bytes_to(dir, "save-32x32.png", blob)?;
Ok(())
}
fn create_default_settings_icon(dir: &PathBuf) -> std::io::Result<()> {
let blob = include_bytes!("../assets/themes/default/images/settings-16x16.png");
write_bytes_to(dir, "settings-16x16.png", blob)?;
Ok(())
}
fn default_theme(directories: &Directories) -> std::io::Result<()> { fn default_theme(directories: &Directories) -> std::io::Result<()> {
let mut dir = PathBuf::new(); let mut dir = PathBuf::new();
dir.push(directories.themes_dir.clone()); dir.push(directories.themes_dir.clone());
@ -32,6 +44,8 @@ fn default_theme(directories: &Directories) -> std::io::Result<()> {
create_default_directory_icon(&dir)?; create_default_directory_icon(&dir)?;
create_default_file_icon(&dir)?; create_default_file_icon(&dir)?;
create_default_save_icon(&dir)?;
create_default_settings_icon(&dir)?;
Ok(()) Ok(())
} }
@ -48,8 +62,14 @@ fn create_railscasts_file_icon(dir: &PathBuf) -> std::io::Result<()> {
} }
fn create_railscasts_save_icon(dir: &PathBuf) -> std::io::Result<()> { fn create_railscasts_save_icon(dir: &PathBuf) -> std::io::Result<()> {
let blob = include_bytes!("../assets/themes/railscasts/images/save-64x64.png"); let blob = include_bytes!("../assets/themes/railscasts/images/save-32x32.png");
write_bytes_to(dir, "save-64x64.png", blob)?; write_bytes_to(dir, "save-32x32.png", blob)?;
Ok(())
}
fn create_railscasts_settings_icon(dir: &PathBuf) -> std::io::Result<()> {
let blob = include_bytes!("../assets/themes/railscasts/images/settings-16x16.png");
write_bytes_to(dir, "settings-16x16.png", blob)?;
Ok(()) Ok(())
} }
@ -62,6 +82,7 @@ fn railscasts_theme(directories: &Directories) -> std::io::Result<()> {
create_railscasts_directory_icon(&dir)?; create_railscasts_directory_icon(&dir)?;
create_railscasts_file_icon(&dir)?; create_railscasts_file_icon(&dir)?;
create_railscasts_save_icon(&dir)?; create_railscasts_save_icon(&dir)?;
create_railscasts_settings_icon(&dir)?;
Ok(()) Ok(())
} }

View File

@ -3,14 +3,21 @@ pub struct ThemeImages {
directory_icon: String, directory_icon: String,
file_icon: String, file_icon: String,
save_icon: String, save_icon: String,
settings_icon: String,
} }
impl ThemeImages { impl ThemeImages {
pub fn new(directory_icon: String, file_icon: String, save_icon: String) -> Self { pub fn new(
directory_icon: String,
file_icon: String,
save_icon: String,
settings_icon: String,
) -> Self {
Self { Self {
file_icon, file_icon,
directory_icon, directory_icon,
save_icon, save_icon,
settings_icon,
} }
} }
@ -25,6 +32,10 @@ impl ThemeImages {
pub fn save_icon(&self) -> String { pub fn save_icon(&self) -> String {
self.save_icon.clone() self.save_icon.clone()
} }
pub fn settings_icon(&self) -> String {
self.settings_icon.clone()
}
} }
impl Default for ThemeImages { impl Default for ThemeImages {
@ -32,7 +43,8 @@ impl Default for ThemeImages {
Self { Self {
directory_icon: "default/images/directory-64x64.png".to_string(), directory_icon: "default/images/directory-64x64.png".to_string(),
file_icon: "default/images/file-64x64.png".to_string(), file_icon: "default/images/file-64x64.png".to_string(),
save_icon: "default/images/save-64x64.png".to_string(), save_icon: "default/images/save-16x16.png".to_string(),
settings_icon: "default/images/settings-16x16.png".to_string(),
} }
} }
} }
@ -43,7 +55,12 @@ mod test {
#[test] #[test]
fn assert_directory_icon() { fn assert_directory_icon() {
let config = ThemeImages::new("foo".to_owned(), "bar".to_owned(), "baz".to_owned()); let config = ThemeImages::new(
"foo".to_owned(),
"bar".to_owned(),
"baz".to_owned(),
"foz".to_owned(),
);
let result = config.directory_icon(); let result = config.directory_icon();
let expected = "foo".to_owned(); let expected = "foo".to_owned();
assert_eq!(result, expected); assert_eq!(result, expected);
@ -51,7 +68,12 @@ mod test {
#[test] #[test]
fn assert_file_icon() { fn assert_file_icon() {
let config = ThemeImages::new("foo".to_owned(), "bar".to_owned(), "baz".to_owned()); let config = ThemeImages::new(
"foo".to_owned(),
"bar".to_owned(),
"baz".to_owned(),
"foz".to_owned(),
);
let result = config.file_icon(); let result = config.file_icon();
let expected = "bar".to_owned(); let expected = "bar".to_owned();
assert_eq!(result, expected); assert_eq!(result, expected);
@ -59,9 +81,27 @@ mod test {
#[test] #[test]
fn assert_save_icon() { fn assert_save_icon() {
let config = ThemeImages::new("foo".to_owned(), "bar".to_owned(), "baz".to_owned()); let config = ThemeImages::new(
"foo".to_owned(),
"bar".to_owned(),
"baz".to_owned(),
"foz".to_owned(),
);
let result = config.save_icon(); let result = config.save_icon();
let expected = "baz".to_owned(); let expected = "baz".to_owned();
assert_eq!(result, expected); assert_eq!(result, expected);
} }
#[test]
fn assert_settings_icon() {
let config = ThemeImages::new(
"foo".to_owned(),
"bar".to_owned(),
"baz".to_owned(),
"foz".to_owned(),
);
let result = config.settings_icon();
let expected = "foz".to_owned();
assert_eq!(result, expected);
}
} }

View File

@ -44,7 +44,8 @@ pub fn build_theme() -> Theme {
ThemeImages::new( ThemeImages::new(
"railscasts/images/directory-64x64.png".to_owned(), "railscasts/images/directory-64x64.png".to_owned(),
"railscasts/images/file-64x64.png".to_owned(), "railscasts/images/file-64x64.png".to_owned(),
"railscasts/images/save-64x64.png".to_owned(), "railscasts/images/save-32x32.png".to_owned(),
"railscasts/images/settings-16x16.png".to_owned(),
), ),
) )
} }