/// <summary>
        /// Remove a child node and return the node's next sibling, previous sibling or the parent node.
        /// </summary>
        public FolderConfigurationNodeBase RemoveChildNode(FolderConfigurationNodeBase node)
        {
            var nextSelectedNode = node.NextSibling ?? node.PreviousSibling ?? this;

            this.SubTree.Items.Remove(node);
            this.Modified = true;
            return(nextSelectedNode);
        }
        public DragDropKind CanAcceptDrop(FolderConfigurationNodeBase dropData, DragDropKind kind)
        {
            if (dropData == null || this == dropData || this == dropData.Parent || this.IsDescendentOf(dropData))
            {
                return(DragDropKind.None);
            }

            return(DragDropKind.Move);
        }
        /// <summary>
        /// Add a node to the sub tree.
        /// </summary>
        public void AddChildNode(FolderConfigurationNodeBase node)
        {
            BuildSubTree();

            node.Parent          = this;
            node.ModifiedEnabled = this.ModifiedEnabled;
            _subTree.Items.Add(node);
            this.Modified = true;

            // expand the tree right away
            this.ExpandSubTree();
        }
        /// <summary>
        /// Propagates check state up to parent.
        /// </summary>
        /// <param name="parent"></param>
        private static void PropagateCheckStateUp(FolderConfigurationNodeBase parent)
        {
            if (parent == null)
            {
                return;
            }

            var b = CollectionUtils.Contains(parent.SubTree.Items, n => n.IsChecked);

            parent.SetCheckStateInternal(b);

            PropagateCheckStateUp(parent.Parent);
        }
        /// <summary>
        /// Propagates check state down to children.
        /// </summary>
        /// <param name="parent"></param>
        private static void PropagateCheckStateDown(FolderConfigurationNodeBase parent)
        {
            if (parent == null || parent.SubTree == null)
            {
                return;
            }

            foreach (var child in parent.SubTree.Items)
            {
                child.SetCheckStateInternal(parent.IsChecked);
                PropagateCheckStateDown(child);
            }
        }
        /// <summary>
        /// Determine whether this node is a descendent of the ancestorNode.
        /// </summary>
        /// <param name="ancestorNode">The unknown ancestorNode.</param>
        /// <returns>True if this node is the descendent of the ancestorNode.</returns>
        private bool IsDescendentOf(FolderConfigurationNodeBase ancestorNode)
        {
            // testNode has no children
            if (ancestorNode.SubTree == null)
            {
                return(false);
            }

            var isDescendentOfAncestorNode = CollectionUtils.Contains(ancestorNode.SubTree.Items,
                                                                      childOfTestNode => this == childOfTestNode || this.IsDescendentOf(childOfTestNode));

            return(isDescendentOfAncestorNode);
        }
        /// <summary>
        /// Insert a node to the proper depth using the path.
        /// </summary>
        public void InsertNode(FolderConfigurationNodeBase node, Path path)
        {
            // There is no recommended path.  Add it immediately
            if (path == null || path.Segments.Count == 0)
            {
                AddChildNode(node);
                return;
            }

            var text = CollectionUtils.FirstElement(path.Segments).LocalizedText;
            var childWithMatchingText = _subTree == null ? null : CollectionUtils.SelectFirst(_subTree.Items, child => child.Text == text);

            if (childWithMatchingText == null)
            {
                if (path.Segments.Count == 1)
                {
                    // There are no more depth to the path, add child now.
                    AddChildNode(node);
                    PropagateCheckStateUp(node.Parent);
                }
                else
                {
                    // create a container node and insert into the container node's subtree
                    var containerNode = new ContainerNode(text);
                    AddChildNode(containerNode);
                    containerNode.InsertNode(node, path.SubPath(1, path.Segments.Count - 1));
                }
            }
            else
            {
                if (path.Segments.Count == 1)
                {
                    // There are no more depth to the path, add child now.
                    if (childWithMatchingText is ContainerNode)
                    {
                        ReplaceChildNode(childWithMatchingText, node);
                    }
                    else
                    {
                        AddChildNode(node);
                    }

                    PropagateCheckStateUp(node.Parent);
                }
                else
                {
                    // insert this node child's subtree
                    childWithMatchingText.InsertNode(node, path.SubPath(1, path.Segments.Count - 1));
                }
            }
        }
        public DragDropKind AcceptDrop(FolderConfigurationNodeBase dropData, DragDropKind kind)
        {
            if (dropData.Parent != null)
            {
                dropData.Parent.SubTree.Items.Remove(dropData);
            }

            AddChildNode(dropData);
            PropagateCheckStateUp(this);

            this.Modified = true;

            return(DragDropKind.Move);
        }
        /// <summary>
        /// Replace a child node with a new node.
        /// </summary>
        public void ReplaceChildNode(FolderConfigurationNodeBase oldChildNode, FolderConfigurationNodeBase newChildNode)
        {
            // Move the subtree of the old node to the new node.
            foreach (var node in oldChildNode.SubTree.Items)
            {
                newChildNode.AddChildNode(node);
            }
            oldChildNode.ClearSubTree();
            newChildNode.Parent = oldChildNode.Parent;

            // replace the nodes
            var index = this.SubTree.Items.IndexOf(oldChildNode);

            this.SubTree.Items.Insert(index, newChildNode);
            this.SubTree.Items.Remove(oldChildNode);
            this.Modified = true;
        }
		/// <summary>
		/// Determine whether this node is a descendent of the ancestorNode.
		/// </summary>
		/// <param name="ancestorNode">The unknown ancestorNode.</param>
		/// <returns>True if this node is the descendent of the ancestorNode.</returns>
		private bool IsDescendentOf(FolderConfigurationNodeBase ancestorNode)
		{
			// testNode has no children
			if (ancestorNode.SubTree == null)
				return false;

			var isDescendentOfAncestorNode = CollectionUtils.Contains(ancestorNode.SubTree.Items,
				childOfTestNode => this == childOfTestNode || this.IsDescendentOf(childOfTestNode));

			return isDescendentOfAncestorNode;
		}
		public DragDropKind AcceptDrop(FolderConfigurationNodeBase dropData, DragDropKind kind)
		{
			if (dropData.Parent != null)
				dropData.Parent.SubTree.Items.Remove(dropData);

			AddChildNode(dropData);
			PropagateCheckStateUp(this);

			this.Modified = true;

			return DragDropKind.Move;
		}
		public DragDropKind CanAcceptDrop(FolderConfigurationNodeBase dropData, DragDropKind kind)
		{
			if (dropData == null || this == dropData || this == dropData.Parent || this.IsDescendentOf(dropData))
				return DragDropKind.None;

			return DragDropKind.Move;
		}
		/// <summary>
		/// Insert a node to the proper depth using the path.
		/// </summary>
		public void InsertNode(FolderConfigurationNodeBase node, Path path)
		{
			// There is no recommended path.  Add it immediately
			if (path == null || path.Segments.Count == 0)
			{
				AddChildNode(node);
				return;
			}

			var text  = CollectionUtils.FirstElement(path.Segments).LocalizedText;
			var childWithMatchingText = _subTree == null ? null : CollectionUtils.SelectFirst(_subTree.Items, child => child.Text == text);
			
			if (childWithMatchingText == null)
			{
				if (path.Segments.Count == 1)
				{
					// There are no more depth to the path, add child now.
					AddChildNode(node);
					PropagateCheckStateUp(node.Parent);
				}
				else
				{
					// create a container node and insert into the container node's subtree
					var containerNode = new ContainerNode(text);
					AddChildNode(containerNode);
					containerNode.InsertNode(node, path.SubPath(1, path.Segments.Count - 1));
				}
			}
			else
			{
				if (path.Segments.Count == 1)
				{
					// There are no more depth to the path, add child now.
					if (childWithMatchingText is ContainerNode)
						ReplaceChildNode(childWithMatchingText, node);
					else
						AddChildNode(node);

					PropagateCheckStateUp(node.Parent);
				}
				else
				{
					// insert this node child's subtree
					childWithMatchingText.InsertNode(node, path.SubPath(1, path.Segments.Count - 1));
				}
			}
		}
		/// <summary>
		/// Replace a child node with a new node.
		/// </summary>
		public void ReplaceChildNode(FolderConfigurationNodeBase oldChildNode, FolderConfigurationNodeBase newChildNode)
		{
			// Move the subtree of the old node to the new node.
			foreach (var node in oldChildNode.SubTree.Items)
			{
				newChildNode.AddChildNode(node);
			}
			oldChildNode.ClearSubTree();
			newChildNode.Parent = oldChildNode.Parent;

			// replace the nodes
			var index = this.SubTree.Items.IndexOf(oldChildNode);
			this.SubTree.Items.Insert(index, newChildNode);
			this.SubTree.Items.Remove(oldChildNode);
			this.Modified = true;
		}
		/// <summary>
		/// Remove a child node and return the node's next sibling, previous sibling or the parent node.
		/// </summary>
		public FolderConfigurationNodeBase RemoveChildNode(FolderConfigurationNodeBase node)
		{
			var nextSelectedNode = node.NextSibling ?? node.PreviousSibling ?? this;
			this.SubTree.Items.Remove(node);
			this.Modified = true;
			return nextSelectedNode;
		}
		/// <summary>
		/// Add a node to the sub tree.
		/// </summary>
		public void AddChildNode(FolderConfigurationNodeBase node)
		{
			BuildSubTree();

			node.Parent = this;
			node.ModifiedEnabled = this.ModifiedEnabled;
			_subTree.Items.Add(node);
			this.Modified = true;

			// expand the tree right away
			this.ExpandSubTree();
		}
		/// <summary>
		/// Propagates check state up to parent.
		/// </summary>
		/// <param name="parent"></param>
		private static void PropagateCheckStateUp(FolderConfigurationNodeBase parent)
		{
			if (parent == null)
				return;

			var b = CollectionUtils.Contains(parent.SubTree.Items, n => n.IsChecked);
			parent.SetCheckStateInternal(b);

			PropagateCheckStateUp(parent.Parent);
		}
		/// <summary>
		/// Propagates check state down to children.
		/// </summary>
		/// <param name="parent"></param>
		private static void PropagateCheckStateDown(FolderConfigurationNodeBase parent)
		{
			if (parent == null || parent.SubTree == null)
				return;

			foreach (var child in parent.SubTree.Items)
			{
				child.SetCheckStateInternal(parent.IsChecked);
				PropagateCheckStateDown(child);
			}
		}
 public FolderExplorerConfigurationComponent()
 {
     _folderTree           = FolderConfigurationNodeBase.BuildTree();
     _folderSystemsToReset = new List <IFolderSystem>();
 }