@@ -8,11 +8,12 @@ use cosmic::iced_core::text;
88use cosmic:: iced_core:: time:: Duration ;
99use cosmic:: iced_core:: widget:: Tree ;
1010use cosmic:: iced_core:: {
11- Alignment , Clipboard , Element , Event , Layout , Length , Pixels , Point , Rectangle , Shell , Widget ,
11+ Alignment , Clipboard , Element , Event , Layout , Length , Pixels , Point , Rectangle ,
12+ Shell , Widget ,
1213} ;
1314use cosmic:: iced_widget:: { Row , Text } ;
1415
15- use crate :: keyframes :: { self , toggler:: Chain } ;
16+ use crate :: { chain , id , lerp , toggler} ;
1617pub use cosmic:: iced_style:: toggler:: { Appearance , StyleSheet } ;
1718
1819/// The default animation duration. Change here for custom widgets. Or at runtime with `.anim_multiplier`
4041 Renderer : text:: Renderer ,
4142 Renderer :: Theme : StyleSheet ,
4243{
43- id : crate :: keyframes :: toggler :: Id ,
44+ id : id :: Toggler ,
4445 is_toggled : bool ,
45- on_toggle : Box < dyn Fn ( Chain , bool ) -> Message + ' a > ,
46+ on_toggle : Box < dyn Fn ( chain :: Toggler , bool ) -> Message + ' a > ,
4647 label : Option < String > ,
4748 width : Length ,
4849 size : f32 ,
7374 /// * a function that will be called when the [`Toggler`] is toggled. It
7475 /// will receive the new state of the [`Toggler`] and must produce a
7576 /// `Message`.
76- pub fn new < F > (
77- id : crate :: keyframes:: toggler:: Id ,
78- label : impl Into < Option < String > > ,
79- is_toggled : bool ,
80- f : F ,
81- ) -> Self
77+ pub fn new < F > ( id : id:: Toggler , label : impl Into < Option < String > > , is_toggled : bool , f : F ) -> Self
8278 where
83- F : ' a + Fn ( Chain , bool ) -> Message ,
79+ F : ' a + Fn ( chain :: Toggler , bool ) -> Message ,
8480 {
8581 Toggler {
8682 id,
@@ -221,25 +217,20 @@ where
221217 // TODO this should be possible to fix once redirectable
222218 // animations are implemented.
223219 if mouse_over && ( self . percent == 0.0 || self . percent == 1.0 ) {
220+ let duration = ( ANIM_DURATION * self . anim_multiplier . round ( ) ) as u64 ;
224221 if self . is_toggled {
225- let off_animation = Chain :: new ( self . id . clone ( ) )
226- . link ( keyframes:: toggler:: Toggler :: new ( Duration :: ZERO ) . percent ( 1.0 ) )
227- . link (
228- keyframes:: toggler:: Toggler :: new ( Duration :: from_millis (
229- ( ANIM_DURATION * self . anim_multiplier . round ( ) ) as u64 ,
230- ) )
231- . percent ( 0.0 ) ,
232- ) ;
222+ let off_animation = chain ! (
223+ self . id. clone( ) ,
224+ toggler( Duration :: ZERO ) . percent( 1.0 ) ,
225+ toggler( Duration :: from_millis( duration) ) . percent( 0.0 ) ,
226+ ) ;
233227 shell. publish ( ( self . on_toggle ) ( off_animation, !self . is_toggled ) ) ;
234228 } else {
235- let on_animation = Chain :: new ( self . id . clone ( ) )
236- . link ( keyframes:: toggler:: Toggler :: new ( Duration :: ZERO ) . percent ( 0.0 ) )
237- . link (
238- keyframes:: toggler:: Toggler :: new ( Duration :: from_millis (
239- ( ANIM_DURATION * self . anim_multiplier . round ( ) ) as u64 ,
240- ) )
241- . percent ( 1.0 ) ,
242- ) ;
229+ let on_animation = chain ! (
230+ self . id. clone( ) ,
231+ toggler( Duration :: ZERO ) . percent( 0.0 ) ,
232+ toggler( Duration :: from_millis( duration) ) . percent( 1.0 ) ,
233+ ) ;
243234 shell. publish ( ( self . on_toggle ) ( on_animation, !self . is_toggled ) ) ;
244235 }
245236
@@ -310,9 +301,17 @@ where
310301 let is_mouse_over = bounds. contains ( cursor_position) ;
311302
312303 let style = if is_mouse_over {
313- theme. hovered ( & self . style , self . is_toggled )
304+ blend_appearances (
305+ theme. hovered ( & self . style , false ) ,
306+ theme. hovered ( & self . style , true ) ,
307+ self . percent ,
308+ )
314309 } else {
315- theme. active ( & self . style , self . is_toggled )
310+ blend_appearances (
311+ theme. active ( & self . style , false ) ,
312+ theme. active ( & self . style , true ) ,
313+ self . percent ,
314+ )
316315 } ;
317316
318317 let border_radius = bounds. height / BORDER_RADIUS_RATIO ;
@@ -337,11 +336,11 @@ where
337336
338337 let toggler_foreground_bounds = Rectangle {
339338 x : bounds. x
340- + if self . is_toggled {
341- bounds . width - 2.0 * space - ( bounds . height - ( 4.0 * space ) )
342- } else {
343- 2.0 * space
344- } ,
339+ + lerp (
340+ 2.0 * space,
341+ bounds . width - 2.0 * space - ( bounds . height - ( 4.0 * space ) ) ,
342+ self . percent ,
343+ ) ,
345344 y : bounds. y + ( 2.0 * space) ,
346345 width : bounds. height - ( 4.0 * space) ,
347346 height : bounds. height - ( 4.0 * space) ,
@@ -369,3 +368,24 @@ where
369368 Element :: new ( toggler)
370369 }
371370}
371+
372+ fn blend_appearances ( one : Appearance , mut two : Appearance , percent : f32 ) -> Appearance {
373+ if percent == 0. {
374+ one
375+ } else if percent == 1. {
376+ two
377+ } else {
378+ let background: [ f32 ; 4 ] = one
379+ . background
380+ . into_linear ( )
381+ . iter ( )
382+ . zip ( two. background . into_linear ( ) . iter ( ) )
383+ . map ( |( o, t) | o * ( 1.0 - percent) + t * percent)
384+ . collect :: < Vec < f32 > > ( )
385+ . try_into ( )
386+ . unwrap ( ) ;
387+
388+ two. background = background. into ( ) ;
389+ two
390+ }
391+ }
0 commit comments