Example #1
0
        /// <summary>
        /// If the DataRangeBinding property is set then this method updates the minimum/maximum range
        /// of this object by including the value passed in.
        /// </summary>
        /// <param name="data">Object to extract the value from (the Source of the DataRangeBinding).</param>
        internal virtual void IncludeInRange(object data)
        {
            if (DataRangeBinding != null)
            {
                if (!Double.IsNaN(DataMinimum) && !Double.IsNaN(DataMaximum))
                {
                    return;
                }

                IConvertible input = _helper.RetrieveProperty(data, DataRangeBinding) as IConvertible;
                if (input == null)
                {
                    throw new ArgumentException(
                              Properties.Resources.Interpolator_IncludeInRange_DataRangeBindingNotIConvertible);
                }

                double value = input.ToDouble(CultureInfo.InvariantCulture);
                if (Double.IsNaN(DataMinimum) && value < ActualDataMinimum)
                {
                    ActualDataMinimum = value;
                }

                if (Double.IsNaN(DataMaximum) && value > ActualDataMaximum)
                {
                    ActualDataMaximum = value;
                }
            }
        }
Example #2
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);
        }