public override List <WidgetAndPosition> FindDescendants(IEnumerable <string> namesToSearchFor, List <WidgetAndPosition> foundChildren, RectangleDouble touchingBounds, SearchType seachType, bool allowInvalidItems = true)
        {
            foreach (var child in Scene.Children)
            {
                string object3DName = child.Name;
                if (object3DName == null && child.MeshPath != null)
                {
                    object3DName = Path.GetFileName(child.MeshPath);
                }

                bool nameFound = false;

                foreach (var nameToSearchFor in namesToSearchFor)
                {
                    if (seachType == SearchType.Exact)
                    {
                        if (object3DName == nameToSearchFor)
                        {
                            nameFound = true;
                        }
                    }
                    else
                    {
                        if (nameToSearchFor == "" ||
                            object3DName.Contains(nameToSearchFor))
                        {
                            nameFound = true;
                        }
                    }
                }

                if (nameFound)
                {
                    AxisAlignedBoundingBox bounds = child.GetBVHData().GetAxisAlignedBoundingBox();

                    RectangleDouble screenBoundsOfObject3D = RectangleDouble.ZeroIntersection;
                    for (int i = 0; i < 4; i++)
                    {
                        screenBoundsOfObject3D.ExpandToInclude(this.World.GetScreenPosition(bounds.GetTopCorner(i)));
                        screenBoundsOfObject3D.ExpandToInclude(this.World.GetScreenPosition(bounds.GetBottomCorner(i)));
                    }

                    if (touchingBounds.IsTouching(screenBoundsOfObject3D))
                    {
                        Vector3 renderPosition           = bounds.Center;
                        Vector2 objectCenterScreenSpace  = this.World.GetScreenPosition(renderPosition);
                        Point2D screenPositionOfObject3D = new Point2D((int)objectCenterScreenSpace.X, (int)objectCenterScreenSpace.Y);

                        foundChildren.Add(new WidgetAndPosition(this, screenPositionOfObject3D, object3DName));
                    }
                }
            }

            return(base.FindDescendants(namesToSearchFor, foundChildren, touchingBounds, seachType, allowInvalidItems));
        }
Ejemplo n.º 2
0
        public RectangleDouble GetTotalBounds()
        {
            RectangleDouble totalBounds = GetTrackBounds();

            totalBounds.ExpandToInclude(GetThumbBounds());
            if (sliderAttachedTo.sliderTextWidget.Text != "")
            {
                totalBounds.ExpandToInclude(sliderAttachedTo.sliderTextWidget.BoundsRelativeToParent);
            }

            return(totalBounds);
        }
Ejemplo n.º 3
0
        public RectangleDouble GetTotalBounds()
        {
            RectangleDouble totalBounds = GetTrackBounds();

            totalBounds.ExpandToInclude(GetThumbBounds());
            return(totalBounds);
        }
Ejemplo n.º 4
0
        public RectangleDouble GetBounds()
        {
            RectangleDouble bounds = RectangleDouble.ZeroIntersection;

            foreach (VertexData vertexData in Vertices())
            {
                bounds.ExpandToInclude(vertexData.position);
            }

            return(bounds);
        }
Ejemplo n.º 5
0
        public static RectangleDouble GetBounds(this Polygon poly)
        {
            RectangleDouble bounds = RectangleDouble.ZeroIntersection;

            foreach (var point in poly)
            {
                bounds.ExpandToInclude(point.X, point.Y);
            }

            return(bounds);
        }
Ejemplo n.º 6
0
        public static RectangleDouble GetBounds(this Polygons polys)
        {
            RectangleDouble bounds = RectangleDouble.ZeroIntersection;

            foreach (var poly in polys)
            {
                bounds.ExpandToInclude(poly.GetBounds());
            }

            return(bounds);
        }
Ejemplo n.º 7
0
        private RectangleDouble GetScreenBounds(AxisAlignedBoundingBox meshBounds)
        {
            RectangleDouble screenBounds = RectangleDouble.ZeroIntersection;

            screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.minXYZ.x, meshBounds.minXYZ.y, meshBounds.minXYZ.z)));
            screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.maxXYZ.x, meshBounds.minXYZ.y, meshBounds.minXYZ.z)));
            screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.maxXYZ.x, meshBounds.maxXYZ.y, meshBounds.minXYZ.z)));
            screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.minXYZ.x, meshBounds.maxXYZ.y, meshBounds.minXYZ.z)));

            screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.minXYZ.x, meshBounds.minXYZ.y, meshBounds.maxXYZ.z)));
            screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.maxXYZ.x, meshBounds.minXYZ.y, meshBounds.maxXYZ.z)));
            screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.maxXYZ.x, meshBounds.maxXYZ.y, meshBounds.maxXYZ.z)));
            screenBounds.ExpandToInclude(trackballTumbleWidget.GetScreenPosition(new Vector3(meshBounds.minXYZ.x, meshBounds.maxXYZ.y, meshBounds.maxXYZ.z)));
            return(screenBounds);
        }
Ejemplo n.º 8
0
        public static RectangleDouble GetScreenBounds(AxisAlignedBoundingBox meshBounds, WorldView world)
        {
            RectangleDouble screenBounds = RectangleDouble.ZeroIntersection;

            screenBounds.ExpandToInclude(world.GetScreenPosition(new Vector3(meshBounds.minXYZ.X, meshBounds.minXYZ.Y, meshBounds.minXYZ.Z)));
            screenBounds.ExpandToInclude(world.GetScreenPosition(new Vector3(meshBounds.maxXYZ.X, meshBounds.minXYZ.Y, meshBounds.minXYZ.Z)));
            screenBounds.ExpandToInclude(world.GetScreenPosition(new Vector3(meshBounds.maxXYZ.X, meshBounds.maxXYZ.Y, meshBounds.minXYZ.Z)));
            screenBounds.ExpandToInclude(world.GetScreenPosition(new Vector3(meshBounds.minXYZ.X, meshBounds.maxXYZ.Y, meshBounds.minXYZ.Z)));

            screenBounds.ExpandToInclude(world.GetScreenPosition(new Vector3(meshBounds.minXYZ.X, meshBounds.minXYZ.Y, meshBounds.maxXYZ.Z)));
            screenBounds.ExpandToInclude(world.GetScreenPosition(new Vector3(meshBounds.maxXYZ.X, meshBounds.minXYZ.Y, meshBounds.maxXYZ.Z)));
            screenBounds.ExpandToInclude(world.GetScreenPosition(new Vector3(meshBounds.maxXYZ.X, meshBounds.maxXYZ.Y, meshBounds.maxXYZ.Z)));
            screenBounds.ExpandToInclude(world.GetScreenPosition(new Vector3(meshBounds.minXYZ.X, meshBounds.maxXYZ.Y, meshBounds.maxXYZ.Z)));
            return(screenBounds);
        }
        public static RectangleDouble GetBounds(this IVertexSource source)
        {
            RectangleDouble bounds = RectangleDouble.ZeroIntersection;

            foreach (var vertex in source.Vertices())
            {
                if (!vertex.IsClose && !vertex.IsStop)
                {
                    bounds.ExpandToInclude(vertex.position);
                }
            }

            return(bounds);
        }
Ejemplo n.º 10
0
        public ImageBuffer GetImageForCharacter(char character, double xFraction, double yFraction, RGBA_Bytes color)
        {
            if (xFraction > 1 || xFraction < 0 || yFraction > 1 || yFraction < 0)
            {
                throw new ArgumentException("The x and y fractions must both be between 0 and 1.");
            }

            ImageBuffer imageForCharacter;
            Dictionary <char, ImageBuffer> characterImageCache = StyledTypeFaceImageCache.GetCorrectCache(this.TypeFace, color, this.emSizeInPixels);

            characterImageCache.TryGetValue(character, out imageForCharacter);
            if (imageForCharacter != null)
            {
                return(imageForCharacter);
            }

            IVertexSource glyphForCharacter = GetGlyphForCharacter(character);

            if (glyphForCharacter == null)
            {
                return(null);
            }

            glyphForCharacter.rewind(0);
            double x, y;

            ShapePath.FlagsAndCommand curCommand = glyphForCharacter.vertex(out x, out y);
            RectangleDouble           bounds     = new RectangleDouble(x, y, x, y);

            while (curCommand != ShapePath.FlagsAndCommand.CommandStop)
            {
                bounds.ExpandToInclude(x, y);
                curCommand = glyphForCharacter.vertex(out x, out y);
            }

            int         descentExtraHeight = (int)(-DescentInPixels + .5);
            ImageBuffer charImage          = new ImageBuffer(Math.Max((int)(bounds.Width + .5), 1) + 1, Math.Max((int)(EmSizeInPixels + descentExtraHeight + .5), 1) + 1, 32, new BlenderPreMultBGRA());

            charImage.OriginOffset = new VectorMath.Vector2(0, descentExtraHeight);
            Graphics2D graphics = charImage.NewGraphics2D();

            graphics.Render(glyphForCharacter, xFraction, yFraction + descentExtraHeight, color);
            characterImageCache[character] = charImage;

            return(charImage);
        }
Ejemplo n.º 11
0
		private void CalculateChildrenBounds()
		{
			if (Children.Count > 0)
			{
				RectangleDouble boundsOfChildren = new RectangleDouble(double.MaxValue, double.MaxValue, double.MinValue, double.MinValue);
				foreach (GuiWidget widget in Children)
				{
					boundsOfChildren.ExpandToInclude(widget.BoundsRelativeToParent);
					boundsOfChildren.Left = Math.Min(boundsOfChildren.Left, widget.BoundsRelativeToParent.Left);
					boundsOfChildren.Bottom = Math.Min(boundsOfChildren.Bottom, widget.BoundsRelativeToParent.Bottom);
					boundsOfChildren.Right = Math.Max(boundsOfChildren.Right, widget.BoundsRelativeToParent.Right);
					boundsOfChildren.Top = Math.Max(boundsOfChildren.Top, widget.BoundsRelativeToParent.Top);
				}

				LocalBounds = boundsOfChildren;
			}
		}
Ejemplo n.º 12
0
        private void CalculateChildrenBounds()
        {
            if (Children.Count > 0)
            {
                RectangleDouble boundsOfChildren = new RectangleDouble(double.MaxValue, double.MaxValue, double.MinValue, double.MinValue);
                foreach (GuiWidget widget in Children)
                {
                    boundsOfChildren.ExpandToInclude(widget.BoundsRelativeToParent);
                    boundsOfChildren.Left   = Math.Min(boundsOfChildren.Left, widget.BoundsRelativeToParent.Left);
                    boundsOfChildren.Bottom = Math.Min(boundsOfChildren.Bottom, widget.BoundsRelativeToParent.Bottom);
                    boundsOfChildren.Right  = Math.Max(boundsOfChildren.Right, widget.BoundsRelativeToParent.Right);
                    boundsOfChildren.Top    = Math.Max(boundsOfChildren.Top, widget.BoundsRelativeToParent.Top);
                }

                LocalBounds = boundsOfChildren;
            }
        }
Ejemplo n.º 13
0
        public override void FindNamedChildrenRecursive(string nameToSearchFor, List <WidgetAndPosition> foundChildren, RectangleDouble touchingBounds, SearchType seachType, bool allowInvalidItems = true)
        {
            foreach (InteractionVolume child in interactionLayer.InteractionVolumes)
            {
                string object3DName = child.Name;

                bool nameFound = false;

                if (seachType == SearchType.Exact)
                {
                    if (object3DName == nameToSearchFor)
                    {
                        nameFound = true;
                    }
                }
                else
                {
                    if (nameToSearchFor == "" ||
                        object3DName.Contains(nameToSearchFor))
                    {
                        nameFound = true;
                    }
                }

                if (nameFound &&
                    child.CollisionVolume != null)
                {
                    AxisAlignedBoundingBox bounds = child.CollisionVolume.GetAxisAlignedBoundingBox();
                    bounds = bounds.NewTransformed(child.TotalTransform);

                    RectangleDouble screenBoundsOfObject3D = RectangleDouble.ZeroIntersection;
                    for (int i = 0; i < 4; i++)
                    {
                        screenBoundsOfObject3D.ExpandToInclude(this.World.GetScreenPosition(bounds.GetTopCorner(i)));
                        screenBoundsOfObject3D.ExpandToInclude(this.World.GetScreenPosition(bounds.GetBottomCorner(i)));
                    }

                    if (touchingBounds.IsTouching(screenBoundsOfObject3D))
                    {
                        Vector3 renderPosition           = bounds.Center;
                        Vector2 objectCenterScreenSpace  = this.World.GetScreenPosition(renderPosition);
                        Point2D screenPositionOfObject3D = new Point2D((int)objectCenterScreenSpace.X, (int)objectCenterScreenSpace.Y);

                        foundChildren.Add(new WidgetAndPosition(this, screenPositionOfObject3D, object3DName, child));
                    }
                }
            }

            foreach (var child in scene.Children)
            {
                string object3DName = child.Name;
                if (object3DName == null && child.MeshPath != null)
                {
                    object3DName = Path.GetFileName(child.MeshPath);
                }

                bool nameFound = false;

                if (seachType == SearchType.Exact)
                {
                    if (object3DName == nameToSearchFor)
                    {
                        nameFound = true;
                    }
                }
                else
                {
                    if (nameToSearchFor == "" ||
                        object3DName.Contains(nameToSearchFor))
                    {
                        nameFound = true;
                    }
                }

                if (nameFound)
                {
                    AxisAlignedBoundingBox bounds = child.TraceData().GetAxisAlignedBoundingBox();

                    RectangleDouble screenBoundsOfObject3D = RectangleDouble.ZeroIntersection;
                    for (int i = 0; i < 4; i++)
                    {
                        screenBoundsOfObject3D.ExpandToInclude(this.World.GetScreenPosition(bounds.GetTopCorner(i)));
                        screenBoundsOfObject3D.ExpandToInclude(this.World.GetScreenPosition(bounds.GetBottomCorner(i)));
                    }

                    if (touchingBounds.IsTouching(screenBoundsOfObject3D))
                    {
                        Vector3 renderPosition           = bounds.Center;
                        Vector2 objectCenterScreenSpace  = this.World.GetScreenPosition(renderPosition);
                        Point2D screenPositionOfObject3D = new Point2D((int)objectCenterScreenSpace.X, (int)objectCenterScreenSpace.Y);

                        foundChildren.Add(new WidgetAndPosition(this, screenPositionOfObject3D, object3DName, child));
                    }
                }
            }

            base.FindNamedChildrenRecursive(nameToSearchFor, foundChildren, touchingBounds, seachType, allowInvalidItems);
        }
Ejemplo n.º 14
0
		public ImageBuffer GetImageForCharacter(char character, double xFraction, double yFraction, RGBA_Bytes color)
		{
			if (xFraction > 1 || xFraction < 0 || yFraction > 1 || yFraction < 0)
			{
				throw new ArgumentException("The x and y fractions must both be between 0 and 1.");
			}

			ImageBuffer imageForCharacter;
			Dictionary<char, ImageBuffer> characterImageCache = StyledTypeFaceImageCache.GetCorrectCache(this.TypeFace, color, this.emSizeInPixels);
			characterImageCache.TryGetValue(character, out imageForCharacter);
			if (imageForCharacter != null)
			{
				return imageForCharacter;
			}

			IVertexSource glyphForCharacter = GetGlyphForCharacter(character);
			if (glyphForCharacter == null)
			{
				return null;
			}

			glyphForCharacter.rewind(0);
			double x, y;
			ShapePath.FlagsAndCommand curCommand = glyphForCharacter.vertex(out x, out y);
			RectangleDouble bounds = new RectangleDouble(x, y, x, y);
			while (curCommand != ShapePath.FlagsAndCommand.CommandStop)
			{
				bounds.ExpandToInclude(x, y);
				curCommand = glyphForCharacter.vertex(out x, out y);
			}

			int descentExtraHeight = (int)(-DescentInPixels + .5);
			ImageBuffer charImage = new ImageBuffer(Math.Max((int)(bounds.Width + .5), 1) + 1, Math.Max((int)(EmSizeInPixels + descentExtraHeight + .5), 1) + 1, 32, new BlenderPreMultBGRA());
			charImage.OriginOffset = new VectorMath.Vector2(0, descentExtraHeight);
			Graphics2D graphics = charImage.NewGraphics2D();
			graphics.Render(glyphForCharacter, xFraction, yFraction + descentExtraHeight, color);
			characterImageCache[character] = charImage;

			return charImage;
		}
Ejemplo n.º 15
0
        private void DoLayoutChildren(LayoutEventArgs layoutEventArgs)
        {
            GuiWidget parent = layoutEventArgs.ParentWidget;

            if (parent.CountVisibleChildren() == 0)
            {
                return;
            }

            RectangleDouble boundsOfAllChildrenIncludingMargin = RectangleDouble.ZeroIntersection;

            double totalWidthWithMargin  = 0;
            double totalHeightWithMargin = 0;

            double totalWidthOfStaticItems  = 0;
            double totalHeightOfStaticItems = 0;
            int    numItemsNeedingExpanding = 0;

            double totalMinimumWidthOfAllItems  = 0;
            double totalMinimumHeightOfAllItems = 0;

            for (int childIndex = 0; childIndex < parent.Children.Count; childIndex++)
            {
                GuiWidget child = parent.Children[childIndex];
                if (child.Visible == false)
                {
                    continue;
                }

                RectangleDouble childBoundsWithMargin = child.LocalBounds;
                childBoundsWithMargin.Inflate(child.Margin);
                totalWidthWithMargin  += childBoundsWithMargin.Width;
                totalHeightWithMargin += childBoundsWithMargin.Height;
                boundsOfAllChildrenIncludingMargin.ExpandToInclude(childBoundsWithMargin);

                switch (FlowDirection)
                {
                case UI.FlowDirection.LeftToRight:
                case UI.FlowDirection.RightToLeft:
                    totalMinimumWidthOfAllItems += child.MinimumSize.x + child.Margin.Width;
                    totalMinimumHeightOfAllItems = Math.Max(totalMinimumHeightOfAllItems, child.MinimumSize.y + child.Margin.Height);

                    if (child.HAnchorIsSet(HAnchor.ParentLeftRight))
                    {
                        numItemsNeedingExpanding++;
                        totalWidthOfStaticItems += child.Margin.Width;
                    }
                    else if (child.HAnchor == HAnchor.AbsolutePosition || child.HAnchorIsSet(HAnchor.FitToChildren))
                    {
                        totalWidthOfStaticItems += childBoundsWithMargin.Width;
                    }
                    else
                    {
                        throw new Exception("Only None or ParentLeftRight are valid HAnchor for a horizontal flowWidget.");
                    }
                    break;

                case UI.FlowDirection.TopToBottom:
                case UI.FlowDirection.BottomToTop:
                    totalMinimumWidthOfAllItems   = Math.Max(totalMinimumWidthOfAllItems, child.MinimumSize.x + child.Margin.Width);
                    totalMinimumHeightOfAllItems += child.MinimumSize.y + child.Margin.Height;
                    if (child.VAnchorIsSet(VAnchor.ParentBottomTop))
                    {
                        numItemsNeedingExpanding++;
                        totalHeightOfStaticItems += child.Margin.Height;
                    }
                    else if (child.VAnchor == VAnchor.AbsolutePosition || child.VAnchorIsSet(VAnchor.FitToChildren))
                    {
                        totalHeightOfStaticItems += childBoundsWithMargin.Height;
                    }
                    else
                    {
                        throw new Exception("Only None or ParentBottomTop are valid VAnchor for a vertial flowWidget.");
                    }
                    break;

                default:
                    throw new NotImplementedException();
                }
            }

            switch (FlowDirection)
            {
            case UI.FlowDirection.LeftToRight:
            {
                double curX = parent.Padding.Left;
                foreach (GuiWidget child in parent.Children)
                {
                    if (child.Visible == true)
                    {
                        double newX = curX - child.LocalBounds.Left + child.Margin.Left;
                        child.OriginRelativeParent = new Vector2(newX, child.OriginRelativeParent.y);
                        if (child.HAnchorIsSet(HAnchor.ParentLeftRight))
                        {
                            RectangleDouble curChildBounds = child.LocalBounds;
                            double          newWidth       = (parent.LocalBounds.Width - parent.Padding.Width - totalWidthOfStaticItems) / numItemsNeedingExpanding;
                            child.LocalBounds = new RectangleDouble(curChildBounds.Left, curChildBounds.Bottom,
                                                                    newWidth, curChildBounds.Top);
                        }
                        curX += child.LocalBounds.Width + child.Margin.Width;
                    }
                }
            }
            break;

            case UI.FlowDirection.RightToLeft:
            {
                double curX = parent.LocalBounds.Right - parent.Padding.Right;
                foreach (GuiWidget child in parent.Children)
                {
                    if (child.Visible == true)
                    {
                        if (child.HAnchorIsSet(HAnchor.ParentLeftRight))
                        {
                            RectangleDouble curChildBounds = child.LocalBounds;
                            double          newWidth       = (parent.LocalBounds.Width - parent.Padding.Width - totalWidthOfStaticItems) / numItemsNeedingExpanding;
                            child.LocalBounds = new RectangleDouble(curChildBounds.Left, curChildBounds.Bottom,
                                                                    newWidth, curChildBounds.Top);
                        }

                        double newX = curX - child.LocalBounds.Left - (child.LocalBounds.Width + child.Margin.Right);
                        child.OriginRelativeParent = new Vector2(newX, child.OriginRelativeParent.y);
                        curX -= (child.LocalBounds.Width + child.Margin.Width);
                    }
                }
            }
            break;

            case UI.FlowDirection.BottomToTop:
            {
                double curY = parent.Padding.Bottom;
                foreach (GuiWidget child in parent.Children)
                {
                    if (child.Visible == true)
                    {
                        double newY = curY - child.LocalBounds.Bottom + child.Margin.Bottom;
                        child.OriginRelativeParent = new Vector2(child.OriginRelativeParent.x, newY);
                        if (child.VAnchorIsSet(VAnchor.ParentBottomTop))
                        {
                            RectangleDouble curChildBounds = child.LocalBounds;
                            double          newHeight      = (parent.LocalBounds.Height - parent.Padding.Height - totalHeightOfStaticItems) / numItemsNeedingExpanding;
                            child.LocalBounds = new RectangleDouble(curChildBounds.Left, curChildBounds.Bottom,
                                                                    curChildBounds.Right, newHeight);
                        }
                        curY += child.LocalBounds.Height + child.Margin.Height;
                    }
                }
            }
            break;

            case UI.FlowDirection.TopToBottom:
            {
                double curY = parent.LocalBounds.Top - parent.Padding.Top;
                foreach (GuiWidget child in parent.Children)
                {
                    if (child.Visible == true)
                    {
                        if (child.VAnchorIsSet(VAnchor.ParentBottomTop))
                        {
                            RectangleDouble curChildBounds = child.LocalBounds;
                            double          newHeight      = (parent.LocalBounds.Height - parent.Padding.Height - totalHeightOfStaticItems) / numItemsNeedingExpanding;
                            child.LocalBounds = new RectangleDouble(curChildBounds.Left, curChildBounds.Bottom,
                                                                    curChildBounds.Right, newHeight);
                        }

                        double newY = curY - child.LocalBounds.Bottom - (child.LocalBounds.Height + child.Margin.Top);
                        child.OriginRelativeParent = new Vector2(child.OriginRelativeParent.x, newY);
                        curY -= (child.LocalBounds.Height + child.Margin.Height);
                    }
                }
            }
            break;

            default:
                throw new NotImplementedException();
            }
        }
Ejemplo n.º 16
0
        private void DoLayoutChildren(LayoutEventArgs layoutEventArgs)
        {
            GuiWidget parent = layoutEventArgs.ParentWidget;

            if (parent.CountVisibleChildren() == 0)
            {
                return;
            }

            RectangleDouble boundsOfAllChildrenIncludingMargin = RectangleDouble.ZeroIntersection;
            var             totalSizeWithMargin        = Vector2.Zero;
            var             totalSizeOfStaticItems     = Vector2.Zero;
            var             totalMinimumSizeOfAllItems = Vector2.Zero;

            double totalWidthWithMargin  = 0;
            double totalHeightWithMargin = 0;

            foreach (GuiWidget child in parent.Children)
            {
                if (parent.HasBeenClosed)
                {
                    return;
                }

                if (child.Visible == false)
                {
                    continue;
                }

                RectangleDouble childBoundsWithMargin = child.LocalBounds;
                childBoundsWithMargin.Inflate(child.DeviceMarginAndBorder);
                totalWidthWithMargin  += childBoundsWithMargin.Width;
                totalHeightWithMargin += childBoundsWithMargin.Height;
                boundsOfAllChildrenIncludingMargin.ExpandToInclude(childBoundsWithMargin);
            }

            int numItemsNeedingExpanding = CalculateContentSizes(parent,
                                                                 ref totalSizeWithMargin,
                                                                 ref totalSizeOfStaticItems,
                                                                 ref totalMinimumSizeOfAllItems);

            var availableSpaceInParent = new Vector2(parent.LocalBounds.Width - parent.DevicePadding.Width,
                                                     parent.LocalBounds.Height - parent.DevicePadding.Height);
            var sizePerChild = new Vector2((availableSpaceInParent.X - totalSizeOfStaticItems.X) / numItemsNeedingExpanding,
                                           (availableSpaceInParent.Y - totalSizeOfStaticItems.Y) / numItemsNeedingExpanding);

            if (numItemsNeedingExpanding > 0)
            {
                // Iterate all the children and add back in and size that they can't grow bigger than back into the sizePerChild.
                var extraSizeDueToMax = default(Vector2);
                var maxSizeCount      = default(Point2D);

                foreach (GuiWidget child in parent.Children)
                {
                    if (child.MaximumSize.X < sizePerChild.X)
                    {
                        extraSizeDueToMax.X += sizePerChild.X - child.MaximumSize.X;
                        maxSizeCount.x++;
                    }

                    if (child.MaximumSize.Y < sizePerChild.Y)
                    {
                        extraSizeDueToMax.Y += sizePerChild.Y - child.MaximumSize.Y;
                        maxSizeCount.y++;
                    }
                }

                // add back in the amount this item cannot grow to the amount we will try to give each child
                if (maxSizeCount.x > 0)
                {
                    sizePerChild.X += extraSizeDueToMax.X / (numItemsNeedingExpanding - maxSizeCount.x);
                }

                if (maxSizeCount.y > 0)
                {
                    sizePerChild.Y += extraSizeDueToMax.Y / (numItemsNeedingExpanding - maxSizeCount.y);
                }
            }

            switch (FlowDirection)
            {
            case UI.FlowDirection.LeftToRight:
            {
                double curX = parent.DevicePadding.Left;
                foreach (GuiWidget child in parent.Children)
                {
                    if (parent.HasBeenClosed)
                    {
                        return;
                    }

                    if (child.Visible == true)
                    {
                        double newX = curX - child.LocalBounds.Left + child.DeviceMarginAndBorder.Left;
                        child.OriginRelativeParent = new Vector2(newX, child.OriginRelativeParent.Y);
                        if (child.HAnchorIsSet(HAnchor.Stretch))
                        {
                            RectangleDouble curChildBounds = child.LocalBounds;
                            child.LocalBounds = new RectangleDouble(curChildBounds.Left,
                                                                    curChildBounds.Bottom,
                                                                    curChildBounds.Left + sizePerChild.X,
                                                                    curChildBounds.Top);
                        }

                        curX += child.LocalBounds.Width + child.DeviceMarginAndBorder.Width;
                    }
                }
            }

            break;

            case UI.FlowDirection.RightToLeft:
            {
                double curX = parent.LocalBounds.Right - parent.DevicePadding.Right;
                foreach (GuiWidget child in parent.Children)
                {
                    if (parent.HasBeenClosed)
                    {
                        return;
                    }

                    if (child.Visible == true)
                    {
                        if (child.HAnchorIsSet(HAnchor.Stretch))
                        {
                            RectangleDouble curChildBounds = child.LocalBounds;
                            child.LocalBounds = new RectangleDouble(curChildBounds.Left,
                                                                    curChildBounds.Bottom,
                                                                    curChildBounds.Left + sizePerChild.X,
                                                                    curChildBounds.Top);
                        }

                        double newX = curX - child.LocalBounds.Left - (child.LocalBounds.Width + child.DeviceMarginAndBorder.Right);
                        child.OriginRelativeParent = new Vector2(newX, child.OriginRelativeParent.Y);
                        curX -= child.LocalBounds.Width + child.DeviceMarginAndBorder.Width;
                    }
                }
            }

            break;

            case UI.FlowDirection.BottomToTop:
            {
                double curY = parent.DevicePadding.Bottom;
                foreach (GuiWidget child in parent.Children)
                {
                    if (parent.HasBeenClosed)
                    {
                        return;
                    }

                    if (child.Visible == true)
                    {
                        double newY = curY - child.LocalBounds.Bottom + child.DeviceMarginAndBorder.Bottom;
                        child.OriginRelativeParent = new Vector2(child.OriginRelativeParent.X, newY);
                        if (child.VAnchorIsSet(VAnchor.Stretch))
                        {
                            RectangleDouble curChildBounds = child.LocalBounds;
                            child.LocalBounds = new RectangleDouble(curChildBounds.Left,
                                                                    curChildBounds.Bottom,
                                                                    curChildBounds.Right,
                                                                    curChildBounds.Bottom + sizePerChild.Y);
                        }

                        curY += child.LocalBounds.Height + child.DeviceMarginAndBorder.Height;
                    }
                }
            }

            break;

            case UI.FlowDirection.TopToBottom:
            {
                double curY = parent.LocalBounds.Top - parent.DevicePadding.Top;
                foreach (GuiWidget child in parent.Children)
                {
                    if (parent.HasBeenClosed)
                    {
                        return;
                    }

                    if (child.Visible == true)
                    {
                        if (child.VAnchorIsSet(VAnchor.Stretch))
                        {
                            RectangleDouble curChildBounds = child.LocalBounds;
                            child.LocalBounds = new RectangleDouble(curChildBounds.Left,
                                                                    curChildBounds.Bottom,
                                                                    curChildBounds.Right,
                                                                    curChildBounds.Bottom + sizePerChild.Y);
                        }

                        double newY = curY - child.LocalBounds.Bottom - (child.LocalBounds.Height + child.DeviceMarginAndBorder.Top);
                        child.OriginRelativeParent = new Vector2(child.OriginRelativeParent.X, newY);
                        curY -= child.LocalBounds.Height + child.DeviceMarginAndBorder.Height;
                    }
                }
            }

            break;

            default:
                throw new NotImplementedException();
            }
        }
Ejemplo n.º 17
0
		public RectangleDouble GetChildrenBoundsIncludingMargins(bool considerChildAnchor = false)
		{
			RectangleDouble boundsOfAllChildrenIncludingMargin = new RectangleDouble();

			if (this.CountVisibleChildren() > 0)
			{
				Vector2 minSize = Vector2.Zero;
				boundsOfAllChildrenIncludingMargin = RectangleDouble.ZeroIntersection;
				bool foundHBounds = false;
				bool foundVBounds = false;
				foreach (GuiWidget child in Children)
				{
					if (child.Visible == false)
					{
						continue;
					}

					if (considerChildAnchor)
					{
						minSize.x = Math.Max(child.Width + child.Margin.Width, minSize.x);
						minSize.y = Math.Max(child.Height + child.Margin.Height, minSize.y);

						RectangleDouble childBoundsWithMargin = child.BoundsRelativeToParent;
						childBoundsWithMargin.Inflate(child.Margin);

						if (!child.HAnchorIsFloating)
						{
							foundHBounds = true;
							// it can't move so make sure our horizontal bounds enclose it
							if (boundsOfAllChildrenIncludingMargin.Right < childBoundsWithMargin.Right)
							{
								boundsOfAllChildrenIncludingMargin.Right = childBoundsWithMargin.Right;
							}

							if (boundsOfAllChildrenIncludingMargin.Left > childBoundsWithMargin.Left)
							{
								boundsOfAllChildrenIncludingMargin.Left = childBoundsWithMargin.Left;
							}
						}

						if (!child.VAnchorIsFloating)
						{
							foundVBounds = true;
							// it can't move so make sure our vertical bounds enclose it
							if (boundsOfAllChildrenIncludingMargin.Top < childBoundsWithMargin.Top)
							{
								boundsOfAllChildrenIncludingMargin.Top = childBoundsWithMargin.Top;
							}

							if (boundsOfAllChildrenIncludingMargin.Bottom > childBoundsWithMargin.Bottom)
							{
								boundsOfAllChildrenIncludingMargin.Bottom = childBoundsWithMargin.Bottom;
							}
						}
					}
					else
					{
						RectangleDouble childBoundsWithMargin = child.BoundsRelativeToParent;
						childBoundsWithMargin.Inflate(child.Margin);
						boundsOfAllChildrenIncludingMargin.ExpandToInclude(childBoundsWithMargin);
					}
				}

				if (considerChildAnchor)
				{
					if (foundHBounds)
					{
						boundsOfAllChildrenIncludingMargin.Right = boundsOfAllChildrenIncludingMargin.Left + Math.Max(boundsOfAllChildrenIncludingMargin.Width, minSize.x);
					}
					else
					{
						boundsOfAllChildrenIncludingMargin.Left = 0;
						boundsOfAllChildrenIncludingMargin.Right = minSize.x;
					}

					if (foundVBounds)
					{
						boundsOfAllChildrenIncludingMargin.Top = boundsOfAllChildrenIncludingMargin.Bottom + Math.Max(boundsOfAllChildrenIncludingMargin.Height, minSize.y);
					}
					else
					{
						boundsOfAllChildrenIncludingMargin.Bottom = 0;
						boundsOfAllChildrenIncludingMargin.Top = minSize.y;
					}
				}
			}

			return boundsOfAllChildrenIncludingMargin;
		}
Ejemplo n.º 18
0
        private int CalculateContentSizes(GuiWidget parent, ref Vector2 totalSizeWithMargin, ref Vector2 totalSizeOfStaticItems, ref Vector2 totalMinimumSizeOfAllItems)
        {
            int             numItemsNeedingExpanding           = 0;
            RectangleDouble boundsOfAllChildrenIncludingMargin = RectangleDouble.ZeroIntersection;

            foreach (GuiWidget child in parent.Children)
            {
                if (child.Visible == false)
                {
                    continue;
                }

                RectangleDouble childBoundsWithMargin = child.LocalBounds;
                childBoundsWithMargin.Inflate(child.DeviceMarginAndBorder);
                totalSizeWithMargin.X += childBoundsWithMargin.Width;
                totalSizeWithMargin.Y += childBoundsWithMargin.Height;
                boundsOfAllChildrenIncludingMargin.ExpandToInclude(childBoundsWithMargin);

                switch (FlowDirection)
                {
                case UI.FlowDirection.LeftToRight:
                case UI.FlowDirection.RightToLeft:
                    totalMinimumSizeOfAllItems.X += child.MinimumFlowSize().X + child.DeviceMarginAndBorder.Width;
                    totalMinimumSizeOfAllItems.Y  = Math.Max(totalMinimumSizeOfAllItems.Y, child.MinimumFlowSize().Y + child.DeviceMarginAndBorder.Height);

                    if (child.HAnchorIsSet(HAnchor.Stretch))
                    {
                        numItemsNeedingExpanding++;
                        totalSizeOfStaticItems.X += child.DeviceMarginAndBorder.Width;
                    }
                    else if (child.HAnchor == HAnchor.Absolute ||
                             child.HAnchorIsSet(HAnchor.Fit) ||
                             child.HAnchorIsSet(HAnchor.MinFitOrStretch))
                    {
                        totalSizeOfStaticItems.X += childBoundsWithMargin.Width;
                    }
                    else
                    {
                        throw new Exception("Only Absolute or Stretch are valid HAnchor for a horizontal flowWidget.");
                    }

                    break;

                case UI.FlowDirection.TopToBottom:
                case UI.FlowDirection.BottomToTop:
                    totalMinimumSizeOfAllItems.X  = Math.Max(totalMinimumSizeOfAllItems.X, child.MinimumFlowSize().X + child.DeviceMarginAndBorder.Width);
                    totalMinimumSizeOfAllItems.Y += child.MinimumFlowSize().Y + child.DeviceMarginAndBorder.Height;
                    if (child.VAnchorIsSet(VAnchor.Stretch))
                    {
                        numItemsNeedingExpanding++;
                        totalSizeOfStaticItems.Y += child.DeviceMarginAndBorder.Height;
                    }
                    else if (child.VAnchor == VAnchor.Absolute || child.VAnchorIsSet(VAnchor.Fit))
                    {
                        totalSizeOfStaticItems.Y += childBoundsWithMargin.Height;
                    }
                    else
                    {
                        throw new Exception("Only Absolute or Stretch are valid VAnchor for a vertical flowWidget.");
                    }

                    break;

                default:
                    throw new NotImplementedException();
                }
            }

            return(numItemsNeedingExpanding);
        }
        public override string ReadLine()
        {
            // Send any commands that are queue before moving on to the internal stream.
            string nextCommand = queuedCommands.ReadLine();

            if (nextCommand != null)
            {
                return(nextCommand);
            }

            switch (RecoveryState)
            {
            // heat the extrude to remove it from the part
            case RecoveryState.RemoveHeating:
                // TODO: make sure we heat up all the extruders that we need to (all that are used)
                queuedCommands.Add("G21; set units to millimeters");
                queuedCommands.Add("M107; fan off");
                queuedCommands.Add("T0; set the active extruder to 0");
                queuedCommands.Add("G90; use absolute coordinates");
                queuedCommands.Add("G92 E0; reset the expected extruder position");
                queuedCommands.Add("M82; use absolute distance for extrusion");

                bool   hasHeatedBed = printer.Settings.GetValue <bool>(SettingsKey.has_heated_bed);
                double bedTemp      = printer.Settings.GetValue <double>(SettingsKey.bed_temperature);
                if (hasHeatedBed && bedTemp > 0)
                {
                    // start heating the bed
                    queuedCommands.Add($"M140 S{bedTemp}");
                }

                // heat up the extruder
                queuedCommands.Add("M109 S{0}".FormatWith(printer.Settings.Helpers.ExtruderTemperature(0)));

                if (hasHeatedBed && bedTemp > 0)
                {
                    // finish heating the bed
                    queuedCommands.Add($"M190 S{bedTemp}");
                }

                RecoveryState = RecoveryState.Raising;
                return("");

            // remove it from the part
            case RecoveryState.Raising:
                // We don't know where the printer is for sure (it make have been turned off). Disable leveling until we know where it is.
                PrintLevelingStream.AllowLeveling = false;
                queuedCommands.Add("M114 ; get current position");
                queuedCommands.Add("G91 ; move relative");
                queuedCommands.Add("G1 Z10 F{0}".FormatWith(printer.Settings.ZSpeed()));
                queuedCommands.Add("G90 ; move absolute");
                RecoveryState = RecoveryState.Homing;
                return("");

            // if top homing, home the extruder
            case RecoveryState.Homing:
                if (printer.Settings.GetValue <bool>(SettingsKey.z_homes_to_max))
                {
                    queuedCommands.Add("G28");
                }
                else
                {
                    // home x
                    queuedCommands.Add("G28 X0");
                    // home y
                    queuedCommands.Add("G28 Y0");
                    // move to the place we can home z from
                    Vector2 recoveryPositionXy = printer.Settings.GetValue <Vector2>(SettingsKey.recover_position_before_z_home);
                    queuedCommands.Add("G1 X{0:0.###}Y{1:0.###}F{2}".FormatWith(recoveryPositionXy.X, recoveryPositionXy.Y, printer.Settings.XSpeed()));
                    // home z
                    queuedCommands.Add("G28 Z0");
                }
                // We now know where the printer is re-enable print leveling
                PrintLevelingStream.AllowLeveling = true;
                RecoveryState = RecoveryState.FindingRecoveryLayer;
                return("");

            // This is to recover printing if an out a filament occurs.
            // Help the user move the extruder down to just touching the part
            case RecoveryState.FindingRecoveryLayer:
                if (false)                         // help the user get the head to the right position
                {
                    // move to above the completed print
                    // move over a know good part of the model at the current top layer (extrude vertex from gcode)
                    // let the user move down until they like the height
                    // calculate that position and continue
                }
                else                         // we are resuming because of disconnect or reset, skip this
                {
                    RecoveryState = RecoveryState.SkippingGCode;
                    goto case RecoveryState.SkippingGCode;
                }

            case RecoveryState.SkippingGCode:
                // run through the gcode that the device expected looking for things like temp
                // and skip everything else until we get to the point we left off last time
                int commandCount = 0;
                boundsOfSkippedLayers = RectangleDouble.ZeroIntersection;
                while (internalStream.GCodeFile.PercentComplete(internalStream.LineIndex) < percentDone)
                {
                    string line = internalStream.ReadLine();
                    if (line == null)
                    {
                        break;
                    }
                    commandCount++;

                    // make sure we don't parse comments
                    if (line.Contains(";"))
                    {
                        line = line.Split(';')[0];
                    }
                    lastDestination = GetPosition(line, lastDestination);

                    if (commandCount > 100)
                    {
                        boundsOfSkippedLayers.ExpandToInclude(lastDestination.position.Xy);
                    }

                    // check if the line is something we want to send to the printer (like a temp)
                    if (line.StartsWith("M109") ||                          // heat and wait extruder
                        line.StartsWith("M104") ||                                 // heat extruder
                        line.StartsWith("M190") ||                                 // heat and wait bed
                        line.StartsWith("M140") ||                                 // heat bed
                        line.StartsWith("T") ||                                 // switch extruder
                        line.StartsWith("M106") ||                                 // fan on
                        line.StartsWith("M107") ||                                 // fan off
                        line.StartsWith("G92"))                                    // set position
                    {
                        return(line);
                    }
                }

                RecoveryState = RecoveryState.PrimingAndMovingToStart;

                // make sure we always- pick up the last movement
                boundsOfSkippedLayers.ExpandToInclude(lastDestination.position.Xy);
                return("");

            case RecoveryState.PrimingAndMovingToStart:
            {
                if (printer.Settings.GetValue("z_homes_to_max") == "0")                                 // we are homed to the bed
                {
                    // move to the height we can recover printing from
                    Vector2 recoverPositionXy = printer.Settings.GetValue <Vector2>(SettingsKey.recover_position_before_z_home);
                    queuedCommands.Add(CreateMovementLine(new PrinterMove(new VectorMath.Vector3(recoverPositionXy.X, recoverPositionXy.Y, lastDestination.position.Z), 0, printer.Settings.ZSpeed())));
                }

                double extruderWidth = printer.Settings.GetValue <double>(SettingsKey.nozzle_diameter);
                // move to a position outside the printed bounds
                queuedCommands.Add(CreateMovementLine(new PrinterMove(
                                                          new Vector3(boundsOfSkippedLayers.Left - extruderWidth * 2, boundsOfSkippedLayers.Bottom + boundsOfSkippedLayers.Height / 2, lastDestination.position.Z),
                                                          0, printer.Settings.XSpeed())));

                // let's prime the extruder
                queuedCommands.Add("G1 E10 F{0}".FormatWith(printer.Settings.EFeedRate(0))); // extrude 10
                queuedCommands.Add("G1 E9");                                                 // and retract a bit

                // move to the actual print position
                queuedCommands.Add(CreateMovementLine(new PrinterMove(lastDestination.position, 0, printer.Settings.XSpeed())));

                /// reset the printer to know where the filament should be
                queuedCommands.Add("G92 E{0}".FormatWith(lastDestination.extrusion));
                RecoveryState = RecoveryState.PrintingSlow;
            }
                return("");

            case RecoveryState.PrintingSlow:
            {
                string lineToSend = internalStream.ReadLine();
                if (lineToSend == null)
                {
                    return(null);
                }

                if (!GCodeFile.IsLayerChange(lineToSend))
                {
                    // have not seen the end of this layer so keep printing slow
                    if (LineIsMovement(lineToSend))
                    {
                        PrinterMove currentMove = GetPosition(lineToSend, lastDestination);
                        PrinterMove moveToSend  = currentMove;

                        moveToSend.feedRate = recoverFeedRate;

                        lineToSend      = CreateMovementLine(moveToSend, lastDestination);
                        lastDestination = currentMove;
                        return(lineToSend);
                    }

                    return(lineToSend);
                }
            }

                // we only fall through to here after seeing the next "; Layer:"
                RecoveryState = RecoveryState.PrintingToEnd;
                return("");

            case RecoveryState.PrintingToEnd:
                return(internalStream.ReadLine());
            }

            return(null);
        }
Ejemplo n.º 20
0
        private void DoLayoutChildren(LayoutEventArgs layoutEventArgs)
        {
            GuiWidget parent = layoutEventArgs.ParentWidget;

            if (parent.CountVisibleChildren() == 0)
            {
                return;
            }

            RectangleDouble boundsOfAllChildrenIncludingMargin = RectangleDouble.ZeroIntersection;
            var             totalSizeWithMargin        = Vector2.Zero;
            var             totalSizeOfStaticItems     = Vector2.Zero;
            var             totalMinimumSizeOfAllItems = Vector2.Zero;

            double totalWidthWithMargin  = 0;
            double totalHeightWithMargin = 0;

            foreach (GuiWidget child in parent.Children)
            {
                if (parent.HasBeenClosed)
                {
                    return;
                }

                if (child.Visible == false)
                {
                    continue;
                }

                RectangleDouble childBoundsWithMargin = child.LocalBounds;
                childBoundsWithMargin.Inflate(child.DeviceMarginAndBorder);
                totalWidthWithMargin  += childBoundsWithMargin.Width;
                totalHeightWithMargin += childBoundsWithMargin.Height;
                boundsOfAllChildrenIncludingMargin.ExpandToInclude(childBoundsWithMargin);
            }

            int numItemsNeedingExpanding = CalculateContentSizes(parent,
                                                                 ref totalSizeWithMargin,
                                                                 ref totalSizeOfStaticItems,
                                                                 ref totalMinimumSizeOfAllItems);

            switch (FlowDirection)
            {
            case UI.FlowDirection.LeftToRight:
            {
                double curX = parent.DevicePadding.Left;
                foreach (GuiWidget child in parent.Children)
                {
                    if (parent.HasBeenClosed)
                    {
                        return;
                    }

                    if (child.Visible == true)
                    {
                        double newX = curX - child.LocalBounds.Left + child.DeviceMarginAndBorder.Left;
                        child.OriginRelativeParent = new Vector2(newX, child.OriginRelativeParent.Y);
                        if (child.HAnchorIsSet(HAnchor.Stretch))
                        {
                            RectangleDouble curChildBounds = child.LocalBounds;
                            double          newWidth       = (parent.LocalBounds.Width - parent.DevicePadding.Width - totalSizeOfStaticItems.X) / numItemsNeedingExpanding;
                            child.LocalBounds = new RectangleDouble(curChildBounds.Left,
                                                                    curChildBounds.Bottom,
                                                                    curChildBounds.Left + newWidth,
                                                                    curChildBounds.Top);
                        }

                        curX += child.LocalBounds.Width + child.DeviceMarginAndBorder.Width;
                    }
                }
            }

            break;

            case UI.FlowDirection.RightToLeft:
            {
                double curX = parent.LocalBounds.Right - parent.DevicePadding.Right;
                foreach (GuiWidget child in parent.Children)
                {
                    if (parent.HasBeenClosed)
                    {
                        return;
                    }

                    if (child.Visible == true)
                    {
                        if (child.HAnchorIsSet(HAnchor.Stretch))
                        {
                            RectangleDouble curChildBounds = child.LocalBounds;
                            double          newWidth       = (parent.LocalBounds.Width - parent.DevicePadding.Width - totalSizeOfStaticItems.X) / numItemsNeedingExpanding;
                            child.LocalBounds = new RectangleDouble(curChildBounds.Left,
                                                                    curChildBounds.Bottom,
                                                                    curChildBounds.Left + newWidth,
                                                                    curChildBounds.Top);
                        }

                        double newX = curX - child.LocalBounds.Left - (child.LocalBounds.Width + child.DeviceMarginAndBorder.Right);
                        child.OriginRelativeParent = new Vector2(newX, child.OriginRelativeParent.Y);
                        curX -= child.LocalBounds.Width + child.DeviceMarginAndBorder.Width;
                    }
                }
            }

            break;

            case UI.FlowDirection.BottomToTop:
            {
                double curY = parent.DevicePadding.Bottom;
                foreach (GuiWidget child in parent.Children)
                {
                    if (parent.HasBeenClosed)
                    {
                        return;
                    }

                    if (child.Visible == true)
                    {
                        double newY = curY - child.LocalBounds.Bottom + child.DeviceMarginAndBorder.Bottom;
                        child.OriginRelativeParent = new Vector2(child.OriginRelativeParent.X, newY);
                        if (child.VAnchorIsSet(VAnchor.Stretch))
                        {
                            RectangleDouble curChildBounds = child.LocalBounds;
                            double          newHeight      = (parent.LocalBounds.Height - parent.DevicePadding.Height - totalSizeOfStaticItems.Y) / numItemsNeedingExpanding;
                            child.LocalBounds = new RectangleDouble(curChildBounds.Left,
                                                                    curChildBounds.Bottom,
                                                                    curChildBounds.Right,
                                                                    curChildBounds.Bottom + newHeight);
                        }

                        curY += child.LocalBounds.Height + child.DeviceMarginAndBorder.Height;
                    }
                }
            }

            break;

            case UI.FlowDirection.TopToBottom:
            {
                double curY = parent.LocalBounds.Top - parent.DevicePadding.Top;
                foreach (GuiWidget child in parent.Children)
                {
                    if (parent.HasBeenClosed)
                    {
                        return;
                    }

                    if (child.Visible == true)
                    {
                        if (child.VAnchorIsSet(VAnchor.Stretch))
                        {
                            RectangleDouble curChildBounds = child.LocalBounds;
                            double          newHeight      = (parent.LocalBounds.Height - parent.DevicePadding.Height - totalSizeOfStaticItems.Y) / numItemsNeedingExpanding;                                                                       // - child.DeviceMarginAndBorder.Height;
                            child.LocalBounds = new RectangleDouble(curChildBounds.Left,
                                                                    curChildBounds.Bottom,
                                                                    curChildBounds.Right,
                                                                    curChildBounds.Bottom + newHeight);
                        }

                        double newY = curY - child.LocalBounds.Bottom - (child.LocalBounds.Height + child.DeviceMarginAndBorder.Top);
                        child.OriginRelativeParent = new Vector2(child.OriginRelativeParent.X, newY);
                        curY -= child.LocalBounds.Height + child.DeviceMarginAndBorder.Height;
                    }
                }
            }

            break;

            default:
                throw new NotImplementedException();
            }
        }