@@ -162,6 +162,93 @@ impl ToolMetadata for PathTool {
162162 ToolType :: Path
163163 }
164164}
165+ pub fn proportional_edit_options ( options : & PathToolOptions ) -> Vec < LayoutGroup > {
166+ let mut widgets = Vec :: new ( ) ;
167+
168+ // Header row with title
169+ widgets. push ( LayoutGroup :: Row {
170+ widgets : vec ! [ TextLabel :: new( "Proportional Edit" ) . bold( true ) . widget_holder( ) ] ,
171+ } ) ;
172+
173+ // Enabled row
174+ widgets. push ( LayoutGroup :: Row {
175+ widgets : vec ! [
176+ TextLabel :: new( "Enabled" ) . center_align( true ) . widget_holder( ) ,
177+ Separator :: new( SeparatorType :: Unrelated ) . widget_holder( ) ,
178+ CheckboxInput :: new( options. proportional_editing_enabled)
179+ . tooltip( "Enable proportional editing (Alt+P)" )
180+ . on_update( |checkbox| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalEditingEnabled ( checkbox. checked) ) . into( ) )
181+ . widget_holder( ) ,
182+ ] ,
183+ } ) ;
184+
185+ // Falloff type row
186+ widgets. push ( LayoutGroup :: Row {
187+ widgets : vec ! [
188+ TextLabel :: new( "Falloff Type" ) . center_align( true ) . multiline( true ) . widget_holder( ) ,
189+ Separator :: new( SeparatorType :: Unrelated ) . widget_holder( ) ,
190+ DropdownInput :: new( vec![ vec![
191+ MenuListEntry :: new( "Smooth" )
192+ . label( "Smooth" )
193+ . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Smooth ) ) . into( ) ) ,
194+ MenuListEntry :: new( "Sphere" )
195+ . label( "Sphere" )
196+ . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Sphere ) ) . into( ) ) ,
197+ MenuListEntry :: new( "Root" )
198+ . label( "Root" )
199+ . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Root ) ) . into( ) ) ,
200+ MenuListEntry :: new( "Inverse Square" )
201+ . label( "Inverse Square" )
202+ . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: InverseSquare ) ) . into( ) ) ,
203+ MenuListEntry :: new( "Sharp" )
204+ . label( "Sharp" )
205+ . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Sharp ) ) . into( ) ) ,
206+ MenuListEntry :: new( "Linear" )
207+ . label( "Linear" )
208+ . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Linear ) ) . into( ) ) ,
209+ MenuListEntry :: new( "Constant" )
210+ . label( "Constant" )
211+ . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Constant ) ) . into( ) ) ,
212+ MenuListEntry :: new( "Random" )
213+ . label( "Random" )
214+ . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Random ) ) . into( ) ) ,
215+ ] ] )
216+ . selected_index( Some ( options. proportional_falloff_type as u32 ) )
217+ . disabled( !options. proportional_editing_enabled)
218+ . widget_holder( ) ,
219+ ] ,
220+ } ) ;
221+
222+ // Radius row
223+ widgets. push ( LayoutGroup :: Row {
224+ widgets : vec ! [
225+ TextLabel :: new( "Radius" ) . center_align( true ) . widget_holder( ) ,
226+ Separator :: new( SeparatorType :: Unrelated ) . widget_holder( ) ,
227+ NumberInput :: new( Some ( options. proportional_radius as f64 ) )
228+ . unit( " px" )
229+ . min( 1.0 )
230+ . disabled( !options. proportional_editing_enabled)
231+ . on_update( |number_input| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalRadius ( number_input. value. unwrap_or( 0. ) as i32 ) ) . into( ) )
232+ . widget_holder( ) ,
233+ ] ,
234+ } ) ;
235+
236+ // Strength row
237+ widgets. push ( LayoutGroup :: Row {
238+ widgets : vec ! [
239+ TextLabel :: new( "Strength" ) . center_align( true ) . widget_holder( ) ,
240+ Separator :: new( SeparatorType :: Unrelated ) . widget_holder( ) ,
241+ NumberInput :: new( Some ( options. proportional_falloff_strength as f64 ) )
242+ . min( 1.0 )
243+ . step( 1.0 )
244+ . disabled( !options. proportional_editing_enabled)
245+ . on_update( |number_input| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffStrength ( number_input. value. unwrap_or( 1.0 ) as i32 ) ) . into( ) )
246+ . widget_holder( ) ,
247+ ] ,
248+ } ) ;
249+
250+ widgets
251+ }
165252
166253impl LayoutHolder for PathTool {
167254 fn layout ( & self ) -> Layout {
@@ -247,59 +334,19 @@ impl LayoutHolder for PathTool {
247334 . selected_index ( Some ( self . options . path_overlay_mode as u32 ) )
248335 . widget_holder ( ) ;
249336
250- let proportional_editing_label = TextLabel :: new ( "Proportional Edit" ) . disabled ( !self . options . proportional_editing_enabled ) . widget_holder ( ) ;
251- let proportional_checkbox = CheckboxInput :: new ( self . options . proportional_editing_enabled )
252- . on_update ( |checkbox| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalEditingEnabled ( checkbox. checked ) ) . into ( ) )
337+ // Create the proportional edit dropdown trigger (checkbox icon)
338+ // TODO: use this when icon is available?
339+ // let proportional_edit_trigger = CheckboxInput::new(self.options.proportional_editing_enabled)
340+ // .icon("ProportionalEdit")
341+ // .tooltip("Proportional Editing (Alt+P)")
342+ // .on_update(|checkbox| PathToolMessage::UpdateOptions(
343+ // PathOptionsUpdate::ProportionalEditingEnabled(checkbox.checked)).into())
344+ // .widget_holder();
345+ let proportional_edit_trigger = CheckboxInput :: new ( self . options . proportional_editing_enabled )
253346 . tooltip ( "Proportional Editing (Alt+P)" )
347+ . on_update ( |checkbox| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalEditingEnabled ( checkbox. checked ) ) . into ( ) )
254348 . widget_holder ( ) ;
255-
256- let falloff_label = TextLabel :: new ( "Falloff" ) . disabled ( !self . options . proportional_editing_enabled ) . widget_holder ( ) ;
257-
258- let falloff_entries = vec ! [
259- MenuListEntry :: new( "Smooth" )
260- . label( "Smooth" )
261- . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Smooth ) ) . into( ) ) ,
262- MenuListEntry :: new( "Sphere" )
263- . label( "Sphere" )
264- . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Sphere ) ) . into( ) ) ,
265- MenuListEntry :: new( "Root" )
266- . label( "Root" )
267- . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Root ) ) . into( ) ) ,
268- MenuListEntry :: new( "Inverse Square" )
269- . label( "Inverse Square" )
270- . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: InverseSquare ) ) . into( ) ) ,
271- MenuListEntry :: new( "Sharp" )
272- . label( "Sharp" )
273- . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Sharp ) ) . into( ) ) ,
274- MenuListEntry :: new( "Linear" )
275- . label( "Linear" )
276- . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Linear ) ) . into( ) ) ,
277- MenuListEntry :: new( "Constant" )
278- . label( "Constant" )
279- . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Constant ) ) . into( ) ) ,
280- MenuListEntry :: new( "Random" )
281- . label( "Random" )
282- . on_commit( |_| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffType ( ProportionalFalloffType :: Random ) ) . into( ) ) ,
283- ] ;
284-
285- let falloff_dropdown = DropdownInput :: new ( vec ! [ falloff_entries] )
286- . selected_index ( Some ( self . options . proportional_falloff_type as u32 ) )
287- . disabled ( !self . options . proportional_editing_enabled )
288- . widget_holder ( ) ;
289- let radius_label = TextLabel :: new ( "Radius" ) . disabled ( !self . options . proportional_editing_enabled ) . widget_holder ( ) ;
290- let radius_input = NumberInput :: new ( Some ( self . options . proportional_radius as f64 ) )
291- . unit ( " px" )
292- . min ( 1.0 )
293- . disabled ( !self . options . proportional_editing_enabled )
294- . on_update ( |number_input| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalRadius ( number_input. value . unwrap_or ( 0. ) as i32 ) ) . into ( ) )
295- . widget_holder ( ) ;
296- let strength_label = TextLabel :: new ( "Strength" ) . disabled ( !self . options . proportional_editing_enabled ) . widget_holder ( ) ;
297- let strength_input = NumberInput :: new ( Some ( self . options . proportional_falloff_strength as f64 ) )
298- . min ( 1 as f64 )
299- . step ( 1 as f64 )
300- . disabled ( !self . options . proportional_editing_enabled )
301- . on_update ( |number_input| PathToolMessage :: UpdateOptions ( PathOptionsUpdate :: ProportionalFalloffStrength ( number_input. value . unwrap_or ( 1.0 ) as i32 ) ) . into ( ) )
302- . widget_holder ( ) ;
349+ let proportional_edit_dropdown = PopoverButton :: new ( ) . popover_layout ( proportional_edit_options ( & self . options ) ) . widget_holder ( ) ;
303350
304351 Layout :: WidgetLayout ( WidgetLayout :: new ( vec ! [ LayoutGroup :: Row {
305352 widgets: vec![
@@ -308,27 +355,13 @@ impl LayoutHolder for PathTool {
308355 y_location,
309356 unrelated_seperator. clone( ) ,
310357 colinear_handle_checkbox,
311- related_seperator. clone ( ) ,
358+ related_seperator,
312359 colinear_handles_label,
313360 unrelated_seperator. clone( ) ,
314361 path_overlay_mode_widget,
315- unrelated_seperator. clone( ) ,
316- proportional_editing_label,
317- related_seperator. clone( ) ,
318- proportional_checkbox,
319- unrelated_seperator. clone( ) ,
320- falloff_label,
321- related_seperator. clone( ) ,
322- falloff_dropdown,
323- unrelated_seperator. clone( ) ,
324- radius_label,
325- related_seperator. clone( ) ,
326- radius_input,
327- unrelated_seperator. clone( ) ,
328- strength_label,
329- related_seperator,
330- strength_input,
331362 unrelated_seperator,
363+ proportional_edit_trigger,
364+ proportional_edit_dropdown,
332365 ] ,
333366 } ] ) )
334367 }
0 commit comments