Пример #1
0
        /*
         * Align elements horizontally and return a canvas.
         * Elements include Canvas and MathText.
         */
        public AlignCanvas ArrangeHorizontalGroup(params FrameworkElement[] elements)
        {
            AlignCanvas board = new AlignCanvas();
            //  maxAlignDepth: the max depth from the top, where all nodes are to be aligned
            double startWidth = 0, maxAlignDepth = 0;

            // set each element's left margin
            foreach (var element in elements)
            {
                AlignCanvas.SetLeft(element, startWidth);
                if (element is MathText)
                {
                    element.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
                    startWidth += element.DesiredSize.Width;
                    if (maxAlignDepth < element.DesiredSize.Height / 2)
                    {
                        maxAlignDepth = element.DesiredSize.Height / 2;
                    }
                }
                else
                {
                    // it's a canvas.
                    startWidth += element.Width;
                    if (maxAlignDepth < (element as AlignCanvas).alignHeight)
                    {
                        maxAlignDepth = (element as AlignCanvas).alignHeight;
                    }
                }
            }

            // set each element's top margin
            double maxDepth = 0;

            foreach (var element in elements)
            {
                if (element is MathText)
                {
                    AlignCanvas.SetTop(element, maxAlignDepth - element.DesiredSize.Height / 2);
                    if (element.DesiredSize.Height + maxAlignDepth - element.DesiredSize.Height / 2 > maxDepth)
                    {
                        maxDepth = element.DesiredSize.Height + maxAlignDepth - element.DesiredSize.Height / 2;
                    }
                }
                else
                {
                    AlignCanvas.SetTop(element, maxAlignDepth - (element as AlignCanvas).alignHeight);
                    if (element.Height + maxAlignDepth - (element as AlignCanvas).alignHeight > maxDepth)
                    {
                        maxDepth = element.Height + maxAlignDepth - (element as AlignCanvas).alignHeight;
                    }
                }
                board.Children.Add(element);
            }
            board.Width       = startWidth;
            board.Height      = maxDepth;
            board.alignHeight = maxAlignDepth;
            return(board);
        }
Пример #2
0
        public AlignCanvas ArrangeVerticalGroup(params FrameworkElement[] elements)
        {
            AlignCanvas board = new AlignCanvas();
            double      startDepth = 0, maxWidth = 0;

            // set each element's left margin
            foreach (var element in elements)
            {
                AlignCanvas.SetTop(element, startDepth);
                if (element is Rectangle) // fraction bar
                {
                    board.alignHeight = startDepth;
                }
                if (element is MathText)
                {
                    element.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
                    startDepth += element.DesiredSize.Height;
                    if (maxWidth < element.DesiredSize.Width)
                    {
                        maxWidth = element.DesiredSize.Width;
                    }
                }
                else
                {
                    // it's a canvas or sth like that.
                    startDepth += element.Height;
                    if (maxWidth < element.Width)
                    {
                        maxWidth = element.Width;
                    }
                }
            }

            // set each element's top margin
            foreach (var element in elements)
            {
                if (element is MathText)
                {
                    AlignCanvas.SetLeft(element, (maxWidth - element.DesiredSize.Width) / 2);
                }
                else
                {
                    AlignCanvas.SetLeft(element, (maxWidth - element.Width) / 2);
                }
                board.Children.Add(element);
            }
            board.Height = startDepth;
            board.Width  = maxWidth;
            if (board.alignHeight == 0)
            {
                board.alignHeight = startDepth;
            }
            return(board);
        }
Пример #3
0
        public AlignCanvas RenderElement(Calc_node exp, double fontsize = defaultFontSize)
        {
            AlignCanvas board = null;

            if (exp is Value_node)
            {
                MathText text = null;
                if (exp.isint)
                {
                    text = new MathText(exp.result.ToString(), fontsize);
                }
                else
                {
                    text = new MathText(exp.fresult.ToString(), fontsize);
                }
                board = ArrangeHorizontalGroup(text);
                // board.alignHeight = text.DesiredSize.Height;
            }
            else if (exp is Bracket_node)
            {
                // we separate brackets and inner text
                MathText    lparen     = new MathText("(", fontsize);
                AlignCanvas inner_text = RenderElement((exp as Bracket_node).internal_node, fontsize);
                MathText    rparen     = new MathText(")", fontsize);
                // arrange positions of these elements
                board = ArrangeHorizontalGroup(lparen, inner_text, rparen);
            }
            else if (exp is Binary_node)
            {
                AlignCanvas operand1 = null, operand2 = null;
                switch ((exp as Binary_node).op)
                {
                // horizontal expressions
                case Binary_node.Operator.ADD:
                case Binary_node.Operator.MINUS:
                case Binary_node.Operator.MULTI:
                    operand1 = RenderElement((exp as Binary_node).node1, fontsize);
                    MathText add = new MathText(opID[(int)(exp as Binary_node).op], fontsize);
                    operand2 = RenderElement((exp as Binary_node).node2, fontsize);
                    board    = ArrangeHorizontalGroup(operand1, add, operand2);
                    break;

                // vertical expressions
                case Binary_node.Operator.DIVIDE:
                    operand1 = RenderElement((exp as Binary_node).node1, fontsize * shrinkRatio);
                    operand2 = RenderElement((exp as Binary_node).node2, fontsize * shrinkRatio);
                    // strip the bracket if operand2 is a bracket node
                    if (operand2.Children.Count == 3 && operand2.Children[0] is MathText && operand2.Children[2] is MathText)
                    {
                        AlignCanvas inner_node = operand2.Children[1] as AlignCanvas;
                        operand2.Children.Remove(inner_node);
                        operand2 = inner_node;
                    }
                    Rectangle fractline = new Rectangle();
                    // fractline's width should be the longer of two elements
                    fractline.Width  = (operand1.Width > operand2.Width ? operand1.Width : operand2.Width) * 1.1;
                    fractline.Height = fractionBarHeight;
                    fractline.Fill   = System.Windows.Media.Brushes.Black;
                    fractline.HorizontalAlignment = HorizontalAlignment.Center;
                    board = ArrangeVerticalGroup(operand1, fractline, operand2);
                    break;

                // miscellaneous
                case Binary_node.Operator.EXPO:
                    operand1 = RenderElement((exp as Binary_node).node1, fontsize);
                    operand2 = RenderElement((exp as Binary_node).node2, fontsize * expoRatio);
                    board    = new AlignCanvas();
                    Canvas.SetTop(operand1, operand2.Height / 2);
                    Canvas.SetLeft(operand1, 0);
                    board.Children.Add(operand1);
                    Canvas.SetTop(operand2, 0);
                    Canvas.SetLeft(operand2, operand1.Width);
                    board.Children.Add(operand2);
                    board.Height      = operand1.Height + operand2.Height / 2;
                    board.Width       = operand1.Width + operand2.Width;
                    board.alignHeight = operand1.alignHeight + operand2.Height / 2; // this step is important
                    break;

                case Binary_node.Operator.LOG:
                    MathText logID = new MathText("log", fontsize);
                    operand1 = RenderElement((exp as Binary_node).node1, fontsize * logRatio);
                    MathText lparen = new MathText("(", fontsize);
                    operand2 = RenderElement((exp as Binary_node).node2, fontsize);
                    MathText rparen = new MathText(")", fontsize);
                    // first, we apply ArrangeHorizontal
                    board = ArrangeHorizontalGroup(logID, operand1, lparen, operand2, rparen);
                    // then, adjust operand1
                    board.Children.Remove(operand1);
                    Canvas.SetTop(operand1, Canvas.GetTop(board.Children[0]) + board.Children[0].DesiredSize.Height * 2 / 3);
                    board.Children.Add(operand1);
                    // update height of canvas `board`
                    board.Height = Math.Max(Canvas.GetTop(board.Children[0]) + board.Children[0].DesiredSize.Height * 2 / 3 + operand1.Height, board.Height);
                    break;

                default:
                    break;
                }
            }
            else if (exp is Unary_node)
            {
                MathText    funcText   = new MathText(funcID[(int)(exp as Unary_node).func] + "(", fontsize);
                AlignCanvas inner_node = RenderElement((exp as Unary_node).node1, fontsize);
                MathText    rparen     = new MathText(")", fontsize);
                board = ArrangeHorizontalGroup(funcText, inner_node, rparen);
            }
            else if (exp == null)
            {
                Rectangle placeholder = new Rectangle();
                placeholder.Width  = fontsize;
                placeholder.Height = fontsize;
                placeholder.Fill   = System.Windows.Media.Brushes.LightBlue;
                board = new AlignCanvas();
                board.Children.Add(placeholder);
                board.Height      = placeholder.Height;
                board.Width       = placeholder.Width;
                board.alignHeight = board.Height / 2;
            }
            return(board);
        }