示例#1
0
        /// <summary>
        /// Draws a box using the characters given in <paramref name="charSet"/>.
        /// The box will be filled with characters if <paramref name="fill"/> is true,
        /// this is a hugh performance plus if <paramref name="fColor"/> equals <paramref name="fFillColor"/> and <paramref name="bColor"/> equals <paramref name="bFillColor"/>.
        /// </summary>
        /// <param name="rect">The dimensions of the box</param>
        /// <param name="charSet">The characters to use to draw the box</param>
        /// <param name="boundary">The boundary to draw in, nothing will be drawn outside this area</param>
        /// <param name="fColor">The foreground color of the edges</param>
        /// <param name="bColor">The background color of the edges</param>
        /// <param name="fill">true if the box should be filled, otherwise false</param>
        /// <param name="fFillColor">The foreground color of the fill</param>
        /// <param name="bFillColor">The background color of the fill</param>
        public static void DrawBox(Rectangle rect, DrawCharacterSet charSet, Rectangle boundary = null,
            ConsoleColor fColor = ConsoleColor.Gray, ConsoleColor bColor = ConsoleColor.Black,
            bool fill = false, ConsoleColor fFillColor = ConsoleColor.Gray, ConsoleColor bFillColor = ConsoleColor.Black)
        {
            if(rect.Width == 0 || rect.Height == 0)
                return;

            #region Corners
            var topLine = charSet.TopLeftCorner + new string(charSet.HorizontalEdge, rect.Width - 2) + charSet.TopRightCorner;
            var bottomLine = charSet.BottomLeftCorner + new string(charSet.HorizontalEdge, rect.Width - 2) + charSet.BottomRightCorner;

            if(boundary != null && topLine.Length + rect.Left > boundary.Left + boundary.Width)
            {
                var charsInside = boundary.Width - (rect.Left - boundary.Left);
                topLine = topLine.Substring(0, charsInside);
                bottomLine = bottomLine.Substring(0, charsInside);
            }

            Write(rect.Left, rect.Top, topLine, null, fColor, bColor);
            var bottomLineTop = rect.Top + rect.Height - 1;
            if(boundary == null || bottomLineTop < boundary.Top + boundary.Height)
                Write(rect.Left, bottomLineTop, bottomLine, null, fColor, bColor);
            #endregion

            #region Left and right edge
            // Drawing of left and right edges is optimized to call Console.Write as few as possible.
            // This is only possible when the box should be filled and all fill-colors equals the edge-colors.
            //     Fill = true
            //         Colors same:
            //             create a string which contains the whole line (edges and fill) => draw in one part
            //         Colors different:
            //             draw the line in 3 parts
            //             TODO: draw edges with dummy chars in between + draw the actual filling afterwards (=> 2 parts instead of 3)
            //     Fill = false
            //         draw the line in 3 parts (existing characters which could be inside the box have to be preserved)

            string middleLine;
            if (fColor == fFillColor && bColor == bFillColor)
                middleLine = charSet.VerticalEdge + new string(charSet.Empty, rect.Width - 2) + charSet.VerticalEdge;
            else
                middleLine = new string(charSet.Empty, rect.Width - 2);

            if (boundary != null &&
                middleLine.Length + rect.Left > boundary.Left + boundary.Width &&
                (fColor == fFillColor && bColor == bFillColor))
            {
                var charsInside = boundary.Width - (rect.Left - boundary.Left);
                middleLine = middleLine.Substring(0, charsInside);
            }

            var middleHeight = rect.Height - 1;
            if (boundary != null && rect.Top + middleHeight > boundary.Top + boundary.Height)
            {
                middleHeight = boundary.Height - (rect.Top - boundary.Top);
            }

            for (int i = 1; i < middleHeight; i++)
            {
                if (!fill || fColor != fFillColor || bColor == bFillColor)
                {
                    Write(rect.Left, rect.Top + i, charSet.VerticalEdge, null, fColor, bColor);
                    var left = rect.Left + rect.Width - 1;
                    if(boundary == null || left < boundary.Left + boundary.Width)
                        Write(left, rect.Top + i, charSet.VerticalEdge, null, fColor, bColor);
                }
                if(fill)
                {
                    if (fColor == fFillColor && bColor == bFillColor)
                    {
                        Write(rect.Left, rect.Top + i, middleLine, null, fColor, bColor);
                    }
                    else
                    {
                        Write(rect.Left + 1, rect.Top + i, middleLine, null, fFillColor, bFillColor);
                    }
                }
            }
            #endregion
        }
示例#2
0
        /// <summary>
        /// Writes <paramref name="o"/> at (<paramref name="left"/>|<paramref name="top"/>)
        /// sets the foreground color to <paramref name="fColor"/> (default: <code>System.ConsoleColor.Gray</code>) and
        /// the background color to <paramref name="bColor"/> (default: <code>System.ConsoleColor.Black</code>)
        /// </summary>
        /// <param name="left">Distance from the left edge of the window in characters</param>
        /// <param name="top">Distance from the top edge of the window in characters</param>
        /// <param name="o">The object to write</param>
        /// <param name="boundary">The boundary to draw in, nothing will be drawn outside this area</param>
        /// <param name="fColor">The foreground color to set</param>
        /// <param name="bColor">The background color to set</param>
        public static void Write(int left, int top, object o, Rectangle boundary = null,
            ConsoleColor fColor = ConsoleColor.Gray, ConsoleColor bColor = ConsoleColor.Black)
        {
            var str = o.ToString();
            if (boundary != null)
            {
                int lastCharLeft = left + str.Length;
                int lastAllowedCharLeft = boundary.Left + boundary.Width;

                if (left > lastAllowedCharLeft) // string is completely out of view
                    return;
                if (lastCharLeft > lastAllowedCharLeft) // string is partially out of view
                    str = str.Substring(0, boundary.Width - (left - boundary.Left));
            }

            // check for changed values, only set what is needed (huge performance plus)
            // Console.CursorLeft and Console.CursorTop get the other value and call
            // SetCursorPosition, which just sets both values directly.
            // That means that SetCursorPosition will always be faster,
            // up to 3,5x times as fast on my system.
            // See ConsoleBenchmark.cs for detailed results.
            if (left != _left || top != _top)
                Console.SetCursorPosition(left, top);
            if (fColor != _fColor)
                Console.ForegroundColor = fColor;
            if (bColor != _bColor)
                Console.BackgroundColor = bColor;

            Console.Write(str);

            // remember the set values
            _left = left;
            // Console.Write moves the cursor to the end of the written text,
            // so have have to adjust our saved value
            _left += str.Length;
            _top = top;
            _fColor = fColor;
            _bColor = bColor;
        }
示例#3
0
 private void CalculateRootBound()
 {
     var rootBound = STANDARD_ROOT_BOUNDARY;
     // Size dedection will work on windows and on most unix-systems
     // mono uses the same values for Window- and Buffer-Properties,
     // so it doesn't matter which values are used.
     if (Console.WindowHeight != 0)
         rootBound = new Rectangle(0, 0, Console.WindowHeight, Console.WindowWidth);
     RootContainer.Drawer.CalculateBoundary(0, 0, rootBound);
 }