first prototype

This commit is contained in:
electria 2026-06-25 14:24:07 -07:00
commit 1ea9e22d01
Signed by: electria
SSH key fingerprint: SHA256:8LlB3ucPbBHqozqkhsNbaV5oG3SlzzqUj8FZDL6IPQs
3 changed files with 208 additions and 7 deletions

View file

@ -1,20 +1,164 @@
use iced::{Element, Renderer, Theme, widget};
use std::fs;
use iced::{
Color, Element, Renderer, Theme,
alignment::{Horizontal, Vertical},
color, widget,
};
mod data;
enum Message {}
macro_rules! data {
() => {
dirs::data_dir().unwrap().join("fridge.ron")
};
}
struct State {}
#[derive(Clone, Debug)]
enum Message {
AddCategory,
RemoveCategory {
i_category: usize,
},
CategoryChanged {
i_category: usize,
new_value: String,
},
AddElement {
i_category: usize,
},
RemoveElement {
i_category: usize,
i_element: usize,
},
ElementChanged {
i_category: usize,
i_element: usize,
new_value: String,
},
}
#[derive(Clone, Debug, Default)]
struct State {
table: data::Table,
}
impl State {
fn new() -> Self {
Self {}
let mut state = Self::default();
if let Ok(file) =
fs::File::open(data!()).inspect_err(|e| eprintln!("failed to read data file: {e}"))
{
state.table = ron::de::from_reader(file).unwrap();
}
state
}
fn view(&self) -> Element<'_, Message, Theme, Renderer> {
widget::space().into()
widget::row(self.table.iter().enumerate().map(|(i_category, category)| {
widget::column([
widget::row([
widget::text_input("category", &category.header)
.on_input(move |new_value| Message::CategoryChanged {
i_category,
new_value,
})
.size(30)
.into(),
widget::button("X")
.style(widget::button::danger)
.on_press(Message::RemoveCategory { i_category })
.height(50)
.into(),
])
.align_y(Vertical::Center)
.into(),
widget::scrollable(widget::column(category.elements.iter().enumerate().map(
|(i_element, element)| {
widget::row([
widget::text_input("content", &element)
.on_input(move |new_value| Message::ElementChanged {
i_category,
i_element,
new_value,
})
.into(),
widget::button("X")
.style(widget::button::warning)
.on_press(Message::RemoveElement {
i_category,
i_element,
})
.into(),
])
.into()
},
)))
.into(),
widget::button("add element")
.on_press(Message::AddElement { i_category })
.into(),
])
.align_x(Horizontal::Center)
.into()
}))
.push(widget::button("add category").on_press(Message::AddCategory))
.into()
}
fn update(&mut self, message: Message) {
match message {
Message::AddCategory => {
self.table.push(Default::default());
}
Message::RemoveCategory { i_category } => {
self.table.remove(i_category);
}
Message::CategoryChanged {
i_category,
new_value,
} => {
self.table[i_category].header = new_value;
}
Message::AddElement { i_category } => {
self.table[i_category].elements.push(Default::default());
}
Message::RemoveElement {
i_category,
i_element,
} => {
self.table[i_category].elements.remove(i_element);
}
Message::ElementChanged {
i_category,
i_element,
new_value,
} => {
self.table[i_category].elements[i_element] = new_value;
}
}
}
}
impl Drop for State {
fn drop(&mut self) {
ron::Options::default()
.to_io_writer(fs::File::create(data!()).unwrap(), &self.table)
.unwrap();
}
fn update(&mut self, message: Message) {}
}
fn main() -> Result<(), iced::Error> {
iced::application(State::new, State::update, State::view).run()
iced::application(State::new, State::update, State::view)
.theme(Theme::custom(
"custom",
iced::theme::Palette {
background: color!(0x080808),
text: Color::WHITE,
primary: color!(0xff00ff),
success: color!(0x00ff00),
warning: color!(0x880000),
danger: color!(0xff0000),
},
))
.run()
}