static StylePropertyPart CreatePart(StyleSheet styleSheet, StyleValueHandle handle, int offset) { var part = StylePropertyPart.Create(); part.offset = offset; part.handles.Add( new StyleValueHandleContext { styleSheet = styleSheet, handle = handle }); return(part); }
void RemoveValue(Index indices) { var part = stylePropertyParts[indices.partIndex]; var initialOffset = part.offset; var nextOffset = indices.partIndex + 1 >= stylePropertyParts.Count ? -1 : stylePropertyParts[indices.partIndex + 1].offset; // Range of handles to remove in the StyleProperty.values array var range = nextOffset < 0 ? styleProperty.values.Length - initialOffset : nextOffset - initialOffset; if (part.isVariable) { if (part.isVariableUnresolved && indices.valueIndex == -1) { // If there's only a single value, simply remove the property. if (stylePropertyParts.Count == 1) { RemoveProperty(); return; } var valueList = styleProperty.values.ToList(); if (indices.partIndex > 0) { initialOffset -= 1; } if (indices.partIndex == stylePropertyParts.Count - 1) { range += 1; } valueList.RemoveRange(initialOffset, range); var firstPropertyValue = stylePropertyParts[indices.partIndex]; for (var i = indices.partIndex + 1; i < stylePropertyParts.Count; ++i) { var propertyValue = stylePropertyParts[i]; propertyValue.offset -= 2; } firstPropertyValue.Dispose(); stylePropertyParts.RemoveAt(indices.partIndex); styleProperty.values = valueList.ToArray(); return; } var newParts = new List <StylePropertyPart>(); // To set an explicit value on top of a variable, we must first remove the variable. In the case where // the variable points to a list of values, we must remove all values of the list and set them as // explicit values of the same type. var list = styleProperty.values.ToList(); list.RemoveRange(initialOffset, range); var currentOffset = initialOffset; for (var i = 0; i < part.handles.Count; ++i, ++currentOffset) { var propertyValue = StylePropertyPart.Create(); propertyValue.offset = currentOffset; var handle = TransferTypedValue(part.handles[i]); list.Insert(currentOffset, handle); if (i < part.handles.Count - 1 || indices.partIndex < stylePropertyParts.Count - 1) { list.Insert(++currentOffset, new StyleValueHandle(-1, StyleValueType.CommaSeparator)); } propertyValue.handles.Add(new StyleValueHandleContext { styleSheet = styleSheet, handle = handle }); newParts.Add(propertyValue); } styleProperty.values = list.ToArray(); stylePropertyParts.RemoveAt(indices.partIndex); // Manually dispose removed part part.Dispose(); stylePropertyParts.InsertRange(indices.partIndex, newParts); var adjustIndex = indices.partIndex + newParts.Count; var offset = currentOffset - nextOffset; for (var i = adjustIndex; i < stylePropertyParts.Count; ++i) { var nextPart = stylePropertyParts[i]; nextPart.offset += offset; stylePropertyParts[i] = nextPart; } // Now that the variable has been transferred as explicit values, we can remove the actual value. if (indices.valueIndex >= 0) { RemoveAtIndex(indices.index); } } else { // If there's only a single value, simply remove the property. if (stylePropertyParts.Count == 1) { RemoveProperty(); return; } var list = styleProperty.values.ToList(); if (indices.partIndex > 0) { initialOffset -= 1; } if (indices.partIndex == stylePropertyParts.Count - 1) { range += 1; } list.RemoveRange(initialOffset, range); var partToRemove = stylePropertyParts[indices.partIndex]; partToRemove.Dispose(); stylePropertyParts.RemoveAt(indices.partIndex); AdjustOffsets(indices.partIndex, -2); styleProperty.values = list.ToArray(); } }
void OverrideVariableWithValue <T>(Index indices, T value, StyleValueType valueType) { if (!stylePropertyParts[indices.partIndex].isVariable) { return; } var part = stylePropertyParts[indices.partIndex]; var initialOffset = part.offset; var nextOffset = indices.partIndex + 1 >= stylePropertyParts.Count ? -1 : stylePropertyParts[indices.partIndex + 1].offset; // Range of handles to remove in the StyleProperty.values array var range = nextOffset < 0 ? styleProperty.values.Length - initialOffset : nextOffset - initialOffset; var newParts = new List <StylePropertyPart>(); // To set an explicit value on top of a variable, we must first remove the variable. In the case where // the variable points to a list of values, we must remove all values of the list and set them as // explicit values of the same type. var list = styleProperty.values.ToList(); list.RemoveRange(initialOffset, range); var currentOffset = initialOffset; for (var i = 0; i < part.handles.Count; ++i, ++currentOffset) { var propertyValue = StylePropertyPart.Create(); propertyValue.offset = currentOffset; if (i == indices.valueIndex && typeof(Variable).IsAssignableFrom(typeof(T)) && value is Variable variable) { var handles = AddVariableToStyleSheet(variable.name); var property = new StyleProperty { name = styleProperty.name, values = handles }; var ib = 0; var newPart = ResolveValueOrVariable(styleSheet, element, styleRule, property, ref ib, editorExtensionMode); list.InsertRange(currentOffset, handles); currentOffset += 2; if (i < part.handles.Count - 1 || indices.partIndex < stylePropertyParts.Count - 1) { list.Insert(++currentOffset, new StyleValueHandle(-1, StyleValueType.CommaSeparator)); } newParts.Add(newPart); } else { var handle = i == indices.valueIndex ? AddTypedValue(value, valueType) : TransferTypedValue(part.handles[i]); list.Insert(currentOffset, handle); if (i < part.handles.Count - 1 || indices.partIndex < stylePropertyParts.Count - 1) { list.Insert(++currentOffset, new StyleValueHandle(-1, StyleValueType.CommaSeparator)); } propertyValue.handles.Add(new StyleValueHandleContext { styleSheet = styleSheet, handle = handle }); newParts.Add(propertyValue); } } if (part.isVariableUnresolved && indices.valueIndex == -1) { if (typeof(Variable).IsAssignableFrom(typeof(T)) && value is Variable variable) { var handles = AddVariableToStyleSheet(variable.name); var newPart = StylePropertyPart.Create(); newPart.offset = currentOffset; newPart.handles.Add(new StyleValueHandleContext { styleSheet = styleSheet, handle = handles[2], }); list.InsertRange(currentOffset, handles); newParts.Add(newPart); } else { var handle = AddTypedValue(value, valueType); var newPart = StylePropertyPart.Create(); newPart.offset = currentOffset; newPart.handles.Add(new StyleValueHandleContext { styleSheet = styleSheet, handle = handle, }); list.Insert(currentOffset, handle); newParts.Add(newPart); } } styleProperty.values = list.ToArray(); stylePropertyParts.RemoveAt(indices.partIndex); // Manually dispose removed part part.Dispose(); stylePropertyParts.InsertRange(indices.partIndex, newParts); var partsCount = indices.partIndex + newParts.Count; var offset = currentOffset - nextOffset; for (var i = partsCount; i < stylePropertyParts.Count; ++i) { var nextPart = stylePropertyParts[i]; nextPart.offset += offset; stylePropertyParts[i] = nextPart; } }
internal static StylePropertyPart ResolveValueOrVariable( StyleSheet styleSheet, VisualElement element, StyleRule styleRule, StyleProperty property, ref int currentIndex, bool isEditorExtensionMode) { var handle = property.values[currentIndex]; switch (handle.valueType) { case StyleValueType.Invalid: case StyleValueType.Keyword: case StyleValueType.Float: case StyleValueType.Dimension: case StyleValueType.Color: case StyleValueType.ResourcePath: case StyleValueType.AssetReference: case StyleValueType.Enum: case StyleValueType.String: case StyleValueType.ScalableImage: case StyleValueType.MissingAssetReference: { // skip comma ++currentIndex; var part = StylePropertyPart.Create(); part.handles.Add(new StyleValueHandleContext { styleSheet = styleSheet, handle = handle }); return(part); } case StyleValueType.Function: { var argCountHandle = property.values[++currentIndex]; var argCount = (int)styleSheet.ReadFloat(argCountHandle); var varHandle = property.values[++currentIndex]; var variable = styleSheet.ReadVariable(varHandle); using (var manipulator = ResolveVariable(element, styleSheet, styleRule, variable, isEditorExtensionMode)) { if (argCount == 1) { // Skip comma ++currentIndex; var part = StylePropertyPart.Create(); if (null == manipulator || manipulator.stylePropertyParts.Count == 0) { part.isVariable = true; part.variableName = variable; return(part); } part.handles.AddRange(manipulator.stylePropertyParts.SelectMany(o => o.handles)); part.isVariable = true; part.variableName = variable; return(part); } } // Skip comma and point to next function argument. currentIndex += 2; var fallbackPart = ResolveValueOrVariable(styleSheet, element, styleRule, property, ref currentIndex, isEditorExtensionMode); fallbackPart.isVariable = true; fallbackPart.variableName = variable; return(fallbackPart); } // These should never be hit as they are being handled by the cases above case StyleValueType.Variable: case StyleValueType.CommaSeparator: throw new InvalidOperationException(); default: throw new ArgumentOutOfRangeException(); } }