protected override void OnMouseClick(MouseEventArgs e) { base.OnMouseClick(e); var hit = false; foreach (var node in _nodeLocations) { if (OriginToClient(node.Value).Contains(e.Location)) { if (Selected != null) { Invalidate(Selected); } Selected = node.Key; Invalidate(Selected); OnNodeSelected(EventArgs.Empty); hit = true; break; } } if (!hit && Selected != null) { Invalidate(Selected); Selected = null; OnNodeSelected(EventArgs.Empty); } }
private void Invalidate(IExecutionPlanNode node) { // Inflate the node rectangle by 1 pixel to allow for antialiasing var rect = OriginToClient(_nodeLocations[node]); rect.Inflate(1, 1); Invalidate(rect); }
private void SortFetchXmlElements(IExecutionPlanNode node) { if (node is FetchXmlScan fetchXml) { SortFetchXmlElements(fetchXml.FetchXml.Items); } foreach (var source in node.GetSources()) { SortFetchXmlElements(source); } }
private IEnumerable <IExecutionPlanNode> GetAllNodes(IExecutionPlanNode node) { foreach (var source in node.GetSources()) { yield return(source); foreach (var subSource in GetAllNodes(source)) { yield return(subSource); } } }
private Size MeasureNode(IExecutionPlanNode node) { var label = GetLabel(node); using (var bitmap = new Bitmap(100, 100)) using (var g = Graphics.FromImage(bitmap)) { var labelSize = g.MeasureString(label, Font); const int iconLabelGap = 10; var width = Math.Max(_iconSize.Width, labelSize.Width); return(new Size((int)Math.Ceiling(width), _iconSize.Height + iconLabelGap + (int)Math.Ceiling(labelSize.Height))); } }
private void LayoutChildren(IExecutionPlanNode parent) { var i = 0; var sourceCount = parent.GetSources().Count(); var parentRect = _nodeLocations[parent]; var parentIconRect = GetIconRect(parentRect); var lineYSpacing = _iconSize.Height / (sourceCount + 1); foreach (var child in parent.GetSources()) { var size = MeasureNode(child); Point pt; if (i == 0) { // First source stays on the same level as the parent, one step to the right pt = new Point(parentRect.Right + _offset, parentRect.Top); } else { // Subsequent nodes move down pt = new Point(parentRect.Right + _offset, _maxBottom + _offset); _maxY = pt.Y; _maxBottom = _maxY + size.Height; } var fullRect = new Rectangle(pt, size); var iconRect = GetIconRect(fullRect); _nodeLocations[child] = fullRect; var rows = child is IDataExecutionPlanNode dataChild ? Executed ? dataChild.RowsOut : dataChild.EstimateRowsOut(DataSources.Values.Cast <Engine.DataSource>().ToDictionary(ds => ds.Name, StringComparer.OrdinalIgnoreCase), Options, null) : 1; var width = rows == 0 ? 1 : (int)Math.Log10(rows); _lines.Add(new Line { Source = child, Start = new Point(iconRect.Left, parentIconRect.Top == iconRect.Top ? (parentIconRect.Top + (i + 1) * lineYSpacing) : (iconRect.Top + iconRect.Height / 2)), End = new Point(parentIconRect.Right, parentIconRect.Top + (i + 1) * lineYSpacing), Width = width }); LayoutChildren(child); i++; } }
private string GetLabel(IExecutionPlanNode node) { var text = node.ToString(); if (Executed) { var nodeTime = node.Duration.TotalMilliseconds - node.GetSources().Sum(source => source.Duration.TotalMilliseconds); var totalTime = Plan.Duration.TotalMilliseconds; var cost = Math.Min(1, Math.Max(0, nodeTime / totalTime)); if (Double.IsNaN(cost)) { cost = 1; } text += "\r\nCost: " + cost.ToString("P0"); } return(text); }