Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrated Image and ProgressBar widgets #2

Merged
merged 1 commit into from
Sep 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ mod row;

pub mod button;
pub mod checkbox;
pub mod image;
pub mod progress_bar;
pub mod radio;
pub mod slider;
pub mod text;

pub use button::Button;
pub use checkbox::Checkbox;
pub use image::Image;
pub use column::Column;
pub use progress_bar::ProgressBar;
pub use radio::Radio;
pub use row::Row;
pub use slider::Slider;
Expand Down
139 changes: 139 additions & 0 deletions src/widget/image.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
//! Displays image to your users.

use crate::{
Style, Node, Element, MouseCursor, Layout, Hasher, Widget,
Rectangle, Point,
};

use std::hash::Hash;

/// A widget that displays an image.
///
/// It implements [`Widget`] when the associated [`core::Renderer`] implements
/// the [`image::Renderer`] trait.
///
/// [`Widget`]: ../../core/trait.Widget.html
/// [`core::Renderer`]: ../../core/trait.Renderer.html
/// [`image::Renderer`]: trait.Renderer.html
/// # Example
///
/// ```
/// use iced::Image;
///
/// let image = Image::new("image");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would probably write something like:

# let my_image_handle = String::from("some_handle"); // This line will be hidden in docs
let image = Image::new(my_image_handle);

That way, we remark the fact that the handle is generic.

/// ```
pub struct Image<I> {
image: I,
source: Option<Rectangle<u16>>,
style: Style,
}

impl<I> std::fmt::Debug for Image<I> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Image")
.field("source", &self.source)
.field("style", &self.style)
.finish()
}
}

impl<I> Image<I> {
/// Creates a new [`Image`] with given image handle.
///
/// [`Image`]: struct.Image.html
pub fn new(image: &I) -> Self where I: Clone {
Image {
image: image.clone(),
source: None,
style: Style::default().fill_width().fill_height(),
}
}

/// Sets the portion of the [`Image`] that we want to draw.
///
/// [`Image`]: struct.Image.html
pub fn clip(mut self, source: Rectangle<u16>) -> Self {
self.source = Some(source);
self
}

/// Sets the width of the [`Image`] boundaries in pixels.
///
/// [`Image`]: struct.Image.html
pub fn width(mut self, width: u32) -> Self {
self.style = self.style.width(width);
self
}

/// Sets the height of the [`Image`] boundaries in pixels.
///
/// [`Image`]: struct.Image.html
pub fn height(mut self, height: u32) -> Self {
self.style = self.style.height(height);
self
}
}

impl<I, Message, Renderer> Widget<Message, Renderer> for Image<I>
where
Renderer: self::Renderer<I>,
I: Clone,
{
fn node(&self, _renderer: &Renderer) -> Node {
Node::new(self.style)
}

fn draw(
&self,
renderer: &mut Renderer,
layout: Layout<'_>,
_cursor_position: Point,
) -> MouseCursor {
renderer.draw(
layout.bounds(),
self.image.clone(),
self.source,
);

MouseCursor::OutOfBounds
}

fn hash(&self, state: &mut Hasher) {
self.style.hash(state);
}
}

/// The renderer of a [`Image`].
///
/// Your [`core::Renderer`] will need to implement this trait before being
/// able to use a [`Image`] in your user interface.
///
/// [`Image`]: struct.Image.html
/// [`core::Renderer`]: ../../core/trait.Renderer.html
pub trait Renderer<I> {
/// Draws a [`Image`].
///
/// It receives:
/// * the bounds of the [`Image`]
/// * the handle of the loaded [`Image`]
/// * the portion of the image that we wants to draw,
/// if not specified, draw entire image
///
/// [`Image`]: struct.Image.html
fn draw(
&mut self,
bounds: Rectangle<f32>,
image: I,
source: Option<Rectangle<u16>>,
);
}

impl<'a, I, Message, Renderer> From<Image<I>> for Element<'a, Message, Renderer>
where
Renderer: self::Renderer<I>,
I: Clone + 'a,
{
fn from(image: Image<I>) -> Element<'a, Message, Renderer> {
Element::new(image)
}
}
117 changes: 117 additions & 0 deletions src/widget/progress_bar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
//! Displays action progress to your users.

use crate::{
Style, Node, Element, MouseCursor, Layout, Hasher, Widget,
Point, Rectangle,
};

use std::hash::Hash;

/// A widget that displays a progress of an action.
///
/// It implements [`Widget`] when the associated [`core::Renderer`] implements
/// the [`button::Renderer`] trait.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

progress_bar::Renderer here.

///
/// [`Widget`]: ../../core/trait.Widget.html
/// [`core::Renderer`]: ../../core/trait.Renderer.html
/// [`progress_bar::Renderer`]: trait.Renderer.html
/// # Example
///
/// ```
/// use coffee::ui::ProgressBar;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be iced::ProgressBar.

///
/// let progress = 0.75;
///
/// ProgressBar::new(progress);
/// ```
#[derive(Debug)]
pub struct ProgressBar {
progress: f32,
style: Style,
}

impl ProgressBar {
/// Creates a new [`ProgressBar`] with given progress.
///
/// [`ProgressBar`]: struct.ProgressBar.html
pub fn new(progress: f32) -> Self {
ProgressBar {
progress,
style: Style::default().fill_width(),
}
}

/// Sets the width of the [`ProgressBar`] in pixels.
///
/// [`ProgressBar`]: struct.ProgressBar.html
pub fn width(mut self, width: u32) -> Self {
self.style = self.style.width(width);
self
}

/// Makes the [`ProgressBar`] fill the horizontal space of its container.
///
/// [`ProgressBar`]: struct.ProgressBar.html
pub fn fill_width(mut self) -> Self {
self.style = self.style.fill_width();
self
}
}

impl<Message, Renderer> Widget<Message, Renderer> for ProgressBar
where
Renderer: self::Renderer
{
fn node(&self, _renderer: &Renderer) -> Node {
Node::new(self.style.height(50))
}

fn draw(
&self,
renderer: &mut Renderer,
layout: Layout<'_>,
_cursor_position: Point,
) -> MouseCursor {
renderer.draw(
layout.bounds(),
self.progress,
);

MouseCursor::OutOfBounds
}

fn hash(&self, state: &mut Hasher) {
self.style.hash(state);
}
}

/// The renderer of a [`ProgressBar`].
///
/// Your [`core::Renderer`] will need to implement this trait before being
/// able to use a [`ProgressBar`] in your user interface.
///
/// [`ProgressBar`]: struct.ProgressBar.html
/// [`core::Renderer`]: ../../core/trait.Renderer.html
pub trait Renderer {
/// Draws a [`ProgressBar`].
///
/// It receives:
/// * the bounds of the [`ProgressBar`]
/// * the progress of the [`ProgressBar`]
///
/// [`ProgressBar`]: struct.ProgressBar.html
fn draw(
&mut self,
bounds: Rectangle<f32>,
progress: f32,
);
}

impl<'a, Message, Renderer> From<ProgressBar> for Element<'a, Message, Renderer>
where
Renderer: self::Renderer,
{
fn from(progress_bar: ProgressBar) -> Element<'a, Message, Renderer> {
Element::new(progress_bar)
}
}