I created a calendar with the iced gui crate. How can I make this a widget, so I can spawn multiple calendars?
I couldn't understand the examples as it doesn't use other elements, it renders a circle or a canvas and not another widget like buttons and text.
/// # How the `iced` library works:
///
/// Iced expects the following structure:
///
/// - State: the current data of the application
/// - Messages: events that trigger the update of the state
/// - View logic: widgets or components
/// - Update logic: how the message operate on the state
// States for the elemtns
use iced::{button};
// The elements to use
use iced::{Element, Button, Column, Row, Text, Container, Rule};
// Styling options
use iced::{HorizontalAlignment, Align, Length};
// The application settings
use iced::{Settings, Application, executor, Command};
use time;
/// This is the state of the application. In here we store the current count.
struct Calendar {
day: u8,
month: u8,
year: i32,
// Buttons handler that manipulate the counter
// this is the local state of the buttons
previous_month_button: button::State,
next_month_button: button::State,
}
/// The events that will trigger changes on the ui or on the data
#[derive(Debug, Clone, Copy)]
pub enum Message {
PreviousMonth,
NextMonth,
}
impl Application for Calendar {
type Message = Message;
type Executor = executor::Default;
type Flags = ();
/// Default settings when starting the GUI
fn new(_flags: ()) -> (Self, Command<Message>) {
let now = time::Date::today();
let day = now.day();
let month = now.month();
let year = now.year();
(
Self {
day,
month,
year,
previous_month_button: Default::default(),
next_month_button: Default::default()
},
Command::none()
)
}
/// The title of the window
fn title(&self) -> String {
String::from("Calendar")
}
// The view logic where we define the gui
fn view(&mut self) -> Element<Message> {
let days = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
let months = vec!["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"];
let month = Text::new(months[(self.month as usize) - 1])
.size(32)
.color([0.6, 0.6, 0.6]);
let year = Text::new(self.year.to_string())
.size(32)
.color([0.6, 0.6, 0.6]);
// Create a header for the weekdays name
let header: Row<Message> = days
.iter()
.enumerate()
.fold(Row::new().spacing(25), |row, (_i, day)| {
row.push(
Column::new()
.push(
Text::new(day.clone().to_string())
.size(25)
)
.align_items(Align::Center)
.width(Length::Fill)
.max_width(75)
)
});
let mut calendar = Column::new()
// Push the calendar month and year header
.push(
Row::new()
.push(
Row::new()
.push(month)
.push(year)
.spacing(12)
.width(Length::from(250))
)
.push(
Button::new(&mut self.previous_month_button,
Text::new("<")
.horizontal_alignment(HorizontalAlignment::Center)
)
.width(Length::from(65))
.on_press(Message::PreviousMonth)
)
.push(
Button::new(&mut self.next_month_button,
Text::new(">")
.horizontal_alignment(HorizontalAlignment::Center)
)
.width(Length::from(65))
.on_press(Message::NextMonth)
)
.padding(12)
.spacing(12)
.width(Length::Fill)
)
// Push the weekday header
.push(header)
.align_items(Align::Center);
// Check the starting day of the selected month
let month_start_day = time::Date::try_from_ymd(self.year, self.month, 1)
.unwrap()
.weekday()
.number_from_sunday();
// Keep track of the current day
let mut day_count = 0;
// Iterate over 6 weeks - months won't ocupy more than 6 weeks
for _ in 0..6 {
let mut week = Row::new();
// Iterate over all the weekdays, starting from sunday
for weekday_num in 1..8 {
if month_start_day == weekday_num || day_count >= 1
{
day_count += 1;
if time::Date::try_from_ymd(self.year, self.month, day_count).is_ok() {
week = week.push(
Column::new()
.push(
Text::new(day_count.to_string())
)
.align_items(Align::Center)
.width(Length::Fill)
)
.spacing(25);
} else {
week = week.push(
Column::new()
.push(
Text::new("")
)
.align_items(Align::Center)
.width(Length::Fill)
)
.spacing(25);
}
} else {
week = week.push(
Column::new()
.push(
Text::new("")
)
.align_items(Align::Center)
.width(Length::Fill)
)
.spacing(25);
}
}
calendar = calendar.push(week);
}
let calendar_container = Container::new(calendar)
.width(Length::Fill)
.height(Length::Fill)
.center_x()
.center_y()
.into();
calendar_container
}
// The update logic
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::PreviousMonth => {
if self.month <= 1 {
self.month = 12;
self.year -= 1;
} else {
self.month -= 1
}
Command::none()
}
Message::NextMonth => {
if self.month >= 12 {
self.month = 1;
self.year += 1;
} else {
self.month += 1;
}
Command::none()
}
}
}
}
fn main() {
Calendar::run(Settings::default()).unwrap();
}