/// <summary> /// This method toggles Explorer Tree options in a way suitable to show the given item. /// For example, of a filter is currently specified, but the given item does not fulfill /// the filter criteria, Filtering will be toggled off in the UI. /// </summary> /// <param name="item"></param> public TreeNodeAdv EnsureNodeVisible(ITabularNamedObject item) { var node = UI.TreeView.FindNodeByTag(item); if (node != null) { return(node); } LogicalTreeOptions optionsToApply = 0; if ((item as IHideableObject)?.IsHidden ?? false && !Tree.Options.HasFlag(LogicalTreeOptions.ShowHidden)) { // If the object is hidden, make sure the tree is set up to show hidden objects: optionsToApply |= LogicalTreeOptions.ShowHidden; UI.FormMain.actToggleHidden.Checked = true; } switch (item.ObjectType) { case ObjectType.Table: // Tables will always be visible case ObjectType.Column: case ObjectType.Measure: case ObjectType.Hierarchy: case ObjectType.Level: case ObjectType.KPI: default: break; } return(null); }
public void Goto(ITabularNamedObject obj) { var node = UI.TreeView.FindNodeByTag(obj); if (node == null) { TreeModel.BeginUpdate(); var options = TreeModel.Options; // Adjust the LogicalTreeOptions based on the object itself. For example, if the object is hidden, // make sure the tree displays hidden objects, etc.: if ((obj is IHideableObject) && (obj as IHideableObject).IsHidden) { options = options | LogicalTreeOptions.ShowHidden; } if ((obj is Column)) { options = options | LogicalTreeOptions.Columns; } else if ((obj is Measure)) { options = options | LogicalTreeOptions.Measures; } else if ((obj is Hierarchy)) { options = options | LogicalTreeOptions.Hierarchies; } else if ((obj is Table) || (obj is Model)) /* Do nothing */ } {
public static int GetIconIndex(ITabularNamedObject obj) { if (obj is TabularObject) { if (obj is CalculatedColumn) { return(TabularIcons.ICON_CALCCOLUMN); } if (obj is CalculatedTable) { return(TabularIcons.ICON_CALCTABLE); } if (obj is Level) { var icon = TabularIcons.ICON_LEVEL1 + (obj as Level).Ordinal; return(icon > TabularIcons.ICON_LEVEL12 ? TabularIcons.ICON_LEVEL12 : icon); } int iconIndex; if (IconMap.TryGetValue((obj as TabularObject).ObjectType, out iconIndex)) { return(iconIndex); } } if (obj is PartitionViewTable) { return(GetIconIndex((obj as PartitionViewTable).Table)); } return(-1); }
public void Goto(ITabularNamedObject obj) { var node = UI.TreeView.FindNodeByTag(obj); if (node == null) { TreeModel.BeginUpdate(); TreeModel.Options = TreeModel.Options | LogicalTreeOptions.ShowHidden | LogicalTreeOptions.AllObjectTypes | LogicalTreeOptions.Columns | LogicalTreeOptions.Measures | LogicalTreeOptions.Hierarchies; InternalApplyFilter(""); UI.FormMain.UpdateTreeUIButtons(); TreeModel.EndUpdate(); node = UI.TreeView.FindNodeByTag(obj); } if (node != null) { UI.TreeView.EnsureVisible(node); UI.TreeView.SelectedNode = node; UI.FormMain.Activate(); UI.TreeView.Focus(); } }
public void ExpandItem(ITabularNamedObject item) { var node = UI.TreeView.FindNodeByTag(item); if (node != null) { node.Expand(); } }
public static string GetLinqPath(this ITabularNamedObject obj) { switch (obj.ObjectType) { case ObjectType.KPI: return((obj as KPI).Measure.GetLinqPath() + ".KPI"); case ObjectType.Model: return("Model"); case ObjectType.Column: return(string.Format("({0}.Columns[\"{1}\"] as {2})", (obj as ITabularTableObject).Table.GetLinqPath(), obj.Name, obj.GetType().Name)); case ObjectType.Measure: return(string.Format("{0}.Measures[\"{1}\"]", (obj as ITabularTableObject).Table.GetLinqPath(), obj.Name)); case ObjectType.Hierarchy: return(string.Format("{0}.Hierarchies[\"{1}\"]", (obj as ITabularTableObject).Table.GetLinqPath(), obj.Name)); case ObjectType.Partition: return(string.Format("({0}.Partitions[\"{1}\"] as {2})", (obj as ITabularTableObject).Table.GetLinqPath(), obj.Name, obj.GetType().Name)); case ObjectType.Table: return(string.Format("{0}.Tables[\"{1}\"]", obj.Model.GetLinqPath(), obj.Name)); case ObjectType.Level: return(string.Format("{0}.Levels[\"{1}\"]", (obj as Level).Hierarchy.GetLinqPath(), obj.Name)); case ObjectType.Perspective: return(string.Format("{0}.Perspectives[\"{1}\"]", obj.Model.GetLinqPath(), obj.Name)); case ObjectType.Culture: return(string.Format("{0}.Cultures[\"{1}\"]", obj.Model.GetLinqPath(), obj.Name)); case ObjectType.DataSource: return(string.Format("({0}.DataSources[\"{1}\"] as {2})", obj.Model.GetLinqPath(), obj.Name, obj.GetType().Name)); case ObjectType.Relationship: return(string.Format("({0}.Relationships[{1}] as {2})", obj.Model.GetLinqPath(), obj.MetadataIndex, obj.GetType().Name)); case ObjectType.Role: return(string.Format("{0}.Roles[\"{1}\"]", obj.Model.GetLinqPath(), obj.Name)); case ObjectType.Expression: return(string.Format("{0}.Expressions[\"{1}\"]", obj.Model.GetLinqPath(), obj.Name)); case ObjectType.TablePermission: return(string.Format("{0}.TablePermissions[\"{1}\"]", (obj as TablePermission).Role.GetLinqPath(), (obj as TablePermission).Table.Name)); case ObjectType.CalculationGroupTable: return(string.Format("({0}.Tables[\"{1}\"] as CalculationGroupTable)", obj.Model.GetLinqPath(), obj.Name)); default: throw new NotSupportedException(); } }
public void EditName(ITabularNamedObject item) { var node = EnsureNodeVisible(item); if (node != null) { UI.TreeView.SelectedNode = node; TreeView_NameCol.BeginEdit(); } }
public override void OnStructureChanged(ITabularNamedObject obj = null) { if (obj == null) { OnStructureChanged(new TreePath(Model)); } else { OnStructureChanged(GetPath(obj)); } }
internal void DoObjectDeleted(TabularObject obj, ITabularNamedObject parentBeforeDeletion) { if (obj is IFolderObject) { Tree.RebuildFolderCacheForTable(parentBeforeDeletion as Table); } var e = new ObjectDeletedEventArgs(obj); ObjectDeleted?.Invoke(this, e); }
/// <summary> /// Call this method to signal to the TreeView that a nodes name was changed. When /// using the OrderByName option, this typically requires a call to OnStructureChanged /// on the parent node. /// </summary> /// <param name="nodeItem"></param> public void OnNodeNameChanged(ITabularNamedObject nodeItem) { if (Options.HasFlag(LogicalTreeOptions.OrderByName)) { OnStructureChanged(nodeItem.GetContainer()); } else { OnNodesChanged(nodeItem); } }
private void RecursiveAdd(ITabularNamedObject obj, TreeNodeCollection nodes, string toolTip = null) { var img = UI.Tree.TabularIcon.GetIconIndex(obj); var n = new TreeNode((obj as IDaxObject)?.DaxObjectFullName ?? obj.Name, img, img) { Tag = obj }; n.ToolTipText = toolTip ?? (obj as IExpressionObject)?.Expression; nodes.Add(n); if (obj is IDaxDependantObject) { foreach (var d in ((IDaxDependantObject)obj).DependsOn.OrderBy(k => k.Key.ObjectType)) { currentDepth++; if (d.Key == _rootObject) { var i = UI.Tree.TabularIcon.GetIconIndex(d.Key); var node = new TreeNode(d.Key.Name + " (circular dependency)", i, i); n.Nodes.Add(node); } else if (currentDepth < MAX_LEVELS) { var daxProps = d.Value.Select(v => v.property).Distinct() .Select(p => p.ToString() + ": " + ((IDaxDependantObject)obj).GetDAX(p).Replace("\r\n", " ").Replace("\n", " ").Left(100)).ToArray(); RecursiveAdd(d.Key, n.Nodes, string.Join("\n", daxProps)); } else { n.Nodes.Add("(Infinite recursion)"); } currentDepth--; } } else { if (obj is ITabularTableObject) { RecursiveAdd(((ITabularTableObject)obj).Table, n.Nodes); } } // Include the column used as a Sort-by column for the current column: if (obj is Column c && c.SortByColumn != null) { RecursiveAdd(c.SortByColumn, n.Nodes); } }
public static void CustomAction(this ITabularNamedObject selection, string actionName) { var act = GetCustomActions().FirstOrDefault(a => a.BaseName == actionName); if (act != null) { act.ExecuteWithSelection(null, Enumerable.Repeat(selection, 1)); } else { throw new InvalidOperationException(string.Format("There is no Custom Action with the name '{0}'.", actionName)); } }
public static bool SetName(this ITabularNamedObject obj, string newName, Culture culture) { if (obj is ITranslatableObject && culture != null) { var tObj = obj as ITranslatableObject; tObj.TranslatedNames[culture] = newName; return true; } if (string.IsNullOrEmpty(newName)) return false; obj.Name = newName; return true; }
private void CreateRelationshipTree(ITabularNamedObject startFrom, TreeNode node) { var q = new Queue <TreeNode>(); q.Enqueue(node); if (startFrom is Table) { while (q.Count > 0) { node = q.Dequeue(); var obj = ObjFromNode(node); var relevantRelationships = obj.Model.Relationships.Where(r => (r.FromTable == obj || r.ToTable == obj) && (chkShowInactive.Checked || r.IsActive)).OrderBy(r => !r.IsActive).ToList(); foreach (var r in relevantRelationships) { var dstTable = r.FromTable == obj ? r.ToTable : r.FromTable; if (VisitedRelationships.Contains(r)) { continue; } VisitedRelationships.Add(r); var prefix = string.Format("({0} {2} {1}) ", (r.FromTable == obj ? r.FromCardinality : r.ToCardinality) == RelationshipEndCardinality.Many ? 'n' : '1', (r.FromTable == obj ? r.ToCardinality : r.FromCardinality) == RelationshipEndCardinality.Many ? 'n' : '1', r.CrossFilteringBehavior == CrossFilteringBehavior.BothDirections ? "\u2194" : r.FromTable == obj ? "\u2190" : "\u2192"); var img = UI.Tree.TabularIcon.GetIconIndex(dstTable); var n = new TreeNode(prefix + dstTable.DaxObjectFullName, img, img) { Tag = new ObjectRel { Object = dstTable, Relationship = r } }; if (!r.IsActive) { n.ForeColor = Color.Silver; } n.ToolTipText = r.Name; node.Nodes.Add(n); q.Enqueue(n); } } } }
public static string GetFullPath(ITabularNamedObject obj) { if (obj is TabularNamedObject) { return((obj as TabularNamedObject).Name); } else if (obj is Folder) { return((obj as Folder).FullPath); } else { throw new ArgumentException("Argument must be of type Table or Folder.", "obj"); } }
private bool SatisfiesFilterCriteria(ITabularNamedObject obj) { if (_useWildcardSearch) { return(obj.Name.ToUpperInvariant().EqualsWildcard(_filterUpper)); } else if (_useLinqSearch) { return(SatisfiesLinq(obj)); } else { return(obj.Name.ToUpperInvariant().Contains(_filterUpper)); } }
public static string GetName(this ITabularNamedObject obj, Culture culture) { // Translatable objects must take culture into account for their name: if (obj is ITranslatableObject && culture != null) { var name = (obj as ITranslatableObject).TranslatedNames[culture]; // Return base name if there was no translated name: if (string.IsNullOrEmpty(name)) name = obj.Name; return name; } // Other objects simply use their name: return obj.Name; }
public static int GetDisplayOrder(this ITabularNamedObject item) { switch (item.ObjectType) { case ObjectType.PartitionCollection: return(0); case ObjectType.Folder: return(1); case ObjectType.Measure: return(2); case ObjectType.Column: return(3); case ObjectType.Hierarchy: return(4); default: return(5); } }
public override void OnStructureChanged(ITabularNamedObject obj = null) { if (UpdateLocks > 0) { structureChangedItems.AddIfNotExists(obj); return; } else { if (obj == null) { OnStructureChanged(new TreePath()); } else { OnStructureChanged(GetPath(obj)); } } }
public static FluentPropertyGridTest PropertyGridTest(this ITabularNamedObject obj) { var propertyGrid = new PropertyGrid(); propertyGrid.SelectedObject = obj; var item = propertyGrid.SelectedGridItem; while (item.Parent != null) { item = item.Parent; } var result = new FluentPropertyGridTest(obj); var itemStack = new Stack <GridItem>(); itemStack.Push(item); while (itemStack.Count > 0) { item = itemStack.Pop(); if (item.Expandable) { item.Expanded = true; } foreach (GridItem subItem in item.GridItems) { itemStack.Push(subItem); } if (item.PropertyDescriptor != null) { result.Add(item.GetPath(), item.PropertyDescriptor); } else { result.Categories.Add(item.Label, item.GridItems.OfType <GridItem>().Where(gi => gi.PropertyDescriptor != null).Select(gi => gi.PropertyDescriptor.Name).ToList()); } } return(result); }
public void Goto(ITabularNamedObject obj) { if (!Tree.VisibleInTree(obj)) { Tree.BeginUpdate(); Tree.Options = LogicalTreeOptions.Default | LogicalTreeOptions.ShowHidden; Tree.Filter = ""; UI.FormMain.UpdateTreeUIButtons(); Tree.EndUpdate(); } var node = UI.TreeView.FindNodeByTag(obj); if (node != null) { UI.TreeView.EnsureVisible(node); UI.TreeView.SelectedNode = node; UI.FormMain.Activate(); UI.TreeView.Focus(); } }
public override void OnStructureChanged(ITabularNamedObject obj = null) { }
internal void UpdateObjectName(ITabularNamedObject obj) { Tree.OnNodeNameChanged(obj); }
/// <summary> /// Inserts the specified list of objects into the model, at the optional destination. Objects that cannot /// be meaningfully inserted in the destination, will be inserted at the destination parent (recursively). /// If no suitable destination can be found, insertion will be ignored. /// Useful for drag-and-drop or copy-paste operations. /// </summary> /// <param name="objects"></param> /// <param name="destination"></param> public List <TabularObject> InsertObjects(ObjectJsonContainer objectContainer, ITabularNamedObject destination = null) { Handler.BeginUpdate("Paste objects"); var inserted = new List <TabularObject>(); // Possible destinations: var destHier = (destination as Level)?.Hierarchy ?? (destination as Hierarchy); var destTable = (destination as Folder)?.Table ?? (destination as Partition)?.Table ?? (destination as PartitionViewTable)?.Table ?? destHier?.Table ?? (destination as IDetailObject)?.Table ?? (destination as Table); var folder = (destination as Folder)?.Path; if (destHier != null) { // Levels can only be deserialized on a Hierarchy destination: foreach (var obj in objectContainer[typeof(Level)]) { inserted.Add(Serializer.DeserializeLevel(obj, destHier)); } destHier.CompactLevelOrdinals(); } if (destTable?.GetType() == typeof(Table)) { // DataColumns and Partitions can only be deserialized onto a Table destination (not CalculatedTable): foreach (var obj in objectContainer[typeof(DataColumn)]) { inserted.Add(Serializer.DeserializeDataColumn(obj, destTable)); } foreach (var obj in objectContainer[typeof(Partition)]) { inserted.Add(Serializer.DeserializePartition(obj, destTable)); } } if (destTable is Table) { // Measures, Hierarchies and CalculatedColumns can be deserialized onto a Table (or Table derived) destinated: foreach (var obj in objectContainer[typeof(CalculatedColumn)]) { inserted.Add(Serializer.DeserializeCalculatedColumn(obj, destTable)); } foreach (var obj in objectContainer[typeof(Hierarchy)]) { inserted.Add(Serializer.DeserializeHierarchy(obj, destTable)); } foreach (var obj in objectContainer[typeof(Measure)]) { inserted.Add(Serializer.DeserializeMeasure(obj, destTable)); } } foreach (var obj in objectContainer[typeof(CalculatedTable)]) { inserted.Add(Serializer.DeserializeCalculatedTable(obj, Handler.Model)); } foreach (var obj in objectContainer[typeof(Table)]) { inserted.Add(Serializer.DeserializeTable(obj, Handler.Model)); } foreach (var obj in objectContainer[typeof(ModelRole)]) { inserted.Add(Serializer.DeserializeModelRole(obj, Handler.Model)); } foreach (var obj in objectContainer[typeof(ProviderDataSource)]) { inserted.Add(Serializer.DeserializeProviderDataSource(obj, Handler.Model)); } foreach (var obj in objectContainer[typeof(SingleColumnRelationship)]) { inserted.Add(Serializer.DeserializeSingleColumnRelationship(obj, Handler.Model)); } foreach (var obj in objectContainer[typeof(Perspective)]) { inserted.Add(Serializer.DeserializePerspective(obj, Handler.Model)); } foreach (var obj in objectContainer[typeof(Culture)]) { inserted.Add(Serializer.DeserializeCulture(obj, Handler.Model)); } if (Handler.CompatibilityLevel >= 1400) { foreach (var obj in objectContainer[typeof(NamedExpression)]) { inserted.Add(Serializer.DeserializeNamedExpression(obj, Handler.Model)); } foreach (var obj in objectContainer[typeof(StructuredDataSource)]) { inserted.Add(Serializer.DeserializeStructuredDataSource(obj, Handler.Model)); } } foreach (var obj in inserted) { (obj as ITranslatableObject)?.LoadTranslations(true); (obj as ITabularPerspectiveObject)?.LoadPerspectives(true); (obj as Table)?.LoadRLS(); if (!string.IsNullOrEmpty(folder) && obj is IDetailObject) { (obj as IDetailObject).DisplayFolder = folder; } if (Handler.CompatibilityLevel >= 1400) { (obj as Table)?.LoadOLS(true); (obj as Column)?.LoadOLS(); } (obj as IAnnotationObject)?.ClearTabularEditorAnnotations(); } Handler.EndUpdate(); FormulaFixup.BuildDependencyTree(); return(inserted); }
public abstract void OnStructureChanged(ITabularNamedObject obj = null);
public bool VisibleInTree(ITabularNamedObject tabularObject) { // Never show the RowNumber column: if ((tabularObject as Column)?.Type == ColumnType.RowNumber) { return(false); } // Don't show invisible objects: if ((tabularObject is IHideableObject) && (tabularObject as IHideableObject).IsHidden && !Options.HasFlag(LogicalTreeOptions.ShowHidden)) { return(false); } // Empty folders are never shown: if (tabularObject is Folder) { if ((tabularObject as Folder).GetChildren().All(c => !VisibleInTree(c))) { return(false); } } // Don't show objects not in the current perspective: if (Perspective != null && tabularObject is ITabularPerspectiveObject && !(tabularObject as ITabularPerspectiveObject).InPerspective[Perspective]) { return(false); } /*// Hide items not matching the filter text: * if (!string.IsNullOrEmpty(Filter)) * { * switch (tabularObject.ObjectType) * { * case ObjectType.Relationship: * case ObjectType.Partition: * case ObjectType.DataSource: * case ObjectType.Perspective: * case ObjectType.Role: * case ObjectType.Culture: * case ObjectType.Column: * case ObjectType.Hierarchy: * case ObjectType.Measure: * if(tabularObject is ITabularTableObject) * { * // If the parent table's name matches the filter criteria, show all objects inside the table, even * // though they don't match the filter: * if ((tabularObject as ITabularTableObject).Table.Name.IndexOf(Filter, StringComparison.InvariantCultureIgnoreCase) >= 0) break; * } * if (tabularObject.Name.IndexOf(Filter, StringComparison.InvariantCultureIgnoreCase) == -1) return false; * break; * } * }*/ // Type dependent display: switch (tabularObject.ObjectType) { case ObjectType.Column: return(Options.HasFlag(LogicalTreeOptions.Columns)); case ObjectType.Measure: return(Options.HasFlag(LogicalTreeOptions.Measures)); case ObjectType.Hierarchy: return(Options.HasFlag(LogicalTreeOptions.Hierarchies)); case ObjectType.PartitionCollection: return(Options.HasFlag(LogicalTreeOptions.Partitions)); } /*// Always hide empty tables when filtering, unless the table name matches the filter criteria * if (tabularObject is Table) * { * var table = tabularObject as Table; * return string.IsNullOrEmpty(Filter) || (table.GetChildren().Any(o => VisibleInTree(o)) || table.Name.IndexOf(Filter, StringComparison.InvariantCultureIgnoreCase) >= 0); * } * // Same goes for PartitionViewTables: * if (tabularObject is PartitionViewTable) * { * var table = tabularObject as PartitionViewTable; * return string.IsNullOrEmpty(Filter) || (table.GetChildren().Any(o => VisibleInTree(o)) || table.Name.IndexOf(Filter, StringComparison.InvariantCultureIgnoreCase) >= 0); * } * * // If a filter is in place, Logical Groups are only shown when they contain objects: * if (tabularObject is LogicalGroup) * { * return string.IsNullOrEmpty(Filter) || (tabularObject as LogicalGroup).GetChildren().Any(o => VisibleInTree(o)); * }*/ // All other objects should be visible by default: return(true); }
public static ITabularNamedObject GetContainer(this ITabularNamedObject obj, bool useFolders = true) { var tree = TabularModelHandler.Singleton.Tree; if (obj is Model) { return(null); } if (obj is Partition) { return((obj as Partition).Table.Partitions); } if (obj is KPI) { return((obj as KPI).Measure); } if (tree.Options.HasFlag(LogicalTreeOptions.AllObjectTypes)) { if (obj is DataSource) { return(LogicalGroups.Singleton.DataSources); } if (obj is Relationship) { return(LogicalGroups.Singleton.Relationships); } if (obj is ModelRole) { return(LogicalGroups.Singleton.Roles); } if (obj is Perspective) { return(LogicalGroups.Singleton.Perspectives); } if (obj is Culture) { return(LogicalGroups.Singleton.Translations); } if (obj is Table) { return(LogicalGroups.Singleton.Tables); } if (obj is NamedExpression) { return(LogicalGroups.Singleton.Expressions); } } if (obj is IFolderObject) { var dObj = obj as IFolderObject; if (useFolders) { var path = ((tree.Culture == null || obj is Folder) ? dObj.DisplayFolder : dObj.TranslatedDisplayFolders[tree.Culture]).TrimFolder(); if (string.IsNullOrEmpty(path)) { return(dObj.Table); } Folder result; if (dObj.Table.FolderCache.TryGetValue(path, out result)) { return(result); } } return(dObj.Table); } return(obj.Model); }
public static bool HasAncestor(this IDetailObject child, ITabularNamedObject ancestor, Culture culture) { string ancestorPath = GetFullPath(ancestor); return((child.Table.Name.ConcatPath(child.GetDisplayFolder(culture)) + "\\").StartsWith(ancestorPath + "\\")); }
public virtual void OnStructureChanged(ITabularNamedObject obj = null) { StructureChanged?.Invoke(this, obj); }
public static bool HasParent(this IDetailObject child, ITabularNamedObject parent, Culture culture) { string parentPath = GetFullPath(parent); return(child.Table.Name.ConcatPath(child.GetDisplayFolder(culture)) == parentPath); }