private void LoadCategories() { ModelErrorDisplayFilter filter = myModel.ModelErrorDisplayFilter; DomainDataDirectory dataDirectory = myModel.Store.DomainDataDirectory; DomainClassInfo baseType = dataDirectory.GetDomainClass(typeof(ModelErrorCategory)); ReadOnlyCollection <DomainClassInfo> categoryDescendants = baseType.AllDescendants; int numCategories = categoryDescendants.Count; Category[] categories = new Category[numCategories + 1]; categories[numCategories] = new Category(null, false); for (int i = 0; i < numCategories; ++i) { DomainClassInfo info = categoryDescendants[i]; Type categoryType = info.ImplementationClass; categories[i] = new Category(info, filter != null && filter.IsCategoryExcluded(categoryType)); } // Presort the categories list Category.Sort(categories); baseType = dataDirectory.GetDomainClass(typeof(ModelError)); ReadOnlyCollection <DomainClassInfo> errorDescendants = baseType.AllDescendants; int errorDescendantCount = errorDescendants.Count; int includedErrorCount = 0; for (int i = 0; i < errorDescendantCount; ++i) { if (!errorDescendants[i].ImplementationClass.IsAbstract) { ++includedErrorCount; } } Error[] errors = new Error[includedErrorCount]; int includedErrorIndex = -1; for (int i = 0; i < errorDescendantCount; ++i) { DomainClassInfo info = errorDescendants[i]; Type error = info.ImplementationClass; if (!error.IsAbstract) { ++includedErrorIndex; errors[includedErrorIndex] = new Error( info, Category.IndexOf(categories, ResolveErrorCategory(error)), filter != null && filter.IsErrorExcluded(error)); } } // Sort the errors with a primary sort on the presorted category index Array.Sort(errors, delegate(Error error1, Error error2) { int retVal = 0; int categoryIndex1 = error1.CategoryIndex; int categoryIndex2 = error2.CategoryIndex; if (categoryIndex1 < categoryIndex2) { retVal = -1; } else if (categoryIndex1 > categoryIndex2) { retVal = 1; } else { retVal = string.Compare(error1.DisplayName, error2.DisplayName, StringComparison.CurrentCultureIgnoreCase); } return(retVal); }); // Walk the errors and bind the categories to the errors int currentCategoryStartErrorIndex = -1; int lastCategoryIndex = -1; for (int i = 0; i < includedErrorCount; ++i) { int currentIndex = errors[i].CategoryIndex; if (currentIndex != lastCategoryIndex) { if (lastCategoryIndex == -1) { lastCategoryIndex = currentIndex; currentCategoryStartErrorIndex = i; } else { categories[lastCategoryIndex].BindErrorRange(currentCategoryStartErrorIndex, i - 1); currentCategoryStartErrorIndex = i; lastCategoryIndex = currentIndex; } } } if (lastCategoryIndex != -1) { categories[lastCategoryIndex].BindErrorRange(currentCategoryStartErrorIndex, includedErrorCount - 1); } myCategories = categories; myErrors = errors; }
private void SaveChanges() { ORMModel model = myModel; ModelErrorDisplayFilter filter = model.ModelErrorDisplayFilter; Store store = model.Store; using (Transaction t = store.TransactionManager.BeginTransaction(ResourceStrings.ModelErrorDisplayFilterChangeTransactionName)) { bool deleteFilter = true, anyChanges = false; Error[] errors = myErrors; Category[] categories = myCategories; foreach (Category category in categories) { bool allExcluded = true, allIncluded = true; if (category.FirstError == -1) { allExcluded = false; allIncluded = true; } else { for (int i = category.FirstError; i <= category.LastError; ++i) { Error error = errors[i]; if (error.IsExcluded != error.WasExcluded) { anyChanges = true; } if (error.IsExcluded) { deleteFilter = false; allIncluded = false; } else { allExcluded = false; } if (anyChanges && !deleteFilter && !allExcluded && !allIncluded) { break; } } } if (allIncluded) { category.IsExcluded = false; } else if (allExcluded) { category.IsExcluded = true; } } if (deleteFilter) { //if all errors are included, we can delete the filter anyChanges = true; if (filter != null) { filter.Delete(); } } else if (anyChanges) { if (filter == null) { filter = new ModelErrorDisplayFilter(store); filter.Model = model; } foreach (Category category in categories) { if (category.Type != null) { filter.ToggleCategory(category.Type, category.IsExcluded); } } foreach (Error error in errors) { filter.ToggleError(error.Type, error.IsExcluded); } filter.CommitChanges(); } if (anyChanges && t.HasPendingChanges) { t.Commit(); } } }
/// <summary> /// Attempt to activate an activatable error. /// </summary> /// <param name="e">DiagramPointEventArgs. Indicates the element to activate.</param> /// <returns>true if an error was activated</returns> public static bool AttemptErrorActivation(DiagramPointEventArgs e) { bool retVal = false; if (!e.Handled) { DiagramClientView clientView = e.DiagramClientView; MouseAction action = clientView.ActiveMouseAction; if ((action == null || !(action is ConnectAction || action is ToolboxAction)) && clientView.Selection.Count == 1) { DiagramItem diagramItem = e.DiagramHitTestInfo.HitDiagramItem; IModelErrorActivation activator = diagramItem.Shape as IModelErrorActivation; if (activator != null) { IModelErrorOwner errorOwner = null; foreach (ModelElement mel in diagramItem.RepresentedElements) { errorOwner = EditorUtility.ResolveContextInstance(mel, false) as IModelErrorOwner; break; } if (errorOwner != null) { ModelErrorDisplayFilter displayFilter = null; ORMDiagram diagram; ORMModel model; if (null != (diagram = diagramItem.Diagram as ORMDiagram) && null != (model = diagram.ModelElement as ORMModel)) { displayFilter = model.ModelErrorDisplayFilter; } MouseAction startingMouseAction = clientView.ActiveMouseAction; foreach (ModelError error in errorOwner.GetErrorCollection(ModelErrorUses.DisplayPrimary)) { if (ModelError.IsDisplayed(error, displayFilter)) { if (activator.ActivateModelError(error)) { // UNDONE: MSBUG Report Microsoft bug DiagramClientView.OnDoubleClick is checking // for an active mouse action after the double click and clearing it if it is set. // This may be appropriate if the mouse action was set before the subfield double // click and did not change during the callback, but is definitely not appropriate // if the double click activated the mouse action. // Note that this bug makes it impossible to override OnDoubleClick and OnSubFieldDoubleClick // because e.Handled cannot be reliably checked, so there is no way to call base.OnDoubleClick // of base.OnSubFieldDoubleClick from a more derived class without attempting error activation // twice. If this is fixed, then any OnDoubleClick/OnSubFieldDoubleClick implementation // that simply defers to this method then calls the base can be eliminated in favor // of the same methods here. if (clientView.ActiveMouseAction == startingMouseAction) { e.Handled = true; } retVal = true; break; } else { if (!retVal) { IORMToolTaskItem task; IORMToolServices services; IORMToolTaskProvider provider; if (null != (task = error.TaskData as IORMToolTaskItem) && null != (services = error.Store as IORMToolServices) && null != (provider = services.TaskProvider)) { if (provider.NavigateTo(task)) { retVal = true; break; } } } } } } } } } } return(retVal); }