Esempio n. 1
0
        protected override void Render(Drawable window, Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags)
        {
            if (isDisposed)
            {
                return;
            }
            if (diffMode)
            {
                if (path.Equals(selctedPath))
                {
                    selectedLine = -1;
                    selctedPath  = null;
                }

                int w, maxy;
                window.GetSize(out w, out maxy);
                if (DrawLeft)
                {
                    cell_area.Width += cell_area.X - leftSpace;
                    cell_area.X      = leftSpace;
                }
                var treeview = widget as FileTreeView;
                var p        = treeview != null? treeview.CursorLocation : null;

                cell_area.Width -= RightPadding;

                window.DrawRectangle(widget.Style.BaseGC(Gtk.StateType.Normal), true, cell_area.X, cell_area.Y, cell_area.Width - 1, cell_area.Height);

                Gdk.GC normalGC  = widget.Style.TextGC(StateType.Normal);
                Gdk.GC removedGC = new Gdk.GC(window);
                removedGC.Copy(normalGC);
                removedGC.RgbFgColor = Styles.LogView.DiffRemoveBackgroundColor.AddLight(-0.3).ToGdkColor();
                Gdk.GC addedGC = new Gdk.GC(window);
                addedGC.Copy(normalGC);
                addedGC.RgbFgColor = Styles.LogView.DiffAddBackgroundColor.AddLight(-0.3).ToGdkColor();
                Gdk.GC infoGC = new Gdk.GC(window);
                infoGC.Copy(normalGC);
                infoGC.RgbFgColor = widget.Style.Text(StateType.Normal).AddLight(0.2);

                Cairo.Context ctx = CairoHelper.Create(window);

                // Rendering is done in two steps:
                // 1) Get a list of blocks to render
                // 2) render the blocks

                int y = cell_area.Y + 2;

                // cline keeps track of the current source code line (the one to jump to when double clicking)
                int       cline        = 1;
                bool      inHeader     = true;
                BlockInfo currentBlock = null;

                List <BlockInfo> blocks = new List <BlockInfo> ();

                for (int n = 0; n < lines.Length; n++, y += lineHeight)
                {
                    string line = lines [n];
                    if (line.Length == 0)
                    {
                        currentBlock = null;
                        y           -= lineHeight;
                        continue;
                    }

                    char tag = line [0];

                    if (line.StartsWith("---", StringComparison.Ordinal) ||
                        line.StartsWith("+++", StringComparison.Ordinal))
                    {
                        // Ignore this part of the header.
                        currentBlock = null;
                        y           -= lineHeight;
                        continue;
                    }
                    if (tag == '@')
                    {
                        int l = ParseCurrentLine(line);
                        if (l != -1)
                        {
                            cline = l - 1;
                        }
                        inHeader = false;
                    }
                    else if (tag == '+' && !inHeader)
                    {
                        cline++;
                    }

                    BlockType type;
                    switch (tag)
                    {
                    case '-': type = BlockType.Removed; break;

                    case '+': type = BlockType.Added; break;

                    case '@': type = BlockType.Info; break;

                    default: type = BlockType.Unchanged; break;
                    }

                    if (currentBlock == null || type != currentBlock.Type)
                    {
                        if (y > maxy)
                        {
                            break;
                        }

                        // Starting a new block. Mark section ends between a change block and a normal code block
                        if (currentBlock != null && IsChangeBlock(currentBlock.Type) && !IsChangeBlock(type))
                        {
                            currentBlock.SectionEnd = true;
                        }

                        currentBlock = new BlockInfo()
                        {
                            YStart          = y,
                            FirstLine       = n,
                            Type            = type,
                            SourceLineStart = cline,
                            SectionStart    = (blocks.Count == 0 || !IsChangeBlock(blocks[blocks.Count - 1].Type)) && IsChangeBlock(type)
                        };
                        blocks.Add(currentBlock);
                    }
                    // Include the line in the current block
                    currentBlock.YEnd     = y + lineHeight;
                    currentBlock.LastLine = n;
                }

                // Now render the blocks

                // The y position of the highlighted line
                int selectedLineRowTop = -1;

                BlockInfo lastCodeSegmentStart = null;
                BlockInfo lastCodeSegmentEnd   = null;

                foreach (BlockInfo block in blocks)
                {
                    if (block.Type == BlockType.Info)
                    {
                        // Finished drawing the content of a code segment. Now draw the segment border and label.
                        if (lastCodeSegmentStart != null)
                        {
                            DrawCodeSegmentBorder(infoGC, ctx, cell_area.X, cell_area.Width, lastCodeSegmentStart, lastCodeSegmentEnd, lines, widget, window);
                        }
                        lastCodeSegmentStart = block;
                    }

                    lastCodeSegmentEnd = block;

                    if (block.YEnd < 0)
                    {
                        continue;
                    }

                    // Draw the block background
                    DrawBlockBg(ctx, cell_area.X + 1, cell_area.Width - 2, block);

                    // Get all text for the current block
                    StringBuilder sb = new StringBuilder();
                    for (int n = block.FirstLine; n <= block.LastLine; n++)
                    {
                        string s = ProcessLine(lines [n]);
                        if (n > block.FirstLine)
                        {
                            sb.Append('\n');
                        }
                        if ((block.Type == BlockType.Added || block.Type == BlockType.Removed) && s.Length > 0)
                        {
                            sb.Append(' ');
                            sb.Append(s, 1, s.Length - 1);
                        }
                        else
                        {
                            sb.Append(s);
                        }
                    }

                    // Draw a special background for the selected line

                    if (block.Type != BlockType.Info && p.HasValue && p.Value.X >= cell_area.X && p.Value.X <= cell_area.Right && p.Value.Y >= block.YStart && p.Value.Y <= block.YEnd)
                    {
                        int    row  = (p.Value.Y - block.YStart) / lineHeight;
                        double yrow = block.YStart + lineHeight * row;
                        double xrow = cell_area.X + LeftPaddingBlock;
                        int    wrow = cell_area.Width - 1 - LeftPaddingBlock;
                        if (block.Type == BlockType.Added)
                        {
                            ctx.SetSourceColor(Styles.LogView.DiffAddBackgroundColor.AddLight(0.1).ToCairoColor());
                        }
                        else if (block.Type == BlockType.Removed)
                        {
                            ctx.SetSourceColor(Styles.LogView.DiffRemoveBackgroundColor.AddLight(0.1).ToCairoColor());
                        }
                        else
                        {
                            ctx.SetSourceColor(Styles.LogView.DiffHighlightColor.ToCairoColor());
                            xrow -= LeftPaddingBlock;
                            wrow += LeftPaddingBlock;
                        }
                        ctx.Rectangle(xrow, yrow, wrow, lineHeight);
                        ctx.Fill();
                        selectedLine       = block.SourceLineStart + row;
                        selctedPath        = path;
                        selectedLineRowTop = (int)yrow;
                    }

                    // Draw the line text. Ignore header blocks, since they are drawn as labels in DrawCodeSegmentBorder

                    if (block.Type != BlockType.Info)
                    {
                        layout.SetMarkup("");
                        layout.SetText(sb.ToString());
                        Gdk.GC gc;
                        switch (block.Type)
                        {
                        case BlockType.Removed: gc = removedGC; break;

                        case BlockType.Added: gc = addedGC; break;

                        case BlockType.Info: gc = infoGC; break;

                        default: gc = normalGC; break;
                        }
                        window.DrawLayout(gc, cell_area.X + 2 + LeftPaddingBlock, block.YStart, layout);
                    }

                    // Finally draw the change symbol at the left margin

                    DrawChangeSymbol(ctx, widget, cell_area.X + 1, cell_area.Width - 2, block);
                }

                // Finish the drawing of the code segment
                if (lastCodeSegmentStart != null)
                {
                    DrawCodeSegmentBorder(infoGC, ctx, cell_area.X, cell_area.Width, lastCodeSegmentStart, lastCodeSegmentEnd, lines, widget, window);
                }

                // Draw the source line number at the current selected line. It must be done at the end because it must
                // be drawn over the source code text and segment borders.
                if (selectedLineRowTop != -1)
                {
                    DrawLineBox(normalGC, ctx, ((Gtk.TreeView)widget).VisibleRect.Right - 4, selectedLineRowTop, selectedLine, widget, window);
                }

                ((IDisposable)ctx).Dispose();
                removedGC.Dispose();
                addedGC.Dispose();
                infoGC.Dispose();
            }
            else
            {
                // Rendering a normal text row
                int y = cell_area.Y + (cell_area.Height - height) / 2;
                window.DrawLayout(widget.Style.TextGC(GetState(widget, flags)), cell_area.X, y, layout);
            }
        }
Esempio n. 2
0
        protected override void Render(Drawable window, Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags)
        {
            if (isDisposed || layout == null)
            {
                return;
            }
            if (diffMode)
            {
                if (path.Equals(selctedPath))
                {
                    selectedLine = -1;
                    selctedPath  = null;
                }

                int w, maxy;
                window.GetSize(out w, out maxy);
                if (DrawLeft)
                {
                    cell_area.Width += cell_area.X - leftSpace;
                    cell_area.X      = leftSpace;
                }
                var treeview = widget as FileTreeView;
                var p        = treeview != null? treeview.CursorLocation : null;
                cell_area.Width -= RightPadding;

                window.DrawRectangle(widget.Style.BaseGC(Gtk.StateType.Normal), true, cell_area.X, cell_area.Y, cell_area.Width - 1, cell_area.Height);

                Gdk.GC normalGC  = widget.Style.TextGC(StateType.Normal);
                Gdk.GC removedGC = new Gdk.GC(window);
                removedGC.Copy(normalGC);
                removedGC.RgbFgColor = Styles.LogView.DiffRemoveBackgroundColor.AddLight(-0.3).ToGdkColor();
                Gdk.GC addedGC = new Gdk.GC(window);
                addedGC.Copy(normalGC);
                addedGC.RgbFgColor = Styles.LogView.DiffAddBackgroundColor.AddLight(-0.3).ToGdkColor();
                Gdk.GC infoGC = new Gdk.GC(window);
                infoGC.Copy(normalGC);
                infoGC.RgbFgColor = widget.Style.Text(StateType.Normal).AddLight(0.2);

                Cairo.Context ctx = CairoHelper.Create(window);

                // Rendering is done in two steps:
                // 1) Get a list of blocks to render
                // 2) render the blocks

                var blocks = CalculateBlocks(maxy, cell_area.Y + 2);

                // Now render the blocks

                // The y position of the highlighted line
                int selectedLineRowTop = -1;

                BlockInfo lastCodeSegmentStart = null;
                BlockInfo lastCodeSegmentEnd   = null;

                foreach (BlockInfo block in blocks)
                {
                    if (block.Type == BlockType.Info)
                    {
                        // Finished drawing the content of a code segment. Now draw the segment border and label.
                        if (lastCodeSegmentStart != null)
                        {
                            DrawCodeSegmentBorder(infoGC, ctx, cell_area.X, cell_area.Width, lastCodeSegmentStart, lastCodeSegmentEnd, lines, widget, window);
                        }
                        lastCodeSegmentStart = block;
                    }

                    lastCodeSegmentEnd = block;

                    if (block.YEnd < 0)
                    {
                        continue;
                    }

                    // Draw the block background
                    DrawBlockBg(ctx, cell_area.X + 1, cell_area.Width - 2, block);

                    // Get all text for the current block
                    StringBuilder sb = new StringBuilder();
                    for (int n = block.FirstLine; n <= block.LastLine; n++)
                    {
                        string s = ProcessLine(lines [n]);
                        if (n > block.FirstLine)
                        {
                            sb.Append('\n');
                        }
                        if ((block.Type == BlockType.Added || block.Type == BlockType.Removed) && s.Length > 0)
                        {
                            sb.Append(' ');
                            sb.Append(s, 1, s.Length - 1);
                        }
                        else
                        {
                            sb.Append(s);
                        }
                    }

                    // Draw a special background for the selected line

                    if (block.Type != BlockType.Info && p.HasValue && p.Value.X >= cell_area.X && p.Value.X <= cell_area.Right && p.Value.Y >= block.YStart && p.Value.Y <= block.YEnd)
                    {
                        int    row  = (p.Value.Y - block.YStart) / lineHeight;
                        double yrow = block.YStart + lineHeight * row;
                        double xrow = cell_area.X + LeftPaddingBlock;
                        int    wrow = cell_area.Width - 1 - LeftPaddingBlock;
                        if (block.Type == BlockType.Added)
                        {
                            ctx.SetSourceColor(Styles.LogView.DiffAddBackgroundColor.AddLight(0.1).ToCairoColor());
                        }
                        else if (block.Type == BlockType.Removed)
                        {
                            ctx.SetSourceColor(Styles.LogView.DiffRemoveBackgroundColor.AddLight(0.1).ToCairoColor());
                        }
                        else
                        {
                            ctx.SetSourceColor(Styles.LogView.DiffHighlightColor.ToCairoColor());
                            xrow -= LeftPaddingBlock;
                            wrow += LeftPaddingBlock;
                        }
                        ctx.Rectangle(xrow, yrow, wrow, lineHeight);
                        ctx.Fill();
                        selectedLine       = block.SourceLineStart + row;
                        selctedPath        = path;
                        selectedLineRowTop = (int)yrow;
                    }

                    // Draw the line text. Ignore header blocks, since they are drawn as labels in DrawCodeSegmentBorder

                    if (block.Type != BlockType.Info)
                    {
                        layout.SetMarkup("");
                        layout.SetText(sb.ToString());
                        Gdk.GC gc;
                        switch (block.Type)
                        {
                        case BlockType.Removed: gc = removedGC; break;

                        case BlockType.Added: gc = addedGC; break;

                        case BlockType.Info: gc = infoGC; break;

                        default: gc = normalGC; break;
                        }
                        window.DrawLayout(gc, cell_area.X + 2 + LeftPaddingBlock, block.YStart, layout);
                    }

                    // Finally draw the change symbol at the left margin

                    DrawChangeSymbol(ctx, widget, cell_area.X + 1, cell_area.Width - 2, block);
                }

                // Finish the drawing of the code segment
                if (lastCodeSegmentStart != null)
                {
                    DrawCodeSegmentBorder(infoGC, ctx, cell_area.X, cell_area.Width, lastCodeSegmentStart, lastCodeSegmentEnd, lines, widget, window);
                }

                // Draw the source line number at the current selected line. It must be done at the end because it must
                // be drawn over the source code text and segment borders.
                if (selectedLineRowTop != -1)
                {
                    DrawLineBox(normalGC, ctx, ((Gtk.TreeView)widget).VisibleRect.Right - 4, selectedLineRowTop, selectedLine, widget, window);
                }

                ((IDisposable)ctx).Dispose();
                removedGC.Dispose();
                addedGC.Dispose();
                infoGC.Dispose();
            }
            else
            {
                // Rendering a normal text row
                int y = cell_area.Y + (cell_area.Height - height) / 2;
                window.DrawLayout(widget.Style.TextGC(GetState(widget, flags)), cell_area.X, y, layout);
            }
        }
Esempio n. 3
0
        private void OnDataRowDeleted(object o, RowDeletedArgs args)
        {
            if (model == null || args.Path == null)
            {
                return;
            }

            bool sel_paths_changed = false;

            // Don't update the real n_cells, as doing this will
            // throw off ScrollToPath if called before SizeAllocate
            // is run
            int n_cells = model.IterNChildren();

            for (int i = 0; i < selected_paths.Count; i++)
            {
                TreePath path = (TreePath)selected_paths[i];

                int cmp = path.Compare(args.Path);
                if (cmp == 0)
                {
                    selected_paths.RemoveAt(i);
                    i--;
                    sel_paths_changed = true;
                    continue;
                }

                // decrement each path that follows the one we
                // just deleted
                if (cmp > 0)
                {
                    path.Prev();
                    selected_paths[i] = path;
                    continue;
                }
            }

            if (sel_paths_changed && SelectionChanged != null)
            {
                SelectionChanged(this, new EventArgs());
            }

            if (focused_path != null &&
                focused_path.Equals(args.Path))
            {
                focused_path = focused_path.Copy();

                // try to advance the focus forward
                focused_path.Next();

                if (!PathIsValid(focused_path, n_cells) &&
                    !focused_path.Prev())
                {
                    focused_path = null;
                }
            }

            if (selection_anchor != null &&
                selection_anchor.Equals(args.Path))
            {
                selection_anchor = null;
            }

            QueueResize();
        }
Esempio n. 4
0
        protected override void Render(Drawable window, Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags)
        {
            if (isDisposed)
            {
                return;
            }
            if (diffMode)
            {
                if (path.Equals(selctedPath))
                {
                    selectedLine = -1;
                    selctedPath  = null;
                }

                int w, maxy;
                window.GetSize(out w, out maxy);

                var treeview = widget as FileTreeView;
                var p        = treeview != null? treeview.CursorLocation : null;

                int recty = cell_area.Y;
                int recth = cell_area.Height - 1;
                if (recty < 0)
                {
                    recth += recty + 1;
                    recty  = -1;
                }
                if (recth > maxy + 2)
                {
                    recth = maxy + 2;
                }

                window.DrawRectangle(widget.Style.BaseGC(Gtk.StateType.Normal), true, cell_area.X, recty, cell_area.Width - 1, recth);

                Gdk.GC normalGC  = widget.Style.TextGC(StateType.Normal);
                Gdk.GC removedGC = new Gdk.GC(window);
                removedGC.Copy(normalGC);
                removedGC.RgbFgColor = new Color(255, 0, 0);
                Gdk.GC addedGC = new Gdk.GC(window);
                addedGC.Copy(normalGC);
                addedGC.RgbFgColor = new Color(0, 0, 255);
                Gdk.GC infoGC = new Gdk.GC(window);
                infoGC.Copy(normalGC);
                infoGC.RgbFgColor = new Color(0xa5, 0x2a, 0x2a);

                int  y        = cell_area.Y + 2;
                int  cline    = 1;
                bool inHeader = true;

                for (int n = 0; n < lines.Length; n++, y += lineHeight)
                {
                    string line = lines [n];
                    if (line.Length == 0)
                    {
                        continue;
                    }

                    char tag = line [0];

                    // Keep track of the real file line
                    int thisLine = cline;
                    if (tag == '@')
                    {
                        int l = ParseCurrentLine(line);
                        if (l != -1)
                        {
                            cline = thisLine = l;
                        }
                        inHeader = false;
                    }
                    else if (tag != '-' && !inHeader)
                    {
                        cline++;
                    }

                    if (y + lineHeight < 0)
                    {
                        continue;
                    }
                    if (y > maxy)
                    {
                        break;
                    }

                    Gdk.GC gc;
                    switch (tag)
                    {
                    case '-': gc = removedGC; break;

                    case '+': gc = addedGC; break;

                    case '@': gc = infoGC; break;

                    default: gc = normalGC; break;
                    }

                    if (p.HasValue && p.Value.X >= cell_area.X && p.Value.X <= cell_area.Right && p.Value.Y >= y && p.Value.Y < y + lineHeight)
                    {
                        window.DrawRectangle(widget.Style.BaseGC(Gtk.StateType.Prelight), true, cell_area.X, y, cell_area.Width - 1, lineHeight);
                        selectedLine = thisLine;
                        selctedPath  = path;
                    }

                    layout.SetText(line);
                    window.DrawLayout(gc, cell_area.X + 2, y, layout);
                }
                window.DrawRectangle(widget.Style.DarkGC(Gtk.StateType.Prelight), false, cell_area.X, recty, cell_area.Width - 1, recth);
                removedGC.Dispose();
                addedGC.Dispose();
                infoGC.Dispose();
            }
            else
            {
                int y = cell_area.Y + (cell_area.Height - height) / 2;
                window.DrawLayout(widget.Style.TextGC(GetState(flags)), cell_area.X, y, layout);
            }
        }