Add Widget trait, improve scrollbar
This commit is contained in:
parent
9b6ef389b9
commit
a0d7f4acec
@ -1,8 +1,5 @@
|
|||||||
use crate::app::{ConfigAccess, ConfigHolder, UpdateResult as UR};
|
use crate::app::{ConfigAccess, UpdateResult as UR};
|
||||||
use crate::renderer::Renderer;
|
use crate::ui::{UpdateContext, Widget, WidgetInner};
|
||||||
use crate::ui::{
|
|
||||||
move_render_point, CanvasAccess, ClickHandler, RenderBox, RenderContext, Update, UpdateContext,
|
|
||||||
};
|
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
|
|
||||||
const ICON_DEST_WIDTH: u32 = 16;
|
const ICON_DEST_WIDTH: u32 = 16;
|
||||||
@ -11,97 +8,69 @@ const ICON_SRC_WIDTH: u32 = 32;
|
|||||||
const ICON_SRC_HEIGHT: u32 = 32;
|
const ICON_SRC_HEIGHT: u32 = 32;
|
||||||
|
|
||||||
pub struct SaveButton {
|
pub struct SaveButton {
|
||||||
source: Rect,
|
inner: WidgetInner,
|
||||||
dest: Rect,
|
}
|
||||||
config: ConfigAccess,
|
|
||||||
|
impl std::ops::Deref for SaveButton {
|
||||||
|
type Target = WidgetInner;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::DerefMut for SaveButton {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for SaveButton {
|
||||||
|
fn texture_path(&self) -> Option<String> {
|
||||||
|
let c = self.config.read().unwrap();
|
||||||
|
let mut themes_dir = c.directories().themes_dir.clone();
|
||||||
|
let path = c.theme().images().save_icon();
|
||||||
|
themes_dir.push(path);
|
||||||
|
Some(themes_dir.to_str().unwrap().to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dest(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dest(&mut self, rect: &Rect) {
|
||||||
|
self.inner.dest = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source(&self) -> &Rect {
|
||||||
|
&self.source
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_source(&mut self, rect: &Rect) {
|
||||||
|
self.inner.source = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UR {
|
||||||
|
UR::SaveCurrentFile
|
||||||
|
}
|
||||||
|
|
||||||
|
fn padding_width(&self) -> u32 {
|
||||||
|
ICON_DEST_WIDTH
|
||||||
|
}
|
||||||
|
|
||||||
|
fn padding_height(&self) -> u32 {
|
||||||
|
ICON_DEST_HEIGHT
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SaveButton {
|
impl SaveButton {
|
||||||
pub fn new(config: ConfigAccess) -> Self {
|
pub fn new(config: ConfigAccess) -> Self {
|
||||||
Self {
|
Self {
|
||||||
dest: Rect::new(0, 0, ICON_DEST_WIDTH, ICON_DEST_HEIGHT),
|
inner: WidgetInner::new(
|
||||||
source: Rect::new(0, 0, ICON_SRC_WIDTH, ICON_SRC_HEIGHT),
|
|
||||||
config,
|
config,
|
||||||
|
Rect::new(0, 0, ICON_SRC_WIDTH, ICON_SRC_HEIGHT),
|
||||||
|
Rect::new(0, 0, ICON_DEST_WIDTH, ICON_DEST_HEIGHT),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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::ParentPosition(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 save_texture_path = {
|
|
||||||
let c = self.config.read().unwrap();
|
|
||||||
let mut themes_dir = c.directories().themes_dir.clone();
|
|
||||||
let path = c.theme().images().save_icon();
|
|
||||||
themes_dir.push(path);
|
|
||||||
themes_dir.to_str().unwrap().to_owned()
|
|
||||||
};
|
|
||||||
let maybe_tex = renderer.load_image(save_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 SaveButton {
|
|
||||||
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR {
|
|
||||||
UR::NoOp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClickHandler for SaveButton {
|
|
||||||
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UR {
|
|
||||||
UR::SaveCurrentFile
|
|
||||||
}
|
|
||||||
|
|
||||||
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 SaveButton {
|
|
||||||
fn render_start_point(&self) -> Point {
|
|
||||||
self.dest.top_left()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dest(&self) -> Rect {
|
|
||||||
self.dest
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
use crate::app::{ConfigAccess, ConfigHolder, UpdateResult as UR};
|
use crate::app::UpdateResult as UR;
|
||||||
use crate::renderer::Renderer;
|
use crate::ui::{UpdateContext, Widget, WidgetInner};
|
||||||
use crate::ui::{
|
use rider_config::ConfigAccess;
|
||||||
move_render_point, CanvasAccess, ClickHandler, RenderBox, RenderContext, Update, UpdateContext,
|
|
||||||
};
|
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
|
|
||||||
const ICON_DEST_WIDTH: u32 = 16;
|
const ICON_DEST_WIDTH: u32 = 16;
|
||||||
@ -11,97 +9,69 @@ const ICON_SRC_WIDTH: u32 = 16;
|
|||||||
const ICON_SRC_HEIGHT: u32 = 16;
|
const ICON_SRC_HEIGHT: u32 = 16;
|
||||||
|
|
||||||
pub struct SettingsButton {
|
pub struct SettingsButton {
|
||||||
source: Rect,
|
inner: WidgetInner,
|
||||||
dest: Rect,
|
}
|
||||||
config: ConfigAccess,
|
|
||||||
|
impl std::ops::Deref for SettingsButton {
|
||||||
|
type Target = WidgetInner;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::DerefMut for SettingsButton {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for SettingsButton {
|
||||||
|
fn texture_path(&self) -> Option<String> {
|
||||||
|
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);
|
||||||
|
Some(themes_dir.to_str().unwrap().to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dest(&self) -> &Rect {
|
||||||
|
&self.dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dest(&mut self, rect: &Rect) {
|
||||||
|
self.inner.dest = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source(&self) -> &Rect {
|
||||||
|
&self.source
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_source(&mut self, rect: &Rect) {
|
||||||
|
self.inner.source = rect.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UR {
|
||||||
|
UR::OpenSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
fn padding_width(&self) -> u32 {
|
||||||
|
ICON_DEST_WIDTH
|
||||||
|
}
|
||||||
|
|
||||||
|
fn padding_height(&self) -> u32 {
|
||||||
|
ICON_DEST_HEIGHT
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SettingsButton {
|
impl SettingsButton {
|
||||||
pub fn new(config: ConfigAccess) -> Self {
|
pub fn new(config: ConfigAccess) -> Self {
|
||||||
Self {
|
Self {
|
||||||
dest: Rect::new(0, 0, ICON_DEST_WIDTH, ICON_DEST_HEIGHT),
|
inner: WidgetInner::new(
|
||||||
source: Rect::new(0, 0, ICON_SRC_WIDTH, ICON_SRC_HEIGHT),
|
|
||||||
config,
|
config,
|
||||||
|
Rect::new(0, 0, ICON_SRC_WIDTH, ICON_SRC_HEIGHT),
|
||||||
|
Rect::new(0, 0, ICON_DEST_WIDTH, ICON_DEST_HEIGHT),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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::ParentPosition(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 {
|
|
||||||
UR::NoOp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClickHandler for SettingsButton {
|
|
||||||
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UR {
|
|
||||||
UR::OpenSettings
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ use crate::ui::file::TextCollection;
|
|||||||
use crate::ui::file::TextWidget;
|
use crate::ui::file::TextWidget;
|
||||||
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::Scroll;
|
use crate::ui::scroll_bar::ScrollWidget;
|
||||||
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;
|
||||||
@ -175,8 +175,8 @@ impl FileAccess for FileEditor {
|
|||||||
if let Some(f) = self.file.as_ref() {
|
if let Some(f) = self.file.as_ref() {
|
||||||
self.full_rect = f.full_rect();
|
self.full_rect = f.full_rect();
|
||||||
}
|
}
|
||||||
self.vertical_scroll_bar.set_location(0);
|
self.vertical_scroll_bar.reset();
|
||||||
self.horizontal_scroll_bar.set_location(0);
|
self.horizontal_scroll_bar.reset();
|
||||||
file
|
file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,15 +71,21 @@ impl MenuBar {
|
|||||||
)
|
)
|
||||||
.unwrap_or_else(|_| panic!("Failed to draw main menu background"));
|
.unwrap_or_else(|_| panic!("Failed to draw main menu background"));
|
||||||
|
|
||||||
let context = RenderContext::ParentPosition(
|
self.save_button.render(
|
||||||
|
canvas,
|
||||||
|
renderer,
|
||||||
|
&RenderContext::ParentPosition(
|
||||||
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);
|
|
||||||
|
|
||||||
let context = RenderContext::ParentPosition(
|
self.settings_button.render(
|
||||||
|
canvas,
|
||||||
|
renderer,
|
||||||
|
&RenderContext::ParentPosition(
|
||||||
relative_position.offset(SAVE_BUTTON_OFFSET_LEFT * 2, SAVE_BUTTON_OFFSET_TOP),
|
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) {
|
||||||
|
@ -4,7 +4,7 @@ use sdl2::render::Texture;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::app::application::WindowCanvas;
|
use crate::app::application::WindowCanvas;
|
||||||
use crate::app::UpdateResult as UR;
|
use crate::app::{UpdateResult as UR, UpdateResult};
|
||||||
use crate::renderer::managers::*;
|
use crate::renderer::managers::*;
|
||||||
use rider_config::*;
|
use rider_config::*;
|
||||||
|
|
||||||
@ -31,6 +31,7 @@ pub use self::modal::*;
|
|||||||
pub use self::project_tree::*;
|
pub use self::project_tree::*;
|
||||||
pub use self::scroll_bar::*;
|
pub use self::scroll_bar::*;
|
||||||
pub use self::text_character::*;
|
pub use self::text_character::*;
|
||||||
|
use crate::renderer::Renderer;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum UpdateContext<'l> {
|
pub enum UpdateContext<'l> {
|
||||||
@ -140,6 +141,100 @@ pub trait RenderBox {
|
|||||||
fn dest(&self) -> Rect;
|
fn dest(&self) -> Rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct WidgetInner {
|
||||||
|
source: Rect,
|
||||||
|
dest: Rect,
|
||||||
|
config: ConfigAccess,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetInner {
|
||||||
|
pub fn new(config: ConfigAccess, source: Rect, dest: Rect) -> Self {
|
||||||
|
Self {
|
||||||
|
dest,
|
||||||
|
source,
|
||||||
|
config,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Widget {
|
||||||
|
fn texture_path(&self) -> Option<String>;
|
||||||
|
|
||||||
|
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||||
|
where
|
||||||
|
C: CanvasAccess,
|
||||||
|
R: Renderer,
|
||||||
|
{
|
||||||
|
let mut dest = match context {
|
||||||
|
&RenderContext::ParentPosition(p) => move_render_point(p.clone(), &self.dest()),
|
||||||
|
_ => self.dest().clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
canvas.set_clipping(self.clipping(&dest));
|
||||||
|
self.texture_path()
|
||||||
|
.and_then(|path| renderer.load_image(path).ok())
|
||||||
|
.and_then(|texture| {
|
||||||
|
dest.set_width(self.dest().width());
|
||||||
|
dest.set_height(self.dest().height());
|
||||||
|
canvas
|
||||||
|
.render_image(texture.clone(), self.source().clone(), dest.clone())
|
||||||
|
.unwrap_or_else(|_| panic!("Failed to draw widget texture"));
|
||||||
|
Some(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_ui<'l, T>(&mut self, _renderer: &mut T)
|
||||||
|
where
|
||||||
|
T: ConfigHolder + Renderer,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dest(&self) -> &Rect;
|
||||||
|
|
||||||
|
fn set_dest(&mut self, rect: &Rect);
|
||||||
|
|
||||||
|
fn source(&self) -> &Rect;
|
||||||
|
|
||||||
|
fn set_source(&mut self, rect: &Rect);
|
||||||
|
|
||||||
|
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UpdateResult {
|
||||||
|
UpdateResult::NoOp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_left_click(&mut self, _point: &Point, _context: &UpdateContext) -> UpdateResult {
|
||||||
|
UpdateResult::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().clone(),
|
||||||
|
}
|
||||||
|
.contains_point(point.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_start_point(&self) -> Point {
|
||||||
|
self.dest().top_left()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clipping(&self, relative_dest: &Rect) -> Rect {
|
||||||
|
Rect::new(
|
||||||
|
relative_dest.x(),
|
||||||
|
relative_dest.y(),
|
||||||
|
relative_dest.width() + self.padding_width(),
|
||||||
|
relative_dest.height() + self.padding_height(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn padding_width(&self) -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn padding_height(&self) -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -24,6 +24,30 @@ pub struct OpenFile {
|
|||||||
config: ConfigAccess,
|
config: ConfigAccess,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ScrollView<VerticalScrollBar, HorizontalScrollBar> for OpenFile {
|
||||||
|
fn mut_horizontal_scroll_handler(&mut self) -> Option<&mut HorizontalScrollBar> {
|
||||||
|
Some(&mut self.horizontal_scroll_bar)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigHolder for OpenFile {
|
||||||
|
fn config(&self) -> &ConfigAccess {
|
||||||
|
&self.config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl OpenFile {
|
impl OpenFile {
|
||||||
pub fn new(root_path: String, width: u32, height: u32, config: ConfigAccess) -> Self {
|
pub fn new(root_path: String, width: u32, height: u32, config: ConfigAccess) -> Self {
|
||||||
let (window_width, window_height, background_color, border_color) = {
|
let (window_width, window_height, background_color, border_color) = {
|
||||||
@ -79,35 +103,6 @@ impl OpenFile {
|
|||||||
&self.full_dest
|
&self.full_dest
|
||||||
}
|
}
|
||||||
|
|
||||||
pub 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn scroll(&self) -> Point {
|
|
||||||
Point::new(
|
|
||||||
-self.horizontal_scroll_bar.scroll_value(),
|
|
||||||
-self.vertical_scroll_bar.scroll_value(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self, ticks: i32, context: &UC) -> UR {
|
pub fn update(&mut self, ticks: i32, context: &UC) -> UR {
|
||||||
let (window_width, window_height, color, scroll_width, scroll_margin) = {
|
let (window_width, window_height, color, scroll_width, scroll_margin) = {
|
||||||
let c = self.config.read().unwrap();
|
let c = self.config.read().unwrap();
|
||||||
@ -218,8 +213,8 @@ impl OpenFile {
|
|||||||
|
|
||||||
pub fn is_left_click_target(&self, point: &Point, context: &UC) -> bool {
|
pub fn is_left_click_target(&self, point: &Point, context: &UC) -> bool {
|
||||||
let dest = match context {
|
let dest = match context {
|
||||||
UC::ParentPosition(p) => move_render_point(p.clone(), &self.dest),
|
UC::ParentPosition(p) => move_render_point(p.clone(), &self.dest()),
|
||||||
_ => self.dest.clone(),
|
_ => self.dest().clone(),
|
||||||
};
|
};
|
||||||
let p =
|
let p =
|
||||||
dest.top_left() + Point::new(CONTENT_MARGIN_LEFT, CONTENT_MARGIN_TOP) + self.scroll();
|
dest.top_left() + Point::new(CONTENT_MARGIN_LEFT, CONTENT_MARGIN_TOP) + self.scroll();
|
||||||
@ -248,7 +243,7 @@ mod tests {
|
|||||||
let config = build_config();
|
let config = build_config();
|
||||||
let mut widget = OpenFile::new("/tmp".to_owned(), 100, 100, config);
|
let mut widget = OpenFile::new("/tmp".to_owned(), 100, 100, config);
|
||||||
widget.scroll_by(12, 13);
|
widget.scroll_by(12, 13);
|
||||||
assert_eq!(widget.scroll(), Point::new(0, -390));
|
assert_eq!(widget.scroll(), Point::new(-360, -390));
|
||||||
}
|
}
|
||||||
|
|
||||||
//#######################################################################
|
//#######################################################################
|
||||||
|
@ -311,7 +311,7 @@ mod tests {
|
|||||||
let mut widget = ProjectTreeSidebar::new("/tmp".to_owned(), config);
|
let mut widget = ProjectTreeSidebar::new("/tmp".to_owned(), config);
|
||||||
widget.scroll_by(10, 10);
|
widget.scroll_by(10, 10);
|
||||||
let res = widget.scroll();
|
let res = widget.scroll();
|
||||||
let expected = Point::new(0, -300);
|
let expected = Point::new(-300, -300);
|
||||||
assert_eq!(res, expected);
|
assert_eq!(res, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
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 std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
pub struct HorizontalScrollBar {
|
pub struct HorizontalScrollBar {
|
||||||
@ -22,6 +20,7 @@ impl DerefMut for HorizontalScrollBar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
impl HorizontalScrollBar {
|
impl HorizontalScrollBar {
|
||||||
pub fn new(config: ConfigAccess) -> Self {
|
pub fn new(config: ConfigAccess) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -30,70 +29,55 @@ impl HorizontalScrollBar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Update for HorizontalScrollBar {
|
impl ScrollWidget for HorizontalScrollBar {
|
||||||
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR {
|
fn update_rect(&mut self, pos: i32, max: u32) {
|
||||||
if self.full < self.viewport {
|
self.mut_rect().set_width(max);
|
||||||
return UR::NoOp;
|
self.mut_rect().set_x(pos);
|
||||||
}
|
|
||||||
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 - self.viewport) as f64);
|
|
||||||
self.rect.set_x(x as i32);
|
|
||||||
|
|
||||||
UR::NoOp
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
#[inline]
|
||||||
impl HorizontalScrollBar {
|
|
||||||
pub fn render<T>(&self, canvas: &mut T, context: &RenderContext)
|
|
||||||
where
|
|
||||||
T: CanvasAccess,
|
|
||||||
{
|
|
||||||
if self.full < self.viewport {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas
|
|
||||||
.render_rect(
|
|
||||||
match context {
|
|
||||||
RenderContext::ParentPosition(p) => move_render_point(p.clone(), &self.rect),
|
|
||||||
_ => self.rect.clone(),
|
|
||||||
},
|
|
||||||
Color::RGBA(255, 255, 255, 0),
|
|
||||||
)
|
|
||||||
.unwrap_or_else(|_| panic!("Failed to render vertical scroll back"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn scroll_value(&self) -> i32 {
|
fn scroll_value(&self) -> i32 {
|
||||||
self.scroll_value
|
self.scroll_value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn set_viewport(&mut self, n: u32) {
|
fn set_viewport(&mut self, n: u32) {
|
||||||
self.viewport = n;
|
self.viewport = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn set_full_size(&mut self, n: u32) {
|
fn set_full_size(&mut self, n: u32) {
|
||||||
self.full = n;
|
self.full = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn set_location(&mut self, n: i32) {
|
fn set_location(&mut self, n: i32) {
|
||||||
self.rect.set_y(n);
|
self.rect.set_y(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scrolled_part(&self) -> f64 {
|
#[inline]
|
||||||
if self.full < self.viewport() {
|
fn viewport(&self) -> u32 {
|
||||||
return 1.0;
|
self.viewport
|
||||||
}
|
}
|
||||||
self.scroll_value().abs() as f64 / (self.full - self.viewport()) as f64
|
|
||||||
|
#[inline]
|
||||||
|
fn full(&self) -> u32 {
|
||||||
|
self.full
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rect(&self) -> &sdl2::rect::Rect {
|
||||||
|
&self.rect
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mut_rect(&mut self) -> &mut sdl2::rect::Rect {
|
||||||
|
&mut self.rect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +88,7 @@ mod test_update {
|
|||||||
use std::sync::*;
|
use std::sync::*;
|
||||||
|
|
||||||
impl HorizontalScrollBar {
|
impl HorizontalScrollBar {
|
||||||
pub fn rect_mut(&mut self) -> &mut Rect {
|
pub fn rect_mut(&mut self) -> &mut sdl2::rect::Rect {
|
||||||
&mut self.rect
|
&mut self.rect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
|
|
||||||
|
use crate::app::UpdateResult;
|
||||||
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 crate::ui::{move_render_point, CanvasAccess, RenderContext, UpdateContext};
|
||||||
use rider_config::{ConfigAccess, ConfigHolder};
|
use rider_config::{ConfigAccess, ConfigHolder};
|
||||||
|
use sdl2::pixels::Color;
|
||||||
|
|
||||||
pub mod horizontal_scroll_bar;
|
pub mod horizontal_scroll_bar;
|
||||||
pub mod vertical_scroll_bar;
|
pub mod vertical_scroll_bar;
|
||||||
|
|
||||||
pub trait ScrollView<VS, HS>: ConfigHolder
|
pub trait ScrollView<VS, HS>: ConfigHolder
|
||||||
where
|
where
|
||||||
VS: Scroll,
|
VS: ScrollWidget,
|
||||||
HS: Scroll,
|
HS: ScrollWidget,
|
||||||
{
|
{
|
||||||
fn scroll_by(&mut self, x: i32, y: i32) {
|
fn scroll_by(&mut self, x: i32, y: i32) {
|
||||||
let speed = self.config().read().unwrap().scroll().speed();
|
let speed = self.config().read().unwrap().scroll().speed();
|
||||||
@ -70,7 +73,39 @@ where
|
|||||||
fn vertical_scroll_handler(&self) -> Option<&VS>;
|
fn vertical_scroll_handler(&self) -> Option<&VS>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Scroll {
|
pub trait ScrollWidget {
|
||||||
|
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UpdateResult {
|
||||||
|
if self.full() < self.viewport() {
|
||||||
|
return UpdateResult::NoOp;
|
||||||
|
}
|
||||||
|
let max = (self.viewport() as f64 / self.ratio()) as u32;
|
||||||
|
let pos = (self.viewport() - max) as f64 * self.scrolled_part();
|
||||||
|
self.update_rect(pos as i32, max);
|
||||||
|
|
||||||
|
UpdateResult::NoOp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render<T>(&self, canvas: &mut T, context: &RenderContext)
|
||||||
|
where
|
||||||
|
T: CanvasAccess,
|
||||||
|
{
|
||||||
|
if self.full() < self.viewport() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas
|
||||||
|
.render_border(
|
||||||
|
match context {
|
||||||
|
RenderContext::ParentPosition(p) => move_render_point(p.clone(), self.rect()),
|
||||||
|
_ => self.rect().clone(),
|
||||||
|
},
|
||||||
|
Color::RGBA(255, 255, 255, 0),
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|_| panic!("Failed to render vertical scroll back"));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_rect(&mut self, pos: i32, max: u32);
|
||||||
|
|
||||||
fn scroll_to(&mut self, n: i32);
|
fn scroll_to(&mut self, n: i32);
|
||||||
|
|
||||||
fn scroll_value(&self) -> i32;
|
fn scroll_value(&self) -> i32;
|
||||||
@ -81,7 +116,31 @@ pub trait Scroll {
|
|||||||
|
|
||||||
fn set_location(&mut self, n: i32);
|
fn set_location(&mut self, n: i32);
|
||||||
|
|
||||||
fn scrolled_part(&self) -> f64;
|
#[inline]
|
||||||
|
fn scrolled_part(&self) -> f64 {
|
||||||
|
if self.full() <= self.viewport() {
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
self.scroll_value().abs() as f64 / (self.full() - self.viewport()) as f64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn viewport(&self) -> u32;
|
||||||
|
|
||||||
|
fn full(&self) -> u32;
|
||||||
|
|
||||||
|
fn rect(&self) -> &Rect;
|
||||||
|
|
||||||
|
fn mut_rect(&mut self) -> &mut Rect;
|
||||||
|
|
||||||
|
fn ratio(&self) -> f64 {
|
||||||
|
self.full() as f64 / self.viewport() as f64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(&mut self) {
|
||||||
|
self.update_rect(0, 0);
|
||||||
|
self.set_full_size(0);
|
||||||
|
self.scroll_to(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ScrollBar {
|
pub struct ScrollBar {
|
||||||
@ -101,19 +160,4 @@ impl ScrollBar {
|
|||||||
rect: Rect::new(0, 0, width, 0),
|
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
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 std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
pub struct VerticalScrollBar {
|
pub struct VerticalScrollBar {
|
||||||
@ -22,6 +20,7 @@ impl DerefMut for VerticalScrollBar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
impl VerticalScrollBar {
|
impl VerticalScrollBar {
|
||||||
pub fn new(config: ConfigAccess) -> Self {
|
pub fn new(config: ConfigAccess) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -30,69 +29,55 @@ impl VerticalScrollBar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Update for VerticalScrollBar {
|
impl ScrollWidget for VerticalScrollBar {
|
||||||
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UR {
|
fn update_rect(&mut self, pos: i32, max: u32) {
|
||||||
if self.full < self.viewport() {
|
self.mut_rect().set_height(max);
|
||||||
return UR::NoOp;
|
self.mut_rect().set_y(pos);
|
||||||
}
|
|
||||||
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);
|
|
||||||
|
|
||||||
UR::NoOp
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
#[inline]
|
||||||
impl VerticalScrollBar {
|
|
||||||
pub fn render<T>(&self, canvas: &mut T, context: &RenderContext)
|
|
||||||
where
|
|
||||||
T: CanvasAccess,
|
|
||||||
{
|
|
||||||
if self.full < self.viewport() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas
|
|
||||||
.render_border(
|
|
||||||
match context {
|
|
||||||
RenderContext::ParentPosition(p) => move_render_point(p.clone(), &self.rect),
|
|
||||||
_ => self.rect.clone(),
|
|
||||||
},
|
|
||||||
Color::RGBA(255, 255, 255, 0),
|
|
||||||
)
|
|
||||||
.unwrap_or_else(|_| panic!("Failed to render vertical scroll back"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn scroll_value(&self) -> i32 {
|
fn scroll_value(&self) -> i32 {
|
||||||
self.scroll_value
|
self.scroll_value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn set_viewport(&mut self, n: u32) {
|
fn set_viewport(&mut self, n: u32) {
|
||||||
self.viewport = n;
|
self.viewport = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn set_full_size(&mut self, n: u32) {
|
fn set_full_size(&mut self, n: u32) {
|
||||||
self.full = n;
|
self.full = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn set_location(&mut self, n: i32) {
|
fn set_location(&mut self, n: i32) {
|
||||||
self.rect.set_x(n);
|
self.rect.set_x(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scrolled_part(&self) -> f64 {
|
#[inline]
|
||||||
if self.full <= self.viewport() {
|
fn viewport(&self) -> u32 {
|
||||||
return 1.0;
|
self.viewport
|
||||||
}
|
}
|
||||||
self.scroll_value().abs() as f64 / (self.full - self.viewport()) as f64
|
|
||||||
|
#[inline]
|
||||||
|
fn full(&self) -> u32 {
|
||||||
|
self.full
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rect(&self) -> &sdl2::rect::Rect {
|
||||||
|
&self.rect
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mut_rect(&mut self) -> &mut sdl2::rect::Rect {
|
||||||
|
&mut self.rect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,5 +269,4 @@ mod tests {
|
|||||||
let expected = ThemeConfig::new(SerdeColor::new(0, 0, 0, 0), false, false);
|
let expected = ThemeConfig::new(SerdeColor::new(0, 0, 0, 0), false, false);
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user