void ToggleNode(HashSet <int> map, NodeModel node) { // make sure a node cant be selected and ignored simultaneously if (map != IgnoredNodes && IgnoredNodes.Contains(node.ID)) { IgnoredNodes.Remove(node.ID); } if (map != FilteredNodes && FilteredNodes.Contains(node.ID)) { FilteredNodes.Remove(node.ID); } // toggle the setting of the node in the map if (map.Contains(node.ID)) { map.Remove(node.ID); } else { map.Add(node.ID); } DoRedraw = true; Renderer.ViewInvalidate(); }
private void DrawNode(NodeModel node, RectangleF area, RectangleF labelArea, int depth, bool drawChildren, bool showHit) { if (!node.Show) { return; } var xNode = node.XNode; // set background of node base color Color background = XColors.EmptyColor; // if selcted if (node.Hovered && ViewLayout == LayoutType.TreeMap) { if (depth > XColors.OverColors.Length - 1) { depth = XColors.OverColors.Length - 1; } background = XColors.OverColors[depth]; } else if (ViewLayout != LayoutType.TreeMap && !CenterMap.Contains(node.ID)) { background = XColors.OutsideColor; } // if no overlay, draw the border color as the entire node cause its very small bool noBorder = area.Width < 3.0f || area.Height < 3.0f; if (noBorder) { background = XColors.ObjColors[(int)node.ObjType]; } Color overlay = XColors.EmptyColor; if (showHit) { // check if function is an entry point or holding if (XRay.FlowTracking && xNode.StillInside > 0) { GLUtils.BlendColors((xNode.EntryPoint > 0) ? XColors.EntryColor : XColors.HoldingColor, ref overlay); } // not an else if, draw over holding or entry if (xNode.ExceptionHit > 0) { GLUtils.BlendColors(XColors.ExceptionColors[xNode.ExceptionHit], ref overlay); } else if (xNode.FunctionHit > 0) { if (node.ObjType == XObjType.Field) { if (xNode.LastFieldOp == FieldOp.Set) { GLUtils.BlendColors(XColors.FieldSetColors[xNode.FunctionHit], ref overlay); } else { GLUtils.BlendColors(XColors.FieldGetColors[xNode.FunctionHit], ref overlay); } } else { GLUtils.BlendColors(XColors.HitColors[xNode.FunctionHit], ref overlay); } } else if (xNode.ConstructedHit > 0) { GLUtils.BlendColors(XColors.ConstructedColors[xNode.ConstructedHit], ref overlay); } else if (xNode.DisposeHit > 0) { GLUtils.BlendColors(XColors.DisposedColors[xNode.DisposeHit], ref overlay); } } if (FocusedNodes.Count > 0 && node.ObjType == XObjType.Class) { bool dependent = DependentClasses.Contains(node.ID); bool independent = IndependentClasses.Contains(node.ID); if (dependent && independent) { GLUtils.BlendColors(XColors.InterdependentColor, ref overlay); } else if (dependent) { GLUtils.BlendColors(XColors.DependentColor, ref overlay); } else if (independent) { GLUtils.BlendColors(XColors.IndependentColor, ref overlay); } } if (node.SearchMatch && !SearchStrobe) { GLUtils.BlendColors(XColors.SearchMatchColor, ref overlay); } if (FilteredNodes.Contains(node.ID)) { GLUtils.BlendColors(XColors.FilteredColor, ref overlay); } else if (IgnoredNodes.Contains(node.ID)) { GLUtils.BlendColors(XColors.IgnoredColor, ref overlay); } // mix background with overlay if (overlay != XColors.EmptyColor) { GLUtils.BlendColors(overlay, ref background); } // use a circle for external/outside nodes in the call map bool outside = (ViewLayout == LayoutType.CallGraph && node.XNode.External); // if just a point, drawing a border messes up pixels if (noBorder && !DrawSubpixel) { Renderer.DrawNode(background, area, outside, node, depth); } else { Color pen = XColors.ObjColors[(int)node.ObjType]; if (FilteredNodes.Contains(node.ID)) { pen = XColors.FilteredColor; } else if (IgnoredNodes.Contains(node.ID)) { pen = XColors.IgnoredColor; } int penWidth = 1; if (FocusedNodes.Contains(node)) { penWidth = 2; } Renderer.DrawNode(background, area, outside, node, depth); Renderer.DrawNodeOutline(pen, penWidth, area, outside, node, depth); } // draw label //buffer.FillRectangle(SearchMatchBrush, node.DebugRect); if (ShowLabels && node.RoomForLabel) { Renderer.DrawTextBackground(XColors.LabelBgColor, labelArea.X, labelArea.Y, labelArea.Width, labelArea.Height); Renderer.DrawNodeLabel(node.Name, TextFont, XColors.ObjColors[(int)node.ObjType], labelArea, node, depth); // draw code inside node if (ShowCode && node.AreaF.Width > 50 && node.AreaF.Height > 50) { if (node.ObjType == XObjType.Method) { string code = node.XNode.GetMethodCode(); Renderer.DrawString(code, TextFont, XColors.CodeColor, node.AreaF.X + 5, node.AreaF.Y + labelArea.Height + 5, node.AreaF.Width - 10, node.AreaF.Height - 10 - labelArea.Height); } // draw field values inside node else if (node.ObjType == XObjType.Field) { var summary = ""; foreach (var value in node.GetFieldValues()) { summary += value + "\r\n"; } Renderer.DrawString(summary, TextFont, XColors.CodeColor, node.AreaF.X + 5, node.AreaF.Y + labelArea.Height + 5, node.AreaF.Width - 10, node.AreaF.Height - 10 - labelArea.Height); } } } if (MapMode == TreeMapMode.Dependencies && node.ObjType == XObjType.Class) { drawChildren = false; } if (drawChildren && ((area.Width > 1 && area.Height > 1) || DrawSubpixel)) { foreach (var sub in node.Nodes) { DrawNode(sub, depth + 1, drawChildren); } } // after drawing children, draw instance tracking on top of it all /*if (XRay.InstanceTracking && node.ObjType == XObjType.Class) * { * if (XRay.InstanceCount[node.ID] > 0) * { * string count = XRay.InstanceCount[node.ID].ToString(); * Rectangle x = new Rectangle(node.Area.Location, buffer.MeasureString(count, InstanceFont).ToSize()); * * if (node.Area.Contains(x)) * { * buffer.FillRectangle(NothingBrush, x); * buffer.DrawString(count, InstanceFont, InstanceBrush, node.Area.Location.X + 2, node.Area.Location.Y + 2); * } * } * }*/ }