Skip to content

Commit

Permalink
#4990 RevisionGrid: Show more informative tooltips
Browse files Browse the repository at this point in the history
Show lane information in tooltip for RevisionGrid.GraphDataGridViewColumn.
Show tooltips for RevisionGrid /always/ if text has been truncated.
  • Loading branch information
mstv authored and drewnoakes committed Jun 5, 2018
1 parent 84fe304 commit 74871a9
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 19 deletions.
5 changes: 2 additions & 3 deletions GitUI/BuildServerIntegration/BuildInfoDrawingLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Brush GetBrush()
}
}

public static void BuildStatusMessageCellPainting(DataGridViewCellPaintingEventArgs e, GitRevision revision, Color foreColor, Font rowFont, bool isSelected)
public static void BuildStatusMessageCellPainting(DataGridViewCellPaintingEventArgs e, GitRevision revision, Color foreColor, Font rowFont, bool isSelected, RevisionGrid revisions)
{
if (revision.BuildStatus == null)
{
Expand All @@ -60,8 +60,7 @@ public static void BuildStatusMessageCellPainting(DataGridViewCellPaintingEventA

var color = GetColor();
var text = (string)e.FormattedValue;
var rect = RevisionGridUtils.GetCellRectangle(e);
RevisionGridUtils.DrawColumnText(e.Graphics, text, rowFont, color, rect);
revisions.DrawColumnText(e, text, rowFont, color);

Color GetColor()
{
Expand Down
1 change: 1 addition & 0 deletions GitUI/UserControls/RevisionGrid.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

95 changes: 82 additions & 13 deletions GitUI/UserControls/RevisionGrid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ public RevisionGrid()
Revisions.KeyUp += RevisionsKeyUp;
Revisions.KeyDown += RevisionsKeyDown;
Revisions.MouseDown += RevisionsMouseDown;
Revisions.ShowCellToolTips = false;
Revisions.MouseEnter += RevisionsMouseEnter;
Revisions.CellMouseMove += RevisionsMouseMove;

showMergeCommitsToolStripMenuItem.Checked = AppSettings.ShowMergeCommits;
BranchFilter = string.Empty;
Expand All @@ -191,7 +194,6 @@ public RevisionGrid()
Revisions.ColumnHeadersVisible = false;
Revisions.IdColumn.Visible = AppSettings.ShowIds;

IsMessageMultilineDataGridViewColumn.Width = DpiUtil.Scale(25);
IsMessageMultilineDataGridViewColumn.DisplayIndex = 2;
IsMessageMultilineDataGridViewColumn.Resizable = DataGridViewTriState.False;

Expand All @@ -217,6 +219,75 @@ public RevisionGrid()
BuildServerWatcher = new BuildServerWatcher(this, Revisions);
}

#region ToolTip

private ToolTip _toolTip = new ToolTip();
private Dictionary<Point, bool> _showCellToolTip = new Dictionary<Point, bool>();

private void RevisionsMouseEnter(object sender, EventArgs e)
{
_toolTip.Active = false;
_toolTip.AutoPopDelay = 32767;
}

private void RevisionsMouseMove(object sender, DataGridViewCellMouseEventArgs e)
{
string oldTooltip = _toolTip.GetToolTip(Revisions);
string newToolTip = oldTooltip;
bool showToolTip = false;
if (e.ColumnIndex == GraphDataGridViewColumn.Index)
{
newToolTip = Revisions.GetLaneInfo(e.RowIndex, e.X, Module);
}
else if (e.ColumnIndex == IsMessageMultilineDataGridViewColumn.Index)
{
newToolTip = IsMessageMultiline(e.RowIndex) ? Revisions.GetRowData(e.RowIndex).Body : string.Empty;
}
else if (e.ColumnIndex == MessageDataGridViewColumn.Index && IsMessageMultiline(e.RowIndex))
{
newToolTip = Revisions.GetRowData(e.RowIndex).Body;
}
else if (_showCellToolTip.TryGetValue(new Point(e.ColumnIndex, e.RowIndex), out showToolTip) && showToolTip)
{
newToolTip = e.ColumnIndex == IdDataGridViewColumn.Index
? Revisions.GetRowData(e.RowIndex).Guid
: Revisions.Rows[e.RowIndex].Cells[e.ColumnIndex].FormattedValue.ToString();
}
else
{
// no tooltip unless always active or truncated
newToolTip = string.Empty;
}

if (newToolTip != oldTooltip)
{
_toolTip.SetToolTip(Revisions, newToolTip);
}

if (!_toolTip.Active)
{
_toolTip.Active = true;
}
}

private bool IsMessageMultiline(int row)
{
return !Revisions.Rows[row].Cells[IsMessageMultilineDataGridViewColumn.Index].FormattedValue.ToString().IsNullOrEmpty();
}

internal void DrawColumnText(DataGridViewCellPaintingEventArgs e, string text, Font font, Color color)
{
DrawColumnText(e, text, font, color, RevisionGridUtils.GetCellRectangle(e));
}

internal void DrawColumnText(DataGridViewCellPaintingEventArgs e, string text, Font font, Color color, Rectangle bounds)
{
bool truncated = RevisionGridUtils.DrawColumnTextTruncated(e.Graphics, text, font, color, bounds);
_showCellToolTip[new Point(e.ColumnIndex, e.RowIndex)] = truncated;
}

#endregion // ToolTip

private static void FillMenuFromMenuCommands(IEnumerable<MenuCommand> menuCommands, ToolStripMenuItem targetMenuItem)
{
foreach (var menuCommand in menuCommands)
Expand Down Expand Up @@ -266,6 +337,7 @@ public Font NormalFont
_fontOfSHAColumn = new Font("Consolas", _normalFont.SizeInPoints);
IdDataGridViewColumn.DefaultCellStyle.Font = _fontOfSHAColumn;
IsMessageMultilineDataGridViewColumn.DefaultCellStyle.Font = _normalFont;
IsMessageMultilineDataGridViewColumn.Width = TextRenderer.MeasureText(MultilineMessageIndicator, NormalFont).Width;

RefsFont = IsFilledBranchesLayout() ? _normalFont : new Font(_normalFont, FontStyle.Bold);
HeadFont = new Font(_normalFont, FontStyle.Bold);
Expand Down Expand Up @@ -796,6 +868,8 @@ public override void Refresh()

base.Refresh();

_showCellToolTip.Clear();

Revisions.Refresh();
}

Expand Down Expand Up @@ -1835,7 +1909,7 @@ private void RevisionsCellPainting(object sender, DataGridViewCellPaintingEventA

var text = (string)e.FormattedValue;
var bounds = AdjustCellBounds(e.CellBounds, offset);
RevisionGridUtils.DrawColumnText(e.Graphics, text, rowFont, foreColor, bounds);
DrawColumnText(e, text, rowFont, foreColor, bounds);

if (IsCardLayout())
{
Expand Down Expand Up @@ -1891,26 +1965,22 @@ private void RevisionsCellPainting(object sender, DataGridViewCellPaintingEventA
if (!revision.IsArtificial)
{
var text = (string)e.FormattedValue;
e.Graphics.DrawString(text, rowFont, foreBrush,
new PointF(e.CellBounds.Left, e.CellBounds.Top + 4));
DrawColumnText(e, text, rowFont, foreColor);
}
}
else if (columnIndex == dateColIndex)
{
var time = AppSettings.ShowAuthorDate ? revision.AuthorDate : revision.CommitDate;
var text = TimeToString(time);
e.Graphics.DrawString(text, rowFont, foreBrush,
new PointF(e.CellBounds.Left, e.CellBounds.Top + 4));
DrawColumnText(e, text, rowFont, foreColor);
}
else if (columnIndex == idColIndex)
{
if (!revision.IsArtificial)
{
// do not show artificial GUID
var text = revision.Guid;
var rect = RevisionGridUtils.GetCellRectangle(e);
RevisionGridUtils.DrawColumnText(e.Graphics, text, _fontOfSHAColumn,
foreColor, rect);
DrawColumnText(e, text, _fontOfSHAColumn, foreColor);
}
}
else if (columnIndex == BuildServerWatcher.BuildStatusImageColumnIndex)
Expand All @@ -1920,13 +1990,12 @@ private void RevisionsCellPainting(object sender, DataGridViewCellPaintingEventA
else if (columnIndex == BuildServerWatcher.BuildStatusMessageColumnIndex)
{
var isSelected = Revisions.Rows[e.RowIndex].Selected;
BuildInfoDrawingLogic.BuildStatusMessageCellPainting(e, revision, foreColor, rowFont, isSelected);
BuildInfoDrawingLogic.BuildStatusMessageCellPainting(e, revision, foreColor, rowFont, isSelected, this);
}
else if (AppSettings.ShowIndicatorForMultilineMessage && columnIndex == isMsgMultilineColIndex)
{
var text = (string)e.FormattedValue;
e.Graphics.DrawString(text, rowFont, foreBrush,
new PointF(e.CellBounds.Left, e.CellBounds.Top + 4));
DrawColumnText(e, text, rowFont, foreColor);
}
}
}
Expand Down Expand Up @@ -1993,7 +2062,7 @@ private float DrawRef(DrawRefArgs drawRefArgs, float offset, string name, Color
headBounds.Offset((int)(extraOffset + 1), 0);
}

RevisionGridUtils.DrawColumnText(drawRefArgs.Graphics, headName, drawRefArgs.RefsFont, textColor, headBounds);
RevisionGridUtils.DrawColumnTextTruncated(drawRefArgs.Graphics, headName, drawRefArgs.RefsFont, textColor, headBounds);
}

return offset;
Expand Down
105 changes: 105 additions & 0 deletions GitUI/UserControls/RevisionGridClasses/DvcsGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Threading;
using System.Windows.Forms;
using GitCommands;
using GitCommands.Git.Extensions;
using GitExtUtils.GitUI;

namespace GitUI.RevisionGridClasses
Expand Down Expand Up @@ -337,6 +338,110 @@ public GitRevision GetRowData(int rowIndex)
}
}

private static bool AppendBranches(string prefix, ref System.Text.StringBuilder text, IEnumerable<GitUIPluginInterfaces.IGitRef> refs, ref HashSet<string> shown)
{
bool any = false;
foreach (var gitref in refs)
{
if (!AppSettings.ShowRemoteBranches && !gitref.Remote.IsNullOrEmpty())
{
continue;
}

text.Append(any ? ", " : prefix);
any = true;
text.Append(gitref.Name);
shown.Add(gitref.Name);
}

return any;
}

public string GetLaneInfo(int row, int x, GitModule currentModule)
{
int lane = (x - _laneSidePadding) / _laneWidth;
var laneInfoText = new System.Text.StringBuilder();
lock (_graphData)
{
Graph.ILaneRow laneRow = _graphData[row];
if (laneRow != null)
{
DvcsGraph.Node node = null;
if (lane == laneRow.NodeLane)
{
node = laneRow.Node;
if (!node.Id.IsArtificial())
{
laneInfoText.AppendLine(node.Id);
}
}
else if (lane >= 0 && lane < laneRow.Count)
{
for (int laneInfoIndex = 0, laneInfoCount = laneRow.LaneInfoCount(lane); laneInfoIndex < laneInfoCount; ++laneInfoIndex)
{
// search for next node below this row
Graph.LaneInfo laneInfo = laneRow[lane, laneInfoIndex];
DvcsGraph.Junction firstJunction = laneInfo.Junctions.First();
for (int nodeIndex = 0, nodeCount = firstJunction.NodesCount; nodeIndex < nodeCount; ++nodeIndex)
{
DvcsGraph.Node laneNode = firstJunction[nodeIndex];
if (laneNode.Index > row)
{
node = laneNode;
break; // from for (nodes)
}
}
}
}

if (node != null)
{
var shownBranches = new HashSet<string>();
if (AppendBranches("at ", ref laneInfoText, node.Data.Refs, ref shownBranches))
{
laneInfoText.AppendLine();
}

const string headSuffix = "/HEAD";
const string remotesPrefix = "remotes/";
var branches
= currentModule.GetAllBranchesWhichContainGivenCommit(node.Id, getLocal: true, getRemote: AppSettings.ShowRemoteBranches)
.Where(branch => !branch.EndsWith(headSuffix)).ToList();
for (int branchIndex = 0, branchCount = branches.Count; branchIndex < branchCount; ++branchIndex)
{
if (branches[branchIndex].StartsWith(remotesPrefix))
{
branches[branchIndex] = branches[branchIndex].Remove(0, remotesPrefix.Length);
}
}

branches = branches.Except(shownBranches).ToList();
if (branches.Any())
{
const int MaximumDisplayedRefs = 20;
if (branches.Count > MaximumDisplayedRefs)
{
branches[MaximumDisplayedRefs - 2] = "";
branches[MaximumDisplayedRefs - 1] = branches[branches.Count - 1];
branches.RemoveRange(MaximumDisplayedRefs, branches.Count - MaximumDisplayedRefs);
}

laneInfoText.Append("in ").Append(string.Join(", ", branches)).AppendLine();
}

if (laneInfoText.Length > 0)
{
laneInfoText.AppendLine();
}

laneInfoText.Append(node.Data.Subject);
}
}
}

return laneInfoText.ToString();
}

public string GetRowId(int rowIndex)
{
lock (_graphData)
Expand Down
10 changes: 7 additions & 3 deletions GitUI/UserControls/RevisionGridUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ public static Rectangle GetCellRectangle(DataGridViewCellPaintingEventArgs e)
return rect;
}

public static void DrawColumnText(Graphics gc, string text, Font font, Color color, Rectangle bounds)
/// <summary>
/// Draws the text and returns true if the text has been truncated.
/// </summary>
public static bool DrawColumnTextTruncated(Graphics gc, string text, Font font, Color color, Rectangle bounds)
{
TextRenderer.DrawText(gc, text, font, bounds, color,
TextFormatFlags.EndEllipsis | TextFormatFlags.NoPrefix);
int width = TextRenderer.MeasureText(gc, text, font, bounds.Size, TextFormatFlags.NoPrefix).Width;
TextRenderer.DrawText(gc, text, font, bounds, color, TextFormatFlags.NoPrefix | TextFormatFlags.EndEllipsis);
return width > bounds.Width;
}
}
}

0 comments on commit 74871a9

Please sign in to comment.