Example #1
0
 /// <summary>
 /// Draws a text
 /// </summary>
 /// <param name="text">The text which will be drawn.</param>
 /// <param name="position">The drawing location on screen.</param>
 /// <param name="color">A color mask.</param>
 /// <param name="layerDepth">A depth of the layer of this string.</param>
 public void DrawString(SpriteFontBase font, string text, Vector2 position, Color color, float layerDepth = 0.0f)
 {
     font.DrawText(_renderer, text, position, CrossEngineStuff.MultiplyColor(color, Opacity), layerDepth);
 }
Example #2
0
        private void RenderSelection(RenderContext context)
        {
            var bounds = ActualBounds;

            if (string.IsNullOrEmpty(Text) || Selection == null)
            {
                return;
            }

            var selectStart = Math.Min(SelectStart, SelectEnd);
            var selectEnd   = Math.Max(SelectStart, SelectEnd);

            if (selectStart >= selectEnd)
            {
                return;
            }

            var startGlyph = _formattedText.GetGlyphInfoByIndex(selectStart);

            if (startGlyph == null)
            {
                return;
            }

            var lineIndex = startGlyph.TextLine.LineIndex;
            var i         = selectStart;

            while (true)
            {
                startGlyph = _formattedText.GetGlyphInfoByIndex(i);
                var startPosition = GetRenderPositionByIndex(i);

                if (selectEnd < i + startGlyph.TextLine.Count)
                {
                    var endPosition = GetRenderPositionByIndex(selectEnd);

                    context.Draw(Selection,
                                 new Rectangle(startPosition.X - _internalScrolling.X,
                                               startPosition.Y - _internalScrolling.Y,
                                               endPosition.X - startPosition.X,
                                               CrossEngineStuff.LineSpacing(_formattedText.Font)));

                    break;
                }

                context.Draw(Selection,
                             new Rectangle(startPosition.X - _internalScrolling.X,
                                           startPosition.Y - _internalScrolling.Y,
                                           bounds.Left + startGlyph.TextLine.Size.X - startPosition.X,
                                           CrossEngineStuff.LineSpacing(_formattedText.Font)));

                ++lineIndex;
                if (lineIndex >= _formattedText.Strings.Length)
                {
                    break;
                }

                i = 0;
                for (var k = 0; k < lineIndex; ++k)
                {
                    i += _formattedText.Strings[k].Count;
                }
            }
        }
Example #3
0
        private void UpdateScrolling()
        {
            var p = GetRenderPositionByIndex(CursorPosition);

            if (p == _lastCursorPosition)
            {
                return;
            }

            var asScrollViewer = Parent as ScrollViewer;

            Point sz, maximum;
            var   bounds = ActualBounds;

            if (asScrollViewer != null)
            {
                asScrollViewer.UpdateLayout();
                sz      = new Point(asScrollViewer.Bounds.Width, asScrollViewer.Bounds.Height);
                maximum = asScrollViewer.ScrollMaximum;
            }
            else
            {
                sz      = new Point(Bounds.Width, Bounds.Height);
                maximum = new Point(_formattedText.Size.X + CursorWidth - sz.X,
                                    _formattedText.Size.Y - sz.Y);

                if (maximum.X < 0)
                {
                    maximum.X = 0;
                }

                if (maximum.Y < 0)
                {
                    maximum.Y = 0;
                }
            }

            if (maximum == Point.Zero)
            {
                _internalScrolling  = Point.Zero;
                _lastCursorPosition = p;
                return;
            }

            p.X -= bounds.X;
            p.Y -= bounds.Y;

            var lineHeight = CrossEngineStuff.LineSpacing(_formattedText.Font);

            Point sp;

            if (asScrollViewer != null)
            {
                sp = asScrollViewer.ScrollPosition;
            }
            else
            {
                sp = _internalScrolling;
            }

            if (p.Y < sp.Y)
            {
                sp.Y = p.Y;
            }
            else if (p.Y + lineHeight > sp.Y + sz.Y)
            {
                sp.Y = p.Y + lineHeight - sz.Y;
            }

            if (p.X < sp.X)
            {
                sp.X = p.X;
            }
            else if (p.X + CursorWidth > sp.X + sz.X)
            {
                sp.X = p.X + CursorWidth - sz.X;
            }

            if (asScrollViewer != null)
            {
                asScrollViewer.ScrollPosition = sp;
            }
            else
            {
                if (sp.X < 0)
                {
                    sp.X = 0;
                }

                if (sp.X > maximum.X)
                {
                    sp.X = maximum.X;
                }

                if (sp.Y < 0)
                {
                    sp.Y = 0;
                }

                if (sp.Y > maximum.Y)
                {
                    sp.Y = maximum.Y;
                }

                _internalScrolling = sp;
            }

            _lastCursorPosition = p;
        }
Example #4
0
        internal ChunkInfo LayoutRow(int startIndex, int?width, bool parseCommands)
        {
            var r = new ChunkInfo
            {
                StartIndex = startIndex,
                LineEnd    = true
            };

            if (string.IsNullOrEmpty(_text))
            {
                return(r);
            }

            _stringBuilder.Clear();
            int?  lastBreakPosition = null;
            Point?lastBreakMeasure  = null;

            for (var i = r.StartIndex; i < _text.Length; ++i)
            {
                var c = _text[i];

                if (SupportsCommands && c == '\\')
                {
                    if (i < _text.Length - 2 && _text[i + 1] == 'c' && _text[i + 2] == '{')
                    {
                        // Find end
                        var startPos = i + 3;
                        var j        = _text.IndexOf('}', startPos);

                        if (j != -1)
                        {
                            // Found
                            if (i > r.StartIndex)
                            {
                                // Break right here, as next chunk has another color
                                r.LineEnd = false;
                                return(r);
                            }

                            if (parseCommands)
                            {
                                r.Color = _text.Substring(startPos, j - startPos).FromName();
                            }

                            r.StartIndex = j + 1;
                            i            = j;
                            continue;
                        }
                    }
                }

                _stringBuilder.Append(c);

                var sz = Point.Zero;

                if (c != '\n')
                {
                    var v = Font.MeasureString(_stringBuilder);
                    sz = new Point((int)v.X, (int)v.Y);
                }
                else
                {
                    sz = new Point(r.X + NewLineWidth, Math.Max(r.Y, CrossEngineStuff.LineSpacing(_font)));

                    // Break right here
                    ++r.CharsCount;
                    r.X = sz.X;
                    r.Y = sz.Y;
                    break;
                }

                if (width != null && sz.X > width.Value)
                {
                    if (lastBreakPosition != null)
                    {
                        r.CharsCount = lastBreakPosition.Value - r.StartIndex;
                    }

                    if (lastBreakMeasure != null)
                    {
                        r.X = lastBreakMeasure.Value.X;
                        r.Y = lastBreakMeasure.Value.Y;
                    }

                    break;
                }

                if (char.IsWhiteSpace(c))
                {
                    lastBreakPosition = i + 1;
                    lastBreakMeasure  = sz;
                }

                ++r.CharsCount;
                r.X = sz.X;
                r.Y = sz.Y;
            }

            return(r);
        }
Example #5
0
        public void Render(RenderContext context)
        {
            if (!Visible)
            {
                return;
            }

            UpdateLayout();

            var view = Rectangle.Intersect(context.View, Bounds);

            if (view.Width == 0 || view.Height == 0)
            {
                return;
            }

            var batch = context.Batch;
            var oldScissorRectangle = CrossEngineStuff.GetScissor();

            if (ClipToBounds && !MyraEnvironment.DisableClipping)
            {
                var newScissorRectangle = Rectangle.Intersect(oldScissorRectangle, view);

                if (newScissorRectangle.IsEmpty)
                {
                    return;
                }

                context.Flush();

                CrossEngineStuff.SetScissor(newScissorRectangle);
            }

            var oldOpacity = context.Opacity;

            context.Opacity *= Opacity;

            // Background
            var background = GetCurrentBackground();

            if (background != null)
            {
                context.Draw(background, Bounds);
            }

            var oldView = context.View;

            context.View = view;
            InternalRender(context);
            context.View = oldView;

            // Border
            var border = GetCurrentBorder();

            if (border != null)
            {
                context.Draw(border, Bounds);
            }

            if (MyraEnvironment.DrawWidgetsFrames)
            {
                batch.DrawRectangle(Bounds, Color.LightGreen);
            }

            if (MyraEnvironment.DrawKeyboardFocusedWidgetFrame && IsKeyboardFocused)
            {
                batch.DrawRectangle(Bounds, Color.Red);
            }

            if (MyraEnvironment.DrawMouseWheelFocusedWidgetFrame && IsMouseWheelFocused)
            {
                batch.DrawRectangle(Bounds, Color.Yellow);
            }

            if (ClipToBounds && !MyraEnvironment.DisableClipping)
            {
                context.Flush();
                CrossEngineStuff.SetScissor(oldScissorRectangle);
            }

            context.Opacity = oldOpacity;
        }
Example #6
0
        public void Render(RenderContext context)
        {
            if (!Visible)
            {
                return;
            }

            UpdateLayout();

            var view = Rectangle.Intersect(context.View, Bounds);

            if (view.Width == 0 || view.Height == 0)
            {
                return;
            }

            var batch = context.Batch;
            var oldScissorRectangle = CrossEngineStuff.GetScissor();

            if (ClipToBounds && !MyraEnvironment.DisableClipping)
            {
                var newScissorRectangle = Rectangle.Intersect(oldScissorRectangle, view);

                if (newScissorRectangle.IsEmpty)
                {
                    return;
                }

                context.Flush();

                CrossEngineStuff.SetScissor(newScissorRectangle);
            }

            var oldOpacity = context.Opacity;
            var oldView    = context.View;

            context.Opacity *= Opacity;
            context.View     = view;

            BeforeRender?.Invoke(context);

            // Background
            var background = GetCurrentBackground();

            if (background != null)
            {
                context.Draw(background, BackgroundBounds);
            }

            // Borders
            var border = GetCurrentBorder();

            if (border != null)
            {
                var borderBounds = BorderBounds;
                if (BorderThickness.Left > 0)
                {
                    context.Draw(border, new Rectangle(borderBounds.X, borderBounds.Y, BorderThickness.Left, borderBounds.Height));
                }

                if (BorderThickness.Top > 0)
                {
                    context.Draw(border, new Rectangle(borderBounds.X, borderBounds.Y, borderBounds.Width, BorderThickness.Top));
                }

                if (BorderThickness.Right > 0)
                {
                    context.Draw(border, new Rectangle(borderBounds.Right - BorderThickness.Right, borderBounds.Y, BorderThickness.Right, borderBounds.Height));
                }

                if (BorderThickness.Bottom > 0)
                {
                    context.Draw(border, new Rectangle(borderBounds.X, borderBounds.Bottom - BorderThickness.Bottom, borderBounds.Width, BorderThickness.Bottom));
                }
            }

            InternalRender(context);

            AfterRender?.Invoke(context);

            // Restore context settings
            context.View    = oldView;
            context.Opacity = oldOpacity;

            // Optional debug rendering
            if (MyraEnvironment.DrawWidgetsFrames)
            {
                batch.DrawRectangle(Bounds, Color.LightGreen);
            }

            if (MyraEnvironment.DrawKeyboardFocusedWidgetFrame && IsKeyboardFocused)
            {
                batch.DrawRectangle(Bounds, Color.Red);
            }

            if (MyraEnvironment.DrawMouseWheelFocusedWidgetFrame && IsMouseWheelFocused)
            {
                batch.DrawRectangle(Bounds, Color.Yellow);
            }

            if (ClipToBounds && !MyraEnvironment.DisableClipping)
            {
                // Restore scissor
                context.Flush();
                CrossEngineStuff.SetScissor(oldScissorRectangle);
            }
        }
Example #7
0
        public override void InternalRender(RenderContext context)
        {
            if (_formattedText.Font == null)
            {
                return;
            }

            var bounds = ActualBounds;

            if (Selection != null && !string.IsNullOrEmpty(Text))
            {
                var selectStart = Math.Min(SelectStart, SelectEnd);
                var selectEnd   = Math.Max(SelectStart, SelectEnd);

                if (selectStart < selectEnd)
                {
                    //					Debug.WriteLine("{0} - {1}", selectStart, selectEnd);

                    var startGlyph = _formattedText.GetGlyphInfoByIndex(selectStart);
                    var lineIndex  = startGlyph.TextLine.LineIndex;
                    var i          = selectStart;

                    while (true)
                    {
                        startGlyph = _formattedText.GetGlyphInfoByIndex(i);
                        var startPosition = GetRenderPositionByIndex(i);

                        if (selectEnd < i + startGlyph.TextLine.Count)
                        {
                            var endPosition = GetRenderPositionByIndex(selectEnd);

                            context.Draw(Selection,
                                         new Rectangle(startPosition.X - _internalScrolling.X,
                                                       startPosition.Y - _internalScrolling.Y,
                                                       endPosition.X - startPosition.X,
                                                       CrossEngineStuff.LineSpacing(_formattedText.Font)));

                            break;
                        }

                        context.Draw(Selection,
                                     new Rectangle(startPosition.X - _internalScrolling.X,
                                                   startPosition.Y - _internalScrolling.Y,
                                                   bounds.Left + startGlyph.TextLine.Size.X - startPosition.X,
                                                   CrossEngineStuff.LineSpacing(_formattedText.Font)));

                        ++lineIndex;
                        if (lineIndex >= _formattedText.Strings.Length)
                        {
                            break;
                        }

                        i = 0;
                        for (var k = 0; k < lineIndex; ++k)
                        {
                            i += _formattedText.Strings[k].Count;
                        }
                    }
                }
            }

            var textColor = TextColor;

            if (!Enabled && DisabledTextColor != null)
            {
                textColor = DisabledTextColor.Value;
            }
            else if (IsKeyboardFocused && FocusedTextColor != null)
            {
                textColor = FocusedTextColor.Value;
            }

            var centeredBounds = LayoutUtils.Align(new Point(bounds.Width, bounds.Height), _formattedText.Size, HorizontalAlignment.Left, TextVerticalAlignment);

            centeredBounds.Offset(bounds.Location);

            var p = new Point(centeredBounds.Location.X - _internalScrolling.X,
                              centeredBounds.Location.Y - _internalScrolling.Y);

            _formattedText.Draw(context.Batch,
                                p,
                                context.View, textColor, context.Opacity);

            if (!IsKeyboardFocused)
            {
                // Skip cursor rendering if the widget doesnt have the focus
                return;
            }

            var now = DateTime.Now;

            if ((now - _lastBlinkStamp).TotalMilliseconds >= BlinkIntervalInMs)
            {
                _cursorOn       = !_cursorOn;
                _lastBlinkStamp = now;
            }

            if (Enabled && _cursorOn && Cursor != null)
            {
                p    = GetRenderPositionByIndex(CursorPosition);
                p.X -= _internalScrolling.X;
                p.Y -= _internalScrolling.Y;
                context.Draw(Cursor,
                             new Rectangle(p.X, p.Y,
                                           Cursor.Size.X,
                                           CrossEngineStuff.LineSpacing(_formattedText.Font)));
            }
        }
Example #8
0
        public override void InternalRender(RenderContext context)
        {
            if (_formattedText.Font == null)
            {
                return;
            }

            var bounds = ActualBounds;

            RenderSelection(context);

            var textColor = TextColor;
            var opacity   = context.Opacity;

            if (HintTextEnabled)
            {
                opacity *= 0.5f;
            }
            else if (!Enabled && DisabledTextColor != null)
            {
                textColor = DisabledTextColor.Value;
            }
            else if (IsKeyboardFocused && FocusedTextColor != null)
            {
                textColor = FocusedTextColor.Value;
            }

            var centeredBounds = LayoutUtils.Align(new Point(bounds.Width, bounds.Height), _formattedText.Size, HorizontalAlignment.Left, TextVerticalAlignment);

            centeredBounds.Offset(bounds.Location);

            var p = new Point(centeredBounds.Location.X - _internalScrolling.X,
                              centeredBounds.Location.Y - _internalScrolling.Y);

            _formattedText.Draw(context.Batch, TextAlign.Left, bounds, context.View, textColor, false, opacity);

            if (!IsKeyboardFocused)
            {
                // Skip cursor rendering if the widget doesnt have the focus
                return;
            }

            var now = DateTime.Now;

            if ((now - _lastBlinkStamp).TotalMilliseconds >= BlinkIntervalInMs)
            {
                _cursorOn       = !_cursorOn;
                _lastBlinkStamp = now;
            }

            if (Enabled && _cursorOn && Cursor != null)
            {
                p    = GetRenderPositionByIndex(CursorPosition);
                p.X -= _internalScrolling.X;
                p.Y -= _internalScrolling.Y;
                context.Draw(Cursor,
                             new Rectangle(p.X, p.Y,
                                           Cursor.Size.X,
                                           CrossEngineStuff.LineSpacing(_formattedText.Font)));
            }
        }
Example #9
0
        private void RenderSelection(RenderContext context)
        {
            var bounds = ActualBounds;

            if (string.IsNullOrEmpty(Text) || Selection == null)
            {
                return;
            }

            var selectStart = Math.Min(SelectStart, SelectEnd);
            var selectEnd   = Math.Max(SelectStart, SelectEnd);

            if (selectStart >= selectEnd)
            {
                return;
            }

            var startGlyph = _formattedText.GetGlyphInfoByIndex(selectStart);

            if (startGlyph == null)
            {
                return;
            }

            var lineIndex = startGlyph.TextChunk.LineIndex;
            var i         = selectStart;

            var lineHeight = CrossEngineStuff.LineSpacing(_formattedText.Font);

            while (true)
            {
                startGlyph = _formattedText.GetGlyphInfoByIndex(i);
                var startPosition = GetRenderPositionByIndex(i);

                var line = _formattedText.Lines[startGlyph.TextChunk.LineIndex];

                if (selectEnd < line.TextStartIndex + line.Count)
                {
                    var endPosition = GetRenderPositionByIndex(selectEnd);

                    context.Draw(Selection,
                                 new Rectangle(startPosition.X - _internalScrolling.X,
                                               startPosition.Y - _internalScrolling.Y,
                                               endPosition.X - startPosition.X,
                                               lineHeight));

                    break;
                }

                context.Draw(Selection,
                             new Rectangle(startPosition.X - _internalScrolling.X,
                                           startPosition.Y - _internalScrolling.Y,
                                           bounds.Left + startGlyph.TextChunk.Size.X - startPosition.X,
                                           lineHeight));

                ++lineIndex;
                if (lineIndex >= _formattedText.Lines.Count)
                {
                    break;
                }

                i = _formattedText.Lines[lineIndex].TextStartIndex;
            }
        }
Example #10
0
        public Point Measure(int?width)
        {
            var result = Point.Zero;

            var key = GetMeasureKey(width);

            if (_measures.TryGetValue(key, out result))
            {
                return(result);
            }

            if (!string.IsNullOrEmpty(_text))
            {
                var i = 0;
                var y = 0;

                var remainingWidth = width;
                var lineWidth      = 0;
                while (i < _text.Length)
                {
                    var chunkInfo = LayoutRow(i, remainingWidth, false);
                    if (i == chunkInfo.StartIndex && chunkInfo.CharsCount == 0)
                    {
                        break;
                    }

                    lineWidth += chunkInfo.X;
                    i          = chunkInfo.StartIndex + chunkInfo.CharsCount;

                    if (remainingWidth.HasValue)
                    {
                        remainingWidth = remainingWidth.Value - chunkInfo.X;
                    }

                    if (chunkInfo.LineEnd)
                    {
                        if (lineWidth > result.X)
                        {
                            result.X = lineWidth;
                        }

                        lineWidth      = 0;
                        remainingWidth = width;

                        y += chunkInfo.Y;
                        y += _verticalSpacing;
                    }
                }

                result.Y = y;
            }

            if (result.Y == 0)
            {
                result.Y = CrossEngineStuff.LineSpacing(_font);
            }

            _measures[key] = result;

            return(result);
        }
Example #11
0
        internal void Update()
        {
            if (!_dirty)
            {
                return;
            }

            if (!string.IsNullOrEmpty(_text))
            {
                var sz = _spriteFont.MeasureString(_text);
                _size = new Point((int)sz.X, (int)sz.Y);
#if MONOGAME
                var fontGlyphs = _spriteFont.GetGlyphs();

                var offset           = Vector2.Zero;
                var firstGlyphOfLine = true;

                for (var i = 0; i < _text.Length; ++i)
                {
                    SpriteFont.Glyph g;
                    fontGlyphs.TryGetValue(_text[i], out g);

                    // The first character on a line might have a negative left side bearing.
                    // In this scenario, SpriteBatch/SpriteFont normally offset the text to the right,
                    //  so that text does not hang off the left side of its rectangle.
                    if (firstGlyphOfLine)
                    {
                        offset.X         = Math.Max(g.LeftSideBearing, 0);
                        firstGlyphOfLine = false;
                    }
                    else
                    {
                        offset.X += _spriteFont.Spacing + g.LeftSideBearing;
                    }

                    var p = offset;

                    p += g.Cropping.Location.ToVector2();

                    var result = new Rectangle((int)p.X, (int)p.Y, (int)(g.Width + g.RightSideBearing), g.BoundsInTexture.Height);

                    _glyphs[i].Bounds = result;

                    offset.X += g.Width + g.RightSideBearing;
                }
#else
                var offset = Vector2.Zero;
                for (var i = 0; i < _text.Length; ++i)
                {
                    Vector2 v      = _spriteFont.MeasureString(_text[i].ToString());
                    var     result = new Rectangle((int)offset.X, (int)offset.Y, (int)v.X, (int)v.Y);

                    _glyphs[i].Bounds = result;

                    offset.X += v.X;
                }
#endif
            }
            else
            {
                _size = new Point(0, CrossEngineStuff.LineSpacing(_spriteFont));
            }

            _dirty = false;
        }
Example #12
0
        internal TextEditRow LayoutRow(int startIndex, int?width)
        {
            var r = new TextEditRow();

            if (string.IsNullOrEmpty(_text))
            {
                return(r);
            }

            _stringBuilder.Clear();
            int?    lastBreakPosition = null;
            Vector2?lastBreakMeasure  = null;

            for (var i = startIndex; i < _text.Length; ++i)
            {
                var c = _displayText[i];

                _stringBuilder.Append(c);

                Vector2 sz = Vector2.Zero;

                if (c != '\n')
                {
                    sz = Font.MeasureString(_stringBuilder);
                }
                else
                {
                    sz = new Vector2(r.x1 + NewLineWidth, Math.Max(r.ymax, CrossEngineStuff.LineSpacing(_font)));
                }

                if (width != null && c == '\n')
                {
                    // Break right here
                    ++r.num_chars;
                    r.x1               = sz.X;
                    r.ymax             = sz.Y;
                    r.baseline_y_delta = sz.Y;
                    break;
                }

                if (width != null && sz.X > width.Value)
                {
                    if (lastBreakPosition != null)
                    {
                        r.num_chars = lastBreakPosition.Value - startIndex;
                    }

                    if (lastBreakMeasure != null)
                    {
                        r.x1               = lastBreakMeasure.Value.X;
                        r.ymax             = lastBreakMeasure.Value.Y;
                        r.baseline_y_delta = lastBreakMeasure.Value.Y;
                    }

                    break;
                }

                if (char.IsWhiteSpace(c))
                {
                    lastBreakPosition = i + 1;
                    lastBreakMeasure  = sz;
                }

                ++r.num_chars;
                r.x1               = sz.X;
                r.ymax             = sz.Y;
                r.baseline_y_delta = sz.Y;
            }

            return(r);
        }