public void AddComponent_ReturnsFirstAddedComponent_WhenComponentAddedTwice()
        {
            // Arrange

            var testInputTargetType = ThemeComponentType.TextColor;
            var testInputComponentName = "testComponent";
            var testInputColor = new Color();

            var componentCollection = new ThemeComponentCollection();

            // Act
            var firstResult = componentCollection.AddComponent(testInputTargetType, testInputComponentName, testInputColor);
            var secondResult = componentCollection.AddComponent(testInputTargetType, testInputComponentName, testInputColor);

            // Assert
            Assert.AreSame(firstResult, secondResult);
        }
        private T GetColorBlockItemFromString <T>(string inputString) where T : ColorBlockItem
        {
            var blockItem = Activator.CreateInstance <T>();
            var result    = Regex.Matches(inputString, @"([\w\s]*)[#]?(.*)");

            blockItem.Color = GetColorFromString(result[0].Groups[1].Value);

            var componentName = result[0].Groups[2].Value.Trim();

            if (!string.IsNullOrEmpty(componentName))
            {
                ThemeComponentType componentType;
                if (typeof(T) == typeof(TextColorBlockItem))
                {
                    componentType = ThemeComponentType.TextColor;
                }
                else if (typeof(T) == typeof(BackgroundColorBlockItem))
                {
                    componentType = ThemeComponentType.BackgroundColor;
                }
                else if (typeof(T) == typeof(BorderColorBlockItem))
                {
                    componentType = ThemeComponentType.BorderColor;
                }
                else
                {
                    throw new Exception("Parsing error - unknown theme component type");
                }
                if (_masterComponentCollection != null)
                {
                    blockItem.ThemeComponent = _masterComponentCollection.AddComponent(componentType, componentName,
                                                                                       blockItem.Color);
                }
            }

            return(blockItem);
        }
Пример #3
0
        // This method converts a string into a ItemFilterBlock. This is used for pasting ItemFilterBlocks
        // and reading ItemFilterScripts from a file.
        public IItemFilterBlock TranslateStringToItemFilterBlock(string inputString, IItemFilterScript parentItemFilterScript, string originalString = "", bool initialiseBlockGroupHierarchyBuilder = false)
        {
            if (initialiseBlockGroupHierarchyBuilder)
            {
                _blockGroupHierarchyBuilder.Initialise(parentItemFilterScript.ItemFilterBlockGroups.First());
            }

            _masterComponentCollection = parentItemFilterScript.ItemFilterScriptSettings.ThemeComponentCollection;
            var block         = new ItemFilterBlock(parentItemFilterScript);
            var showHideFound = false;

            block.OriginalText = originalString;

            foreach (var line in new LineReader(() => new StringReader(inputString)))
            {
                if (line.StartsWith(@"#"))
                {
                    if (!showHideFound)
                    {
                        block.Description = line.TrimStart('#').TrimStart(' ');
                    }
                    else
                    {
                        if (block.BlockItems.Count > 1)
                        {
                            block.BlockItems.Last().Comment += Environment.NewLine + line.TrimStart('#');
                        }
                        else
                        {
                            block.ActionBlockItem.Comment += Environment.NewLine + line.TrimStart('#');
                        }
                    }
                    continue;
                }

                var fullLine           = line.Trim();
                var trimmedLine        = fullLine;
                var blockComment       = "";
                var themeComponentType = -1;
                if (trimmedLine.IndexOf('#') > 0)
                {
                    blockComment = trimmedLine.Substring(trimmedLine.IndexOf('#') + 1);
                    trimmedLine  = trimmedLine.Substring(0, trimmedLine.IndexOf('#')).Trim();
                }
                var spaceOrEndOfLinePos = trimmedLine.IndexOf(" ", StringComparison.Ordinal) > 0 ? trimmedLine.IndexOf(" ", StringComparison.Ordinal) : trimmedLine.Length;

                var lineOption = trimmedLine.Substring(0, spaceOrEndOfLinePos);
                switch (lineOption)
                {
                case "Show":
                case "Hide":
                case "ShowDisabled":
                case "HideDisabled":
                {
                    showHideFound = true;
                    block.Action  = lineOption.StartsWith("Show") ? BlockAction.Show : BlockAction.Hide;
                    block.Enabled = !lineOption.EndsWith("Disabled");

                    // If block groups are enabled for this script, the comment after Show/Hide is parsed as a block
                    // group hierarchy, if block groups are disabled it is preserved as a simple text comment.
                    if (parentItemFilterScript.ItemFilterScriptSettings.BlockGroupsEnabled)
                    {
                        AddBlockGroupToBlock(block, fullLine);
                    }
                    else
                    {
                        block.ActionBlockItem.Comment = GetTextAfterFirstComment(fullLine);
                    }
                    break;
                }

                case "ItemLevel":
                {
                    AddNumericFilterPredicateItemToBlockItems <ItemLevelBlockItem>(block, trimmedLine);
                    break;
                }

                case "DropLevel":
                {
                    AddNumericFilterPredicateItemToBlockItems <DropLevelBlockItem>(block, trimmedLine);
                    break;
                }

                case "Quality":
                {
                    AddNumericFilterPredicateItemToBlockItems <QualityBlockItem>(block, trimmedLine);
                    break;
                }

                case "Rarity":
                {
                    RemoveExistingBlockItemsOfType <RarityBlockItem>(block);

                    var blockItemValue = new RarityBlockItem();
                    var result         = Regex.Match(trimmedLine, @"^\w+\s+([><!=]{0,2})\s*(\w+)$");
                    if (result.Groups.Count == 3)
                    {
                        blockItemValue.FilterPredicate.PredicateOperator =
                            EnumHelper.GetEnumValueFromDescription <FilterPredicateOperator>(string.IsNullOrEmpty(result.Groups[1].Value) ? "=" : result.Groups[1].Value);
                        blockItemValue.FilterPredicate.PredicateOperand =
                            (int)EnumHelper.GetEnumValueFromDescription <ItemRarity>(result.Groups[2].Value);
                    }

                    block.BlockItems.Add(blockItemValue);
                    break;
                }

                case "Class":
                {
                    AddStringListItemToBlockItems <ClassBlockItem>(block, trimmedLine);
                    break;
                }

                case "BaseType":
                {
                    AddStringListItemToBlockItems <BaseTypeBlockItem>(block, trimmedLine);
                    break;
                }

                case "Prophecy":
                {
                    AddStringListItemToBlockItems <ProphecyBlockItem>(block, trimmedLine);
                    break;
                }

                case "Corrupted":
                {
                    AddBooleanItemToBlockItems <CorruptedBlockItem>(block, trimmedLine);
                    break;
                }

                case "Identified":
                {
                    AddBooleanItemToBlockItems <IdentifiedBlockItem>(block, trimmedLine);
                    break;
                }

                case "ElderItem":
                {
                    AddBooleanItemToBlockItems <ElderItemBlockItem>(block, trimmedLine);
                    break;
                }

                case "ShaperItem":
                {
                    AddBooleanItemToBlockItems <ShaperItemBlockItem>(block, trimmedLine);
                    break;
                }

                case "ShapedMap":
                {
                    AddBooleanItemToBlockItems <ShapedMapBlockItem>(block, trimmedLine);
                    break;
                }

                case "Sockets":
                {
                    AddNumericFilterPredicateItemToBlockItems <SocketsBlockItem>(block, trimmedLine);
                    break;
                }

                case "LinkedSockets":
                {
                    AddNumericFilterPredicateItemToBlockItems <LinkedSocketsBlockItem>(block, trimmedLine);
                    break;
                }

                case "Width":
                {
                    AddNumericFilterPredicateItemToBlockItems <WidthBlockItem>(block, trimmedLine);
                    break;
                }

                case "Height":
                {
                    AddNumericFilterPredicateItemToBlockItems <HeightBlockItem>(block, trimmedLine);
                    break;
                }

                case "SocketGroup":
                {
                    AddStringListItemToBlockItems <SocketGroupBlockItem>(block, trimmedLine);
                    break;
                }

                case "SetTextColor":
                {
                    // Only ever use the last SetTextColor item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <TextColorBlockItem>(block);

                    var result = Regex.Matches(trimmedLine, @"([\w\s]*)");

                    var blockItem = new TextColorBlockItem {
                        Color = GetColorFromString(result[0].Groups[1].Value)
                    };
                    block.BlockItems.Add(blockItem);
                    themeComponentType = (int)ThemeComponentType.TextColor;
                    break;
                }

                case "SetBackgroundColor":
                {
                    // Only ever use the last SetBackgroundColor item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <BackgroundColorBlockItem>(block);

                    var result = Regex.Matches(trimmedLine, @"([\w\s]*)");

                    var blockItem = new BackgroundColorBlockItem {
                        Color = GetColorFromString(result[0].Groups[1].Value)
                    };
                    block.BlockItems.Add(blockItem);
                    themeComponentType = (int)ThemeComponentType.BackgroundColor;
                    break;
                }

                case "SetBorderColor":
                {
                    // Only ever use the last SetBorderColor item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <BorderColorBlockItem>(block);

                    var result = Regex.Matches(trimmedLine, @"([\w\s]*)");

                    var blockItem = new BorderColorBlockItem {
                        Color = GetColorFromString(result[0].Groups[1].Value)
                    };
                    block.BlockItems.Add(blockItem);
                    themeComponentType = (int)ThemeComponentType.BorderColor;
                    break;
                }

                case "SetFontSize":
                {
                    // Only ever use the last SetFontSize item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <FontSizeBlockItem>(block);

                    var match = Regex.Matches(trimmedLine, @"(\s+(\d+)\s*)");
                    if (match.Count > 0)
                    {
                        var blockItem = new FontSizeBlockItem(Convert.ToInt16(match[0].Groups[2].Value));
                        block.BlockItems.Add(blockItem);
                        themeComponentType = (int)ThemeComponentType.FontSize;
                    }
                    break;
                }

                case "PlayAlertSound":
                case "PlayAlertSoundPositional":
                {
                    // Only ever use the last PlayAlertSound item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <SoundBlockItem>(block);
                    RemoveExistingBlockItemsOfType <PositionalSoundBlockItem>(block);
                    RemoveExistingBlockItemsOfType <CustomSoundBlockItem>(block);

                    var match = Regex.Match(trimmedLine, @"\S+\s+(\S+)\s?(\d+)?");

                    if (match.Success)
                    {
                        string firstValue = match.Groups[1].Value;

                        var secondValue = match.Groups[2].Success ? Convert.ToInt16(match.Groups[2].Value) : 79;

                        if (lineOption == "PlayAlertSound")
                        {
                            var blockItemValue = new SoundBlockItem
                            {
                                Value       = firstValue,
                                SecondValue = secondValue
                            };
                            block.BlockItems.Add(blockItemValue);
                        }
                        else
                        {
                            var blockItemValue = new PositionalSoundBlockItem
                            {
                                Value       = firstValue,
                                SecondValue = secondValue
                            };
                            block.BlockItems.Add(blockItemValue);
                        }
                        themeComponentType = (int)ThemeComponentType.AlertSound;
                    }
                    break;
                }

                case "GemLevel":
                {
                    AddNumericFilterPredicateItemToBlockItems <GemLevelBlockItem>(block, trimmedLine);
                    break;
                }

                case "StackSize":
                {
                    AddNumericFilterPredicateItemToBlockItems <StackSizeBlockItem>(block, trimmedLine);
                    break;
                }

                case "HasExplicitMod":
                {
                    AddStringListItemToBlockItems <HasExplicitModBlockItem>(block, trimmedLine);
                    break;
                }

                case "ElderMap":
                {
                    AddBooleanItemToBlockItems <ElderMapBlockItem>(block, trimmedLine);
                    break;
                }

                case "DisableDropSound":
                {
                    // Only ever use the last DisableDropSound item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <DisableDropSoundBlockItem>(block);

                    AddNilItemToBlockItems <DisableDropSoundBlockItem>(block, trimmedLine);
                    break;
                }

                case "MinimapIcon":
                {
                    // Only ever use the last Icon item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <MapIconBlockItem>(block);

                    // TODO: Get size, color, shape values programmatically
                    var match = Regex.Match(trimmedLine,
                                            @"\S+\s+(0|1|2)\s+(Red|Green|Blue|Brown|White|Yellow)\s+(Circle|Diamond|Hexagon|Square|Star|Triangle)\s*([#]?)(.*)",
                                            RegexOptions.IgnoreCase);

                    if (match.Success)
                    {
                        var blockItemValue = new MapIconBlockItem
                        {
                            Size  = (IconSize)short.Parse(match.Groups[1].Value),
                            Color = EnumHelper.GetEnumValueFromDescription <IconColor>(match.Groups[2].Value),
                            Shape = EnumHelper.GetEnumValueFromDescription <IconShape>(match.Groups[3].Value)
                        };

                        block.BlockItems.Add(blockItemValue);
                        themeComponentType = (int)ThemeComponentType.Icon;
                    }
                    break;
                }

                case "PlayEffect":
                {
                    // Only ever use the last BeamColor item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <PlayEffectBlockItem>(block);

                    // TODO: Get colors programmatically
                    var match = Regex.Match(trimmedLine, @"\S+\s+(Red|Green|Blue|Brown|White|Yellow)\s*(Temp)?", RegexOptions.IgnoreCase);

                    if (match.Success)
                    {
                        var blockItemValue = new PlayEffectBlockItem
                        {
                            Color     = EnumHelper.GetEnumValueFromDescription <EffectColor>(match.Groups[1].Value),
                            Temporary = match.Groups[2].Value.Trim().ToLower() == "temp"
                        };
                        block.BlockItems.Add(blockItemValue);
                        themeComponentType = (int)ThemeComponentType.Effect;
                    }
                    break;
                }

                case "CustomAlertSound":
                {
                    // Only ever use the last CustomSoundBlockItem item encountered as multiples aren't valid.
                    RemoveExistingBlockItemsOfType <CustomSoundBlockItem>(block);
                    RemoveExistingBlockItemsOfType <SoundBlockItem>(block);
                    RemoveExistingBlockItemsOfType <PositionalSoundBlockItem>(block);

                    var match = Regex.Match(trimmedLine, @"\S+\s+""([^\*\<\>\?|]+)""");

                    if (match.Success)
                    {
                        var blockItemValue = new CustomSoundBlockItem
                        {
                            Value = match.Groups[1].Value
                        };
                        block.BlockItems.Add(blockItemValue);
                        themeComponentType = (int)ThemeComponentType.CustomSound;
                    }
                    break;
                }

                case "MapTier":
                {
                    AddNumericFilterPredicateItemToBlockItems <MapTierBlockItem>(block, trimmedLine);
                    break;
                }
                }

                if (!string.IsNullOrWhiteSpace(blockComment) && block.BlockItems.Count > 1)
                {
                    if (!(block.BlockItems.Last() is IBlockItemWithTheme blockItemWithTheme))
                    {
                        block.BlockItems.Last().Comment = blockComment;
                    }
                    else
                    {
                        switch ((ThemeComponentType)themeComponentType)
                        {
                        case ThemeComponentType.AlertSound:
                        {
                            ThemeComponent themeComponent;
                            if (blockItemWithTheme is SoundBlockItem item)
                            {
                                themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.AlertSound, blockComment.Trim(),
                                                                                         item.Value, item.SecondValue);
                            }
                            else
                            {
                                themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.AlertSound, blockComment.Trim(),
                                                                                         ((PositionalSoundBlockItem)blockItemWithTheme).Value, ((PositionalSoundBlockItem)blockItemWithTheme).SecondValue);
                            }
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.BackgroundColor:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.BackgroundColor,
                                                                                                    blockComment.Trim(), ((BackgroundColorBlockItem)blockItemWithTheme).Color);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.BorderColor:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.BorderColor,
                                                                                                    blockComment.Trim(), ((BorderColorBlockItem)blockItemWithTheme).Color);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.CustomSound:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.CustomSound,
                                                                                                    blockComment.Trim(), ((CustomSoundBlockItem)blockItemWithTheme).Value);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.Effect:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.Effect,
                                                                                                    blockComment.Trim(), ((EffectColorBlockItem)blockItemWithTheme).Color, ((EffectColorBlockItem)blockItemWithTheme).Temporary);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.FontSize:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.FontSize,
                                                                                                    blockComment.Trim(), ((FontSizeBlockItem)blockItemWithTheme).Value);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.Icon:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.Icon, blockComment.Trim(),
                                                                                                    ((IconBlockItem)blockItemWithTheme).Size, ((IconBlockItem)blockItemWithTheme).Color, ((IconBlockItem)blockItemWithTheme).Shape);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }

                        case ThemeComponentType.TextColor:
                        {
                            ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.TextColor,
                                                                                                    blockComment.Trim(), ((TextColorBlockItem)blockItemWithTheme).Color);
                            blockItemWithTheme.ThemeComponent = themeComponent;
                            break;
                        }
                        }
                    }
                }
            }
        public void ReplaceAudioVisualBlockItemsFromString(ObservableCollection <IItemFilterBlockItem> blockItems, string inputString)
        {
            // Reverse iterate to remove existing IAudioVisualBlockItems
            for (var idx = blockItems.Count - 1; idx >= 0; idx--)
            {
                if (blockItems[idx] is IAudioVisualBlockItem)
                {
                    blockItems.RemoveAt(idx);
                }
            }

            foreach (var line in new LineReader(() => new StringReader(inputString)))
            {
                var matches      = Regex.Match(line, @"(\w+)");
                var blockComment = "";
                var trimmedLine  = line.Trim();
                if (trimmedLine.IndexOf('#') > 0)
                {
                    blockComment = trimmedLine.Substring(trimmedLine.IndexOf('#') + 1);
                    trimmedLine  = trimmedLine.Substring(0, trimmedLine.IndexOf('#')).Trim();
                }

                switch (matches.Value)
                {
                case "PlayAlertSound":
                {
                    var match = Regex.Match(trimmedLine, @"\s+(\S+) (\d+)");
                    if (!match.Success)
                    {
                        break;
                    }
                    var blockItem = new SoundBlockItem(match.Groups[1].Value, Convert.ToInt16(match.Groups[2].Value));
                    if (_masterComponentCollection != null && !string.IsNullOrWhiteSpace(blockComment))
                    {
                        ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.AlertSound,
                                                                                                blockComment, blockItem.Value, blockItem.SecondValue);
                        blockItem.ThemeComponent = themeComponent;
                    }
                    blockItems.Add(blockItem);
                    break;
                }

                case "SetTextColor":
                {
                    var result = Regex.Matches(trimmedLine, @"([\w\s]*)");

                    var blockItem = new TextColorBlockItem();
                    blockItem.Color = GetColorFromString(result[0].Groups[1].Value);
                    if (_masterComponentCollection != null && !string.IsNullOrWhiteSpace(blockComment))
                    {
                        ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.TextColor,
                                                                                                blockComment, blockItem.Color);
                        blockItem.ThemeComponent = themeComponent;
                    }
                    blockItems.Add(blockItem);
                    break;
                }

                case "SetBackgroundColor":
                {
                    var result = Regex.Matches(trimmedLine, @"([\w\s]*)");

                    var blockItem = new BackgroundColorBlockItem();
                    blockItem.Color = GetColorFromString(result[0].Groups[1].Value);
                    if (_masterComponentCollection != null && !string.IsNullOrWhiteSpace(blockComment))
                    {
                        ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.BackgroundColor,
                                                                                                blockComment, blockItem.Color);
                        blockItem.ThemeComponent = themeComponent;
                    }
                    blockItems.Add(blockItem);
                    break;
                }

                case "SetBorderColor":
                {
                    var result = Regex.Matches(trimmedLine, @"([\w\s]*)");

                    var blockItem = new BorderColorBlockItem();
                    blockItem.Color = GetColorFromString(result[0].Groups[1].Value);
                    if (_masterComponentCollection != null && !string.IsNullOrWhiteSpace(blockComment))
                    {
                        ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.BorderColor,
                                                                                                blockComment, blockItem.Color);
                        blockItem.ThemeComponent = themeComponent;
                    }
                    blockItems.Add(blockItem);
                    break;
                }

                case "SetFontSize":
                {
                    var match = Regex.Match(trimmedLine, @"\s+(\d+)");
                    if (!match.Success)
                    {
                        break;
                    }
                    var blockItem = new FontSizeBlockItem(Convert.ToInt16(match.Value));
                    if (_masterComponentCollection != null && !string.IsNullOrWhiteSpace(blockComment))
                    {
                        ThemeComponent themeComponent = _masterComponentCollection.AddComponent(ThemeComponentType.FontSize,
                                                                                                blockComment, blockItem.Value);
                        blockItem.ThemeComponent = themeComponent;
                    }
                    blockItems.Add(blockItem);
                    break;
                }
                }
            }
        }