diff --git a/rider-editor/src/ui/file_editor/mod.rs b/rider-editor/src/ui/file_editor/mod.rs index 4ddc1dc..99784b2 100644 --- a/rider-editor/src/ui/file_editor/mod.rs +++ b/rider-editor/src/ui/file_editor/mod.rs @@ -7,10 +7,9 @@ use crate::ui::caret::MoveDirection; use crate::ui::file::editor_file::EditorFile; use crate::ui::file::TextCollection; use crate::ui::file::TextWidget; -use crate::ui::move_render_point; use crate::ui::scroll_bar::horizontal_scroll_bar::*; use crate::ui::scroll_bar::vertical_scroll_bar::*; -use crate::ui::scroll_bar::Scrollable; +use crate::ui::scroll_bar::Scroll; use crate::ui::text_character::CharacterSizeManager; use crate::ui::CanvasAccess; use crate::ui::ClickHandler; @@ -18,6 +17,7 @@ use crate::ui::RenderBox; use crate::ui::RenderContext; use crate::ui::Update; use crate::ui::UpdateContext; +use crate::ui::{move_render_point, ScrollView}; use sdl2::rect::Point; use sdl2::rect::Rect; use std::mem; @@ -47,12 +47,6 @@ pub trait CaretAccess { fn set_caret_to_end_of_line(&mut self, line: i32); } -pub trait ScrollableView { - fn scroll_by(&mut self, x: i32, y: i32); - - fn scroll(&self) -> Point; -} - pub struct FileEditor { dest: Rect, full_rect: Rect, @@ -144,34 +138,21 @@ impl FileEditor { } } -impl ScrollableView for FileEditor { - fn scroll_by(&mut self, x: i32, y: i32) { - let read_config = self.config.read().unwrap(); - - let value_x = read_config.scroll().speed() * x; - let value_y = read_config.scroll().speed() * y; - let old_x = self.horizontal_scroll_bar.scroll_value(); - let old_y = self.vertical_scroll_bar.scroll_value(); - - if value_x + old_x >= 0 { - self.horizontal_scroll_bar.scroll_to(value_x + old_x); - if self.horizontal_scroll_bar.scrolled_part() > 1.0 { - self.horizontal_scroll_bar.scroll_to(old_x); - } - } - if value_y + old_y >= 0 { - self.vertical_scroll_bar.scroll_to(value_y + old_y); - if self.vertical_scroll_bar.scrolled_part() > 1.0 { - self.vertical_scroll_bar.scroll_to(old_y); - } - } +impl ScrollView for FileEditor { + fn mut_horizontal_scroll_handler(&mut self) -> Option<&mut HorizontalScrollBar> { + Some(&mut self.horizontal_scroll_bar) } - fn scroll(&self) -> Point { - Point::new( - -self.horizontal_scroll_bar.scroll_value(), - -self.vertical_scroll_bar.scroll_value(), - ) + fn horizontal_scroll_handler(&self) -> Option<&HorizontalScrollBar> { + Some(&self.horizontal_scroll_bar) + } + + fn mut_vertical_scroll_handler(&mut self) -> Option<&mut VerticalScrollBar> { + Some(&mut self.vertical_scroll_bar) + } + + fn vertical_scroll_handler(&self) -> Option<&VerticalScrollBar> { + Some(&self.vertical_scroll_bar) } } diff --git a/rider-editor/src/ui/project_tree/mod.rs b/rider-editor/src/ui/project_tree/mod.rs index b0f0307..2352663 100644 --- a/rider-editor/src/ui/project_tree/mod.rs +++ b/rider-editor/src/ui/project_tree/mod.rs @@ -1,17 +1,16 @@ use crate::app::application::UpdateResult; use crate::renderer::renderer::Renderer; -use crate::ui::file_editor::ScrollableView; use crate::ui::filesystem::directory::DirectoryView; use crate::ui::horizontal_scroll_bar::HorizontalScrollBar; -use crate::ui::move_render_point; -use crate::ui::scroll_bar::Scrollable; use crate::ui::text_character::CharacterSizeManager; use crate::ui::vertical_scroll_bar::VerticalScrollBar; use crate::ui::CanvasAccess; use crate::ui::ClickHandler; use crate::ui::RenderContext; use crate::ui::UpdateContext; +use crate::ui::{move_render_point, ScrollView}; use rider_config::config::Config; +use rider_config::ConfigHolder; use sdl2::pixels::Color; use sdl2::rect::Point; use sdl2::rect::Rect; @@ -169,34 +168,27 @@ impl ClickHandler for ProjectTreeSidebar { } } -impl ScrollableView for ProjectTreeSidebar { - fn scroll_by(&mut self, x: i32, y: i32) { - let read_config = self.config.read().unwrap(); +impl ConfigHolder for ProjectTreeSidebar { + fn config(&self) -> &Arc> { + &self.config + } +} - let value_x = read_config.scroll().speed() * x; - let value_y = read_config.scroll().speed() * y; - let old_x = self.horizontal_scroll_bar.scroll_value(); - let old_y = self.vertical_scroll_bar.scroll_value(); - - if value_x + old_x >= 0 { - self.horizontal_scroll_bar.scroll_to(value_x + old_x); - if self.horizontal_scroll_bar.scrolled_part() > 1.0 { - self.horizontal_scroll_bar.scroll_to(old_x); - } - } - if value_y + old_y >= 0 { - self.vertical_scroll_bar.scroll_to(value_y + old_y); - if self.vertical_scroll_bar.scrolled_part() > 1.0 { - self.vertical_scroll_bar.scroll_to(old_y); - } - } +impl ScrollView for ProjectTreeSidebar { + fn mut_horizontal_scroll_handler(&mut self) -> Option<&mut HorizontalScrollBar> { + Some(&mut self.horizontal_scroll_bar) } - fn scroll(&self) -> Point { - Point::new( - -self.horizontal_scroll_bar.scroll_value(), - -self.vertical_scroll_bar.scroll_value(), - ) + fn horizontal_scroll_handler(&self) -> Option<&HorizontalScrollBar> { + Some(&self.horizontal_scroll_bar) + } + + fn mut_vertical_scroll_handler(&mut self) -> Option<&mut VerticalScrollBar> { + Some(&mut self.vertical_scroll_bar) + } + + fn vertical_scroll_handler(&self) -> Option<&VerticalScrollBar> { + Some(&self.vertical_scroll_bar) } } @@ -207,8 +199,8 @@ mod tests { use crate::renderer::renderer::Renderer; use crate::tests::support::build_config; use crate::tests::support::CanvasMock; - use crate::ui::file_editor::ScrollableView; use crate::ui::project_tree::ProjectTreeSidebar; + use crate::ui::scroll_bar::ScrollView; use crate::ui::text_character::CharacterSizeManager; use crate::ui::ClickHandler; use crate::ui::UpdateContext; diff --git a/rider-editor/src/ui/scroll_bar/horizontal_scroll_bar.rs b/rider-editor/src/ui/scroll_bar/horizontal_scroll_bar.rs index 9bdf7a0..cbd3fb7 100644 --- a/rider-editor/src/ui/scroll_bar/horizontal_scroll_bar.rs +++ b/rider-editor/src/ui/scroll_bar/horizontal_scroll_bar.rs @@ -2,51 +2,44 @@ use crate::app::UpdateResult as UR; use crate::ui::*; use rider_config::ConfigAccess; use sdl2::pixels::Color; -use sdl2::rect::Rect; +use std::ops::{Deref, DerefMut}; pub struct HorizontalScrollBar { - scroll_value: i32, - viewport: u32, - full_width: u32, - rect: Rect, + inner: ScrollBar, +} + +impl Deref for HorizontalScrollBar { + type Target = ScrollBar; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for HorizontalScrollBar { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } } impl HorizontalScrollBar { pub fn new(config: ConfigAccess) -> Self { - let width = { config.read().unwrap().scroll().width() }; Self { - scroll_value: 0, - viewport: 1, - full_width: 1, - rect: Rect::new(0, 0, width, 0), + inner: ScrollBar::new(config), } } - - #[inline] - pub fn viewport(&self) -> u32 { - self.viewport - } - - #[inline] - pub fn full_width(&self) -> u32 { - self.full_width - } - - #[inline] - pub fn rect(&self) -> &Rect { - &self.rect - } } impl Update for HorizontalScrollBar { fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR { - if self.full_width < self.viewport { + if self.full < self.viewport { return UR::NoOp; } - let ratio = self.full_width as f64 / self.viewport as f64; - self.rect.set_width((self.viewport as f64 / ratio) as u32); + let ratio = self.full as f64 / self.viewport as f64; + let width = (self.viewport as f64 / ratio) as u32; + self.rect.set_width(width); let x = (self.viewport - self.rect.width()) as f64 - * (self.scroll_value().abs() as f64 / (self.full_width - self.viewport) as f64); + * (self.scroll_value().abs() as f64 / (self.full - self.viewport) as f64); self.rect.set_x(x as i32); UR::NoOp @@ -59,7 +52,7 @@ impl HorizontalScrollBar { where T: CanvasAccess, { - if self.full_width < self.viewport { + if self.full < self.viewport { return; } @@ -75,7 +68,7 @@ impl HorizontalScrollBar { } } -impl Scrollable for HorizontalScrollBar { +impl Scroll for HorizontalScrollBar { fn scroll_to(&mut self, n: i32) { self.scroll_value = n; } @@ -89,7 +82,7 @@ impl Scrollable for HorizontalScrollBar { } fn set_full_size(&mut self, n: u32) { - self.full_width = n; + self.full = n; } fn set_location(&mut self, n: i32) { @@ -97,10 +90,10 @@ impl Scrollable for HorizontalScrollBar { } fn scrolled_part(&self) -> f64 { - if self.full_width() < self.viewport() { + if self.full < self.viewport() { return 1.0; } - self.scroll_value().abs() as f64 / (self.full_width() - self.viewport()) as f64 + self.scroll_value().abs() as f64 / (self.full - self.viewport()) as f64 } } @@ -184,9 +177,9 @@ mod test_scrollable { fn assert_set_full_size() { let config = support::build_config(); let mut widget = HorizontalScrollBar::new(Arc::clone(&config)); - let old = widget.full_width(); + let old = widget.full; widget.set_full_size(157); - let current = widget.full_width(); + let current = widget.full; let expected = 157; assert_ne!(old, current); assert_eq!(current, expected); diff --git a/rider-editor/src/ui/scroll_bar/mod.rs b/rider-editor/src/ui/scroll_bar/mod.rs index 7013b94..9f1800c 100644 --- a/rider-editor/src/ui/scroll_bar/mod.rs +++ b/rider-editor/src/ui/scroll_bar/mod.rs @@ -1,10 +1,76 @@ +use sdl2::rect::{Point, Rect}; + pub use crate::ui::scroll_bar::horizontal_scroll_bar::HorizontalScrollBar; pub use crate::ui::scroll_bar::vertical_scroll_bar::VerticalScrollBar; +use rider_config::{ConfigAccess, ConfigHolder}; pub mod horizontal_scroll_bar; pub mod vertical_scroll_bar; -pub trait Scrollable { +pub trait ScrollView: ConfigHolder +where + VS: Scroll, + HS: Scroll, +{ + fn scroll_by(&mut self, x: i32, y: i32) { + let speed = self.config().read().unwrap().scroll().speed(); + let old_x = self.horizontal_scroll_value(); + let old_y = self.vertical_scroll_value(); + + match (self.mut_horizontal_scroll_handler(), speed * x, old_x) { + (Some(ref mut s), dist, old) if dist + old >= 0 => { + s.scroll_to(dist + old); + if s.scrolled_part() > 1.0 { + s.scroll_to(old); + } + } + _ => (), + }; + match (self.mut_vertical_scroll_handler(), speed * y, old_y) { + (Some(ref mut s), dist, old) if dist + old >= 0 => { + s.scroll_to(dist + old); + if s.scrolled_part() > 1.0 { + s.scroll_to(old); + } + } + _ => (), + }; + } + + fn scroll(&self) -> Point { + Point::new( + -self.horizontal_scroll_value(), + -self.vertical_scroll_value(), + ) + } + + fn horizontal_scroll_value(&self) -> i32 { + self.horizontal_scroll_handler() + .map_or(0, |s| s.scroll_value()) + } + + fn vertical_scroll_value(&self) -> i32 { + self.vertical_scroll_handler() + .map_or(0, |s| s.scroll_value()) + } + + fn vertical_scrolled_part(&self) -> f64 { + self.vertical_scroll_handler() + .map_or(1.0, |s| s.scrolled_part()) + } + + fn horizontal_scrolled_part(&self) -> f64 { + self.horizontal_scroll_handler() + .map_or(1.0, |s| s.scrolled_part()) + } + + fn mut_horizontal_scroll_handler(&mut self) -> Option<&mut HS>; + fn horizontal_scroll_handler(&self) -> Option<&HS>; + fn mut_vertical_scroll_handler(&mut self) -> Option<&mut VS>; + fn vertical_scroll_handler(&self) -> Option<&VS>; +} + +pub trait Scroll { fn scroll_to(&mut self, n: i32); fn scroll_value(&self) -> i32; @@ -17,3 +83,37 @@ pub trait Scrollable { fn scrolled_part(&self) -> f64; } + +pub struct ScrollBar { + scroll_value: i32, + viewport: u32, + full: u32, + rect: Rect, +} + +impl ScrollBar { + pub fn new(config: ConfigAccess) -> Self { + let width = { config.read().unwrap().scroll().width() }; + Self { + scroll_value: 0, + viewport: 1, + full: 1, + rect: Rect::new(0, 0, width, 0), + } + } + + #[inline] + pub fn viewport(&self) -> u32 { + self.viewport + } + + #[inline] + pub fn full(&self) -> u32 { + self.full + } + + #[inline] + pub fn rect(&self) -> &Rect { + &self.rect + } +} diff --git a/rider-editor/src/ui/scroll_bar/vertical_scroll_bar.rs b/rider-editor/src/ui/scroll_bar/vertical_scroll_bar.rs index 73372b7..7f0bd4b 100644 --- a/rider-editor/src/ui/scroll_bar/vertical_scroll_bar.rs +++ b/rider-editor/src/ui/scroll_bar/vertical_scroll_bar.rs @@ -2,50 +2,42 @@ use crate::app::UpdateResult as UR; use crate::ui::*; use rider_config::ConfigAccess; use sdl2::pixels::Color; -use sdl2::rect::Rect; +use std::ops::{Deref, DerefMut}; pub struct VerticalScrollBar { - scroll_value: i32, - viewport: u32, - full_height: u32, - rect: Rect, + inner: ScrollBar, +} + +impl Deref for VerticalScrollBar { + type Target = ScrollBar; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for VerticalScrollBar { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } } impl VerticalScrollBar { pub fn new(config: ConfigAccess) -> Self { - let width = { config.read().unwrap().scroll().width() }; Self { - scroll_value: 0, - viewport: 1, - full_height: 1, - rect: Rect::new(0, 0, width, 0), + inner: ScrollBar::new(config), } } - - #[inline] - pub fn viewport(&self) -> u32 { - self.viewport - } - - #[inline] - pub fn full_height(&self) -> u32 { - self.full_height - } - - #[inline] - pub fn rect(&self) -> &Rect { - &self.rect - } } impl Update for VerticalScrollBar { fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR { - if self.full_height() < self.viewport() { + if self.full < self.viewport() { return UR::NoOp; } - let ratio = self.full_height() as f64 / self.viewport() as f64; - self.rect - .set_height((self.viewport() as f64 / ratio) as u32); + let ratio = self.full as f64 / self.viewport() as f64; + let height = (self.viewport() as f64 / ratio) as u32; + self.rect.set_height(height); let y = (self.viewport() - self.rect.height()) as f64 * self.scrolled_part(); self.rect.set_y(y as i32); @@ -59,7 +51,7 @@ impl VerticalScrollBar { where T: CanvasAccess, { - if self.full_height() < self.viewport() { + if self.full < self.viewport() { return; } @@ -75,7 +67,7 @@ impl VerticalScrollBar { } } -impl Scrollable for VerticalScrollBar { +impl Scroll for VerticalScrollBar { fn scroll_to(&mut self, n: i32) { self.scroll_value = n; } @@ -89,7 +81,7 @@ impl Scrollable for VerticalScrollBar { } fn set_full_size(&mut self, n: u32) { - self.full_height = n; + self.full = n; } fn set_location(&mut self, n: i32) { @@ -97,10 +89,10 @@ impl Scrollable for VerticalScrollBar { } fn scrolled_part(&self) -> f64 { - if self.full_height() <= self.viewport() { + if self.full <= self.viewport() { return 1.0; } - self.scroll_value().abs() as f64 / (self.full_height() - self.viewport()) as f64 + self.scroll_value().abs() as f64 / (self.full - self.viewport()) as f64 } } @@ -111,7 +103,7 @@ mod test_update { use std::sync::*; impl VerticalScrollBar { - pub fn rect_mut(&mut self) -> &mut Rect { + pub fn rect_mut(&mut self) -> &mut sdl2::rect::Rect { &mut self.rect } } @@ -184,9 +176,9 @@ mod test_scrollable { fn assert_set_full_size() { let config = support::build_config(); let mut widget = VerticalScrollBar::new(Arc::clone(&config)); - let old = widget.full_height(); + let old = widget.full; widget.set_full_size(157); - let current = widget.full_height(); + let current = widget.full; let expected = 157; assert_ne!(old, current); assert_eq!(current, expected);