More better
This commit is contained in:
+163
-108
@@ -3,8 +3,8 @@ use std::default::Default;
|
||||
use crate::{
|
||||
buffer::BufferView,
|
||||
color::Color,
|
||||
fonts::FontMap,
|
||||
event::Event,
|
||||
fonts::FontMap,
|
||||
widgets::{Geometry, Widget},
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@ use chrono::{Datelike, Local, NaiveDate};
|
||||
|
||||
pub struct Calendar {
|
||||
font: &'static str,
|
||||
month_font: &'static str,
|
||||
sections_x: i32,
|
||||
sections_y: i32,
|
||||
shown_sections_x: u32,
|
||||
@@ -19,22 +20,35 @@ pub struct Calendar {
|
||||
size: f32,
|
||||
dirty: bool,
|
||||
geometry: Geometry,
|
||||
year_width: u32,
|
||||
date_width: u32,
|
||||
day_width: u32,
|
||||
}
|
||||
|
||||
const DAY_FACTOR: f32 = 1.;
|
||||
const YEAR_FACTOR: f32 = 1.5;
|
||||
const MONTH_FACTOR: f32 = 2.;
|
||||
const DATE_FACTOR: f32 = 2.;
|
||||
const LINE_HEIGHT: f32 = 1.8;
|
||||
const DAY_FACTOR: f32 = 0.6;
|
||||
const YEAR_FACTOR: f32 = 0.75;
|
||||
const MONTH_FACTOR: f32 = 1.25;
|
||||
const DATE_FACTOR: f32 = 1.;
|
||||
|
||||
const LINE_HEIGHT: f32 = 0.85;
|
||||
|
||||
impl Calendar {
|
||||
pub fn new(fm: &mut FontMap, font: &'static str, size: f32, sections_x: i32, sections_y: i32) -> Calendar {
|
||||
fm.queue_font(font, size, "ADEFHIMNORSTUW");
|
||||
fm.queue_font(font, size * 1.5, "0123456789");
|
||||
fm.queue_font(font, size * 2.0, "0123456789 ADFJMOSabcehgilmnoprstuvy");
|
||||
pub fn new(
|
||||
fm: &mut FontMap,
|
||||
font: &'static str,
|
||||
month_font: &'static str,
|
||||
size: f32,
|
||||
sections_x: i32,
|
||||
sections_y: i32,
|
||||
) -> Calendar {
|
||||
fm.queue_font(font, size * DAY_FACTOR, "ADEFHIMNORSTUW");
|
||||
fm.queue_font(font, size * YEAR_FACTOR, "0123456789");
|
||||
fm.queue_font(font, size * DATE_FACTOR, "0123456789");
|
||||
fm.queue_font(month_font, size * MONTH_FACTOR, "ADFJMOSabcehgilmnoprstuvy");
|
||||
|
||||
Calendar {
|
||||
font,
|
||||
month_font,
|
||||
size,
|
||||
sections_x,
|
||||
sections_y,
|
||||
@@ -42,6 +56,9 @@ impl Calendar {
|
||||
shown_sections_y: 0,
|
||||
dirty: true,
|
||||
geometry: Default::default(),
|
||||
date_width: 0,
|
||||
day_width: 0,
|
||||
year_width: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,39 +69,33 @@ impl Calendar {
|
||||
orig: NaiveDate,
|
||||
mut time: NaiveDate,
|
||||
) {
|
||||
let white = Color::WHITE;
|
||||
let dim = Color::GREY80;
|
||||
let dimmer = Color::GREY75;
|
||||
|
||||
let mut y_off = 1;
|
||||
// TODO: Fix offsets:
|
||||
// - Headline font is not correctly accounted for
|
||||
|
||||
let cal_width = 8 * self.date_width + 7 * (self.date_width / 2);
|
||||
//
|
||||
// Draw the week day
|
||||
//
|
||||
let day_offset = (self.date_width - self.day_width) / 2;
|
||||
let date_offset = self.date_width + self.date_width / 2;
|
||||
for idx in 1..8 {
|
||||
let day_font = fonts.get_font(self.font, self.size * DAY_FACTOR);
|
||||
let wk_chr = match idx {
|
||||
1 => "MON",
|
||||
2 => "TUE",
|
||||
3 => "WED",
|
||||
4 => "THU",
|
||||
5 => "FRI",
|
||||
6 => "SAT",
|
||||
7 => "SUN",
|
||||
let (wk_chr, c) = match idx {
|
||||
1 => ("MON", Color::WHITE),
|
||||
2 => ("TUE", Color::WHITE),
|
||||
3 => ("WED", Color::WHITE),
|
||||
4 => ("THU", Color::WHITE),
|
||||
5 => ("FRI", Color::WHITE),
|
||||
6 => ("SAT", Color::GREY80),
|
||||
7 => ("SUN", Color::GREY80),
|
||||
_ => panic!("impossible value"),
|
||||
};
|
||||
|
||||
day_font
|
||||
.draw_text(
|
||||
&mut view
|
||||
.offset((
|
||||
idx * (self.size * 2.5).ceil() as u32 + (self.size / 5.).ceil() as u32,
|
||||
y_off * (self.size * LINE_HEIGHT).ceil() as u32
|
||||
+ (self.size * 1.).ceil() as u32,
|
||||
)),
|
||||
white,
|
||||
&mut view.offset((
|
||||
idx * date_offset + day_offset,
|
||||
(self.size * MONTH_FACTOR).ceil() as u32
|
||||
+ (self.size * DAY_FACTOR * 0.2).ceil() as u32,
|
||||
)),
|
||||
c,
|
||||
&wk_chr,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -93,18 +104,7 @@ impl Calendar {
|
||||
//
|
||||
// Draw the month
|
||||
//
|
||||
if time.year() != orig.year() {
|
||||
let year_font = fonts.get_font(self.font, self.size * YEAR_FACTOR);
|
||||
year_font
|
||||
.draw_text(
|
||||
&mut view.offset(((self.size * 17.).ceil() as u32, 0)),
|
||||
dim,
|
||||
&format!("{:}", time.year()),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let cal_font = fonts.get_font(self.font, self.size * DATE_FACTOR);
|
||||
let month_font = fonts.get_font(self.month_font, self.size * MONTH_FACTOR);
|
||||
let month_str = match time.month() {
|
||||
1 => "January",
|
||||
2 => "February",
|
||||
@@ -120,59 +120,62 @@ impl Calendar {
|
||||
12 => "December",
|
||||
_ => panic!("impossible value"),
|
||||
};
|
||||
cal_font
|
||||
.draw_text(&mut view, white, month_str)
|
||||
month_font
|
||||
.draw_text(&mut view, Color::WHITE, month_str)
|
||||
.unwrap();
|
||||
|
||||
let mut done = false;
|
||||
while !done {
|
||||
let mut x_pos = 0;
|
||||
|
||||
//
|
||||
// Find the start of this week
|
||||
//
|
||||
let mut wkday = time.weekday();
|
||||
while wkday != chrono::Weekday::Mon {
|
||||
x_pos += 1;
|
||||
wkday = wkday.pred();
|
||||
}
|
||||
//
|
||||
// Draw the year
|
||||
//
|
||||
if time.year() != orig.year() {
|
||||
let year_font = fonts.get_font(self.font, self.size * YEAR_FACTOR);
|
||||
year_font
|
||||
.draw_text(
|
||||
&mut view.offset((cal_width - self.year_width, 0)),
|
||||
Color::GREY80,
|
||||
&format!("{:}", time.year()),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let cal_font = fonts.get_font(self.font, self.size * DATE_FACTOR);
|
||||
'row: for y_off in 1.. {
|
||||
//
|
||||
// Draw the week number
|
||||
//
|
||||
let wk = time.iso_week();
|
||||
cal_font
|
||||
.draw_text(
|
||||
&mut view
|
||||
.offset((
|
||||
0,
|
||||
y_off * (self.size * LINE_HEIGHT).ceil() as u32
|
||||
+ (self.size * MONTH_FACTOR).ceil() as u32,
|
||||
)),
|
||||
dimmer,
|
||||
&mut view.offset((
|
||||
0,
|
||||
y_off * (self.size * LINE_HEIGHT).ceil() as u32
|
||||
+ (self.size * MONTH_FACTOR).ceil() as u32,
|
||||
)),
|
||||
Color::GREY75,
|
||||
&format!("{:02}", wk.week()),
|
||||
)
|
||||
.unwrap();
|
||||
x_pos += 1;
|
||||
|
||||
//
|
||||
// Draw the dates
|
||||
//
|
||||
while x_pos < 8 {
|
||||
let x_off = time.weekday().number_from_monday();
|
||||
for x_pos in x_off..8 {
|
||||
let c = if time.day() == orig.day() && time.month() == orig.month() {
|
||||
Color::WHITE
|
||||
} else {
|
||||
} else if x_pos < 6 {
|
||||
Color::GREY50
|
||||
} else {
|
||||
Color::GREY35
|
||||
};
|
||||
|
||||
cal_font
|
||||
.draw_text(
|
||||
&mut view
|
||||
.offset((
|
||||
x_pos * (self.size * 2.5).ceil() as u32,
|
||||
y_off * (self.size * LINE_HEIGHT).ceil() as u32
|
||||
+ (self.size * MONTH_FACTOR).ceil() as u32,
|
||||
)),
|
||||
&mut view.offset((
|
||||
x_pos * date_offset,
|
||||
y_off * (self.size * LINE_HEIGHT).ceil() as u32
|
||||
+ (self.size * MONTH_FACTOR).ceil() as u32,
|
||||
)),
|
||||
c,
|
||||
&format!("{:02}", time.day()),
|
||||
)
|
||||
@@ -180,14 +183,10 @@ impl Calendar {
|
||||
|
||||
let t = time.with_day(time.day() + 1);
|
||||
if t.is_none() {
|
||||
done = true;
|
||||
break;
|
||||
break 'row;
|
||||
}
|
||||
time = t.unwrap();
|
||||
x_pos += 1;
|
||||
}
|
||||
|
||||
y_off += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,9 +221,10 @@ impl<'a> Widget for Calendar {
|
||||
|
||||
let time = Local::now().naive_local().date();
|
||||
|
||||
let cal_height = (self.size * 16.25).ceil() as u32;
|
||||
let cal_width = (7. * self.size * 2.5 + self.size * 2.).ceil() as u32;
|
||||
let cal_pad = (3. * self.size).ceil() as u32;
|
||||
let cal_height =
|
||||
(self.size * MONTH_FACTOR).ceil() as u32 + (self.size * LINE_HEIGHT * 8.).ceil() as u32;
|
||||
let cal_width = 8 * self.date_width + 7 * (self.date_width / 2);
|
||||
let cal_pad = self.date_width * 2;
|
||||
|
||||
let mut t = time.with_day(1).unwrap();
|
||||
let cals = self.shown_sections_y * self.shown_sections_x;
|
||||
@@ -236,8 +236,7 @@ impl<'a> Widget for Calendar {
|
||||
for idx in 0..self.shown_sections_x {
|
||||
self.draw_month(
|
||||
fonts,
|
||||
&mut view
|
||||
.offset(((cal_width + cal_pad) * idx, (cal_height) * ydx)),
|
||||
&mut view.offset(((cal_width + cal_pad) * idx, cal_height * ydx)),
|
||||
time,
|
||||
t,
|
||||
);
|
||||
@@ -252,35 +251,91 @@ impl<'a> Widget for Calendar {
|
||||
self.geometry
|
||||
}
|
||||
|
||||
fn geometry_update(&mut self, _fonts: &mut FontMap, geometry: &Geometry) -> Geometry {
|
||||
let cal_width = 7 * (self.size * 2.5).ceil() as u32 + (self.size * 2.).ceil() as u32;
|
||||
let cal_height = (self.size * MONTH_FACTOR).ceil() as u32
|
||||
+ (self.size * LINE_HEIGHT * 8.).ceil() as u32;
|
||||
let cal_pad = (self.size * 3.).ceil() as u32;
|
||||
fn geometry_update(&mut self, fonts: &mut FontMap, geometry: &Geometry) -> Geometry {
|
||||
let year_font = fonts.get_font(self.font, self.size * YEAR_FACTOR);
|
||||
self.year_width = year_font.auto_widest("0123456789").unwrap() * 4;
|
||||
let cal_font = fonts.get_font(self.font, self.size * DATE_FACTOR);
|
||||
self.date_width = cal_font.auto_widest("0123456789").unwrap() * 2;
|
||||
let day_font = fonts.get_font(self.font, self.size * DAY_FACTOR);
|
||||
self.day_width = day_font.auto_widest("ADEFHIMNORSTUW").unwrap() * 3;
|
||||
|
||||
let possible_sections_x = geometry.width / (cal_width + cal_pad);
|
||||
let possible_sections_y = geometry.height / cal_height;
|
||||
let cal_width = 8 * self.date_width + 7 * (self.date_width / 2);
|
||||
let cal_height =
|
||||
(self.size * MONTH_FACTOR).ceil() as u32 + (self.size * LINE_HEIGHT * 8.).ceil() as u32;
|
||||
|
||||
let cal_pad = self.date_width * 2;
|
||||
|
||||
if geometry.width < cal_width || geometry.height < cal_height {
|
||||
self.geometry = Default::default();
|
||||
return self.geometry;
|
||||
}
|
||||
|
||||
let possible_sections_x = 1 + (geometry.width - cal_width) / (cal_width + cal_pad);
|
||||
let possible_sections_y = 1 + (geometry.height - cal_height) / cal_height;
|
||||
|
||||
self.shown_sections_x =
|
||||
if self.sections_x > 0 && self.sections_x < possible_sections_x as i32 {
|
||||
self.sections_x as u32
|
||||
} else {
|
||||
possible_sections_x
|
||||
};
|
||||
self.shown_sections_y =
|
||||
if self.sections_y > 0 && self.sections_y < possible_sections_y as i32 {
|
||||
self.sections_y as u32
|
||||
} else {
|
||||
possible_sections_y
|
||||
};
|
||||
|
||||
let width = if self.sections_x > 0 && self.sections_x < possible_sections_x as i32 {
|
||||
self.shown_sections_x = self.sections_x as u32;
|
||||
cal_width * self.sections_x as u32 + cal_pad * (self.sections_x as u32 - 1)
|
||||
} else {
|
||||
self.shown_sections_x = possible_sections_x;
|
||||
(geometry.width / (cal_width + cal_pad)) * (cal_width + cal_pad)
|
||||
};
|
||||
let height = if self.sections_y > 0 && self.sections_y < possible_sections_y as i32 {
|
||||
self.shown_sections_y = self.sections_y as u32;
|
||||
cal_height * self.sections_y as u32
|
||||
} else {
|
||||
self.shown_sections_y = possible_sections_y;
|
||||
(geometry.height / cal_height) * cal_height
|
||||
};
|
||||
self.geometry = Geometry {
|
||||
x: geometry.x,
|
||||
y: geometry.y,
|
||||
width: width,
|
||||
height: height,
|
||||
width: cal_width * self.shown_sections_x as u32
|
||||
+ cal_pad * (self.shown_sections_x as u32 - 1),
|
||||
height: cal_height * self.shown_sections_y as u32,
|
||||
};
|
||||
self.geometry
|
||||
}
|
||||
|
||||
fn minimum_size(&mut self, fonts: &mut FontMap) -> Geometry {
|
||||
let cal_font = fonts.get_font(self.font, self.size * DATE_FACTOR);
|
||||
let date_width = cal_font.auto_widest("0123456789").unwrap() * 2;
|
||||
|
||||
let cal_width = 8 * date_width + 7 * (date_width / 2);
|
||||
let cal_height =
|
||||
(self.size * MONTH_FACTOR).ceil() as u32 + (self.size * LINE_HEIGHT * 8.).ceil() as u32;
|
||||
let cal_pad = date_width * 2;
|
||||
|
||||
let sections_x = match self.sections_x {
|
||||
-1 => 1,
|
||||
0 => {
|
||||
return Geometry {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
}
|
||||
}
|
||||
x => x,
|
||||
};
|
||||
let sections_y = match self.sections_y {
|
||||
-1 => 1,
|
||||
0 => {
|
||||
return Geometry {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
}
|
||||
}
|
||||
y => y,
|
||||
};
|
||||
let width = cal_width * sections_x as u32 + cal_pad * (sections_x as u32 - 1);
|
||||
let height = cal_height * sections_y as u32;
|
||||
Geometry {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: width,
|
||||
height: height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user