Base class of panel that has polymorphic layout/animate strategy.
Inheritance: System.Windows.Controls.Panel
Exemplo n.º 1
0
        /// <summary>
        /// Calculate target state for each element based on layout algorithm.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        public override void TargetChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            if (_count > 0)
            {
                // Each child is an equal angle around the radius
                double angleCurrent = StartAngle;
                double diff         = (EndAngle - StartAngle);
                double angleDelta   = diff / ((diff == (double)360) ? _count : _count - 1);

                // Calculate the radius separately for each dimension
                double radiusX = (finalSize.Width - _maxLength * 2) / 2;
                double radiusY = (finalSize.Height - _maxLength * 2) / 2;

                // Do we force into being a circle?
                if (Circle)
                {
                    // Always reduce to using the smallest direction
                    radiusX = Math.Min(radiusX, radiusY);
                    radiusY = radiusX;
                }

                // Rotate around the center point
                Point center = new Point(finalSize.Width / 2, finalSize.Height / 2);

                // Calculate the target rectangle for each element
                foreach (UIElement element in elements)
                {
                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // We ignore items that are collapsed
                        if (element.Visibility != Visibility.Collapsed)
                        {
                            // Rotate around the center point using the accumulated angle
                            double childX = center.X + Math.Cos(2 * Math.PI * angleCurrent / 360) * radiusX;
                            double childY = center.Y + Math.Sin(2 * Math.PI * angleCurrent / 360) * radiusY;
                            angleCurrent += angleDelta;

                            // Position the element at
                            Size desiredSize   = element.DesiredSize;
                            Rect newTargetRect = new Rect(childX - desiredSize.Width / 2,
                                                          childY - desiredSize.Height / 2,
                                                          desiredSize.Width,
                                                          desiredSize.Height);

                            // Store the new target rectangle
                            if (!stateDict[element].TargetRect.Equals(newTargetRect))
                            {
                                stateDict[element].TargetChanged = true;
                                stateDict[element].TargetRect    = newTargetRect;
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Perform animation effects on the set of children.
        /// </summary>
        /// <param name="animateId">Identifier of the animate to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be animated.</param>
        /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
        public override void ApplyAnimation(string animateId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            double elapsedMilliseconds)
        {
            // Only apply if we match the incoming animate identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(animateId))
            {
                foreach (UIElement element in elements)
                {
                    MetaElementState elementState = stateDict[element];

                    // If this is a new element that has not had its current rectangle set
                    if ((elementState.Status == MetaElementStatus.New) && elementState.NewCalculating)
                    {
                        elementState.CurrentRect = RectFromSize(Size, RectFromLocation(Location, metaPanel, elementState), elementState);
                        elementState.TargetChanged = true;
                        elementState.AnimateComplete = false;
                    }
                }
            }

            // Let base class take care of easing animations
            base.ApplyAnimation(animateId, metaPanel, stateDict, elements, elapsedMilliseconds);
        }
        /// <summary>
        /// Perform animation effects on the set of children.
        /// </summary>
        /// <param name="animateId">Identifier of the animate to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be animated.</param>
        /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
        public override void ApplyAnimation(string animateId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            double elapsedMilliseconds)
        {
            // Only apply if we match the incoming animate identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(animateId))
            {
                foreach (UIElement element in elements)
                {
                    MetaElementState elementState = stateDict[element];

                    // Only interested in elements being removed...
                    if (elementState.Status == MetaElementStatus.Removing)
                    {
                        // ...and having the final target rectangle calculated just the once...
                        if (!elementState.RemoveCalculated)
                        {
                            // Calculate the correct target rectangle
                            Rect positionRect = RectFromSize(Size, RectFromLocation(Location, metaPanel, elementState), elementState);

                            // Update the final target value
                            elementState.TargetRect      = positionRect;
                            elementState.TargetChanged   = true;
                            elementState.AnimateComplete = false;
                        }
                    }
                }
            }

            // Let base class take care of easing animations
            base.ApplyAnimation(animateId, metaPanel, stateDict, elements, elapsedMilliseconds);
        }
        /// <summary>
        /// Perform animation effects on the set of children.
        /// </summary>
        /// <param name="animateId">Identifier of the animate to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be animated.</param>
        /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
        public override void ApplyAnimation(string animateId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            double elapsedMilliseconds)
        {
            // Only apply if we match the incoming animate identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(animateId))
            {
                foreach (UIElement element in elements)
                {
                    MetaElementState elementState = stateDict[element];

                    // Only interested in elements being removed...
                    if (elementState.Status == MetaElementStatus.Removing)
                    {
                        // ...and having the final target rectangle calculated just the once...
                        if (!elementState.RemoveCalculated)
                        {
                            // Calculate the correct target rectangle
                            Rect positionRect = RectFromSize(Size, RectFromLocation(Location, metaPanel, elementState), elementState);

                            // Update the final target value
                            elementState.TargetRect = positionRect;
                            elementState.TargetChanged = true;
                            elementState.AnimateComplete = false;
                        }
                    }
                }
            }

            // Let base class take care of easing animations
            base.ApplyAnimation(animateId, metaPanel, stateDict, elements, elapsedMilliseconds);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Invoked when a property change requires a measure to occur.
        /// </summary>
        /// <param name="d">Owning object.</param>
        /// <param name="e">Details of property that has changed.</param>
        protected static void OnNeedMeasureOnChanged(DependencyObject d,
                                                     DependencyPropertyChangedEventArgs e)
        {
            MetaPanelBase sender = (MetaPanelBase)d;

            sender.OnNeedMeasure(sender, EventArgs.Empty);
        }
Exemplo n.º 6
0
 /// <summary>
 /// Calculate target state for each element based on layout algorithm.
 /// </summary>
 /// <param name="layoutId">Identifier of the layout to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be arranged.</param>
 /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
 public override void TargetChildren(string layoutId,
                                     MetaPanelBase metaPanel,
                                     MetaElementStateDict stateDict,
                                     ICollection elements,
                                     Size finalSize)
 {
     // Only apply if we match the incoming layout identifier
     if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
     {
         Rect newTargetRect = new Rect(Utility.PointZero, finalSize);
         foreach (UIElement element in elements)
         {
             // We ignore items being removed
             if (stateDict[element].Status != MetaElementStatus.Removing)
             {
                 // Store the new target rectangle
                 if (!stateDict[element].TargetRect.Equals(newTargetRect))
                 {
                     stateDict[element].TargetChanged = true;
                     stateDict[element].TargetRect    = newTargetRect;
                 }
             }
         }
     }
 }
Exemplo n.º 7
0
        /// <summary>
        /// Perform animation effects on the set of children.
        /// </summary>
        /// <param name="animateId">Identifier of the animate to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be animated.</param>
        /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
        public override void ApplyAnimation(string animateId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            double elapsedMilliseconds)
        {
            // Only apply if we match the incoming animate identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(animateId))
            {
                foreach (UIElement element in elements)
                {
                    MetaElementState elementState = stateDict[element];

                    // If this is a new element that has not had its current rectangle set
                    if ((elementState.Status == MetaElementStatus.New) && elementState.NewCalculating)
                    {
                        elementState.CurrentRect     = RectFromSize(Size, RectFromLocation(Location, metaPanel, elementState), elementState);
                        elementState.TargetChanged   = true;
                        elementState.AnimateComplete = false;
                    }
                }
            }

            // Let base class take care of easing animations
            base.ApplyAnimation(animateId, metaPanel, stateDict, elements, elapsedMilliseconds);
        }
Exemplo n.º 8
0
 /// <summary>
 /// Calculate target state for each element based on layout algorithm.
 /// </summary>
 /// <param name="layoutId">Identifier of the layout to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be arranged.</param>
 /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
 public override void TargetChildren(string layoutId,
                                     MetaPanelBase metaPanel,
                                     MetaElementStateDict stateDict,
                                     ICollection elements,
                                     Size finalSize)
 {
     // Only apply if we match the incoming layout identifier
     if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
     {
         Rect newTargetRect = new Rect(Utility.PointZero, finalSize);
         foreach (UIElement element in elements)
         {
             // We ignore items being removed
             if (stateDict[element].Status != MetaElementStatus.Removing)
             {
                 // Store the new target rectangle
                 if (!stateDict[element].TargetRect.Equals(newTargetRect))
                 {
                     stateDict[element].TargetChanged = true;
                     stateDict[element].TargetRect = newTargetRect;
                 }
             }
         }
     }
 }
Exemplo n.º 9
0
        private static void OnIsAnimatingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MetaPanelBase metaPanelBase = (MetaPanelBase)d;

            // By always requesting a panel measure when the Rendering event is
            // fired we ensure that the panel invokes the animation instances and
            // the child elements are updated until the animation ends.
            if ((bool)e.NewValue)
            {
                // Reset the last ticks as we do not want to use the duration since the
                // last time animation finished, which might have been a long time ago
                metaPanelBase._lastTicks = -1;

                // This event is fired just before rendering of each display frame
                CompositionTarget.Rendering += new EventHandler(metaPanelBase.OnRendering);
            }
            else
            {
                CompositionTarget.Rendering -= new EventHandler(metaPanelBase.OnRendering);
            }

            // Raise the changed event
            EventHandler handler = metaPanelBase.IsAnimatingChanged;

            if (handler != null)
            {
                handler(metaPanelBase, EventArgs.Empty);
            }
        }
Exemplo n.º 10
0
 /// <summary>
 /// Perform animation effects on the set of children.
 /// </summary>
 /// <param name="animateId">Identifier of the animate to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be animated.</param>
 /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
 public override void ApplyAnimation(string animateId,
                                     MetaPanelBase metaPanel,
                                     MetaElementStateDict stateDict,
                                     ICollection elements,
                                     double elapsedMilliseconds)
 {
     ApplyAnimation(animateId, metaPanel, stateDict, elements, elapsedMilliseconds, Start, End);
 }
Exemplo n.º 11
0
        /// <summary>
        /// Calculate target state for each element based on layout algorithm.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        public override void TargetChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Calculate the target rectangle for each element
                foreach (UIElement element in elements)
                {
                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // Default to being the desired size but at position zero,zero
                        Rect newTargetRect = new Rect(0, 0, element.DesiredSize.Width, element.DesiredSize.Height);

                        // Use the Left or Right value provided as attached properties of the element
                        double left = CanvasLayout.GetLeft(element);
                        if (!double.IsNaN(left))
                        {
                            newTargetRect.X = left;
                        }
                        else
                        {
                            double right = CanvasLayout.GetRight(element);
                            if (!double.IsNaN(right))
                            {
                                newTargetRect.X = (finalSize.Width - element.DesiredSize.Width) - right;
                            }
                        }

                        // Use the Top or Bottom value provided as attached properties of the element
                        double top = CanvasLayout.GetTop(element);
                        if (!double.IsNaN(top))
                        {
                            newTargetRect.Y = top;
                        }
                        else
                        {
                            double bottom = CanvasLayout.GetBottom(element);
                            if (!double.IsNaN(bottom))
                            {
                                newTargetRect.Y = (finalSize.Height - element.DesiredSize.Height) - bottom;
                            }
                        }

                        // Store the new target rectangle
                        if (!stateDict[element].TargetRect.Equals(newTargetRect))
                        {
                            stateDict[element].TargetChanged = true;
                            stateDict[element].TargetRect    = newTargetRect;
                        }
                    }
                }
            }
        }
Exemplo n.º 12
0
 /// <summary>
 /// Calculate target state for each element based on layout algorithm.
 /// </summary>
 /// <param name="layoutId">Identifier of the layout to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be arranged.</param>
 /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
 public void TargetChildren(string layoutId,
                            MetaPanelBase metaPanel,
                            MetaElementStateDict stateDict,
                            ICollection elements,
                            Size finalSize)
 {
     foreach (Layout layout in this)
     {
         layout.TargetChildren(layoutId, metaPanel, stateDict, elements, finalSize);
     }
 }
Exemplo n.º 13
0
        /// <summary>
        /// Perform animation effects on the set of children.
        /// </summary>
        /// <param name="animateId">Identifier of the animate to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be animated.</param>
        /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
        /// <param name="startOpacity">Opacity for start of animation.</param>
        /// <param name="endOpacity">Opacity for end of animation.</param>
        public void ApplyAnimation(string animateId,
                                   MetaPanelBase metaPanel,
                                   MetaElementStateDict stateDict,
                                   ICollection elements,
                                   double elapsedMilliseconds,
                                   double startOpacity,
                                   double endOpacity)
        {
            // Only apply if we match the incoming animate identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(animateId))
            {
                // Only grab the dependancy properties once, for improved perf
                double duration = Duration;

                foreach (UIElement element in elements)
                {
                    // Only apply animation to element of required target state
                    MetaElementState elementState = stateDict[element];
                    if (elementState.Status == Target)
                    {
                        // If the element is the correct target and correct status for starting animation
                        if ((!elementState.RemoveCalculated && (Target == MetaElementStatus.Removing)) ||
                            (elementState.NewCalculating && (Target == MetaElementStatus.New)))
                        {
                            // Use the starting opacity
                            element.Opacity = startOpacity;
                            elementState.ElapsedOpacityTime = 0;
                        }
                        else
                        {
                            // Only perform animation if some time has actually ellapsed and not already at target
                            if ((elapsedMilliseconds > 0) && (element.Opacity != (double)endOpacity))
                            {
                                // Add new elapsed time to the animation running time
                                elementState.ElapsedOpacityTime += elapsedMilliseconds;

                                // Does elapsed time indicate animation should have completed?
                                if (elementState.ElapsedOpacityTime >= duration)
                                {
                                    element.Opacity = endOpacity;
                                }
                                else
                                {
                                    element.Opacity = EasingCalculation.Calculate(elementState.ElapsedOpacityTime, startOpacity, endOpacity - startOpacity, duration);
                                }
                            }
                        }

                        // If not yet at target opacity then not finished with animating
                        elementState.AnimateComplete &= (element.Opacity == (double)endOpacity);
                    }
                }
            }
        }
Exemplo n.º 14
0
 /// <summary>
 /// Perform animation effects on the set of children.
 /// </summary>
 /// <param name="animateId">Identifier of the animate to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be animated.</param>
 /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
 public void ApplyAnimation(string animateId,
                            MetaPanelBase metaPanel,
                            MetaElementStateDict stateDict,
                            ICollection elements,
                            double elapsedMilliseconds)
 {
     foreach (Animate animate in this)
     {
         animate.ApplyAnimation(animateId, metaPanel, stateDict, elements, elapsedMilliseconds);
     }
 }
Exemplo n.º 15
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Measure each element in turn
                _validCount = 0;
                Size usedSize = new Size();
                Size maxSize  = new Size();
                foreach (UIElement element in elements)
                {
                    // Allow element to have all the remainder size available
                    Size elementSize = new Size(Math.Max(0.0, (double)(availableSize.Width - usedSize.Width)),
                                                Math.Max(0.0, (double)(availableSize.Height - usedSize.Height)));

                    element.Measure(elementSize);

                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // Discover the used size and the maximum required size for opposite direction
                        Size desiredSize = element.DesiredSize;
                        switch (GetDock(element))
                        {
                        case Dock.Left:
                        case Dock.Right:
                            maxSize.Height  = Math.Max(maxSize.Height, usedSize.Height + desiredSize.Height);
                            usedSize.Width += desiredSize.Width;
                            break;

                        case Dock.Top:
                        case Dock.Bottom:
                            maxSize.Width    = Math.Max(maxSize.Width, usedSize.Width + desiredSize.Width);
                            usedSize.Height += desiredSize.Height;
                            break;
                        }

                        _validCount++;
                    }
                }

                return(new Size(Math.Max(maxSize.Width, usedSize.Width),
                                Math.Max(maxSize.Height, usedSize.Height)));
            }
            else
            {
                return(Size.Empty);
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Cache the dependancy properties for faster perf
                Orientation orientation = Orientation;

                // Give children as much space as they want in the opposite direction to the stacking
                if (orientation == Orientation.Horizontal)
                {
                    availableSize.Width = double.PositiveInfinity;
                }
                else
                {
                    availableSize.Height = double.PositiveInfinity;
                }

                // Measure each element in turn
                Size measureSize = new Size();
                foreach (UIElement element in elements)
                {
                    element.Measure(availableSize);

                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // Accumulate in the orientation direction, but track maximum value in the opposite
                        if (orientation == Orientation.Horizontal)
                        {
                            measureSize.Width += element.DesiredSize.Width;
                            measureSize.Height = Math.Max(measureSize.Height, element.DesiredSize.Height);
                        }
                        else
                        {
                            measureSize.Width   = Math.Max(measureSize.Width, element.DesiredSize.Width);
                            measureSize.Height += element.DesiredSize.Height;
                        }
                    }
                }

                return(measureSize);
            }
            else
            {
                return(Size.Empty);
            }
        }
Exemplo n.º 17
0
 /// <summary>
 /// Calculate target state for each element based on layout algorithm.
 /// </summary>
 /// <param name="layoutId">Identifier of the layout to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be arranged.</param>
 /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
 public override void TargetChildren(string layoutId,
                                     MetaPanelBase metaPanel,
                                     MetaElementStateDict stateDict,
                                     ICollection elements,
                                     Size finalSize)
 {
     // Only apply if we match the incoming layout identifier
     if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
     {
         // TODO target elements that are not in tree drawing
         TargetTreeNodes(Utility.PointZero, StartNode, stateDict, false);
     }
 }
Exemplo n.º 18
0
        /// <summary>
        /// Calculate target state for each element based on layout algorithm.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        public override void TargetChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Find the size of each size and start at the top left cell
                Rect cellRect = new Rect(0, 0, finalSize.Width / (double)_columns, finalSize.Height / (double)_rows);

                // Move across to the defined starting column
                cellRect.X += cellRect.Width * FirstColumn;

                // Calculate the right hand side where we need to start a new row
                double finalSizeRight = finalSize.Width - 1.0;

                // Calculate the target rectangle for each element
                foreach (UIElement element in elements)
                {
                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // We ignore items that are collapsed from view
                        if (element.Visibility != Visibility.Collapsed)
                        {
                            // The new target is the current cell rect
                            Rect newTargetRect = cellRect;

                            // Move across to next column
                            cellRect.X += cellRect.Width;

                            // Do we start a line row?
                            if (cellRect.X >= finalSizeRight)
                            {
                                cellRect.X  = 0;
                                cellRect.Y += cellRect.Height;
                            }

                            // Store the new target rectangle
                            if (!stateDict[element].TargetRect.Equals(newTargetRect))
                            {
                                stateDict[element].TargetChanged = true;
                                stateDict[element].TargetRect    = newTargetRect;
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Perform animation effects on the set of children.
        /// </summary>
        /// <param name="animateId">Identifier of the animate to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be animated.</param>
        /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
        /// <param name="startOpacity">Opacity for start of animation.</param>
        /// <param name="endOpacity">Opacity for end of animation.</param>
        public void ApplyAnimation(string animateId,
                                   MetaPanelBase metaPanel,
                                   MetaElementStateDict stateDict,
                                   ICollection elements,
                                   double elapsedMilliseconds,
                                   double startOpacity,
                                   double endOpacity)
        {
            // Only apply if we match the incoming animate identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(animateId))
            {
                // Only grab the dependancy properties once, for improved perf
                double duration = Duration;

                foreach (UIElement element in elements)
                {
                    // Only apply animation to element of required target state
                    MetaElementState elementState = stateDict[element];
                    if (elementState.Status == Target)
                    {
                        // If the element is the correct target and correct status for starting animation
                        if ((!elementState.RemoveCalculated && (Target == MetaElementStatus.Removing)) ||
                            (elementState.NewCalculating && (Target == MetaElementStatus.New)))
                        {
                            // Use the starting opacity
                            element.Opacity = startOpacity;
                            elementState.ElapsedOpacityTime = 0;
                        }
                        else
                        {
                            // Only perform animation if some time has actually ellapsed and not already at target
                            if ((elapsedMilliseconds > 0) && (element.Opacity != (double)endOpacity))
                            {
                                // Add new elapsed time to the animation running time
                                elementState.ElapsedOpacityTime += elapsedMilliseconds;

                                // Does elapsed time indicate animation should have completed?
                                if (elementState.ElapsedOpacityTime >= duration)
                                    element.Opacity = endOpacity;
                                else
                                    element.Opacity = EasingCalculation.Calculate(elementState.ElapsedOpacityTime, startOpacity, endOpacity - startOpacity, duration);
                            }
                        }

                        // If not yet at target opacity then not finished with animating
                        elementState.AnimateComplete &= (element.Opacity == (double)endOpacity);
                    }
                }
            }
        }
Exemplo n.º 20
0
        private static void OnWrapChanged(DependencyObject d,
                                          DependencyPropertyChangedEventArgs e)
        {
            UIElement element = d as UIElement;

            if (element != null)
            {
                MetaPanelBase parent = VisualTreeHelper.GetParent(element) as MetaPanelBase;
                if (parent != null)
                {
                    parent.InvalidateMeasure();
                }
            }
        }
Exemplo n.º 21
0
        /// <summary>
        /// Position child elements according to already calculated target state.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        /// <returns>Size used by the layout panel.</returns>
        public Size ArrangeChildren(string layoutId,
                                    MetaPanelBase metaPanel,
                                    MetaElementStateDict stateDict,
                                    ICollection elements,
                                    Size finalSize)
        {
            foreach (UIElement element in elements)
            {
                MetaElementState elementState = stateDict[element];
                elementState.Element.Arrange(elementState.CurrentRect);
            }

            // Layout panel takes all the provided size
            return(finalSize);
        }
Exemplo n.º 22
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // TODO measure elements that are not in tree drawing
                return MeasureTreeNodes(StartNode, stateDict, false);
            }

            return Size.Empty;
        }
Exemplo n.º 23
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // TODO measure elements that are not in tree drawing
                return(MeasureTreeNodes(StartNode, stateDict, false));
            }

            return(Size.Empty);
        }
Exemplo n.º 24
0
 /// <summary>
 /// Perform animation effects on the set of children.
 /// </summary>
 /// <param name="animateId">Identifier of the animate to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be animated.</param>
 /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
 public override void ApplyAnimation(string animateId,
                                     MetaPanelBase metaPanel,
                                     MetaElementStateDict stateDict,
                                     ICollection elements,
                                     double elapsedMilliseconds)
 {
     // Only apply if we match the incoming animate identifier
     if (string.IsNullOrEmpty(Id) || Id.Equals(animateId))
     {
         foreach (UIElement element in elements)
         {
             // Immediately move to the target rectangle
             MetaElementState elementState = stateDict[element];
             elementState.CurrentRect = elementState.TargetRect;
         }
     }
 }
Exemplo n.º 25
0
 /// <summary>
 /// Perform animation effects on the set of children.
 /// </summary>
 /// <param name="animateId">Identifier of the animate to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be animated.</param>
 /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
 public override void ApplyAnimation(string animateId,
                                     MetaPanelBase metaPanel,
                                     MetaElementStateDict stateDict,
                                     ICollection elements,
                                     double elapsedMilliseconds)
 {
     // Only apply if we match the incoming animate identifier
     if (string.IsNullOrEmpty(Id) || Id.Equals(animateId))
     {
         foreach (UIElement element in elements)
         {
             // Immediately move to the target rectangle
             MetaElementState elementState = stateDict[element];
             elementState.CurrentRect = elementState.TargetRect;
         }
     }
 }
Exemplo n.º 26
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Cache the dependancy properties for faster perf
                Orientation orientation = Orientation;

                // Give children as much space as they want in the opposite direction to the stacking
                if (orientation == Orientation.Horizontal)
                    availableSize.Width = double.PositiveInfinity;
                else
                    availableSize.Height = double.PositiveInfinity;

                // Measure each element in turn
                Size measureSize = new Size();
                foreach (UIElement element in elements)
                {
                    element.Measure(availableSize);

                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // Accumulate in the orientation direction, but track maximum value in the opposite
                        if (orientation == Orientation.Horizontal)
                        {
                            measureSize.Width += element.DesiredSize.Width;
                            measureSize.Height = Math.Max(measureSize.Height, element.DesiredSize.Height);
                        }
                        else
                        {
                            measureSize.Width = Math.Max(measureSize.Width, element.DesiredSize.Width);
                            measureSize.Height += element.DesiredSize.Height;
                        }
                    }
                }

                return measureSize;
            }
            else
                return Size.Empty;
        }
Exemplo n.º 27
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Measure each element in turn
                foreach (UIElement element in elements)
                {
                    stateDict[element].Element.Measure(Utility.SizeInfinity);
                }
            }

            // Return an empty size
            return(Size.Empty);
        }
Exemplo n.º 28
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public Size MeasureChildren(string layoutId,
                                    MetaPanelBase metaPanel,
                                    MetaElementStateDict stateDict,
                                    ICollection elements,
                                    Size availableSize)
        {
            Size retSize = new Size();

            foreach (Layout layout in this)
            {
                Size layoutSize = layout.MeasureChildren(layoutId, metaPanel, stateDict, elements, availableSize);

                // Find the largest requested size
                retSize.Width  = Math.Max(retSize.Width, layoutSize.Width);
                retSize.Height = Math.Max(retSize.Height, layoutSize.Height);
            }

            return(retSize);
        }
Exemplo n.º 29
0
        /// <summary>
        /// Calculate target state for each element based on layout algorithm.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        public override void TargetChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Cache the dependancy properties for faster perf
                Orientation orientation = Orientation;

                // Calculate the target rectangle for each element
                double offset = 0;
                foreach (UIElement element in elements)
                {
                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        Rect newTargetRect;

                        // Updating the elements target rectangle depends on orientation
                        if (orientation == Orientation.Horizontal)
                        {
                            newTargetRect = new Rect(offset, 0, element.DesiredSize.Width, Math.Max(finalSize.Height, element.DesiredSize.Height));
                            offset       += element.DesiredSize.Width;
                        }
                        else
                        {
                            newTargetRect = new Rect(0, offset, Math.Max(finalSize.Width, element.DesiredSize.Width), element.DesiredSize.Height);
                            offset       += element.DesiredSize.Height;
                        }

                        // Store the new target rectangle
                        if (!stateDict[element].TargetRect.Equals(newTargetRect))
                        {
                            stateDict[element].TargetChanged = true;
                            stateDict[element].TargetRect    = newTargetRect;
                        }
                    }
                }
            }
        }
Exemplo n.º 30
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Calculate number of rows and columns needed to show all children
                UpdateRowsColumns(stateDict, elements);

                // Each element should be equal sized according to grid cell size
                Size elementSize = new Size(availableSize.Width / (double)_columns,
                                            availableSize.Height / (double)_rows);

                // Measure each element in turn
                double widest  = 0;
                double tallest = 0;
                foreach (UIElement element in elements)
                {
                    element.Measure(elementSize);
                    if (element.Visibility != Visibility.Collapsed)
                    {
                        // We ignore items being removed
                        if (stateDict[element].Status != MetaElementStatus.Removing)
                        {
                            // Track widest/tallest for calculating cell size later
                            widest  = Math.Max(widest, element.DesiredSize.Width);
                            tallest = Math.Max(tallest, element.DesiredSize.Height);
                        }
                    }
                }

                // We would like a size that ensures each cell is big enough for the biggest child
                return(new Size(_columns * widest, _rows * tallest));
            }
            else
            {
                return(Size.Empty);
            }
        }
Exemplo n.º 31
0
        /// <summary>
        /// Position child elements according to already calculated target state.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        /// <returns>Size used by the layout panel.</returns>
        public virtual Size ArrangeChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Position each element
                foreach (UIElement element in elements)
                {
                    MetaElementState elementState = stateDict[element];
                    elementState.Element.Arrange(elementState.CurrentRect);
                }
            }

            // Layout panel takes all the provided size
            return(finalSize);
        }
Exemplo n.º 32
0
        /// <summary>
        /// Position child elements according to already calculated target state.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        /// <returns>Size used by the layout panel.</returns>
        public virtual Size ArrangeChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Position each element
                foreach (UIElement element in elements)
                {
                    MetaElementState elementState = stateDict[element];
                    elementState.Element.Arrange(elementState.CurrentRect);
                }
            }

            // Layout panel takes all the provided size
            return finalSize;
        }
Exemplo n.º 33
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            Size retSize = new Size();

            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                foreach (UIElement element in elements)
                {
                    stateDict[element].Element.Measure(availableSize);
                    retSize.Width  = Math.Max(retSize.Width, stateDict[element].Element.DesiredSize.Width);
                    retSize.Height = Math.Max(retSize.Height, stateDict[element].Element.DesiredSize.Height);
                }
            }

            return(retSize);
        }
Exemplo n.º 34
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            Size retSize = new Size();

            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                foreach (UIElement element in elements)
                {
                    stateDict[element].Element.Measure(availableSize);
                    retSize.Width = Math.Max(retSize.Width, stateDict[element].Element.DesiredSize.Width);
                    retSize.Height = Math.Max(retSize.Height, stateDict[element].Element.DesiredSize.Height);
                }
            }

            return retSize;
        }
Exemplo n.º 35
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Measure each element in turn
            _count = 0;
            Size maxSize = new Size();

            foreach (UIElement element in elements)
            {
                if (element != null)
                {
                    element.Measure(Utility.SizeInfinity);

                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // We ignore items that are collapsed
                        if (element.Visibility != Visibility.Collapsed)
                        {
                            // Find the widest and tallest element
                            maxSize.Width  = Math.Max(maxSize.Width, element.DesiredSize.Width);
                            maxSize.Height = Math.Max(maxSize.Height, element.DesiredSize.Height);

                            // Count number of valid elements
                            _count++;
                        }
                    }
                }
            }

            // Max length is the diagonal length of biggest element
            _maxLength = Math.Sqrt((maxSize.Width * maxSize.Width) + (maxSize.Height * maxSize.Height));

            // Always use the provided size
            return(availableSize);
        }
Exemplo n.º 36
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            Size retSize = new Size();

            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // If there are no column/row definitions then size to available area
                if ((_columns.Count == 0) && (_rows.Count == 0))
                {
                    foreach (UIElement element in elements)
                    {
                        stateDict[element].Element.Measure(availableSize);
                        retSize.Width  = Math.Max(retSize.Width, stateDict[element].Element.DesiredSize.Width);
                        retSize.Height = Math.Max(retSize.Height, stateDict[element].Element.DesiredSize.Height);
                    }
                }
                else
                {
                    BuildProxyColumns();
                    BuildProxyRows();
                    PreMeasure(availableSize);
                    MeasureElements(stateDict, elements);
                    UpdateDefinitions(stateDict, elements, false);
                    UpdateDefinitions(stateDict, elements, true);
                    CalculateOffsetsAndTotals();
                    retSize = CalculateDesiredSize(stateDict, elements, availableSize);
                }
            }

            return(retSize);
        }
Exemplo n.º 37
0
        /// <summary>
        /// Calculate target state for each element based on layout algorithm.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        public override void TargetChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Calculate the target rectangle for each element
                foreach (UIElement element in elements)
                {
                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // Default to being the desired size but at position zero,zero
                        Rect newTargetRect = new Rect(0, 0, element.DesiredSize.Width, element.DesiredSize.Height);

                        // Use the Left or Right value provided as attached properties of the element
                        double left = CanvasLayout.GetLeft(element);
                        if (!double.IsNaN(left))
                            newTargetRect.X = left;
                        else
                        {
                            double right = CanvasLayout.GetRight(element);
                            if (!double.IsNaN(right))
                                newTargetRect.X = (finalSize.Width - element.DesiredSize.Width) - right;
                        }

                        // Use the Top or Bottom value provided as attached properties of the element
                        double top = CanvasLayout.GetTop(element);
                        if (!double.IsNaN(top))
                            newTargetRect.Y = top;
                        else
                        {
                            double bottom = CanvasLayout.GetBottom(element);
                            if (!double.IsNaN(bottom))
                                newTargetRect.Y = (finalSize.Height - element.DesiredSize.Height) - bottom;
                        }

                        // Store the new target rectangle
                        if (!stateDict[element].TargetRect.Equals(newTargetRect))
                        {
                            stateDict[element].TargetChanged = true;
                            stateDict[element].TargetRect = newTargetRect;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Calculate appropriate rectangle from given current state and target location.
        /// </summary>
        /// <param name="location">Location enumeration.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="elementState">Animation state of element.</param>
        /// <returns>Calculated rectangle using provided location.</returns>
        protected Rect RectFromLocation(AnimateLocation location,
                                        MetaPanelBase metaPanel,
                                        MetaElementState elementState)
        {
            // Nearest edge is converted into a particular edge
            switch (location)
            {
                case AnimateLocation.NearestEdge:
                case AnimateLocation.NearestEdgePaged:
                    bool paged = (location == AnimateLocation.NearestEdgePaged);

                    // Find distance from each edge
                    double left = Math.Abs(elementState.TargetRect.Left);
                    double top = Math.Abs(elementState.TargetRect.Top);
                    double right = Math.Abs(metaPanel.ActualWidth - elementState.TargetRect.Right);
                    double bottom = Math.Abs(metaPanel.ActualHeight - elementState.TargetRect.Bottom);

                    // Find nearest distance for vertical and horizontal
                    double horz = (left < right ? left : right);
                    double vert = (top < bottom ? top : bottom);

                    // Is horizontal nearest?
                    if (horz <= vert)
                    {
                        // Is the left the nearest?
                        if (horz == left)
                            location = (paged ? AnimateLocation.LeftPaged : AnimateLocation.Left);
                        else
                            location = (paged ? AnimateLocation.RightPaged : AnimateLocation.Right);
                    }
                    else
                    {
                        // Is the top the nearest?
                        if (vert == top)
                            location = (paged ? AnimateLocation.TopPaged : AnimateLocation.Top);
                        else
                            location = (paged ? AnimateLocation.BottomPaged : AnimateLocation.Bottom);
                    }
                    break;
            }

            switch (location)
            {
                case AnimateLocation.Target:
                    return elementState.TargetRect;
                case AnimateLocation.Center:
                    return new Rect((metaPanel.ActualWidth / 2) - (elementState.TargetRect.Width - 2),
                                    (metaPanel.ActualHeight / 2) - (elementState.TargetRect.Height - 2),
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.Top:
                    return new Rect(elementState.TargetRect.X,
                                    -elementState.TargetRect.Height,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.TopPaged:
                    return new Rect(elementState.TargetRect.X,
                                    -metaPanel.ActualHeight + elementState.TargetRect.Y,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.Bottom:
                    return new Rect(elementState.TargetRect.X,
                                    metaPanel.ActualHeight,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.BottomPaged:
                    return new Rect(elementState.TargetRect.X,
                                    metaPanel.ActualHeight + elementState.TargetRect.Y,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.Left:
                    return new Rect(-elementState.TargetRect.Width,
                                    elementState.TargetRect.Y,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.LeftPaged:
                    return new Rect(-metaPanel.ActualWidth + elementState.TargetRect.X,
                                    elementState.TargetRect.Y,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.Right:
                    return new Rect(metaPanel.ActualWidth,
                                    elementState.TargetRect.Y,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.RightPaged:
                    return new Rect(metaPanel.ActualWidth + elementState.TargetRect.X,
                                    elementState.TargetRect.Y,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.TopLeft:
                    return new Rect(-elementState.TargetRect.Width,
                                    -elementState.TargetRect.Height,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.TopRight:
                    return new Rect(metaPanel.ActualWidth,
                                    -elementState.TargetRect.Height,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.BottomLeft:
                    return new Rect(-elementState.TargetRect.Width,
                                    metaPanel.ActualHeight,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.BottomRight:
                    return new Rect(metaPanel.ActualWidth,
                                    metaPanel.ActualHeight,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                default:
                    // Should never happen!
                    Debug.Assert(false);
                    return new Rect();
            }
        }
Exemplo n.º 39
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Cache the dependancy properties for faster perf
                double itemWidth = ItemWidth;
                double itemHeight = ItemHeight;
                Orientation orientation = Orientation;

                // Cache if the defined sizes are valid
                bool itemWidthDefined = !double.IsNaN(ItemWidth);
                bool itemHeightDefined = !double.IsNaN(itemHeight);

                // Find size we provide to each child for measuring against, we use item sizes if defined
                Size elementSize = new Size(itemWidthDefined ? itemWidth : double.PositiveInfinity,
                                            itemHeightDefined ? itemHeight : double.PositiveInfinity);

                // Measure each element in turn
                bool breakAfter = false;
                double lineMax = 0;
                double lineOffset = 0;
                Size measureSize = new Size();
                foreach (UIElement element in elements)
                {
                    element.Measure(elementSize);

                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // Decide on the actual size we will allocate to the element
                        Size childSize = new Size(itemWidthDefined ? itemWidth : element.DesiredSize.Width,
                                                  itemHeightDefined ? itemHeight : element.DesiredSize.Height);

                        // Calculation depends on orientation
                        if (orientation == Orientation.Horizontal)
                        {
                            // Does this element overflow the line?
                            if (breakAfter || (((lineOffset + childSize.Width) > availableSize.Width) && !measureSize.IsEmpty))
                            {
                                // Total measured size is equal to the widest line and tallest item per line
                                measureSize.Width = Math.Max(measureSize.Width, lineOffset);
                                measureSize.Height += lineMax;

                                // Start at the left edge of the next line
                                lineOffset = 0;
                                lineMax = 0;
                            }

                            // Position the child on the current line
                            lineOffset += childSize.Width;
                            lineMax = Math.Max(lineMax, childSize.Height);
                        }
                        else
                        {
                            // Does this element overflow the line?
                            if (breakAfter || (((lineOffset + childSize.Height) > availableSize.Height) && !measureSize.IsEmpty))
                            {
                                // Total measured size is equal to the tallest line and widest item per line
                                measureSize.Height = Math.Max(measureSize.Height, lineOffset);
                                measureSize.Width += lineMax;

                                // Start at the top edge of the next line
                                lineOffset = 0;
                                lineMax = 0;
                            }

                            // Position the child on the current line
                            lineOffset += childSize.Height;
                            lineMax = Math.Max(lineMax, childSize.Width);
                        }

                        // Do we perform a line break after this element
                        breakAfter = WrapLayout.GetBreakAfter(element);
                    }
                }

                // Remember to take into account the last line
                if (orientation == Orientation.Horizontal)
                {
                    // Total measured size is equal to the widest line and tallest item per line
                    measureSize.Width = Math.Max(measureSize.Width, lineOffset);
                    measureSize.Height += lineMax;
                }
                else
                {
                    // Total measured size is equal to the tallest line and widest item per line
                    measureSize.Height = Math.Max(measureSize.Height, lineOffset);
                    measureSize.Width += lineMax;
                }

                // Return minimum size needed to contain all the elements according to their desired sizes
                return measureSize;
            }
            else
                return Size.Empty;
        }
Exemplo n.º 40
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Measure each element in turn
                foreach (UIElement element in elements)
                    stateDict[element].Element.Measure(Utility.SizeInfinity);
            }

            // Return an empty size
            return Size.Empty;
        }
Exemplo n.º 41
0
 /// <summary>
 /// Measure the layout size required to arrange all elements.
 /// </summary>
 /// <param name="layoutId">Identifier of the layout to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be measured.</param>
 /// <param name="availableSize">Available size that can be given to elements.</param>
 /// <returns>Size the layout determines it needs based on child element sizes.</returns>
 public abstract Size MeasureChildren(string layoutId,
                                      MetaPanelBase metaPanel,
                                      MetaElementStateDict stateDict,
                                      ICollection elements,
                                      Size availableSize);
Exemplo n.º 42
0
        /// <summary>
        /// Calculate target state for each element based on layout algorithm.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        public override void TargetChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Cache the dependancy properties for faster perf
                double itemWidth = ItemWidth;
                double itemHeight = ItemHeight;
                Orientation orientation = Orientation;

                // Cache if the defined sizes are valid
                bool itemWidthDefined = !double.IsNaN(ItemWidth);
                bool itemHeightDefined = !double.IsNaN(itemHeight);

                // Find size we provide to each child for measuring against, we use item sizes if defined
                Size elementSize = new Size(itemWidthDefined ? itemWidth : double.PositiveInfinity,
                                            itemHeightDefined ? itemHeight : double.PositiveInfinity);

                // Measure each element in turn
                int current = 0;
                double lineOffset = 0;
                double lineMax = 0;
                double positionOffset = 0;
                bool breakAfter = false;
                List<UIElement> targets = new List<UIElement>();
                foreach (UIElement element in elements)
                {
                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // Decide on the actual size we will allocate to the element
                        Size childSize = new Size(itemWidthDefined ? itemWidth : element.DesiredSize.Width,
                                                  itemHeightDefined ? itemHeight : element.DesiredSize.Height);

                        // Calculation depends on orientation
                        if (orientation == Orientation.Horizontal)
                        {
                            // Does this element overflow the line?
                            if (breakAfter || (((lineOffset + childSize.Width) > finalSize.Width) && (current > 0)))
                            {
                                // Create position targets for items on this line
                                TargetLine(stateDict, targets,
                                           positionOffset, lineMax,
                                           itemWidthDefined, itemHeightDefined,
                                           itemWidth, itemHeight,
                                           finalSize, orientation);

                                // Move positioning down by height of the line
                                positionOffset += lineMax;

                                // Start at the left edge of the next line
                                lineOffset = 0;
                                lineMax = 0;
                                targets.Clear();
                            }

                            // Position the child on the current line
                            lineOffset += childSize.Width;
                            lineMax = Math.Max(lineMax, childSize.Height);
                        }
                        else
                        {
                            // Does this element overflow the line?
                            if (breakAfter || (((lineOffset + childSize.Height) > finalSize.Height) && (current > 0)))
                            {
                                // Create position targets for items on this line
                                TargetLine(stateDict, targets,
                                           positionOffset, lineMax,
                                           itemWidthDefined, itemHeightDefined,
                                           itemWidth, itemHeight,
                                           finalSize, orientation);

                                // Move positioning down by height of the line
                                positionOffset += lineMax;

                                // Start at the left edge of the next line
                                lineOffset = 0;
                                lineMax = 0;
                                targets.Clear();
                            }

                            // Position the child on the current line
                            lineOffset += childSize.Height;
                            lineMax = Math.Max(lineMax, childSize.Width);
                        }

                        targets.Add(element);
                        current++;

                        // Do we perform a line break after this element
                        breakAfter = WrapLayout.GetBreakAfter(element);
                    }
                }

                // Remember to take into account the last line
                TargetLine(stateDict, targets,
                           positionOffset, lineMax,
                           itemWidthDefined, itemHeightDefined,
                           itemWidth, itemHeight,
                           finalSize, orientation);
            }
        }
Exemplo n.º 43
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Cache the dependancy properties for faster perf
                double      itemWidth   = ItemWidth;
                double      itemHeight  = ItemHeight;
                Orientation orientation = Orientation;

                // Cache if the defined sizes are valid
                bool itemWidthDefined  = !double.IsNaN(ItemWidth);
                bool itemHeightDefined = !double.IsNaN(itemHeight);

                // Find size we provide to each child for measuring against, we use item sizes if defined
                Size elementSize = new Size(itemWidthDefined ? itemWidth : double.PositiveInfinity,
                                            itemHeightDefined ? itemHeight : double.PositiveInfinity);

                // Measure each element in turn
                bool   breakAfter  = false;
                double lineMax     = 0;
                double lineOffset  = 0;
                Size   measureSize = new Size();
                foreach (UIElement element in elements)
                {
                    element.Measure(elementSize);

                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // Decide on the actual size we will allocate to the element
                        Size childSize = new Size(itemWidthDefined ? itemWidth : element.DesiredSize.Width,
                                                  itemHeightDefined ? itemHeight : element.DesiredSize.Height);

                        // Calculation depends on orientation
                        if (orientation == Orientation.Horizontal)
                        {
                            // Does this element overflow the line?
                            if (breakAfter || (((lineOffset + childSize.Width) > availableSize.Width) && !measureSize.IsEmpty))
                            {
                                // Total measured size is equal to the widest line and tallest item per line
                                measureSize.Width   = Math.Max(measureSize.Width, lineOffset);
                                measureSize.Height += lineMax;

                                // Start at the left edge of the next line
                                lineOffset = 0;
                                lineMax    = 0;
                            }

                            // Position the child on the current line
                            lineOffset += childSize.Width;
                            lineMax     = Math.Max(lineMax, childSize.Height);
                        }
                        else
                        {
                            // Does this element overflow the line?
                            if (breakAfter || (((lineOffset + childSize.Height) > availableSize.Height) && !measureSize.IsEmpty))
                            {
                                // Total measured size is equal to the tallest line and widest item per line
                                measureSize.Height = Math.Max(measureSize.Height, lineOffset);
                                measureSize.Width += lineMax;

                                // Start at the top edge of the next line
                                lineOffset = 0;
                                lineMax    = 0;
                            }

                            // Position the child on the current line
                            lineOffset += childSize.Height;
                            lineMax     = Math.Max(lineMax, childSize.Width);
                        }

                        // Do we perform a line break after this element
                        breakAfter = WrapLayout.GetBreakAfter(element);
                    }
                }

                // Remember to take into account the last line
                if (orientation == Orientation.Horizontal)
                {
                    // Total measured size is equal to the widest line and tallest item per line
                    measureSize.Width   = Math.Max(measureSize.Width, lineOffset);
                    measureSize.Height += lineMax;
                }
                else
                {
                    // Total measured size is equal to the tallest line and widest item per line
                    measureSize.Height = Math.Max(measureSize.Height, lineOffset);
                    measureSize.Width += lineMax;
                }

                // Return minimum size needed to contain all the elements according to their desired sizes
                return(measureSize);
            }
            else
            {
                return(Size.Empty);
            }
        }
Exemplo n.º 44
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Measure each element in turn
            _count = 0;
            Size maxSize = new Size();
            foreach (UIElement element in elements)
                if (element != null)
                {
                    element.Measure(Utility.SizeInfinity);

                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // We ignore items that are collapsed
                        if (element.Visibility != Visibility.Collapsed)
                        {
                            // Find the widest and tallest element
                            maxSize.Width = Math.Max(maxSize.Width, element.DesiredSize.Width);
                            maxSize.Height = Math.Max(maxSize.Height, element.DesiredSize.Height);

                            // Count number of valid elements
                            _count++;
                        }
                    }
                }

            // Max length is the diagonal length of biggest element
            _maxLength = Math.Sqrt((maxSize.Width * maxSize.Width) + (maxSize.Height * maxSize.Height));

            // Always use the provided size
            return availableSize;
        }
 /// <summary>
 /// Perform animation effects on the set of children.
 /// </summary>
 /// <param name="animateId">Identifier of the animate to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be animated.</param>
 /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
 public override void ApplyAnimation(string animateId,
                                     MetaPanelBase metaPanel,
                                     MetaElementStateDict stateDict,
                                     ICollection elements,
                                     double elapsedMilliseconds)
 {
     ApplyAnimation(animateId, metaPanel, stateDict, elements, elapsedMilliseconds, Start, End);
 }
Exemplo n.º 46
0
 /// <summary>
 /// Perform animation effects on the set of children.
 /// </summary>
 /// <param name="animateId">Identifier of the animate to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be animated.</param>
 /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
 public abstract void ApplyAnimation(string animateId,
                                     MetaPanelBase metaPanel,
                                     MetaElementStateDict stateDict,
                                     ICollection elements,
                                     double elapsedMilliseconds);
Exemplo n.º 47
0
        /// <summary>
        /// Perform animation effects on the set of children.
        /// </summary>
        /// <param name="animateId">Identifier of the animate to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be animated.</param>
        /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
        public override void ApplyAnimation(string animateId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            double elapsedMilliseconds)
        {
            // Only apply if we match the incoming animate identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(animateId))
            {
                // Update the easing equation with latest value
                EasingCalculation.Easing = Easing;

                // Cache dependancy properties for faster perf
                double duration = Math.Max((double)1, Duration);

                foreach (UIElement element in elements)
                {
                    // Only apply animation to element of required target state
                    MetaElementState elementState = stateDict[element];
                    if (elementState.Status == Target)
                    {
                        Rect targetRect = elementState.TargetRect;
                        Rect currentRect = (elementState.CurrentRect.IsEmpty ? targetRect : elementState.CurrentRect);

                        // If start of animation....
                        if (elementState.TargetChanged)
                        {
                            // Cache starting information
                            elementState.StartRect = currentRect;
                            elementState.ElapsedBoundsTime = 0;
                        }
                        else
                        {
                            // Only perform animation if some time has actually ellapsed and not already at target
                            if ((elapsedMilliseconds > 0) && !currentRect.Equals(targetRect))
                            {
                                // Add new elapsed time to the animation running time
                                elementState.ElapsedBoundsTime += elapsedMilliseconds;

                                // Does elapsed time indicate animation should have completed?
                                if (elementState.ElapsedBoundsTime >= duration)
                                    currentRect = targetRect;
                                else
                                {
                                    Rect startRect = elementState.StartRect;
                                    double elapsedTime = elementState.ElapsedBoundsTime;

                                    // Using animation easing to discover new target rectangle corners
                                    double left = EasingCalculation.Calculate(elapsedTime, startRect.X, targetRect.X - startRect.X, duration);
                                    double top = EasingCalculation.Calculate(elapsedTime, startRect.Y, targetRect.Y - startRect.Y, duration);
                                    double bottom = EasingCalculation.Calculate(elapsedTime, startRect.Bottom, targetRect.Bottom - startRect.Bottom, duration);
                                    double right = EasingCalculation.Calculate(elapsedTime, startRect.Right, targetRect.Right - startRect.Right, duration);

                                    // Normalize edges left/right edges
                                    if (left > right)
                                    {
                                        elapsedTime = left;
                                        left = right;
                                        right = elapsedTime;
                                    }

                                    // Normalize edges top/bottom edges
                                    if (top > bottom)
                                    {
                                        elapsedTime = top;
                                        top = bottom;
                                        bottom = elapsedTime;
                                    }

                                    currentRect = new Rect(left, top, right - left, bottom - top);
                                }
                            }
                        }

                        // Put back the updated rectangle and decide if more animation is needed
                        elementState.CurrentRect = currentRect;
                        elementState.AnimateComplete &= (currentRect.Equals(targetRect));
                    }
                }
            }
        }
Exemplo n.º 48
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Measure each element in turn
                _validCount = 0;
                Size usedSize = new Size();
                Size maxSize = new Size();
                foreach (UIElement element in elements)
                {
                    // Allow element to have all the remainder size available
                    Size elementSize = new Size(Math.Max(0.0, (double)(availableSize.Width - usedSize.Width)),
                                                Math.Max(0.0, (double)(availableSize.Height - usedSize.Height)));

                    element.Measure(elementSize);

                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // Discover the used size and the maximum required size for opposite direction
                        Size desiredSize = element.DesiredSize;
                        switch (GetDock(element))
                        {
                            case Dock.Left:
                            case Dock.Right:
                                maxSize.Height = Math.Max(maxSize.Height, usedSize.Height + desiredSize.Height);
                                usedSize.Width += desiredSize.Width;
                                break;
                            case Dock.Top:
                            case Dock.Bottom:
                                maxSize.Width = Math.Max(maxSize.Width, usedSize.Width + desiredSize.Width);
                                usedSize.Height += desiredSize.Height;
                                break;
                        }

                        _validCount++;
                    }
                }

                return new Size(Math.Max(maxSize.Width, usedSize.Width),
                                Math.Max(maxSize.Height, usedSize.Height));
            }
            else
                return Size.Empty;
        }
Exemplo n.º 49
0
        /// <summary>
        /// Calculate target state for each element based on layout algorithm.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        public override void TargetChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                double x = 0.0;
                double y = 0.0;
                double right = 0.0;
                double bottom = 0.0;

                // If using LastChildFill then the last element takes up all the remainder space
                int lastDockElement = (LastChildFill ? _validCount - 1 : _validCount);

                // Calculate the target rectangle for each element
                int i = 0;
                foreach (UIElement element in elements)
                {
                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // Calculate the maximum possible rect for the element
                        Rect newTargetRect = new Rect(x, y,
                                                      Math.Max(0.0, (double)(finalSize.Width - (x + right))),
                                                      Math.Max(0.0, (double)(finalSize.Height - (y + bottom))));

                        if (i < lastDockElement)
                        {
                            // Constrain target rect by the dock edge
                            Size desiredSize = element.DesiredSize;
                            switch (GetDock(element))
                            {
                                case Dock.Left:
                                    x += desiredSize.Width;
                                    newTargetRect.Width = desiredSize.Width;
                                    break;
                                case Dock.Top:
                                    y += desiredSize.Height;
                                    newTargetRect.Height = desiredSize.Height;
                                    break;
                                case Dock.Right:
                                    right += desiredSize.Width;
                                    newTargetRect.X = Math.Max(0.0, (double)(finalSize.Width - right));
                                    newTargetRect.Width = desiredSize.Width;
                                    break;
                                case Dock.Bottom:
                                    bottom += desiredSize.Height;
                                    newTargetRect.Y = Math.Max(0.0, (double)(finalSize.Height - bottom));
                                    newTargetRect.Height = desiredSize.Height;
                                    break;
                            }
                        }

                        // Store the new target rectangle
                        if (!stateDict[element].TargetRect.Equals(newTargetRect))
                        {
                            stateDict[element].TargetChanged = true;
                            stateDict[element].TargetRect = newTargetRect;
                        }

                        i++;
                    }
                }
            }
        }
Exemplo n.º 50
0
        /// <summary>
        /// Measure the layout size required to arrange all elements.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be measured.</param>
        /// <param name="availableSize">Available size that can be given to elements.</param>
        /// <returns>Size the layout determines it needs based on child element sizes.</returns>
        public override Size MeasureChildren(string layoutId,
                                             MetaPanelBase metaPanel,
                                             MetaElementStateDict stateDict,
                                             ICollection elements,
                                             Size availableSize)
        {
            Size retSize = new Size();

            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // If there are no column/row definitions then size to available area
                if ((_columns.Count == 0) && (_rows.Count == 0))
                {
                    foreach (UIElement element in elements)
                    {
                        stateDict[element].Element.Measure(availableSize);
                        retSize.Width = Math.Max(retSize.Width, stateDict[element].Element.DesiredSize.Width);
                        retSize.Height = Math.Max(retSize.Height, stateDict[element].Element.DesiredSize.Height);
                    }
                }
                else
                {
                    BuildProxyColumns();
                    BuildProxyRows();
                    PreMeasure(availableSize);
                    MeasureElements(stateDict, elements);
                    UpdateDefinitions(stateDict, elements, false);
                    UpdateDefinitions(stateDict, elements, true);
                    CalculateOffsetsAndTotals();
                    retSize = CalculateDesiredSize(stateDict, elements, availableSize);
                }
            }

            return retSize;
        }
Exemplo n.º 51
0
        /// <summary>
        /// Calculate target state for each element based on layout algorithm.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        public override void TargetChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // If there are no column/row definitions then arrange to entire final size
                if ((_columns.Count == 0) && (_rows.Count == 0))
                {
                    Rect newTargetRect = new Rect(Utility.PointZero, finalSize);
                    foreach (UIElement element in elements)
                    {
                        // We ignore items being removed
                        if (stateDict[element].Status != MetaElementStatus.Removing)
                        {
                            // Store the new target rectangle
                            if (!stateDict[element].TargetRect.Equals(newTargetRect))
                            {
                                stateDict[element].TargetChanged = true;
                                stateDict[element].TargetRect = newTargetRect;
                            }
                        }
                    }
                }
                else
                {
                    // Calculate final width/height of col/row definitions
                    PreTarget(finalSize);

                    // Update new target rectangle for each non-removing element
                    foreach (UIElement element in elements)
                    {
                        // We ignore items being removed
                        if (stateDict[element].Status != MetaElementStatus.Removing)
                        {
                            // Find the arrange size for the element
                            Rect newTargetRect = TargetArrangeSize(element);

                            // Store the new target rectangle
                            if (!stateDict[element].TargetRect.Equals(newTargetRect))
                            {
                                stateDict[element].TargetChanged = true;
                                stateDict[element].TargetRect = newTargetRect;
                            }
                        }
                    }
                }
            }

            // Update rows and columns with actual widths/heights
            for (int i = 0; i < ColumnDefinitions.Count; i++)
                ColumnDefinitions[i].ActualWidth = _proxyColumns[i].MinSize;

            for (int i = 0; i < RowDefinitions.Count; i++)
                RowDefinitions[i].ActualHeight = _proxyRows[i].MinSize;
        }
Exemplo n.º 52
0
        /// <summary>
        /// Calculate target state for each element based on layout algorithm.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        public override void TargetChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            if (_count > 0)
            {
                // Each child is an equal angle around the radius
                double angleCurrent = StartAngle;
                double diff = (EndAngle - StartAngle);
                double angleDelta = diff / ((diff == (double)360) ? _count : _count - 1);

                // Calculate the radius separately for each dimension
                double radiusX = (finalSize.Width - _maxLength * 2) / 2;
                double radiusY = (finalSize.Height - _maxLength * 2) / 2;

                // Do we force into being a circle?
                if (Circle)
                {
                    // Always reduce to using the smallest direction
                    radiusX = Math.Min(radiusX, radiusY);
                    radiusY = radiusX;
                }

                // Rotate around the center point
                Point center = new Point(finalSize.Width / 2, finalSize.Height / 2);

                // Calculate the target rectangle for each element
                foreach (UIElement element in elements)
                {
                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // We ignore items that are collapsed
                        if (element.Visibility != Visibility.Collapsed)
                        {
                            // Rotate around the center point using the accumulated angle
                            double childX = center.X + Math.Cos(2 * Math.PI * angleCurrent / 360) * radiusX;
                            double childY = center.Y + Math.Sin(2 * Math.PI * angleCurrent / 360) * radiusY;
                            angleCurrent += angleDelta;

                            // Position the element at
                            Size desiredSize = element.DesiredSize;
                            Rect newTargetRect = new Rect(childX - desiredSize.Width / 2,
                                                          childY - desiredSize.Height / 2,
                                                          desiredSize.Width,
                                                          desiredSize.Height);

                            // Store the new target rectangle
                            if (!stateDict[element].TargetRect.Equals(newTargetRect))
                            {
                                stateDict[element].TargetChanged = true;
                                stateDict[element].TargetRect = newTargetRect;
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 53
0
 /// <summary>
 /// Perform animation effects on the set of children.
 /// </summary>
 /// <param name="animateId">Identifier of the animate to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be animated.</param>
 /// <param name="elapsedMilliseconds">Elapsed milliseconds since last animation cycle.</param>
 public abstract void ApplyAnimation(string animateId,
                                     MetaPanelBase metaPanel,
                                     MetaElementStateDict stateDict,
                                     ICollection elements,
                                     double elapsedMilliseconds);
Exemplo n.º 54
0
        /// <summary>
        /// Calculate target state for each element based on layout algorithm.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        public override void TargetChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Cache the dependancy properties for faster perf
                double      itemWidth   = ItemWidth;
                double      itemHeight  = ItemHeight;
                Orientation orientation = Orientation;

                // Cache if the defined sizes are valid
                bool itemWidthDefined  = !double.IsNaN(ItemWidth);
                bool itemHeightDefined = !double.IsNaN(itemHeight);

                // Find size we provide to each child for measuring against, we use item sizes if defined
                Size elementSize = new Size(itemWidthDefined ? itemWidth : double.PositiveInfinity,
                                            itemHeightDefined ? itemHeight : double.PositiveInfinity);

                // Measure each element in turn
                int              current        = 0;
                double           lineOffset     = 0;
                double           lineMax        = 0;
                double           positionOffset = 0;
                bool             breakAfter     = false;
                List <UIElement> targets        = new List <UIElement>();
                foreach (UIElement element in elements)
                {
                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        // Decide on the actual size we will allocate to the element
                        Size childSize = new Size(itemWidthDefined ? itemWidth : element.DesiredSize.Width,
                                                  itemHeightDefined ? itemHeight : element.DesiredSize.Height);

                        // Calculation depends on orientation
                        if (orientation == Orientation.Horizontal)
                        {
                            // Does this element overflow the line?
                            if (breakAfter || (((lineOffset + childSize.Width) > finalSize.Width) && (current > 0)))
                            {
                                // Create position targets for items on this line
                                TargetLine(stateDict, targets,
                                           positionOffset, lineMax,
                                           itemWidthDefined, itemHeightDefined,
                                           itemWidth, itemHeight,
                                           finalSize, orientation);

                                // Move positioning down by height of the line
                                positionOffset += lineMax;

                                // Start at the left edge of the next line
                                lineOffset = 0;
                                lineMax    = 0;
                                targets.Clear();
                            }

                            // Position the child on the current line
                            lineOffset += childSize.Width;
                            lineMax     = Math.Max(lineMax, childSize.Height);
                        }
                        else
                        {
                            // Does this element overflow the line?
                            if (breakAfter || (((lineOffset + childSize.Height) > finalSize.Height) && (current > 0)))
                            {
                                // Create position targets for items on this line
                                TargetLine(stateDict, targets,
                                           positionOffset, lineMax,
                                           itemWidthDefined, itemHeightDefined,
                                           itemWidth, itemHeight,
                                           finalSize, orientation);

                                // Move positioning down by height of the line
                                positionOffset += lineMax;

                                // Start at the left edge of the next line
                                lineOffset = 0;
                                lineMax    = 0;
                                targets.Clear();
                            }

                            // Position the child on the current line
                            lineOffset += childSize.Height;
                            lineMax     = Math.Max(lineMax, childSize.Width);
                        }

                        targets.Add(element);
                        current++;

                        // Do we perform a line break after this element
                        breakAfter = WrapLayout.GetBreakAfter(element);
                    }
                }

                // Remember to take into account the last line
                TargetLine(stateDict, targets,
                           positionOffset, lineMax,
                           itemWidthDefined, itemHeightDefined,
                           itemWidth, itemHeight,
                           finalSize, orientation);
            }
        }
Exemplo n.º 55
0
 /// <summary>
 /// Calculate target state for each element based on layout algorithm.
 /// </summary>
 /// <param name="layoutId">Identifier of the layout to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be arranged.</param>
 /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
 public override void TargetChildren(string layoutId,
                                     MetaPanelBase metaPanel,
                                     MetaElementStateDict stateDict,
                                     ICollection elements,
                                     Size finalSize)
 {
     // Only apply if we match the incoming layout identifier
     if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
     {
         // TODO target elements that are not in tree drawing
         TargetTreeNodes(Utility.PointZero, StartNode, stateDict, false);
     }
 }
Exemplo n.º 56
0
        /// <summary>
        /// Calculate target state for each element based on layout algorithm.
        /// </summary>
        /// <param name="layoutId">Identifier of the layout to be used.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="stateDict">Dictionary of per-element state.</param>
        /// <param name="elements">Collection of elements to be arranged.</param>
        /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
        public override void TargetChildren(string layoutId,
                                            MetaPanelBase metaPanel,
                                            MetaElementStateDict stateDict,
                                            ICollection elements,
                                            Size finalSize)
        {
            // Only apply if we match the incoming layout identifier
            if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId))
            {
                // Cache the dependancy properties for faster perf
                Orientation orientation = Orientation;

                // Calculate the target rectangle for each element
                double offset = 0;
                foreach (UIElement element in elements)
                {
                    // We ignore items being removed
                    if (stateDict[element].Status != MetaElementStatus.Removing)
                    {
                        Rect newTargetRect;

                        // Updating the elements target rectangle depends on orientation
                        if (orientation == Orientation.Horizontal)
                        {
                            newTargetRect = new Rect(offset, 0, element.DesiredSize.Width, Math.Max(finalSize.Height, element.DesiredSize.Height));
                            offset += element.DesiredSize.Width;
                        }
                        else
                        {
                            newTargetRect = new Rect(0, offset, Math.Max(finalSize.Width, element.DesiredSize.Width), element.DesiredSize.Height);
                            offset += element.DesiredSize.Height;
                        }

                        // Store the new target rectangle
                        if (!stateDict[element].TargetRect.Equals(newTargetRect))
                        {
                            stateDict[element].TargetChanged = true;
                            stateDict[element].TargetRect = newTargetRect;
                        }
                    }
                }
            }
        }
Exemplo n.º 57
0
 /// <summary>
 /// Calculate target state for each element based on layout algorithm.
 /// </summary>
 /// <param name="layoutId">Identifier of the layout to be used.</param>
 /// <param name="metaPanel">Reference to owning panel instance.</param>
 /// <param name="stateDict">Dictionary of per-element state.</param>
 /// <param name="elements">Collection of elements to be arranged.</param>
 /// <param name="finalSize">Size that layout should use to arrange child elements.</param>
 public abstract void TargetChildren(string layoutId,
                                     MetaPanelBase metaPanel,
                                     MetaElementStateDict stateDict,
                                     ICollection elements,
                                     Size finalSize);