@@ -12,7 +12,7 @@ use crate::{ |
| 12 | 12 | agenda::{ |
| 13 | 13 | AgendaSource, DayAgenda, DayMinute, EmptyAgendaSource, Event, EventTiming, TimedAgendaEvent, |
| 14 | 14 | }, |
| 15 | | - app::{AppState, CreateEventForm, ViewMode}, |
| 15 | + app::{AppState, CreateEventForm, CreateEventFormRowKind, ViewMode}, |
| 16 | 16 | calendar::{ |
| 17 | 17 | CalendarCell, CalendarDate, CalendarMonth, CalendarWeek, DAYS_PER_WEEK, MONTH_GRID_WEEKS, |
| 18 | 18 | }, |
@@ -478,6 +478,8 @@ struct CreateModalStyles { |
| 478 | 478 | title: Style, |
| 479 | 479 | label: Style, |
| 480 | 480 | value: Style, |
| 481 | + checkbox: Style, |
| 482 | + checkbox_mark: Style, |
| 481 | 483 | error: Style, |
| 482 | 484 | footer: Style, |
| 483 | 485 | } |
@@ -491,8 +493,10 @@ impl CreateModalStyles { |
| 491 | 493 | .fg(Color::Cyan) |
| 492 | 494 | .bg(Color::Black) |
| 493 | 495 | .add_modifier(Modifier::BOLD), |
| 494 | | - label: Style::new().fg(Color::Gray).bg(Color::Black), |
| 495 | | - value: Style::new().fg(Color::White).bg(Color::Black), |
| 496 | + label: Style::new().fg(Color::White).bg(Color::Black), |
| 497 | + value: Style::new().fg(Color::Gray).bg(Color::Black), |
| 498 | + checkbox: Style::new().fg(Color::Yellow).bg(Color::Black), |
| 499 | + checkbox_mark: Style::new().fg(Color::White).bg(Color::Black), |
| 496 | 500 | error: Style::new() |
| 497 | 501 | .fg(Color::Red) |
| 498 | 502 | .bg(Color::Black) |
@@ -835,7 +839,14 @@ fn render_create_event_modal( |
| 835 | 839 | let value_x = label_x.saturating_add(label_width).saturating_add(1); |
| 836 | 840 | if value_x < content.right() { |
| 837 | 841 | let value_width = content.right() - value_x; |
| 838 | | - write_padded_left(buf, y, value_x, value_width, &row.value, styles.value); |
| 842 | + match row.kind { |
| 843 | + CreateEventFormRowKind::Text => { |
| 844 | + write_padded_left(buf, y, value_x, value_width, &row.value, styles.value); |
| 845 | + } |
| 846 | + CreateEventFormRowKind::Toggle => { |
| 847 | + write_toggle_value(buf, y, value_x, value_width, &row.value, styles); |
| 848 | + } |
| 849 | + } |
| 839 | 850 | } |
| 840 | 851 | } |
| 841 | 852 | |
@@ -1609,6 +1620,29 @@ fn write_padded_left(buf: &mut Buffer, y: u16, x: u16, width: u16, text: &str, s |
| 1609 | 1620 | buf.set_stringn(x, y, text, usize::from(width), style); |
| 1610 | 1621 | } |
| 1611 | 1622 | |
| 1623 | +fn write_toggle_value( |
| 1624 | + buf: &mut Buffer, |
| 1625 | + y: u16, |
| 1626 | + x: u16, |
| 1627 | + width: u16, |
| 1628 | + value: &str, |
| 1629 | + styles: CreateModalStyles, |
| 1630 | +) { |
| 1631 | + write_padded_left(buf, y, x, width, value, styles.value); |
| 1632 | + if width == 0 || !value.starts_with('[') { |
| 1633 | + return; |
| 1634 | + } |
| 1635 | + |
| 1636 | + set_cell(buf, x, y, "[", styles.checkbox); |
| 1637 | + if width > 1 { |
| 1638 | + let mark = value.get(1..2).unwrap_or(" "); |
| 1639 | + set_cell(buf, x.saturating_add(1), y, mark, styles.checkbox_mark); |
| 1640 | + } |
| 1641 | + if width > 2 && value.get(2..3) == Some("]") { |
| 1642 | + set_cell(buf, x.saturating_add(2), y, "]", styles.checkbox); |
| 1643 | + } |
| 1644 | +} |
| 1645 | + |
| 1612 | 1646 | const fn inset_rect(area: Rect) -> Rect { |
| 1613 | 1647 | Rect::new( |
| 1614 | 1648 | area.x.saturating_add(1), |
@@ -1652,6 +1686,7 @@ fn distribute<const N: usize>(total: u16) -> [u16; N] { |
| 1652 | 1686 | #[cfg(test)] |
| 1653 | 1687 | mod tests { |
| 1654 | 1688 | use super::*; |
| 1689 | + use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; |
| 1655 | 1690 | use ratatui::style::Modifier; |
| 1656 | 1691 | use time::{Month, Time}; |
| 1657 | 1692 | |
@@ -1675,6 +1710,10 @@ mod tests { |
| 1675 | 1710 | CalendarDate::from_ymd(year, month, day).expect("valid test date") |
| 1676 | 1711 | } |
| 1677 | 1712 | |
| 1713 | + fn key(code: KeyCode) -> KeyEvent { |
| 1714 | + KeyEvent::new(code, KeyModifiers::empty()) |
| 1715 | + } |
| 1716 | + |
| 1678 | 1717 | fn render_test_buffer(month: &CalendarMonth, width: u16, height: u16) -> Buffer { |
| 1679 | 1718 | let area = Rect::new(0, 0, width, height); |
| 1680 | 1719 | let mut buffer = Buffer::empty(area); |
@@ -1728,16 +1767,24 @@ mod tests { |
| 1728 | 1767 | } |
| 1729 | 1768 | } |
| 1730 | 1769 | |
| 1770 | + fn assert_styled_cell(buffer: &Buffer, x: u16, y: u16, symbol: &str, fg: Color) { |
| 1771 | + let cell = buffer.cell((x, y)).expect("text cell exists"); |
| 1772 | + assert_eq!(cell.symbol(), symbol); |
| 1773 | + assert_eq!(cell.fg, fg); |
| 1774 | + assert_eq!(cell.bg, Color::Black); |
| 1775 | + assert!(!cell.modifier.contains(Modifier::DIM)); |
| 1776 | + assert!(!cell.modifier.contains(Modifier::BOLD)); |
| 1777 | + } |
| 1778 | + |
| 1731 | 1779 | fn assert_styled_text(buffer: &Buffer, x: u16, y: u16, text: &str, fg: Color) { |
| 1732 | 1780 | for (offset, character) in text.chars().enumerate() { |
| 1733 | | - let cell = buffer |
| 1734 | | - .cell((x + u16::try_from(offset).expect("offset fits"), y)) |
| 1735 | | - .expect("text cell exists"); |
| 1736 | | - assert_eq!(cell.symbol(), character.to_string()); |
| 1737 | | - assert_eq!(cell.fg, fg); |
| 1738 | | - assert_eq!(cell.bg, Color::Black); |
| 1739 | | - assert!(!cell.modifier.contains(Modifier::DIM)); |
| 1740 | | - assert!(!cell.modifier.contains(Modifier::BOLD)); |
| 1781 | + assert_styled_cell( |
| 1782 | + buffer, |
| 1783 | + x + u16::try_from(offset).expect("offset fits"), |
| 1784 | + y, |
| 1785 | + &character.to_string(), |
| 1786 | + fg, |
| 1787 | + ); |
| 1741 | 1788 | } |
| 1742 | 1789 | } |
| 1743 | 1790 | |
@@ -1955,10 +2002,13 @@ mod tests { |
| 1955 | 2002 | } |
| 1956 | 2003 | |
| 1957 | 2004 | #[test] |
| 1958 | | - fn create_modal_uses_gray_labels_and_white_values() { |
| 2005 | + fn create_modal_uses_bright_labels_gray_values_and_checkbox_styles() { |
| 1959 | 2006 | let selected = date(2026, Month::April, 23); |
| 1960 | 2007 | let mut app = AppState::new(selected); |
| 1961 | 2008 | app.apply(AppAction::OpenCreate); |
| 2009 | + let _ = app.handle_create_key(key(KeyCode::Char('A'))); |
| 2010 | + let _ = app.handle_create_key(key(KeyCode::Tab)); |
| 2011 | + let _ = app.handle_create_key(key(KeyCode::Enter)); |
| 1962 | 2012 | |
| 1963 | 2013 | let area = Rect::new(0, 0, 84, 26); |
| 1964 | 2014 | let buffer = render_app_buffer(&app, area.width, area.height); |
@@ -1969,13 +2019,20 @@ mod tests { |
| 1969 | 2019 | let label_width = 12.min(content.width.saturating_sub(1)); |
| 1970 | 2020 | let value_x = label_x.saturating_add(label_width).saturating_add(1); |
| 1971 | 2021 | |
| 1972 | | - assert_styled_text(&buffer, content.x, row_y, ">", Color::Gray); |
| 1973 | | - assert_styled_text(&buffer, label_x, row_y, "Title", Color::Gray); |
| 1974 | | - assert_styled_text(&buffer, label_x, row_y + 2, "Start date", Color::Gray); |
| 1975 | | - assert_styled_text(&buffer, value_x, row_y + 1, "[ ]", Color::White); |
| 1976 | | - assert_styled_text(&buffer, value_x, row_y + 2, "2026-04-23", Color::White); |
| 1977 | | - assert_styled_text(&buffer, value_x, row_y + 3, "09:00", Color::White); |
| 1978 | | - assert_styled_text(&buffer, value_x, row_y + 8, "[ ] 5m", Color::White); |
| 2022 | + assert_styled_text(&buffer, content.x, row_y + 1, ">", Color::White); |
| 2023 | + assert_styled_text(&buffer, label_x, row_y, "Title", Color::White); |
| 2024 | + assert_styled_text(&buffer, label_x, row_y + 1, "All day", Color::White); |
| 2025 | + assert_styled_text(&buffer, label_x, row_y + 2, "Start date", Color::White); |
| 2026 | + assert_styled_text(&buffer, value_x, row_y, "A", Color::Gray); |
| 2027 | + assert_styled_text(&buffer, value_x, row_y + 2, "2026-04-23", Color::Gray); |
| 2028 | + assert_styled_text(&buffer, value_x, row_y + 3, "09:00", Color::Gray); |
| 2029 | + assert_styled_cell(&buffer, value_x, row_y + 1, "[", Color::Yellow); |
| 2030 | + assert_styled_cell(&buffer, value_x + 1, row_y + 1, "x", Color::White); |
| 2031 | + assert_styled_cell(&buffer, value_x + 2, row_y + 1, "]", Color::Yellow); |
| 2032 | + assert_styled_cell(&buffer, value_x, row_y + 8, "[", Color::Yellow); |
| 2033 | + assert_styled_cell(&buffer, value_x + 1, row_y + 8, " ", Color::White); |
| 2034 | + assert_styled_cell(&buffer, value_x + 2, row_y + 8, "]", Color::Yellow); |
| 2035 | + assert_styled_text(&buffer, value_x + 4, row_y + 8, "5m", Color::Gray); |
| 1979 | 2036 | } |
| 1980 | 2037 | |
| 1981 | 2038 | #[test] |