Skip to content

Commit

Permalink
upgrade time picker to latest iced style changes
Browse files Browse the repository at this point in the history
  • Loading branch information
genusistimelord committed May 28, 2024
1 parent 64deedb commit 72d466e
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 249 deletions.
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ default = [
"grid",
#"tab_bar",
#"tabs",
#"time_picker",
"time_picker",
"slide_bar",
"wrap",
"selection_list",
Expand Down Expand Up @@ -85,7 +85,7 @@ members = [
"examples/grid",
#"examples/tab_bar",
#"examples/tabs",
#"examples/time_picker",
"examples/time_picker",
"examples/sliderbar",
"examples/wrap",
"examples/selection_list",
Expand Down
143 changes: 44 additions & 99 deletions examples/time_picker/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
use iced::{
alignment, font,
widget::{container, text, Button, Container, Row, Text},
Alignment, Application, Command, Element, Length, Settings, Theme,
widget::{Button, Container, Row, Text},
Alignment, Element, Length,
};
use iced_aw::{time_picker::Time, TimePicker};

fn main() -> iced::Result {
TimePickerExample::run(Settings::default())
iced::program(
"TimePicker example",
TimePickerExample::update,
TimePickerExample::view,
)
.font(iced_aw::BOOTSTRAP_FONT_BYTES)
.run()
}

#[derive(Clone, Debug)]
Expand All @@ -15,113 +20,53 @@ enum Message {
ChooseTime,
SubmitTime(Time),
CancelTime,
#[allow(dead_code)]
Loaded(Result<(), String>),
FontLoaded(Result<(), font::Error>),
}

#[derive(Debug)]
enum TimePickerExample {
Loading,
Loaded(State),
}

#[derive(Debug)]
struct State {
#[derive(Debug, Default)]
struct TimePickerExample {
time: Time,
show_picker: bool,
}

async fn load() -> Result<(), String> {
Ok(())
}

impl Application for TimePickerExample {
type Message = Message;
type Theme = Theme;
type Executor = iced::executor::Default;
type Flags = ();

fn new(_flags: ()) -> (TimePickerExample, Command<Message>) {
(
TimePickerExample::Loading,
Command::batch(vec![
font::load(iced_aw::BOOTSTRAP_FONT_BYTES).map(Message::FontLoaded),
Command::perform(load(), Message::Loaded),
]),
)
}

fn title(&self) -> String {
String::from("TimePicker example")
}

fn update(&mut self, message: Self::Message) -> Command<Message> {
match self {
TimePickerExample::Loading => {
if let Message::Loaded(_) = message {
*self = TimePickerExample::Loaded(State {
time: Time::now_hm(true),
show_picker: false,
})
}
impl TimePickerExample {
fn update(&mut self, message: Message) {
match message {
Message::ChooseTime => {
self.show_picker = true;
}
Message::SubmitTime(time) => {
self.time = time;
self.show_picker = false;
}
Message::CancelTime => {
self.show_picker = false;
}
TimePickerExample::Loaded(state) => match message {
Message::ChooseTime => {
state.show_picker = true;
}
Message::SubmitTime(time) => {
state.time = time;
state.show_picker = false;
}
Message::CancelTime => {
state.show_picker = false;
}
_ => {}
},
}

Command::none()
}

fn view(&self) -> Element<'_, Self::Message> {
match self {
TimePickerExample::Loading => container(
text("Loading...")
.horizontal_alignment(alignment::Horizontal::Center)
.size(50),
)
.width(Length::Fill)
.height(Length::Fill)
.center_y()
.center_x()
.into(),
TimePickerExample::Loaded(state) => {
let but = Button::new(Text::new("Set Time")).on_press(Message::ChooseTime);
fn view(&self) -> Element<'_, Message> {
let but = Button::new(Text::new("Set Time")).on_press(Message::ChooseTime);

let timepicker = TimePicker::new(
state.show_picker,
state.time,
but,
Message::CancelTime,
Message::SubmitTime,
)
//.show_seconds()
.use_24h();
let timepicker = TimePicker::new(
self.show_picker,
self.time,
but,
Message::CancelTime,
Message::SubmitTime,
)
.use_24h();

let row = Row::new()
.align_items(Alignment::Center)
.spacing(10)
.push(timepicker)
.push(Text::new(format!("Time: {}", state.time)));
let row = Row::new()
.align_items(Alignment::Center)
.spacing(10)
.push(timepicker)
.push(Text::new(format!("Time: {}", self.time)));

Container::new(row)
.center_x()
.center_y()
.width(Length::Fill)
.height(Length::Fill)
.into()
}
}
Container::new(row)
.center_x(Length::Fill)
.center_y(Length::Fill)
.width(Length::Fill)
.height(Length::Fill)
.into()
}
}
10 changes: 10 additions & 0 deletions src/core/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ pub enum Time {
},
}

impl Default for Time {
fn default() -> Self {
Self::Hm {
hour: 1,
minute: 0,
period: Period::Am,
}
}
}

impl Time {
/// Creates a new time (hours, minutes) from the current timestamp.
#[must_use]
Expand Down
2 changes: 0 additions & 2 deletions src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ pub use tab_bar::TabBarStyles;

#[cfg(feature = "time_picker")]
pub mod time_picker;
#[cfg(feature = "time_picker")]
pub use time_picker::TimePickerStyle;

#[cfg(feature = "number_input")]
pub mod number_input;
Expand Down
142 changes: 51 additions & 91 deletions src/style/time_picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
//!
//! *This API requires the following crate features to be activated: `time_picker`*
#![allow(clippy::doc_markdown)]
use std::rc::Rc;

use super::{Status, StyleFn};
use iced::{Background, Color, Theme};

/// The appearance of a [`TimePicker`](crate::widgets::TimePicker).
/// The style of a [`TimePicker`](crate::widgets::TimePicker).
#[derive(Clone, Copy, Debug)]
pub struct Appearance {
pub struct Style {
/// The background of the [`TimePicker`](crate::widgets::TimePicker).
pub background: Background,

Expand Down Expand Up @@ -45,103 +44,64 @@ pub struct Appearance {
pub clock_hand_width: f32,
}

/// The appearance of a [`TimePicker`](crate::widgets::TimePicker).
pub trait StyleSheet {
/// The style type of this stylesheet
type Style: Default + Clone;
/// The normal appearance of a [`TimePicker`](crate::widgets::TimePicker).
fn active(&self, style: &Self::Style) -> Appearance;

/// The appearance when something is selected of the
/// [`TimePicker`](crate::widgets::TimePicker)
fn selected(&self, style: &Self::Style) -> Appearance;
/// The Catalog of a [`TimePicker`](crate::widgets::TimePicker).
pub trait Catalog {
///Style for the trait to use.
type Class<'a>;

/// The appearance when something is hovered of the
/// [`TimePicker`](crate::widgets::TimePicker).
fn hovered(&self, style: &Self::Style) -> Appearance;
/// The default class produced by the [`Catalog`].
fn default<'a>() -> Self::Class<'a>;

/// The appearance when something is focused of the
/// [`TimePicker`](crate::widgets::TimePicker).
fn focused(&self, style: &Self::Style) -> Appearance;
/// The [`Style`] of a class with the given status.
fn style(&self, class: &Self::Class<'_>, status: Status) -> Style;
}

/// The style appearance of the [`TimePicker`](crate::widgets::TimePicker)
#[derive(Clone, Default)]
#[allow(missing_docs, clippy::missing_docs_in_private_items)]
pub enum TimePickerStyle {
#[default]
Default,
Custom(Rc<dyn StyleSheet<Style = Theme>>),
}
impl Catalog for Theme {
type Class<'a> = StyleFn<'a, Self, Style>;

impl TimePickerStyle {
/// Creates a custom [`TimePickerStyle`] style variant.
pub fn custom(style_sheet: impl StyleSheet<Style = Theme> + 'static) -> Self {
Self::Custom(Rc::new(style_sheet))
fn default<'a>() -> Self::Class<'a> {
Box::new(primary)
}
}

impl StyleSheet for Theme {
type Style = TimePickerStyle;

fn active(&self, style: &Self::Style) -> Appearance {
if let TimePickerStyle::Custom(custom) = style {
return custom.active(self);
}

let palette = self.extended_palette();
let foreground = self.palette();

Appearance {
background: palette.background.base.color.into(),
border_radius: 15.0,
border_width: 1.0,
border_color: foreground.text,
text_color: foreground.text,
clock_number_color: foreground.text,
clock_number_background: palette.background.base.color,
clock_dots_color: [0.87, 0.87, 0.87].into(),
clock_hand_color: [0.87, 0.87, 0.87].into(),
clock_hand_width: 3.0,
}
}

fn selected(&self, style: &Self::Style) -> Appearance {
if let TimePickerStyle::Custom(custom) = style {
return custom.selected(self);
}

let palette = self.extended_palette();

Appearance {
clock_number_color: palette.primary.strong.text,
clock_number_background: palette.primary.strong.color,
..self.active(style)
}
fn style(&self, class: &Self::Class<'_>, status: Status) -> Style {
class(self, status)
}
}

fn hovered(&self, style: &Self::Style) -> Appearance {
if let TimePickerStyle::Custom(custom) = style {
return custom.hovered(self);
}

let palette = self.extended_palette();

Appearance {
/// The primary theme of a [`TimePicker`](crate::widgets::TimePicker).
#[must_use]
pub fn primary(theme: &Theme, status: Status) -> Style {
let palette = theme.extended_palette();
let foreground = theme.palette();

let base = Style {
background: palette.background.base.color.into(),
border_radius: 15.0,
border_width: 1.0,
border_color: foreground.text,
text_color: foreground.text,
clock_number_color: foreground.text,
clock_number_background: palette.background.base.color,
clock_dots_color: [0.87, 0.87, 0.87].into(),
clock_hand_color: [0.87, 0.87, 0.87].into(),
clock_hand_width: 3.0,
};

match status {
Status::Focused => Style {
border_color: Color::from_rgb(0.5, 0.5, 0.5),
..base
},
Status::Hovered => Style {
clock_number_color: palette.primary.weak.text,
clock_number_background: palette.primary.weak.color,
..self.active(style)
}
}

fn focused(&self, style: &Self::Style) -> Appearance {
if let TimePickerStyle::Custom(custom) = style {
return custom.focused(self);
}

Appearance {
border_color: Color::from_rgb(0.5, 0.5, 0.5),
..self.active(style)
}
..base
},
Status::Selected => Style {
clock_number_color: palette.primary.strong.text,
clock_number_background: palette.primary.strong.color,
..base
},
_ => base,
}
}
Loading

0 comments on commit 72d466e

Please sign in to comment.