/// <summary>
        /// Exposes virtual protected for testing.
        /// </summary>
        /// <param name="oldValue">The old Value.</param>
        /// <param name="newValue">The new Value.</param>
        protected override void OnItemDefinitionPropertyChanged(TreeMapItemDefinition oldValue, TreeMapItemDefinition newValue)
        {
            base.OnItemDefinitionPropertyChanged(oldValue, newValue);

            if (OnItemDefinitionPropertyChangedEvent != null)
            {
                OnItemDefinitionPropertyChangedEvent(oldValue, newValue);
            }
        }
        public virtual void ValueChildItemPadding()
        {
            TreeMapItemDefinition testItemDef = new TreeMapItemDefinition();

            Assert.IsNotNull(testItemDef.ChildItemPadding);
            Assert.AreEqual(0, testItemDef.ChildItemPadding.Left);
            Assert.AreEqual(0, testItemDef.ChildItemPadding.Top);
            Assert.AreEqual(0, testItemDef.ChildItemPadding.Right);
            Assert.AreEqual(0, testItemDef.ChildItemPadding.Bottom);
        }
        public virtual void ValuePathTest()
        {
            const string BindingName = "Foo";
            TreeMapItemDefinition testItemDef = new TreeMapItemDefinition();

            Assert.IsNull(testItemDef.ValueBinding);
            Assert.IsNull(testItemDef.ValuePath);

            testItemDef.ValuePath = BindingName;
            
            Assert.IsNotNull(testItemDef.ValueBinding);
            Assert.AreEqual(BindingName, testItemDef.ValueBinding.Path.Path);

            testItemDef.ValuePath = null;

            Assert.IsNull(testItemDef.ValueBinding);
            Assert.IsNull(testItemDef.ValuePath);
        }
Example #4
0
        /// <summary>
        /// Called when the value of the ItemDefinitionProperty property changes.
        /// </summary>
        /// <param name="d">Reference to the TreeMap object.</param>
        /// <param name="e">Event handler arguments.</param>
        private static void OnItemDefinitionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is TreeMap treeMap)
            {
                TreeMapItemDefinition oldValue = e.OldValue as TreeMapItemDefinition;
                TreeMapItemDefinition newValue = e.NewValue as TreeMapItemDefinition;

                // Unregister old TreeMapItemDefinition
                if (oldValue != null)
                {
                    oldValue.PropertyChanged -= treeMap.OnItemDefinitionPropertyChanged;
                }

                // Register new TreeMapItemDefinition
                if (newValue != null)
                {
                    newValue.PropertyChanged += treeMap.OnItemDefinitionPropertyChanged;
                }

                treeMap.OnItemDefinitionPropertyChanged(oldValue, newValue);
            }
        }
Example #5
0
        /// <summary>
        /// Builds the parallel trees of TreeMapNodes with references to the original user's trees.
        /// </summary>
        /// <param name="nodes">The list of roots of the user hierarchies (whatever was passed through ItemsSource).</param>
        /// <param name="level">Level being processed at this recursive call (the root node is at level 0).</param>
        /// <returns>The list of roots of the internal trees of TreeMapNodes.</returns>
        private IEnumerable <TreeMapNode> BuildTreeMapTree(IEnumerable nodes, int level)
        {
            List <TreeMapNode> retList = new List <TreeMapNode>();

            if (nodes == null)
            {
                return(retList);
            }

            foreach (object root in nodes)
            {
                // Give the template selector a chance to override the template for this item.
                TreeMapItemDefinition template = null;
                if (ItemDefinitionSelector != null)
                {
                    template = ItemDefinitionSelector.SelectItemDefinition(this, root, level);
                }

                // Use the default otherwise
                if (template == null)
                {
                    template = ItemDefinition;
                }

                if (template == null)
                {
                    throw new ArgumentException(
                              Properties.Resources.TreeMap_BuildTreeMapTree_TemplateNotSet);
                }

                // Silently create 0 elements if ValueBinding is set to null
                // in the template
                if (template.ValueBinding != null)
                {
                    IEnumerable objectChildren = (template.ItemsSource != null) ?
                                                 _helper.RetrieveProperty(root, template.ItemsSource) as IEnumerable :
                                                 null;
                    IEnumerable <TreeMapNode> children = (objectChildren != null) ?
                                                         BuildTreeMapTree(objectChildren, level + 1) :
                                                         children = Enumerable.Empty <TreeMapNode>();

                    // Subscribe to CollectionChanged for the collection
                    WeakEventListener <TreeMap, object, NotifyCollectionChangedEventArgs> weakEventListener = null;
                    INotifyCollectionChanged objectChildrenINotifyCollectionChanged = objectChildren as INotifyCollectionChanged;
                    if (objectChildrenINotifyCollectionChanged != null)
                    {
                        // Use a WeakEventListener so that the backwards reference doesn't keep this object alive
                        weakEventListener = new WeakEventListener <TreeMap, object, NotifyCollectionChangedEventArgs>(this);
                        weakEventListener.OnEventAction  = (instance, source, eventArgs) => instance.ItemsSourceCollectionChanged(source, eventArgs);
                        weakEventListener.OnDetachAction = (wel) => objectChildrenINotifyCollectionChanged.CollectionChanged -= wel.OnEvent;
                        objectChildrenINotifyCollectionChanged.CollectionChanged += weakEventListener.OnEvent;
                    }

                    // Auto-aggregate children area values
                    double area;
                    if (children.Any())
                    {
                        area = children.Sum(x => x.Area);
                    }
                    else
                    {
                        IConvertible value = _helper.RetrieveProperty(root, template.ValueBinding) as IConvertible;
                        if (value == null)
                        {
                            // Provide a default value so there's something to display
                            value = 1.0;
                        }

                        area = value.ToDouble(CultureInfo.InvariantCulture);
                    }

                    // Do not include elements with negative or 0 size in the
                    // VisualTransition tree. We skip interpolation for such
                    // elements as well
                    if (area > 0)
                    {
                        // Calculate ranges for all interpolators, only consider leaf
                        // nodes in the LeafNodesOnly mode, or all nodes in the AllNodes
                        // mode.
                        foreach (Interpolator interpolator in Interpolators)
                        {
                            if (interpolator.InterpolationMode == InterpolationMode.AllNodes || !children.Any())
                            {
                                interpolator.IncludeInRange(root);
                            }
                        }

                        retList.Add(new TreeMapNode()
                        {
                            DataContext       = root,
                            Level             = level,
                            Area              = area,
                            ItemDefinition    = template,
                            ChildItemPadding  = template.ChildItemPadding,
                            Children          = children,
                            WeakEventListener = weakEventListener,
                        });
                    }
                }
            }

            return(retList);
        }
Example #6
0
 /// <summary>
 /// Called when the value of the ItemDefinitionProperty property changes.
 /// Triggers a recalculation of the layout.
 /// </summary>
 /// <param name="oldValue">The old item definition.</param>
 /// <param name="newValue">The new item definition.</param>
 protected virtual void OnItemDefinitionPropertyChanged(TreeMapItemDefinition oldValue, TreeMapItemDefinition newValue)
 {
     RebuildTree();
 }
        public void TreeMapInheritViaProtectedVirtual()
        {
            InheritedTreeMap treeMap = new InheritedTreeMap();

            // Set initial values.
            TreeMapItemDefinitionSelector selectorOld = new SampleTemplateSelector();
            treeMap.SetValue(TreeMap.ItemDefinitionSelectorProperty, selectorOld);
            TreeMapItemDefinition definitionOld = new TreeMapItemDefinition { ChildItemPadding = new Thickness(0) };
            treeMap.SetValue(TreeMap.ItemDefinitionProperty, definitionOld);
            int[] itemsOld = new int[] { 1 };
            treeMap.SetValue(TreeMap.ItemsSourceProperty, itemsOld);
            Collection<Interpolator> collectionOld = new Collection<Interpolator> { new DoubleInterpolator() };
            treeMap.SetValue(TreeMap.InterpolatorsProperty, collectionOld);

            // Test TreeMapItemDefinitionSelectorProperty
            TreeMapItemDefinitionSelector selectorNew = new SampleTemplateSelector();
            bool calledItemDefinitionSelectorPropertyEvent = false;
            
            treeMap.OnItemDefinitionSelectorPropertyChangedEvent += (oldValue, newValue) =>
            {
                Assert.AreEqual(oldValue, selectorOld);
                Assert.AreEqual(newValue, selectorNew);
                Assert.AreNotEqual(newValue, oldValue);
                Assert.IsFalse(calledItemDefinitionSelectorPropertyEvent);
                calledItemDefinitionSelectorPropertyEvent = true;
            };
            treeMap.SetValue(TreeMap.ItemDefinitionSelectorProperty, selectorNew);
            Assert.IsTrue(calledItemDefinitionSelectorPropertyEvent);

            // Test ItemDefinitionProperty
            TreeMapItemDefinition definitionNew = new TreeMapItemDefinition { ChildItemPadding = new Thickness(1) };

            bool calledItemDefinitionPropertyyEvent = false;
            treeMap.OnItemDefinitionPropertyChangedEvent += (oldValue, newValue) =>
            {
                Assert.AreEqual(oldValue, definitionOld);
                Assert.AreEqual(newValue, definitionNew);
                Assert.AreNotEqual(newValue, oldValue);
                Assert.IsFalse(calledItemDefinitionPropertyyEvent);
                calledItemDefinitionPropertyyEvent = true;
            };
            treeMap.SetValue(TreeMap.ItemDefinitionProperty, definitionNew);
            Assert.IsTrue(calledItemDefinitionPropertyyEvent);

            // Test ItemsSourceProperty
            int[] itemsNew = new int[] { 1, 2, 3 };

            bool calledItemsSourceProperty = false;
            treeMap.OnItemsSourcePropertyChangedEvent += (oldValue, newValue) =>
            {
                Assert.AreEqual(oldValue, itemsOld);
                Assert.AreEqual(newValue, itemsNew);
                Assert.AreNotEqual(newValue, oldValue);
                Assert.AreNotEqual(newValue, oldValue);
                Assert.IsFalse(calledItemsSourceProperty);
                calledItemsSourceProperty = true;
            };
            treeMap.SetValue(TreeMap.ItemsSourceProperty, itemsNew);
            Assert.IsTrue(calledItemsSourceProperty);

            // Test InterpolatorsPropertyChanged
            Collection<Interpolator> collectionNew = new Collection<Interpolator> { new SolidColorBrushInterpolator() };

            bool calledOnInterpolatorsPropertyChangedEvent = false;
            treeMap.OnInterpolatorsPropertyChangedEvent += (oldValue, newValue) =>
            {
                Assert.AreEqual(oldValue, collectionOld);
                Assert.AreEqual(newValue, collectionNew);
                Assert.IsFalse(calledOnInterpolatorsPropertyChangedEvent);
                calledOnInterpolatorsPropertyChangedEvent = true;
            };
            treeMap.SetValue(TreeMap.InterpolatorsProperty, collectionNew);
            Assert.IsTrue(calledOnInterpolatorsPropertyChangedEvent);
        }
 public void ChangingContentsOfNestedObservableCollectionUpdatesTreeMap()
 {
     TreeMap treeMap = new TreeMap();
     TreeMapItemDefinition itemDefinition = new TreeMapItemDefinition
     {
         ValueBinding = new Binding(),
         ItemsSource = new Binding("Value"),
     };
     itemDefinition.ItemTemplate = (DataTemplate)XamlReader.Load(SimpleItemTemplate);
     treeMap.ItemDefinition = itemDefinition;
     ObservableCollection<int> nestedItemsSourceA = new ObservableCollection<int>();
     ObservableCollection<int> nestedItemsSourceB = new ObservableCollection<int>();
     treeMap.ItemsSource = new KeyValuePair<int, ObservableCollection<int>>[]
     {
         new KeyValuePair<int, ObservableCollection<int>>(0, nestedItemsSourceA),
         new KeyValuePair<int, ObservableCollection<int>>(0, nestedItemsSourceB),
     };
     TestAsync(
         treeMap,
         // +1 because of the Border in default template
         () => Assert.AreEqual(0 + 2 + 1, treeMap.GetVisualDescendents().OfType<Border>().Count()),
         () => nestedItemsSourceA.Add(1),
         () => Assert.AreEqual(1 + 2 + 1, treeMap.GetVisualDescendents().OfType<Border>().Count()),
         () => nestedItemsSourceB.Add(2),
         () => Assert.AreEqual(2 + 2 + 1, treeMap.GetVisualDescendents().OfType<Border>().Count()),
         () => nestedItemsSourceA.Add(3),
         () => Assert.AreEqual(3 + 2 + 1, treeMap.GetVisualDescendents().OfType<Border>().Count()),
         () => nestedItemsSourceB.Clear(),
         () => Assert.AreEqual(2 + 2 + 1, treeMap.GetVisualDescendents().OfType<Border>().Count()),
         () => nestedItemsSourceA.Clear(),
         () => Assert.AreEqual(0 + 2 + 1, treeMap.GetVisualDescendents().OfType<Border>().Count()));
 }
 public void ChangingTreeMapItemDefinitionItemsSourceUpdatesTreeMap()
 {
     TreeMap treeMap = new TreeMap();
     TreeMapItemDefinition itemDefinition = new TreeMapItemDefinition { ValueBinding = new Binding() };
     itemDefinition.ItemTemplate = (DataTemplate)XamlReader.Load(SimpleItemTemplate);
     treeMap.ItemDefinition = itemDefinition;
     treeMap.ItemsSource = new KeyValuePair<int, int[]>[] { new KeyValuePair<int, int[]>(1, new int[] { 2, 3, 4, 5 }) };
     TestAsync(
         treeMap,
         // +1 because of the Border in default template
         () => Assert.AreEqual(1 + 1, treeMap.GetVisualDescendents().OfType<Border>().Count()),
         () => itemDefinition.ItemsSource = new Binding("Value"),
         () => Assert.AreEqual(5 + 1, treeMap.GetVisualDescendents().OfType<Border>().Count()));
 }
 /// <summary>
 /// Called when the value of the ItemDefinitionProperty property changes.
 /// Triggers a recalculation of the layout.
 /// </summary>
 /// <param name="oldValue">The old item definition.</param>
 /// <param name="newValue">The new item definition.</param>
 protected virtual void OnItemDefinitionPropertyChanged(TreeMapItemDefinition oldValue, TreeMapItemDefinition newValue)
 {
     RebuildTree();
 }