This commit is contained in:
Martin Vrhovšek 2025-02-01 13:55:54 +01:00
parent 589da50def
commit 6a8ea96c1c
2 changed files with 100 additions and 52 deletions

View File

@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
iced = "0.13.1" iced = { version = "0.13.1", features = ["advanced"] }

View File

@ -1,13 +1,14 @@
use iced::keyboard::key;
use iced::widget::{button, center, checkbox, column, row, scrollable, text_input, Text}; use iced::widget::{button, center, checkbox, column, row, scrollable, text_input, Text};
use iced::window::Settings; use iced::window::Settings;
use iced::{Element, Length, Size, Theme}; use iced::{event, keyboard, widget, Element, Event, Length, Size, Subscription, Task, Theme};
use std::collections::HashMap;
struct TaskData { struct TaskData {
checked: bool, checked: bool,
value: String, value: String,
edit: bool, edit: bool,
can_update: bool, can_update: bool,
can_delete: bool,
} }
fn main() -> iced::Result { fn main() -> iced::Result {
@ -18,6 +19,7 @@ fn main() -> iced::Result {
}; };
iced::application("To Do App", Todo::update, Todo::view) iced::application("To Do App", Todo::update, Todo::view)
.subscription(Todo::subscription)
.theme(Todo::theme) .theme(Todo::theme)
.window(settings) .window(settings)
.run() .run()
@ -27,8 +29,7 @@ fn main() -> iced::Result {
struct Todo { struct Todo {
new_task: String, new_task: String,
updated_task: String, updated_task: String,
tasks: HashMap<usize, TaskData>, tasks: Vec<TaskData>,
task_id: usize,
completed_tasks: usize, completed_tasks: usize,
} }
@ -40,10 +41,12 @@ enum Message {
DeleteTask(usize), DeleteTask(usize),
DeleteAll, DeleteAll,
ContentUpdated(bool, String), ContentUpdated(bool, String),
Event(Event),
TaskPush(Option<usize>),
} }
impl Todo { impl Todo {
fn update(&mut self, message: Message) { fn update(&mut self, message: Message) -> Task<Message> {
match message { match message {
Message::ContentUpdated(new, value) => { Message::ContentUpdated(new, value) => {
if new { if new {
@ -51,63 +54,97 @@ impl Todo {
} else { } else {
self.updated_task = value self.updated_task = value
} }
Task::none()
} }
Message::AddTask => { Message::AddTask => {
if self.new_task.is_empty() { return; } if self.new_task.is_empty() { return Task::none(); }
let data = TaskData { let data = TaskData {
checked: false, checked: false,
value: self.new_task.to_string(), value: self.new_task.to_string(),
edit: false, edit: false,
can_update: true, can_update: true,
can_delete: true,
}; };
self.tasks.insert(self.task_id, data); self.tasks.push(data);
self.task_id += 1; self.new_task = String::new();
// temp disable for testing fixme Task::none()
//self.new_task = String::new();
}, },
Message::DeleteTask(id) => { Message::DeleteTask(id) => {
// todo maybe some better checks if self.tasks[id].checked {
if let Some(t) = self.tasks.get_mut(&id) { self.completed_tasks -= 1;
if t.checked {
self.completed_tasks -= 1;
}
} }
self.tasks.remove(id);
if let Some(t) = self.tasks.remove(&id) { Task::none()
println!("Removed {}", t.value);
}
}, },
Message::CheckTask(choice, id) => { Message::CheckTask(choice, id) => {
if let Some(t) = self.tasks.get_mut(&id) { self.completed_tasks = if choice { self.completed_tasks + 1 } else { self.completed_tasks - 1 };
self.completed_tasks = if choice { self.completed_tasks + 1 } else { self.completed_tasks - 1 }; self.tasks[id].checked = choice;
t.checked = choice;
} Task::none()
}, },
Message::EditTask(id) => { Message::EditTask(id) => {
let mut set_update = None; let set_update;
if let Some(t) = self.tasks.get_mut(&id) { if self.tasks[id].edit {
if t.edit == true { if self.updated_task.is_empty() {
t.value = self.updated_task.clone(); return Task::none();
set_update = Some(true);
self.updated_task = String::new();
} else {
set_update = Some(false);
} }
t.edit = !t.edit; self.tasks[id].value = self.updated_task.clone();
set_update = true;
self.updated_task = String::new();
} else {
set_update = false;
} }
if let Some(t) = set_update { self.tasks[id].edit = !self.tasks[id].edit;
self.set_other_update(id, t); self.set_other_update(id, set_update);
}
widget::focus_previous()
}, },
Message::DeleteAll => { Message::DeleteAll => {
self.new_task = String::from("");
self.updated_task = String::from("");
self.tasks.clear(); self.tasks.clear();
self.completed_tasks = 0; self.completed_tasks = 0;
Task::none()
},
Message::Event(event) => match event {
Event::Keyboard(keyboard::Event::KeyPressed {
key: keyboard::Key::Named(key::Named::Tab),
modifiers,
..
}) => {
if modifiers.shift() {
widget::focus_previous()
} else {
widget::focus_next()
}
}
Event::Keyboard(keyboard::Event::KeyPressed {
key: keyboard::Key::Named(key::Named::Delete),
modifiers,
..
}) => {
if modifiers.control() {
Task::perform(async move { Message::DeleteAll }, |result| result)
} else {
Task::none()
}
}
_ => Task::none()
},
Message::TaskPush(option_id) => {
match option_id {
Some(i) => Task::perform(async move { Message::EditTask(i) }, |result| result),
None => Task::perform(async { Message::AddTask }, |result| result),
}
}, },
} }
} }
@ -116,7 +153,8 @@ impl Todo {
let input = text_input("Enter new task", &self.new_task) let input = text_input("Enter new task", &self.new_task)
.width(300) .width(300)
.size(25) .size(25)
.on_input(|str| Message::ContentUpdated(true, str)); .on_input(|str| Message::ContentUpdated(true, str))
.on_submit(Message::TaskPush(None));
let add_btn = button( let add_btn = button(
Text::new("Add") Text::new("Add")
@ -140,18 +178,23 @@ impl Todo {
let new_task = row![input, add_btn, clear_btn].spacing(10); let new_task = row![input, add_btn, clear_btn].spacing(10);
let mut saved_tasks = column![]; let mut saved_tasks = column![];
for task in &self.tasks { for (i, task) in self.tasks.iter().enumerate() {
let chk = checkbox("", task.1.checked).size(25).on_toggle(|b| Message::CheckTask(b, *task.0)); let chk = checkbox("", task.checked).size(25).on_toggle(move |b| Message::CheckTask(b, i));
let label = Text::new(&task.1.value).width(200); let label = Text::new(&task.value).width(200);
let input = text_input("Enter new name", &self.updated_task).width(200).on_input(|str| Message::ContentUpdated(false, str)); let input = text_input("Enter new name", &self.updated_task)
let mut edit = button(if task.1.edit { "save" } else { "edit" }).width(Length::Shrink); .width(200)
if task.1.can_update { .on_input(|str| Message::ContentUpdated(false, str))
edit = edit.on_press(Message::EditTask(*task.0)); .on_submit(Message::TaskPush(Some(i)));
let mut edit = button(if task.edit { "save" } else { "edit" }).width(Length::Shrink);
if task.can_update {
edit = edit.on_press(Message::EditTask(i));
}
let mut delete = button("delete").width(Length::Shrink);
if task.can_delete {
delete = delete.on_press(Message::DeleteTask(i));
} }
let delete = button("delete").width(Length::Shrink).on_press(Message::DeleteTask(*task.0));
let mut task_line = row![chk]; let mut task_line = row![chk];
task_line = if task.1.edit { task_line.push(input) } else { task_line.push(label) }; task_line = if task.edit { task_line.push(input) } else { task_line.push(label) };
task_line = task_line.push(edit).push(delete).spacing(10).padding([5, 10]); task_line = task_line.push(edit).push(delete).spacing(10).padding([5, 10]);
saved_tasks = saved_tasks.push(task_line); saved_tasks = saved_tasks.push(task_line);
@ -170,11 +213,16 @@ impl Todo {
Theme::Dark Theme::Dark
} }
fn subscription(&self) -> Subscription<Message> {
event::listen().map(Message::Event)
}
fn set_other_update(&mut self, id: usize, enable: bool) { fn set_other_update(&mut self, id: usize, enable: bool) {
for task in self.tasks.iter_mut() { for (i, task) in self.tasks.iter_mut().enumerate() {
if id != self.task_id { if id != i {
task.1.can_update = enable; task.can_update = enable;
} }
task.can_delete = enable;
} }
} }
} }