This commit is contained in:
Adrian Wozniak 2019-12-21 14:29:18 +01:00
parent 7cf3e9de18
commit 9b6ef389b9
5 changed files with 195 additions and 137 deletions

View File

@ -7,10 +7,9 @@ use crate::ui::caret::MoveDirection;
use crate::ui::file::editor_file::EditorFile; use crate::ui::file::editor_file::EditorFile;
use crate::ui::file::TextCollection; use crate::ui::file::TextCollection;
use crate::ui::file::TextWidget; use crate::ui::file::TextWidget;
use crate::ui::move_render_point;
use crate::ui::scroll_bar::horizontal_scroll_bar::*; use crate::ui::scroll_bar::horizontal_scroll_bar::*;
use crate::ui::scroll_bar::vertical_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::text_character::CharacterSizeManager;
use crate::ui::CanvasAccess; use crate::ui::CanvasAccess;
use crate::ui::ClickHandler; use crate::ui::ClickHandler;
@ -18,6 +17,7 @@ use crate::ui::RenderBox;
use crate::ui::RenderContext; use crate::ui::RenderContext;
use crate::ui::Update; use crate::ui::Update;
use crate::ui::UpdateContext; use crate::ui::UpdateContext;
use crate::ui::{move_render_point, ScrollView};
use sdl2::rect::Point; use sdl2::rect::Point;
use sdl2::rect::Rect; use sdl2::rect::Rect;
use std::mem; use std::mem;
@ -47,12 +47,6 @@ pub trait CaretAccess {
fn set_caret_to_end_of_line(&mut self, line: i32); 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 { pub struct FileEditor {
dest: Rect, dest: Rect,
full_rect: Rect, full_rect: Rect,
@ -144,34 +138,21 @@ impl FileEditor {
} }
} }
impl ScrollableView for FileEditor { impl ScrollView<VerticalScrollBar, HorizontalScrollBar> for FileEditor {
fn scroll_by(&mut self, x: i32, y: i32) { fn mut_horizontal_scroll_handler(&mut self) -> Option<&mut HorizontalScrollBar> {
let read_config = self.config.read().unwrap(); Some(&mut self.horizontal_scroll_bar)
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);
}
}
} }
fn scroll(&self) -> Point { fn horizontal_scroll_handler(&self) -> Option<&HorizontalScrollBar> {
Point::new( Some(&self.horizontal_scroll_bar)
-self.horizontal_scroll_bar.scroll_value(), }
-self.vertical_scroll_bar.scroll_value(),
) 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)
} }
} }

View File

@ -1,17 +1,16 @@
use crate::app::application::UpdateResult; use crate::app::application::UpdateResult;
use crate::renderer::renderer::Renderer; use crate::renderer::renderer::Renderer;
use crate::ui::file_editor::ScrollableView;
use crate::ui::filesystem::directory::DirectoryView; use crate::ui::filesystem::directory::DirectoryView;
use crate::ui::horizontal_scroll_bar::HorizontalScrollBar; 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::text_character::CharacterSizeManager;
use crate::ui::vertical_scroll_bar::VerticalScrollBar; use crate::ui::vertical_scroll_bar::VerticalScrollBar;
use crate::ui::CanvasAccess; use crate::ui::CanvasAccess;
use crate::ui::ClickHandler; use crate::ui::ClickHandler;
use crate::ui::RenderContext; use crate::ui::RenderContext;
use crate::ui::UpdateContext; use crate::ui::UpdateContext;
use crate::ui::{move_render_point, ScrollView};
use rider_config::config::Config; use rider_config::config::Config;
use rider_config::ConfigHolder;
use sdl2::pixels::Color; use sdl2::pixels::Color;
use sdl2::rect::Point; use sdl2::rect::Point;
use sdl2::rect::Rect; use sdl2::rect::Rect;
@ -169,34 +168,27 @@ impl ClickHandler for ProjectTreeSidebar {
} }
} }
impl ScrollableView for ProjectTreeSidebar { impl ConfigHolder for ProjectTreeSidebar {
fn scroll_by(&mut self, x: i32, y: i32) { fn config(&self) -> &Arc<RwLock<Config>> {
let read_config = self.config.read().unwrap(); &self.config
}
}
let value_x = read_config.scroll().speed() * x; impl ScrollView<VerticalScrollBar, HorizontalScrollBar> for ProjectTreeSidebar {
let value_y = read_config.scroll().speed() * y; fn mut_horizontal_scroll_handler(&mut self) -> Option<&mut HorizontalScrollBar> {
let old_x = self.horizontal_scroll_bar.scroll_value(); Some(&mut self.horizontal_scroll_bar)
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);
}
}
} }
fn scroll(&self) -> Point { fn horizontal_scroll_handler(&self) -> Option<&HorizontalScrollBar> {
Point::new( Some(&self.horizontal_scroll_bar)
-self.horizontal_scroll_bar.scroll_value(), }
-self.vertical_scroll_bar.scroll_value(),
) 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::renderer::renderer::Renderer;
use crate::tests::support::build_config; use crate::tests::support::build_config;
use crate::tests::support::CanvasMock; use crate::tests::support::CanvasMock;
use crate::ui::file_editor::ScrollableView;
use crate::ui::project_tree::ProjectTreeSidebar; use crate::ui::project_tree::ProjectTreeSidebar;
use crate::ui::scroll_bar::ScrollView;
use crate::ui::text_character::CharacterSizeManager; use crate::ui::text_character::CharacterSizeManager;
use crate::ui::ClickHandler; use crate::ui::ClickHandler;
use crate::ui::UpdateContext; use crate::ui::UpdateContext;

View File

@ -2,51 +2,44 @@ use crate::app::UpdateResult as UR;
use crate::ui::*; use crate::ui::*;
use rider_config::ConfigAccess; use rider_config::ConfigAccess;
use sdl2::pixels::Color; use sdl2::pixels::Color;
use sdl2::rect::Rect; use std::ops::{Deref, DerefMut};
pub struct HorizontalScrollBar { pub struct HorizontalScrollBar {
scroll_value: i32, inner: ScrollBar,
viewport: u32, }
full_width: u32,
rect: Rect, 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 { impl HorizontalScrollBar {
pub fn new(config: ConfigAccess) -> Self { pub fn new(config: ConfigAccess) -> Self {
let width = { config.read().unwrap().scroll().width() };
Self { Self {
scroll_value: 0, inner: ScrollBar::new(config),
viewport: 1,
full_width: 1,
rect: Rect::new(0, 0, width, 0),
} }
} }
#[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 { impl Update for HorizontalScrollBar {
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR { fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR {
if self.full_width < self.viewport { if self.full < self.viewport {
return UR::NoOp; return UR::NoOp;
} }
let ratio = self.full_width as f64 / self.viewport as f64; let ratio = self.full as f64 / self.viewport as f64;
self.rect.set_width((self.viewport as f64 / ratio) as u32); let width = (self.viewport as f64 / ratio) as u32;
self.rect.set_width(width);
let x = (self.viewport - self.rect.width()) as f64 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); self.rect.set_x(x as i32);
UR::NoOp UR::NoOp
@ -59,7 +52,7 @@ impl HorizontalScrollBar {
where where
T: CanvasAccess, T: CanvasAccess,
{ {
if self.full_width < self.viewport { if self.full < self.viewport {
return; return;
} }
@ -75,7 +68,7 @@ impl HorizontalScrollBar {
} }
} }
impl Scrollable for HorizontalScrollBar { impl Scroll for HorizontalScrollBar {
fn scroll_to(&mut self, n: i32) { fn scroll_to(&mut self, n: i32) {
self.scroll_value = n; self.scroll_value = n;
} }
@ -89,7 +82,7 @@ impl Scrollable for HorizontalScrollBar {
} }
fn set_full_size(&mut self, n: u32) { fn set_full_size(&mut self, n: u32) {
self.full_width = n; self.full = n;
} }
fn set_location(&mut self, n: i32) { fn set_location(&mut self, n: i32) {
@ -97,10 +90,10 @@ impl Scrollable for HorizontalScrollBar {
} }
fn scrolled_part(&self) -> f64 { fn scrolled_part(&self) -> f64 {
if self.full_width() < self.viewport() { if self.full < self.viewport() {
return 1.0; 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() { fn assert_set_full_size() {
let config = support::build_config(); let config = support::build_config();
let mut widget = HorizontalScrollBar::new(Arc::clone(&config)); let mut widget = HorizontalScrollBar::new(Arc::clone(&config));
let old = widget.full_width(); let old = widget.full;
widget.set_full_size(157); widget.set_full_size(157);
let current = widget.full_width(); let current = widget.full;
let expected = 157; let expected = 157;
assert_ne!(old, current); assert_ne!(old, current);
assert_eq!(current, expected); assert_eq!(current, expected);

View File

@ -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::horizontal_scroll_bar::HorizontalScrollBar;
pub use crate::ui::scroll_bar::vertical_scroll_bar::VerticalScrollBar; pub use crate::ui::scroll_bar::vertical_scroll_bar::VerticalScrollBar;
use rider_config::{ConfigAccess, ConfigHolder};
pub mod horizontal_scroll_bar; pub mod horizontal_scroll_bar;
pub mod vertical_scroll_bar; pub mod vertical_scroll_bar;
pub trait Scrollable { pub trait ScrollView<VS, HS>: 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_to(&mut self, n: i32);
fn scroll_value(&self) -> i32; fn scroll_value(&self) -> i32;
@ -17,3 +83,37 @@ pub trait Scrollable {
fn scrolled_part(&self) -> f64; 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
}
}

View File

@ -2,50 +2,42 @@ use crate::app::UpdateResult as UR;
use crate::ui::*; use crate::ui::*;
use rider_config::ConfigAccess; use rider_config::ConfigAccess;
use sdl2::pixels::Color; use sdl2::pixels::Color;
use sdl2::rect::Rect; use std::ops::{Deref, DerefMut};
pub struct VerticalScrollBar { pub struct VerticalScrollBar {
scroll_value: i32, inner: ScrollBar,
viewport: u32, }
full_height: u32,
rect: Rect, 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 { impl VerticalScrollBar {
pub fn new(config: ConfigAccess) -> Self { pub fn new(config: ConfigAccess) -> Self {
let width = { config.read().unwrap().scroll().width() };
Self { Self {
scroll_value: 0, inner: ScrollBar::new(config),
viewport: 1,
full_height: 1,
rect: Rect::new(0, 0, width, 0),
} }
} }
#[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 { impl Update for VerticalScrollBar {
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR { fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR {
if self.full_height() < self.viewport() { if self.full < self.viewport() {
return UR::NoOp; return UR::NoOp;
} }
let ratio = self.full_height() as f64 / self.viewport() as f64; let ratio = self.full as f64 / self.viewport() as f64;
self.rect let height = (self.viewport() as f64 / ratio) as u32;
.set_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(); let y = (self.viewport() - self.rect.height()) as f64 * self.scrolled_part();
self.rect.set_y(y as i32); self.rect.set_y(y as i32);
@ -59,7 +51,7 @@ impl VerticalScrollBar {
where where
T: CanvasAccess, T: CanvasAccess,
{ {
if self.full_height() < self.viewport() { if self.full < self.viewport() {
return; return;
} }
@ -75,7 +67,7 @@ impl VerticalScrollBar {
} }
} }
impl Scrollable for VerticalScrollBar { impl Scroll for VerticalScrollBar {
fn scroll_to(&mut self, n: i32) { fn scroll_to(&mut self, n: i32) {
self.scroll_value = n; self.scroll_value = n;
} }
@ -89,7 +81,7 @@ impl Scrollable for VerticalScrollBar {
} }
fn set_full_size(&mut self, n: u32) { fn set_full_size(&mut self, n: u32) {
self.full_height = n; self.full = n;
} }
fn set_location(&mut self, n: i32) { fn set_location(&mut self, n: i32) {
@ -97,10 +89,10 @@ impl Scrollable for VerticalScrollBar {
} }
fn scrolled_part(&self) -> f64 { fn scrolled_part(&self) -> f64 {
if self.full_height() <= self.viewport() { if self.full <= self.viewport() {
return 1.0; 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::*; use std::sync::*;
impl VerticalScrollBar { impl VerticalScrollBar {
pub fn rect_mut(&mut self) -> &mut Rect { pub fn rect_mut(&mut self) -> &mut sdl2::rect::Rect {
&mut self.rect &mut self.rect
} }
} }
@ -184,9 +176,9 @@ mod test_scrollable {
fn assert_set_full_size() { fn assert_set_full_size() {
let config = support::build_config(); let config = support::build_config();
let mut widget = VerticalScrollBar::new(Arc::clone(&config)); let mut widget = VerticalScrollBar::new(Arc::clone(&config));
let old = widget.full_height(); let old = widget.full;
widget.set_full_size(157); widget.set_full_size(157);
let current = widget.full_height(); let current = widget.full;
let expected = 157; let expected = 157;
assert_ne!(old, current); assert_ne!(old, current);
assert_eq!(current, expected); assert_eq!(current, expected);