Last active
September 23, 2020 17:12
-
-
Save kivimango/3b42f1755e99124d1f9c4e27bbfd5c60 to your computer and use it in GitHub Desktop.
Calendar latest
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [package] | |
| name = "calendar" | |
| version = "0.1.0" | |
| authors = ["kivimango <balazsviktor23@gmail.com>"] | |
| edition = "2018" | |
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
| [dependencies] | |
| orbtk = { git = "https://github.com/redox-os/orbtk.git", branch = "develop" } | |
| chrono = "0.4.6" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| extern crate chrono; | |
| use orbtk::{ | |
| prelude::*, | |
| theming::config::ThemeConfig, | |
| }; | |
| use chrono::prelude::*; | |
| use chrono::Duration; | |
| use std::ops::{Sub, Add}; | |
| const CALENDAR_GRID: &str = "_CLNDR_GRD"; | |
| const HEADER_GRID: &str = "_HDR_GRD"; | |
| const CURRENT_DATE_LABEL: &str = "_CRRNT_DT_LBL_ID"; | |
| const CELL_WIDTH: u32 = 90; | |
| const CELL_HEIGHT: u32 = 90; | |
| const CELL_DAY_NAME_HEIGHT: u32 = 16; | |
| const PADDING: u32 = 8; | |
| const WINDOW_WIDTH: u32 = 7 * (CELL_WIDTH + PADDING) + PADDING; | |
| const WINDOW_HEIGHT: u32 = 6 * (CELL_HEIGHT + PADDING) + 16 + CELL_DAY_NAME_HEIGHT + 24; | |
| const DAYS_OF_WEEK: [&'static str; 7] = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]; | |
| enum CalendarCommand { | |
| IncreaseMonth, | |
| DecreaseMonth | |
| } | |
| struct TimeMachine { | |
| date: DateTime<Local> | |
| } | |
| impl TimeMachine { | |
| fn new() -> Self { | |
| TimeMachine { | |
| date: Local::now() | |
| } | |
| } | |
| fn increase_month(&mut self) { | |
| self.date = self.date.add(Duration::days(31)) | |
| .with_day(1) | |
| .unwrap(); | |
| } | |
| fn decrease_month(&mut self) { | |
| self.date = self.date.sub(Duration::days(28)) | |
| .with_day(1) | |
| .unwrap(); | |
| } | |
| fn get_date(&self) -> DateTime<Local> { | |
| self.date | |
| } | |
| } | |
| impl Default for TimeMachine { | |
| fn default() -> Self { | |
| TimeMachine::new() | |
| } | |
| } | |
| #[derive(Default, AsAny)] | |
| struct CalendarState { | |
| command: Option<CalendarCommand>, | |
| date: TimeMachine, | |
| header_grid: Entity, | |
| calendar_grid: Entity, | |
| label_date: Entity | |
| } | |
| impl CalendarState { | |
| fn command(&mut self, command: CalendarCommand) { | |
| self.command = Some(command); | |
| } | |
| fn redraw_date(&self, ctx: &mut Context ) { | |
| let string_date = self.date.get_date().format("%B %Y").to_string(); | |
| ctx.get_widget(self.label_date).set::<String>("text", string_date); | |
| } | |
| fn redraw_grid(&self, ctx: &mut Context) { | |
| ctx.clear_children_of(self.calendar_grid); | |
| let date = self.date.get_date(); | |
| let mut day = 1; | |
| let day_offset = self.date.get_date().with_day(1).unwrap().weekday().number_from_monday() as usize - 1; | |
| let today = Local::now().date(); | |
| for idx in day_offset..6*7usize { | |
| match date.with_day(day) { | |
| Some(x) => { | |
| let styles = { | |
| match x.date() == today { | |
| true => ("date_today", "text_block_today"), | |
| false => ("date_cell", "text_block") | |
| } | |
| }; | |
| let cell = get_cell(idx, format!("{}", x.day()), styles, &mut ctx.build_context()); | |
| if x.date() == today { | |
| ctx.get_widget(cell).set::<String>("name", "today".to_string()); | |
| } | |
| ctx.append_child_entity_to(cell, self.calendar_grid); | |
| }, | |
| None => {} | |
| } | |
| day += 1; | |
| } | |
| } | |
| } | |
| fn get_cell(index: usize, text: String, styles: (&str, &str), ctx: &mut BuildContext) -> Entity { | |
| Container::new() | |
| .style(styles.0) | |
| .attach(Grid::column(index % 7)) | |
| .attach(Grid::row(index / 7)) | |
| .child( | |
| TextBlock::new() | |
| .text(text) | |
| .style(styles.1) | |
| .h_align("center") | |
| .v_align("center") | |
| .build(ctx) | |
| ) | |
| .build(ctx) | |
| } | |
| impl State for CalendarState { | |
| fn init(&mut self, _: &mut Registry, ctx: &mut Context) { | |
| self.label_date = ctx.entity_of_child(CURRENT_DATE_LABEL) | |
| .expect("Could not find entity of current date label!"); | |
| self.calendar_grid = ctx.entity_of_child(CALENDAR_GRID) | |
| .expect("Could not find entity of calendar grid!"); | |
| self.header_grid = ctx.entity_of_child(HEADER_GRID) | |
| .expect("Could not find entity of header grid!"); | |
| self.redraw_date(ctx); | |
| for(i, day) in DAYS_OF_WEEK.iter().enumerate() { | |
| let label = generate_weekday_label(i, day); | |
| ctx.append_child_to(label, self.header_grid); | |
| } | |
| self.redraw_grid(ctx); | |
| } | |
| fn update(&mut self, _: &mut Registry, ctx: &mut Context) { | |
| if let Some(command) = &self.command { | |
| match command { | |
| CalendarCommand::DecreaseMonth => { | |
| self.date.decrease_month(); | |
| self.redraw_date(ctx); | |
| self.redraw_grid(ctx); | |
| }, | |
| CalendarCommand::IncreaseMonth => { | |
| self.date.increase_month(); | |
| self.redraw_date(ctx); | |
| self.redraw_grid(ctx); | |
| } | |
| } | |
| self.command = None; | |
| } | |
| } | |
| } | |
| widget!(CalendarView<CalendarState>); | |
| impl Template for CalendarView { | |
| fn template(self, id: Entity, ctx: &mut BuildContext) -> Self { | |
| self.name("CalendarView") | |
| .child( | |
| Stack::new() | |
| .orientation("vertical") | |
| .spacing(32.0) | |
| .child( | |
| Grid::new() | |
| .id(HEADER_GRID) | |
| .h_align("center") | |
| .width(7 * 90 + PADDING) | |
| .margin(8.0) | |
| .rows(Rows::create().push("auto").push("auto").build()) | |
| .columns(Columns::create().repeat(90, 7).build()) | |
| .child( | |
| Button::new() | |
| .style("button_styled") | |
| .attach(Grid::row(0)) | |
| .attach(Grid::column(2)) | |
| .h_align("center") | |
| .v_align("center") | |
| .icon(material_icons_font::MD_KEYBOARD_ARROW_LEFT) | |
| .on_click(move |states, _| ->bool { | |
| states.get_mut::<CalendarState>(id).command(CalendarCommand::DecreaseMonth); | |
| true | |
| }) | |
| .build(ctx) | |
| ) | |
| .child( | |
| TextBlock::new() | |
| .style("text_block") | |
| .id(CURRENT_DATE_LABEL) | |
| .attach(Grid::row(0)) | |
| .attach(Grid::column(3)) | |
| .h_align("center") | |
| .size(300, 16) | |
| .v_align("center") | |
| .build(ctx) | |
| ) | |
| .child( | |
| Button::new() | |
| .style("button_styled") | |
| .attach(Grid::row(0)) | |
| .attach(Grid::column(4)) | |
| .h_align("center") | |
| .v_align("center") | |
| .icon(material_icons_font::MD_KEYBOARD_ARROW_RIGHT) | |
| .width(32) | |
| .height(32) | |
| .on_click(move |states, _| ->bool { | |
| states.get_mut::<CalendarState>(id).command(CalendarCommand::IncreaseMonth); | |
| true | |
| }) | |
| .build(ctx) | |
| ) | |
| .build(ctx) | |
| ) | |
| .child( | |
| Grid::new() | |
| .id(CALENDAR_GRID) | |
| .h_align("center") | |
| .margin((4.0, 4.0)) | |
| .width(7 * CELL_WIDTH + PADDING) | |
| .rows( | |
| Rows::create() | |
| .repeat("auto", 6) | |
| .build() | |
| ) | |
| .columns( | |
| Columns::create() | |
| .repeat(90.0, 7) | |
| .build() | |
| ) | |
| .build(ctx) | |
| ) | |
| .build(ctx) | |
| ) | |
| } | |
| } | |
| fn generate_weekday_label(column_index: usize, day: &str) -> TextBlock { | |
| TextBlock::new() | |
| .attach(Grid::row(1)) | |
| .attach(Grid::column(column_index)) | |
| .h_align("center") | |
| .style("text_block") | |
| .text(day) | |
| } | |
| static CALENDAR_THEME: &str = include_str!("theme.ron"); | |
| fn theme() -> Theme { | |
| Theme::from_config( | |
| ThemeConfig::from(CALENDAR_THEME) | |
| ) | |
| } | |
| fn main() { | |
| Application::new() | |
| .theme(theme()) | |
| .window(|ctx| { | |
| Window::new() | |
| //.borderless(true) | |
| .h_align("center") | |
| .title("Calendar") | |
| .position((5.0, 5.0)) | |
| .size(WINDOW_WIDTH, WINDOW_HEIGHT) | |
| .resizeable(true) | |
| .child(CalendarView::new().build(ctx)) | |
| .build(ctx) | |
| }) | |
| .run(); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Theme ( | |
| styles: { | |
| "window": ( | |
| properties: { | |
| "background": "#F5F6F7", | |
| "border_brush": "#CFD6E6", | |
| "border_radius": 0, | |
| "border_width": 1, | |
| } | |
| ), | |
| "base": ( | |
| properties: { | |
| "font_size": "16", | |
| "font_family": "Roboto-Medium", | |
| } | |
| ), | |
| "text_block": ( | |
| properties: { | |
| "foreground": "#000000", | |
| } | |
| ), | |
| "text_block_today": ( | |
| properties: { | |
| "foreground": "#FFFFFF", | |
| } | |
| ), | |
| "button_styled": ( | |
| properties: { | |
| "background": "#FFFFFF", | |
| "border_brush": "#CFD6E6", | |
| "border_radius": 2, | |
| "border_width": 1, | |
| "icon_brush": "#000000", | |
| "height": 32, | |
| "width": 32, | |
| "max_width": 32 | |
| } | |
| ), | |
| "date_cell": ( | |
| properties: { | |
| "background": "#FFFFFF", | |
| "border_brush": "#CFD6E6", | |
| "border_radius": 4, | |
| "border_width": 1, | |
| "width": 82, | |
| "height": 82 | |
| } | |
| ), | |
| "date_today": ( | |
| properties: { | |
| "background": "#5294E2", | |
| "border_brush": "#000000", | |
| "border_radius": 4, | |
| "border_width": 1, | |
| "foreground": "#FFFFFF", | |
| "width": 82, | |
| "height": 82 | |
| } | |
| ) | |
| } | |
| ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment