Beispiel #1
0
        void RenderLineNumberIcon(Widget widget, Cairo.Context cr, Gdk.Rectangle cell_area, int markupHeight, int yOffset)
        {
            if (!IsStackFrame)
            {
                return;
            }

            cr.Save();

                        #if CENTER_ROUNDED_RECTANGLE
            cr.Translate(cell_area.X + Padding, (cell_area.Y + (cell_area.Height - RoundedRectangleHeight) / 2.0));
                        #else
            cr.Translate(cell_area.X + Padding, cell_area.Y + Padding + yOffset);
                        #endif

            cr.Antialias = Cairo.Antialias.Subpixel;

            cr.RoundedRectangle(0.0, 0.0, RoundedRectangleWidth, RoundedRectangleHeight, RoundedRectangleRadius);
            cr.Clip();

            if (IsUserCode)
            {
                cr.SetSourceRGBA(0.90, 0.60, 0.87, 1.0);                  // 230, 152, 223
            }
            else
            {
                cr.SetSourceRGBA(0.77, 0.77, 0.77, 1.0);                  // 197, 197, 197
            }
            cr.RoundedRectangle(0.0, 0.0, RoundedRectangleWidth, RoundedRectangleHeight, RoundedRectangleRadius);
            cr.Fill();

            cr.SetSourceRGBA(0.0, 0.0, 0.0, 0.11);
            cr.RoundedRectangle(0.0, 0.0, RoundedRectangleWidth, RoundedRectangleHeight, RoundedRectangleRadius);
            cr.LineWidth = 2;
            cr.Stroke();

            using (var layout = PangoUtil.CreateLayout(widget, LineNumber != -1 ? LineNumber.ToString() : "???")) {
                layout.Alignment       = Pango.Alignment.Left;
                layout.FontDescription = LineNumberFont;

                int width, height;
                layout.GetPixelSize(out width, out height);

                double y_offset = (RoundedRectangleHeight - height) / 2.0;
                double x_offset = (RoundedRectangleWidth - width) / 2.0;

                // render the text shadow
                cr.Save();
                cr.SetSourceRGBA(0.0, 0.0, 0.0, 0.34);
                cr.Translate(x_offset, y_offset + 1);
                cr.ShowLayout(layout);
                cr.Restore();

                cr.SetSourceRGBA(1.0, 1.0, 1.0, 1.0);
                cr.Translate(x_offset, y_offset);
                cr.ShowLayout(layout);
            }

            cr.Restore();
        }
Beispiel #2
0
        protected override bool OnExposeEvent(Gdk.EventExpose evnt)
        {
            using (Cairo.Context cr = Gdk.CairoHelper.Create(evnt.Window)) {
                cr.Rectangle(evnt.Region.Clipbox.X, evnt.Region.Clipbox.Y, evnt.Region.Clipbox.Width, evnt.Region.Clipbox.Height);
                cr.SetSourceColor(editor.ColorStyle.PlainText.Background);
                cr.Fill();
                using (var layout = PangoUtil.CreateLayout(editor)) {
                    layout.FontDescription = editor.Options.Font;

                    layout.SetText("000,00-00");
                    int minstatusw, minstatush;
                    layout.GetPixelSize(out minstatusw, out minstatush);

                    var line      = editor.GetLine(editor.Caret.Line);
                    var visColumn = line.GetVisualColumn(editor.GetTextEditorData(), editor.Caret.Column);

                    if (visColumn != editor.Caret.Column)
                    {
                        layout.SetText(editor.Caret.Line + "," + editor.Caret.Column + "-" + visColumn);
                    }
                    else
                    {
                        layout.SetText(editor.Caret.Line + "," + editor.Caret.Column);
                    }

                    int statusw, statush;
                    layout.GetPixelSize(out statusw, out statush);

                    statusw = System.Math.Max(statusw, minstatusw);

                    statusw += 8;
                    cr.MoveTo(Allocation.Width - statusw, 0);
                    statusw += 8;
                    cr.SetSourceColor(editor.ColorStyle.PlainText.Foreground);
                    cr.ShowLayout(layout);

                    layout.SetText(statusText ?? "");
                    int w, h;
                    layout.GetPixelSize(out w, out h);
                    var x = System.Math.Min(0, -w + Allocation.Width - editor.TextViewMargin.CharWidth - statusw);
                    cr.MoveTo(x, 0);
                    cr.SetSourceColor(editor.ColorStyle.PlainText.Foreground);
                    cr.ShowLayout(layout);
                    if (ShowCaret)
                    {
                                                #if false
                        if (editor.TextViewMargin.caretBlink)
                        {
                            cr.Rectangle(w + x, 0, (int)editor.TextViewMargin.CharWidth, (int)editor.LineHeight);
                            cr.Fill();
                        }
                                                #endif
                    }
                }
            }
            return(true);
        }
Beispiel #3
0
            protected override void OnDrawContent(Gdk.EventExpose evnt, Cairo.Context g)
            {
                Theme.BorderColor = marker.TooltipColor.Color;
                g.Rectangle(0, 0, Allocation.Width, Allocation.Height);
                g.SetSourceColor(marker.TooltipColor.Color);
                g.Fill();

                using (var drawingLayout = new Pango.Layout(this.PangoContext)) {
                    drawingLayout.FontDescription = cache.tooltipFontDescription;
                    double y = verticalTextBorder;

                    var showBulletedList = marker.Errors.Count > 1;
                    foreach (var msg in marker.Errors)
                    {
                        var icon = msg.IsError ? cache.errorPixbuf : cache.warningPixbuf;

                        if (!showBulletedList)
                        {
                            drawingLayout.Width = maxTextWidth;
                        }
                        drawingLayout.SetText(GetFirstLine(msg));
                        int w;
                        int h;
                        drawingLayout.GetPixelSize(out w, out h);

                        if (showBulletedList)
                        {
                            g.Save();

                            g.Translate(
                                textBorder,
                                y + verticalTextSpace / 2
                                );
                            Gdk.CairoHelper.SetSourcePixbuf(g, icon, 0, 0);
                            g.Paint();
                            g.Restore();
                        }

                        g.Save();

                        g.Translate(showBulletedList ? textBorder + iconTextSpacing + icon.Width: textBorder, y + verticalTextSpace / 2 + 1);
                        g.SetSourceColor(ShadowColor);
                        g.ShowLayout(drawingLayout);

                        g.Translate(0, -1);

                        g.SetSourceColor(marker.TagColor.SecondColor);
                        g.ShowLayout(drawingLayout);

                        g.Restore();


                        y += h + verticalTextSpace;
                    }
                }
            }
Beispiel #4
0
        public void Render(Cairo.Context cr, double _x, double _y, int max_height)
        {
            double x             = _x;
            double y             = _y;
            int    w             = Width;
            int    h             = max_height;
            int    inner_padding = 0;

            if (Outlined)
            {
                x -= outlinePadding;
                y -= outlinePadding;
                w += outlinePadding * 2;
                h += outlinePadding * 2;

                cr.MoveTo(x, y);
                cr.LineWidth = 1;
                cr.SetSourceColor(Styles.ModeHelpWindowTokenOutlineColor.ToCairoColor());

                if (Symbol == SymbolTokenType.None)
                {
                    inner_padding = textInnerPadding;
                }

                // -0.5f to fix the @1x stroke problem:
                // 1px stroke is rendered on the center of the shape edge, resulting in
                // two semitransparent pixels. Even worse the rounded rectangle renders
                // transparency artifacts on edge overlaps. See http://vncr.in/atks
                FoldingScreenbackgroundRenderer.DrawRoundRectangle(cr, true, true, x - inner_padding - 0.5f, y - 0.5f, 8, w + inner_padding * 2 + 1, h + 1);

                cr.Stroke();

                if (Symbol == SymbolTokenType.Down)
                {
                    RenderTriangleDown(cr, x + 4, y + 3, 8, 6);
                }
                else if (Symbol == SymbolTokenType.Up)
                {
                    RenderTriangleUp(cr, x + 4, y + 3, 8, 6);
                }
                else
                {
                    cr.MoveTo(x + outlinePadding, y + (max_height - Height - 0.5));
                    cr.ShowLayout(layout);
                }
            }
            else
            {
                cr.MoveTo(x, y);
                cr.SetSourceColor(Styles.ModeHelpWindowTokenTextColor.ToCairoColor());
                cr.ShowLayout(layout);
            }
        }
        public void DrawLineNumber(TextEditor editor, double width, Cairo.Context cr, Cairo.Rectangle area, DocumentLine lineSegment, int line, double x, double y, double lineHeight)
        {
            var lineNumberBgGC = editor.ColorStyle.LineNumbers.Background;
            var lineNumberGC   = editor.ColorStyle.LineNumbers.Foreground;

            cr.Rectangle(x, y, width, lineHeight);
            cr.Color = editor.Caret.Line == line?editor.ColorStyle.LineMarker.GetColor("color") : lineNumberGC;

            cr.Fill();

            if (line <= editor.Document.LineCount)
            {
                // Due to a mac? gtk bug I need to re-create the layout here
                // otherwise I get pango exceptions.
                using (var layout = PangoUtil.CreateLayout(editor)) {
                    layout.FontDescription = editor.Options.Font;
                    layout.Width           = (int)width;
                    layout.Alignment       = Pango.Alignment.Right;
                    layout.SetText(line.ToString());
                    cr.Save();
                    cr.Translate(x + (int)width + (editor.Options.ShowFoldMargin ? 0 : -2), y);
                    cr.Color = lineNumberBgGC;
                    cr.ShowLayout(layout);
                    cr.Restore();
                }
            }
        }
Beispiel #6
0
        void RenderLineNumberIcon(Widget widget, Cairo.Context cr, Gdk.Rectangle cell_area, int markupHeight, int yOffset)
        {
            if (Frame == null)
            {
                return;
            }

            cr.Save();

                        #if CENTER_ROUNDED_RECTANGLE
            cr.Translate(cell_area.X + Padding, (cell_area.Y + (cell_area.Height - RoundedRectangleHeight) / 2.0));
                        #else
            cr.Translate(cell_area.X + Padding, cell_area.Y + Padding + yOffset);
                        #endif

            cr.Antialias = Cairo.Antialias.Subpixel;

            cr.RoundedRectangle(0.0, 0.0, RoundedRectangleWidth, RoundedRectangleHeight, RoundedRectangleRadius);
            cr.Clip();

            if (IsUserCode)
            {
                cr.SetSourceColor(Styles.ExceptionCaughtDialog.LineNumberInUserCodeBackgroundColor.ToCairoColor());                   // 230, 152, 223
            }
            else
            {
                cr.SetSourceColor(Styles.ExceptionCaughtDialog.LineNumberBackgroundColor.ToCairoColor());                   // 197, 197, 197
            }
            cr.RoundedRectangle(0.0, 0.0, RoundedRectangleWidth, RoundedRectangleHeight, RoundedRectangleRadius);
            cr.Fill();

            var lineNumber = !string.IsNullOrEmpty(Frame.File) ? Frame.Line : -1;

            using (var layout = PangoUtil.CreateLayout(widget, lineNumber != -1 ? lineNumber.ToString() : "???")) {
                layout.Alignment       = Pango.Alignment.Left;
                layout.FontDescription = LineNumberFont;

                int width, height;
                layout.GetPixelSize(out width, out height);

                double y_offset = (RoundedRectangleHeight - height) / 2.0;
                double x_offset = (RoundedRectangleWidth - width) / 2.0;

                cr.SetSourceColor(Styles.ExceptionCaughtDialog.LineNumberTextColor.ToCairoColor());
                cr.Translate(x_offset, y_offset);
                cr.ShowLayout(layout);
            }

            cr.Restore();
        }
Beispiel #7
0
            public override void DrawAfterEol(Mono.TextEditor.TextEditor textEditor, Cairo.Context cr, double y, EndOfLineMetrics lineHeight)
            {
                using (var pango = cr.CreateLayout()) {
                    pango.FontDescription = textEditor.Options.Font;
                    cr.SetSourceColor(bg);

                    pango.SetText(hits.ToString());

                    cr.MoveTo(lineHeight.TextRenderEndPosition, y);
                    cr.ShowLayout(pango);
                }

                base.DrawAfterEol(textEditor, cr, y, lineHeight);
            }
Beispiel #8
0
 void DrawLine(Cairo.Context g, TextEditor editor, int lineNumber, ref int y)
 {
     using (var drawingLayout = new Pango.Layout(this.PangoContext)) {
         drawingLayout.FontDescription = fontDescription;
         var line = editor.GetLine(lineNumber);
         var correctedIndentLength = CorrectIndent(editor, line, indentLength);
         drawingLayout.SetMarkup(editor.GetPangoMarkup(line.Offset + Math.Min(correctedIndentLength, line.Length), Math.Max(0, line.Length - correctedIndentLength)));
         g.Save();
         g.Translate(textBorder, y);
         g.ShowLayout(drawingLayout);
         g.Restore();
         y += lineHeight;
     }
 }
Beispiel #9
0
 internal void DrawForeground(Cairo.Context cr, int line, double x, double y, double lineHeight, bool isSpaceAbove)
 {
     using (var layout = editor.LayoutCache.RequestLayout()) {
         layout.FontDescription = gutterFont;
         layout.Width           = (int)Width;
         layout.Alignment       = Pango.Alignment.Right;
         layout.SetText(line.ToString());
         cr.Save();
         cr.Translate(x + (int)Width + (editor.Options.ShowFoldMargin ? 0 : -2), y + (isSpaceAbove ? lineHeight - editor.LineHeight : 0));
         cr.SetSourceColor(lineNumberGC);
         cr.ShowLayout(layout);
         cr.Restore();
     }
 }
Beispiel #10
0
 void DrawTextLine(Cairo.Context g, IReadonlyTextDocument document, int lineNumber, ref int y)
 {
     using (var drawingLayout = new Pango.Layout(this.PangoContext)) {
         drawingLayout.FontDescription = fontDescription;
         var line = document.GetLine(lineNumber);
         var correctedIndentLength = CorrectIndent(document, line, indentLength);
         drawingLayout.SetText(document.GetTextAt(line.Offset + Math.Min(correctedIndentLength, line.Length), Math.Max(0, line.Length - correctedIndentLength)));
         g.Save();
         g.Translate(textBorder, y);
         g.ShowLayout(drawingLayout);
         g.Restore();
         y += lineHeight;
     }
 }
        void DrawMessageExtendIcon(Mono.TextEditor.TextEditor editor, Cairo.Context g, double y, int errorCounterWidth, int eh)
        {
            EnsureLayoutCreated(editor);
            double rW = errorCounterWidth - 2;
            double rH = editor.LineHeight * 3 / 4;

            double rX = editor.Allocation.Width - rW - 2;
            double rY = y + (editor.LineHeight - rH) / 2;

            BookmarkMarker.DrawRoundRectangle(g, rX, rY, 8, rW, rH);

            g.Color = oldIsOver ? new Cairo.Color(0.3, 0.3, 0.3) : new Cairo.Color(0.5, 0.5, 0.5);
            g.Fill();
            if (CollapseExtendedErrors)
            {
                if (errorCountLayout != null)
                {
                    g.Color = cache.gcLight;
                    g.Save();
                    g.Translate(rX + rW / 4, rY + (rH - eh) / 2);
                    g.ShowLayout(errorCountLayout);
                    g.Restore();
                }
                else
                {
                    g.MoveTo(rX + rW / 2 - rW / 4, rY + rH / 4);
                    g.LineTo(rX + rW / 2 + rW / 4, rY + rH / 4);
                    g.LineTo(rX + rW / 2, rY + rH - rH / 4);
                    g.ClosePath();

                    g.Color = new Cairo.Color(1, 1, 1);
                    g.Fill();
                }
            }
            else
            {
                g.MoveTo(rX + rW / 2 - rW / 4, rY + rH - rH / 4);
                g.LineTo(rX + rW / 2 + rW / 4, rY + rH - rH / 4);
                g.LineTo(rX + rW / 2, rY + rH / 4);
                g.ClosePath();

                g.Color = new Cairo.Color(1, 1, 1);
                g.Fill();
            }
        }
Beispiel #12
0
                bool BgBufferUpdater()
                {
                    if (mode.TextEditor.Document == null || handler == 0)
                    {
                        return(false);
                    }
                    try
                    {
                        for (int i = 0; i < 25 && curLine < maxLine; i++)
                        {
                            var nr   = mode.TextEditor.GetTextEditorData().VisualToLogicalLine(curLine);
                            var line = mode.TextEditor.GetLine(nr);
                            if (line != null)
                            {
                                var layout = mode.TextEditor.TextViewMargin.GetLayout(line);
                                cr.MoveTo(0, (curLine - 1) * mode.TextEditor.LineHeight);
                                cr.ShowLayout(layout.Layout);

                                if (layout.IsUncached)
                                {
                                    layout.Dispose();
                                }
                            }

                            curLine++;
                        }

                        if (curLine >= maxLine)
                        {
                            mode.SwapBuffer();
                            ((IDisposable)cr).Dispose();
                            cr             = null;
                            mode.curUpdate = null;
                            mode.QueueDraw();
                            return(false);
                        }
                    }
                    catch (Exception e)
                    {
                        LoggingService.LogError("Error in background buffer drawer.", e);
                        return(false);
                    }
                    return(true);
                }
Beispiel #13
0
        internal protected override void Draw(Cairo.Context cr, Cairo.Rectangle area, DocumentLine lineSegment, int line, double x, double y, double lineHeight)
        {
            var  extendingMarker = lineSegment != null ? (IExtendingTextLineMarker)editor.Document.GetMarkers(lineSegment).FirstOrDefault(l => l is IExtendingTextLineMarker) : null;
            bool isSpaceAbove    = extendingMarker != null ? extendingMarker.IsSpaceAbove : false;

            var gutterMarker = lineSegment != null ? (MarginMarker)editor.Document.GetMarkers(lineSegment).FirstOrDefault(marker => marker is MarginMarker && ((MarginMarker)marker).CanDraw(this)) : null;

            if (gutterMarker != null && gutterMarker.CanDrawBackground(this))
            {
                bool hasDrawn = gutterMarker.DrawBackground(editor, cr, new MarginDrawMetrics(this, area, lineSegment, line, x, y, lineHeight));
                if (!hasDrawn)
                {
                    DrawGutterBackground(cr, line, x, y, lineHeight);
                }
            }
            else
            {
                DrawGutterBackground(cr, line, x, y, lineHeight);
            }

            if (gutterMarker != null && gutterMarker.CanDrawForeground(this))
            {
                gutterMarker.DrawForeground(editor, cr, new MarginDrawMetrics(this, area, lineSegment, line, x, y, lineHeight));
                return;
            }

            if (line <= editor.Document.LineCount)
            {
                // Due to a mac? gtk bug I need to re-create the layout here
                // otherwise I get pango exceptions.
                using (var layout = editor.LayoutCache.RequestLayout()) {
                    layout.FontDescription = gutterFont;
                    layout.Width           = (int)Width;
                    layout.Alignment       = Pango.Alignment.Right;
                    layout.SetText(line.ToString());
                    cr.Save();
                    cr.Translate(x + (int)Width + (editor.Options.ShowFoldMargin ? 0 : -2), y + (isSpaceAbove ? lineHeight - editor.LineHeight : 0));
                    cr.SetSourceColor(lineNumberGC);
                    cr.ShowLayout(layout);
                    cr.Restore();
                }
            }
        }
            protected override void OnDrawContent(Gdk.EventExpose evnt, Cairo.Context g)
            {
                Theme.BorderColor = marker.TagColor.Color;
                g.Rectangle(0, 0, Allocation.Width, Allocation.Height);
                g.SetSourceColor(marker.TagColor.Color);
                g.Fill();

                double y = 8;
                double x = 4;

                foreach (var layout in marker.Layouts)
                {
                    g.Save();
                    g.Translate(x, y);
                    g.SetSourceColor(marker.TagColor.SecondColor);
                    g.ShowLayout(layout.Layout);
                    g.Restore();
                    y += layout.Height;
                }
            }
        void DrawCategoryText(Cairo.Context ctx, Widget widget, Rectangle cell_area, Rectangle iconRect, Rectangle languageRect, CellRendererState flags)
        {
            StateType state      = GetState(widget, flags);
            var       isSelected = state == StateType.Selected || state == StateType.Active;

            using (var layout = new Pango.Layout(widget.PangoContext)) {
                layout.Ellipsize = Pango.EllipsizeMode.End;
                int textPixelWidth = widget.Allocation.Width - ((int)Xpad * 2) - iconRect.Width - iconTextPadding - languageRect.Width;
                layout.Width           = (int)(textPixelWidth * Pango.Scale.PangoScale);
                layout.FontDescription = Fonts.FontExtensions.CopyModified(widget.Style.FontDesc, -1);

                layout.SetMarkup(GLib.Markup.EscapeText(TemplateCategory));

                int w, h;
                layout.GetPixelSize(out w, out h);
                int textY = cell_area.Y + ((cell_area.Height - h) - 2);

                ctx.MoveTo(iconRect.Right + iconTextPadding, textY);
                ctx.SetSourceColor((isSelected ? Styles.BaseSelectionTextColor : Styles.DimTextColor).ToCairoColor());
                ctx.ShowLayout(layout);
            }
        }
        public override void DrawForeground(MonoTextEditor editor, Cairo.Context cr, MarginDrawMetrics metrics)
        {
            var width          = metrics.Width;
            var lineNumberBgGC = editor.ColorStyle.LineNumbers.Background;

            if (metrics.LineNumber <= editor.Document.LineCount)
            {
                // Due to a mac? gtk bug I need to re-create the layout here
                // otherwise I get pango exceptions.
                using (var layout = PangoUtil.CreateLayout(editor)) {
                    layout.FontDescription = editor.Options.Font;
                    layout.Width           = (int)width;
                    layout.Alignment       = Pango.Alignment.Right;
                    layout.SetText(metrics.LineNumber.ToString());
                    cr.Save();
                    cr.Translate(metrics.X + (int)width + (editor.Options.ShowFoldMargin ? 0 : -2), metrics.Y);
                    cr.SetSourceColor(lineNumberBgGC);
                    cr.ShowLayout(layout);
                    cr.Restore();
                }
            }
        }
Beispiel #17
0
        internal protected override void Draw(Cairo.Context cr, Cairo.Rectangle area, DocumentLine lineSegment, int line, double x, double y, double lineHeight)
        {
            var gutterMarker = lineSegment != null ? (IGutterMarker)lineSegment.Markers.FirstOrDefault(marker => marker is IGutterMarker) : null;

            if (gutterMarker != null)
            {
                gutterMarker.DrawLineNumber(editor, Width, cr, area, lineSegment, line, x, y, lineHeight);
                return;
            }
            if (editor.Caret.Line == line)
            {
                editor.TextViewMargin.DrawCaretLineMarker(cr, x, y, Width, lineHeight);
            }
            else
            {
                cr.Rectangle(x, y, Width, lineHeight);
                cr.Color = lineNumberBgGC;
                cr.Fill();
            }

            if (line <= editor.Document.LineCount)
            {
                // Due to a mac? gtk bug I need to re-create the layout here
                // otherwise I get pango exceptions.
                using (var layout = PangoUtil.CreateLayout(editor)) {
                    layout.FontDescription = gutterFont;

                    layout.Width     = (int)Width;
                    layout.Alignment = Pango.Alignment.Right;
                    layout.SetText(line.ToString());
                    cr.Save();
                    cr.Translate(x + (int)Width + (editor.Options.ShowFoldMargin ? 0 : -2), y + (lineHeight - fontHeight) / 2);
                    cr.Color = lineNumberGC;
                    cr.ShowLayout(layout);
                    cr.Restore();
                }
            }
        }
Beispiel #18
0
        internal protected override void Draw(Cairo.Context cr, Cairo.Rectangle area, DocumentLine lineSegment, int line, double x, double y, double lineHeight)
        {
            cr.Rectangle(x, y, Width, lineHeight);
            cr.Color = lineNumberBgGC;
            cr.Fill();

            if (line <= editor.Document.LineCount)
            {
                // Due to a mac? gtk bug I need to re-create the layout here
                // otherwise I get pango exceptions.
                using (var layout = PangoUtil.CreateLayout(editor)) {
                    layout.FontDescription = editor.Options.Font;
                    layout.Width           = (int)Width;
                    layout.Alignment       = Pango.Alignment.Right;
                    layout.SetText(line.ToString());
                    cr.Save();
                    cr.Translate(x + (int)Width + (editor.Options.ShowFoldMargin ? 0 : -2), y);
                    cr.Color = editor.Caret.Line == line ? lineNumberHighlightGC : lineNumberGC;
                    cr.ShowLayout(layout);
                    cr.Restore();
                }
            }
        }
Beispiel #19
0
            protected override bool OnExposeEvent(Gdk.EventExpose e)
            {
                using (Cairo.Context cr = Gdk.CairoHelper.Create(e.Window)) {
                    cr.LineWidth = Math.Max(1.0, widget.Editor.Options.Zoom);

                    cr.Rectangle(leftSpacer, 0, Allocation.Width, Allocation.Height);
                    cr.SetSourceRGB(0.95, 0.95, 0.95);
                    cr.Fill();

                    int    startLine = widget.Editor.YToLine((int)widget.Editor.VAdjustment.Value);
                    double startY    = widget.Editor.LineToY(startLine);
                    while (startLine > 1 && startLine < annotations.Count && annotations[startLine - 1] != null && annotations[startLine] != null && annotations[startLine - 1].Revision == annotations[startLine].Revision)
                    {
                        startLine--;
                        startY -= widget.Editor.GetLineHeight(widget.Editor.Document.GetLine(startLine));
                    }
                    double curY = startY - widget.Editor.VAdjustment.Value;
                    int    line = startLine;
                    while (curY < Allocation.Bottom && line <= widget.Editor.LineCount)
                    {
                        double curStart = curY;
//						widget.JumpOverFoldings (ref line);
                        int        lineStart = line;
                        int        authorWidth = 0, revisionWidth = 0, dateWidth = 0, h = 16;
                        Annotation ann = line <= annotations.Count ? annotations[line - 1] : null;
                        if (ann != null)
                        {
                            do
                            {
                                widget.JumpOverFoldings(ref line);
                                line++;
                            } while (line <= annotations.Count && annotations[line - 1] != null && annotations[line - 1].Revision == ann.Revision);

                            double nextY = widget.editor.LineToY(line) - widget.editor.VAdjustment.Value;
                            if (highlightAnnotation != null && highlightAnnotation.Revision == ann.Revision && curStart <= highlightPositon && highlightPositon < nextY)
                            {
                                cr.Rectangle(leftSpacer, curStart + cr.LineWidth, Allocation.Width - leftSpacer, nextY - curStart - cr.LineWidth);
                                cr.SetSourceRGB(1, 1, 1);
                                cr.Fill();
                            }

                            // use a fixed size revision to get a approx. revision width
                            layout.SetText("88888888");
                            layout.GetPixelSize(out revisionWidth, out h);
                            layout.SetText(TruncRevision(ann.Revision));
                            e.Window.DrawLayout(Style.BlackGC, Allocation.Width - revisionWidth - margin, (int)(curY + (widget.Editor.LineHeight - h) / 2), layout);

                            const int dateRevisionSpacing = 16;
                            if (ann.HasDate)
                            {
                                string dateTime = ann.Date.ToShortDateString();
                                // use a fixed size date to get a approx. date width
                                layout.SetText(new DateTime(1999, 10, 10).ToShortDateString());
                                layout.GetPixelSize(out dateWidth, out h);
                                layout.SetText(dateTime);
                                e.Window.DrawLayout(Style.BlackGC, Allocation.Width - revisionWidth - margin - revisionWidth - dateRevisionSpacing, (int)(curY + (widget.Editor.LineHeight - h) / 2), layout);
                            }

                            using (var authorLayout = PangoUtil.CreateLayout(this)) {
                                var description = Pango.FontDescription.FromString("Tahoma " + (int)(10 * widget.Editor.Options.Zoom));
                                authorLayout.FontDescription = description;
                                authorLayout.SetText(ann.Author);
                                authorLayout.GetPixelSize(out authorWidth, out h);

                                var maxWidth = Allocation.Width - revisionWidth - margin - revisionWidth - dateRevisionSpacing;

                                /*				if (authorWidth > maxWidth) {
                                 *                                      int idx = ann.Author.IndexOf ('<');
                                 *                                      if (idx > 0)
                                 *                                              authorLayout.SetText (ann.Author.Substring (0, idx) + Environment.NewLine + ann.Author.Substring (idx));
                                 *                                      authorLayout.GetPixelSize (out authorWidth, out h);
                                 *                              }*/

                                cr.Save();
                                cr.Rectangle(0, 0, maxWidth, Allocation.Height);
                                cr.Clip();
                                cr.Translate(leftSpacer + margin, (int)(curY + (widget.Editor.LineHeight - h) / 2));
                                cr.SetSourceRGB(0, 0, 0);
                                cr.ShowLayout(authorLayout);
                                cr.ResetClip();
                                cr.Restore();
                            }

                            curY = nextY;
                        }
                        else
                        {
                            curY += widget.Editor.GetLineHeight(line);
                            line++;
                            widget.JumpOverFoldings(ref line);
                        }

                        if (ann != null && line - lineStart > 1)
                        {
                            string msg = GetCommitMessage(lineStart, false);
                            if (!string.IsNullOrEmpty(msg))
                            {
                                msg = Revision.FormatMessage(msg);

                                layout.SetText(msg);
                                layout.Width = (int)(Allocation.Width * Pango.Scale.PangoScale);
                                using (var gc = new Gdk.GC(e.Window)) {
                                    gc.RgbFgColor    = Style.Dark(State);
                                    gc.ClipRectangle = new Rectangle(0, (int)curStart, Allocation.Width, (int)(curY - curStart));
                                    e.Window.DrawLayout(gc, (int)(leftSpacer + margin), (int)(curStart + h), layout);
                                }
                            }
                        }

                        cr.Rectangle(0, curStart, leftSpacer, curY - curStart);

                        if (ann != null && ann != locallyModified && !string.IsNullOrEmpty(ann.Author))
                        {
                            double a;

                            if (ann != null && (maxDate - minDate).TotalHours > 0)
                            {
                                a = 1 - (ann.Date - minDate).TotalHours / (maxDate - minDate).TotalHours;
                            }
                            else
                            {
                                a = 1;
                            }
                            HslColor color = new Cairo.Color(0.90, 0.90, 1);
                            color.L = 0.4 + a / 2;
                            color.S = 1 - a / 2;
                            cr.SetSourceColor(color);
                        }
                        else
                        {
                            cr.SetSourceColor(ann != null ? new Cairo.Color(1, 1, 0) : new Cairo.Color(0.95, 0.95, 0.95));
                        }
                        cr.Fill();

                        if (ann != null)
                        {
                            cr.MoveTo(0, curY + 0.5);
                            cr.LineTo(Allocation.Width, curY + 0.5);
                            cr.SetSourceRGB(0.6, 0.6, 0.6);
                            cr.Stroke();
                        }
                    }
                }
                return(true);
            }
Beispiel #20
0
        protected override bool OnExposeEvent(Gdk.EventExpose e)
        {
            using (Cairo.Context cr = Gdk.CairoHelper.Create(e.Window)) {
                cr.LineWidth = 1;
                cr.Rectangle(0, 0, Allocation.Width, 16);
                var pattern = new Cairo.LinearGradient(0, 0, 0, 16);
                pattern.AddColorStop(0, new Cairo.Color(0.6, 0.8, 0.6));
                pattern.AddColorStop(1, new Cairo.Color(0.8, 1.0, 0.8));
                cr.Pattern = pattern;
                cr.Fill();
                cr.Rectangle(0, 16, Allocation.Width, Allocation.Height - 16);
                pattern = new Cairo.LinearGradient(0, 16, 0, Allocation.Height);
                pattern.AddColorStop(0, new Cairo.Color(0.8, 1.0, 0.8));
                pattern.AddColorStop(1, new Cairo.Color(0.6, 0.8, 0.6));
                cr.Pattern = pattern;
                cr.Fill();

                cr.Line(0, 0, Allocation.Width, 0);
                cr.Color = new Cairo.Color(0.4, 0.6, 0.4);
                cr.Stroke();

                double xPos = padding, yPos = padding;
                var    layout = PangoUtil.CreateLayout(this);
                int    w, h;
                layout.SetText(new string ('X', maxLength));
                layout.GetPixelSize(out w, out h);

                foreach (Category cat in categories)
                {
                    yPos = padding;
                    cr.MoveTo(xPos, yPos);
                    layout.SetMarkup("<b>" + cat.Title + "</b>");
                    cr.Color = (HslColor)Style.Text(StateType.Normal);
                    cr.ShowLayout(layout);
                    layout.SetMarkup("");
                    int w2, h2;
                    layout.GetPixelSize(out w2, out h2);
                    yPos += h2;
                    yPos += headerDistance;
                    var startY     = yPos;
                    int curItem    = 0;
                    int row        = 0;
                    var iconHeight = Math.Max(h, cat.Items[0].Icon.Height + 2);
                    if (cat.FirstVisibleItem > 0)
                    {
                        Gtk.Style.PaintArrow(Style, e.Window, State, ShadowType.None,
                                             new Rectangle((int)xPos, (int)yPos, w, h),
                                             this,
                                             "",
                                             ArrowType.Up,
                                             true,
                                             (int)xPos,
                                             (int)yPos,
                                             w,
                                             h);
                        yPos += iconHeight;
                        curItem++;
                    }

                    for (int i = cat.FirstVisibleItem; i < cat.Items.Count; i++)
                    {
                        var item = cat.Items[i];

                        if (curItem + 1 >= maxItems && row + 1 >= maxRows && i + 1 < cat.Items.Count)
                        {
                            Gtk.Style.PaintArrow(Style, e.Window, State, ShadowType.None,
                                                 new Rectangle((int)xPos, (int)yPos, w, h),
                                                 this,
                                                 "",
                                                 ArrowType.Down,
                                                 true,
                                                 (int)xPos,
                                                 (int)yPos,
                                                 w,
                                                 h);
                            break;
                        }

                        if (item == ActiveItem)
                        {
                            cr.Rectangle(xPos + 0.5, yPos + 0.5, w + item.Icon.Width + 2, iconHeight);

                            pattern = new Cairo.LinearGradient(xPos, yPos, xPos, yPos + iconHeight * 2);
                            pattern.AddColorStop(0, (HslColor)Style.Base(StateType.Selected));
                            pattern.AddColorStop(1, new Cairo.Color(0.8, 1.0, 0.8));
                            cr.Pattern = pattern;
                            cr.FillPreserve();

                            cr.Color = (HslColor)Style.Base(StateType.Selected);
                            cr.Stroke();
                            cr.Color = (HslColor)Style.Text(StateType.Selected);
                        }
                        else if (item == hoverItem)
                        {
                            cr.Rectangle(xPos + 0.5, yPos + 0.5, w + item.Icon.Width + 2, iconHeight);
                            pattern = new Cairo.LinearGradient(xPos, yPos, xPos, yPos + iconHeight);
                            pattern.AddColorStop(0, new Cairo.Color(0.6, 0.8, 0.6));
                            pattern.AddColorStop(1, new Cairo.Color(0.8, 1.0, 0.8));
                            cr.Pattern = pattern;
                            cr.Fill();
                            cr.Color = (HslColor)Style.Text(StateType.Normal);
                        }
                        else
                        {
                            cr.Color = (HslColor)Style.Text(StateType.Normal);
                        }
                        cr.MoveTo(xPos + item.Icon.Width + 2, yPos + (iconHeight - h) / 2);
                        layout.SetText(Ellipsize(item.ListTitle ?? item.Title, maxLength));
                        cr.ShowLayout(layout);
                        e.Window.DrawPixbuf(Style.BaseGC(StateType.Normal), item.Icon, 0, 0, (int)xPos, (int)(yPos + (iconHeight - item.Icon.Height) / 2), item.Icon.Width, item.Icon.Height, RgbDither.None, 0, 0);

                        yPos += iconHeight;
                        if (++curItem >= maxItems)
                        {
                            curItem = 0;
                            yPos    = startY;
                            xPos   += w + cat.Items[0].Icon.Width + 2 + padding;
                            row++;
                        }
                    }


                    xPos += w + cat.Items[0].Icon.Width + 2 + padding;
                }
                layout.Dispose();
            }
            return(true);
        }
Beispiel #21
0
        protected override bool OnExposeEvent(Gdk.EventExpose e)
        {
            using (Cairo.Context cr = Gdk.CairoHelper.Create(e.Window)) {
                double xPos = padding, yPos = padding;
                var    layout = PangoUtil.CreateLayout(this);
                int    w, h;
                layout.SetText(new string ('X', maxLength));
                layout.GetPixelSize(out w, out h);

                foreach (Category cat in categories)
                {
                    yPos = padding;
                    cr.MoveTo(xPos, yPos);
                    layout.SetMarkup("<b>" + cat.Title + "</b>");
                    cr.SetSourceColor(Style.Text(StateType.Normal).ToCairoColor());
                    cr.ShowLayout(layout);

                    if (cat.Items.Count == 0)
                    {
                        continue;
                    }

                    layout.SetMarkup("");
                    int w2, h2;
                    layout.GetPixelSize(out w2, out h2);
                    yPos += h2;
                    yPos += headerDistance;
                    var startY     = yPos;
                    int curItem    = 0;
                    int row        = 0;
                    var iconHeight = Math.Max(h, cat.Items [0].Icon.Height + 2) + itemPadding * 2;
                    if (cat.FirstVisibleItem > 0)
                    {
                        Gtk.Style.PaintArrow(Style, e.Window, State, ShadowType.None,
                                             new Rectangle((int)xPos, (int)yPos, w, h),
                                             this,
                                             "",
                                             ArrowType.Up,
                                             true,
                                             (int)xPos,
                                             (int)yPos,
                                             w,
                                             h);
                        yPos += iconHeight;
                        curItem++;
                    }

                    for (int i = cat.FirstVisibleItem; i < cat.Items.Count; i++)
                    {
                        var item = cat.Items [i];

                        if (curItem + 1 >= maxItems && row + 1 >= maxRows && i + 1 < cat.Items.Count)
                        {
                            Gtk.Style.PaintArrow(Style, e.Window, State, ShadowType.None,
                                                 new Rectangle((int)xPos, (int)yPos, w, h),
                                                 this,
                                                 "",
                                                 ArrowType.Down,
                                                 true,
                                                 (int)xPos,
                                                 (int)yPos,
                                                 w,
                                                 h);
                            break;
                        }

                        if (item == ActiveItem)
                        {
                            int itemWidth = w + (int)item.Icon.Width + 2 + itemPadding * 2;
                            cr.Rectangle(xPos, yPos, itemWidth, iconHeight);
                            cr.LineWidth = 1;
                            cr.SetSourceColor(Style.Base(StateType.Selected).ToCairoColor());
                            cr.Fill();
                        }
                        else if (item == hoverItem)
                        {
                            int itemWidth = w + (int)item.Icon.Width + 2 + itemPadding * 2;
                            cr.Rectangle(xPos + 0.5, yPos + 0.5, itemWidth - 1, iconHeight);
                            cr.LineWidth = 1;
                            cr.SetSourceColor(Style.Base(StateType.Selected).ToCairoColor());
                            cr.Stroke();
                        }
                        cr.SetSourceColor(Style.Text(item == ActiveItem? StateType.Selected : StateType.Normal).ToCairoColor());
                        cr.MoveTo(xPos + item.Icon.Width + 2 + itemPadding, yPos + (iconHeight - h) / 2);
                        layout.SetText(Ellipsize(item.ListTitle ?? item.Title, maxLength));
                        cr.ShowLayout(layout);
                        cr.DrawImage(this, item.Icon, (int)xPos + itemPadding,
                                     (int)(yPos + (iconHeight - item.Icon.Height) / 2));
                        yPos += iconHeight;
                        if (++curItem >= maxItems)
                        {
                            curItem = 0;
                            yPos    = startY;
                            xPos   += w + cat.Items [0].Icon.Width + 2 + padding + itemPadding * 2;
                            row++;
                        }
                    }


                    xPos += w + cat.Items [0].Icon.Width + 2 + padding + itemPadding * 2;
                }
                layout.Dispose();
            }
            return(true);
        }
        public override void DrawAfterEol(MonoTextEditor textEditor, Cairo.Context g, EndOfLineMetrics metrics)
        {
            if (!IsVisible)
            {
                return;
            }
            EnsureLayoutCreated(editor);
            int errorCounterWidth = 0, eh = 0;

            if (errorCountLayout != null)
            {
                errorCountLayout.GetPixelSize(out errorCounterWidth, out eh);
                errorCounterWidth = Math.Max(15, Math.Max(errorCounterWidth + 3, (int)(editor.LineHeight * 3 / 4)));
            }

            var  sx = metrics.TextRenderEndPosition;
            var  width      = LayoutWidth + errorCounterWidth + editor.LineHeight;
            var  drawLayout = layouts[0].Layout;
            var  y            = metrics.LineYRenderStartPosition;
            bool customLayout = true;             //sx + width > editor.Allocation.Width;
            bool hideText     = false;

            bubbleIsReduced = customLayout;
            var    showErrorCount = errorCounterWidth > 0 && errorCountLayout != null;
            double roundingRadius = editor.LineHeight / 2 - 1;

            if (customLayout)
            {
                width = editor.Allocation.Width - sx;
                string text = layouts[0].Layout.Text;
                drawLayout = new Pango.Layout(editor.PangoContext);
                drawLayout.FontDescription = cache.fontDescription;
                var paintWidth = (width - errorCounterWidth - editor.LineHeight + 4);
                var minWidth   = Math.Max(25, errorCounterWidth) * editor.Options.Zoom;
                if (paintWidth < minWidth)
                {
                    hideText       = true;
                    showErrorCount = false;
//					drawLayout.SetMarkup ("<span weight='heavy'>···</span>");
                    width = minWidth;
                    //roundingRadius = 10 * editor.Options.Zoom;
                    sx = Math.Min(sx, editor.Allocation.Width - width);
                }
                else
                {
                    drawLayout.Ellipsize = Pango.EllipsizeMode.End;
                    drawLayout.Width     = (int)(paintWidth * Pango.Scale.PangoScale);
                    drawLayout.SetText(text);
                    int w2, h2;
                    drawLayout.GetPixelSize(out w2, out h2);
                    width = w2 + errorCounterWidth + editor.LineHeight - 2;
                }
            }

            bubbleDrawX = sx - editor.TextViewMargin.XOffset;
            bubbleDrawY = y + 2;
            bubbleWidth = width;
            var bubbleHeight = editor.LineHeight;

            g.RoundedRectangle(sx, y, width, bubbleHeight, roundingRadius);
            g.SetSourceColor(TagColor.Color);
            g.Fill();

            // Draw error count icon
            if (showErrorCount)
            {
                var errorCounterHeight = bubbleHeight - 2;
                var errorCounterX      = sx + width - errorCounterWidth - 1;
                var errorCounterY      = Math.Round(y + (bubbleHeight - errorCounterHeight) / 2);

                g.RoundedRectangle(
                    errorCounterX,
                    errorCounterY,
                    errorCounterWidth,
                    errorCounterHeight,
                    editor.LineHeight / 2 - 2
                    );

                // FIXME: VV: Remove gradient features
                using (var lg = new Cairo.LinearGradient(errorCounterX, errorCounterY, errorCounterX, errorCounterY + errorCounterHeight)) {
                    lg.AddColorStop(0, CounterColor.Color);
                    lg.AddColorStop(1, CounterColor.Color.AddLight(-0.1));
                    g.SetSource(lg);
                    g.Fill();
                }

                g.Save();

                int ew;
                errorCountLayout.GetPixelSize(out ew, out eh);

                var tx = Math.Round(errorCounterX + (2 + errorCounterWidth - ew) / 2);
                var ty = Math.Round(errorCounterY + (-1 + errorCounterHeight - eh) / 2);

                g.Translate(tx, ty);
                g.SetSourceColor(CounterColor.SecondColor);
                g.ShowLayout(errorCountLayout);
                g.Restore();
            }

            if (hideText)
            {
                // Draw dots
                double radius  = 2 * editor.Options.Zoom;
                double spacing = 1 * editor.Options.Zoom;

                sx += 1 * editor.Options.Zoom + Math.Ceiling((bubbleWidth - 3 * (radius * 2) - 2 * spacing) / 2);

                for (int i = 0; i < 3; i++)
                {
                    g.Arc(sx, y + bubbleHeight / 2, radius, 0, Math.PI * 2);
                    g.SetSourceColor(TagColor.SecondColor);
                    g.Fill();
                    sx += radius * 2 + spacing;
                }
            }
            else
            {
                // Draw label text
                var tx = Math.Round(sx + editor.LineHeight / 2);
                var ty = Math.Round(y + (editor.LineHeight - layouts [0].Height) / 2) - 1;

                g.Save();
                g.Translate(tx, ty);

                g.SetSourceColor(TagColor.SecondColor);
                g.ShowLayout(drawLayout);
                g.Restore();
            }

            if (customLayout)
            {
                drawLayout.Dispose();
            }
        }
        public override void DrawAfterEol(TextEditor textEditor, Cairo.Context g, double y, EndOfLineMetrics metrics)
        {
            if (!IsVisible)
            {
                return;
            }
            EnsureLayoutCreated(editor);
            int errorCounterWidth = 0, eh = 0;

            if (errorCountLayout != null)
            {
                errorCountLayout.GetPixelSize(out errorCounterWidth, out eh);
                errorCounterWidth = Math.Max(15, Math.Max(errorCounterWidth + 3, (int)(editor.LineHeight * 3 / 4)));
            }

            var  sx = metrics.TextRenderEndPosition;
            var  width = LayoutWidth + errorCounterWidth + editor.LineHeight;
            var  drawLayout = layouts[0].Layout;
            int  ex = 0, ey = 0;
            bool customLayout = true;             //sx + width > editor.Allocation.Width;
            bool hideText     = false;

            bubbleIsReduced = customLayout;
            var showErrorCount = errorCounterWidth > 0 && errorCountLayout != null;

            if (customLayout)
            {
                width = editor.Allocation.Width - sx;
                string text = layouts[0].Layout.Text;
                drawLayout = new Pango.Layout(editor.PangoContext);
                drawLayout.FontDescription = cache.fontDescription;
                var paintWidth = (width - errorCounterWidth - editor.LineHeight + 4);
                var minWidth   = Math.Max(17, errorCounterWidth) + editor.LineHeight;
                if (paintWidth < minWidth)
                {
                    hideText = true;
                    drawLayout.SetMarkup("<span weight='heavy'>···</span>");
                    width          = minWidth;
                    showErrorCount = false;
                    sx             = Math.Min(sx, editor.Allocation.Width - width);
                }
                else
                {
                    drawLayout.Ellipsize = Pango.EllipsizeMode.End;
                    drawLayout.Width     = (int)(paintWidth * Pango.Scale.PangoScale);
                    drawLayout.SetText(text);
                }
            }
            bubbleDrawX = sx - editor.TextViewMargin.XOffset;
            bubbleDrawY = y;
            bubbleWidth = width;

            var bubbleHeight = editor.LineHeight - 1;

            g.RoundedRectangle(sx, y + 1, width, bubbleHeight, editor.LineHeight / 2 - 1);
            g.SetSourceColor(TagColor.Color);
            g.Fill();

            // Draw error count icon
            if (showErrorCount)
            {
                var errorCounterHeight = bubbleHeight - 2;
                var errorCounterX      = sx + width - errorCounterWidth - 3;
                var errorCounterY      = y + 1 + (bubbleHeight - errorCounterHeight) / 2;

                g.RoundedRectangle(
                    errorCounterX - 1,
                    errorCounterY - 1,
                    errorCounterWidth + 2,
                    errorCounterHeight + 2,
                    editor.LineHeight / 2 - 3
                    );

                g.SetSourceColor(new Cairo.Color(0, 0, 0, 0.081));
                g.Fill();

                g.RoundedRectangle(
                    errorCounterX,
                    errorCounterY,
                    errorCounterWidth,
                    errorCounterHeight,
                    editor.LineHeight / 2 - 3
                    );
                using (var lg = new Cairo.LinearGradient(errorCounterX, errorCounterY, errorCounterX, errorCounterY + errorCounterHeight)) {
                    lg.AddColorStop(0, CounterColor.Color);
                    lg.AddColorStop(1, CounterColor.Color.AddLight(-0.1));
                    g.Pattern = lg;
                    g.Fill();
                }

                g.Save();

                int ew;
                errorCountLayout.GetPixelSize(out ew, out eh);

                g.Translate(
                    errorCounterX + (errorCounterWidth - ew) / 2,
                    errorCounterY + (errorCounterHeight - eh) / 2
                    );
                g.SetSourceColor(CounterColor.SecondColor);
                g.ShowLayout(errorCountLayout);
                g.Restore();
            }

            // Draw label text
            if (!showErrorCount || !hideText)
            {
                g.Save();
                g.Translate(sx + editor.LineHeight / 2, y + (editor.LineHeight - layouts [0].Height) / 2 + 1);

                // draw shadow
                g.SetSourceColor(MessageBubbleCache.ShadowColor);
                g.ShowLayout(drawLayout);
                g.Translate(0, -1);

                g.SetSourceColor(TagColor.SecondColor);
                g.ShowLayout(drawLayout);
                g.Restore();
            }

            if (customLayout)
            {
                drawLayout.Dispose();
            }
        }
Beispiel #24
0
        public override void DrawAfterEol(TextEditor textEditor, Cairo.Context g, double y, EndOfLineMetrics metrics)
        {
            EnsureLayoutCreated(editor);
            int errorCounterWidth = 0, eh = 0;

            if (errorCountLayout != null)
            {
                errorCountLayout.GetPixelSize(out errorCounterWidth, out eh);
                errorCounterWidth = Math.Max(errorCounterWidth + 3, (int)(editor.LineHeight * 3 / 4));
            }

            var  sx = metrics.TextRenderEndPosition;
            var  width = LayoutWidth + errorCounterWidth + editor.LineHeight;
            var  drawLayout = layouts[0].Layout;
            int  ex = 0, ey = 0;
            bool customLayout = sx + width > editor.Allocation.Width;
            bool hideText     = false;

            bubbleIsReduced = customLayout;
            if (customLayout)
            {
                width = editor.Allocation.Width - sx;
                string text = layouts[0].Layout.Text;
                drawLayout = new Pango.Layout(editor.PangoContext);
                drawLayout.FontDescription = cache.fontDescription;
                for (int j = text.Length - 4; j > 0; j--)
                {
                    drawLayout.SetText(text.Substring(0, j) + "...");
                    drawLayout.GetPixelSize(out ex, out ey);
                    if (ex + (errorCountLayout != null ? errorCounterWidth : 0) + editor.LineHeight < width)
                    {
                        break;
                    }
                }
                if (ex + (errorCountLayout != null ? errorCounterWidth : 0) + editor.LineHeight > width)
                {
                    hideText = true;
                    drawLayout.SetMarkup("<span weight='heavy'>···</span>");
                    width = Math.Max(17, errorCounterWidth) + editor.LineHeight;
                    sx    = Math.Min(sx, editor.Allocation.Width - width);
                }
            }
            bubbleDrawX = sx - editor.TextViewMargin.XOffset;
            bubbleDrawY = y;
            bubbleWidth = width;
            g.RoundedRectangle(sx, y + 1, width, editor.LineHeight - 2, editor.LineHeight / 2 - 1);
            g.SetSourceColor(TagColor.Color);
            g.Fill();
            if (errorCounterWidth > 0 && errorCountLayout != null)
            {
                g.RoundedRectangle(sx + width - errorCounterWidth - editor.LineHeight / 2, y + 2, errorCounterWidth, editor.LineHeight - 4, editor.LineHeight / 2 - 3);
                g.SetSourceColor(CounterColor.Color);
                g.Fill();

                g.Save();

                int ew;
                errorCountLayout.GetPixelSize(out ew, out eh);

                g.Translate(sx + width - errorCounterWidth - editor.LineHeight / 2 + (errorCounterWidth - ew) / 2, y + 1);
                g.SetSourceColor(CounterColor.SecondColor);
                g.ShowLayout(errorCountLayout);
                g.Restore();
            }

            if (errorCounterWidth <= 0 || errorCountLayout == null || !hideText)
            {
                g.Save();
                g.Translate(sx + editor.LineHeight / 2, y + (editor.LineHeight - layouts [0].Height) / 2 + layouts [0].Height % 2);
                g.SetSourceColor(TagColor.SecondColor);
                g.ShowLayout(drawLayout);
                g.Restore();
            }

            if (customLayout)
            {
                drawLayout.Dispose();
            }
        }
        public bool DrawBackground(TextEditor editor, Cairo.Context g, TextViewMargin.LayoutWrapper layout2, int selectionStart, int selectionEnd, int startOffset, int endOffset, double y, double startXPos, double endXPos, ref bool drawBg)
        {
            if (!IsVisible)
            {
                return(true);
            }
            EnsureLayoutCreated(editor);
            double x                 = editor.TextViewMargin.XOffset;
            int    right             = editor.Allocation.Width;
            bool   isCaretInLine     = startOffset <= editor.Caret.Offset && editor.Caret.Offset <= endOffset;
            var    lineTextPx        = editor.TextViewMargin.XOffset + editor.TextViewMargin.TextStartPosition + layout2.PangoWidth / Pango.Scale.PangoScale;
            int    errorCounterWidth = GetErrorCountBounds(layout2).Item1;
//			int eh = GetErrorCountBounds ().Item2;
            double x2 = System.Math.Max(right - LayoutWidth - border - (ShowIconsInBubble ? cache.errorPixbuf.Width : 0) - errorCounterWidth, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);

            bool isEolSelected = editor.IsSomethingSelected && editor.SelectionMode != SelectionMode.Block ? editor.SelectionRange.Contains(lineSegment.Offset + lineSegment.Length) : false;

            int active      = editor.Document.GetTextAt(lineSegment) == initialText ? 0 : 1;
            int highlighted = active == 0 && isCaretInLine ? 1 : 0;
            int selected    = 0;

            double topSize    = Math.Floor(editor.LineHeight / 2);
            double bottomSize = editor.LineHeight / 2 + editor.LineHeight % 2;

            if (!fitsInSameLine)
            {
                if (isEolSelected)
                {
                    x -= (int)editor.HAdjustment.Value;
                    editor.TextViewMargin.DrawRectangleWithRuler(g, x, new Cairo.Rectangle(x, y + editor.LineHeight, editor.TextViewMargin.TextStartPosition, editor.LineHeight), editor.ColorStyle.PlainText.Background, true);
                    editor.TextViewMargin.DrawRectangleWithRuler(g, x + editor.TextViewMargin.TextStartPosition, new Cairo.Rectangle(x + editor.TextViewMargin.TextStartPosition, y + editor.LineHeight, editor.Allocation.Width + (int)editor.HAdjustment.Value, editor.LineHeight), editor.ColorStyle.SelectedText.Background, true);
                    x += (int)editor.HAdjustment.Value;
                }
                else
                {
                    editor.TextViewMargin.DrawRectangleWithRuler(g, x, new Cairo.Rectangle(x, y + editor.LineHeight, x2, editor.LineHeight), editor.ColorStyle.PlainText.Background, true);
                }
            }
            DrawRectangle(g, x, y, right, topSize);
            g.Color = colorMatrix [active, TOP, LIGHT, highlighted, selected];
            g.Fill();
            DrawRectangle(g, x, y + topSize, right, bottomSize);
            g.Color = colorMatrix [active, BOTTOM, LIGHT, highlighted, selected];
            g.Fill();

            g.MoveTo(new Cairo.PointD(x, y + 0.5));
            g.LineTo(new Cairo.PointD(x + right, y + 0.5));
            g.Color = colorMatrix [active, TOP, LINE, highlighted, selected];
            g.Stroke();

            g.MoveTo(new Cairo.PointD(x, y + editor.LineHeight - 0.5));
            g.LineTo(new Cairo.PointD((fitsInSameLine ? x + right : x2 + 1), y + editor.LineHeight - 0.5));
            g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
            g.Stroke();
            if (editor.Options.ShowRuler)
            {
                double divider = Math.Max(editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
                g.MoveTo(new Cairo.PointD(divider + 0.5, y));
                g.LineTo(new Cairo.PointD(divider + 0.5, y + editor.LineHeight));
                g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
                g.Stroke();
            }

// draw background
            if (layout2.StartSet || selectionStart == endOffset)
            {
                double startX;
                double endX;

                if (selectionStart != endOffset)
                {
                    var start = layout2.Layout.IndexToPos((int)layout2.SelectionStartIndex);
                    startX = (int)(start.X / Pango.Scale.PangoScale);
                    var end = layout2.Layout.IndexToPos((int)layout2.SelectionEndIndex);
                    endX = (int)(end.X / Pango.Scale.PangoScale);
                }
                else
                {
                    startX = x2;
                    endX   = startX;
                }

                if (editor.MainSelection.SelectionMode == SelectionMode.Block && startX == endX)
                {
                    endX = startX + 2;
                }
                startX += startXPos;
                endX   += startXPos;
                startX  = Math.Max(editor.TextViewMargin.XOffset, startX);
// clip region to textviewmargin start
                if (isEolSelected)
                {
                    endX = editor.Allocation.Width + (int)editor.HAdjustment.Value;
                }
                if (startX < endX)
                {
                    DrawRectangle(g, startX, y, endX - startX, topSize);
                    g.Color = colorMatrix [active, TOP, LIGHT, highlighted, 1];
                    g.Fill();
                    DrawRectangle(g, startX, y + topSize, endX - startX, bottomSize);
                    g.Color = colorMatrix [active, BOTTOM, LIGHT, highlighted, 1];
                    g.Fill();

                    g.MoveTo(new Cairo.PointD(startX, y + 0.5));
                    g.LineTo(new Cairo.PointD(endX, y + 0.5));
                    g.Color = colorMatrix [active, TOP, LINE, highlighted, 1];
                    g.Stroke();

                    if (startX < x2)
                    {
                        g.MoveTo(new Cairo.PointD(startX, y + editor.LineHeight - 0.5));
                        g.LineTo(new Cairo.PointD(System.Math.Min(endX, x2 + 1), y + editor.LineHeight - 0.5));
                        g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, 1];
                        g.Stroke();
                        if (x2 + 1 < endX)
                        {
                            g.MoveTo(new Cairo.PointD(x2 + 1, y + editor.LineHeight - 0.5));
                            g.LineTo(new Cairo.PointD(endX, y + editor.LineHeight - 0.5));
                            g.Color = colorMatrix [active, BOTTOM, LIGHT, highlighted, 1];
                            g.Stroke();
                        }
                    }

                    if (editor.Options.ShowRuler)
                    {
                        double divider = Math.Max(editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
                        g.MoveTo(new Cairo.PointD(divider + 0.5, y));
                        g.LineTo(new Cairo.PointD(divider + 0.5, y + editor.LineHeight));
                        g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, 1];
                        g.Stroke();
                    }
                }
            }

            if (!fitsInSameLine)
            {
                y += editor.LineHeight;
            }
            double y2       = y + 0.5;
            double y2Bottom = y2 + editor.LineHeight - 1;

            selected = isEolSelected && (CollapseExtendedErrors) ? 1 : 0;
            if (x2 < lineTextPx)
            {
                x2 = lineTextPx;
            }

// draw message text background
            if (CollapseExtendedErrors)
            {
                if (!fitsInSameLine)
                {
// draw box below line
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2 - 1));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2 - 1));
                    g.ClosePath();
                    g.Color = colorMatrix [active, BOTTOM, LIGHT, highlighted, selected];
                    g.Fill();

                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2 - 1));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2Bottom));
                    g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
                    g.Stroke();
                }
                else
                {
// draw 'arrow marker' in the same line
                    if (errors.Count > 1)
                    {
                        g.MoveTo(new Cairo.PointD(x2 + 0.5, y2));
                        double mid = y2 + topSize;
                        g.LineTo(new Cairo.PointD(x2 - editor.LineHeight / 2 + 0.5, mid));

                        g.LineTo(new Cairo.PointD(right, mid));
                        g.LineTo(new Cairo.PointD(right, y2));
                        g.ClosePath();
                        g.Color = colorMatrix [active, TOP, DARK, highlighted, selected];
                        g.Fill();
                        g.MoveTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                        g.LineTo(new Cairo.PointD(x2 - editor.LineHeight / 2 + 0.5, mid));

                        g.LineTo(new Cairo.PointD(right, mid));
                        g.LineTo(new Cairo.PointD(right, y2Bottom));
                        g.ClosePath();

                        g.Color = colorMatrix [active, BOTTOM, DARK, highlighted, selected];
                        g.Fill();
                    }

// draw border
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2));
                    g.LineTo(new Cairo.PointD(x2 - editor.LineHeight / 2 + 0.5, y2 + editor.LineHeight / 2));

                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2));
                    g.ClosePath();

                    g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
                    g.Stroke();
                }
            }
            else
            {
                if (!fitsInSameLine)
                {
// draw box below line
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2 - 1));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2 - 1));
                    g.ClosePath();
                }
                else
                {
// draw filled arrow box
                    if (!(errors.Count == 1 && !CollapseExtendedErrors))
                    {
                        g.MoveTo(new Cairo.PointD(x2 + 0.5, y2));
                        g.LineTo(new Cairo.PointD(x2 - editor.LineHeight / 2 + 0.5, y2 + editor.LineHeight / 2));
                        g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                        g.LineTo(new Cairo.PointD(right, y2Bottom));
                        g.LineTo(new Cairo.PointD(right, y2));
                        g.ClosePath();
                    }
                }
                g.Color = colorMatrix [active, BOTTOM, LIGHT, highlighted, selected];
                g.Fill();

// draw light bottom line
                g.MoveTo(new Cairo.PointD(right, y2Bottom));
                g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                g.Stroke();

// stroke left line
                if (fitsInSameLine)
                {
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2));
                    g.LineTo(new Cairo.PointD(x2 - editor.LineHeight / 2 + 0.5, y2 + editor.LineHeight / 2));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                }
                else
                {
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2 - 1));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom + 1));
                }

                g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
                g.Stroke();

// stroke top line
                if (fitsInSameLine)
                {
                    g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
                    g.MoveTo(new Cairo.PointD(right, y2));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2));
                    g.Stroke();
                }
            }

            if (editor.Options.ShowRuler)
            {
                double divider = Math.Max(editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
                if (divider >= x2)
                {
                    g.MoveTo(new Cairo.PointD(divider + 0.5, y2));
                    g.LineTo(new Cairo.PointD(divider + 0.5, y2Bottom));
                    g.Color = colorMatrix [active, BOTTOM, DARK, highlighted, selected];
                    g.Stroke();
                }
            }


            for (int i = 0; i < layouts.Count; i++)
            {
                if (!IsCurrentErrorTextFitting(layout2) && !CollapseExtendedErrors)
                {
                    break;
                }

                var layout = layouts [i];
                x2 = right - layout.Width - border - (ShowIconsInBubble ? cache.errorPixbuf.Width : 0);
                if (i == 0)
                {
                    x2 -= errorCounterWidth;
                    if (x2 < lineTextPx)
                    {
                        //			if (CollapseExtendedErrors) {
                        x2 = lineTextPx;
                        //			}
                    }
                }
//				x2 = System.Math.Max (x2, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);

                if (i > 0)
                {
                    editor.TextViewMargin.DrawRectangleWithRuler(g, x, new Cairo.Rectangle(x, y, right, editor.LineHeight), isEolSelected ? editor.ColorStyle.SelectedText.Background : editor.ColorStyle.PlainText.Background, true);
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y + editor.LineHeight));
                    g.LineTo(new Cairo.PointD(right, y + editor.LineHeight));
                    g.LineTo(new Cairo.PointD(right, y));
                    g.ClosePath();

                    if (CollapseExtendedErrors)
                    {
                        using (var pat = new Cairo.LinearGradient(x2, y, x2, y + editor.LineHeight)) {
                            pat.AddColorStop(0, colorMatrix [active, TOP, LIGHT, highlighted, selected]);
                            pat.AddColorStop(1, colorMatrix [active, BOTTOM, LIGHT, highlighted, selected]);
                            g.Pattern = pat;
                        }
                    }
                    else
                    {
                        g.Color = colorMatrix [active, TOP, LIGHT, highlighted, selected];
                    }
                    g.Fill();
                    if (editor.Options.ShowRuler)
                    {
                        double divider = Math.Max(editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
                        if (divider >= x2)
                        {
                            g.MoveTo(new Cairo.PointD(divider + 0.5, y));
                            g.LineTo(new Cairo.PointD(divider + 0.5, y + editor.LineHeight));
                            g.Color = colorMatrix [active, BOTTOM, DARK, highlighted, selected];
                            g.Stroke();
                        }
                    }
                }
                g.Color = (HslColor)(selected == 0 ? gc : cache.gcSelected);
                g.Save();
                g.Translate(x2 + (ShowIconsInBubble ? cache.errorPixbuf.Width : 0) + border, y + (editor.LineHeight - layout.Height) / 2 + layout.Height % 2);
                g.ShowLayout(layout.Layout);
                g.Restore();
                y += editor.LineHeight;
                if (!UseVirtualLines)
                {
                    break;
                }
            }
            return(true);
        }
        public bool DrawBackground(TextEditor editor, Cairo.Context g, TextViewMargin.LayoutWrapper layout2, int selectionStart, int selectionEnd, int startOffset, int endOffset, double y, double startXPos, double endXPos, ref bool drawBg)
        {
            if (!IsVisible || DebuggingService.IsDebugging)
            {
                return(true);
            }
            EnsureLayoutCreated(editor);
            double x = editor.TextViewMargin.XOffset;
            int    right = editor.Allocation.Width;
            int    errorCounterWidth = 0;
            bool   isCaretInLine = startOffset <= editor.Caret.Offset && editor.Caret.Offset <= endOffset;
            int    ew = 0, eh = 0;

            if (errors.Count > 1 && errorCountLayout != null)
            {
                errorCountLayout.GetPixelSize(out ew, out eh);
                errorCounterWidth = ew + 10;
            }

            double x2            = System.Math.Max(right - LayoutWidth - border - (ShowIconsInBubble ? errorPixbuf.Width : 0) - errorCounterWidth, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);
            bool   isEolSelected = editor.IsSomethingSelected && editor.SelectionMode != SelectionMode.Block ? editor.SelectionRange.Contains(lineSegment.Offset + lineSegment.EditableLength) : false;

            int active      = editor.Document.GetTextAt(lineSegment) == initialText ? 0 : 1;
            int highlighted = active == 0 && isCaretInLine ? 1 : 0;
            int selected    = 0;

            double topSize    = Math.Floor(editor.LineHeight / 2);
            double bottomSize = editor.LineHeight / 2 + editor.LineHeight % 2;

            if (!fitsInSameLine)
            {
                if (isEolSelected)
                {
                    x -= (int)editor.HAdjustment.Value;
                    editor.TextViewMargin.DrawRectangleWithRuler(g, x, new Cairo.Rectangle(x, y + editor.LineHeight, editor.TextViewMargin.TextStartPosition, editor.LineHeight), editor.ColorStyle.Default.CairoBackgroundColor, true);
                    editor.TextViewMargin.DrawRectangleWithRuler(g, x + editor.TextViewMargin.TextStartPosition, new Cairo.Rectangle(x + editor.TextViewMargin.TextStartPosition, y + editor.LineHeight, editor.Allocation.Width + (int)editor.HAdjustment.Value, editor.LineHeight), editor.ColorStyle.Selection.CairoBackgroundColor, true);
                    x += (int)editor.HAdjustment.Value;
                }
                else
                {
                    editor.TextViewMargin.DrawRectangleWithRuler(g, x, new Cairo.Rectangle(x, y + editor.LineHeight, x2, editor.LineHeight), editor.ColorStyle.Default.CairoBackgroundColor, true);
                }
            }
            DrawRectangle(g, x, y, right, topSize);
            g.Color = colorMatrix [active, TOP, LIGHT, highlighted, selected];
            g.Fill();
            DrawRectangle(g, x, y + topSize, right, bottomSize);
            g.Color = colorMatrix [active, BOTTOM, LIGHT, highlighted, selected];
            g.Fill();

            g.MoveTo(new Cairo.PointD(x, y + 0.5));
            g.LineTo(new Cairo.PointD(x + right, y + 0.5));
            g.Color = colorMatrix [active, TOP, LINE, highlighted, selected];
            g.Stroke();

            g.MoveTo(new Cairo.PointD(x, y + editor.LineHeight - 0.5));
            g.LineTo(new Cairo.PointD((fitsInSameLine ? x + right : x2 + 1), y + editor.LineHeight - 0.5));
            g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
            g.Stroke();
            if (editor.Options.ShowRuler)
            {
                double divider = Math.Max(editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
                g.MoveTo(new Cairo.PointD(divider + 0.5, y));
                g.LineTo(new Cairo.PointD(divider + 0.5, y + editor.LineHeight));
                g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
                g.Stroke();
            }

// draw background
            if (layout2.StartSet || selectionStart == endOffset)
            {
                double startX;
                double endX;

                if (selectionStart != endOffset)
                {
                    var start = layout2.Layout.IndexToPos((int)layout2.SelectionStartIndex);
                    startX = (int)(start.X / Pango.Scale.PangoScale);
                    var end = layout2.Layout.IndexToPos((int)layout2.SelectionEndIndex);
                    endX = (int)(end.X / Pango.Scale.PangoScale);
                }
                else
                {
                    startX = x2;
                    endX   = startX;
                }

                if (editor.MainSelection.SelectionMode == SelectionMode.Block && startX == endX)
                {
                    endX = startX + 2;
                }
                startX += startXPos;
                endX   += startXPos;
                startX  = Math.Max(editor.TextViewMargin.XOffset, startX);
// clip region to textviewmargin start
                if (isEolSelected)
                {
                    endX = editor.Allocation.Width + (int)editor.HAdjustment.Value;
                }
                if (startX < endX)
                {
                    DrawRectangle(g, startX, y, endX - startX, topSize);
                    g.Color = colorMatrix [active, TOP, LIGHT, highlighted, 1];
                    g.Fill();
                    DrawRectangle(g, startX, y + topSize, endX - startX, bottomSize);
                    g.Color = colorMatrix [active, BOTTOM, LIGHT, highlighted, 1];
                    g.Fill();

                    g.MoveTo(new Cairo.PointD(startX, y + 0.5));
                    g.LineTo(new Cairo.PointD(endX, y + 0.5));
                    g.Color = colorMatrix [active, TOP, LINE, highlighted, 1];
                    g.Stroke();

                    if (startX < x2)
                    {
                        g.MoveTo(new Cairo.PointD(startX, y + editor.LineHeight - 0.5));
                        g.LineTo(new Cairo.PointD(System.Math.Min(endX, x2 + 1), y + editor.LineHeight - 0.5));
                        g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, 1];
                        g.Stroke();
                        if (x2 + 1 < endX)
                        {
                            g.MoveTo(new Cairo.PointD(x2 + 1, y + editor.LineHeight - 0.5));
                            g.LineTo(new Cairo.PointD(endX, y + editor.LineHeight - 0.5));
                            g.Color = colorMatrix [active, BOTTOM, LIGHT, highlighted, 1];
                            g.Stroke();
                        }
                    }

                    if (editor.Options.ShowRuler)
                    {
                        double divider = Math.Max(editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
                        g.MoveTo(new Cairo.PointD(divider + 0.5, y));
                        g.LineTo(new Cairo.PointD(divider + 0.5, y + editor.LineHeight));
                        g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, 1];
                        g.Stroke();
                    }
                }
            }

            if (!fitsInSameLine)
            {
                y += editor.LineHeight;
            }
            double y2       = y + 0.5;
            double y2Bottom = y2 + editor.LineHeight - 1;

            selected = isEolSelected && (CollapseExtendedErrors || errors.Count == 1) ? 1 : 0;

// draw message text background
            if (CollapseExtendedErrors || errors.Count == 1)
            {
                if (!fitsInSameLine)
                {
// draw box below line
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2 - 1));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2 - 1));
                    g.ClosePath();
                    g.Color = colorMatrix [active, BOTTOM, LIGHT, highlighted, selected];
                    g.Fill();

                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2 - 1));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2Bottom));
                    g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
                    g.Stroke();
                }
                else
                {
// draw 'arrow marker' in the same line
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2));
                    double mid = y2 + topSize;
                    g.LineTo(new Cairo.PointD(x2 - editor.LineHeight / 2 + 0.5, mid));

                    g.LineTo(new Cairo.PointD(right, mid));
                    g.LineTo(new Cairo.PointD(right, y2));
                    g.ClosePath();
                    g.Color = colorMatrix [active, TOP, DARK, highlighted, selected];
                    g.Fill();
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                    g.LineTo(new Cairo.PointD(x2 - editor.LineHeight / 2 + 0.5, mid));

                    g.LineTo(new Cairo.PointD(right, mid));
                    g.LineTo(new Cairo.PointD(right, y2Bottom));
                    g.ClosePath();

                    g.Color = colorMatrix [active, BOTTOM, DARK, highlighted, selected];
                    g.Fill();

// draw border
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2));
                    g.LineTo(new Cairo.PointD(x2 - editor.LineHeight / 2 + 0.5, y2 + editor.LineHeight / 2));

                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2));
                    g.ClosePath();

                    g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
                    g.Stroke();
                }
            }
            else
            {
                if (!fitsInSameLine)
                {
// draw box below line
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2 - 1));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2 - 1));
                    g.ClosePath();
                }
                else
                {
// draw filled arrow box
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2));
                    g.LineTo(new Cairo.PointD(x2 - editor.LineHeight / 2 + 0.5, y2 + editor.LineHeight / 2));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2Bottom));
                    g.LineTo(new Cairo.PointD(right, y2));
                    g.ClosePath();
                }
                g.Color = colorMatrix [active, BOTTOM, LIGHT, highlighted, selected];
                g.Fill();

// draw light bottom line
                g.MoveTo(new Cairo.PointD(right, y2Bottom));
                g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                g.Stroke();

// stroke left line
                if (fitsInSameLine)
                {
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2));
                    g.LineTo(new Cairo.PointD(x2 - editor.LineHeight / 2 + 0.5, y2 + editor.LineHeight / 2));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom));
                }
                else
                {
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y2 - 1));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2Bottom + 1));
                }

                g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
                g.Stroke();

// stroke top line
                if (fitsInSameLine)
                {
                    g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
                    g.MoveTo(new Cairo.PointD(right, y2));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y2));
                    g.Stroke();
                }
            }

            if (editor.Options.ShowRuler)
            {
                double divider = Math.Max(editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
                if (divider >= x2)
                {
                    g.MoveTo(new Cairo.PointD(divider + 0.5, y2));
                    g.LineTo(new Cairo.PointD(divider + 0.5, y2Bottom));
                    g.Color = colorMatrix [active, BOTTOM, DARK, highlighted, selected];
                    g.Stroke();
                }
            }

            if (errors.Count > 1 && errorCountLayout != null)
            {
                double rX = x2 + (ShowIconsInBubble ? errorPixbuf.Width : 0) + border + LayoutWidth;
                double rY = y + editor.LineHeight / 6;
                double rW = errorCounterWidth - 2;
                double rH = editor.LineHeight * 3 / 4;
                BookmarkMarker.DrawRoundRectangle(g, rX, rY, 8, rW, rH);

                g.Color = oldIsOver ? new Cairo.Color(0.3, 0.3, 0.3) : new Cairo.Color(0.5, 0.5, 0.5);
                g.Fill();
                if (CollapseExtendedErrors)
                {
                    g.Color = gcLight;
                    g.Save();
                    g.Translate(x2 + (ShowIconsInBubble ? errorPixbuf.Width : 0) + border + LayoutWidth + 4, y + (editor.LineHeight - eh) / 2 + eh % 2);
                    g.ShowLayout(errorCountLayout);
                    g.Restore();
                }
                else
                {
                    g.MoveTo(rX + rW / 2 - rW / 4, rY + rH - rH / 4);
                    g.LineTo(rX + rW / 2 + rW / 4, rY + rH - rH / 4);
                    g.LineTo(rX + rW / 2, rY + rH / 4);
                    g.ClosePath();

                    g.Color = new Cairo.Color(1, 1, 1);
                    g.Fill();
                }
            }

            for (int i = 0; i < layouts.Count; i++)
            {
                LayoutDescriptor layout = layouts [i];
                x2 = right - layout.Width - border - errorPixbuf.Width;
                if (i == 0)
                {
                    x2 -= errorCounterWidth;
                }
                x2 = System.Math.Max(x2, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);
                if (i > 0)
                {
                    editor.TextViewMargin.DrawRectangleWithRuler(g, x, new Cairo.Rectangle(x, y, right, editor.LineHeight), isEolSelected ? editor.ColorStyle.Selection.CairoBackgroundColor : editor.ColorStyle.Default.CairoBackgroundColor, true);
                    g.MoveTo(new Cairo.PointD(x2 + 0.5, y));
                    g.LineTo(new Cairo.PointD(x2 + 0.5, y + editor.LineHeight));
                    g.LineTo(new Cairo.PointD(right, y + editor.LineHeight));
                    g.LineTo(new Cairo.PointD(right, y));
                    g.ClosePath();

                    if (CollapseExtendedErrors)
                    {
                        using (var pat = new Cairo.LinearGradient(x2, y, x2, y + editor.LineHeight)) {
                            pat.AddColorStop(0, colorMatrix [active, TOP, LIGHT, highlighted, selected]);
                            pat.AddColorStop(1, colorMatrix [active, BOTTOM, LIGHT, highlighted, selected]);
                            g.Pattern = pat;
                        }
                    }
                    else
                    {
                        g.Color = colorMatrix[active, TOP, LIGHT, highlighted, selected];
                    }
                    g.Fill();
                    if (editor.Options.ShowRuler)
                    {
                        double divider = Math.Max(editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
                        if (divider >= x2)
                        {
                            g.MoveTo(new Cairo.PointD(divider + 0.5, y));
                            g.LineTo(new Cairo.PointD(divider + 0.5, y + editor.LineHeight));
                            g.Color = colorMatrix[active, BOTTOM, DARK, highlighted, selected];
                            g.Stroke();
                        }
                    }
                }
                int lw, lh;
                layout.Layout.GetPixelSize(out lw, out lh);
                g.Color = (HslColor)(selected == 0 ? gc : gcSelected);
                g.Save();
                g.Translate(x2 + errorPixbuf.Width + border, y + (editor.LineHeight - layout.Height) / 2 + layout.Height % 2);
                g.ShowLayout(layout.Layout);
                g.Restore();
                y += editor.LineHeight;
                if (!UseVirtualLines)
                {
                    break;
                }
            }
            return(true);
        }
        public void Draw(TextEditor editor, Cairo.Context g, int lineNr, Cairo.Rectangle lineArea)
        {
            EnsureLayoutCreated(editor);
            int    lineNumber        = editor.Document.OffsetToLineNumber(lineSegment.Offset);
            int    errorNumber       = lineNr - lineNumber;
            double x                 = editor.TextViewMargin.XOffset;
            double y                 = lineArea.Y;
            double right             = editor.Allocation.Width;
            int    errorCounterWidth = 0;

            int ew = 0, eh = 0;

            if (errors.Count > 1 && errorCountLayout != null)
            {
                errorCountLayout.GetPixelSize(out ew, out eh);
                errorCounterWidth = ew + 10;
            }

            double x2 = System.Math.Max(right - LayoutWidth - border - (ShowIconsInBubble ? errorPixbuf.Width : 0) - errorCounterWidth, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);
//			bool isEolSelected = editor.IsSomethingSelected && editor.SelectionMode != SelectionMode.Block ? editor.SelectionRange.Contains (lineSegment.Offset  + lineSegment.EditableLength) : false;
            int              active        = editor.Document.GetTextAt(lineSegment) == initialText ? 0 : 1;
            bool             isCaretInLine = lineSegment.Offset <= editor.Caret.Offset && editor.Caret.Offset <= lineSegment.EndOffset;
            int              highlighted   = active == 0 && isCaretInLine ? 1 : 0;
            int              selected      = 0;
            LayoutDescriptor layout        = layouts[errorNumber];

            x2 = right - LayoutWidth - border - (ShowIconsInBubble ? errorPixbuf.Width : 0);

            x2 -= errorCounterWidth;
            x2  = System.Math.Max(x2, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);

            g.MoveTo(new Cairo.PointD(x2 + 0.5, y));
            g.LineTo(new Cairo.PointD(x2 + 0.5, y + editor.LineHeight));
            g.LineTo(new Cairo.PointD(right, y + editor.LineHeight));
            g.LineTo(new Cairo.PointD(right, y));
            g.ClosePath();
            g.Color = colorMatrix[active, BOTTOM, LIGHT, highlighted, selected];
            g.Fill();

            g.Color = colorMatrix[active, BOTTOM, LINE, highlighted, selected];
            g.MoveTo(new Cairo.PointD(x2 + 0.5, y));
            g.LineTo(new Cairo.PointD(x2 + 0.5, y + editor.LineHeight));
            if (errorNumber == errors.Count - 1)
            {
                g.LineTo(new Cairo.PointD(lineArea.X + lineArea.Width, y + editor.LineHeight));
            }
            g.Stroke();

            if (editor.Options.ShowRuler)
            {
                double divider = Math.Max(editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
                if (divider >= x2)
                {
                    g.MoveTo(new Cairo.PointD(divider + 0.5, y));
                    g.LineTo(new Cairo.PointD(divider + 0.5, y + editor.LineHeight));
                    g.Color = colorMatrix[active, BOTTOM, DARK, highlighted, selected];
                    g.Stroke();
                }
            }
            g.Save();
            g.Translate(x2 + (ShowIconsInBubble ? errorPixbuf.Width : 0) + border, y + (editor.LineHeight - layout.Height) / 2 + layout.Height % 2);
            g.Color = selected == 0 ? gc : gcSelected;
            g.ShowLayout(layout.Layout);
            g.Restore();
//			if (ShowIconsInBubble)
//				win.DrawPixbuf (editor.Style.BaseGC (Gtk.StateType.Normal), errors[errorNumber].IsError ? errorPixbuf : warningPixbuf, 0, 0, x2, y + (editor.LineHeight - errorPixbuf.Height) / 2, errorPixbuf.Width, errorPixbuf.Height, Gdk.RgbDither.None, 0, 0);
        }
        public void Draw(TextEditor editor, Cairo.Context g, int lineNr, Cairo.Rectangle lineArea)
        {
            EnsureLayoutCreated(editor);
            int lineNumber  = editor.Document.OffsetToLineNumber(lineSegment.Offset);
            int errorNumber = lineNr - lineNumber;

            if (!IsCurrentErrorTextFitting())
            {
                errorNumber--;
            }
            double x                 = editor.TextViewMargin.XOffset;
            double y                 = lineArea.Y;
            double right             = editor.Allocation.Width;
            int    errorCounterWidth = GetErrorCountBounds().Item1;
//			int eh = GetErrorCountBounds ().Item2;

            double x2 = System.Math.Max(right - LayoutWidth - border - (ShowIconsInBubble ? cache.errorPixbuf.Width : 0) - errorCounterWidth, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);

            if (errors.Count == 1)
            {
                x2 = editor.TextViewMargin.XOffset;
            }
//			bool isEolSelected = editor.IsSomethingSelected && editor.SelectionMode != SelectionMode.Block ? editor.SelectionRange.Contains (lineSegment.Offset  + lineSegment.EditableLength) : false;
            int  active        = editor.Document.GetTextAt(lineSegment) == initialText ? 0 : 1;
            bool isCaretInLine = lineSegment.Offset <= editor.Caret.Offset && editor.Caret.Offset <= lineSegment.EndOffsetIncludingDelimiter;
            int  highlighted   = active == 0 && isCaretInLine ? 1 : 0;
            int  selected      = 0;
            var  layout        = layouts [errorNumber];

            x2 = right - LayoutWidth - border - (ShowIconsInBubble ? cache.errorPixbuf.Width : 0);

            x2 -= errorCounterWidth;
            x2  = System.Math.Max(x2, fitsInSameLine ? editor.TextViewMargin.XOffset + editor.LineHeight / 2 : editor.TextViewMargin.XOffset);

            g.MoveTo(new Cairo.PointD(x2 + 0.5, y));
            g.LineTo(new Cairo.PointD(x2 + 0.5, y + editor.LineHeight));
            g.LineTo(new Cairo.PointD(right, y + editor.LineHeight));
            g.LineTo(new Cairo.PointD(right, y));
            g.ClosePath();
            g.Color = colorMatrix [active, BOTTOM, LIGHT, highlighted, selected];
            g.Fill();

            g.Color = colorMatrix [active, BOTTOM, LINE, highlighted, selected];
            g.MoveTo(new Cairo.PointD(x2 + 0.5, y));
            g.LineTo(new Cairo.PointD(x2 + 0.5, y + editor.LineHeight));
            if (errorNumber == errors.Count - 1)
            {
                g.LineTo(new Cairo.PointD(lineArea.X + lineArea.Width, y + editor.LineHeight));
            }
            g.Stroke();

            if (editor.Options.ShowRuler)
            {
                double divider = Math.Max(editor.TextViewMargin.XOffset, x + editor.TextViewMargin.RulerX);
                if (divider >= x2)
                {
                    g.MoveTo(new Cairo.PointD(divider + 0.5, y));
                    g.LineTo(new Cairo.PointD(divider + 0.5, y + editor.LineHeight));
                    g.Color = colorMatrix [active, BOTTOM, DARK, highlighted, selected];
                    g.Stroke();
                }
            }
            g.Save();
            g.Translate(x2 + (ShowIconsInBubble ? cache.errorPixbuf.Width : 0) + border, y + (editor.LineHeight - layout.Height) / 2 + layout.Height % 2);
            g.Color = selected == 0 ? gc : cache.gcSelected;
            g.ShowLayout(layout.Layout);
            g.Restore();

            if (ShowIconsInBubble)
            {
                var pixbuf = errors [errorNumber].IsError ? cache.errorPixbuf: cache.warningPixbuf;
                Gdk.CairoHelper.SetSourcePixbuf(g, pixbuf, x2, y + (editor.LineHeight - cache.errorPixbuf.Height) / 2);
                g.Paint();
            }
        }