/// <summary> /// Sets the watch on a node that is not our document node, but a node lower in the hierarchy. We watch both the Changed event and the TunneledEvent of this node. /// </summary> /// <param name="node">The node to watch.</param> protected virtual void SetWatchOnNode(IDocumentLeafNode node) { #if DOCNODEPROXY_CONCURRENTDEBUG int debugUsn = System.Threading.Interlocked.Increment(ref _debugUSN); _debug.Enqueue("START SetWatchOnNode " + debugUsn.ToString()); #endif if (null == node) { throw new ArgumentNullException(nameof(node)); } if (null != _weakDocNodeChangedHandler) { _weakDocNodeChangedHandler.Remove(); _weakDocNodeChangedHandler = null; } if (null != _weakDocNodeTunneledEventHandler) { _weakDocNodeTunneledEventHandler.Remove(); _weakDocNodeTunneledEventHandler = null; } node.TunneledEvent += (_weakDocNodeTunneledEventHandler = new WeakActionHandler <object, object, TunnelingEventArgs>(EhWatchedNode_TunneledEvent, handler => node.TunneledEvent -= handler)); node.Changed += (_weakDocNodeChangedHandler = new WeakEventHandler(EhWatchedNode_Changed, handler => node.Changed -= handler)); #if DEBUG_DOCNODEPROXYLOGGING Current.Console.WriteLine("Start watching node <<{0}>> of total path <<{1}>>", AbsoluteDocumentPath.GetAbsolutePath(node), _docNodePath); #endif #if DOCNODEPROXY_CONCURRENTDEBUG _debug.Enqueue("STOP SetWatchOnNode " + debugUsn.ToString() + (_docNodeRef == null).ToString()); #endif }
/// <summary> /// Sets the watch on a node that is not our document node, but a node lower in the hierarchy. We watch both the Changed event and the TunneledEvent of this node. /// </summary> /// <param name="node">The node to watch.</param> protected virtual void SetWatchOnNode(IDocumentLeafNode node) { if (null == node) { throw new ArgumentNullException(nameof(node)); } if (null != _weakDocNodeChangedHandler) { _weakDocNodeChangedHandler.Remove(); _weakDocNodeChangedHandler = null; } if (null != _weakDocNodeTunneledEventHandler) { _weakDocNodeTunneledEventHandler.Remove(); _weakDocNodeTunneledEventHandler = null; } node.TunneledEvent += (_weakDocNodeTunneledEventHandler = new WeakActionHandler <object, object, TunnelingEventArgs>(EhWatchedNode_TunneledEvent, handler => node.TunneledEvent -= handler)); node.Changed += (_weakDocNodeChangedHandler = new WeakEventHandler(EhWatchedNode_Changed, handler => node.Changed -= handler)); #if DEBUG_DOCNODEPROXYLOGGING Current.Console.WriteLine("Start watching node <<{0}>> of total path <<{1}>>", AbsoluteDocumentPath.GetAbsolutePath(node), _docNodePath); #endif }
/// <summary> /// Initializes a new instance of the <see cref="SimpleCollectionChangedEventArgs"/> class. /// </summary> /// <param name="originator">The originator.</param> /// <exception cref="System.ArgumentNullException">originator</exception> public SimpleCollectionChangedEventArgs(IDocumentLeafNode originator) { if (null == originator) throw new ArgumentNullException("originator"); Originator = originator; }
/// <summary> /// Fires the <see cref="TunneledEvent"/> event. /// </summary> /// <param name="originalSource">The original source of the tunneled event.</param> /// <param name="e">The <see cref="TunnelingEventArgs"/> instance containing the event data.</param> protected virtual void OnTunnelingEvent(IDocumentLeafNode originalSource, TunnelingEventArgs e) { var ev = TunneledEvent; if (null != ev) { ev(this, originalSource, e); } }
public DocNodeProxy(IDocumentLeafNode docNode) { if (null == docNode) { throw new ArgumentNullException(nameof(docNode)); } SetDocNode(docNode); }
/// <summary> /// Initializes a new instance of the <see cref="SimpleCollectionChangedEventArgs"/> class. /// </summary> /// <param name="originator">The originator.</param> /// <exception cref="System.ArgumentNullException">originator</exception> public SimpleCollectionChangedEventArgs(IDocumentLeafNode originator) { if (null == originator) { throw new ArgumentNullException("originator"); } Originator = originator; }
/// <summary> /// Sets the document node that is held by this proxy. /// </summary> /// <param name="value">The document node. If <c>docNode</c> implements <see cref="Main.IDocumentLeafNode" />, /// the document path is stored for this object in addition to the object itself.</param> /// <param name="parentNode">The start point of the document path. Should be equal to the member _parent, but this might be not set now.</param> protected void InternalSetDocNode(Main.IDocumentLeafNode value, IDocumentLeafNode parentNode) { if (!IsValidDocument(value)) { throw new ArgumentException("This type of document is not allowed for the proxy of type " + GetType().ToString()); } if (null == parentNode) { throw new InvalidOperationException("Parent of this node must be set in order to set the docnode."); } var oldValue = InternalDocNode; if (object.ReferenceEquals(oldValue, value)) { return; // Nothing to do } if (null != _weakDocNodeChangedHandler) { _weakDocNodeChangedHandler.Remove(); _weakDocNodeChangedHandler = null; } if (null != _weakDocNodeTunneledEventHandler) { _weakDocNodeTunneledEventHandler.Remove(); _weakDocNodeTunneledEventHandler = null; } if (null != oldValue) { ClearDocNode(); } var newPath = RelativeDocumentPath.GetRelativePathFromTo(parentNode, value); if (null != newPath) { InternalDocumentPath = newPath; // especially in dispose situations, the new path can be null. In this case we leave the path as it was } _docNodeRef = new WeakReference(value); #if DEBUG_DOCNODEPROXYLOGGING Current.Console.WriteLine("RelDocNodeProxy.SetDocNode, path is <<{0}>>", _docNodePath); #endif value.TunneledEvent += (_weakDocNodeTunneledEventHandler = new WeakActionHandler <object, object, TunnelingEventArgs>(EhDocNode_TunneledEvent, handler => value.TunneledEvent -= handler)); if (null != _docNodePath && !_docNodePath.IsIdentity) // it does not make sense to watch the changed event of our target node is our parent because the parent can handle the Changed event itself { value.Changed += (_weakDocNodeChangedHandler = new WeakEventHandler(EhDocNode_Changed, handler => value.Changed -= handler)); } OnAfterSetDocNode(); EhSelfChanged(new Main.InstanceChangedEventArgs(oldValue, value)); }
/// <summary> /// Resolves the path by first using startnode as starting point. If that failed, try using documentRoot as starting point. /// </summary> /// <param name="path">The path to resolve.</param> /// <param name="startnode">The node object which is considered as the starting point of the path.</param> /// <param name="documentRoot">An alternative node which is used as starting point of the path if the first try failed.</param> /// <returns>The resolved object. If the resolving process failed, the return value is null.</returns> public static IDocumentLeafNode GetObject(AbsoluteDocumentPath path, IDocumentLeafNode startnode, IDocumentNode documentRoot) { var retval = GetObject(path, startnode); if (null == retval && null != documentRoot) { retval = GetObject(path, documentRoot); } return(retval); }
public string GetNameOfChildObject(IDocumentLeafNode o) { if (null != o) { return("Infrastructure object of type " + o.GetType().FullName); } else { return("<<null>>"); } }
/// <summary> /// Get the first parent node of the node <code>node</code> that implements the given type <code>type.</code>. /// </summary> /// <param name="node">The node from where the search begins.</param> /// <param name="type">The type to search for.</param> /// <returns>The first parental node that implements the type <code>type.</code> /// </returns> public static IDocumentLeafNode GetRootNodeImplementing(IDocumentLeafNode node, System.Type type) { if (null == node) { return(null); } node = node.ParentObject; while (node != null && !type.IsInstanceOfType(node)) { node = node.ParentObject; } return(type.IsInstanceOfType(node) ? node : null); }
/// <summary> /// Get the first parent node of the node <code>node</code> that implements the given type <code>type.</code>. /// </summary> /// <typeparam name="T">The type to search for.</typeparam> /// <param name="node">The node from where the search begins.</param> /// <returns>The first parental node that implements the type <code>T</code>.</returns> public static T GetRootNodeImplementing <T>(IDocumentLeafNode node) { if (null == node) { return(default(T)); } node = node.ParentObject; while (node != null && !(node is T)) { node = node.ParentObject; } return((node is T) ? (T)node : default(T)); }
/// <summary> /// Get the root node of the node <code>node</code>. The root node is defined as last node in the hierarchie that /// either has not implemented the <see cref="IDocumentLeafNode"/> interface or has no parent. /// </summary> /// <param name="node">The node from where the search begins.</param> /// <returns>The root node, i.e. the last node in the hierarchie that /// either has not implemented the <see cref="IDocumentLeafNode"/> interface or has no parent</returns> public static IDocumentLeafNode GetRootNode(IDocumentLeafNode node) { if (null == node) { throw new ArgumentNullException(nameof(node)); } var parent = node.ParentObject; while (null != parent) { node = parent; parent = node.ParentObject; } return(node); }
/// <summary> /// Get the absolute path of the node <code>node</code> starting either from the root, or from the object in the depth /// <code>maxDepth</code>, whatever is reached first. /// </summary> /// <param name="node">The node for which the path is to be retrieved.</param> /// <param name="maxDepth">The maximal hierarchie depth (the maximal number of path elements returned).</param> /// <returns>The path from the root or from the node in the depth <code>maxDepth</code>, whatever is reached first. The path is <b>not</b> prepended /// by a "/". /// </returns> public static AbsoluteDocumentPath GetPath(IDocumentLeafNode node, int maxDepth) { if (null == node) { throw new ArgumentNullException("node"); } if (maxDepth <= 0) { throw new ArgumentOutOfRangeException("maxDepth should be > 0"); } var list = new List <string>(); int depth = 0; var parent = node.ParentObject; while (parent != null) { if (depth >= maxDepth) { break; } string name = parent.GetNameOfChildObject(node); if (null == name) // an empty string is a valid name, e.g. for a folder text document located in the root folder { throw new InvalidOperationException(string.Format("Parent node (type:{0}) of node (type: {1}) did not return a valid name for the child node!", parent.GetType(), node.GetType())); } list.Add(name); node = parent; parent = node.ParentObject; ++depth; } if (maxDepth == int.MaxValue && node != null && !(node is IProject)) { string msg = string.Format("Document {0} is not rooted. The path so far retrieved is {1}", node, list); throw new InvalidOperationException(msg); } return(new AbsoluteDocumentPath(list.TakeFromUpperIndexExclusiveDownToLowerIndexInclusive(list.Count, 0))); }
public override string GetNameOfChildObject(IDocumentLeafNode o) { if (null == o) { return(null); } else if (object.ReferenceEquals(o, _dataTables)) { return("Tables"); } else if (object.ReferenceEquals(o, _graphs)) { return("Graphs"); } else if (object.ReferenceEquals(o, _graphs3D)) { return("Graphs3D"); } else if (object.ReferenceEquals(o, _textDocuments)) { return("Texts"); } else if (object.ReferenceEquals(o, _tableLayouts)) { return("TableLayouts"); } else if (object.ReferenceEquals(o, _fitFunctionScripts)) { return("FitFunctionScripts"); } else if (object.ReferenceEquals(o, _projectFolderProperties)) { return("FolderProperties"); } else if (object.ReferenceEquals(o, _projectFolders)) { return("ProjectFolders"); } else { return(null); } }
public static IDocumentLeafNode GetObject(AbsoluteDocumentPath path, IDocumentLeafNode startnode) { if (null == path) { throw new ArgumentNullException("path"); } if (null == startnode) { throw new ArgumentNullException("startnode"); } var node = startnode; node = GetRootNode(node); for (int i = 0; i < path.Count; i++) { if (path[i] == "..") { if (null != node) { node = node.ParentObject; } else { return(null); } } else { if (node is Main.IDocumentNode) { node = ((Main.IDocumentNode)node).GetChildObjectNamed(path[i]); } else { return(null); } } } // end for return(node); }
public static IDocumentLeafNode GetObject(RelativeDocumentPath path, IDocumentLeafNode startnode) { if (null == path) { throw new ArgumentNullException(nameof(path)); } if (null == startnode) { throw new ArgumentNullException(nameof(startnode)); } var node = startnode; for (int i = 0; i < path._numberOfLevelsDown && null != node; ++i) { node = node.ParentNode; } if (null == node) { return(null); // Path not resolveable } for (int i = 0; i < path._pathParts.Length; i++) { if (node is Main.IDocumentNode) { node = ((Main.IDocumentNode)node).GetChildObjectNamed(path._pathParts[i]); } else { return(null); } } // end for return(node); }
/// <summary> /// Replaces parts of the part of the document node by another part. If the replacement was successful, the original document node is cleared. /// See <see cref="M:DocumentPath.ReplacePathParts"/> for details of the part replacement. /// </summary> /// <param name="partToReplace">Part of the path that should be replaced. This part has to match the beginning of this part. The last item of the part /// is allowed to be given only partially.</param> /// <param name="newPart">The new part to replace that piece of the path, that match the <c>partToReplace</c>.</param> /// <param name="rootNode">Any document node in the hierarchy that is used to find the root node of the hierarchy.</param> /// <returns>True if the path could be replaced. Returns false if the path does not fulfill the presumptions given above.</returns> /// <remarks> /// As stated above, the last item of the partToReplace can be given only partially. As an example, the path (here separated by space) /// <para>Tables Preexperiment1/WDaten Time</para> /// <para>should be replaced by </para> /// <para>Tables Preexperiment2\WDaten Time</para> /// <para>To make this replacement, the partToReplace should be given by</para> /// <para>Tables Preexperiment1/</para> /// <para>and the newPart should be given by</para> /// <para>Tables Preexperiment2\</para> /// <para>Note that Preexperiment1\ and Preexperiment2\ are only partially defined items of the path.</para> /// </remarks> public bool ReplacePathParts(AbsoluteDocumentPath partToReplace, AbsoluteDocumentPath newPart, IDocumentLeafNode rootNode) { if (!(_docNodePath != null || IsDisposeInProgress)) throw new InvalidProgramException(); if (null == rootNode) throw new ArgumentNullException(nameof(rootNode)); AbsoluteDocumentPath newPath; var success = _docNodePath.ReplacePathParts(partToReplace, newPart, out newPath); if (success) { _docNodePath = newPath; ClearDocNode(); ResolveDocumentObject(rootNode); } return success; }
/// <summary> /// Gets the node that is designated by the provided <paramref name="path"/> or the least resolveable node. /// </summary> /// <param name="path">The document path to resolve.</param> /// <param name="startnode">The startnode.</param> /// <param name="pathWasCompletelyResolved">If set to <c>true</c> on return, the path was completely resolved. Otherwise, <c>false</c>.</param> /// <returns>The resolved node, or the least node on the path that could be resolved.</returns> /// <exception cref="System.ArgumentNullException"> /// path /// or /// startnode /// </exception> public static IDocumentLeafNode GetNodeOrLeastResolveableNode(AbsoluteDocumentPath path, IDocumentLeafNode startnode, out bool pathWasCompletelyResolved) { if (null == path) { throw new ArgumentNullException("path"); } if (null == startnode) { throw new ArgumentNullException("startnode"); } var node = startnode; node = GetRootNode(node); if (null == node) { throw new InvalidProgramException("startnote is not rooted"); } var prevNode = node; pathWasCompletelyResolved = true; for (int i = 0; i < path.Count; i++) { prevNode = node; if (path[i] == "..") { node = node.ParentObject; } else { if (node is Main.IDocumentNode) { node = ((Main.IDocumentNode)node).GetChildObjectNamed(path[i]); } else { node = null; } } if (node == null) { pathWasCompletelyResolved = false; break; } } // end for return(node ?? prevNode); }
/// <summary> /// Can be overriden by derived classes to ensure that the right type of document is stored in /// this proxy. /// </summary> /// <param name="obj">The object to test.</param> /// <returns>True if the <c>obj</c> has the right type to store in this proxy, false otherwise.</returns> protected virtual bool IsValidDocument(IDocumentLeafNode obj) { return true; }
/// <summary> /// Sets the document node that is held by this proxy. /// </summary> /// <param name="value">The document node. If <c>docNode</c> implements <see cref="Main.IDocumentLeafNode" />, /// the document path is stored for this object in addition to the object itself.</param> /// <param name="parentNode">The start point of the document path. Should be equal to the member _parent, but this might be not set now.</param> protected void InternalSetDocNode(Main.IDocumentLeafNode value, IDocumentLeafNode parentNode) { if (!IsValidDocument(value)) throw new ArgumentException("This type of document is not allowed for the proxy of type " + this.GetType().ToString()); if (null == parentNode) throw new InvalidOperationException("Parent of this node must be set in order to set the docnode."); var oldValue = this.InternalDocNode; if (object.ReferenceEquals(oldValue, value)) return; // Nothing to do if (null != _weakDocNodeChangedHandler) { _weakDocNodeChangedHandler.Remove(); _weakDocNodeChangedHandler = null; } if (null != _weakDocNodeTunneledEventHandler) { _weakDocNodeTunneledEventHandler.Remove(); _weakDocNodeTunneledEventHandler = null; } if (null != oldValue) { ClearDocNode(); } var newPath = RelativeDocumentPath.GetRelativePathFromTo(parentNode, value); if (null != newPath) InternalDocumentPath = newPath; // especially in dispose situations, the new path can be null. In this case we leave the path as it was _docNodeRef = new WeakReference(value); #if DEBUG_DOCNODEPROXYLOGGING Current.Console.WriteLine("RelDocNodeProxy.SetDocNode, path is <<{0}>>", _docNodePath); #endif value.TunneledEvent += (_weakDocNodeTunneledEventHandler = new WeakActionHandler<object, object, TunnelingEventArgs>(EhDocNode_TunneledEvent, handler => value.TunneledEvent -= handler)); if (null != _docNodePath && !_docNodePath.IsIdentity) // it does not make sense to watch the changed event of our target node is our parent because the parent can handle the Changed event itself { value.Changed += (_weakDocNodeChangedHandler = new WeakEventHandler(EhDocNode_Changed, handler => value.Changed -= handler)); } OnAfterSetDocNode(); EhSelfChanged(new Main.InstanceChangedEventArgs(oldValue, value)); }
/// <summary> /// Sets the watch on a node that is not our document node, but a node lower in the hierarchy. We watch both the Changed event and the TunneledEvent of this node. /// </summary> /// <param name="node">The node to watch.</param> protected virtual void SetWatchOnNode(IDocumentLeafNode node) { if (null == node) throw new ArgumentNullException(nameof(node)); if (null != _weakDocNodeChangedHandler) { _weakDocNodeChangedHandler.Remove(); _weakDocNodeChangedHandler = null; } if (null != _weakDocNodeTunneledEventHandler) { _weakDocNodeTunneledEventHandler.Remove(); _weakDocNodeTunneledEventHandler = null; } node.TunneledEvent += (_weakDocNodeTunneledEventHandler = new WeakActionHandler<object, object, TunnelingEventArgs>(EhWatchedNode_TunneledEvent, handler => node.TunneledEvent -= handler)); node.Changed += (_weakDocNodeChangedHandler = new WeakEventHandler(EhWatchedNode_Changed, handler => node.Changed -= handler)); #if DEBUG_DOCNODEPROXYLOGGING Current.Console.WriteLine("Start watching node <<{0}>> of total path <<{1}>>", AbsoluteDocumentPath.GetAbsolutePath(node), _docNodePath); #endif }
/// <summary> /// Retrieves the relative path from the node <code>startnode</code> to the node <code>endnode</code>. /// </summary> /// <param name="startnode">The node where the path begins.</param> /// <param name="endnode">The node where the path ends.</param> /// <returns>If the two nodes share a common root, the function returns the relative path from <code>startnode</code> to <code>endnode</code>. /// If the nodes have no common root, then the function returns the absolute path of the endnode.</returns> public static RelativeDocumentPath GetRelativePathFromTo(IDocumentLeafNode startnode, IDocumentLeafNode endnode) { return GetRelativePathFromTo(startnode, endnode, null); }
/// <summary> /// Constructor by giving a numeric column. /// </summary> /// <param name="column">The numeric column to hold.</param> protected NumericColumnProxy(IDocumentLeafNode column) : base(column) { }
public string GetNameOfChildObject(IDocumentLeafNode o) { throw new NotImplementedException(); }
public DocNodeProxy(IDocumentLeafNode docNode) { if (null == docNode) throw new ArgumentNullException(nameof(docNode)); SetDocNode(docNode); }
/// <summary> /// Gets the node that is designated by the provided <paramref name="path"/> or the least resolveable node. /// </summary> /// <param name="path">The document path to resolve.</param> /// <param name="startnode">The startnode.</param> /// <param name="pathWasCompletelyResolved">If set to <c>true</c> on return, the path was completely resolved. Otherwise, <c>false</c>.</param> /// <returns>The resolved node, or the least node on the path that could be resolved.</returns> /// <exception cref="System.ArgumentNullException"> /// path /// or /// startnode /// </exception> public static IDocumentLeafNode GetNodeOrLeastResolveableNode(RelativeDocumentPath path, IDocumentLeafNode startnode, out bool pathWasCompletelyResolved) { if (null == path) { throw new ArgumentNullException(nameof(path)); } if (null == startnode) { throw new ArgumentNullException(nameof(startnode)); } var node = startnode; var prevNode = startnode; for (int i = 0; i < path._numberOfLevelsDown && null != node; ++i) { prevNode = node; node = node.ParentNode; } if (null == node) { pathWasCompletelyResolved = false; return(prevNode); } pathWasCompletelyResolved = true; for (int i = 0; i < path._pathParts.Length && null != node; i++) { prevNode = node; if (node is Main.IDocumentNode) { node = ((Main.IDocumentNode)node).GetChildObjectNamed(path._pathParts[i]); } else { node = null; } } // end for pathWasCompletelyResolved = null != node; return(node ?? prevNode); }
/// <summary> /// Retrieves the relative path from the node <code>startnode</code> to the node <code>endnode</code>. /// </summary> /// <param name="startnode">The node where the path begins.</param> /// <param name="endnode">The node where the path ends.</param> /// <param name="stoppernode">A object which is used as stopper. If the relative path would step down below this node in the hierarchie, /// not the relative path, but the absolute path of the endnode is returned. This is usefull for instance for serialization purposes.You can set the stopper node /// to the root object of serialization, so that path in the inner of the serialization tree are relative paths, whereas paths to objects not includes in the /// serialization tree are returned as absolute paths. The stoppernode can be null.</param> /// <returns>If the two nodes share a common root, the function returns the relative path from <code>startnode</code> to <code>endnode</code>. /// If the nodes have no common root, then the function returns the absolute path of the endnode. /// <para>If either startnode or endnode is null, then null is returned.</para></returns> public static RelativeDocumentPath GetRelativePathFromTo(IDocumentLeafNode startnode, IDocumentLeafNode endnode, IDocumentNode stoppernode) { if (startnode == null) { throw new ArgumentNullException(nameof(startnode)); } if (endnode == null) { throw new ArgumentNullException(nameof(endnode)); } if (object.ReferenceEquals(startnode, endnode)) { return(IdentityPath); // Start node and end node are identical } var currStart = startnode; var currEnd = endnode; var startNodesList = new List <IDocumentLeafNode>(Collections.TreeNodeExtensions.TakeFromHereToRoot(startnode)); var endNodesList = new List <IDocumentLeafNode>(Collections.TreeNodeExtensions.TakeFromHereToRoot(endnode)); var commonNodes = new HashSet <IDocumentLeafNode>(startNodesList); commonNodes.IntersectWith(new HashSet <IDocumentLeafNode>(endNodesList)); if (commonNodes.Count == 0) { return(null); // happens if either startnode or endnode are not rooted (this can happen temporarily during instance creation) } int numberOfNodesDown = 0; IDocumentLeafNode commonNode = null; for (int i = 0; i < startNodesList.Count; ++i) { if (commonNodes.Contains(startNodesList[i])) { commonNode = startNodesList[i]; break; } else { numberOfNodesDown++; } } if (null == commonNodes) { throw new InvalidOperationException(nameof(commonNode) + " should always be != null"); } var idx = endNodesList.IndexOf(commonNode); if (idx < 0) { throw new InvalidOperationException(nameof(idx) + " of commonNode in endNodesList should always be >=0"); } else if (idx == 0) { throw new InvalidOperationException(nameof(idx) + "=0 should not happen because this means identical startnode and endnode"); } return(new RelativeDocumentPath(numberOfNodesDown, endNodesList.TakeFromUpperIndexExclusiveDownToLowerIndexInclusive(idx, 0).Select(x => x.ParentObject.GetNameOfChildObject(x)))); }
/// <summary> /// Retrieves the relative path from the node <code>startnode</code> to the node <code>endnode</code>. /// </summary> /// <param name="startnode">The node where the path begins.</param> /// <param name="endnode">The node where the path ends.</param> /// <returns>If the two nodes share a common root, the function returns the relative path from <code>startnode</code> to <code>endnode</code>. /// If the nodes have no common root, then the function returns the absolute path of the endnode.</returns> public static RelativeDocumentPath GetRelativePathFromTo(IDocumentLeafNode startnode, IDocumentLeafNode endnode) { return(GetRelativePathFromTo(startnode, endnode, null)); }
/// <summary> /// Sets the watch on a node that is not our document node, but a node lower in the hierarchy. We watch both the Changed event and the TunneledEvent of this node. /// </summary> /// <param name="node">The node to watch.</param> protected virtual void SetWatchOnNode(IDocumentLeafNode node) { #if DOCNODEPROXY_CONCURRENTDEBUG int debugUsn = System.Threading.Interlocked.Increment(ref _debugUSN); _debug.Enqueue("START SetWatchOnNode " + debugUsn.ToString()); #endif if (null == node) throw new ArgumentNullException(nameof(node)); if (null != _weakDocNodeChangedHandler) { _weakDocNodeChangedHandler.Remove(); _weakDocNodeChangedHandler = null; } if (null != _weakDocNodeTunneledEventHandler) { _weakDocNodeTunneledEventHandler.Remove(); _weakDocNodeTunneledEventHandler = null; } node.TunneledEvent += (_weakDocNodeTunneledEventHandler = new WeakActionHandler<object, object, TunnelingEventArgs>(EhWatchedNode_TunneledEvent, handler => node.TunneledEvent -= handler)); node.Changed += (_weakDocNodeChangedHandler = new WeakEventHandler(EhWatchedNode_Changed, handler => node.Changed -= handler)); #if DEBUG_DOCNODEPROXYLOGGING Current.Console.WriteLine("Start watching node <<{0}>> of total path <<{1}>>", AbsoluteDocumentPath.GetAbsolutePath(node), _docNodePath); #endif #if DOCNODEPROXY_CONCURRENTDEBUG _debug.Enqueue("STOP SetWatchOnNode " + debugUsn.ToString() + (_docNodeRef == null).ToString()); #endif }
/// <summary> /// Retrieves the relative path from the node <code>startnode</code> to the node <code>endnode</code>. /// </summary> /// <param name="startnode">The node where the path begins.</param> /// <param name="endnode">The node where the path ends.</param> /// <param name="stoppernode">A object which is used as stopper. If the relative path would step down below this node in the hierarchie, /// not the relative path, but the absolute path of the endnode is returned. This is usefull for instance for serialization purposes.You can set the stopper node /// to the root object of serialization, so that path in the inner of the serialization tree are relative paths, whereas paths to objects not includes in the /// serialization tree are returned as absolute paths. The stoppernode can be null.</param> /// <returns>If the two nodes share a common root, the function returns the relative path from <code>startnode</code> to <code>endnode</code>. /// If the nodes have no common root, then the function returns the absolute path of the endnode. /// <para>If either startnode or endnode is null, then null is returned.</para></returns> public static RelativeDocumentPath GetRelativePathFromTo(IDocumentLeafNode startnode, IDocumentLeafNode endnode, IDocumentNode stoppernode) { if (startnode == null) throw new ArgumentNullException(nameof(startnode)); if (endnode == null) throw new ArgumentNullException(nameof(endnode)); if (object.ReferenceEquals(startnode, endnode)) return IdentityPath; // Start node and end node are identical var currStart = startnode; var currEnd = endnode; var startNodesList = new List<IDocumentLeafNode>(Altaxo.Collections.TreeNodeExtensions.TakeFromHereToRoot(startnode)); var endNodesList = new List<IDocumentLeafNode>(Altaxo.Collections.TreeNodeExtensions.TakeFromHereToRoot(endnode)); var commonNodes = new HashSet<IDocumentLeafNode>(startNodesList); commonNodes.IntersectWith(new HashSet<IDocumentLeafNode>(endNodesList)); if (commonNodes.Count == 0) return null; // happens if either startnode or endnode are not rooted (this can happen temporarily during instance creation) int numberOfNodesDown = 0; IDocumentLeafNode commonNode = null; for (int i = 0; i < startNodesList.Count; ++i) { if (commonNodes.Contains(startNodesList[i])) { commonNode = startNodesList[i]; break; } else { numberOfNodesDown++; } } if (null == commonNodes) throw new InvalidOperationException(nameof(commonNode) + " should always be != null"); var idx = endNodesList.IndexOf(commonNode); if (idx < 0) throw new InvalidOperationException(nameof(idx) + " of commonNode in endNodesList should always be >=0"); else if (idx == 0) throw new InvalidOperationException(nameof(idx) + "=0 should not happen because this means identical startnode and endnode"); return new RelativeDocumentPath(numberOfNodesDown, endNodesList.TakeFromUpperIndexExclusiveDownToLowerIndexInclusive(idx, 0).Select(x => x.ParentObject.GetNameOfChildObject(x))); }
public bool ReplacePathParts(AbsoluteDocumentPath partToReplace, AbsoluteDocumentPath newPart, IDocumentLeafNode rootNode) { return(false); }
/// <summary> /// Constructor by giving a numeric column. /// </summary> /// <param name="column">The numeric column to hold.</param> protected NumericColumnProxy(IDocumentLeafNode column) : base(column) { }
public bool ReplacePathParts(AbsoluteDocumentPath partToReplace, AbsoluteDocumentPath newPart, IDocumentLeafNode rootNode) { return false; }
/// <summary> /// Gets the node that is designated by the provided <paramref name="path"/> or the least resolveable node. /// </summary> /// <param name="path">The document path to resolve.</param> /// <param name="startnode">The startnode.</param> /// <param name="pathWasCompletelyResolved">If set to <c>true</c> on return, the path was completely resolved. Otherwise, <c>false</c>.</param> /// <returns>The resolved node, or the least node on the path that could be resolved.</returns> /// <exception cref="System.ArgumentNullException"> /// path /// or /// startnode /// </exception> public static IDocumentLeafNode GetNodeOrLeastResolveableNode(RelativeDocumentPath path, IDocumentLeafNode startnode, out bool pathWasCompletelyResolved) { if (null == path) throw new ArgumentNullException(nameof(path)); if (null == startnode) throw new ArgumentNullException(nameof(startnode)); var node = startnode; var prevNode = startnode; for (int i = 0; i < path._numberOfLevelsDown && null != node; ++i) { prevNode = node; node = node.ParentNode; } if (null == node) { pathWasCompletelyResolved = false; return prevNode; } pathWasCompletelyResolved = true; for (int i = 0; i < path._pathParts.Length && null != node; i++) { prevNode = node; if (node is Main.IDocumentNode) node = ((Main.IDocumentNode)node).GetChildObjectNamed(path._pathParts[i]); else node = null; } // end for pathWasCompletelyResolved = null != node; return node ?? prevNode; }
protected ReadableColumnProxy(IDocumentLeafNode column) : base(column) { }
/// <summary> /// Sets the document node that is held by this proxy. /// </summary> /// <param name="value">The document node. If <c>docNode</c> implements <see cref="Main.IDocumentLeafNode" />, /// the document path is stored for this object in addition to the object itself.</param> public void SetDocNode(IDocumentLeafNode value) { if (null == value) { throw new ArgumentNullException(nameof(value)); } var oldValue = InternalDocumentNode; if (object.ReferenceEquals(oldValue, value)) { return; } if (!IsValidDocument(value)) { throw new ArgumentException("This type of document is not allowed for the proxy of type " + GetType().ToString()); } #if DOCNODEPROXY_CONCURRENTDEBUG _debug.Enqueue("START SetDocNode"); #endif if (null != _weakDocNodeChangedHandler) { _weakDocNodeChangedHandler.Remove(); _weakDocNodeChangedHandler = null; } if (null != _weakDocNodeTunneledEventHandler) { _weakDocNodeTunneledEventHandler.Remove(); _weakDocNodeTunneledEventHandler = null; } #if DOCNODEPROXY_CONCURRENTDEBUG _debug.Enqueue("MIDDL SetDocNode EventHandlers removed"); #endif if (oldValue != null) { ClearDocNode(); } InternalDocumentPath = Main.AbsoluteDocumentPath.GetAbsolutePath(value); _docNodeRef = new WeakReference(value); #if DEBUG_DOCNODEPROXYLOGGING Current.Console.WriteLine("DocNodeProxy.SetDocNode, path is <<{0}>>", _docNodePath); #endif InternalCheckAbsolutePath(); value.TunneledEvent += (_weakDocNodeTunneledEventHandler = new WeakActionHandler <object, object, TunnelingEventArgs>(EhDocNode_TunneledEvent, handler => value.TunneledEvent -= handler)); value.Changed += (_weakDocNodeChangedHandler = new WeakEventHandler(EhDocNode_Changed, handler => value.Changed -= handler)); OnAfterSetDocNode(); EhSelfChanged(new Main.InstanceChangedEventArgs(oldValue, value)); #if DOCNODEPROXY_CONCURRENTDEBUG _debug.Enqueue("STOP SetDocNode"); #endif }
/// <summary> /// Get the absolute path of the node <code>node</code> starting from the root. /// </summary> /// <param name="node">The node for which the path is retrieved.</param> /// <returns>The absolute path of the node. The first element is a "/" to mark this as absolute path.</returns> public static AbsoluteDocumentPath GetAbsolutePath(IDocumentLeafNode node) { AbsoluteDocumentPath path = GetPath(node, int.MaxValue); return(path); }
/// <summary> /// Replaces parts of the part of the document node by another part. If the replacement was successful, the original document node is cleared. /// See <see cref="M:DocumentPath.ReplacePathParts"/> for details of the part replacement. /// </summary> /// <param name="partToReplace">Part of the path that should be replaced. This part has to match the beginning of this part. The last item of the part /// is allowed to be given only partially.</param> /// <param name="newPart">The new part to replace that piece of the path, that match the <c>partToReplace</c>.</param> /// <param name="rootNode">Any document node in the hierarchy that is used to find the root node of the hierarchy.</param> /// <returns>True if the path could be replaced. Returns false if the path does not fulfill the presumptions given above.</returns> /// <remarks> /// As stated above, the last item of the partToReplace can be given only partially. As an example, the path (here separated by space) /// <para>Tables Preexperiment1/WDaten Time</para> /// <para>should be replaced by </para> /// <para>Tables Preexperiment2\WDaten Time</para> /// <para>To make this replacement, the partToReplace should be given by</para> /// <para>Tables Preexperiment1/</para> /// <para>and the newPart should be given by</para> /// <para>Tables Preexperiment2\</para> /// <para>Note that Preexperiment1\ and Preexperiment2\ are only partially defined items of the path.</para> /// </remarks> public bool ReplacePathParts(AbsoluteDocumentPath partToReplace, AbsoluteDocumentPath newPart, IDocumentLeafNode rootNode) { if (!(_docNodePath != null || IsDisposeInProgress)) { throw new InvalidProgramException(); } if (null == rootNode) { throw new ArgumentNullException(nameof(rootNode)); } var success = _docNodePath.ReplacePathParts(partToReplace, newPart, out var newPath); if (success) { _docNodePath = newPath; ClearDocNode(); ResolveDocumentObject(rootNode); } return(success); }
public static string GetPathString(IDocumentLeafNode node, int maxDepth) { return(GetPath(node, maxDepth).ToString()); }
public static IDocumentLeafNode GetObject(RelativeDocumentPath path, IDocumentLeafNode startnode) { if (null == path) throw new ArgumentNullException(nameof(path)); if (null == startnode) throw new ArgumentNullException(nameof(startnode)); var node = startnode; for (int i = 0; i < path._numberOfLevelsDown && null != node; ++i) { node = node.ParentNode; } if (null == node) return null; // Path not resolveable for (int i = 0; i < path._pathParts.Length; i++) { if (node is Main.IDocumentNode) node = ((Main.IDocumentNode)node).GetChildObjectNamed(path._pathParts[i]); else return null; } // end for return node; }
public DocumentNodeAndName(IDocumentLeafNode doc, Action setMemberToNullAction, string name) { _doc = doc; _name = name; _setMemberToNullAction = setMemberToNullAction; }
public DocumentNodeAndName(IDocumentLeafNode doc, Action setMemberToNullAction, string name) { _doc = doc; _name = name; _setMemberToNullAction = setMemberToNullAction; }
/// <summary> /// Can be overriden by derived classes to ensure that the right type of document is stored in /// this proxy. /// </summary> /// <param name="obj">The object to test.</param> /// <returns>True if the <c>obj</c> has the right type to store in this proxy, false otherwise.</returns> protected virtual bool IsValidDocument(IDocumentLeafNode obj) { return(true); }
/// <summary> /// Sets the document node that is held by this proxy. /// </summary> /// <param name="value">The document node. If <c>docNode</c> implements <see cref="Main.IDocumentLeafNode" />, /// the document path is stored for this object in addition to the object itself.</param> public void SetDocNode(IDocumentLeafNode value) { if (null == value) throw new ArgumentNullException(nameof(value)); var oldValue = InternalDocumentNode; if (object.ReferenceEquals(oldValue, value)) return; if (!IsValidDocument(value)) throw new ArgumentException("This type of document is not allowed for the proxy of type " + this.GetType().ToString()); #if DOCNODEPROXY_CONCURRENTDEBUG _debug.Enqueue("START SetDocNode"); #endif if (null != _weakDocNodeChangedHandler) { _weakDocNodeChangedHandler.Remove(); _weakDocNodeChangedHandler = null; } if (null != _weakDocNodeTunneledEventHandler) { _weakDocNodeTunneledEventHandler.Remove(); _weakDocNodeTunneledEventHandler = null; } #if DOCNODEPROXY_CONCURRENTDEBUG _debug.Enqueue("MIDDL SetDocNode EventHandlers removed"); #endif if (oldValue != null) { ClearDocNode(); } InternalDocumentPath = Main.AbsoluteDocumentPath.GetAbsolutePath(value); _docNodeRef = new WeakReference(value); #if DEBUG_DOCNODEPROXYLOGGING Current.Console.WriteLine("DocNodeProxy.SetDocNode, path is <<{0}>>", _docNodePath); #endif InternalCheckAbsolutePath(); value.TunneledEvent += (_weakDocNodeTunneledEventHandler = new WeakActionHandler<object, object, TunnelingEventArgs>(EhDocNode_TunneledEvent, handler => value.TunneledEvent -= handler)); value.Changed += (_weakDocNodeChangedHandler = new WeakEventHandler(EhDocNode_Changed, handler => value.Changed -= handler)); OnAfterSetDocNode(); EhSelfChanged(new Main.InstanceChangedEventArgs(oldValue, value)); #if DOCNODEPROXY_CONCURRENTDEBUG _debug.Enqueue("STOP SetDocNode"); #endif }
public string GetNameOfChildObject(IDocumentLeafNode o) { throw new NotImplementedException(); }
protected ReadableColumnProxy(IDocumentLeafNode column) : base(column) { }