Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
StephaneDelcroix committed Apr 18, 2023
1 parent 0e4dbf1 commit bdbfe9c
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 27 deletions.
36 changes: 16 additions & 20 deletions src/Controls/src/Core/BindableObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -479,14 +479,6 @@ internal void SetValue(BindablePropertyKey propertyKey, object value, SetterSpec
internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes = SetValueFlags.None)
=> SetValueCore(property, value, attributes, SetValuePrivateFlags.Default, new SetterSpecificity());

//FIXME: GO AWAY
void SetBackupStyleValue(BindableProperty property, object value)
{
var context = GetOrCreateContext(property);
context.StyleValueSet = true;
context.StyleValue = value;
}

//FIXME: GO AWAY
internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
=> SetValueCore(property, value, attributes, privateAttributes, new SetterSpecificity());
Expand All @@ -498,7 +490,7 @@ internal void SetValueCore(BindableProperty property, object value, SetValueFlag

//bool checkAccess = (privateAttributes & SetValuePrivateFlags.CheckAccess) != 0;
//bool manuallySet = (privateAttributes & SetValuePrivateFlags.ManuallySet) != 0;
bool silent = (privateAttributes & SetValuePrivateFlags.Silent) != 0;
//bool silent = (privateAttributes & SetValuePrivateFlags.Silent) != 0;
//bool fromStyle = (privateAttributes & SetValuePrivateFlags.FromStyle) != 0;
bool converted = (privateAttributes & SetValuePrivateFlags.Converted) != 0;

Expand Down Expand Up @@ -548,7 +540,7 @@ internal void SetValueCore(BindableProperty property, object value, SetValueFlag
else
{
context.Attributes |= BindableContextAttributes.IsBeingSet;
SetValueActual(property, context, value, currentlyApplying, attributes, specificity, silent);
SetValueActual(property, context, value, currentlyApplying, attributes, specificity);

Queue<SetValueArgs> delayQueue = context.DelayedSetters;
if (delayQueue != null)
Expand All @@ -571,6 +563,15 @@ void SetValueActual(BindableProperty property, BindablePropertyContext context,
object original = context.Values.LastOrDefault().Value;
var originalSpecificity = context.Values.LastOrDefault().Key;

//if the last value was set from handler, override it
if ( specificity != SetterSpecificity.FromHandler
&& originalSpecificity == SetterSpecificity.FromHandler)
{
context.Values.Remove(SetterSpecificity.FromHandler);
original = context.Values.LastOrDefault().Value;
originalSpecificity = context.Values.LastOrDefault().Key;
}

//We keep setter of lower specificity so we can unapply
if (specificity.CompareTo(originalSpecificity) < 0)
{
Expand Down Expand Up @@ -750,27 +751,22 @@ internal class BindablePropertyContext

public Queue<SetValueArgs> DelayedSetters;
public BindableProperty Property;
public SortedList<SetterSpecificity, object> Values = new();
//public object Value;
private SortedList<SetterSpecificity, object> _values = new();

//TODO GO AWAY
public bool StyleValueSet;
public object StyleValue;
public SortedList<SetterSpecificity, object> Values {
get => _values;
set => _values = value; }
}


[Flags]
internal enum SetValuePrivateFlags
{
None = 0,
[Obsolete("no longer in use")]CheckAccess = 1 << 0,
Silent = 1 << 1,
[Obsolete("no longer in use")] ManuallySet = 1 << 2,
FromStyle = 1 << 3,
Converted = 1 << 4,
#pragma warning disable CS0618 // Type or member is obsolete
Default = CheckAccess
#pragma warning restore CS0618 // Type or member is obsolete
Default = None
}

internal class SetValueArgs
Expand Down
8 changes: 3 additions & 5 deletions src/Controls/src/Core/RadioButton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,7 @@ void ApplyIsCheckedState()
void SelectRadioButton(object sender, EventArgs e)
{
if (IsEnabled)
{
IsChecked = true;
}
SetValue(IsCheckedProperty, true, specificity: SetterSpecificity.FromHandler);
}

void OnIsCheckedPropertyChanged(bool isChecked)
Expand Down Expand Up @@ -436,7 +434,7 @@ void HandleRadioButtonGroupSelectionChanged(RadioButton selected, RadioButtonGro
return;
}

IsChecked = false;
SetValue(IsCheckedProperty, false, specificity: SetterSpecificity.FromHandler);
}

void HandleRadioButtonGroupValueChanged(Element layout, RadioButtonGroupValueChanged args)
Expand All @@ -446,7 +444,7 @@ void HandleRadioButtonGroupValueChanged(Element layout, RadioButtonGroupValueCha
return;
}

IsChecked = true;
SetValue(IsCheckedProperty, true, specificity: SetterSpecificity.FromHandler);
}

static void BindToTemplatedParent(BindableObject bindableObject, params BindableProperty[] properties)
Expand Down
2 changes: 1 addition & 1 deletion src/Controls/src/Core/RadioButtonGroupController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void AddRadioButton(RadioButton radioButton)

if (object.Equals(radioButton.Value, this.SelectedValue))
{
radioButton.IsChecked = true;
radioButton.SetValue(RadioButton.IsCheckedProperty, true, specificity: SetterSpecificity.FromHandler);
}
}

Expand Down
13 changes: 12 additions & 1 deletion src/Controls/src/Core/Setter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ internal void UnApply(BindableObject target, SetterSpecificity specificity)
internal readonly struct SetterSpecificity : IComparable<SetterSpecificity>
{
public static readonly SetterSpecificity DefaultValue = new(-1, 0, 0, 0, -1, 0, 0, 0);
public static readonly SetterSpecificity FromHandler = new SetterSpecificity(0, 0,0,0);
public static readonly SetterSpecificity VisualStateSetter = new SetterSpecificity(1, 0, 0, 0, 0, 0, 0, 0);
public static readonly SetterSpecificity FromBinding = new SetterSpecificity(0, 0, 0, 1, 0, 0, 0, 0);

Expand All @@ -136,6 +135,9 @@ internal void UnApply(BindableObject target, SetterSpecificity specificity)

public static readonly SetterSpecificity DynamicResourceSetter = new SetterSpecificity(0, 0, 1, 0, 0, 0, 0, 0);

//handler always apply, but are removed when anything else comes in. see SetValueActual
public static readonly SetterSpecificity FromHandler = new SetterSpecificity(1000, 0, 0, 0, 0, 0, 0, 0);

//100-n: direct VSM (not from Style), n = max(99, distance between the RD and the target)
public int Vsm { get; }

Expand Down Expand Up @@ -192,5 +194,14 @@ public int CompareTo(SetterSpecificity other)
if (Class != other.Class) return Class.CompareTo(other.Class);
return Type.CompareTo(other.Type);
}

public override bool Equals(object obj) => Equals((SetterSpecificity)obj);

bool Equals(SetterSpecificity other) => CompareTo(other) == 0;

public override int GetHashCode() => (Vsm, Manual, DynamicResource, Binding, Style, Id, Class, Type).GetHashCode();

public static bool operator ==(SetterSpecificity left, SetterSpecificity right) => left.Equals(right);
public static bool operator !=(SetterSpecificity left, SetterSpecificity right) => !left.Equals(right);
}
}
16 changes: 16 additions & 0 deletions src/Controls/tests/Core.UnitTests/BindableObjectUnitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1604,5 +1604,21 @@ public void SetBindingToTextInvokesToString()
Assert.Equal("converted", bindable.GetValue(prop));
}

[Fact]
public void SpecificityOfHandlers()
{
var prop = BindableProperty.Create("foo", typeof(string), typeof(MockBindable), null);
var bindable = new MockBindable();

bindable.SetValue(prop, "manual");
Assert.Equal("manual", bindable.GetValue(prop));

bindable.SetValueFromRenderer(prop, "handler");
Assert.Equal("handler", bindable.GetValue(prop));

bindable.SetValue(prop, "manual");
Assert.Equal("manual", bindable.GetValue(prop));
}

}
}

0 comments on commit bdbfe9c

Please sign in to comment.