Skip to content

Commit

Permalink
Introduces date selector to xilem
Browse files Browse the repository at this point in the history
  • Loading branch information
giannissc committed Aug 29, 2024
1 parent ac95f25 commit 19c9d8b
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 3 deletions.
7 changes: 4 additions & 3 deletions xilem/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ crate-type = ["cdylib"]
[[example]]
name = "calc"

[[example]]
name = "calendar"

[[example]]
name = "calc_android"
path = "examples/calc.rs"
Expand Down Expand Up @@ -66,11 +69,9 @@ vello.workspace = true
smallvec.workspace = true
accesskit.workspace = true
tokio = { version = "1.39.1", features = ["rt", "rt-multi-thread", "time"] }

[dev-dependencies]
# Used for `variable_clock`
time = { workspace = true, features = ["local-offset"] }

[dev-dependencies]
# Make wgpu use tracing for its spans.
profiling = { version = "1.0.15", features = ["profile-with-tracing"] }

Expand Down
72 changes: 72 additions & 0 deletions xilem/examples/calendar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use std::fmt::format;

// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use masonry::widget::{CrossAxisAlignment, MainAxisAlignment};
use time::{util::days_in_year_month, Date, Month, OffsetDateTime};
use winit::error::EventLoopError;
use xilem::{
view::{button, date, flex, label, sized_box, Axis, DateData, FlexExt as _, FlexSpacer},
EventLoop, WidgetView, Xilem,
};
use xilem_core::{frozen, map_state};

struct Calendar {
// selected_date: Date,
// month: Month,
// year: i32,
date: DateData,
}

impl Calendar {
fn new() -> Self {
let now = OffsetDateTime::now_utc();
Self {
// selected_date: ,
// month: now.month(),
// year: now.year(),
date: DateData::new(now.date(), now.month(), now.year()),
}
}
}
fn selected_date(selected_date: Date) -> impl WidgetView<Calendar> {
flex((label("Selected date:"), label(format!("{selected_date}")))).direction(Axis::Horizontal)
}

/// A component to make a bigger than usual button
fn external_controls() -> impl WidgetView<Calendar> {
flex((
button("Today", |data: &mut Calendar| {
data.date.selected_date = OffsetDateTime::now_utc().date();
}),
button("Tomorrow", |data: &mut Calendar| {
data.date.selected_date = OffsetDateTime::now_utc().date().next_day().unwrap();
}),
))
.direction(Axis::Horizontal)
}

fn app_logic(data: &mut Calendar) -> impl WidgetView<Calendar> {
flex((
selected_date(data.date.selected_date),
external_controls(),
map_state(
date(
&mut data.date.selected_date,
&mut data.date.month,
&mut data.date.year,
),
|data: &mut Calendar| &mut data.date,
),
))
.direction(Axis::Vertical)
.cross_axis_alignment(CrossAxisAlignment::Center)
.main_axis_alignment(MainAxisAlignment::Center)
}

fn main() -> Result<(), EventLoopError> {
let data = Calendar::new();
let app = Xilem::new(data, app_logic);
app.run_windowed(EventLoop::with_user_event(), "Calendar".into())?;
Ok(())
}
106 changes: 106 additions & 0 deletions xilem/src/view/date_selector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use masonry::widget::{Axis, CrossAxisAlignment, MainAxisAlignment};
use time::{format_description::modifier::Year, Date, Month, OffsetDateTime};

use crate::{view::sized_box, WidgetView};

use super::{button, flex, FlexSpacer};

pub struct DateData {
pub selected_date: Date,
pub month: Month,
pub year: i32,
}

impl DateData {
pub fn new(selected_date: Date, month: Month, year: i32) -> Self {
Self {
selected_date,
month,
year,
}
}
}

pub fn date(
selected_date: &mut Date,
month: &mut Month,
year: &mut i32,
) -> impl WidgetView<DateData> {
flex((
date_controls(month, year),
date_grid(selected_date, month, year),
))
.direction(Axis::Vertical)
.cross_axis_alignment(CrossAxisAlignment::Center)
.main_axis_alignment(MainAxisAlignment::Center)
}

fn date_controls(month: &mut Month, year: &mut i32) -> impl WidgetView<DateData> {
flex((
button("<", |data: &mut DateData| {
data.month = data.month.previous();
}),
sized_box(button(format!("{month}"), |_| {})).width(100.),
button(">", |data: &mut DateData| {
data.month = data.month.next();
}),
FlexSpacer::Fixed(40.),
button("<", |data: &mut DateData| {
data.year -= 1;
}),
button(format!("{year}"), |_| {}),
button(">", |data: &mut DateData| {
data.year += 1;
}),
))
.direction(Axis::Horizontal)
.main_axis_alignment(MainAxisAlignment::Center)
}

// The selected_date in the interface is needed to highlight the currently selected date
// It is currently not implemented
fn date_grid(
selected_date: &mut Date,
month: &mut Month,
year: &mut i32,
) -> impl WidgetView<DateData> {
const COLUMNS: u8 = 7;
const ROWS: u8 = 5;
let mut date = Date::from_calendar_date(*year, *month, 1).unwrap();
let days_from_monday = date.weekday().number_days_from_monday();

for _day in 0..days_from_monday {
date = date.previous_day().unwrap();
}

let mut rows = Vec::new();
for _row in 0..ROWS {
let mut columns = Vec::new();
for _column in 0..COLUMNS {
// Add buttons of each row into columns vec
let day_number = date.day();
let date_copy = date.clone();
columns.push(
sized_box(button(
format!("{day_number}"),
move |data: &mut DateData| {
// Set the selected_date
data.selected_date = date_copy;
},
))
.width(50.),
);
date = date.next_day().unwrap();
}
// Add column vec into flex with horizontal axis
// Add flex into rows vec
rows.push(
flex(columns)
.direction(Axis::Horizontal)
.main_axis_alignment(MainAxisAlignment::Center)
.gap(10.),
);
}
// Add row vec into flex with vertical axis
flex(rows).direction(Axis::Vertical)
}
3 changes: 3 additions & 0 deletions xilem/src/view/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ pub use textbox::*;

mod portal;
pub use portal::*;

mod date_selector;
pub use date_selector::*;

0 comments on commit 19c9d8b

Please sign in to comment.