refacatoring
This commit is contained in:
parent
a9582750fc
commit
f925f33348
@ -4,4 +4,4 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
iced = { version = "0.13.1", features = ["advanced"] }
|
iced = { version = "0.13.1"}
|
30
src/def.rs
Normal file
30
src/def.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use iced::Event;
|
||||||
|
|
||||||
|
pub struct TaskData {
|
||||||
|
pub(crate) checked: bool,
|
||||||
|
pub(crate) value: String,
|
||||||
|
pub(crate) edit: bool,
|
||||||
|
pub(crate) can_update: bool,
|
||||||
|
pub(crate) can_delete: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Todo {
|
||||||
|
pub(crate) new_task: String,
|
||||||
|
pub(crate) updated_task: String,
|
||||||
|
pub(crate) tasks: Vec<TaskData>,
|
||||||
|
pub(crate) completed_tasks: usize,
|
||||||
|
pub(crate) local_storage: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Message {
|
||||||
|
AddTask,
|
||||||
|
CheckTask(bool, usize),
|
||||||
|
EditTask(usize),
|
||||||
|
DeleteTask(usize),
|
||||||
|
DeleteAll,
|
||||||
|
ContentUpdated(bool, String),
|
||||||
|
Event(Event),
|
||||||
|
TaskPush(Option<usize>),
|
||||||
|
StorageToggle(bool),
|
||||||
|
}
|
219
src/main.rs
219
src/main.rs
@ -1,15 +1,9 @@
|
|||||||
use iced::keyboard::key;
|
|
||||||
use iced::widget::{button, center, checkbox, column, row, scrollable, text_input, Space, Text};
|
|
||||||
use iced::window::Settings;
|
use iced::window::Settings;
|
||||||
use iced::{event, keyboard, widget, Center, Element, Event, Length, Size, Subscription, Task, Theme};
|
use iced::Size;
|
||||||
|
use def::Todo;
|
||||||
|
|
||||||
struct TaskData {
|
mod todo;
|
||||||
checked: bool,
|
mod def;
|
||||||
value: String,
|
|
||||||
edit: bool,
|
|
||||||
can_update: bool,
|
|
||||||
can_delete: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> iced::Result {
|
fn main() -> iced::Result {
|
||||||
let settings = Settings {
|
let settings = Settings {
|
||||||
@ -23,209 +17,4 @@ fn main() -> iced::Result {
|
|||||||
.theme(Todo::theme)
|
.theme(Todo::theme)
|
||||||
.window(settings)
|
.window(settings)
|
||||||
.run()
|
.run()
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct Todo {
|
|
||||||
new_task: String,
|
|
||||||
updated_task: String,
|
|
||||||
tasks: Vec<TaskData>,
|
|
||||||
completed_tasks: usize,
|
|
||||||
local_storage: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
enum Message {
|
|
||||||
AddTask,
|
|
||||||
CheckTask(bool, usize),
|
|
||||||
EditTask(usize),
|
|
||||||
DeleteTask(usize),
|
|
||||||
DeleteAll,
|
|
||||||
ContentUpdated(bool, String),
|
|
||||||
Event(Event),
|
|
||||||
TaskPush(Option<usize>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Todo {
|
|
||||||
fn update(&mut self, message: Message) -> Task<Message> {
|
|
||||||
match message {
|
|
||||||
Message::ContentUpdated(new, value) => {
|
|
||||||
if new {
|
|
||||||
self.new_task = value
|
|
||||||
} else {
|
|
||||||
self.updated_task = value
|
|
||||||
}
|
|
||||||
|
|
||||||
Task::none()
|
|
||||||
}
|
|
||||||
Message::AddTask => {
|
|
||||||
if self.new_task.is_empty() { return Task::none(); }
|
|
||||||
|
|
||||||
let data = TaskData {
|
|
||||||
checked: false,
|
|
||||||
value: self.new_task.to_string(),
|
|
||||||
edit: false,
|
|
||||||
can_update: true,
|
|
||||||
can_delete: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.tasks.push(data);
|
|
||||||
self.new_task = String::new();
|
|
||||||
|
|
||||||
Task::none()
|
|
||||||
},
|
|
||||||
Message::DeleteTask(id) => {
|
|
||||||
if self.tasks[id].checked {
|
|
||||||
self.completed_tasks -= 1;
|
|
||||||
}
|
|
||||||
self.tasks.remove(id);
|
|
||||||
|
|
||||||
Task::none()
|
|
||||||
},
|
|
||||||
Message::CheckTask(choice, id) => {
|
|
||||||
self.completed_tasks = if choice { self.completed_tasks + 1 } else { self.completed_tasks - 1 };
|
|
||||||
self.tasks[id].checked = choice;
|
|
||||||
|
|
||||||
Task::none()
|
|
||||||
},
|
|
||||||
Message::EditTask(id) => {
|
|
||||||
let set_update;
|
|
||||||
|
|
||||||
if self.tasks[id].edit {
|
|
||||||
if self.updated_task.is_empty() {
|
|
||||||
return Task::none();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.tasks[id].value = self.updated_task.clone();
|
|
||||||
set_update = true;
|
|
||||||
self.updated_task = String::new();
|
|
||||||
} else {
|
|
||||||
set_update = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.tasks[id].edit = !self.tasks[id].edit;
|
|
||||||
self.set_other_update(id, set_update);
|
|
||||||
|
|
||||||
widget::focus_previous()
|
|
||||||
},
|
|
||||||
Message::DeleteAll => {
|
|
||||||
self.new_task = String::from("");
|
|
||||||
self.updated_task = String::from("");
|
|
||||||
self.tasks.clear();
|
|
||||||
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),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn view(&self) -> Element<Message> {
|
|
||||||
let input = text_input("Enter new task", &self.new_task)
|
|
||||||
.width(300)
|
|
||||||
.size(25)
|
|
||||||
.on_input(|str| Message::ContentUpdated(true, str))
|
|
||||||
.on_submit(Message::TaskPush(None));
|
|
||||||
|
|
||||||
let add_btn = button(
|
|
||||||
Text::new("Add")
|
|
||||||
.size(19)
|
|
||||||
.center()
|
|
||||||
)
|
|
||||||
.width(Length::Shrink)
|
|
||||||
.padding(10)
|
|
||||||
.on_press(Message::AddTask);
|
|
||||||
|
|
||||||
let clear_btn = button(
|
|
||||||
Text::new("Clear")
|
|
||||||
.size(19)
|
|
||||||
.center()
|
|
||||||
)
|
|
||||||
.width(Length::Shrink)
|
|
||||||
.padding(10)
|
|
||||||
.style(button::danger)
|
|
||||||
.on_press(Message::DeleteAll);
|
|
||||||
|
|
||||||
let new_task = row![input, add_btn, clear_btn].spacing(10);
|
|
||||||
let mut saved_tasks = column![];
|
|
||||||
|
|
||||||
for (i, task) in self.tasks.iter().enumerate() {
|
|
||||||
let chk = checkbox("", task.checked).size(25).on_toggle(move |b| Message::CheckTask(b, i));
|
|
||||||
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))
|
|
||||||
.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 mut task_line = row![chk];
|
|
||||||
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]);
|
|
||||||
|
|
||||||
saved_tasks = saved_tasks.push(task_line);
|
|
||||||
}
|
|
||||||
|
|
||||||
let status = Text::new(format!("{} / {}", self.completed_tasks, self.tasks.len()));
|
|
||||||
let storage = checkbox("Local storage", true);
|
|
||||||
let footer = row![status, Space::with_width(Length::Fill), storage].padding(10);
|
|
||||||
|
|
||||||
let mut output = column![new_task.padding(10)];
|
|
||||||
output = if self.tasks.is_empty() { output.push(saved_tasks.height(Length::Fill)) } else { output.push(scrollable(saved_tasks).height(Length::Fill).spacing(10)) };
|
|
||||||
output = output.align_x(Center).push(footer);
|
|
||||||
|
|
||||||
center(output).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn theme(&self) -> Theme {
|
|
||||||
Theme::Dark
|
|
||||||
}
|
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
|
||||||
event::listen().map(Message::Event)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_other_update(&mut self, id: usize, enable: bool) {
|
|
||||||
for (i, task) in self.tasks.iter_mut().enumerate() {
|
|
||||||
if id != i {
|
|
||||||
task.can_update = enable;
|
|
||||||
}
|
|
||||||
task.can_delete = enable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
215
src/todo.rs
Normal file
215
src/todo.rs
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
use iced::{event, keyboard, widget, Center, Element, Event, Length, Subscription, Task, Theme};
|
||||||
|
use iced::keyboard::key;
|
||||||
|
use iced::widget::{button, center, checkbox, column, row, scrollable, text_input, Space, Text};
|
||||||
|
use crate::def::{Message, TaskData, Todo};
|
||||||
|
|
||||||
|
impl Default for Todo {
|
||||||
|
fn default() -> Self {
|
||||||
|
Todo::new()
|
||||||
|
// startup checks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Todo {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
new_task: String::new(),
|
||||||
|
updated_task: String::new(),
|
||||||
|
tasks: Vec::new(),
|
||||||
|
completed_tasks: 0,
|
||||||
|
local_storage: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) fn update(&mut self, message: Message) -> Task<Message> {
|
||||||
|
match message {
|
||||||
|
Message::ContentUpdated(new, value) => {
|
||||||
|
if new {
|
||||||
|
self.new_task = value
|
||||||
|
} else {
|
||||||
|
self.updated_task = value
|
||||||
|
}
|
||||||
|
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
|
Message::AddTask => {
|
||||||
|
if self.new_task.is_empty() { return Task::none(); }
|
||||||
|
|
||||||
|
let data = TaskData {
|
||||||
|
checked: false,
|
||||||
|
value: self.new_task.to_string(),
|
||||||
|
edit: false,
|
||||||
|
can_update: true,
|
||||||
|
can_delete: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.tasks.push(data);
|
||||||
|
self.new_task = String::new();
|
||||||
|
|
||||||
|
Task::none()
|
||||||
|
},
|
||||||
|
Message::DeleteTask(id) => {
|
||||||
|
if self.tasks[id].checked {
|
||||||
|
self.completed_tasks -= 1;
|
||||||
|
}
|
||||||
|
self.tasks.remove(id);
|
||||||
|
|
||||||
|
Task::none()
|
||||||
|
},
|
||||||
|
Message::CheckTask(choice, id) => {
|
||||||
|
self.completed_tasks = if choice { self.completed_tasks + 1 } else { self.completed_tasks - 1 };
|
||||||
|
self.tasks[id].checked = choice;
|
||||||
|
|
||||||
|
Task::none()
|
||||||
|
},
|
||||||
|
Message::EditTask(id) => {
|
||||||
|
let set_update;
|
||||||
|
|
||||||
|
if self.tasks[id].edit {
|
||||||
|
if self.updated_task.is_empty() {
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tasks[id].value = self.updated_task.clone();
|
||||||
|
set_update = true;
|
||||||
|
self.updated_task = String::new();
|
||||||
|
} else {
|
||||||
|
set_update = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tasks[id].edit = !self.tasks[id].edit;
|
||||||
|
self.set_other_update(id, set_update);
|
||||||
|
|
||||||
|
widget::focus_previous()
|
||||||
|
},
|
||||||
|
Message::DeleteAll => {
|
||||||
|
self.new_task = String::from("");
|
||||||
|
self.updated_task = String::from("");
|
||||||
|
self.tasks.clear();
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Message::StorageToggle(toggle) => {
|
||||||
|
self.local_storage = toggle;
|
||||||
|
|
||||||
|
/*
|
||||||
|
todo
|
||||||
|
here we only call for storage change not implement the whole system
|
||||||
|
as the system should be running since the program startup
|
||||||
|
*/
|
||||||
|
|
||||||
|
Task::none()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn view(&self) -> Element<Message> {
|
||||||
|
let input = text_input("Enter new task", &self.new_task)
|
||||||
|
.width(300)
|
||||||
|
.size(25)
|
||||||
|
.on_input(|str| Message::ContentUpdated(true, str))
|
||||||
|
.on_submit(Message::TaskPush(None));
|
||||||
|
|
||||||
|
let add_btn = button(
|
||||||
|
Text::new("Add")
|
||||||
|
.size(19)
|
||||||
|
.center()
|
||||||
|
)
|
||||||
|
.width(Length::Shrink)
|
||||||
|
.padding(10)
|
||||||
|
.on_press(Message::AddTask);
|
||||||
|
|
||||||
|
let clear_btn = button(
|
||||||
|
Text::new("Clear")
|
||||||
|
.size(19)
|
||||||
|
.center()
|
||||||
|
)
|
||||||
|
.width(Length::Shrink)
|
||||||
|
.padding(10)
|
||||||
|
.style(button::danger)
|
||||||
|
.on_press(Message::DeleteAll);
|
||||||
|
|
||||||
|
let new_task = row![input, add_btn, clear_btn].spacing(10);
|
||||||
|
let mut saved_tasks = column![];
|
||||||
|
|
||||||
|
for (i, task) in self.tasks.iter().enumerate() {
|
||||||
|
let chk = checkbox("", task.checked).size(25).on_toggle(move |b| Message::CheckTask(b, i));
|
||||||
|
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))
|
||||||
|
.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 mut task_line = row![chk];
|
||||||
|
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]);
|
||||||
|
|
||||||
|
saved_tasks = saved_tasks.push(task_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = Text::new(format!("{} / {}", self.completed_tasks, self.tasks.len()));
|
||||||
|
let storage = checkbox("Local storage", self.local_storage).on_toggle(Message::StorageToggle);
|
||||||
|
let footer = row![status, Space::with_width(Length::Fill), storage].padding(10);
|
||||||
|
|
||||||
|
let mut output = column![new_task.padding(10)];
|
||||||
|
output = if self.tasks.is_empty() { output.push(saved_tasks.height(Length::Fill)) } else { output.push(scrollable(saved_tasks).height(Length::Fill).spacing(10)) };
|
||||||
|
output = output.align_x(Center).push(footer);
|
||||||
|
|
||||||
|
center(output).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn theme(&self) -> Theme {
|
||||||
|
Theme::Dark
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn subscription(&self) -> Subscription<Message> {
|
||||||
|
event::listen().map(Message::Event)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_other_update(&mut self, id: usize, enable: bool) {
|
||||||
|
for (i, task) in self.tasks.iter_mut().enumerate() {
|
||||||
|
if id != i {
|
||||||
|
task.can_update = enable;
|
||||||
|
}
|
||||||
|
task.can_delete = enable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user