egui/crates/egui_extras/src/datepicker/button.rs
Emil Ernerfeldt 2dc2a5540d
egui_extras::Table improvements (#2369)
* Use simple `ui.interact` for the resize line

* Introduce TableReizeState

* Simplify some code

* Add striped options to table demo

* Auto-size table columns by double-clicking the resize line

* Table: add option to auto-size the columns

* Table: don't let column width gets too small, unless clipping is on

* egui_extras: always use serde

Otherwise using `get_persisted` etc is impossible,
and working around that tedious.

* Avoid clipping last column in a resizable table

* Some better naming

* Table: Use new `Column` for setting column sizes and properties

Also make `clip` a per-column property

* All Table:s store state for auto-sizing purposes

* Customize each column wether or not it is resizable

* fix some auto-sizing bugs

* Fix shrinkage of adaptive column content

* Rename `scroll` to `vscroll` for clarity

* Add Table::scroll_to_row

* scroll_to_row takes alignment

* Fix bug in table sizing

* Strip: turn clipping OFF by default, because it is dangerous and sucks

* Add TableBody::mac_rect helper

* Table: add options to control the scroll area height.

* Docstring fixes

* Cleanup
2022-11-30 19:56:06 +01:00

143 lines
4.7 KiB
Rust

use super::popup::DatePickerPopup;
use chrono::{Date, Utc};
use egui::{Area, Button, Frame, InnerResponse, Key, Order, RichText, Ui, Widget};
#[derive(Default, Clone, serde::Deserialize, serde::Serialize)]
pub(crate) struct DatePickerButtonState {
pub picker_visible: bool,
}
pub struct DatePickerButton<'a> {
selection: &'a mut Date<Utc>,
id_source: Option<&'a str>,
combo_boxes: bool,
arrows: bool,
calendar: bool,
calendar_week: bool,
}
impl<'a> DatePickerButton<'a> {
pub fn new(selection: &'a mut Date<Utc>) -> Self {
Self {
selection,
id_source: None,
combo_boxes: true,
arrows: true,
calendar: true,
calendar_week: true,
}
}
/// Add id source.
/// Must be set if multiple date picker buttons are in the same Ui.
pub fn id_source(mut self, id_source: &'a str) -> Self {
self.id_source = Some(id_source);
self
}
/// Show combo boxes in date picker popup. (Default: true)
pub fn combo_boxes(mut self, combo_boxes: bool) -> Self {
self.combo_boxes = combo_boxes;
self
}
/// Show arrows in date picker popup. (Default: true)
pub fn arrows(mut self, arrows: bool) -> Self {
self.arrows = arrows;
self
}
/// Show calendar in date picker popup. (Default: true)
pub fn calendar(mut self, calendar: bool) -> Self {
self.calendar = calendar;
self
}
/// Show calendar week in date picker popup. (Default: true)
pub fn calendar_week(mut self, week: bool) -> Self {
self.calendar_week = week;
self
}
}
impl<'a> Widget for DatePickerButton<'a> {
fn ui(self, ui: &mut Ui) -> egui::Response {
let id = ui.make_persistent_id(self.id_source);
let mut button_state = ui
.memory()
.data
.get_persisted::<DatePickerButtonState>(id)
.unwrap_or_default();
let mut text = RichText::new(format!("{} 📆", self.selection.format("%Y-%m-%d")));
let visuals = ui.visuals().widgets.open;
if button_state.picker_visible {
text = text.color(visuals.text_color());
}
let mut button = Button::new(text);
if button_state.picker_visible {
button = button.fill(visuals.bg_fill).stroke(visuals.bg_stroke);
}
let mut button_response = ui.add(button);
if button_response.clicked() {
button_state.picker_visible = true;
ui.memory().data.insert_persisted(id, button_state.clone());
}
if button_state.picker_visible {
let width = 333.0;
let mut pos = button_response.rect.left_bottom();
let width_with_padding = width
+ ui.style().spacing.item_spacing.x
+ ui.style().spacing.window_margin.left
+ ui.style().spacing.window_margin.right;
if pos.x + width_with_padding > ui.clip_rect().right() {
pos.x = button_response.rect.right() - width_with_padding;
}
// Check to make sure the calendar never is displayed out of window
pos.x = pos.x.max(ui.style().spacing.window_margin.left);
//TODO(elwerene): Better positioning
let InnerResponse {
inner: saved,
response: area_response,
} = Area::new(ui.make_persistent_id(self.id_source))
.order(Order::Foreground)
.fixed_pos(pos)
.show(ui.ctx(), |ui| {
let frame = Frame::popup(ui.style());
frame
.show(ui, |ui| {
ui.set_min_width(width);
ui.set_max_width(width);
DatePickerPopup {
selection: self.selection,
button_id: id,
combo_boxes: self.combo_boxes,
arrows: self.arrows,
calendar: self.calendar,
calendar_week: self.calendar_week,
}
.draw(ui)
})
.inner
});
if saved {
button_response.mark_changed();
}
if !button_response.clicked()
&& (ui.input().key_pressed(Key::Escape) || area_response.clicked_elsewhere())
{
button_state.picker_visible = false;
ui.memory().data.insert_persisted(id, button_state);
}
}
button_response
}
}