public override StateRefreshChanges ToggleState(int row, int column) { StateRefreshChanges retVal = StateRefreshChanges.None; IORMGenerator selectedGenerator = _selectedORMGenerator; if (selectedGenerator == null) { retVal = _mainBranch.ToggleOnRequiredBranches(this, row); } else { IORMGenerator newGenerator = _ormGenerators[row]; if (object.ReferenceEquals(newGenerator, selectedGenerator)) { retVal = _mainBranch.ToggleOnRequiredBranches(this, row, true); } else { _mainBranch.RemoveGenerator(this); retVal = _mainBranch.ToggleOnRequiredBranches(this, row, false); } } if (retVal != StateRefreshChanges.None && retVal != StateRefreshChanges.Entire) { retVal = StateRefreshChanges.ParentsChildren; } return(retVal); }
public override VirtualTreeDisplayData GetDisplayData(int row, int column, VirtualTreeDisplayDataMasks requiredData) { VirtualTreeDisplayData displayData = VirtualTreeDisplayData.Empty; bool isModifierRow = TranslateRow(ref row) == RowStyle.Modifier; IORMGenerator selectedGenerator = isModifierRow ? _modifiers[row].SelectedORMGenerator : _branches.Values[row].SelectedORMGenerator; switch (column) { case ColumnNumber.GeneratedFormat: if (selectedGenerator != null) { displayData.Bold = true; } if (0 != (requiredData.Mask & VirtualTreeDisplayMasks.StateImage)) { if (selectedGenerator != null) { // Don't allow this to uncheck if another tool is using it displayData.StateImageIndex = (short)((isModifierRow || CanRemoveGenerator(row)) ? StandardCheckBoxImage.Checked : StandardCheckBoxImage.CheckedDisabled); } else { displayData.StateImageIndex = (short)StandardCheckBoxImage.Unchecked; } } break; case ColumnNumber.GeneratedFileName: displayData.GrayText = true; break; } return(displayData); }
/// <summary> /// Remove the generator for this branch. Note that there is /// no checking here as to whether or not the generator is required /// in other places. Most uses will first call CanRemoveGenerator, but /// switching generators for a format will want to remove this blindly /// then toggle on the other format provider. /// </summary> /// <param name="formatBranch">The branch to remove from the generation process</param> private void RemoveGenerator(OutputFormatBranch formatBranch) { IORMGenerator removeGenerator = formatBranch.SelectedORMGenerator; if (removeGenerator.IsFormatModifier) { OutputFormatBranch primaryBranch = _branches[removeGenerator.ProvidesOutputFormat]; IORMGenerator primaryGenerator = primaryBranch.SelectedORMGenerator; if (primaryGenerator != null) { formatBranch.SelectedORMGenerator = null; PseudoBuildItem pseudoItem; // Turning off a format modifier can indirectly remove the generated target, so make // sure it is still there when the modifier itself is removed. if (_parent.PseudoItemsByOutputFormat.TryGetValue(primaryGenerator.ProvidesOutputFormat, out pseudoItem)) { pseudoItem.CurrentGeneratorNames = primaryBranch.SelectedGeneratorOfficialNames; } } } else { formatBranch.SelectedORMGenerator = null; _parent.RemovePseudoItem(removeGenerator.ProvidesOutputFormat); } }
private static void LoadGenerators(RegistryKey generatorsKey, IDictionary <string, IORMGenerator> generators #if VISUALSTUDIO_15_0 // Allow resolution of reg: prefixed transform URI's , RegistryKey rootKey #endif ) { if (generatorsKey == null) { return; } string[] generatorNames = generatorsKey.GetSubKeyNames(); for (int i = 0; i < generatorNames.Length; i++) { string generatorName = generatorNames[i]; RegistryKey generatorKey = null; try { generatorKey = generatorsKey.OpenSubKey(generatorName, RegistryKeyPermissionCheck.ReadSubTree); string type = generatorKey.GetValue("Type", null) as string; IORMGenerator ormGenerator = null; if (String.Equals(type, "XSLT", StringComparison.OrdinalIgnoreCase)) { ormGenerator = new XslORMGenerator(generatorKey #if VISUALSTUDIO_15_0 , rootKey #endif ); } else if (String.Equals(type, "Class", StringComparison.OrdinalIgnoreCase)) { ormGenerator = LoadGeneratorClass(generatorKey); } if (ormGenerator != null) { System.Diagnostics.Debug.Assert(String.Equals(generatorName, ormGenerator.OfficialName, StringComparison.OrdinalIgnoreCase)); //ormGenerator.ORMCustomTool = this; generators.Add(ormGenerator.OfficialName, ormGenerator); } } catch (Exception ex) { // TODO: Localize message. ReportError("WARNING: Exception ocurred while trying to load generator \"" + generatorName + "\" in ORMCustomTool:", ex); } finally { if (generatorKey != null) { generatorKey.Close(); } } } }
public override string GetTipText(int row, int column, ToolTipType tipType) { if (column == ColumnNumber.GeneratedFormat && tipType == ToolTipType.StateIcon) { OutputFormatBranch currentBranch = (TranslateRow(ref row) == RowStyle.Generator) ? _branches.Values[row] : _modifiers[row]; IORMGenerator useGenerator = currentBranch.SelectedORMGenerator; if (useGenerator == null) { useGenerator = currentBranch.ORMGenerators[0]; } return(useGenerator.DisplayDescription); } return(base.GetTipText(row, column, tipType)); }
/// <summary> /// Remove the generator for this branch. Note that there is /// no checking here as to whether or not the generator is required /// in other places. Most uses will first call CanRemoveGenerator, but /// switching generators for a format will want to remove this blindly /// then toggle on the other format provider. /// </summary> /// <param name="formatBranch">The branch to remove from the generation process</param> private void RemoveGenerator(OutputFormatBranch formatBranch) { IORMGenerator removeGenerator = formatBranch.SelectedORMGenerator; #if VISUALSTUDIO_10_0 IDictionary <string, ProjectItemElement> buildItemsByGeneratorName #else IDictionary <string, BuildItem> buildItemsByGeneratorName #endif = _parent.BuildItemsByGenerator; if (removeGenerator.IsFormatModifier) { OutputFormatBranch primaryBranch = _branches[removeGenerator.ProvidesOutputFormat]; IORMGenerator primaryGenerator = primaryBranch.SelectedORMGenerator; if (primaryGenerator != null) { #if VISUALSTUDIO_10_0 ProjectItemElement updateBuildItem #else BuildItem updateBuildItem #endif = buildItemsByGeneratorName[primaryGenerator.OfficialName]; formatBranch.SelectedORMGenerator = null; SetItemMetaData(updateBuildItem, ITEMMETADATA_ORMGENERATOR, primaryBranch.SelectedGeneratorOfficialNames); } } else { string generatorKey = removeGenerator.OfficialName; formatBranch.SelectedORMGenerator = null; #if VISUALSTUDIO_10_0 ProjectItemElement removeBuildItem #else BuildItem removeBuildItem #endif = buildItemsByGeneratorName[generatorKey]; buildItemsByGeneratorName.Remove(generatorKey); #if VISUALSTUDIO_10_0 _parent._itemGroup.RemoveChild(removeBuildItem); #else _parent._itemGroup.RemoveItem(removeBuildItem); #endif _parent.AddRemovedItem(removeBuildItem); } }
public override string GetText(int row, int column) { string retVal = null; switch (column) { case ColumnNumber.GeneratedFormat: switch (TranslateRow(ref row)) { case RowStyle.Generator: retVal = _branches.Keys[row]; break; case RowStyle.Modifier: retVal = _modifiers[row].ORMGenerators[0].DisplayName; break; } break; case ColumnNumber.GeneratedFileName: { IORMGenerator selectedORMGenerator = null; switch (TranslateRow(ref row)) { case RowStyle.Generator: selectedORMGenerator = _branches.Values[row].SelectedORMGenerator; break; case RowStyle.Modifier: selectedORMGenerator = _modifiers[row].SelectedORMGenerator; if (selectedORMGenerator != null) { selectedORMGenerator = _branches[selectedORMGenerator.ProvidesOutputFormat].SelectedORMGenerator; } break; } if (selectedORMGenerator != null) { retVal = ORMCustomToolUtility.GetItemInclude(_parent.BuildItemsByGenerator[selectedORMGenerator.OfficialName]); } } break; } return(retVal); }
public override string GetText(int row, int column) { string retVal = null; switch (column) { case ColumnNumber.GeneratedFormat: switch (TranslateRow(ref row)) { case RowStyle.Generator: retVal = _branches.Keys[row]; break; case RowStyle.Modifier: retVal = _modifiers[row].ORMGenerators[0].DisplayName; break; } break; case ColumnNumber.GeneratedFileName: { IORMGenerator selectedORMGenerator = null; switch (TranslateRow(ref row)) { case RowStyle.Generator: selectedORMGenerator = _branches.Values[row].SelectedORMGenerator; break; case RowStyle.Modifier: selectedORMGenerator = _modifiers[row].SelectedORMGenerator; if (selectedORMGenerator != null) { selectedORMGenerator = _branches[selectedORMGenerator.ProvidesOutputFormat].SelectedORMGenerator; } break; } if (selectedORMGenerator != null) { retVal = _parent.PseudoItemsByOutputFormat[selectedORMGenerator.ProvidesOutputFormat].DefaultGeneratedFileName; } } break; } return(retVal); }
/// <summary> /// Add a new item, or resurrect a deleted one. /// </summary> /// <param name="generator">The generator to add.</param> /// <param name="currentGeneratorNames">The current generator names. Note that if this is a /// toggle that adds a new generator for the same format, then the current names may /// include format modifiers that are not available from the generator itself.</param> private void AddPseudoItem(IORMGenerator generator, string currentGeneratorNames) { Dictionary <string, PseudoBuildItem> items = _pseudoItemsByOutputFormat; string outputFormat = generator.ProvidesOutputFormat; string generatedFileName = generator.GetOutputFileDefaultName(_sourceFileName); PseudoBuildItem pseudoItem; if (items.TryGetValue(outputFormat, out pseudoItem)) { pseudoItem.CurrentGeneratorNames = currentGeneratorNames; pseudoItem.DefaultGeneratedFileName = generatedFileName; } else { pseudoItem = new PseudoBuildItem(null, generatedFileName); pseudoItem.CurrentGeneratorNames = currentGeneratorNames; items[outputFormat] = pseudoItem; } }
/// <summary> /// Update dependency counts for branches of required formats /// </summary> /// <param name="generator">The generator to add or remove dependencies for</param> /// <param name="addOrRemove">true to add a dependency, false to remove</param> private void UpdateDependencyUseCounts(IORMGenerator generator, bool addOrRemove) { IList <string> requiredFormats = generator.RequiresInputFormats; int requiredFormatCount = requiredFormats.Count; IList <string> companionFormats = generator.RequiresCompanionFormats; int requiredCompanionCount = companionFormats.Count; int dependencyCount = requiredFormatCount + requiredCompanionCount; if (dependencyCount != 0) { string outputFormat = generator.ProvidesOutputFormat; SortedList <string, OutputFormatBranch> branchDictionary = _mainBranch._branches; for (int i = 0; i < dependencyCount; ++i) { OutputFormatBranch dependentUponBranch; bool isRequired = i < requiredFormatCount; if (branchDictionary.TryGetValue(isRequired ? requiredFormats[i] : companionFormats[i - requiredFormatCount], out dependentUponBranch)) { int currentUseCount = dependentUponBranch._selectedUseCount; IORMGenerator selectedGenerator; if (addOrRemove) { if (currentUseCount != -1 && null != (selectedGenerator = dependentUponBranch._selectedORMGenerator) && (isRequired || !selectedGenerator.RequiresCompanionFormats.Contains(outputFormat))) { dependentUponBranch._selectedUseCount = currentUseCount + 1; } } else { selectedGenerator = dependentUponBranch._selectedORMGenerator; bool autoRemove = (selectedGenerator != null) ? selectedGenerator.GeneratesSupportFile : false; if (currentUseCount > 0) { bool companionCycle; if (isRequired || !(companionCycle = selectedGenerator.RequiresCompanionFormats.Contains(outputFormat))) { dependentUponBranch._selectedUseCount = currentUseCount - 1; autoRemove = autoRemove && currentUseCount == 1; } else if (companionCycle) { autoRemove = autoRemove && currentUseCount == 1; } } else if (autoRemove) { if (currentUseCount == -1) { autoRemove = !dependentUponBranch.IsDependency; } else { autoRemove = false; } } else if (!isRequired && selectedGenerator != null && selectedGenerator.RequiresCompanionFormats.Contains(outputFormat)) { autoRemove = (currentUseCount == -1) ? !dependentUponBranch.IsDependency : (currentUseCount == 0); } if (autoRemove) { _mainBranch.RemoveGenerator(dependentUponBranch); } } } } } }
private StateRefreshChanges ToggleOnRequiredBranches(OutputFormatBranch formatBranch, int branchGeneratorIndex, bool testToggleOff) { StateRefreshChanges retVal = StateRefreshChanges.None; if (formatBranch.IsModifier) { if (formatBranch.SelectedORMGenerator == null) { // The build item is associated primarily with the primary generator, // not the modifier. We need to make sure that the primary generator // is turned on. IORMGenerator modifierGenerator = formatBranch.ORMGenerators[0]; OutputFormatBranch primaryBranch = _branches[modifierGenerator.ProvidesOutputFormat]; IORMGenerator primaryGenerator = primaryBranch.SelectedORMGenerator; if (primaryGenerator == null) { if (StateRefreshChanges.None != ToggleOnRequiredBranches(primaryBranch, 0, false)) { retVal = StateRefreshChanges.Entire; } primaryGenerator = primaryBranch.SelectedORMGenerator; if (primaryGenerator == null) { return(StateRefreshChanges.None); } } formatBranch.SelectedORMGenerator = modifierGenerator; SetItemMetaData(_parent.BuildItemsByGenerator[primaryGenerator.OfficialName], ITEMMETADATA_ORMGENERATOR, primaryBranch.SelectedGeneratorOfficialNames); retVal |= StateRefreshChanges.Children | StateRefreshChanges.Children; } else if (testToggleOff) { // Note that we can always remove a modifier, do not call CanRemoveGenerator RemoveGenerator(formatBranch); retVal |= StateRefreshChanges.Current | StateRefreshChanges.Children; } } else if (formatBranch.SelectedORMGenerator == null) { #if VISUALSTUDIO_10_0 string projectPath = Parent._project.FullPath; #else string projectPath = Parent._project.FullFileName; #endif EnvDTE.ProjectItem projectItem = Parent._projectItem; string sourceFileName = _parent._sourceFileName; string projectItemPath = (string)projectItem.Properties.Item("LocalPath").Value; string newItemDirectory = (new Uri(projectPath)).MakeRelativeUri(new Uri(projectItemPath)).ToString(); newItemDirectory = Path.GetDirectoryName(newItemDirectory); retVal = StateRefreshChanges.Current | StateRefreshChanges.Children; IORMGenerator useGenerator = formatBranch.ORMGenerators[branchGeneratorIndex]; string outputFileName = useGenerator.GetOutputFileDefaultName(sourceFileName); outputFileName = Path.Combine(newItemDirectory, outputFileName); #if VISUALSTUDIO_10_0 ProjectItemElement newBuildItem; #else BuildItem newBuildItem; #endif newBuildItem = useGenerator.AddGeneratedFileItem(_parent._itemGroup, sourceFileName, outputFileName); //string.Concat(newItemPath, Path.DirectorySeparatorChar, _parent._sourceFileName)); _parent.BuildItemsByGenerator[useGenerator.OfficialName] = newBuildItem; _parent.RemoveRemovedItem(newBuildItem); formatBranch.SelectedORMGenerator = useGenerator; IList <string> requiredFormats = useGenerator.RequiresInputFormats; int requiredFormatCount = requiredFormats.Count; IList <string> companionFormats = useGenerator.RequiresCompanionFormats; int companionFormatCount = companionFormats.Count; int totalCount = requiredFormatCount + companionFormatCount; for (int i = 0; i < totalCount; ++i) { OutputFormatBranch requiredBranch; if (_branches.TryGetValue(i < requiredFormatCount ? requiredFormats[i] : companionFormats[i - requiredFormatCount], out requiredBranch)) { if (StateRefreshChanges.None != ToggleOnRequiredBranches(requiredBranch, 0, false)) { retVal = StateRefreshChanges.Entire; } } } } else if (testToggleOff && CanRemoveGenerator(formatBranch)) { RemoveGenerator(formatBranch); retVal = StateRefreshChanges.Current | StateRefreshChanges.Children; } return(retVal); }
public ORMGeneratorSelectionControl(EnvDTE.ProjectItem projectItem, IServiceProvider serviceProvider) : this() { _projectItem = projectItem; _serviceProvider = serviceProvider; #if VISUALSTUDIO_10_0 ProjectRootElement project = ProjectRootElement.TryOpen(projectItem.ContainingProject.FullName); string projectFullPath = project.FullPath; #else // VISUALSTUDIO_10_0 Project project = Engine.GlobalEngine.GetLoadedProject(projectItem.ContainingProject.FullName); string projectFullPath = project.FullFileName; #endif // VISUALSTUDIO_10_0 _project = project; string projectItemRelativePath = (string)projectItem.Properties.Item("LocalPath").Value; projectItemRelativePath = (new Uri(projectFullPath)).MakeRelativeUri(new Uri(projectItemRelativePath)).ToString(); _projectItemRelativePath = projectItemRelativePath; #if VISUALSTUDIO_10_0 ProjectItemGroupElement originalItemGroup = ORMCustomTool.GetItemGroup(project, projectItemRelativePath); ProjectItemGroupElement itemGroup; if (originalItemGroup == null) { itemGroup = project.AddItemGroup(); itemGroup.Condition = string.Concat(ITEMGROUP_CONDITIONSTART, projectItemRelativePath, ITEMGROUP_CONDITIONEND); } else { itemGroup = project.AddItemGroup(); itemGroup.Condition = originalItemGroup.Condition; foreach (ProjectItemElement item in originalItemGroup.Items) { ProjectItemElement newItem = itemGroup.AddItem(item.ItemType, item.Include); newItem.Condition = item.Condition; foreach (ProjectMetadataElement metadataElement in item.Metadata) { newItem.AddMetadata(metadataElement.Name, metadataElement.Value); } } } #else // VISUALSTUDIO_10_0 BuildItemGroup originalItemGroup = ORMCustomTool.GetItemGroup(project, projectItemRelativePath); BuildItemGroup itemGroup; if (originalItemGroup == null) { itemGroup = project.AddNewItemGroup(); itemGroup.Condition = string.Concat(ITEMGROUP_CONDITIONSTART, projectItemRelativePath, ITEMGROUP_CONDITIONEND); } else { itemGroup = project.AddNewItemGroup(); itemGroup.Condition = originalItemGroup.Condition; foreach (BuildItem item in originalItemGroup) { BuildItem newItem = itemGroup.AddNewItem(item.Name, item.Include, false); newItem.Condition = item.Condition; item.CopyCustomMetadataTo(newItem); } } #endif // VISUALSTUDIO_10_0 _originalItemGroup = originalItemGroup; _itemGroup = itemGroup; string condition = itemGroup.Condition.Trim(); string sourceFileName = this._sourceFileName = projectItem.Name; this.textBox_ORMFileName.Text = sourceFileName; this.button_SaveChanges.Click += new EventHandler(this.SaveChanges); this.button_Cancel.Click += new EventHandler(this.Cancel); ITree tree = (ITree)(this.virtualTreeControl.MultiColumnTree = new MultiColumnTree(2)); this.virtualTreeControl.SetColumnHeaders(new VirtualTreeColumnHeader[] { // TODO: Localize these. new VirtualTreeColumnHeader("Generated File Format", 0.30f, VirtualTreeColumnHeaderStyles.ColumnPositionLocked | VirtualTreeColumnHeaderStyles.DragDisabled), new VirtualTreeColumnHeader("Generated File Name", 1f, VirtualTreeColumnHeaderStyles.ColumnPositionLocked | VirtualTreeColumnHeaderStyles.DragDisabled) }, true); MainBranch mainBranch = this._mainBranch = new MainBranch(this); int totalCount = mainBranch.VisibleItemCount; int[] primaryIndices = new int[totalCount]; for (int i = 0; i < totalCount; ++i) { if (mainBranch.IsPrimaryDisplayItem(i)) { primaryIndices[i] = i - totalCount; } else { primaryIndices[i] = i + 1; } } Array.Sort <int>(primaryIndices); int lastPrimary = -1; for (int i = 0; i < totalCount; ++i) { int modifiedIndex = primaryIndices[i]; if (modifiedIndex < 0) { primaryIndices[i] = modifiedIndex + totalCount; } else { if (lastPrimary == -1) { lastPrimary = i - 1; } primaryIndices[i] = modifiedIndex - 1; } } int modifierCount = totalCount - mainBranch.Branches.Count; tree.Root = (lastPrimary == -1) ? (IBranch)mainBranch : new BranchPartition( mainBranch, primaryIndices, new BranchPartitionSection(0, lastPrimary + 1, null), new BranchPartitionSection(totalCount - modifierCount, modifierCount, "Generated File Modifiers"), new BranchPartitionSection(lastPrimary + 1, totalCount - lastPrimary - modifierCount - 1, "Intermediate and Secondary Files")); // UNDONE: Localize Header this.virtualTreeControl.ShowToolTips = true; this.virtualTreeControl.FullCellSelect = true; #if VISUALSTUDIO_10_0 Dictionary <string, ProjectItemElement> buildItemsByGenerator = this._itemsByGenerator = new Dictionary <string, ProjectItemElement>(itemGroup.Count, StringComparer.OrdinalIgnoreCase); foreach (ProjectItemElement buildItem in itemGroup.Items) #else // VISUALSTUDIO_10_0 Dictionary <string, BuildItem> buildItemsByGenerator = this._itemsByGenerator = new Dictionary <string, BuildItem>(itemGroup.Count, StringComparer.OrdinalIgnoreCase); foreach (BuildItem buildItem in itemGroup) #endif // VISUALSTUDIO_10_0 { // Do this very defensively so that the dialog can still be opened if a project is out // of step with the generators registered on a specific machine. string generatorNameData = buildItem.GetEvaluatedMetadata(ITEMMETADATA_ORMGENERATOR); string[] generatorNames; // The first string is the primary generator, others are the format modifiers int generatorNameCount; IORMGenerator primaryGenerator; MainBranch.OutputFormatBranch primaryFormatBranch; if (!String.IsNullOrEmpty(generatorNameData) && String.Equals(buildItem.GetEvaluatedMetadata(ITEMMETADATA_DEPENDENTUPON), sourceFileName, StringComparison.OrdinalIgnoreCase) && null != (generatorNames = generatorNameData.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)) && 0 != (generatorNameCount = generatorNames.Length) && ORMCustomTool.ORMGenerators.TryGetValue(generatorNames[0], out primaryGenerator) && mainBranch.Branches.TryGetValue(primaryGenerator.ProvidesOutputFormat, out primaryFormatBranch)) { System.Diagnostics.Debug.Assert(primaryFormatBranch.SelectedORMGenerator == null); primaryFormatBranch.SelectedORMGenerator = primaryGenerator; buildItemsByGenerator.Add(generatorNames[0], buildItem); // Format modifiers are attached to the end of the list for (int i = 1; i < generatorNameCount; ++i) { MainBranch.OutputFormatBranch modifierBranch = primaryFormatBranch.NextModifier; string findName = generatorNames[i]; while (modifierBranch != null) { IORMGenerator testGenerator = modifierBranch.ORMGenerators[0]; if (testGenerator.OfficialName == findName) { modifierBranch.SelectedORMGenerator = testGenerator; break; } modifierBranch = modifierBranch.NextModifier; } } } } }
protected override void OnClosed(EventArgs e) { if (_savedChanges) { // Make sure the current document has the necessary // extensions loaded. // UNDONE: We should be able to do this with the document // closed or open as text as well via a registered service // on the ORMDesignerPackage, but this is sufficient for now. Dictionary <string, string> requiredExtensions = null; string[] loadedExtensions = null; foreach (IORMGenerator selectedGenerator in _mainBranch.SelectedGenerators) { foreach (string requiredExtension in selectedGenerator.GetRequiredExtensionsForInputFormat("ORM")) { if (loadedExtensions == null) { loadedExtensions = (new ORMExtensionManager(_projectItem)).GetLoadedExtensions(_serviceProvider); } if (Array.BinarySearch <string>(loadedExtensions, requiredExtension) < 0) { if (requiredExtensions == null) { requiredExtensions = new Dictionary <string, string>(); } else if (requiredExtensions.ContainsKey(requiredExtension)) { continue; } requiredExtensions.Add(requiredExtension, requiredExtension); } } } if (requiredExtensions != null) { _savedChanges = ORMExtensionManager.EnsureExtensions(_projectItem, _serviceProvider, requiredExtensions.Values); } } if (_savedChanges) { #if VISUALSTUDIO_10_0 ProjectItemGroupElement itemGroup = _originalItemGroup; ProjectRootElement project = _project; #else // VISUALSTUDIO_10_0 BuildItemGroup itemGroup = _originalItemGroup; Microsoft.Build.BuildEngine.Project project = _project; #endif // VISUALSTUDIO_10_0 EnvDTE.ProjectItem projectItem = _projectItem; string sourceFileName = _sourceFileName; Dictionary <string, PseudoBuildItem> pseudoItems = _pseudoItemsByOutputFormat; IDictionary <string, IORMGenerator> generators = #if VISUALSTUDIO_15_0 ORMCustomTool.GetORMGenerators(_serviceProvider); #else ORMCustomTool.ORMGenerators; #endif PseudoBuildItem pseudoItem; string generatorNameData; // The first string is the primary generator, others are the format modifiers, space delimited IVsShell shell; Dictionary <string, IORMGenerator> generatorsWithTargetsByOutputFormat = null; IDictionary <string, ORMCustomToolUtility.GeneratorTargetSet> targetSetsByFormatName = null; foreach (PseudoBuildItem testPseudoItem in pseudoItems.Values) { string primaryGeneratorName; IList <string> generatorTargets; IORMGenerator generator; if (!string.IsNullOrEmpty(generatorNameData = testPseudoItem.CurrentGeneratorNames) && null != (primaryGeneratorName = ORMCustomToolUtility.GetPrimaryGeneratorName(generatorNameData)) && generators.TryGetValue(primaryGeneratorName, out generator) && null != (generatorTargets = generator.GeneratorTargetTypes) && 0 != generatorTargets.Count) { (generatorsWithTargetsByOutputFormat ?? (generatorsWithTargetsByOutputFormat = new Dictionary <string, IORMGenerator>(StringComparer.OrdinalIgnoreCase)))[generator.ProvidesOutputFormat] = generator; } } if (generatorsWithTargetsByOutputFormat != null) { IDictionary <string, GeneratorTarget[]> docTargets = null; EnvDTE.Document projectItemDocument = projectItem.Document; string itemPath; if (projectItemDocument != null) { using (Stream targetsStream = ORMCustomToolUtility.GetDocumentExtension <Stream>(projectItemDocument, "ORMGeneratorTargets", itemPath = projectItem.get_FileNames(0), _serviceProvider)) { if (targetsStream != null) { targetsStream.Seek(0, SeekOrigin.Begin); docTargets = new BinaryFormatter().Deserialize(targetsStream) as IDictionary <string, GeneratorTarget[]>; } } } else if (null != (shell = _serviceProvider.GetService(typeof(SVsShell)) as IVsShell)) { Guid pkgId = typeof(ORMDesignerPackage).GUID; IVsPackage package; if (0 != shell.IsPackageLoaded(ref pkgId, out package) || package == null) { shell.LoadPackage(ref pkgId, out package); } // Temporarily load the document so that the generator targets can be resolved. using (Store store = new ModelLoader(ORMDesignerPackage.ExtensionLoader, true).Load(projectItem.get_FileNames(0))) { docTargets = GeneratorTarget.ConsolidateGeneratorTargets(store as IFrameworkServices); } } // We have generators that care about targets, which means that ExpandGeneratorTargets will // product placeholder targets for these generators even if docTargets is currently null. // This allows the dialog to turn on a generator before the data (or even extension) to feed // it is available in the model and provides a smooth transition in and out of this placeholder // state. It is up to the individual generators to proceed without explicit target data or // to produce a message for the user with instructions on how to add the data to the model. Dictionary <string, string> generatorNamesByOutputFormat = new Dictionary <string, string>(); foreach (KeyValuePair <string, PseudoBuildItem> pair in pseudoItems) { generatorNameData = pair.Value.CurrentGeneratorNames; if (!string.IsNullOrEmpty(generatorNameData)) { generatorNamesByOutputFormat[pair.Key] = ORMCustomToolUtility.GetPrimaryGeneratorName(generatorNameData); } } targetSetsByFormatName = ORMCustomToolUtility.ExpandGeneratorTargets(generatorNamesByOutputFormat, docTargets #if VISUALSTUDIO_15_0 , _serviceProvider #endif // VISUALSTUDIO_15_0 ); } Dictionary <string, BitTracker> processedGeneratorTargets = null; if (targetSetsByFormatName != null) { processedGeneratorTargets = new Dictionary <string, BitTracker>(); foreach (KeyValuePair <string, ORMCustomToolUtility.GeneratorTargetSet> kvp in targetSetsByFormatName) { processedGeneratorTargets[kvp.Key] = new BitTracker(kvp.Value.Instances.Length); } } if (null != itemGroup) { #if VISUALSTUDIO_10_0 Dictionary <string, ProjectItemElement> removedItems = null; foreach (ProjectItemElement item in itemGroup.Items) #else // VISUALSTUDIO_10_0 Dictionary <string, BuildItem> removedItems = null; foreach (BuildItem item in itemGroup) #endif // VISUALSTUDIO_10_0 { string primaryGeneratorName; string outputFormat; IORMGenerator generator; if (null != (primaryGeneratorName = ORMCustomToolUtility.GetPrimaryGeneratorName(item.GetEvaluatedMetadata(ITEMMETADATA_ORMGENERATOR))) && string.Equals(item.GetEvaluatedMetadata(ITEMMETADATA_DEPENDENTUPON), sourceFileName, StringComparison.OrdinalIgnoreCase) && generators.TryGetValue(primaryGeneratorName, out generator) && pseudoItems.TryGetValue(outputFormat = generator.ProvidesOutputFormat, out pseudoItem)) { generatorNameData = pseudoItem.CurrentGeneratorNames; ORMCustomToolUtility.GeneratorTargetSet targetSet = null; BitTracker processedForFormat = default(BitTracker); if (targetSetsByFormatName != null) { if (targetSetsByFormatName.TryGetValue(outputFormat, out targetSet)) { processedForFormat = processedGeneratorTargets[outputFormat]; } } List <PseudoBuildInstance> originalInstances; bool removeInstance = false; if (string.IsNullOrEmpty(generatorNameData)) { // The item is deleted, mark for removal removeInstance = true; } else if (null != (originalInstances = pseudoItem.OriginalInstances)) { for (int i = 0, count = originalInstances.Count; i < count && !removeInstance; ++i) { PseudoBuildInstance instance = originalInstances[i]; if (instance.IsRemoved) { continue; } GeneratorTarget[] targets = instance.OriginalGeneratorTargets; if (targetSet != null) { if (targets == null) { // Remove, if a target set is available then it must be used removeInstance = true; } else { int instanceIndex = targetSet.IndexOfInstance(targets, delegate(int ignoreInstance) { return(processedForFormat[ignoreInstance]); }); if (instanceIndex == -1) { removeInstance = true; } else if (!processedForFormat[instanceIndex]) { if (instance.OriginalGeneratorNames != generatorNameData) { // This is a preexisting item, update its meta information ORMCustomToolUtility.SetItemMetaData(item, ITEMMETADATA_ORMGENERATOR, generatorNameData); } processedForFormat[instanceIndex] = true; processedGeneratorTargets[outputFormat] = processedForFormat; break; } } } else if (targets != null) { // Remove, formatter changed to one that does not use a generator target removeInstance = true; } else if (instance.OriginalGeneratorNames != generatorNameData) { // This is a preexisting item, update its meta information ORMCustomToolUtility.SetItemMetaData(item, ITEMMETADATA_ORMGENERATOR, generatorNameData); } if (removeInstance) { instance.IsRemoved = true; } } } if (removeInstance) { if (removedItems == null) { #if VISUALSTUDIO_10_0 removedItems = new Dictionary <string, ProjectItemElement>(); #else // VISUALSTUDIO_10_0 removedItems = new Dictionary <string, BuildItem>(); #endif // VISUALSTUDIO_10_0 } removedItems[ORMCustomToolUtility.GetItemInclude(item)] = item; } } } if (removedItems != null) { EnvDTE.ProjectItems subItems = projectItem.ProjectItems; #if VISUALSTUDIO_10_0 foreach (KeyValuePair <string, ProjectItemElement> removePair in removedItems) { ProjectItemElement removeItem = removePair.Value; ProjectElementContainer removeFrom; if (null != (removeFrom = removeItem.Parent)) { removeFrom.RemoveChild(removeItem); } #else // VISUALSTUDIO_10_0 foreach (KeyValuePair <string, BuildItem> removePair in removedItems) { project.RemoveItem(removePair.Value); #endif // VISUALSTUDIO_10_0 try { EnvDTE.ProjectItem subItem = subItems.Item(removePair.Key); if (subItem != null) { subItem.Delete(); } } catch (ArgumentException) { // Swallow } } } #if !VISUALSTUDIO_10_0 // Empty item groups remove themselves from the project, we'll need // to recreate below if the group is empty after the remove phase. if (itemGroup.Count == 0) { itemGroup = null; } #endif } // Removes and changes are complete, proceed with adds for any new items string newItemDirectory = null; string projectPath = null; EnvDTE.ProjectItems projectItems = null; string tmpFile = null; // Adding a file to our special item group adds it to the build system. However, // it does not add it to the parallel project system, which is what displays in // the solution explorer. Therefore, we also explicitly add the item to the // project system as well. Unfortunately, this extra add automatically creates // a redundant item (usually in a new item group) for our adding item. Track anything // we add through the project system so that we can remove these redundant items from the // build system when we're done. Dictionary <string, string> sideEffectItemNames = null; try { Action <IORMGenerator, string, ORMCustomToolUtility.GeneratorTargetSet, GeneratorTarget[]> addProjectItem = delegate(IORMGenerator generator, string allGenerators, ORMCustomToolUtility.GeneratorTargetSet targetSet, GeneratorTarget[] targetInstance) { if (itemGroup == null) { #if VISUALSTUDIO_10_0 itemGroup = project.AddItemGroup(); #else itemGroup = project.AddNewItemGroup(); #endif itemGroup.Condition = string.Concat(ITEMGROUP_CONDITIONSTART, _projectItemRelativePath, ITEMGROUP_CONDITIONEND); } if (newItemDirectory == null) { // Initialize general information #if VISUALSTUDIO_10_0 projectPath = project.FullPath; #else projectPath = project.FullFileName; #endif newItemDirectory = Path.GetDirectoryName(new Uri(projectPath).MakeRelativeUri(new Uri((string)projectItem.Properties.Item("LocalPath").Value)).ToString()); projectItems = projectItem.ProjectItems; } string defaultFileName = generator.GetOutputFileDefaultName(sourceFileName); string fileName = targetInstance == null ? defaultFileName : ORMCustomToolUtility.GeneratorTargetSet.DecorateFileName(defaultFileName, targetInstance); string fileRelativePath = Path.Combine(newItemDirectory, fileName); string fileAbsolutePath = string.Concat(new FileInfo(projectPath).DirectoryName, Path.DirectorySeparatorChar, fileRelativePath); #if VISUALSTUDIO_10_0 ProjectItemElement newBuildItem; #else BuildItem newBuildItem; #endif newBuildItem = generator.AddGeneratedFileItem(itemGroup, sourceFileName, fileRelativePath); if (allGenerators != null) { ORMCustomToolUtility.SetItemMetaData(newBuildItem, ITEMMETADATA_ORMGENERATOR, allGenerators); } if (targetInstance != null) { ORMCustomToolUtility.SetGeneratorTargetMetadata(newBuildItem, targetInstance); } (sideEffectItemNames ?? (sideEffectItemNames = new Dictionary <string, string>()))[fileRelativePath] = null; if (File.Exists(fileAbsolutePath)) { try { projectItems.AddFromFile(fileAbsolutePath); } catch (ArgumentException) { // Swallow } } else { if (tmpFile == null) { tmpFile = Path.GetTempFileName(); } EnvDTE.ProjectItem newProjectItem = projectItems.AddFromTemplate(tmpFile, fileName); string customTool; if (!string.IsNullOrEmpty(customTool = newBuildItem.GetMetadata(ITEMMETADATA_GENERATOR))) { newProjectItem.Properties.Item("CustomTool").Value = customTool; } } }; foreach (KeyValuePair <string, PseudoBuildItem> keyedPseudoItem in pseudoItems) { pseudoItem = keyedPseudoItem.Value; string allGenerators = pseudoItem.CurrentGeneratorNames; string primaryGenerator = ORMCustomToolUtility.GetPrimaryGeneratorName(allGenerators); if (allGenerators == primaryGenerator) { allGenerators = null; } IORMGenerator generator = generators[primaryGenerator]; string outputFormat = generator.ProvidesOutputFormat; ORMCustomToolUtility.GeneratorTargetSet targetSet = null; if (targetSetsByFormatName != null) { targetSetsByFormatName.TryGetValue(outputFormat, out targetSet); } if (targetSet != null) { // OriginalInstances were already updated in the remove loop and processed // instances were flagged. Find additional instances from the target set (created // just now from the current model), not from the pseudoItem (created from the project // files that possibly reflect a previous version of the model). GeneratorTarget[][] instances = targetSet.Instances; BitTracker processed = processedGeneratorTargets[outputFormat]; for (int i = 0, count = instances.Length; i < count; ++i) { if (!processed[i]) { addProjectItem(generator, allGenerators, targetSet, instances[i]); } } } else if (pseudoItem.OriginalInstances == null) { addProjectItem(generator, allGenerators, null, null); } else { // Make sure there was an original instance that did not have a target set. List <PseudoBuildInstance> originals = pseudoItem.OriginalInstances; int i = 0, count = originals.Count; for (; i < count; ++i) { if (originals[i].OriginalGeneratorTargets == null) { break; } } if (i == count) { addProjectItem(generator, allGenerators, null, null); } } } } finally { if (tmpFile != null) { File.Delete(tmpFile); } } if (sideEffectItemNames != null) { ORMCustomToolUtility.RemoveSideEffectItems(sideEffectItemNames, project, itemGroup); } #if VISUALSTUDIO_10_0 // Old group remove themselves when empty, but this is // not true in the new build system. Clean up as needed. if (itemGroup != null && itemGroup.Items.Count == 0) { project.RemoveChild(itemGroup); } #endif VSLangProj.VSProjectItem vsProjectItem = projectItem.Object as VSLangProj.VSProjectItem; if (vsProjectItem != null) { vsProjectItem.RunCustomTool(); } } base.OnClosed(e); }
public ORMGeneratorSelectionControl(EnvDTE.ProjectItem projectItem, IServiceProvider serviceProvider) : this() { _projectItem = projectItem; _serviceProvider = serviceProvider; #if VISUALSTUDIO_10_0 ProjectRootElement project = ProjectRootElement.TryOpen(projectItem.ContainingProject.FullName); string projectFullPath = project.FullPath; #else // VISUALSTUDIO_10_0 Microsoft.Build.BuildEngine.Project project = Engine.GlobalEngine.GetLoadedProject(projectItem.ContainingProject.FullName); string projectFullPath = project.FullFileName; #endif // VISUALSTUDIO_10_0 _project = project; string projectItemRelativePath = (string)projectItem.Properties.Item("LocalPath").Value; projectItemRelativePath = (new Uri(projectFullPath)).MakeRelativeUri(new Uri(projectItemRelativePath)).ToString(); _projectItemRelativePath = projectItemRelativePath; #if VISUALSTUDIO_10_0 ProjectItemGroupElement originalItemGroup = ORMCustomTool.GetItemGroup(project, projectItemRelativePath); #else // VISUALSTUDIO_10_0 BuildItemGroup originalItemGroup = ORMCustomTool.GetItemGroup(project, projectItemRelativePath); #endif // VISUALSTUDIO_10_0 _originalItemGroup = originalItemGroup; string sourceFileName = projectItem.Name; _sourceFileName = sourceFileName; this.textBox_ORMFileName.Text = sourceFileName; this.button_SaveChanges.Click += new EventHandler(this.SaveChanges); this.button_Cancel.Click += new EventHandler(this.Cancel); ITree tree = (ITree)(this.virtualTreeControl.MultiColumnTree = new MultiColumnTree(2)); this.virtualTreeControl.SetColumnHeaders(new VirtualTreeColumnHeader[] { // TODO: Localize these. new VirtualTreeColumnHeader("Generated File Format", 0.30f, VirtualTreeColumnHeaderStyles.ColumnPositionLocked | VirtualTreeColumnHeaderStyles.DragDisabled), new VirtualTreeColumnHeader("Generated File Name", 1f, VirtualTreeColumnHeaderStyles.ColumnPositionLocked | VirtualTreeColumnHeaderStyles.DragDisabled) }, true); MainBranch mainBranch = this._mainBranch = new MainBranch(this #if VISUALSTUDIO_15_0 , serviceProvider #endif ); int totalCount = mainBranch.VisibleItemCount; int[] primaryIndices = new int[totalCount]; for (int i = 0; i < totalCount; ++i) { if (mainBranch.IsPrimaryDisplayItem(i)) { primaryIndices[i] = i - totalCount; } else { primaryIndices[i] = i + 1; } } Array.Sort <int>(primaryIndices); int lastPrimary = -1; for (int i = 0; i < totalCount; ++i) { int modifiedIndex = primaryIndices[i]; if (modifiedIndex < 0) { primaryIndices[i] = modifiedIndex + totalCount; } else { if (lastPrimary == -1) { lastPrimary = i - 1; } primaryIndices[i] = modifiedIndex - 1; } } int modifierCount = totalCount - mainBranch.Branches.Count; tree.Root = (lastPrimary == -1) ? (IBranch)mainBranch : new BranchPartition( mainBranch, primaryIndices, new BranchPartitionSection(0, lastPrimary + 1), new BranchPartitionSection(totalCount - modifierCount, modifierCount, "Generated File Modifiers", false), new BranchPartitionSection(lastPrimary + 1, totalCount - lastPrimary - modifierCount - 1, "Intermediate and Secondary Files", true)); // UNDONE: Localize Header this.virtualTreeControl.ShowToolTips = true; this.virtualTreeControl.FullCellSelect = true; Dictionary <string, PseudoBuildItem> pseudoItemsByOutputFormat = new Dictionary <string, PseudoBuildItem>(StringComparer.OrdinalIgnoreCase); _pseudoItemsByOutputFormat = pseudoItemsByOutputFormat; IDictionary <string, IORMGenerator> generators = #if VISUALSTUDIO_15_0 ORMCustomTool.GetORMGenerators(serviceProvider); #else ORMCustomTool.ORMGenerators; #endif if (originalItemGroup != null) { #if VISUALSTUDIO_10_0 foreach (ProjectItemElement buildItem in originalItemGroup.Items) #else // VISUALSTUDIO_10_0 foreach (BuildItem buildItem in originalItemGroup) #endif // VISUALSTUDIO_10_0 { // Do this very defensively so that the dialog can still be opened if a project is out // of step with the generators registered on a specific machine. string generatorNameData; string[] generatorNames; // The first string is the primary generator, others are the format modifiers int generatorNameCount; IORMGenerator primaryGenerator; MainBranch.OutputFormatBranch primaryFormatBranch; if (!string.IsNullOrEmpty(generatorNameData = buildItem.GetEvaluatedMetadata(ITEMMETADATA_ORMGENERATOR)) && !string.IsNullOrEmpty(generatorNameData = generatorNameData.Trim()) && string.Equals(buildItem.GetEvaluatedMetadata(ITEMMETADATA_DEPENDENTUPON), sourceFileName, StringComparison.OrdinalIgnoreCase) && null != (generatorNames = generatorNameData.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)) && 0 != (generatorNameCount = generatorNames.Length) && // This assumes that each generator target of the same type has all of the same options. // This is currently the result of this dialog, and we're not considering hand edits // to the project file at this point. generators.TryGetValue(generatorNames[0], out primaryGenerator) && mainBranch.Branches.TryGetValue(primaryGenerator.ProvidesOutputFormat, out primaryFormatBranch)) { PseudoBuildItem pseudoItem; string outputFormat = primaryGenerator.ProvidesOutputFormat; if (!pseudoItemsByOutputFormat.TryGetValue(outputFormat, out pseudoItem)) { // Note that we can't use the build item file name here as it might be decorated with // target names. Go back to the generator to get an undecorated default name. pseudoItem = new PseudoBuildItem(generatorNameData, primaryGenerator.GetOutputFileDefaultName(sourceFileName)); pseudoItemsByOutputFormat.Add(outputFormat, pseudoItem); if (primaryFormatBranch.SelectedORMGenerator == null) { primaryFormatBranch.SelectedORMGenerator = primaryGenerator; } // Format modifiers are attached to the end of the list for (int i = 1; i < generatorNameCount; ++i) { MainBranch.OutputFormatBranch modifierBranch = primaryFormatBranch.NextModifier; string findName = generatorNames[i]; while (modifierBranch != null) { IORMGenerator testGenerator = modifierBranch.ORMGenerators[0]; if (testGenerator.OfficialName == findName) { modifierBranch.SelectedORMGenerator = testGenerator; break; } modifierBranch = modifierBranch.NextModifier; } } } pseudoItem.AddOriginalInstance(generatorNameData, ORMCustomToolUtility.GeneratorTargetsFromBuildItem(buildItem)); } } } }
/// <summary> /// Update dependency counts for branches of required formats /// </summary> /// <param name="generator">The generator to add or remove dependencies for</param> /// <param name="addOrRemove">true to add a dependency, false to remove</param> private void UpdateDependencyUseCounts(IORMGenerator generator, bool addOrRemove) { IList<string> requiredFormats = generator.RequiresInputFormats; int requiredFormatCount = requiredFormats.Count; IList<string> companionFormats = generator.RequiresCompanionFormats; int requiredCompanionCount = companionFormats.Count; int dependencyCount = requiredFormatCount + requiredCompanionCount; if (dependencyCount != 0) { string outputFormat = generator.ProvidesOutputFormat; SortedList<string, OutputFormatBranch> branchDictionary = _mainBranch._branches; for (int i = 0; i < dependencyCount; ++i) { OutputFormatBranch dependentUponBranch; bool isRequired = i < requiredFormatCount; if (branchDictionary.TryGetValue(isRequired ? requiredFormats[i] : companionFormats[i - requiredFormatCount], out dependentUponBranch)) { int currentUseCount = dependentUponBranch._selectedUseCount; IORMGenerator selectedGenerator; if (addOrRemove) { if (currentUseCount != -1 && null != (selectedGenerator = dependentUponBranch._selectedORMGenerator) && (isRequired || !selectedGenerator.RequiresCompanionFormats.Contains(outputFormat))) { dependentUponBranch._selectedUseCount = currentUseCount + 1; } } else { selectedGenerator = dependentUponBranch._selectedORMGenerator; bool autoRemove = (selectedGenerator != null) ? selectedGenerator.GeneratesSupportFile : false; if (currentUseCount > 0) { bool companionCycle; if (isRequired || !(companionCycle = selectedGenerator.RequiresCompanionFormats.Contains(outputFormat))) { dependentUponBranch._selectedUseCount = currentUseCount - 1; autoRemove = autoRemove && currentUseCount == 1; } else if (companionCycle) { autoRemove = autoRemove && currentUseCount == 1; } } else if (autoRemove) { if (currentUseCount == -1) { autoRemove = !dependentUponBranch.IsDependency; } else { autoRemove = false; } } else if (!isRequired && selectedGenerator != null && selectedGenerator.RequiresCompanionFormats.Contains(outputFormat)) { autoRemove = (currentUseCount == -1) ? !dependentUponBranch.IsDependency : (currentUseCount == 0); } if (autoRemove) { _mainBranch.RemoveGenerator(dependentUponBranch); } } } } } }
private StateRefreshChanges ToggleOnRequiredBranches(OutputFormatBranch formatBranch, int branchGeneratorIndex, bool testToggleOff) { StateRefreshChanges retVal = StateRefreshChanges.None; if (formatBranch.IsModifier) { if (formatBranch.SelectedORMGenerator == null) { // The build item is associated primarily with the output format for // the primary generator, not the modifier. We need to make sure that // the primary generator is turned on. IORMGenerator modifierGenerator = formatBranch.ORMGenerators[0]; OutputFormatBranch primaryBranch = _branches[modifierGenerator.ProvidesOutputFormat]; IORMGenerator primaryGenerator = primaryBranch.SelectedORMGenerator; if (primaryGenerator == null) { if (StateRefreshChanges.None != ToggleOnRequiredBranches(primaryBranch, 0, false)) { retVal = StateRefreshChanges.Entire; } primaryGenerator = primaryBranch.SelectedORMGenerator; if (primaryGenerator == null) { return(StateRefreshChanges.None); } } formatBranch.SelectedORMGenerator = modifierGenerator; PseudoBuildItem pseudoItem = _parent.PseudoItemsByOutputFormat[primaryGenerator.ProvidesOutputFormat]; pseudoItem.CurrentGeneratorNames = primaryBranch.SelectedGeneratorOfficialNames; retVal |= StateRefreshChanges.Children | StateRefreshChanges.Children; } else if (testToggleOff) { // Note that we can always remove a modifier, do not call CanRemoveGenerator RemoveGenerator(formatBranch); retVal |= StateRefreshChanges.Current | StateRefreshChanges.Children; } } else if (formatBranch.SelectedORMGenerator == null) { IORMGenerator generator = formatBranch.ORMGenerators[branchGeneratorIndex]; retVal = StateRefreshChanges.Current | StateRefreshChanges.Children; formatBranch.SelectedORMGenerator = generator; _parent.AddPseudoItem(generator, formatBranch.SelectedGeneratorOfficialNames); // Notify related generator branches IList <string> requiredFormats = generator.RequiresInputFormats; int requiredFormatCount = requiredFormats.Count; IList <string> companionFormats = generator.RequiresCompanionFormats; int companionFormatCount = companionFormats.Count; int totalCount = requiredFormatCount + companionFormatCount; for (int i = 0; i < totalCount; ++i) { OutputFormatBranch requiredBranch; if (_branches.TryGetValue(i < requiredFormatCount ? requiredFormats[i] : companionFormats[i - requiredFormatCount], out requiredBranch)) { if (StateRefreshChanges.None != ToggleOnRequiredBranches(requiredBranch, 0, false)) { retVal = StateRefreshChanges.Entire; } } } } else if (testToggleOff && CanRemoveGenerator(formatBranch)) { RemoveGenerator(formatBranch); retVal = StateRefreshChanges.Current | StateRefreshChanges.Children; } return(retVal); }