Simplify components
This commit is contained in:
parent
a0d7f4acec
commit
a80b3d0107
@ -1,7 +1,7 @@
|
||||
use crate::app::*;
|
||||
use crate::renderer::*;
|
||||
use crate::ui::icon::Icon;
|
||||
use crate::ui::*;
|
||||
use sdl2::pixels::Color;
|
||||
use sdl2::rect::{Point, Rect};
|
||||
use std::fs;
|
||||
use std::path;
|
||||
@ -11,35 +11,234 @@ const CHILD_MARGIN: i32 = 4;
|
||||
const DEFAULT_ICON_SIZE: u32 = 16;
|
||||
|
||||
pub struct DirectoryView {
|
||||
inner: WidgetInner,
|
||||
opened: bool,
|
||||
expanded: bool,
|
||||
name_width: u32,
|
||||
icon_width: u32,
|
||||
icon_height: u32,
|
||||
height: u32,
|
||||
path: String,
|
||||
files: Vec<FileEntry>,
|
||||
directories: Vec<DirectoryView>,
|
||||
pos: Point,
|
||||
source: Rect,
|
||||
config: ConfigAccess,
|
||||
name_label: Label,
|
||||
icon: Icon,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for DirectoryView {
|
||||
type Target = WidgetInner;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for DirectoryView {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for DirectoryView {
|
||||
fn texture_path(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
fn dest(&self) -> &Rect {
|
||||
&self.dest
|
||||
}
|
||||
|
||||
fn set_dest(&mut self, _rect: &Rect) {}
|
||||
|
||||
fn source(&self) -> &Rect {
|
||||
&self.inner.source
|
||||
}
|
||||
|
||||
fn set_source(&mut self, _rect: &Rect) {}
|
||||
|
||||
fn update(&mut self, ticks: i32, context: &UpdateContext) -> UpdateResult {
|
||||
self.icon.update(ticks, context);
|
||||
self.name_label.update(ticks, context);
|
||||
if !path::Path::new(&self.path).exists() {
|
||||
return UpdateResult::RefreshFsTree;
|
||||
}
|
||||
if self.opened {
|
||||
for dir in self.directories.iter_mut() {
|
||||
dir.update(ticks, context);
|
||||
}
|
||||
for file in self.files.iter_mut() {
|
||||
file.update(ticks, context);
|
||||
}
|
||||
}
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
|
||||
fn on_left_click(&mut self, point: &Point, context: &UpdateContext) -> UpdateResult {
|
||||
let dest = self.dest();
|
||||
let move_point = match context {
|
||||
&UpdateContext::ParentPosition(p) => p.clone(),
|
||||
_ => Point::new(0, 0),
|
||||
};
|
||||
let dest = move_render_point(move_point.clone(), &dest);
|
||||
|
||||
// icon or name is target of click
|
||||
let icon_or_name = self.name_and_icon_rect();
|
||||
if move_render_point(move_point, &icon_or_name).contains_point(point.clone()) {
|
||||
return UpdateResult::OpenDirectory(self.path.clone());
|
||||
}
|
||||
|
||||
if !self.expanded {
|
||||
return UpdateResult::NoOp;
|
||||
}
|
||||
|
||||
let mut p = dest.top_left()
|
||||
+ Point::new(
|
||||
self.icon_width() as i32 + CHILD_MARGIN,
|
||||
self.icon_height() as i32 + CHILD_MARGIN,
|
||||
);
|
||||
for dir in self.directories.iter_mut() {
|
||||
let context = UpdateContext::ParentPosition(p.clone());
|
||||
if dir.is_left_click_target(&point, &context) {
|
||||
return dir.on_left_click(&point, &context);
|
||||
}
|
||||
p = p + Point::new(0, dir.height() as i32 + CHILD_MARGIN);
|
||||
}
|
||||
for file in self.files.iter_mut() {
|
||||
let context = UpdateContext::ParentPosition(p.clone());
|
||||
if file.is_left_click_target(&point, &context) {
|
||||
return file.on_left_click();
|
||||
}
|
||||
p = p + Point::new(0, file.height() as i32 + CHILD_MARGIN);
|
||||
}
|
||||
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
|
||||
fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
|
||||
let dest = self.dest();
|
||||
let move_point = match context {
|
||||
UpdateContext::ParentPosition(p) => p.clone(),
|
||||
_ => Point::new(0, 0),
|
||||
};
|
||||
let dest = move_render_point(move_point.clone(), &dest);
|
||||
|
||||
// icon or name is target of click
|
||||
let name_and_icon_rect = self.name_and_icon_rect();
|
||||
if move_render_point(move_point.clone(), &name_and_icon_rect).contains_point(point.clone())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if !self.expanded {
|
||||
return false;
|
||||
}
|
||||
let mut p = dest.top_left()
|
||||
+ Point::new(
|
||||
self.icon_width() as i32 + CHILD_MARGIN,
|
||||
self.icon_height() as i32 + CHILD_MARGIN,
|
||||
);
|
||||
// subdirectory is target of click
|
||||
for dir in self.directories.iter() {
|
||||
let context = UpdateContext::ParentPosition(p.clone());
|
||||
if dir.is_left_click_target(&point, &context) {
|
||||
return true;
|
||||
}
|
||||
p = p + Point::new(0, dir.height() as i32 + CHILD_MARGIN);
|
||||
}
|
||||
// file inside directory is target of click
|
||||
for file in self.files.iter() {
|
||||
let context = UpdateContext::ParentPosition(p.clone());
|
||||
if file.is_left_click_target(&point, &context) {
|
||||
return true;
|
||||
}
|
||||
p = p + Point::new(0, file.height() as i32 + CHILD_MARGIN);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||
where
|
||||
R: Renderer + CharacterSizeManager,
|
||||
C: CanvasAccess,
|
||||
{
|
||||
let mut dest = move_render_point(
|
||||
match context {
|
||||
&RenderContext::ParentPosition(p) => p.clone(),
|
||||
_ => Point::new(0, 0),
|
||||
},
|
||||
self.dest(),
|
||||
);
|
||||
|
||||
self.icon.render(
|
||||
canvas,
|
||||
renderer,
|
||||
&RenderContext::ParentPosition(Point::new(dest.x(), dest.y())),
|
||||
);
|
||||
self.name_label.render(
|
||||
canvas,
|
||||
renderer,
|
||||
&RenderContext::ParentPosition(Point::new(
|
||||
dest.x() + self.icon_width() as i32,
|
||||
dest.y(),
|
||||
)),
|
||||
);
|
||||
|
||||
self.render_children::<C, R>(canvas, renderer, &mut dest);
|
||||
}
|
||||
|
||||
fn prepare_ui<R>(&mut self, renderer: &mut R)
|
||||
where
|
||||
R: Renderer + CharacterSizeManager,
|
||||
{
|
||||
let size = renderer.load_character_size('W');
|
||||
self.icon.prepare_ui(renderer);
|
||||
self.icon.dest.set_height(size.height());
|
||||
self.icon.dest.set_width(size.height());
|
||||
|
||||
self.name_label.prepare_ui(renderer);
|
||||
if self.opened {
|
||||
for dir in self.directories.iter_mut() {
|
||||
dir.prepare_ui(renderer);
|
||||
}
|
||||
for file in self.files.iter_mut() {
|
||||
file.prepare_ui(renderer);
|
||||
}
|
||||
}
|
||||
self.calculate_size(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
impl DirectoryView {
|
||||
pub fn new(path: String, config: ConfigAccess) -> Self {
|
||||
let dir_texture_path = {
|
||||
let c = config.read().unwrap();
|
||||
let mut themes_dir = c.directories().themes_dir.clone();
|
||||
let path = c.theme().images().directory_icon();
|
||||
themes_dir.push(path);
|
||||
themes_dir.to_str().unwrap().to_owned()
|
||||
};
|
||||
|
||||
let name = std::path::Path::new(&path)
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
Self {
|
||||
opened: false,
|
||||
expanded: false,
|
||||
name_width: 0,
|
||||
icon_width: DEFAULT_ICON_SIZE,
|
||||
icon_height: DEFAULT_ICON_SIZE,
|
||||
height: 0,
|
||||
path,
|
||||
files: vec![],
|
||||
directories: vec![],
|
||||
pos: Point::new(0, 0),
|
||||
source: Rect::new(0, 0, 64, 64),
|
||||
config,
|
||||
inner: WidgetInner::new(
|
||||
config.clone(),
|
||||
Rect::new(0, 0, 64, 64),
|
||||
Rect::new(0, 0, 0, 0),
|
||||
),
|
||||
name_label: Label::new(name, config.clone()),
|
||||
icon: Icon::new(
|
||||
config,
|
||||
dir_texture_path,
|
||||
Rect::new(0, 0, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE),
|
||||
Rect::new(0, 0, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,34 +246,24 @@ impl DirectoryView {
|
||||
self.path.clone()
|
||||
}
|
||||
|
||||
pub fn dest(&self) -> Rect {
|
||||
match self.expanded {
|
||||
true => Rect::new(
|
||||
self.pos.x(),
|
||||
self.pos.y(),
|
||||
self.icon_width + self.name_width + NAME_MARGIN as u32,
|
||||
self.height,
|
||||
),
|
||||
false => Rect::new(
|
||||
self.pos.x(),
|
||||
self.pos.y(),
|
||||
self.icon_width + self.name_width + NAME_MARGIN as u32,
|
||||
self.icon_height,
|
||||
),
|
||||
}
|
||||
fn expand_view(&mut self) {
|
||||
self.expanded = true;
|
||||
self.dest = Rect::new(
|
||||
self.dest.x(),
|
||||
self.dest.y(),
|
||||
self.icon_width() + self.name_width() + NAME_MARGIN as u32,
|
||||
self.height,
|
||||
);
|
||||
}
|
||||
|
||||
// pub fn dest(&self) -> Rect {
|
||||
// Rect::new(
|
||||
// self.pos.x(),
|
||||
// self.pos.y(),
|
||||
// self.icon_width,
|
||||
// self.icon_height,
|
||||
// )
|
||||
// }
|
||||
|
||||
pub fn source(&self) -> &Rect {
|
||||
&self.source
|
||||
fn collapse_view(&mut self) {
|
||||
self.expanded = false;
|
||||
self.dest = Rect::new(
|
||||
self.dest.x(),
|
||||
self.dest.y(),
|
||||
self.icon_width() + self.name_width() + NAME_MARGIN as u32,
|
||||
self.icon_height(),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn open_directory<R>(&mut self, dir_path: String, renderer: &mut R) -> bool
|
||||
@ -85,10 +274,12 @@ impl DirectoryView {
|
||||
_ if dir_path == self.path => {
|
||||
if !self.opened {
|
||||
self.opened = true;
|
||||
self.expanded = true;
|
||||
self.expand_view();
|
||||
self.read_directory(renderer);
|
||||
} else if self.expanded {
|
||||
self.collapse_view();
|
||||
} else {
|
||||
self.expanded = !self.expanded;
|
||||
self.expand_view();
|
||||
}
|
||||
self.calculate_size(renderer);
|
||||
true
|
||||
@ -96,7 +287,7 @@ impl DirectoryView {
|
||||
_ if dir_path.contains((self.path.clone() + "/").as_str()) => {
|
||||
if !self.opened {
|
||||
self.opened = true;
|
||||
self.expanded = true;
|
||||
self.expand_view();
|
||||
self.read_directory(renderer);
|
||||
}
|
||||
for dir in self.directories.iter_mut() {
|
||||
@ -124,18 +315,26 @@ impl DirectoryView {
|
||||
.to_owned()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn name_width(&self) -> u32 {
|
||||
self.name_width
|
||||
self.name_label.name_width()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn icon_width(&self) -> u32 {
|
||||
self.icon_width
|
||||
self.icon.width()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn icon_height(&self) -> u32 {
|
||||
self.icon.height()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn height(&self) -> u32 {
|
||||
match self.expanded {
|
||||
true => self.height,
|
||||
false => self.icon_height,
|
||||
false => self.icon.height(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,62 +381,6 @@ impl DirectoryView {
|
||||
self.directories.sort_by(|a, b| a.name().cmp(&b.name()));
|
||||
}
|
||||
|
||||
fn render_icon<C, R>(&self, canvas: &mut C, renderer: &mut R, dest: &mut Rect)
|
||||
where
|
||||
C: CanvasAccess,
|
||||
R: Renderer,
|
||||
{
|
||||
let dir_texture_path = {
|
||||
let c = self.config.read().unwrap();
|
||||
let mut themes_dir = c.directories().themes_dir.clone();
|
||||
let path = c.theme().images().directory_icon();
|
||||
themes_dir.push(path);
|
||||
themes_dir.to_str().unwrap().to_owned()
|
||||
};
|
||||
if let Ok(texture) = renderer.load_image(dir_texture_path.clone()) {
|
||||
canvas
|
||||
.render_image(
|
||||
texture,
|
||||
self.source.clone(),
|
||||
Rect::new(dest.x(), dest.y(), self.icon_width, self.icon_height),
|
||||
)
|
||||
.unwrap_or_else(|_| panic!("Failed to draw directory entry texture"));
|
||||
}
|
||||
}
|
||||
|
||||
fn render_name<C, R>(&self, canvas: &mut C, renderer: &mut R, dest: &mut Rect)
|
||||
where
|
||||
C: CanvasAccess,
|
||||
R: Renderer + CharacterSizeManager,
|
||||
{
|
||||
let mut d = dest.clone();
|
||||
d.set_x(dest.x() + NAME_MARGIN);
|
||||
let font_details = build_font_details(self);
|
||||
let name = self.name();
|
||||
let config = self.config.read().unwrap();
|
||||
let text_color = config.theme().code_highlighting().title.color();
|
||||
|
||||
for c in name.chars() {
|
||||
let size = renderer.load_character_size(c.clone());
|
||||
let mut text_details = TextDetails {
|
||||
color: Color::RGBA(text_color.r, text_color.g, text_color.b, text_color.a),
|
||||
text: c.to_string(),
|
||||
font: font_details.clone(),
|
||||
};
|
||||
let maybe_texture = renderer.load_text_tex(&mut text_details, font_details.clone());
|
||||
|
||||
if let Ok(texture) = maybe_texture {
|
||||
d.set_width(size.width());
|
||||
d.set_height(size.height());
|
||||
|
||||
canvas
|
||||
.render_image(texture, self.source.clone(), d.clone())
|
||||
.unwrap_or_else(|_| panic!("Failed to draw directory entry texture"));
|
||||
d.set_x(d.x() + size.width() as i32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_children<C, R>(&self, canvas: &mut C, renderer: &mut R, dest: &mut Rect)
|
||||
where
|
||||
C: CanvasAccess,
|
||||
@ -248,8 +391,8 @@ impl DirectoryView {
|
||||
}
|
||||
let mut point = dest.top_left()
|
||||
+ Point::new(
|
||||
self.icon_width as i32 + CHILD_MARGIN,
|
||||
self.icon_height as i32 + CHILD_MARGIN,
|
||||
self.icon_width() as i32 + CHILD_MARGIN,
|
||||
self.icon_height() as i32 + CHILD_MARGIN,
|
||||
);
|
||||
for dir in self.directories.iter() {
|
||||
let context = RenderContext::ParentPosition(point.clone());
|
||||
@ -269,14 +412,6 @@ impl DirectoryView {
|
||||
{
|
||||
let size = renderer.load_character_size('W');
|
||||
self.height = size.height();
|
||||
self.icon_height = size.height();
|
||||
self.icon_width = size.height();
|
||||
self.name_width = 0;
|
||||
|
||||
for c in self.name().chars() {
|
||||
let size = renderer.load_character_size(c.clone());
|
||||
self.name_width += size.width();
|
||||
}
|
||||
|
||||
for dir in self.directories.iter_mut() {
|
||||
self.height = self.height + dir.height() + CHILD_MARGIN as u32;
|
||||
@ -288,144 +423,12 @@ impl DirectoryView {
|
||||
|
||||
fn name_and_icon_rect(&self) -> Rect {
|
||||
Rect::new(
|
||||
self.pos.x(),
|
||||
self.pos.y(),
|
||||
self.icon_width + self.name_width + NAME_MARGIN as u32,
|
||||
self.icon_height,
|
||||
self.dest.x(),
|
||||
self.dest.y(),
|
||||
self.icon.width() + self.name_width() + NAME_MARGIN as u32,
|
||||
self.icon.height(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn render<R, C>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||
where
|
||||
R: Renderer + CharacterSizeManager,
|
||||
C: CanvasAccess,
|
||||
{
|
||||
let dest = self.dest();
|
||||
let move_point = match context {
|
||||
&RenderContext::ParentPosition(p) => p.clone(),
|
||||
_ => Point::new(0, 0),
|
||||
};
|
||||
let mut dest = move_render_point(move_point, &dest);
|
||||
self.render_icon::<C, R>(canvas, renderer, &mut dest);
|
||||
self.render_name::<C, R>(canvas, renderer, &mut dest.clone());
|
||||
self.render_children::<C, R>(canvas, renderer, &mut dest);
|
||||
}
|
||||
|
||||
pub fn prepare_ui<R>(&mut self, renderer: &mut R)
|
||||
where
|
||||
R: Renderer + CharacterSizeManager,
|
||||
{
|
||||
if self.opened {
|
||||
for dir in self.directories.iter_mut() {
|
||||
dir.prepare_ui(renderer);
|
||||
}
|
||||
for file in self.files.iter_mut() {
|
||||
file.prepare_ui(renderer);
|
||||
}
|
||||
}
|
||||
self.calculate_size(renderer);
|
||||
}
|
||||
|
||||
pub fn update(&mut self, ticks: i32, context: &UpdateContext) -> UpdateResult {
|
||||
if !path::Path::new(&self.path).exists() {
|
||||
return UpdateResult::RefreshFsTree;
|
||||
}
|
||||
if self.opened {
|
||||
for dir in self.directories.iter_mut() {
|
||||
dir.update(ticks, context);
|
||||
}
|
||||
for file in self.files.iter_mut() {
|
||||
file.update();
|
||||
}
|
||||
}
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
|
||||
pub fn render_start_point(&self) -> Point {
|
||||
self.pos.clone()
|
||||
}
|
||||
|
||||
pub fn on_left_click(&mut self, point: &Point, context: &UpdateContext) -> UpdateResult {
|
||||
let dest = self.dest();
|
||||
let move_point = match context {
|
||||
&UpdateContext::ParentPosition(p) => p.clone(),
|
||||
_ => Point::new(0, 0),
|
||||
};
|
||||
let dest = move_render_point(move_point.clone(), &dest);
|
||||
|
||||
// icon or name is target of click
|
||||
let icon_or_name = self.name_and_icon_rect();
|
||||
if move_render_point(move_point, &icon_or_name).contains_point(point.clone()) {
|
||||
return UpdateResult::OpenDirectory(self.path.clone());
|
||||
}
|
||||
|
||||
if !self.expanded {
|
||||
return UpdateResult::NoOp;
|
||||
}
|
||||
|
||||
let mut p = dest.top_left()
|
||||
+ Point::new(
|
||||
self.icon_width as i32 + CHILD_MARGIN,
|
||||
self.icon_height as i32 + CHILD_MARGIN,
|
||||
);
|
||||
for dir in self.directories.iter_mut() {
|
||||
let context = UpdateContext::ParentPosition(p.clone());
|
||||
if dir.is_left_click_target(&point, &context) {
|
||||
return dir.on_left_click(&point, &context);
|
||||
}
|
||||
p = p + Point::new(0, dir.height() as i32 + CHILD_MARGIN);
|
||||
}
|
||||
for file in self.files.iter_mut() {
|
||||
let context = UpdateContext::ParentPosition(p.clone());
|
||||
if file.is_left_click_target(&point, &context) {
|
||||
return file.on_left_click();
|
||||
}
|
||||
p = p + Point::new(0, file.height() as i32 + CHILD_MARGIN);
|
||||
}
|
||||
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
|
||||
pub fn is_left_click_target(&self, point: &Point, context: &UpdateContext) -> bool {
|
||||
let dest = self.dest();
|
||||
let move_point = match context {
|
||||
UpdateContext::ParentPosition(p) => p.clone(),
|
||||
_ => Point::new(0, 0),
|
||||
};
|
||||
let dest = move_render_point(move_point.clone(), &dest);
|
||||
|
||||
// icon or name is target of click
|
||||
let name_and_icon_rect = self.name_and_icon_rect();
|
||||
if move_render_point(move_point.clone(), &name_and_icon_rect).contains_point(point.clone())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if !self.expanded {
|
||||
return false;
|
||||
}
|
||||
let mut p = dest.top_left()
|
||||
+ Point::new(
|
||||
self.icon_width as i32 + CHILD_MARGIN,
|
||||
self.icon_height as i32 + CHILD_MARGIN,
|
||||
);
|
||||
// subdirectory is target of click
|
||||
for dir in self.directories.iter() {
|
||||
let context = UpdateContext::ParentPosition(p.clone());
|
||||
if dir.is_left_click_target(&point, &context) {
|
||||
return true;
|
||||
}
|
||||
p = p + Point::new(0, dir.height() as i32 + CHILD_MARGIN);
|
||||
}
|
||||
// file inside directory is target of click
|
||||
for file in self.files.iter() {
|
||||
let context = UpdateContext::ParentPosition(p.clone());
|
||||
if file.is_left_click_target(&point, &context) {
|
||||
return true;
|
||||
}
|
||||
p = p + Point::new(0, file.height() as i32 + CHILD_MARGIN);
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigHolder for DirectoryView {
|
||||
@ -569,7 +572,7 @@ mod tests {
|
||||
fn assert_initial_dest() {
|
||||
let config = build_config();
|
||||
let widget = DirectoryView::new("/foo".to_owned(), config);
|
||||
assert_eq!(widget.dest(), Rect::new(0, 0, 36, 16));
|
||||
assert_eq!(widget.dest(), &Rect::new(0, 0, 36, 16));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -578,7 +581,7 @@ mod tests {
|
||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
||||
let mut widget = DirectoryView::new("/foo".to_owned(), config);
|
||||
widget.prepare_ui(&mut renderer);
|
||||
assert_eq!(widget.dest(), Rect::new(0, 0, 73, 14));
|
||||
assert_eq!(widget.dest(), &Rect::new(0, 0, 73, 14));
|
||||
}
|
||||
|
||||
//##########################################################
|
||||
|
@ -1,9 +1,8 @@
|
||||
use crate::app::*;
|
||||
use crate::renderer::*;
|
||||
use crate::ui::icon::Icon;
|
||||
use crate::ui::*;
|
||||
use sdl2::pixels::Color;
|
||||
use sdl2::rect::{Point, Rect};
|
||||
use std::collections::HashMap;
|
||||
use std::path;
|
||||
|
||||
const ICON_DEST_WIDTH: u32 = 16;
|
||||
@ -12,168 +11,151 @@ const ICON_SRC_WIDTH: u32 = 64;
|
||||
const ICON_SRC_HEIGHT: u32 = 64;
|
||||
|
||||
pub struct FileEntry {
|
||||
name_width: u32,
|
||||
icon_width: u32,
|
||||
height: u32,
|
||||
name: String,
|
||||
path: String,
|
||||
dest: Rect,
|
||||
source: Rect,
|
||||
config: ConfigAccess,
|
||||
char_sizes: HashMap<char, Rect>,
|
||||
inner: WidgetInner,
|
||||
icon: Icon,
|
||||
label: Label,
|
||||
}
|
||||
|
||||
impl FileEntry {
|
||||
pub fn new(name: String, path: String, config: ConfigAccess) -> Self {
|
||||
Self {
|
||||
name,
|
||||
path,
|
||||
name_width: 0,
|
||||
icon_width: 0,
|
||||
height: 0,
|
||||
dest: Rect::new(0, 0, ICON_DEST_WIDTH, ICON_DEST_HEIGHT),
|
||||
source: Rect::new(0, 0, ICON_SRC_WIDTH, ICON_SRC_HEIGHT),
|
||||
config,
|
||||
char_sizes: HashMap::new(),
|
||||
}
|
||||
impl std::ops::Deref for FileEntry {
|
||||
type Target = WidgetInner;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for FileEntry {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for FileEntry {
|
||||
fn texture_path(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn name_width(&self) -> u32 {
|
||||
self.name_width
|
||||
fn dest(&self) -> &Rect {
|
||||
&self.inner.dest
|
||||
}
|
||||
|
||||
pub fn icon_width(&self) -> u32 {
|
||||
self.icon_width
|
||||
fn set_dest(&mut self, rect: &Rect) {
|
||||
self.inner.dest = rect.clone();
|
||||
}
|
||||
|
||||
pub fn height(&self) -> u32 {
|
||||
self.height
|
||||
fn source(&self) -> &Rect {
|
||||
&self.inner.source
|
||||
}
|
||||
|
||||
pub fn name(&self) -> String {
|
||||
self.name.clone()
|
||||
fn set_source(&mut self, rect: &Rect) {
|
||||
self.inner.source = rect.clone();
|
||||
}
|
||||
|
||||
pub fn path(&self) -> String {
|
||||
self.path.clone()
|
||||
}
|
||||
|
||||
pub fn dest(&self) -> &Rect {
|
||||
&self.dest
|
||||
}
|
||||
|
||||
pub fn source(&self) -> &Rect {
|
||||
&self.source
|
||||
}
|
||||
|
||||
pub fn full_dest(&self) -> Rect {
|
||||
Rect::new(
|
||||
self.dest.x(),
|
||||
self.dest.y(),
|
||||
self.icon_width + NAME_MARGIN as u32 + self.name_width,
|
||||
self.height,
|
||||
)
|
||||
}
|
||||
|
||||
fn render_icon<C, R>(&self, canvas: &mut C, renderer: &mut R, dest: &mut Rect)
|
||||
where
|
||||
C: CanvasAccess,
|
||||
R: Renderer,
|
||||
{
|
||||
let dir_texture_path = {
|
||||
let c = self.config.read().unwrap();
|
||||
let mut themes_dir = c.directories().themes_dir.clone();
|
||||
let path = c.theme().images().file_icon();
|
||||
themes_dir.push(path);
|
||||
themes_dir.to_str().unwrap().to_owned()
|
||||
};
|
||||
let maybe_tex = renderer.load_image(dir_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"));
|
||||
}
|
||||
}
|
||||
|
||||
fn render_name<C, R>(&self, canvas: &mut C, renderer: &mut R, dest: &mut Rect)
|
||||
where
|
||||
C: CanvasAccess,
|
||||
R: Renderer,
|
||||
{
|
||||
let mut d = dest.clone();
|
||||
d.set_x(dest.x() + NAME_MARGIN);
|
||||
|
||||
let font_details = build_font_details(self);
|
||||
let name = self.name();
|
||||
|
||||
for c in name.chars() {
|
||||
let size = self
|
||||
.char_sizes
|
||||
.get(&c)
|
||||
.unwrap_or(&Rect::new(0, 0, 0, 0))
|
||||
.clone();
|
||||
let mut text_details = TextDetails {
|
||||
color: Color::RGBA(255, 255, 255, 0),
|
||||
text: c.to_string(),
|
||||
font: font_details.clone(),
|
||||
};
|
||||
let maybe_texture = renderer.load_text_tex(&mut text_details, font_details.clone());
|
||||
|
||||
if let Ok(texture) = maybe_texture {
|
||||
d.set_width(size.width());
|
||||
d.set_height(size.height());
|
||||
|
||||
canvas
|
||||
.render_image(texture, self.source.clone(), d.clone())
|
||||
.unwrap_or_else(|_| panic!("Failed to draw directory entry texture"));
|
||||
d.set_x(d.x() + size.width() as i32)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub 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(),
|
||||
};
|
||||
self.render_icon(canvas, renderer, &mut dest);
|
||||
self.render_name(canvas, renderer, &mut dest.clone());
|
||||
}
|
||||
|
||||
pub fn prepare_ui<R>(&mut self, renderer: &mut R)
|
||||
where
|
||||
R: Renderer + CharacterSizeManager,
|
||||
{
|
||||
let w_rect = renderer.load_character_size('W');
|
||||
self.char_sizes.insert('W', w_rect.clone());
|
||||
self.height = w_rect.height();
|
||||
self.icon_width = w_rect.height();
|
||||
self.name_width = 0;
|
||||
|
||||
for c in self.name().chars() {
|
||||
let size = { renderer.load_character_size(c.clone()) };
|
||||
self.char_sizes.insert(c, size);
|
||||
self.name_width += size.width();
|
||||
}
|
||||
self.dest.set_width(w_rect.height());
|
||||
self.dest.set_height(w_rect.height());
|
||||
}
|
||||
|
||||
pub fn update(&mut self) -> UpdateResult {
|
||||
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UpdateResult {
|
||||
if !path::Path::new(&self.path).exists() {
|
||||
return UpdateResult::RefreshFsTree;
|
||||
}
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
|
||||
pub fn render_start_point(&self) -> Point {
|
||||
self.dest.top_left()
|
||||
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||
where
|
||||
C: CanvasAccess,
|
||||
R: Renderer + CharacterSizeManager,
|
||||
{
|
||||
let dest = match context {
|
||||
&RenderContext::ParentPosition(p) => move_render_point(p.clone(), self.dest()),
|
||||
_ => self.dest.clone(),
|
||||
};
|
||||
self.icon.render(
|
||||
canvas,
|
||||
renderer,
|
||||
&RenderContext::ParentPosition(Point::new(dest.x(), dest.y())),
|
||||
);
|
||||
self.label.render(
|
||||
canvas,
|
||||
renderer,
|
||||
&RenderContext::ParentPosition(Point::new(dest.x() + NAME_MARGIN, dest.y())),
|
||||
)
|
||||
}
|
||||
|
||||
fn prepare_ui<R>(&mut self, renderer: &mut R)
|
||||
where
|
||||
R: Renderer + CharacterSizeManager,
|
||||
{
|
||||
let rect = renderer.load_character_size('W');
|
||||
self.icon.prepare_ui(renderer);
|
||||
self.icon.dest.set_height(rect.height());
|
||||
self.icon.dest.set_width(rect.height());
|
||||
self.label.prepare_ui(renderer);
|
||||
let old = self.inner.dest.clone();
|
||||
self.inner.dest = Rect::new(
|
||||
old.x(),
|
||||
old.y(),
|
||||
self.name_width() + self.icon_width(),
|
||||
self.height(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl FileEntry {
|
||||
pub fn new(name: String, path: String, config: ConfigAccess) -> Self {
|
||||
let texture_path = {
|
||||
let c = config.read().unwrap();
|
||||
let mut themes_dir = c.directories().themes_dir.clone();
|
||||
let path = c.theme().images().file_icon();
|
||||
themes_dir.push(path);
|
||||
themes_dir.to_str().unwrap().to_owned()
|
||||
};
|
||||
Self {
|
||||
path,
|
||||
inner: WidgetInner::new(
|
||||
config.clone(),
|
||||
Rect::new(0, 0, ICON_SRC_WIDTH, ICON_SRC_HEIGHT),
|
||||
Rect::new(0, 0, ICON_DEST_WIDTH, ICON_DEST_HEIGHT),
|
||||
),
|
||||
icon: Icon::new(
|
||||
config.clone(),
|
||||
texture_path,
|
||||
Rect::new(0, 0, ICON_SRC_WIDTH, ICON_SRC_HEIGHT),
|
||||
Rect::new(0, 0, ICON_DEST_WIDTH, ICON_DEST_HEIGHT),
|
||||
),
|
||||
label: Label::new(name.clone(), config),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn name_width(&self) -> u32 {
|
||||
self.label.name_width()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn icon_width(&self) -> u32 {
|
||||
self.icon.width()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn height(&self) -> u32 {
|
||||
self.dest().height()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn name(&self) -> String {
|
||||
self.label.name()
|
||||
}
|
||||
|
||||
pub fn path(&self) -> String {
|
||||
self.path.clone()
|
||||
}
|
||||
|
||||
pub fn full_dest(&self) -> Rect {
|
||||
Rect::new(
|
||||
self.dest.x(),
|
||||
self.dest.y(),
|
||||
self.icon.width() + NAME_MARGIN as u32 + self.label.name_width(),
|
||||
self.height(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_left_click(&mut self) -> UpdateResult {
|
||||
@ -184,7 +166,7 @@ impl FileEntry {
|
||||
let dest = Rect::new(
|
||||
self.dest.x(),
|
||||
self.dest.y(),
|
||||
self.icon_width + self.name_width + NAME_MARGIN as u32,
|
||||
self.icon_width() + self.name_width() + NAME_MARGIN as u32,
|
||||
self.dest.height(),
|
||||
);
|
||||
let rect = match context {
|
||||
@ -207,6 +189,7 @@ mod tests {
|
||||
use crate::tests::support::build_config;
|
||||
use crate::tests::support::CanvasMock;
|
||||
use crate::tests::support::SimpleRendererMock;
|
||||
use crate::ui::{UpdateContext, Widget};
|
||||
|
||||
//##########################################################
|
||||
// name_width
|
||||
@ -378,7 +361,10 @@ mod tests {
|
||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/foo".to_owned(), config);
|
||||
widget.prepare_ui(&mut renderer);
|
||||
assert_eq!(widget.update(), UpdateResult::RefreshFsTree);
|
||||
assert_eq!(
|
||||
widget.update(0, &UpdateContext::Nothing),
|
||||
UpdateResult::RefreshFsTree
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -387,7 +373,10 @@ mod tests {
|
||||
let mut renderer = SimpleRendererMock::new(config.clone());
|
||||
let mut widget = FileEntry::new("bar.txt".to_owned(), "/tmp".to_owned(), config);
|
||||
widget.prepare_ui(&mut renderer);
|
||||
assert_eq!(widget.update(), UpdateResult::NoOp);
|
||||
assert_eq!(
|
||||
widget.update(0, &UpdateContext::Nothing),
|
||||
UpdateResult::NoOp
|
||||
);
|
||||
}
|
||||
|
||||
//##########################################################
|
||||
|
67
rider-editor/src/ui/icon.rs
Normal file
67
rider-editor/src/ui/icon.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use crate::ui::{Widget, WidgetInner};
|
||||
use rider_config::ConfigAccess;
|
||||
use sdl2::rect::Rect;
|
||||
|
||||
pub struct Icon {
|
||||
path: String,
|
||||
inner: WidgetInner,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Icon {
|
||||
type Target = WidgetInner;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for Icon {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl Icon {
|
||||
pub fn new(config: ConfigAccess, path: String, source: Rect, dest: Rect) -> Self {
|
||||
Self {
|
||||
path,
|
||||
inner: WidgetInner::new(config, source, dest),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn height(&self) -> u32 {
|
||||
self.inner.dest.height()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn width(&self) -> u32 {
|
||||
self.inner.dest.width()
|
||||
}
|
||||
|
||||
pub fn set_texture_path(&mut self, path: String) {
|
||||
self.path = path;
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for Icon {
|
||||
fn texture_path(&self) -> Option<String> {
|
||||
Some(self.path.clone())
|
||||
}
|
||||
|
||||
fn dest(&self) -> &Rect {
|
||||
&self.inner.dest
|
||||
}
|
||||
|
||||
fn set_dest(&mut self, rect: &Rect) {
|
||||
self.inner.dest = rect.clone();
|
||||
}
|
||||
|
||||
fn source(&self) -> &Rect {
|
||||
&self.inner.source
|
||||
}
|
||||
|
||||
fn set_source(&mut self, rect: &Rect) {
|
||||
self.inner.source = rect.clone();
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ use crate::app::*;
|
||||
use crate::renderer::*;
|
||||
use crate::ui::*;
|
||||
use sdl2::pixels::Color;
|
||||
use sdl2::rect::{Point, Rect};
|
||||
use sdl2::rect::Rect;
|
||||
use std::collections::HashMap;
|
||||
|
||||
const DEST_WIDTH: u32 = 16;
|
||||
@ -11,37 +11,47 @@ const SRC_WIDTH: u32 = 64;
|
||||
const SRC_HEIGHT: u32 = 64;
|
||||
|
||||
pub struct Label {
|
||||
name_width: u32,
|
||||
height: u32,
|
||||
name: String,
|
||||
source: Rect,
|
||||
dest: Rect,
|
||||
char_sizes: HashMap<char, Rect>,
|
||||
config: ConfigAccess,
|
||||
inner: WidgetInner,
|
||||
}
|
||||
|
||||
impl Label {
|
||||
pub fn new(name: String, config: ConfigAccess) -> Self {
|
||||
Self {
|
||||
name,
|
||||
name_width: 0,
|
||||
height: 0,
|
||||
dest: Rect::new(0, 0, DEST_WIDTH, DEST_HEIGHT),
|
||||
source: Rect::new(0, 0, SRC_WIDTH, SRC_HEIGHT),
|
||||
config,
|
||||
char_sizes: HashMap::new(),
|
||||
}
|
||||
impl std::ops::Deref for Label {
|
||||
type Target = WidgetInner;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for Label {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for Label {
|
||||
fn texture_path(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn name_width(&self) -> u32 {
|
||||
self.name_width
|
||||
fn dest(&self) -> &Rect {
|
||||
&self.inner.dest
|
||||
}
|
||||
|
||||
pub fn name(&self) -> String {
|
||||
self.name.clone()
|
||||
fn set_dest(&mut self, rect: &Rect) {
|
||||
self.inner.dest = rect.clone();
|
||||
}
|
||||
|
||||
pub fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||
fn source(&self) -> &Rect {
|
||||
&self.inner.source
|
||||
}
|
||||
|
||||
fn set_source(&mut self, rect: &Rect) {
|
||||
self.inner.source = rect.clone();
|
||||
}
|
||||
|
||||
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||
where
|
||||
C: CanvasAccess,
|
||||
R: Renderer,
|
||||
@ -52,65 +62,78 @@ impl Label {
|
||||
};
|
||||
let mut d = dest.clone();
|
||||
d.set_x(dest.x() + NAME_MARGIN);
|
||||
canvas.set_clipping(d.clone());
|
||||
|
||||
let font_details = build_font_details(self);
|
||||
for c in self.name.chars() {
|
||||
let size = self
|
||||
.char_sizes
|
||||
.get(&c)
|
||||
.unwrap_or(&Rect::new(0, 0, 0, 0))
|
||||
.clone();
|
||||
let mut text_details = TextDetails {
|
||||
color: Color::RGBA(255, 255, 255, 0),
|
||||
text: c.to_string(),
|
||||
font: font_details.clone(),
|
||||
};
|
||||
let maybe_texture = renderer.load_text_tex(&mut text_details, font_details.clone());
|
||||
.cloned()
|
||||
.unwrap_or_else(|| Rect::new(0, 0, 0, 0));
|
||||
renderer
|
||||
.load_text_tex(
|
||||
&mut TextDetails {
|
||||
color: Color::RGBA(255, 255, 255, 0),
|
||||
text: c.to_string(),
|
||||
font: font_details.clone(),
|
||||
},
|
||||
font_details.clone(),
|
||||
)
|
||||
.and_then(|texture| {
|
||||
d.set_width(size.width());
|
||||
d.set_height(size.height());
|
||||
|
||||
if let Ok(texture) = maybe_texture {
|
||||
d.set_width(size.width());
|
||||
d.set_height(size.height());
|
||||
|
||||
canvas
|
||||
.render_image(texture, self.source.clone(), d.clone())
|
||||
.unwrap_or_else(|_| panic!("Failed to draw directory entry texture"));
|
||||
d.set_x(d.x() + size.width() as i32);
|
||||
}
|
||||
canvas
|
||||
.render_image(texture, self.source.clone(), d.clone())
|
||||
.unwrap_or_else(|_| panic!("Failed to draw directory entry texture"));
|
||||
d.set_x(d.x() + size.width() as i32);
|
||||
Ok(())
|
||||
})
|
||||
.unwrap_or_else(|e| {
|
||||
eprintln!("Failed to render label \"{:?}\": {:?}", self.name(), e)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prepare_ui<R>(&mut self, renderer: &mut R)
|
||||
fn prepare_ui<R>(&mut self, renderer: &mut R)
|
||||
where
|
||||
R: Renderer + CharacterSizeManager,
|
||||
{
|
||||
let w_rect = renderer.load_character_size('W');
|
||||
self.char_sizes.insert('W', w_rect.clone());
|
||||
self.height = w_rect.height();
|
||||
self.name_width = 0;
|
||||
let mut name_width = 0;
|
||||
|
||||
for c in self.name().chars() {
|
||||
let size = { renderer.load_character_size(c.clone()) };
|
||||
self.char_sizes.insert(c, size);
|
||||
self.name_width += size.width();
|
||||
name_width += size.width();
|
||||
}
|
||||
self.dest.set_width(w_rect.height());
|
||||
self.dest.set_width(name_width);
|
||||
self.dest.set_height(w_rect.height());
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderBox for Label {
|
||||
fn render_start_point(&self) -> Point {
|
||||
self.dest.top_left()
|
||||
impl Label {
|
||||
pub fn new(name: String, config: ConfigAccess) -> Self {
|
||||
Self {
|
||||
name,
|
||||
char_sizes: HashMap::new(),
|
||||
inner: WidgetInner::new(
|
||||
config,
|
||||
Rect::new(0, 0, SRC_WIDTH, SRC_HEIGHT),
|
||||
Rect::new(0, 0, DEST_WIDTH, DEST_HEIGHT),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn dest(&self) -> Rect {
|
||||
self.dest.clone()
|
||||
#[inline]
|
||||
pub fn name_width(&self) -> u32 {
|
||||
self.dest.width()
|
||||
}
|
||||
}
|
||||
|
||||
impl Update for Label {
|
||||
fn update(&mut self, _ticks: i32, _context: &UpdateContext) -> UpdateResult {
|
||||
UpdateResult::NoOp
|
||||
pub fn name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ impl MenuBar {
|
||||
pub fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||
where
|
||||
C: CanvasAccess,
|
||||
R: Renderer,
|
||||
R: Renderer + CharacterSizeManager,
|
||||
{
|
||||
use std::borrow::*;
|
||||
|
||||
|
@ -13,6 +13,7 @@ pub mod caret;
|
||||
pub mod file;
|
||||
pub mod file_editor;
|
||||
pub mod filesystem;
|
||||
pub mod icon;
|
||||
pub mod label;
|
||||
pub mod menu_bar;
|
||||
pub mod modal;
|
||||
@ -160,35 +161,6 @@ impl WidgetInner {
|
||||
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);
|
||||
@ -233,6 +205,35 @@ pub trait Widget {
|
||||
fn padding_height(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
fn render<C, R>(&self, canvas: &mut C, renderer: &mut R, context: &RenderContext)
|
||||
where
|
||||
C: CanvasAccess,
|
||||
R: Renderer + CharacterSizeManager,
|
||||
{
|
||||
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: Renderer + CharacterSizeManager,
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -4,11 +4,11 @@ use crate::ui::filesystem::directory::DirectoryView;
|
||||
use crate::ui::horizontal_scroll_bar::HorizontalScrollBar;
|
||||
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 crate::ui::{CanvasAccess, Widget};
|
||||
use rider_config::config::Config;
|
||||
use rider_config::ConfigHolder;
|
||||
use sdl2::pixels::Color;
|
||||
|
Loading…
Reference in New Issue
Block a user