@@ -48,6 +48,17 @@ public sealed class SimpleEffectDialog : Gtk.Dialog
4848 private delegate bool TimeoutHandler ( ) ;
4949 TimeoutHandler ? timeout_func ;
5050
51+ private readonly EffectData effect_data ;
52+
53+ // Track widgets with conditional visibility/enabled, so we can update
54+ // them when the effect data changes
55+ private sealed record ConditionalWidget (
56+ Gtk . Widget Widget ,
57+ Func < bool > ? VisibleWhenDelegate ,
58+ Func < bool > ? EnabledWhenDelegate
59+ ) ;
60+ private readonly List < ConditionalWidget > conditional_widgets = new ( ) ;
61+
5162 /// Since this dialog is used by add-ins, the IAddinLocalizer allows for translations to be
5263 /// fetched from the appropriate place.
5364 /// </param>
@@ -82,6 +93,9 @@ public SimpleEffectDialog (
8293 contentAreaBox . Append ( widget ) ;
8394
8495 OnClose += ( _ , _ ) => HandleClose ( ) ;
96+
97+ // Keep reference to effect data, so it can be used for handling conditional widgets
98+ effect_data = effectData ;
8599 }
86100
87101 /// <summary>
@@ -132,8 +146,8 @@ private void HandleClose ()
132146 . GetMembers ( )
133147 . Where ( IsInstanceFieldOrProperty )
134148 . Where ( IsCustomProperty )
149+ . Where ( member => ! member . GetCustomAttributes < SkipAttribute > ( false ) . Any ( ) )
135150 . Select ( CreateSettings )
136- . Where ( settings => ! settings . skip )
137151 . Select ( settings => GenerateWidgetsForMember ( settings , effectData , localizer , workspace ) )
138152 . SelectMany ( widgets => widgets ) ;
139153
@@ -160,7 +174,9 @@ private sealed record MemberSettings (
160174 MemberReflector reflector ,
161175 string caption ,
162176 string ? hint ,
163- bool skip ) ;
177+ string ? visibleWhenMethodName ,
178+ string ? enabledWhenMethodName
179+ ) ;
164180
165181 private static MemberSettings CreateSettings ( MemberInfo memberInfo )
166182 {
@@ -172,11 +188,24 @@ private static MemberSettings CreateSettings (MemberInfo memberInfo)
172188 . Select ( h => h . Caption )
173189 . FirstOrDefault ( ) ;
174190
191+ string ? visibleConditionMethodName =
192+ reflector . Attributes
193+ . OfType < VisibleWhenAttribute > ( )
194+ . Select ( v => v . ConditionMethodName )
195+ . FirstOrDefault ( ) ;
196+
197+ string ? enabledConditionMethodName =
198+ reflector . Attributes
199+ . OfType < EnabledWhenAttribute > ( )
200+ . Select ( e => e . ConditionMethodName )
201+ . FirstOrDefault ( ) ;
202+
175203 return new (
176204 reflector : reflector ,
177205 caption : caption ?? MakeCaption ( memberInfo . Name ) ,
178206 hint : reflector . Attributes . OfType < HintAttribute > ( ) . Select ( h => h . Hint ) . FirstOrDefault ( ) ,
179- skip : reflector . Attributes . OfType < SkipAttribute > ( ) . Any ( ) ) ;
207+ visibleWhenMethodName : visibleConditionMethodName ,
208+ enabledWhenMethodName : enabledConditionMethodName ) ;
180209 }
181210
182211 private static string MakeCaption ( string name )
@@ -209,6 +238,19 @@ static IEnumerable<char> GenerateCharacters (string name)
209238 }
210239 }
211240
241+ /// <summary>
242+ /// Updates all widgets with conditional attributes.
243+ /// </summary>
244+ private void UpdateConditionalWidgets ( EffectData effectData )
245+ {
246+ foreach ( var widget in conditional_widgets ) {
247+ if ( widget . VisibleWhenDelegate is not null )
248+ widget . Widget . Visible = widget . VisibleWhenDelegate ( ) ;
249+
250+ if ( widget . EnabledWhenDelegate is not null )
251+ widget . Widget . Sensitive = widget . EnabledWhenDelegate ( ) ;
252+ }
253+ }
212254 private IEnumerable < Gtk . Widget > GenerateWidgetsForMember (
213255 MemberSettings settings ,
214256 EffectData effectData ,
@@ -217,8 +259,36 @@ static IEnumerable<char> GenerateCharacters (string name)
217259 {
218260 WidgetFactory ? widgetFactory = GetWidgetFactory ( settings ) ;
219261
220- if ( widgetFactory is not null )
221- yield return widgetFactory ( localizer . GetString ( settings . caption ) , effectData , settings , workspace ) ;
262+ if ( widgetFactory is not null ) {
263+ Gtk . Widget widget = widgetFactory ( localizer . GetString ( settings . caption ) , effectData , settings , workspace ) ;
264+
265+ // Keep a reference to widget if it has conditional attributes so we can update it later
266+ if ( settings . visibleWhenMethodName is not null || settings . enabledWhenMethodName is not null ) {
267+
268+ // Create delegates for condition evaluation (do reflection once, not on every update)
269+ Func < bool > ? visibleDelegate = settings . visibleWhenMethodName is not null
270+ ? ReflectionHelper . CreateConditionDelegate ( effectData , settings . visibleWhenMethodName )
271+ : null ;
272+
273+ Func < bool > ? enabledDelegate = settings . enabledWhenMethodName is not null
274+ ? ReflectionHelper . CreateConditionDelegate ( effectData , settings . enabledWhenMethodName )
275+ : null ;
276+
277+ // Apply the initial state
278+ if ( visibleDelegate is not null )
279+ widget . Visible = visibleDelegate ( ) ;
280+
281+ if ( enabledDelegate is not null )
282+ widget . Sensitive = enabledDelegate ( ) ;
283+
284+ conditional_widgets . Add ( new ConditionalWidget (
285+ widget ,
286+ visibleDelegate ,
287+ enabledDelegate )
288+ ) ;
289+ }
290+ yield return widget ;
291+ }
222292
223293 if ( settings . hint != null )
224294 yield return CreateHintLabel ( localizer . GetString ( settings . hint ) ) ;
@@ -530,6 +600,9 @@ private void SetAndNotify (MemberReflector reflector, object o, object val)
530600 {
531601 reflector . SetValue ( o , val ) ;
532602 EffectDataChanged ? . Invoke ( this , new PropertyChangedEventArgs ( reflector . OriginalMemberInfo . Name ) ) ;
603+
604+ // Update conditional widgets when any property changes
605+ UpdateConditionalWidgets ( effect_data ) ;
533606 }
534607
535608 private Gtk . Widget CreateSeed (
0 commit comments