Adapt to new iced version, show events in month view

Signed-off-by: Fabrizio Iannetti <fabrizio.iannetti@gmail.com>
This commit is contained in:
Fabrizio Iannetti 2023-05-21 13:41:16 +02:00
parent c805cc94d3
commit ae13e98388
6 changed files with 1491 additions and 640 deletions

1865
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -9,8 +9,7 @@ tracing = ["dep:lttng-ust"]
[dependencies]
#iced = "0.4.2"
#iced_native = "0.5.1"
iced = { path = "../iced" }
iced_native = { path = "../iced/native" }
iced = { path = "../iced", features = ["advanced"] }
chrono = "0.4"
lttng-ust = { version = "0.1.0", optional = true }

View File

@ -9,6 +9,7 @@ use chrono::{Datelike, NaiveDate, Months, Utc};
use calendar::{CalendarMonthView, CalendarYearView, CalendarParams };
use iced::{
alignment,
executor,
Alignment, Application, Command,
Element, Length, Settings,
@ -100,13 +101,13 @@ impl Controls {
.push(
Text::new(month_name)
.width(Length::Fill)
.horizontal_alignment(iced_native::alignment::Horizontal::Left)
.horizontal_alignment(alignment::Horizontal::Left)
.size(40),
)
.push(
Text::new(year.to_string())
.width(Length::Fill)
.horizontal_alignment(iced_native::alignment::Horizontal::Right)
.horizontal_alignment(alignment::Horizontal::Right)
.size(40),
)
.into()
@ -169,7 +170,7 @@ impl Application for CalendarApp {
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)),
Some(ViewMode::Month) | None => content = content.push(CalendarMonthView::new(&CalendarParams::new(), self.month, &self.events)),
};
Container::new(content)

View File

@ -36,14 +36,14 @@ impl EventsCollection {
// TODO: hard-coded events
events: vec![
Event {
text: String::from("ev_1"),
begin: NaiveDate::from_ymd_opt(2023, 01, 15).unwrap(),
end: NaiveDate::from_ymd_opt(2023, 01, 16).unwrap(),
text: String::from("pentecoste"),
begin: NaiveDate::from_ymd_opt(2023, 05, 30).unwrap(),
end: NaiveDate::from_ymd_opt(2023, 06, 09).unwrap(),
},
Event {
text: String::from("ev_2"),
begin: NaiveDate::from_ymd_opt(2023, 01, 16).unwrap(),
end: NaiveDate::from_ymd_opt(2023, 01, 17).unwrap(),
text: String::from("estate"),
begin: NaiveDate::from_ymd_opt(2023, 07, 31).unwrap(),
end: NaiveDate::from_ymd_opt(2023, 09, 11).unwrap(),
},
],
}
@ -57,6 +57,16 @@ impl EventsCollection {
}
None
}
pub fn for_day(&self, day: NaiveDate) -> Vec<Event> {
let mut events_in_day = Vec::new();
for ev_day in &self.events {
if ev_day.is_in_day(day) {
events_in_day.push(ev_day.clone());
}
}
events_in_day
}
}
impl Default for EventsCollection {

View File

@ -19,7 +19,7 @@ pub struct CellGrid {
width: f32,
height: f32,
// size fo the grid, in number of cells
// size of the grid, in number of cells
num_x: u32,
num_y: u32,
@ -46,6 +46,10 @@ impl CellGrid {
}
}
pub fn rows(&self) -> Self {
CellGrid::new(self.x, self.y, self.width, self.height, 1, self.num_y)
}
fn compute_cell(&mut self) -> () {
self.curr.pos_x = self.pos_x;
self.curr.pos_y = self.pos_y;

View File

@ -8,12 +8,10 @@
// if you wish to, by creating your own `Renderer` trait, which could be
// implemented by `iced_wgpu` and other renderers.
use iced_native::layout::{self, Layout};
use iced_native::renderer;
use iced_native::{Color, Element, Length, Point, Rectangle, Widget};
use iced_native::text;
use iced_native::alignment;
use iced_native::widget::Tree;
use iced::advanced::{layout, renderer};
use iced::advanced::widget::{Tree, Widget};
use iced::{Color, Element, Length, Point, Rectangle, alignment};
use iced::advanced::text::{self, Text, LineHeight, Shaping};
use chrono::{NaiveDate, Datelike, Duration, Local};
use super::basics::CellGrid;
use crate::model::events::EventsCollection;
@ -85,21 +83,102 @@ impl CalendarParams {
//-------------------------------------------------------------------------
pub struct CalendarMonthView {
fn render_events_in_day(
params: &CalendarParams,
renderer: &mut impl text::Renderer,
current_day: NaiveDate,
day_bounds: Rectangle,
font_size: f32,
fg: Color,
content: &str,
events: &EventsCollection
) {
// render events, if enough space
let day_text_size = renderer.measure(
content,
font_size,
LineHeight::default(),
renderer.default_font(),
day_bounds.size(),
Shaping::default());
let ev_height = params.ev_height;
let mut ev_y: f32 = 0.0;
let y = day_bounds.y + params.day_text_margin;
for ev_day in events.for_day(current_day) {
if day_bounds.height - day_text_size.1 > ev_y + ev_height {
let ev_bounds = Rectangle {
y: y + ev_y + day_text_size.1,
height: ev_height,
..day_bounds
};
renderer.fill_quad(renderer::Quad {
bounds: ev_bounds,
border_radius: 0.0.into(),
border_width: 1.0,
border_color: params.day_other_month_fg,
},
params.ev_bg);
renderer.fill_text(Text {
content: ev_day.text.as_str(),
bounds: ev_bounds,
size: params.ev_fontsize,
line_height: LineHeight::default(),
color: fg,
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::default(),
});
ev_y += ev_height
}
}
if day_bounds.height - day_text_size.1 > ev_height {
if let Some(ev_day) = events.is_any_in_day(current_day) {
let ev_bounds = Rectangle {
y: y + day_text_size.1,
height: ev_height,
..day_bounds
};
renderer.fill_quad(renderer::Quad {
bounds: ev_bounds,
border_radius: 0.0.into(),
border_width: 1.0,
border_color: params.day_other_month_fg,
},
params.ev_bg);
renderer.fill_text(Text {
content: ev_day.text.as_str(),
bounds: ev_bounds,
size: params.ev_fontsize,
line_height: LineHeight::default(),
color: fg,
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::default(),
});
}
}
}
//-------------------------------------------------------------------------
pub struct CalendarMonthView<'a> {
first_day: NaiveDate,
first_day_in_view: NaiveDate,
params: CalendarParams,
week_column_width: f32,
week_column_font_size: f32,
events: &'a EventsCollection,
}
impl CalendarMonthView {
pub fn new(params: &CalendarParams, day: NaiveDate) -> Self {
impl<'a> CalendarMonthView<'a> {
pub fn new(params: &CalendarParams, day: NaiveDate, events: &'a EventsCollection) -> Self {
// first day of the month
let first_day = if day.day() == 1 {
day
} else {
NaiveDate::from_ymd(day.year(), day.month(), 1)
NaiveDate::from_ymd_opt(day.year(), day.month(), 1).unwrap()
};
// weekday on first day of the month
@ -114,6 +193,7 @@ impl CalendarMonthView {
params: params.clone(),
week_column_width: 30.0,
week_column_font_size: 18.0,
events,
}
}
@ -122,7 +202,7 @@ impl CalendarMonthView {
let first_day = if day.day() == 1 {
day
} else {
NaiveDate::from_ymd(day.year(), day.month(), 1)
NaiveDate::from_ymd_opt(day.year(), day.month(), 1).unwrap()
};
// weekday on first day of the month
@ -178,14 +258,16 @@ impl CalendarMonthView {
// color of text
let fg = self.params.header_fg;
renderer.fill_text(text::Text {
renderer.fill_text(Text {
content : t,
size: font_size,
bounds,
size: font_size,
line_height: LineHeight::default(),
color: fg,
font: Default::default(),
horizontal_alignment: alignment::Horizontal::Left,
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Right,
vertical_alignment: alignment::Vertical::Center,
shaping: Shaping::default(),
});
}
}
@ -211,18 +293,20 @@ impl CalendarMonthView {
day += Duration::weeks(1);
// render week cell text
renderer.fill_text(text::Text {
renderer.fill_text(Text {
content : &(week_of_first_day_of_month).to_string(),
size: self.week_column_font_size,
bounds: Rectangle {
x: day_bounds.center_x(),
y: day_bounds.y,
..day_bounds
},
size: self.week_column_font_size,
line_height: LineHeight::default(),
color: self.params.day_fg,
font: Default::default(),
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Center,
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::default(),
});
}
}
@ -258,7 +342,7 @@ impl CalendarMonthView {
};
// background color of the day cell
let bg_color = if current_day == Local::today().naive_local() {
let bg_color = if current_day == Local::now().date_naive() {
self.params.day_today_bg
} else if current_day.weekday().num_days_from_monday() > 4 {
self.params.day_weekend_bg
@ -279,22 +363,36 @@ impl CalendarMonthView {
bg_color);
// render day cell text
renderer.fill_text(text::Text {
renderer.fill_text(Text {
content,
size: font_size,
bounds: Rectangle {x, y, ..day_bounds},
size: font_size,
line_height: LineHeight::default(),
color: fg,
font: Default::default(),
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::default()
});
current_day = current_day.succ();
render_events_in_day(
&self.params,
renderer,
current_day,
day_bounds,
font_size,
fg,
content,
self.events
);
current_day = current_day.succ_opt().unwrap();
}
}
} // CalendarMonthView
impl<Message, Renderer> Widget<Message, Renderer> for CalendarMonthView
impl<Message, Renderer> Widget<Message, Renderer> for CalendarMonthView<'_>
where
Renderer: text::Renderer,
{
@ -320,7 +418,7 @@ where
renderer: &mut Renderer,
_theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
layout: layout::Layout<'_>,
_cursor_position: Point,
_viewport: &Rectangle,
) {
@ -359,11 +457,11 @@ where
}
}
impl<'a, Message, Renderer> From<CalendarMonthView> for Element<'a, Message, Renderer>
impl<'a, Message, Renderer> From<CalendarMonthView<'a>> for Element<'a, Message, Renderer>
where
Renderer: text::Renderer,
{
fn from(month_view: CalendarMonthView) -> Self {
fn from(month_view: CalendarMonthView<'a>) -> Self {
Self::new(month_view)
}
}
@ -382,7 +480,7 @@ pub struct CalendarYearView<'a> {
impl<'a> CalendarYearView<'a> {
pub fn new(params: &CalendarParams, day: NaiveDate, events: &'a EventsCollection) -> Self {
// first day of the year
let first_day = NaiveDate::from_ymd(day.year(), 1, 1);
let first_day = NaiveDate::from_ymd_opt(day.year(), 1, 1).unwrap();
// weekday on first day of the year
let weekday_on_first = first_day.weekday();
@ -402,7 +500,7 @@ impl<'a> CalendarYearView<'a> {
pub fn set_year(&mut self, day: NaiveDate) {
// first day of the year
self.first_day = NaiveDate::from_ymd(day.year(), 1, 1);
self.first_day = NaiveDate::from_ymd_opt(day.year(), 1, 1).unwrap();
// weekday on first day of the year
let weekday_on_first = self.first_day.weekday();
@ -474,14 +572,16 @@ impl<'a> CalendarYearView<'a> {
let x = bounds.x + self.params.day_text_margin;
let y = bounds.center_y();
renderer.fill_text(text::Text {
renderer.fill_text(Text {
content : t,
size: font_size,
bounds: Rectangle {x, y, ..bounds},
size: font_size,
line_height: LineHeight::default(),
color: fg,
font: Default::default(),
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Center,
shaping: Shaping::default(),
});
}
}
@ -504,18 +604,20 @@ impl<'a> CalendarYearView<'a> {
};
// render month name
renderer.fill_text(text::Text {
renderer.fill_text(Text {
content : MONTH_NAMES[month],
size: self.month_column_font_size,
bounds: Rectangle {
x: month_name_bounds.x + self.margin,
y: month_name_bounds.center_y(),
..month_name_bounds
},
size: self.month_column_font_size,
line_height: LineHeight::default(),
color: self.params.day_fg,
font: Default::default(),
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Center,
shaping: Shaping::default(),
});
}
}
@ -555,7 +657,7 @@ impl<'a> CalendarYearView<'a> {
let fg = self.params.day_fg;
// background color of the day cell
let bg_color = if current_day == Local::today().naive_local() {
let bg_color = if current_day == Local::now().date_naive() {
self.params.day_today_bg
} else if weekday > 4 {
self.params.day_weekend_bg
@ -576,44 +678,28 @@ impl<'a> CalendarYearView<'a> {
bg_color);
// render day cell text
renderer.fill_text(text::Text {
renderer.fill_text(Text {
content,
size: font_size,
bounds: Rectangle {x, y, ..day_bounds},
size: font_size,
line_height: LineHeight::default(),
color: fg,
font: Default::default(),
font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::default(),
});
// render events, if enough space
let day_text_size = renderer.measure(content, font_size, Default::default(), day_bounds.size());
let ev_height = self.params.ev_height;
if day_bounds.height - day_text_size.1 > ev_height {
if let Some(ev_day) = self.events.is_any_in_day(current_day) {
let ev_bounds = Rectangle {
y: y + day_text_size.1,
height: ev_height,
..day_bounds
};
renderer.fill_quad(renderer::Quad {
bounds: ev_bounds,
border_radius: 0.0.into(),
border_width: 1.0,
border_color: self.params.day_other_month_fg,
},
self.params.ev_bg);
renderer.fill_text(text::Text {
content: ev_day.text.as_str(),
size: self.params.ev_fontsize,
bounds: ev_bounds,
color: fg,
font: Default::default(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
});
}
}
render_events_in_day(
&self.params,
renderer,
current_day,
day_bounds,
font_size,
fg,
content,
self.events
);
}
}
}
@ -621,7 +707,11 @@ impl<'a> CalendarYearView<'a> {
fn compute_month_col_width(&self, renderer: &mut impl text::Renderer) -> f32 {
let mut max_max_font_width = 0.0;
for month_name in MONTH_NAMES {
let month_width = renderer.measure_width(month_name, self.month_column_font_size, Default::default());
let month_width = renderer.measure_width(
month_name,
self.month_column_font_size,
renderer.default_font(),
Shaping::default());
if month_width > max_max_font_width {
max_max_font_width = month_width;
}
@ -657,7 +747,7 @@ where
renderer: &mut Renderer,
_theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
layout: layout::Layout<'_>,
_cursor_position: Point,
_viewport: &Rectangle,
) {