From cf3c53a063b2bb8dcb612e259796fed3fd9b7147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Wed, 13 Nov 2019 07:39:29 +0100 Subject: [PATCH] Implement task edition/deletion in `todos` example --- examples/resources/icons.ttf | Bin 0 -> 5596 bytes examples/todos.rs | 178 +++++++++++++++++++++++++++++++---- 2 files changed, 162 insertions(+), 16 deletions(-) create mode 100644 examples/resources/icons.ttf diff --git a/examples/resources/icons.ttf b/examples/resources/icons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4498299db26811ff8490001ea6f681529a4118f4 GIT binary patch literal 5596 zcmZQzWME+6XJ}wxW+-qE4s}xKR;^-SVEDtpz!2getZ(F|6Qan#z!<>5zz~+4n^r?V3mvv91M&MY%o#ge#Qw5 ztPBiHRZJjX_dsaI2MmUcObiT646Mvh)6uAaG}jachYviTnVEzBXE8)E2Qf^8nh84g9 zG7D@V$lV-J-!OqpW(4^GEH#1&9XEZaC zX9N>s%u5CSDG2BY{CmaE?<1fiu!J#BKu5qwfJsbD;GY6NKcg6!E3lL?UqHZzAC$WO zZ)6r?=4Rk$kY~_mFlUHnh;Rt?wq)X9(^Qlc6tCMqZ*X3c11W=??5XsoWLuFS^HDk{RJ%_u0srmU!>rY@+gq-M)#VrI=~ZpUbD zY$PVnXlx|LD96R2!odY5`oSca=;LCCh_ZA2yZB3*g>@qv3*&1p4l@(ge+H^1jHVzh zYt%V)#5Rd*ajLK7;0j{w1d07C2a!0~Oh%5ZjEt@LIf%VXWMN?pVq;`vWC>?rVPx@^c2L7q$&in!Fw#MY zfk9D0LR^5KlY@bcflY*+Ra9HtT%BFiSd`I3S&5yIO;p6#$ehtkU7S(blu?AAQQaJr zl*CROH5+>{#`CbU{JY4)%gVy2&n)-ipTP@eUy;}su_D%D%_8i^&BiwFOl&+X|1Pnx z@vt!Ju@t`er~i_1maJ&(%NSA7W-(C02h|CT3=Gp4+63bHZN4&aGrs@{-~4C?E+HWF z|BcKqn7P5_3=>Eel0(2{7XwKB|NqP{z~vHD5=^mxWWZREfq^*^EXKfK!SIAJ9ipFs zg&_u%z8OG8r3`}(LoovbLnb$<{0Au(Vz>u4(-f)$R8Dg+m_o&w7}yzXp=@Rb4h9z} zn}vac!3WA_W#DEAfwI{cI2hugY%T_EhIA;Kn?aai5-4x8a56A3WHBs-vKbi!82O=W zCI&u6c_^EiL4Z*g%4T5@V6=s@SsBC_eW7eN1_8!oD4UBRjIkKX=4Mc1Jn5WYP+63j zo>8Kp;jF1(WMF8ikW{IVUzC}inU|QOkXTxhkzZ7-;GmF}pI4HalasHPoSzG02c@Q$ z<|G!uxG*{_wWv5VKTp9>&j2Rmo|>0hlvt9Q0y4e0EZwN2Buyc$C_h)h4Qj4JK~a8I zYI2EQMoCG5mA*bqC&)eqXNG)+0)|S4B8E(cbcPIu5(WhZ4F+chO$G%9BL)KoLk3F* z1%@PsN(Kdne5k5ShCGHuh8zY3hD3%^h7yJhuuL(70)qpC0z(=@K0_Wu2}3GF4nqz@ zK7$@ZGDAK?E{1pzLn=c$Ln%WJLn1>FhAg@%VGOAZMGVCZnPAfu7z`Qo7z{9Uxih3P z2}2s#l|^7zDKNN!O+>g?fuVo_B$vgI%8<-Z!k`BZ zl@f*m1}g@A27L@WVg3WBa8R0N0M*(M1{%r2$i&FZ$im3Vz?7fOT2ho)oWWL*nwOlJ z15wDx!1(_^13!d=L`pD#At*0`@CF7Qg$)d$5w4L63f?;y_yWB*umwj&Y%r1Dpb?pn zrqC4{v4Kf7aVMxTkesZXB(12pfgy4OgR`>BCI&_Z=L9F+4U9S)6cW;OH!$faq$q4S z5U_zoEozenBbT#lvTIOugrc&dbXSDJhJb(w#SIRT(h3_aKrD;MNQI3MMTsdJGy)Z+8Yg6RX4Dx1x6$UNGAqGMkq%rDr|5F zj@ZDcEe-M%)MnictU4RmowYYHFhPQbO=knUvXipH1_ouP#0^YIX&V@mH!vn_VAayy zz^kwLz@zLG zxq%nN3yM(Kz^m*Osk?z+M`42iI7k$BurMTdDJO2=b52m`N>JFqr|hJxyFoz5J0xNw zONvXR$_Cz4993WalXCo(w*3?n30jF~<9fgDq0tpJvps;WTl{cU~q6tb=+BzGwv^QvJ z>2A=`QBZJKz!BWai5AMBvI?&XX~jt04Z83+U=-V+qqTui)BqgHddQ)IDy6TZU}Ws8majG|h)8w_<6Y!uva_+$fvbE1Xr1|uCk zaU0zY#)On^V02El(A{97vyq8GOjSWo!5vi8Y+zFL?CNq?c2`bRh)9wKm3hien~WJ5 zMMbo9H<;>dU=Z8DqPl@a6|7_fr?Ylym!7hMf=!o&?glf2w1OU3fx-qBWham-g$)S- z5egd|0wXpvDKINYZ)Q?smWp%&6>uER3SG)z)yi%O8(5st^GSlj21ad2NzUY)kfOYS z**P&KAYucPbE5PHX6J;+4a}ft6gIG^DZ3?FNGosPaCY0kq`HB_8Ei{}0yayO zLAEGwU~x_Wg*~fk;s#a>Q#Y`vC4%Y(up?9xQUV}F7{abd-3{iTFi=oX*ubg=4FhEx z3*8MCVBrlM%1#Oj3U12o8yK~fL9t~C5(j$#8lns#5qb(X%8Jq;7c)Tw6+mu*1v#7Q z23A#1P*R6gt&oVqOk4@d(3nvMC0{F$O$r-0oT1KANC4Hn=m7_dN^2cu1wBxxxdlZi z*hK1W)MgaX*4uoU9(%s;SL)=YgBLky|@CG9--3{(K8%(rxH+XU!6^iU=cr%8YgYt4gMfCAVvU44Tup4 zQUhWHfz;S(>uv}JsR1!UKx#mYP>>oBBMhX*L0fl2I7khM5dl&IVnl+}fEZCAHO|_) z8=^sKK#UlW8W1BEqz1%@1F5ms*4+>fQUhWnfYg8(i6Au~Mv~43b8S6nm?wic8?3c; zH>7}BHrl!yQb8fJ!CZTTt+wulG@T6=aMkG`4p?;tm<3Xu31)$mX6bCOge%PkallG* zz$}o`TrdlyG*4%P6WMXh(U;qF>l-6AU literal 0 HcmV?d00001 diff --git a/examples/todos.rs b/examples/todos.rs index 7f37300b..e6c932e9 100644 --- a/examples/todos.rs +++ b/examples/todos.rs @@ -1,6 +1,7 @@ use iced::{ - scrollable, text::HorizontalAlignment, text_input, Application, Checkbox, - Color, Column, Container, Element, Length, Scrollable, Text, TextInput, + button, scrollable, text::HorizontalAlignment, text_input, Align, + Application, Background, Button, Checkbox, Color, Column, Container, + Element, Font, Length, Row, Scrollable, Text, TextInput, }; pub fn main() { @@ -19,7 +20,7 @@ struct Todos { pub enum Message { InputChanged(String), CreateTask, - TaskChanged(usize, bool), + TaskMessage(usize, TaskMessage), } impl Application for Todos { @@ -40,9 +41,12 @@ impl Application for Todos { self.input_value.clear(); } } - Message::TaskChanged(i, completed) => { + Message::TaskMessage(i, TaskMessage::Delete) => { + self.tasks.remove(i); + } + Message::TaskMessage(i, task_message) => { if let Some(task) = self.tasks.get_mut(i) { - task.completed = completed; + task.update(task_message); } } } @@ -66,15 +70,29 @@ impl Application for Todos { .size(30) .on_submit(Message::CreateTask); - let tasks = self.tasks.iter_mut().enumerate().fold( - Column::new().spacing(20), - |column, (i, task)| { - column.push( - task.view() - .map(move |state| Message::TaskChanged(i, state)), + let tasks: Element<_> = + if self.tasks.len() > 0 { + self.tasks + .iter_mut() + .enumerate() + .fold(Column::new().spacing(20), |column, (i, task)| { + column.push(task.view().map(move |message| { + Message::TaskMessage(i, message) + })) + }) + .into() + } else { + Container::new( + Text::new("You do not have any tasks! :D") + .size(25) + .horizontal_alignment(HorizontalAlignment::Center) + .color([0.7, 0.7, 0.7]), ) - }, - ); + .width(Length::Fill) + .height(Length::Units(200)) + .center_y() + .into() + }; let content = Column::new() .max_width(800) @@ -94,6 +112,27 @@ impl Application for Todos { struct Task { description: String, completed: bool, + state: TaskState, +} + +#[derive(Debug)] +pub enum TaskState { + Idle { + edit_button: button::State, + }, + Editing { + text_input: text_input::State, + delete_button: button::State, + }, +} + +#[derive(Debug, Clone)] +pub enum TaskMessage { + Completed(bool), + Edit, + DescriptionEdited(String), + FinishEdition, + Delete, } impl Task { @@ -101,12 +140,97 @@ impl Task { Task { description, completed: false, + state: TaskState::Idle { + edit_button: button::State::new(), + }, } } - fn view(&mut self) -> Element { - Checkbox::new(self.completed, &self.description, |checked| checked) - .into() + fn update(&mut self, message: TaskMessage) { + match message { + TaskMessage::Completed(completed) => { + self.completed = completed; + } + TaskMessage::Edit => { + self.state = TaskState::Editing { + text_input: text_input::State::focused(&self.description), + delete_button: button::State::new(), + }; + } + TaskMessage::DescriptionEdited(new_description) => { + self.description = new_description; + } + TaskMessage::FinishEdition => { + if !self.description.is_empty() { + self.state = TaskState::Idle { + edit_button: button::State::new(), + } + } + } + TaskMessage::Delete => {} + } + } + + fn view(&mut self) -> Element { + match &mut self.state { + TaskState::Idle { edit_button } => { + let checkbox = Checkbox::new( + self.completed, + &self.description, + TaskMessage::Completed, + ); + + Row::new() + .spacing(20) + .align_items(Align::Center) + .push(checkbox) + .push( + Button::new( + edit_button, + edit_icon().color([0.5, 0.5, 0.5]), + ) + .on_press(TaskMessage::Edit) + .padding(10), + ) + .into() + } + TaskState::Editing { + text_input, + delete_button, + } => { + let text_input = TextInput::new( + text_input, + "Describe your task...", + &self.description, + TaskMessage::DescriptionEdited, + ) + .on_submit(TaskMessage::FinishEdition) + .padding(10); + + Row::new() + .spacing(20) + .align_items(Align::Center) + .push(text_input) + .push( + Button::new( + delete_button, + Row::new() + .spacing(10) + .push(delete_icon().color(Color::WHITE)) + .push( + Text::new("Delete") + .width(Length::Shrink) + .color(Color::WHITE), + ), + ) + .on_press(TaskMessage::Delete) + .padding(10) + .border_radius(5) + .background(Background::Color([0.8, 0.2, 0.2].into())), + ) + .into() + } + } } } @@ -117,3 +241,25 @@ const GRAY: Color = Color { b: 0.5, a: 1.0, }; + +// Fonts +const ICONS: Font = Font::External { + name: "Icons", + bytes: include_bytes!("./resources/icons.ttf"), +}; + +fn icon(unicode: char) -> Text { + Text::new(&unicode.to_string()) + .font(ICONS) + .width(Length::Units(20)) + .horizontal_alignment(HorizontalAlignment::Center) + .size(20) +} + +fn edit_icon() -> Text { + icon('\u{F303}') +} + +fn delete_icon() -> Text { + icon('\u{F1F8}') +}