diff --git a/rider-config/src/config.rs b/rider-config/src/config.rs index ba417e9..017873f 100644 --- a/rider-config/src/config.rs +++ b/rider-config/src/config.rs @@ -32,7 +32,7 @@ impl Config { Self { width: 1024, height: 860, - menu_height: 60, + menu_height: 40, theme: Theme::default(), editor_config, extensions_mapping, diff --git a/rider-editor/src/app/application.rs b/rider-editor/src/app/application.rs index 0275850..d2a2d6b 100644 --- a/rider-editor/src/app/application.rs +++ b/rider-editor/src/app/application.rs @@ -151,11 +151,9 @@ impl Application { UpdateResult::DeleteBack => { app_state.file_editor_mut().delete_back(&mut renderer); } - UpdateResult::Input(text) => { - app_state - .file_editor_mut() - .insert_text(text.clone(), &mut renderer); - } + UpdateResult::Input(text) => app_state + .file_editor_mut() + .insert_text(text.clone(), &mut renderer), UpdateResult::InsertNewLine => { app_state.file_editor_mut().insert_new_line(&mut renderer); } @@ -174,20 +172,18 @@ impl Application { UpdateResult::Scroll { x, y } => { app_state.scroll_by(-x.clone(), -y.clone()); } - UpdateResult::WindowResize { width, height } => { - app_state - .config() - .write() - .map(|ref mut c| { - if *width > 0 { - c.set_width(*width as u32); - } - if *height > 0 { - c.set_height(*height as u32); - } - }) - .unwrap_or_else(|_| println!("Failed to update window size")); - } + UpdateResult::WindowResize { width, height } => app_state + .config() + .write() + .map(|ref mut c| { + if *width > 0 { + c.set_width(*width as u32); + } + if *height > 0 { + c.set_height(*height as u32); + } + }) + .unwrap_or_else(|_| println!("Failed to update window size")), UpdateResult::RefreshFsTree => unimplemented!(), UpdateResult::OpenFile(file_path) => { app_state.open_file(file_path.clone(), &mut renderer); @@ -206,11 +202,9 @@ impl Application { UpdateResult::MouseDragStart(_point) => (), UpdateResult::MouseDragStop(_point) => (), UpdateResult::FileDropped(_path) => (), - UpdateResult::SaveCurrentFile => { - app_state - .save_file() - .unwrap_or_else(|e| eprintln!("Failed to save {:?}", e)); - } + UpdateResult::SaveCurrentFile => app_state + .save_file() + .unwrap_or_else(|e| eprintln!("Failed to save {:?}", e)), } } self.tasks = new_tasks; diff --git a/rider-editor/src/ui/menu_bar.rs b/rider-editor/src/ui/menu_bar.rs index d1c9e80..36376ec 100644 --- a/rider-editor/src/ui/menu_bar.rs +++ b/rider-editor/src/ui/menu_bar.rs @@ -6,7 +6,7 @@ use sdl2::pixels::Color; use sdl2::rect::{Point, Rect}; const SAVE_BUTTON_OFFSET_LEFT: i32 = 16; -const SAVE_BUTTON_OFFSET_TOP: i32 = 16; +const SAVE_BUTTON_OFFSET_TOP: i32 = 10; pub struct MenuBar { border_color: Color, @@ -14,6 +14,7 @@ pub struct MenuBar { dest: Rect, config: ConfigAccess, save_button: SaveButton, + settings_button: SettingsButton, } impl MenuBar { @@ -32,6 +33,7 @@ impl MenuBar { background_color, dest: Rect::new(0, 0, w as u32, h as u32), save_button: SaveButton::new(config.clone()), + settings_button: SettingsButton::new(config.clone()), config, } } @@ -75,6 +77,11 @@ impl MenuBar { relative_position.offset(SAVE_BUTTON_OFFSET_LEFT, SAVE_BUTTON_OFFSET_TOP), ); 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) { @@ -85,9 +92,12 @@ impl MenuBar { } impl Update for MenuBar { - fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR { - let config = self.config.read().unwrap(); - self.dest.set_width(config.width()); + fn update(&mut self, ticks: i32, context: &UpdateContext) -> UR { + if let Ok(config) = self.config.read() { + self.dest.set_width(config.width()); + self.save_button.update(ticks, context); + self.settings_button.update(ticks, context); + } UR::NoOp } } @@ -106,15 +116,21 @@ impl ClickHandler for MenuBar { if self.save_button.is_left_click_target(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 } 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), - _ => self.dest(), - }; - rect.contains_point(point.clone()) + _ => self.dest, + } + .contains_point(point.clone()) } } diff --git a/rider-editor/src/ui/mod.rs b/rider-editor/src/ui/mod.rs index 1993988..92c5964 100644 --- a/rider-editor/src/ui/mod.rs +++ b/rider-editor/src/ui/mod.rs @@ -17,6 +17,7 @@ pub mod modal; pub mod project_tree; pub mod save_button; pub mod scroll_bar; +pub mod settings_button; pub mod text_character; pub use crate::ui::caret::*; @@ -28,6 +29,7 @@ pub use crate::ui::modal::*; pub use crate::ui::project_tree::*; pub use crate::ui::save_button::*; pub use crate::ui::scroll_bar::*; +pub use crate::ui::settings_button::*; pub use crate::ui::text_character::*; #[derive(Debug)] diff --git a/rider-editor/src/ui/save_button.rs b/rider-editor/src/ui/save_button.rs index 2834fd4..e4079c6 100644 --- a/rider-editor/src/ui/save_button.rs +++ b/rider-editor/src/ui/save_button.rs @@ -5,10 +5,10 @@ use crate::ui::{ }; use sdl2::rect::{Point, Rect}; -const ICON_DEST_WIDTH: u32 = 32; -const ICON_DEST_HEIGHT: u32 = 32; -const ICON_SRC_WIDTH: u32 = 64; -const ICON_SRC_HEIGHT: u32 = 64; +const ICON_DEST_WIDTH: u32 = 16; +const ICON_DEST_HEIGHT: u32 = 16; +const ICON_SRC_WIDTH: u32 = 32; +const ICON_SRC_HEIGHT: u32 = 32; pub struct SaveButton { source: Rect, @@ -36,7 +36,10 @@ impl SaveButton { _ => 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 c = self.config.read().unwrap(); let mut themes_dir = c.directories().themes_dir.clone(); diff --git a/rider-editor/src/ui/settings_button.rs b/rider-editor/src/ui/settings_button.rs new file mode 100644 index 0000000..c230ca3 --- /dev/null +++ b/rider-editor/src/ui/settings_button.rs @@ -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(&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 + } +} diff --git a/rider-generator/assets/themes/default/images/directory-48x48.png b/rider-generator/assets/themes/default/images/directory-48x48.png index d1d5462..d4c959d 100644 Binary files a/rider-generator/assets/themes/default/images/directory-48x48.png and b/rider-generator/assets/themes/default/images/directory-48x48.png differ diff --git a/rider-generator/assets/themes/default/images/directory-64x64.png b/rider-generator/assets/themes/default/images/directory-64x64.png index e18109b..d6ee7c3 100644 Binary files a/rider-generator/assets/themes/default/images/directory-64x64.png and b/rider-generator/assets/themes/default/images/directory-64x64.png differ diff --git a/rider-generator/assets/themes/default/images/file-48x48.png b/rider-generator/assets/themes/default/images/file-48x48.png index 7e0d8a5..721382a 100644 Binary files a/rider-generator/assets/themes/default/images/file-48x48.png and b/rider-generator/assets/themes/default/images/file-48x48.png differ diff --git a/rider-generator/assets/themes/default/images/file-64x64.png b/rider-generator/assets/themes/default/images/file-64x64.png index 63a2ea5..34030e8 100644 Binary files a/rider-generator/assets/themes/default/images/file-64x64.png and b/rider-generator/assets/themes/default/images/file-64x64.png differ diff --git a/rider-generator/assets/themes/default/images/save-32x32.png b/rider-generator/assets/themes/default/images/save-32x32.png new file mode 100644 index 0000000..4a3b76e Binary files /dev/null and b/rider-generator/assets/themes/default/images/save-32x32.png differ diff --git a/rider-generator/assets/themes/default/images/save-64x64.png b/rider-generator/assets/themes/default/images/save-64x64.png index 55fa15e..a4f1215 100644 Binary files a/rider-generator/assets/themes/default/images/save-64x64.png and b/rider-generator/assets/themes/default/images/save-64x64.png differ diff --git a/rider-generator/assets/themes/railscasts/images/save-32x32.png b/rider-generator/assets/themes/railscasts/images/save-32x32.png new file mode 100644 index 0000000..4a3b76e Binary files /dev/null and b/rider-generator/assets/themes/railscasts/images/save-32x32.png differ diff --git a/rider-generator/assets/themes/railscasts/images/save-64x64.png b/rider-generator/assets/themes/railscasts/images/save-64x64.png index 55fa15e..a4f1215 100644 Binary files a/rider-generator/assets/themes/railscasts/images/save-64x64.png and b/rider-generator/assets/themes/railscasts/images/save-64x64.png differ diff --git a/rider-generator/assets/themes/railscasts/images/settings-16x16.png b/rider-generator/assets/themes/railscasts/images/settings-16x16.png new file mode 100644 index 0000000..c830a16 Binary files /dev/null and b/rider-generator/assets/themes/railscasts/images/settings-16x16.png differ diff --git a/rider-generator/src/images.rs b/rider-generator/src/images.rs index 3a7e6da..153f423 100644 --- a/rider-generator/src/images.rs +++ b/rider-generator/src/images.rs @@ -21,6 +21,18 @@ fn create_default_file_icon(dir: &PathBuf) -> std::io::Result<()> { 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<()> { let mut dir = PathBuf::new(); 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_file_icon(&dir)?; + create_default_save_icon(&dir)?; + create_default_settings_icon(&dir)?; 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<()> { - let blob = include_bytes!("../assets/themes/railscasts/images/save-64x64.png"); - write_bytes_to(dir, "save-64x64.png", blob)?; + let blob = include_bytes!("../assets/themes/railscasts/images/save-32x32.png"); + 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(()) } @@ -62,6 +82,7 @@ fn railscasts_theme(directories: &Directories) -> std::io::Result<()> { create_railscasts_directory_icon(&dir)?; create_railscasts_file_icon(&dir)?; create_railscasts_save_icon(&dir)?; + create_railscasts_settings_icon(&dir)?; Ok(()) } diff --git a/rider-themes/src/images.rs b/rider-themes/src/images.rs index 46148e7..c140014 100644 --- a/rider-themes/src/images.rs +++ b/rider-themes/src/images.rs @@ -3,14 +3,21 @@ pub struct ThemeImages { directory_icon: String, file_icon: String, save_icon: String, + settings_icon: String, } 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 { file_icon, directory_icon, save_icon, + settings_icon, } } @@ -25,6 +32,10 @@ impl ThemeImages { pub fn save_icon(&self) -> String { self.save_icon.clone() } + + pub fn settings_icon(&self) -> String { + self.settings_icon.clone() + } } impl Default for ThemeImages { @@ -32,7 +43,8 @@ impl Default for ThemeImages { Self { directory_icon: "default/images/directory-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] 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 expected = "foo".to_owned(); assert_eq!(result, expected); @@ -51,7 +68,12 @@ mod test { #[test] 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 expected = "bar".to_owned(); assert_eq!(result, expected); @@ -59,9 +81,27 @@ mod test { #[test] 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 expected = "baz".to_owned(); 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); + } } diff --git a/rider-themes/src/predef/railscasts.rs b/rider-themes/src/predef/railscasts.rs index 9959bb3..873d0ec 100644 --- a/rider-themes/src/predef/railscasts.rs +++ b/rider-themes/src/predef/railscasts.rs @@ -44,7 +44,8 @@ pub fn build_theme() -> Theme { ThemeImages::new( "railscasts/images/directory-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(), ), ) }