コード例 #1
0
        public bool TrySetAutoRotateOptions(XElement element, IAutoRotateRoot ancestor, IAutoRotateRoot target)
        {
            if (ancestor != null)
            {
                target.AutoRotate     = ancestor.AutoRotate;
                target.AutoRotateFlip = ancestor.AutoRotateFlip;
            }

            var autorotate = element.Attribute("autorotate");

            if (autorotate == null)
            {
                return(true);
            }

            var options = autorotate.Value.Split(',');

            if (options.Length == 0)
            {
                logger.LogError(autorotate, "Autorotate options cannot be empty");
                return(false);
            }

            if (!Enum.TryParse <AutoRotateType>(options[0], true, out var autoRotateType))
            {
                logger.LogError(autorotate, $"Unknown autorotation type '{options[0]}'");
                return(false);
            }

            var flipState = FlipState.None;

            foreach (var option in options.Skip(1))
            {
                if (string.Equals(option, "FlipPrimary", StringComparison.OrdinalIgnoreCase))
                {
                    flipState |= FlipState.Primary;
                }
                else if (string.Equals(option, "FlipSecondary", StringComparison.OrdinalIgnoreCase))
                {
                    flipState |= FlipState.Secondary;
                }
                else
                {
                    logger.LogError(autorotate, $"Unknown option '{option}'");
                    return(false);
                }
            }

            target.AutoRotate     = autoRotateType;
            target.AutoRotateFlip = flipState;
            return(true);
        }
コード例 #2
0
        public static bool GetAttribute(this XElement element, string name, IXmlLoadLogger logger, out XAttribute attr)
        {
            attr = element.Attribute(name);
            if (attr == null)
            {
                logger.LogError(element, $"Missing attribute '{name}' for <{element.Name.LocalName}> tag");
                return(false);
            }

            return(true);
        }
コード例 #3
0
        private bool TryReadDouble(XAttribute attr, out ConditionalCollection <double> result)
        {
            if (!attr.Value.StartsWith("$"))
            {
                if (double.TryParse(attr.Value, out var plainValue))
                {
                    result = new ConditionalCollection <double> {
                        new Conditional <double>(plainValue, ConditionTree.Empty)
                    };
                    return(true);
                }

                result = null;
                return(false);
            }

            // Check variable exists
            var variableName = attr.Value.Substring(1);

            if (!definitionsSection.Definitions.TryGetValue(variableName, out var variableValues))
            {
                logger.LogError(attr, $"Variable '{attr.Value}' does not exist");
                result = null;
                return(false);
            }

            // Check all possible values are valid
            result = new ConditionalCollection <double>();
            foreach (var variableValue in variableValues)
            {
                if (!double.TryParse(variableValue.Value, out var parsedValue))
                {
                    logger.LogError(attr, $"Value '{attr.Value}' for ${variableName} is not a valid number");
                    return(false);
                }

                result.Add(new Conditional <double>(parsedValue, variableValue.Conditions));
            }

            return(true);
        }
コード例 #4
0
        public bool ReadRenderCommand(XElement element, ComponentDescription description, out IXmlRenderCommand command)
        {
            var textCommand = new XmlRenderTextWithDefinitions();

            command = textCommand;

            if (!ReadTextLocation(element, textCommand))
            {
                return(false);
            }

            if (!TryParseTextAlignment(element.Attribute("align"), out ConditionalCollection <TextAlignment> alignment))
            {
                return(false);
            }
            textCommand.Alignment = alignment;

            var tRotation = "0";

            if (description.Metadata.FormatVersion >= TextRotationMinFormatVersion && element.Attribute("rotate") != null)
            {
                tRotation = element.Attribute("rotate").Value;
            }

            var rotation = TextRotation.None;

            switch (tRotation)
            {
            case "0":
                rotation = TextRotation.None;
                break;

            case "90":
                rotation = TextRotation.Rotate90;
                break;

            case "180":
                rotation = TextRotation.Rotate180;
                break;

            case "270":
                rotation = TextRotation.Rotate270;
                break;

            default:
                logger.LogError(element.Attribute("rotate"), $"Invalid value for text rotation: '{tRotation}'");
                break;
            }
            textCommand.Rotation = new ConditionalCollection <TextRotation>
            {
                new Conditional <TextRotation>(rotation, ConditionTree.Empty),
            };

            double size = 11d;

            if (element.Attribute("size") != null)
            {
                if (element.Attribute("size").Value.ToLowerInvariant() == "large")
                {
                    size = 12d;
                }
            }

            var textValueNode = element.Element(XmlLoader.ComponentNamespace + "value");

            if (textValueNode != null)
            {
                foreach (var spanNode in textValueNode.Elements())
                {
                    string nodeValue  = spanNode.Value;
                    var    formatting = TextRunFormatting.Normal;

                    if (spanNode.Name.LocalName == "sub")
                    {
                        formatting = TextRunFormatting.Subscript;
                    }
                    else if (spanNode.Name.LocalName == "sup")
                    {
                        formatting = TextRunFormatting.Superscript;
                    }
                    else if (spanNode.Name.LocalName != "span")
                    {
                        logger.LogWarning(spanNode, $"Unknown node '{spanNode.Name}' will be treated as <span>");
                    }

                    var textRun = new TextRun(nodeValue, formatting);

                    if (!ValidateText(element, description, textRun.Text))
                    {
                        return(false);
                    }

                    textCommand.TextRuns.Add(textRun);
                }
            }
            else if (element.GetAttribute("value", logger, out var value))
            {
                var textRun = new TextRun(value.Value, new TextRunFormatting(TextRunFormattingType.Normal, size));

                if (!ValidateText(value, description, textRun.Text))
                {
                    return(false);
                }

                textCommand.TextRuns.Add(textRun);
            }
            else
            {
                return(false);
            }

            return(true);
        }
コード例 #5
0
        protected IEnumerable <RenderDescription> ReadRenderDescriptions(ComponentDescription description, XElement renderNode)
        {
            IConditionTreeItem conditionCollection = ConditionTree.Empty;
            var conditionsAttribute = renderNode.Attribute("conditions");

            if (conditionsAttribute != null)
            {
                if (!conditionParser.Parse(conditionsAttribute, description, logger, out conditionCollection))
                {
                    yield break;
                }
            }

            var declaredDefinitions  = new List <string>();
            var whenDefinedAttribute = renderNode.Attribute("whenDefined");

            if (whenDefinedAttribute != null)
            {
                var usedVariables = whenDefinedAttribute.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                declaredDefinitions.AddRange(usedVariables.Select(x => x.Substring(1)));
            }
            var allUndefined = declaredDefinitions.Except(availableDefinitions).ToHashSet();

            if (allUndefined.Any())
            {
                foreach (var undefined in allUndefined)
                {
                    logger.LogError(whenDefinedAttribute, $"Usage of undefined variable: ${undefined}");
                }
                yield break;
            }

            var commands = new List <IRenderCommand>();

            foreach (var renderCommandNode in renderNode.Descendants())
            {
                string commandType = renderCommandNode.Name.LocalName;
                if (commandType == "line")
                {
                    foreach (var renderLineDescription in ReadLineCommand(renderCommandNode, conditionCollection, declaredDefinitions))
                    {
                        yield return(renderLineDescription);
                    }
                }
                else if (commandType == "rect")
                {
                    foreach (var renderRectDescription in ReadRectCommand(renderCommandNode, conditionCollection, declaredDefinitions))
                    {
                        yield return(renderRectDescription);
                    }
                }
                else if (commandType == "ellipse")
                {
                    if (ReadEllipseCommand(description.Metadata.Version, renderCommandNode, out var command))
                    {
                        commands.Add(command);
                    }
                }
                else if (commandType == "text")
                {
                    foreach (var renderTextDescription in ReadTextCommand(renderCommandNode, description, conditionCollection, declaredDefinitions))
                    {
                        yield return(renderTextDescription);
                    }
                }
                else if (commandType == "path")
                {
                    if (ReadPathCommand(renderCommandNode, out var command))
                    {
                        commands.Add(command);
                    }
                }
            }

            yield return(new RenderDescription(conditionCollection, commands.ToArray()));
        }
コード例 #6
0
        public void ReadSection(XElement declarationElement, ComponentDescription description)
        {
            // Read meta nodes
            foreach (var metaElement in declarationElement.Elements(XmlLoader.ComponentNamespace + "meta"))
            {
                ReadMetaNode(metaElement, description);
            }

            // Check all required metadata was set
            if (string.IsNullOrEmpty(description.ComponentName))
            {
                logger.LogError(declarationElement, "Component name is required.");
            }

            // Read properties
            List <ComponentProperty> properties = new List <ComponentProperty>();

            foreach (var propertyElement in declarationElement.Elements(XmlLoader.ComponentNamespace + "property"))
            {
                ComponentProperty property = ScanPropertyNode(description, propertyElement);
                properties.Add(property);
            }
            description.Properties = properties.ToArray();

            properties.Clear();
            foreach (var propertyElement in declarationElement.Elements(XmlLoader.ComponentNamespace + "property"))
            {
                ComponentProperty property = ReadPropertyNode(description, propertyElement);
                properties.Add(property);
            }
            description.Properties = properties.ToArray();

            // Read flags
            List <Conditional <FlagOptions> > flagOptions = new List <Conditional <FlagOptions> >();

            foreach (var flagGroup in declarationElement.Elements(XmlLoader.ComponentNamespace + "flags"))
            {
                var flags = ReadFlagOptionNode(description, flagGroup);
                if (flags != null)
                {
                    flagOptions.Add(flags);
                }
            }

            description.Flags = flagOptions.ToArray();

            // Read configurations
            var componentConfigurations = new List <ComponentConfiguration>();
            var configurations          = declarationElement.Element(XmlLoader.ComponentNamespace + "configurations");

            if (configurations != null)
            {
                foreach (var node in configurations.Elements(XmlLoader.ComponentNamespace + "configuration"))
                {
                    ComponentConfiguration newConfiguration = ReadConfigurationNode(node, description);

                    componentConfigurations.Add(newConfiguration);
                }
            }

            description.Metadata.Configurations.AddRange(componentConfigurations);
        }
コード例 #7
0
ファイル: XmlLoader.cs プロジェクト: wyldesw/circuitdiagram
        public bool Load(Stream stream, IXmlLoadLogger logger, out ComponentDescription description)
        {
            description = new ComponentDescription();

            if (stream is FileStream fs)
            {
                description.Source = new ComponentDescriptionSource(fs.Name);
            }

            var errorCheckingLogger = new ErrorCheckingLogger(logger);
            var sectionRegistry     = new SectionRegistry();

            try
            {
                var root = XElement.Load(stream, LoadOptions.SetLineInfo);
                ReadHeader(root, description);

                var featureSwitcher = new FeatureSwitcher();

                // Read declaration
                var declaration = root.Element(ComponentNamespace + "declaration");
                if (declaration == null)
                {
                    logger.LogError(root, "Missing required element: 'declaration'");
                    return(false);
                }
                var declarationReader = container.Value.ResolveNamed <IXmlSectionReader>(declaration.Name.NamespaceName + ":" + declaration.Name.LocalName,
                                                                                         new TypedParameter(typeof(IXmlLoadLogger), errorCheckingLogger),
                                                                                         new TypedParameter(typeof(FeatureSwitcher), featureSwitcher));
                declarationReader.ReadSection(declaration, description);

                var descriptionInstance = description;
                var scope = container.Value.BeginLifetimeScope(configure =>
                {
                    configure.RegisterInstance(errorCheckingLogger).As <IXmlLoadLogger>();
                    configure.RegisterInstance(sectionRegistry).As <ISectionRegistry>();
                    configure.RegisterInstance(descriptionInstance);
                    configure.RegisterInstance(featureSwitcher).As <IFeatureSwitcher>();

                    foreach (var feature in features)
                    {
                        if (featureSwitcher.IsFeatureEnabled(feature.Key, out var featureSourceElement))
                        {
                            logger.Log(LogLevel.Information, featureSourceElement, $"Feature enabled: {feature.Key}");
                            feature.Value(configure);
                        }
                    }
                });

                try
                {
                    // Read remaining elements
                    foreach (var element in root.Elements().Except(new[] { declaration }))
                    {
                        var sectionReader = scope.ResolveOptionalNamed <IXmlSectionReader>(element.Name.NamespaceName + ":" + element.Name.LocalName);
                        sectionReader?.ReadSection(element, description);
                    }

                    return(!errorCheckingLogger.HasErrors);
                }
                finally
                {
                    scope.Dispose();
                }
            }
            catch (Exception ex)
            {
                logger.Log(LogLevel.Error, new FileRange(1, 1, 1, 2), ex.Message, ex);
                return(false);
            }
        }
コード例 #8
0
        protected virtual bool ReadTextCommand(XElement element, ComponentDescription description, out RenderText command)
        {
            command = new RenderText();

            ReadTextLocation(element, command);

            string tAlignment = "TopLeft";

            if (element.Attribute("align") != null)
            {
                tAlignment = element.Attribute("align").Value;
            }

            if (!Enum.TryParse(tAlignment, out TextAlignment alignment))
            {
                logger.LogError(element.Attribute("align"), $"Invalid value for text alignment: '{tAlignment}'");
            }
            command.Alignment = alignment;

            double size = 11d;

            if (element.Attribute("size") != null)
            {
                if (element.Attribute("size").Value.ToLowerInvariant() == "large")
                {
                    size = 12d;
                }
            }

            var textValueNode = element.Element(XmlLoader.ComponentNamespace + "value");

            if (textValueNode != null)
            {
                foreach (var spanNode in textValueNode.Elements())
                {
                    string nodeValue  = spanNode.Value;
                    var    formatting = TextRunFormatting.Normal;

                    if (spanNode.Name.LocalName == "sub")
                    {
                        formatting = TextRunFormatting.Subscript;
                    }
                    else if (spanNode.Name.LocalName == "sup")
                    {
                        formatting = TextRunFormatting.Superscript;
                    }
                    else if (spanNode.Name.LocalName != "span")
                    {
                        logger.LogWarning(spanNode, $"Unknown node '{spanNode.Name}' will be treated as <span>");
                    }

                    var textRun = new TextRun(nodeValue, formatting);

                    if (!ValidateText(element, description, textRun.Text))
                    {
                        return(false);
                    }

                    command.TextRuns.Add(textRun);
                }
            }
            else if (element.GetAttribute("value", logger, out var value))
            {
                var textRun = new TextRun(value.Value, new TextRunFormatting(TextRunFormattingType.Normal, size));

                if (!ValidateText(value, description, textRun.Text))
                {
                    return(false);
                }

                command.TextRuns.Add(textRun);
            }
            else
            {
                return(false);
            }

            return(true);
        }
コード例 #9
0
        public bool ReadRenderCommand(XElement element, ComponentDescription description, out IXmlRenderCommand command)
        {
            var textCommand = new XmlRenderText();

            command = textCommand;

            if (!ReadTextLocation(element, textCommand))
            {
                return(false);
            }

            string tAlignment = "TopLeft";

            if (element.Attribute("align") != null)
            {
                tAlignment = element.Attribute("align").Value;
            }

            if (!Enum.TryParse(tAlignment, out TextAlignment alignment))
            {
                logger.LogError(element.Attribute("align"), $"Invalid value for text alignment: '{tAlignment}'");
                return(false);
            }
            textCommand.Alignment = alignment;

            var tRotation = "0";

            if (description.Metadata.FormatVersion >= TextRotationMinFormatVersion && element.Attribute("rotate") != null)
            {
                tRotation = element.Attribute("rotate").Value;
            }

            var rotation = TextRotation.None;

            switch (tRotation)
            {
            case "0":
                rotation = TextRotation.None;
                break;

            case "90":
                rotation = TextRotation.Rotate90;
                break;

            case "180":
                rotation = TextRotation.Rotate180;
                break;

            case "270":
                rotation = TextRotation.Rotate270;
                break;

            default:
                logger.LogError(element.Attribute("rotate"), $"Invalid value for text rotation: '{tRotation}'");
                break;
            }
            textCommand.Rotation = rotation;

            double size = 11d;

            if (element.Attribute("size") != null)
            {
                switch (element.Attribute("size").Value.ToLowerInvariant())
                {
                case "large":
                    size = 12.0;
                    break;

                case "sm":
                case "small":
                    size = 10.0;
                    break;

                case "xs":
                    size = 9.0;
                    break;

                case "xxs":
                    size = 8.0;
                    break;

                default:
                    logger.LogWarning(element.Attribute("size"), $"Invalid value for size attribute: '{element.Attribute("size").Value}'");
                    break;
                }
            }

            var textValueNode = element.Element(XmlLoader.ComponentNamespace + "value");

            if (textValueNode != null)
            {
                foreach (var spanNode in textValueNode.Elements())
                {
                    string nodeValue  = spanNode.Value;
                    var    formatting = new TextRunFormatting(TextRunFormattingType.Normal, size);

                    if (spanNode.Name.LocalName == "sub")
                    {
                        formatting.FormattingType = TextRunFormattingType.Subscript;
                    }
                    else if (spanNode.Name.LocalName == "sup")
                    {
                        formatting.FormattingType = TextRunFormattingType.Superscript;
                    }
                    else if (spanNode.Name.LocalName != "span")
                    {
                        logger.LogWarning(spanNode, $"Unknown node '{spanNode.Name}' will be treated as <span>");
                    }

                    var textRun = new TextRun(nodeValue, formatting);

                    if (!ValidateText(element, description, textRun.Text))
                    {
                        return(false);
                    }

                    textCommand.TextRuns.Add(textRun);
                }
            }
            else if (element.GetAttribute("value", logger, out var value))
            {
                var textRun = new TextRun(value.Value, new TextRunFormatting(TextRunFormattingType.Normal, size));

                if (!ValidateText(value, description, textRun.Text))
                {
                    return(false);
                }

                textCommand.TextRuns.Add(textRun);
            }
            else
            {
                return(false);
            }

            return(true);
        }