internal void FireFunctionalChildDetached(FunctionalTreeElement oldChild, FunctionalTreeElement parent)
 {
     if (FunctionalChildDetachedInternal != null)
         FunctionalChildDetachedInternal(oldChild, parent, this);
     if (FunctionalChildDetached != null)
         FunctionalChildDetached(oldChild.Element, parent.Element, this);
 }
 internal void FireFunctionalChildAttached(FunctionalTreeElement newChild, FunctionalTreeElement parent)
 {
     if (FunctionalChildAttachedInternal != null && IsChild(newChild.Element))
         FunctionalChildAttachedInternal(newChild, parent, this);
     if (FunctionalChildAttached != null && IsChild(newChild.Element))
         FunctionalChildAttached(newChild.Element, parent.Element, this);
 }
        private IEnumerable<FunctionalTreeElement> GetAllElements(FunctionalTreeElement element)
        {
            List<FunctionalTreeElement> elements = new List<FunctionalTreeElement>();
            elements.Add(element);

            foreach (FunctionalTreeElement child in element.Children)
                elements.AddRange(GetAllElements(child));

            return elements;
        }
        internal FunctionalTreeElement(IFunctionalTreeElement element, FunctionalTreeElement parent)
        {
            if (element == null)
                throw new ArgumentNullException("element", "element is null.");

            Element = element;
            Parent = parent;

            _children = new List<FunctionalTreeElement>();
            Children = new ReadOnlyCollection<FunctionalTreeElement>(_children);
        }
        private void FunctionalElementDetachedFromTree(FunctionalTreeElement element, FunctionalTreeElement parent, FunctionalTree functionalTree)
        {
            foreach (FunctionalProperty property in FunctionalPropertyValuesInternal.Keys)
            {
                if (property.DefaultMetadata == null || !property.DefaultMetadata.Inherits || property.DefaultMetadata.PropertyChangedCallback == null)
                    continue;

                if (HasValue(property, element.Element))
                    continue;

                FunctionalTreeElement curParent = parent;
                while (curParent != null)
                {
                    if (HasValue(property, curParent.Element))
                    {
                        object oldValue = GetValue(property, curParent.Element);
                        object newValue = property.DefaultMetadata.DefaultValue;

                        property.DefaultMetadata.PropertyChangedCallback(element.Element,
                            new FunctionalPropertyChangedEventArgs(property, oldValue, newValue));

                        if (property.DefaultMetadata.Inherits)
                            NotifyChildrenAboutInheritedValue(FunctionalTreeHelper.GetFunctionalChildren(element.Element), property, oldValue, newValue);

                        break;
                    }

                    curParent = curParent.Parent;
                }
            }
        }
 internal FunctionalTree(FunctionalTreeElement root)
 {
     RootElement = root;
 }
 internal FunctionalTree(IFunctionalTreeElement root)
 {
     RootElement = new FunctionalTreeElement(root, null);
 }
        private void Tree_FunctionalChildAttached(FunctionalTreeElement child, FunctionalTreeElement parent, FunctionalTree functionalTree)
        {
            //remove all other trees with the element or any child in it
            IEnumerable<FunctionalTreeElement> childSubElements = GetAllElements(child);
            IEnumerable<FunctionalTree> treesToRemove = FunctionalTreeList.Where(tree => childSubElements.Any(subElement => tree.IsChild(subElement.Element)));
            //Debug.Assert((treesToRemove.Count() - 1) <= 1, "There shouldn't be more than one tree to remove.");

            foreach (FunctionalTree tree in treesToRemove.ToList())
            {
                if (tree == functionalTree)
                    continue;

                tree.FunctionalChildAttachedInternal -= Tree_FunctionalChildAttached;
                tree.FunctionalChildDetachedInternal -= Tree_FunctionalChildDetached;

                FunctionalTreeList.Remove(tree);
            }

            if (FunctionalElementAttachedToTree != null)
                FunctionalElementAttachedToTree(child, parent, functionalTree);
        }
        private void Tree_FunctionalChildDetached(FunctionalTreeElement child, FunctionalTreeElement parent, FunctionalTree functionalTree)
        {
            //Make sure there are no other trees with child in it
            int removedTreeCount = RemoveTreesWithElement(child.Element);
            //TODO fix and remove unused trees effectively
            //Debug.Assert(removedTreeCount == 0, "There shouldn't have been any trees left with child in it.");

            if (child.HasData)
            {
                //save child in new functional tree to save the data
                FunctionalTree tree = new FunctionalTree(child);
                tree.FunctionalChildAttachedInternal += Tree_FunctionalChildAttached;
                tree.FunctionalChildDetachedInternal += Tree_FunctionalChildDetached;

                FunctionalTreeList.Add(tree);
            }

            if (FunctionalElementDetachedFromTree != null)
                FunctionalElementDetachedFromTree(child, parent, functionalTree);
        }