rs-calendar/src/main.rs

251 lines
6.4 KiB
Rust

//! Simple calendar applications.
mod ui;
mod model;
use ui::calendar;
use model::events::EventsCollection;
use model::ical_bridge::load_calendar;
use chrono::{Datelike, NaiveDate, Months, Utc};
use calendar::{CalendarMonthView, CalendarYearView, CalendarParams };
use std::path;
use clap;
use clap::Parser;
use iced::{
alignment,
executor,
Alignment, Application, Command,
Element, Length, Settings,
};
use iced::widget::{
Column, Row,
Container,
Button, Text,
pick_list,
};
//use iced::button;
use iced::theme;
#[cfg(feature = "tracing")]
extern crate lttng_ust;
#[cfg(feature = "tracing")]
use lttng_ust::import_tracepoints;
#[cfg(feature = "tracing")]
import_tracepoints!(
concat!(env!("OUT_DIR"), "/tracepoints.rs"),
tracepoints
);
struct CalendarFlags {
calendar_paths: std::vec::Vec<path::PathBuf>,
}
#[derive(Parser, Debug)]
#[command(version, about)]
struct CliArgs {
files: Vec<String>,
}
pub fn main() -> iced::Result {
let args = CliArgs::parse();
let calendar_files = args.files.iter().map(|arg| path::PathBuf::from(arg)).collect();
//let calendar_files = vec![path::PathBuf::from("/home/fab/calendario.ics")];
CalendarApp::run(Settings::with_flags(CalendarFlags {calendar_paths: calendar_files}))
}
#[derive(Default)]
struct CalendarApp {
month: NaiveDate,
controls: Controls,
events: EventsCollection,
}
#[derive(Debug, Clone, Copy)]
enum Message {
NextMonth,
PrevMonth,
NextYear,
PrevYear,
ViewModeSelected(ViewMode),
}
//#[derive(Default)]
struct Controls {
mode: Option<ViewMode>,
}
impl Default for Controls {
fn default() -> Controls {
Controls {
mode : Some(ViewMode::Year)
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ViewMode {
Month,
Year,
}
impl std::fmt::Display for ViewMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
ViewMode::Month => "Month",
ViewMode::Year => "Year",
}
)
}
}
impl Controls {
const MODES : [ViewMode; 2] = [ViewMode::Month, ViewMode::Year];
fn view<'a>(&'a self, month_name: &'a str, year: i32) -> Element<Message> {
let description = match self.mode {
Some(ViewMode::Month) => month_name,
_ => ""
};
Row::new()
.align_items(Alignment::Center)
.padding(5)
.spacing(10)
.push(
pick_list(
&Controls::MODES[..],
self.mode,
Message::ViewModeSelected,
).placeholder("mode")
)
.push(
Button::new(Text::new("<"))
.on_press(self.get_msg_prev())
.style(theme::Button::Secondary),
)
.push(
Button::new(Text::new(">"))
.on_press(self.get_msg_next())
.style(theme::Button::Secondary),
)
.push(
Text::new(description)
.width(Length::Fill)
.horizontal_alignment(alignment::Horizontal::Left)
.size(40),
)
.push(
Text::new(year.to_string())
.width(Length::Fill)
.horizontal_alignment(alignment::Horizontal::Right)
.size(40),
)
.into()
}
fn get_msg_next(&self) -> Message {
match self.mode {
Some(ViewMode::Month) => Message::NextMonth,
_ => Message::NextYear
}
}
fn get_msg_prev(&self) -> Message {
match self.mode {
Some(ViewMode::Month) => Message::PrevMonth,
_ => Message::PrevYear
}
}
}
impl Application for CalendarApp {
type Executor = executor::Default;
type Message = Message;
type Theme = iced::Theme;
type Flags = CalendarFlags;
fn new(flags: Self::Flags) -> (Self, Command<Message>) {
let month = Utc::now().date_naive();
let mut ret = (CalendarApp {
month,
events: EventsCollection::new(),
..CalendarApp::default()
}, Command::none());
for calendar_path in flags.calendar_paths {
load_calendar(&calendar_path, &mut ret.0.events);
}
ret
}
fn title(&self) -> String {
String::from("Calendar")
}
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::PrevMonth => {
self.month = self.month - Months::new(1);
}
Message::NextMonth => {
self.month = self.month + Months::new(1);
}
Message::PrevYear => {
self.month = self.month - Months::new(12);
}
Message::NextYear => {
self.month = self.month + Months::new(12);
}
Message::ViewModeSelected(mode) => {
self.controls.mode = Some(mode);
}
}
Command::none()
}
fn view(&self) -> Element<Message> {
#[cfg(feature = "tracing")]
tracepoints::calendar::view_entry();
const MONTH_NAMES: [&str;12] = [
"gennaio",
"febbraio",
"marzo",
"aprile",
"maggio",
"giugno",
"luglio",
"agosto",
"settembre",
"ottobre",
"novembre",
"dicembre",
];
let mut content = Column::new()
.align_items(Alignment::Center)
.push(self.controls.view(MONTH_NAMES[self.month.month0() as usize], self.month.year()))
;
match self.controls.mode {
Some(ViewMode::Year) => content = content.push(CalendarYearView::new(&CalendarParams::new(), self.month, &self.events)),
Some(ViewMode::Month) | None => content = content.push(CalendarMonthView::new(&CalendarParams::new(), self.month, &self.events)),
};
let container = Container::new(content)
.width(Length::Fill)
.height(Length::Fill)
.center_x()
.center_y()
.into();
#[cfg(feature = "tracing")]
tracepoints::calendar::view_exit();
container
}
}