11use iced:: alignment;
22use iced:: executor;
3- use iced:: theme:: { self , Theme } ;
43use iced:: time;
54use iced:: widget:: { button, column, container, row, text} ;
6- use iced:: { Alignment , Application , Command , Element , Event , Length , Settings , Subscription } ;
5+ use iced:: { Alignment , Application , Command , Event , Length , Settings , Subscription } ;
6+
7+ mod theme;
8+ use self :: widget:: Element ;
9+ use theme:: Theme ;
710
811use cosmic_time:: {
912 self ,
1013 style_button:: { self , StyleButton } ,
11- Timeline ,
14+ style_container:: { self , StyleContainer } ,
15+ Sinusoidal , Timeline ,
1216} ;
1317use once_cell:: sync:: Lazy ;
1418
1519static BUTTON : Lazy < style_button:: Id > = Lazy :: new ( style_button:: Id :: unique) ;
20+ static CONTAINER : Lazy < style_container:: Id > = Lazy :: new ( style_container:: Id :: unique) ;
1621
1722use std:: time:: { Duration , Instant } ;
1823
@@ -45,9 +50,11 @@ impl Application for Stopwatch {
4550 type Flags = ( ) ;
4651
4752 fn new ( _flags : ( ) ) -> ( Stopwatch , Command < Message > ) {
53+ let mut timeline = Timeline :: new ( ) ;
54+ timeline. set_chain_paused ( anim_background ( ) ) . start ( ) ;
4855 (
4956 Stopwatch {
50- timeline : Timeline :: new ( ) ,
57+ timeline : timeline ,
5158 duration : Duration :: default ( ) ,
5259 state : State :: Idle ,
5360 } ,
@@ -56,7 +63,7 @@ impl Application for Stopwatch {
5663 }
5764
5865 fn title ( & self ) -> String {
59- String :: from ( "Stopwatch - Iced " )
66+ String :: from ( "Stopwatch - Cosmic-Time " )
6067 }
6168
6269 fn update ( & mut self , message : Message ) -> Command < Message > {
@@ -66,11 +73,17 @@ impl Application for Stopwatch {
6673 self . state = State :: Ticking {
6774 last_tick : Instant :: now ( ) ,
6875 } ;
69- self . timeline . set_chain ( anim_to_destructive ( ) ) . start ( ) ;
76+ self . timeline
77+ . set_chain ( anim_to_destructive ( ) )
78+ . resume ( CONTAINER . clone ( ) )
79+ . start ( ) ;
7080 }
7181 State :: Ticking { .. } => {
7282 self . state = State :: Idle ;
73- self . timeline . set_chain ( anim_to_primary ( ) ) . start ( ) ;
83+ self . timeline
84+ . set_chain ( anim_to_primary ( ) )
85+ . pause ( CONTAINER . clone ( ) )
86+ . start ( ) ;
7487 }
7588 } ,
7689 Message :: Tick ( now) => {
@@ -82,6 +95,10 @@ impl Application for Stopwatch {
8295 }
8396 Message :: Reset => {
8497 self . duration = Duration :: default ( ) ;
98+ match self . state {
99+ State :: Idle => self . timeline . set_chain_paused ( anim_background ( ) ) . start ( ) ,
100+ State :: Ticking { .. } => self . timeline . set_chain ( anim_background ( ) ) . start ( ) ,
101+ }
85102 }
86103 }
87104
@@ -156,31 +173,73 @@ impl Application for Stopwatch {
156173 . align_items ( Alignment :: Center )
157174 . spacing ( 20 ) ;
158175
159- container ( content)
160- . width ( Length :: Fill )
161- . height ( Length :: Fill )
162- . center_x ( )
163- . center_y ( )
164- . into ( )
176+ StyleContainer :: as_widget (
177+ CONTAINER . clone ( ) ,
178+ // Cool! Because we implemented the function on our custom, theme's type, adding
179+ // the map argument is easy!
180+ theme:: Container :: map ( ) ,
181+ & self . timeline ,
182+ content,
183+ )
184+ . width ( Length :: Fill )
185+ . height ( Length :: Fill )
186+ . center_x ( )
187+ . center_y ( )
188+ . into ( )
165189 }
166190}
167191
168192fn anim_to_primary ( ) -> style_button:: Chain {
169193 style_button:: Chain :: new ( BUTTON . clone ( ) )
170- . link ( StyleButton :: new ( Duration :: ZERO ) . style ( as_u8 ( theme:: Button :: Destructive ) ) )
171- . link ( StyleButton :: new ( Duration :: from_millis ( 500 ) ) . style ( as_u8 ( theme:: Button :: Primary ) ) )
194+ . link ( StyleButton :: new ( Duration :: ZERO ) . style ( button_u8 ( theme:: Button :: Destructive ) ) )
195+ . link ( StyleButton :: new ( Duration :: from_millis ( 500 ) ) . style ( button_u8 ( theme:: Button :: Primary ) ) )
172196}
173197
174198fn anim_to_destructive ( ) -> style_button:: Chain {
175199 style_button:: Chain :: new ( BUTTON . clone ( ) )
176- . link ( StyleButton :: new ( Duration :: ZERO ) . style ( as_u8 ( theme:: Button :: Primary ) ) )
177- . link ( StyleButton :: new ( Duration :: from_millis ( 500 ) ) . style ( as_u8 ( theme:: Button :: Destructive ) ) )
200+ . link ( StyleButton :: new ( Duration :: ZERO ) . style ( button_u8 ( theme:: Button :: Primary ) ) )
201+ . link (
202+ StyleButton :: new ( Duration :: from_millis ( 500 ) )
203+ . style ( button_u8 ( theme:: Button :: Destructive ) ) ,
204+ )
205+ }
206+
207+ fn anim_background ( ) -> style_container:: Chain {
208+ style_container:: Chain :: new ( CONTAINER . clone ( ) )
209+ . link ( StyleContainer :: new ( Duration :: ZERO ) . style ( theme:: Container :: Red ) )
210+ . link (
211+ StyleContainer :: new ( Duration :: from_secs ( 3 ) )
212+ // Notice how we can just pass the enum value here, where in the `anim_to_primary/destructive`
213+ // we have to use the fucntion `button_u8`? Because we use a implemented a custom iced theme,
214+ // we can just impl Into<u8> on the enum, and it works here!
215+ . style ( theme:: Container :: Green )
216+ . ease ( Sinusoidal :: In ) ,
217+ )
218+ . link (
219+ StyleContainer :: new ( Duration :: from_secs ( 6 ) )
220+ . style ( theme:: Container :: Blue )
221+ . ease ( Sinusoidal :: In ) ,
222+ )
223+ . link (
224+ StyleContainer :: new ( Duration :: from_secs ( 9 ) )
225+ . style ( theme:: Container :: Red )
226+ . ease ( Sinusoidal :: In ) ,
227+ )
228+ . loop_forever ( )
178229}
179230
180231// Style implementations
181232
233+ // Here the button example uses Iced's default theme
234+ // enum. So we have to have some helper functions to make it work.
235+ // we also have another closture, `buttons`, in `fn view()`
236+ //
237+ // For themining reasons, this actually isn't iced's default
238+ // button theme, but the implementation here for button is what you
239+ // would have to do to use the iced type in your project.
240+
182241// the enum's default must be 0
183- fn as_u8 ( style : theme:: Button ) -> u8 {
242+ fn button_u8 ( style : theme:: Button ) -> u8 {
184243 match style {
185244 theme:: Button :: Primary => 0 ,
186245 theme:: Button :: Secondary => 1 ,
@@ -190,3 +249,40 @@ fn as_u8(style: theme::Button) -> u8 {
190249 _ => panic ! ( "Custom is not supported" ) ,
191250 }
192251}
252+
253+ // But! if we are useing a custom theme then
254+ // the code cleans up quite a bit.
255+
256+ impl From < theme:: Container > for u8 {
257+ fn from ( style : theme:: Container ) -> Self {
258+ match style {
259+ theme:: Container :: White => 0 ,
260+ theme:: Container :: Red => 1 ,
261+ theme:: Container :: Green => 2 ,
262+ theme:: Container :: Blue => 3 ,
263+ }
264+ }
265+ }
266+
267+ impl theme:: Container {
268+ fn map ( ) -> fn ( u8 ) -> theme:: Container {
269+ |i : u8 | match i {
270+ 0 => theme:: Container :: White ,
271+ 1 => theme:: Container :: Red ,
272+ 2 => theme:: Container :: Green ,
273+ 3 => theme:: Container :: Blue ,
274+ _ => panic ! ( "Impossible" ) ,
275+ }
276+ }
277+ }
278+
279+ // Just for themeing, not a part of this example.
280+ mod widget {
281+ #![ allow( dead_code) ]
282+ use crate :: theme:: Theme ;
283+
284+ pub type Renderer = iced:: Renderer < Theme > ;
285+ pub type Element < ' a , Message > = iced:: Element < ' a , Message , Renderer > ;
286+ pub type Container < ' a , Message > = iced:: widget:: Container < ' a , Message , Renderer > ;
287+ pub type Button < ' a , Message > = iced:: widget:: Button < ' a , Message , Renderer > ;
288+ }
0 commit comments