/// <summary>
        /// Constructs a new SettingsViewModel that operates on the given skill tree.
        /// </summary>
        /// <param name="tree">The skill tree to operate on. (not null)</param>
        /// <param name="dialogCoordinator"></param>
        /// <param name="generator">Optional <see cref="GeneratorTabViewModel"/> initialize
        /// <see cref="Tabs"/> with. If non is provided, <see cref="AdvancedTabViewModel"/>,
        /// <see cref="AutomatedTabViewModel"/> and <see cref="SteinerTabViewModel"/> will be
        /// added to <see cref="Tabs"/>.</param>
        public SettingsViewModel(SkillTree tree, ISettingsDialogCoordinator dialogCoordinator, GeneratorTabViewModel generator = null)
        {
            if (tree == null)
            {
                throw new ArgumentNullException("tree");
            }

            DisplayName = L10n.Message("Skill tree Generator").ToUpper();

            _tree = tree;
            _dialogCoordinator = dialogCoordinator;
            AdditionalPoints   = CalculateAdditionalPointsNeeded(tree);

            tree.PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == "Level")
                {
                    TotalPoints = _tree.Level - 1 + _additionalPoints;
                }
            };

            if (generator == null)
            {
                CreateTabs();
            }
            else
            {
                Tabs = new ObservableCollection <GeneratorTabViewModel> {
                    generator
                };
            }
        }
        public TreeGeneratorInteraction(ISettingsDialogCoordinator dialogCoordinator, IPersistentData persistentData,
                                        SkillTree skillTree)
        {
            _persistentData    = persistentData;
            _dialogCoordinator = dialogCoordinator;
            SkillTree          = skillTree;

            OpenTreeGeneratorCommand = new AsyncRelayCommand(OpenTreeGenerator);
            RunTaggedNodesCommand    = new AsyncRelayCommand(RunTaggedNodes);
            RunAdvancedCommand       = new AsyncRelayCommand(RunAdvanced);
        }
        public TreeGeneratorInteraction(ISettingsDialogCoordinator dialogCoordinator, IPersistentData persistentData,
            SkillTree skillTree)
        {
            _persistentData = persistentData;
            _dialogCoordinator = dialogCoordinator;
            SkillTree = skillTree;

            OpenTreeGeneratorCommand = new AsyncRelayCommand(OpenTreeGenerator);
            RunTaggedNodesCommand = new AsyncRelayCommand(RunTaggedNodes);
            RunAdvancedCommand = new AsyncRelayCommand(RunAdvanced);
        }
        /// <summary>
        /// Constructs a new SettingsViewModel that operates on the given skill tree.
        /// </summary>
        /// <param name="tree">The skill tree to operate on. (not null)</param>
        /// <param name="dialogCoordinator"></param>
        public SettingsViewModel(SkillTree tree, ISettingsDialogCoordinator dialogCoordinator)
        {
            Tree = tree;
            _dialogCoordinator = dialogCoordinator;

            SelectedTabIndex = new LeafSetting<int>(nameof(SelectedTabIndex), 0);

            Action<GeneratorTabViewModel> runCallback = async g => await RunAsync(g);
            Tabs = new ObservableCollection<GeneratorTabViewModel>
            {
                new SteinerTabViewModel(Tree, _dialogCoordinator, this, runCallback),
                new AdvancedTabViewModel(Tree, _dialogCoordinator, this, runCallback),
                new AutomatedTabViewModel(Tree, _dialogCoordinator, this, runCallback)
            };
            SubSettings = new ISetting[] {SelectedTabIndex}.Union(Tabs).ToArray();
        }
        /// <summary>
        /// Constructs a new SettingsViewModel that operates on the given skill tree.
        /// </summary>
        /// <param name="tree">The skill tree to operate on. (not null)</param>
        /// <param name="dialogCoordinator"></param>
        public SettingsViewModel(SkillTree tree, ISettingsDialogCoordinator dialogCoordinator)
        {
            Tree = tree;
            _dialogCoordinator = dialogCoordinator;

            SelectedTabIndex = new LeafSetting <int>(nameof(SelectedTabIndex), 0);

            Action <GeneratorTabViewModel> runCallback = async g => await RunAsync(g);

            Tabs = new ObservableCollection <GeneratorTabViewModel>
            {
                new SteinerTabViewModel(Tree, _dialogCoordinator, this, runCallback),
                new AdvancedTabViewModel(Tree, _dialogCoordinator, this, runCallback),
                new AutomatedTabViewModel(Tree, _dialogCoordinator, this, runCallback)
            };
            SubSettings = new ISetting[] { SelectedTabIndex }.Union(Tabs).ToArray();
        }
        /// <summary>
        /// Constructs a new SettingsViewModel that operates on the given skill tree.
        /// </summary>
        /// <param name="tree">The skill tree to operate on. (not null)</param>
        /// <param name="persistentData"></param>
        /// <param name="dialogCoordinator"></param>
        /// <param name="dialogContext">The context used for <paramref name="dialogCoordinator"/>.</param>
        public SettingsViewModel(SkillTree tree, IPersistentData persistentData, ISettingsDialogCoordinator dialogCoordinator, object dialogContext)
        {
            Tree = tree;
            _dialogCoordinator = dialogCoordinator;
            _dialogContext     = dialogContext;

            SelectedTabIndex = new LeafSetting <int>(nameof(SelectedTabIndex), 0);

            async void RunCallback(GeneratorTabViewModel g) => await RunAsync(g);

            Tabs = new ObservableCollection <GeneratorTabViewModel>
            {
                new SteinerTabViewModel(Tree, _dialogCoordinator, _dialogContext, RunCallback),
                new AdvancedTabViewModel(Tree, persistentData, _dialogCoordinator, _dialogContext, RunCallback),
                new AutomatedTabViewModel(Tree, _dialogCoordinator, _dialogContext, RunCallback)
            };
            SubSettings = new ISetting[] { SelectedTabIndex }.Union(Tabs).ToArray();
        }