@@ -27,7 +27,7 @@ use graphene_std::text::{Font, TextAlign};
2727use graphene_std:: transform:: { Footprint , ReferencePoint , Transform } ;
2828use graphene_std:: vector:: QRCodeErrorCorrectionLevel ;
2929use graphene_std:: vector:: misc:: { ArcType , CentroidType , ExtrudeJoiningAlgorithm , GridType , MergeByDistanceAlgorithm , PointSpacingType , RowsOrColumns , SpiralType } ;
30- use graphene_std:: vector:: style:: { Fill , FillChoice , FillType , GradientStops , GradientType , PaintOrder , StrokeAlign , StrokeCap , StrokeJoin } ;
30+ use graphene_std:: vector:: style:: { Fill , FillChoice , FillType , Gradient , GradientStops , GradientType , PaintOrder , StrokeAlign , StrokeCap , StrokeJoin } ;
3131
3232pub ( crate ) fn string_properties ( text : & str ) -> Vec < LayoutGroup > {
3333 let widget = TextLabel :: new ( text) . widget_instance ( ) ;
@@ -2009,44 +2009,207 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
20092009 Some ( TaggedValue :: StrokeJoin ( x) ) => x,
20102010 _ => & StrokeJoin :: Miter ,
20112011 } ;
2012-
20132012 let dash_lengths_val = match & document_node. inputs [ DashLengthsInput :: < Vec < f64 > > :: INDEX ] . as_value ( ) {
20142013 Some ( TaggedValue :: VecF64 ( x) ) => x,
20152014 _ => & vec ! [ ] ,
20162015 } ;
2016+
20172017 let has_dash_lengths = dash_lengths_val. is_empty ( ) ;
20182018 let miter_limit_disabled = join_value != & StrokeJoin :: Miter ;
20192019
2020- let color = color_widget (
2021- ParameterWidgetsInfo :: new ( node_id, ColorInput :: INDEX , true , context) ,
2022- crate :: messages:: layout:: utility_types:: widgets:: button_widgets:: ColorInput :: default ( ) ,
2020+ let fill = document_node
2021+ . inputs
2022+ . get ( ColorInput :: < Fill > :: INDEX )
2023+ . and_then ( |i| i. as_non_exposed_value ( ) )
2024+ . and_then ( |t| match t {
2025+ TaggedValue :: Fill ( f) => Some ( f. clone ( ) ) ,
2026+ _ => None ,
2027+ } )
2028+ . unwrap_or ( Fill :: None ) ;
2029+ let backup_color = document_node
2030+ . inputs
2031+ . get ( BackupColorInput :: INDEX )
2032+ . and_then ( |i| i. as_non_exposed_value ( ) )
2033+ . and_then ( |t| match t {
2034+ TaggedValue :: Color ( c) => Some ( c. clone ( ) ) ,
2035+ _ => None ,
2036+ } )
2037+ . unwrap_or ( Table :: new ( ) ) ;
2038+ let backup_gradient = document_node
2039+ . inputs
2040+ . get ( BackupGradientInput :: INDEX )
2041+ . and_then ( |i| i. as_non_exposed_value ( ) )
2042+ . and_then ( |t| match t {
2043+ TaggedValue :: Gradient ( g) => Some ( g. clone ( ) ) ,
2044+ _ => None ,
2045+ } )
2046+ . unwrap_or ( Gradient :: default ( ) ) ;
2047+
2048+ let mut widgets = Vec :: new ( ) ;
2049+
2050+ let mut widgets_first_row = start_widgets ( ParameterWidgetsInfo :: new ( node_id, ColorInput :: < Fill > :: INDEX , true , context) ) ;
2051+ let fill2 = fill. clone ( ) ;
2052+ let backup_color_fill: Fill = backup_color. clone ( ) . into ( ) ;
2053+ let backup_gradient_fill: Fill = backup_gradient. clone ( ) . into ( ) ;
2054+
2055+ widgets_first_row. push ( Separator :: new ( SeparatorStyle :: Unrelated ) . widget_instance ( ) ) ;
2056+ widgets_first_row. push (
2057+ crate :: messages:: layout:: utility_types:: widgets:: button_widgets:: ColorInput :: default ( )
2058+ . value ( fill. clone ( ) . into ( ) )
2059+ . on_update ( move |x : & crate :: messages:: layout:: utility_types:: widgets:: button_widgets:: ColorInput | Message :: Batched {
2060+ messages : Box :: new ( [
2061+ match & fill2 {
2062+ Fill :: None => NodeGraphMessage :: SetInputValue {
2063+ node_id,
2064+ input_index : BackupColorInput :: INDEX ,
2065+ value : TaggedValue :: Color ( Table :: new ( ) ) ,
2066+ }
2067+ . into ( ) ,
2068+ Fill :: Solid ( color) => NodeGraphMessage :: SetInputValue {
2069+ node_id,
2070+ input_index : BackupColorInput :: INDEX ,
2071+ value : TaggedValue :: Color ( Table :: new_from_element ( * color) ) ,
2072+ }
2073+ . into ( ) ,
2074+ Fill :: Gradient ( gradient) => NodeGraphMessage :: SetInputValue {
2075+ node_id,
2076+ input_index : BackupGradientInput :: INDEX ,
2077+ value : TaggedValue :: Gradient ( gradient. clone ( ) ) ,
2078+ }
2079+ . into ( ) ,
2080+ } ,
2081+ NodeGraphMessage :: SetInputValue {
2082+ node_id,
2083+ input_index : ColorInput :: < Fill > :: INDEX ,
2084+ value : TaggedValue :: Fill ( x. value . to_fill ( fill2. as_gradient ( ) ) ) ,
2085+ }
2086+ . into ( ) ,
2087+ ] ) ,
2088+ } )
2089+ . on_commit ( commit_value)
2090+ . widget_instance ( ) ,
20232091 ) ;
2092+ widgets. push ( LayoutGroup :: row ( widgets_first_row) ) ;
2093+
2094+ let mut fill_type_row = vec ! [ TextLabel :: new( "" ) . widget_instance( ) ] ;
2095+ match fill {
2096+ Fill :: Solid ( _) | Fill :: None => add_blank_assist ( & mut fill_type_row) ,
2097+ Fill :: Gradient ( ref gradient) => {
2098+ let reverse_button = IconButton :: new ( "Reverse" , 24 )
2099+ . tooltip_description ( "Reverse the gradient color stops." )
2100+ . on_update ( update_value (
2101+ {
2102+ let gradient = gradient. clone ( ) ;
2103+ move |_| {
2104+ let mut gradient = gradient. clone ( ) ;
2105+ gradient. stops = gradient. stops . reversed ( ) ;
2106+ TaggedValue :: Fill ( Fill :: Gradient ( gradient) )
2107+ }
2108+ } ,
2109+ node_id,
2110+ ColorInput :: < Fill > :: INDEX ,
2111+ ) )
2112+ . widget_instance ( ) ;
2113+ fill_type_row. push ( Separator :: new ( SeparatorStyle :: Unrelated ) . widget_instance ( ) ) ;
2114+ fill_type_row. push ( reverse_button) ;
2115+ }
2116+ }
2117+
2118+ let entries = vec ! [
2119+ RadioEntryData :: new( "solid" )
2120+ . label( "Solid" )
2121+ . on_update( update_value( move |_| TaggedValue :: Fill ( backup_color_fill. clone( ) ) , node_id, ColorInput :: <Fill >:: INDEX ) )
2122+ . on_commit( commit_value) ,
2123+ RadioEntryData :: new( "gradient" )
2124+ . label( "Gradient" )
2125+ . on_update( update_value( move |_| TaggedValue :: Fill ( backup_gradient_fill. clone( ) ) , node_id, ColorInput :: <Fill >:: INDEX ) )
2126+ . on_commit( commit_value) ,
2127+ ] ;
2128+
2129+ fill_type_row. extend_from_slice ( & [
2130+ Separator :: new ( SeparatorStyle :: Unrelated ) . widget_instance ( ) ,
2131+ RadioInput :: new ( entries) . selected_index ( Some ( if fill. as_gradient ( ) . is_some ( ) { 1 } else { 0 } ) ) . widget_instance ( ) ,
2132+ ] ) ;
2133+ widgets. push ( LayoutGroup :: row ( fill_type_row) ) ;
2134+
2135+ if let Fill :: Gradient ( gradient) = fill. clone ( ) {
2136+ let mut row = vec ! [ TextLabel :: new( "" ) . widget_instance( ) ] ;
2137+ match gradient. gradient_type {
2138+ GradientType :: Linear => add_blank_assist ( & mut row) ,
2139+ GradientType :: Radial => {
2140+ let orientation = if ( gradient. end . x - gradient. start . x ) . abs ( ) > f64:: EPSILON * 1e6 {
2141+ gradient. end . x > gradient. start . x
2142+ } else {
2143+ ( gradient. start . x + gradient. start . y ) < ( gradient. end . x + gradient. end . y )
2144+ } ;
2145+ let reverse_radial_gradient_button = IconButton :: new ( if orientation { "ReverseRadialGradientToRight" } else { "ReverseRadialGradientToLeft" } , 24 )
2146+ . tooltip_description ( "Reverse which end the gradient radiates from." )
2147+ . on_update ( update_value (
2148+ {
2149+ let gradient = gradient. clone ( ) ;
2150+ move |_| {
2151+ let mut gradient = gradient. clone ( ) ;
2152+ std:: mem:: swap ( & mut gradient. start , & mut gradient. end ) ;
2153+ TaggedValue :: Fill ( Fill :: Gradient ( gradient) )
2154+ }
2155+ } ,
2156+ node_id,
2157+ ColorInput :: < Fill > :: INDEX ,
2158+ ) )
2159+ . widget_instance ( ) ;
2160+ row. push ( Separator :: new ( SeparatorStyle :: Unrelated ) . widget_instance ( ) ) ;
2161+ row. push ( reverse_radial_gradient_button) ;
2162+ }
2163+ }
2164+
2165+ let gradient_for_closure = gradient. clone ( ) ;
2166+
2167+ let entries = [ GradientType :: Linear , GradientType :: Radial ]
2168+ . iter ( )
2169+ . map ( |& grad_type| {
2170+ let gradient = gradient_for_closure. clone ( ) ;
2171+ let set_input_value = update_value (
2172+ move |_: & ( ) | {
2173+ let mut new_gradient = gradient. clone ( ) ;
2174+ new_gradient. gradient_type = grad_type;
2175+ TaggedValue :: Fill ( Fill :: Gradient ( new_gradient) )
2176+ } ,
2177+ node_id,
2178+ ColorInput :: < Fill > :: INDEX ,
2179+ ) ;
2180+ RadioEntryData :: new ( format ! ( "{:?}" , grad_type) )
2181+ . label ( format ! ( "{:?}" , grad_type) )
2182+ . on_update ( move |_| Message :: Batched {
2183+ messages : Box :: new ( [
2184+ set_input_value ( & ( ) ) ,
2185+ GradientToolMessage :: UpdateOptions {
2186+ options : GradientOptionsUpdate :: Type ( grad_type) ,
2187+ }
2188+ . into ( ) ,
2189+ ] ) ,
2190+ } )
2191+ . on_commit ( commit_value)
2192+ } )
2193+ . collect ( ) ;
2194+
2195+ row. extend_from_slice ( & [
2196+ Separator :: new ( SeparatorStyle :: Unrelated ) . widget_instance ( ) ,
2197+ RadioInput :: new ( entries) . selected_index ( Some ( gradient. gradient_type as u32 ) ) . widget_instance ( ) ,
2198+ ] ) ;
2199+
2200+ widgets. push ( LayoutGroup :: row ( row) ) ;
2201+ }
2202+
20242203 let weight = number_widget ( ParameterWidgetsInfo :: new ( node_id, WeightInput :: INDEX , true , context) , NumberInput :: default ( ) . unit ( " px" ) . min ( 0. ) ) ;
2025- let align = enum_choice :: < StrokeAlign > ( )
2026- . for_socket ( ParameterWidgetsInfo :: new ( node_id, AlignInput :: INDEX , true , context) )
2027- . property_row ( ) ;
2204+ let align = enum_choice :: < StrokeAlign > ( ) . for_socket ( ParameterWidgetsInfo :: new ( node_id, AlignInput :: INDEX , true , context) ) . property_row ( ) ;
20282205 let cap = enum_choice :: < StrokeCap > ( ) . for_socket ( ParameterWidgetsInfo :: new ( node_id, CapInput :: INDEX , true , context) ) . property_row ( ) ;
2029- let join = enum_choice :: < StrokeJoin > ( )
2030- . for_socket ( ParameterWidgetsInfo :: new ( node_id, JoinInput :: INDEX , true , context) )
2031- . property_row ( ) ;
2032-
2033- let miter_limit = number_widget (
2034- ParameterWidgetsInfo :: new ( node_id, MiterLimitInput :: INDEX , true , context) ,
2035- NumberInput :: default ( ) . min ( 0. ) . disabled ( miter_limit_disabled) ,
2036- ) ;
2037- let paint_order = enum_choice :: < PaintOrder > ( )
2038- . for_socket ( ParameterWidgetsInfo :: new ( node_id, PaintOrderInput :: INDEX , true , context) )
2039- . property_row ( ) ;
2040- let disabled_number_input = NumberInput :: default ( ) . unit ( " px" ) . disabled ( has_dash_lengths) ;
2041- let dash_lengths = array_of_number_widget (
2042- ParameterWidgetsInfo :: new ( node_id, DashLengthsInput :: < Vec < f64 > > :: INDEX , true , context) ,
2043- TextInput :: default ( ) . centered ( true ) ,
2044- ) ;
2045- let number_input = disabled_number_input;
2046- let dash_offset = number_widget ( ParameterWidgetsInfo :: new ( node_id, DashOffsetInput :: INDEX , true , context) , number_input) ;
2206+ let join = enum_choice :: < StrokeJoin > ( ) . for_socket ( ParameterWidgetsInfo :: new ( node_id, JoinInput :: INDEX , true , context) ) . property_row ( ) ;
2207+ let miter_limit = number_widget ( ParameterWidgetsInfo :: new ( node_id, MiterLimitInput :: INDEX , true , context) , NumberInput :: default ( ) . min ( 0. ) . disabled ( miter_limit_disabled) ) ;
2208+ let paint_order = enum_choice :: < PaintOrder > ( ) . for_socket ( ParameterWidgetsInfo :: new ( node_id, PaintOrderInput :: INDEX , true , context) ) . property_row ( ) ;
2209+ let dash_lengths = array_of_number_widget ( ParameterWidgetsInfo :: new ( node_id, DashLengthsInput :: < Vec < f64 > > :: INDEX , true , context) , TextInput :: default ( ) . centered ( true ) ) ;
2210+ let dash_offset = number_widget ( ParameterWidgetsInfo :: new ( node_id, DashOffsetInput :: INDEX , true , context) , NumberInput :: default ( ) . unit ( " px" ) . disabled ( has_dash_lengths) ) ;
20472211
2048- vec ! [
2049- color,
2212+ widgets. extend ( [
20502213 LayoutGroup :: row ( weight) ,
20512214 align,
20522215 cap,
@@ -2055,7 +2218,9 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
20552218 paint_order,
20562219 LayoutGroup :: row ( dash_lengths) ,
20572220 LayoutGroup :: row ( dash_offset) ,
2058- ]
2221+ ] ) ;
2222+
2223+ widgets
20592224}
20602225
20612226pub fn offset_path_properties ( node_id : NodeId , context : & mut NodePropertiesContext ) -> Vec < LayoutGroup > {
0 commit comments