/// <summary> /// The value of pre-cascade property has changed /// </summary> /// <param name="Stage"></param> /// <param name="Property"></param> private void Property_onChanged(EPropertyStage Stage, ICssProperty Property) { SetProperties.SetFlag(Property.CssName.Value, Property.HasValue); /*if (!Property.HasValue) SetProperties.Remove(Property.CssName); * else SetProperties.Add(Property.CssName);*/ if (Property.CssName is null) { throw new Exception($"Cannot fire onChange events for unnamed property! (Name: {Property.CssName}"); } StyleDefinition def = CssDefinitions.StyleDefinitions[Property.CssName]; if (def is null) { throw new Exception($"Cannot find a definition for Css property: \"{Property.CssName}\""); } EPropertyDirtFlags Flags = def.Flags; StackTrace Stack = null; #if DEBUG //stack = new StackTrace(STACK_FRAME_OFFSET, true); #endif Property_Changed?.Invoke(Stage, Property, Flags, Stack); }
/// <summary> /// Creates a new CSS property definition /// </summary> /// <param name="Name">CSS property name</param> /// <param name="Inherited">Do child elements inherit this value if they are unset?</param> /// <param name="Flags">Indicates what aspects of an element this property affects</param> /// <param name="Initial">Default value for the property</param> /// <param name="Keywords">List of keywords which can be assigned to this property</param> /// <param name="IsPrivate">If TRUE then this property cannot be set from style-sheets</param> public StyleDefinition(AtomicName <ECssPropertyID> Name, bool Inherited, EPropertyDirtFlags Flags, CssValue Initial, ECssValueTypes AllowedTypes = 0x0, string[] Keywords = null, bool IsPrivate = false, CssPercentageResolver Percentage_Resolver = null, params Tuple <EPropertyStage, PropertyResolverFunc>[] Resolvers) { this.Name = Name; this.Flags = Flags; this.IsPrivate = IsPrivate; this.Inherited = Inherited; this.Initial = Initial; this.Percentage_Resolver = Percentage_Resolver; if (Keywords is null) { keywordWhitelist = Array.Empty <string>(); } else { keywordWhitelist = Keywords.ToArray(); } // Append the specified allowed types to our defaults this.AllowedTypes |= AllowedTypes; // Setup our resolver index foreach (var o in Resolvers) { propertyStageResolver[(int)o.Item1] = o.Item2; } }
/// <summary> /// A post-cascade property has changed assigned values /// </summary> /// <param name="Property"></param> /// <param name="Flags"></param> /// <param name="Stack"></param> private void Handle_Cascaded_Property_Change(EPropertyStage Stage, ICssProperty Property, EPropertyDirtFlags Flags, StackTrace Stack) { bool IsFlow = (Flags & EPropertyDirtFlags.Flow) != 0;// Layout bool IsBlock = (Flags & EPropertyDirtFlags.Box) != 0; bool IsVisual = (Flags & EPropertyDirtFlags.Visual) != 0; bool IsFont = (Flags & EPropertyDirtFlags.Text) != 0; // If the value that changed was a specified one and it affects the block then we need to update our block if (IsBlock && Stage >= EPropertyStage.Specified) { // Flag us dirty so we can resolve next time its called SetFlag(EPropertySystemDirtFlags.NeedsToResolveBlock); // Notify our parent by flagging them aswell // Owner.Box.Flag(EBoxInvalidationReason.Property_Changed); // Owner.Box.FlagProperty(Flags); } // Update our dirt flags appropriately if (IsFlow || IsVisual) { SetFlag(EPropertySystemDirtFlags.NeedsToResolveBlock); } if (IsFont) { SetFlag(EPropertySystemDirtFlags.NeedsToResolveFont); } //Logging.Log.Info("[Property Changed]: {0}", Prop.FieldName); onProperty_Change?.Invoke(Property, Flags, Stack); }
/// <summary> /// A state-specific property changed, we need to resolve this single property /// </summary> private void Handle_Declared_Property_Change(EPropertyStage Stage, ICssProperty Property, EPropertyDirtFlags Flags, StackTrace Origin) { /* XXX: * To be honest cascading here doesnt make sense * if a declared property changes that wont always change the value of our cascaded property. * We should check if this property IS the cascaded property and if so then just update that single property! */ CascadeProperty(Property); }