DependencyGraphViewer: Feature add same window navigation for NodeForm (#84542)
authorMitch Capper (they, them) <mitch.capper@gmail.com>
Mon, 24 Jul 2023 18:18:35 +0000 (11:18 -0700)
committerGitHub <noreply@github.com>
Mon, 24 Jul 2023 18:18:35 +0000 (11:18 -0700)
* DependencyGraphViewer: Feature add same window navigation for NodeForm

Add ability to reuse current window rather than open new, added history
(forward/back) and arrow key accelerators as well.

* Fix code formatting

---------

Co-authored-by: David Wrighton <davidwr@microsoft.com>
src/coreclr/tools/aot/DependencyGraphViewer/NodeForm.Designer.cs
src/coreclr/tools/aot/DependencyGraphViewer/NodeForm.cs

index e01fe39..de1ee51 100644 (file)
@@ -33,6 +33,9 @@ namespace DependencyLogViewer
         {
             this.nodeTitle = new System.Windows.Forms.Label();
             this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+            this.chkSameWindowNav = new System.Windows.Forms.CheckBox();
+            this.btnBack = new System.Windows.Forms.Button();
+            this.btnForward = new System.Windows.Forms.Button();
             this.dependentsListBox = new System.Windows.Forms.ListBox();
             this.exploreDependent = new System.Windows.Forms.Button();
             this.dependeesListBox = new System.Windows.Forms.ListBox();
@@ -45,21 +48,22 @@ namespace DependencyLogViewer
             // 
             // nodeTitle
             // 
-            this.nodeTitle.AutoSize = true;
             this.nodeTitle.BackColor = System.Drawing.SystemColors.Info;
             this.nodeTitle.Dock = System.Windows.Forms.DockStyle.Top;
             this.nodeTitle.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point);
             this.nodeTitle.Location = new System.Drawing.Point(0, 0);
             this.nodeTitle.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
             this.nodeTitle.Name = "nodeTitle";
-            this.nodeTitle.Size = new System.Drawing.Size(116, 30);
+            this.nodeTitle.Size = new System.Drawing.Size(1220, 75);
             this.nodeTitle.TabIndex = 0;
             this.nodeTitle.Text = "Node Title";
+            this.nodeTitle.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
+            this.nodeTitle.AutoEllipsis = true;
             // 
             // splitContainer1
             // 
             this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.splitContainer1.Location = new System.Drawing.Point(0, 30);
+            this.splitContainer1.Location = new System.Drawing.Point(0, 75);
             this.splitContainer1.Margin = new System.Windows.Forms.Padding(4);
             this.splitContainer1.Name = "splitContainer1";
             this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
@@ -78,6 +82,39 @@ namespace DependencyLogViewer
             this.splitContainer1.SplitterWidth = 6;
             this.splitContainer1.TabIndex = 1;
             // 
+            // chkSameWindowNav
+            // 
+            this.chkSameWindowNav.AutoSize = true;
+            this.chkSameWindowNav.Location = new System.Drawing.Point(890, 0);
+            this.chkSameWindowNav.Name = "chkSameWindowNav";
+            this.chkSameWindowNav.Size = new System.Drawing.Size(322, 36);
+            this.chkSameWindowNav.TabIndex = 5;
+            this.chkSameWindowNav.Text = "Same Window Nav";
+            this.chkSameWindowNav.UseVisualStyleBackColor = true;
+            this.chkSameWindowNav.CheckedChanged += ChkSameWindowNav_CheckedChanged;
+            // 
+            // btnBack
+            // 
+            this.btnBack.Location = new System.Drawing.Point(607, 0);
+            this.btnBack.Margin = new System.Windows.Forms.Padding(4);
+            this.btnBack.Name = "btnBack";
+            this.btnBack.Size = new System.Drawing.Size(124, 43);
+            this.btnBack.TabIndex = 3;
+            this.btnBack.Text = "Back";
+            this.btnBack.UseVisualStyleBackColor = true;
+            this.btnBack.Click += btnBack_Click;
+            // 
+            // btnForward
+            // 
+            this.btnForward.Location = new System.Drawing.Point(750, 0);
+            this.btnForward.Margin = new System.Windows.Forms.Padding(4);
+            this.btnForward.Name = "btnForward";
+            this.btnForward.Size = new System.Drawing.Size(124, 43);
+            this.btnForward.TabIndex = 4;
+            this.btnForward.Text = "Forward";
+            this.btnForward.UseVisualStyleBackColor = true;
+            this.btnForward.Click += btnForward_Click;
+            // 
             // dependentsListBox
             // 
             this.dependentsListBox.Dock = System.Windows.Forms.DockStyle.Fill;
@@ -133,6 +170,9 @@ namespace DependencyLogViewer
             this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 30F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
             this.ClientSize = new System.Drawing.Size(1126, 836);
+            Controls.Add(chkSameWindowNav);
+            Controls.Add(btnBack);
+            Controls.Add(btnForward);
             this.Controls.Add(this.splitContainer1);
             this.Controls.Add(this.nodeTitle);
             this.Margin = new System.Windows.Forms.Padding(4);
@@ -148,6 +188,7 @@ namespace DependencyLogViewer
 
         }
 
+
         #endregion
 
         private System.Windows.Forms.Label nodeTitle;
@@ -156,5 +197,8 @@ namespace DependencyLogViewer
         private System.Windows.Forms.ListBox dependeesListBox;
         private System.Windows.Forms.Button exploreDependent;
         private System.Windows.Forms.ListBox dependentsListBox;
+        private System.Windows.Forms.Button btnBack;
+        private System.Windows.Forms.CheckBox chkSameWindowNav;
+        private System.Windows.Forms.Button btnForward;
     }
 }
index 25c5a26..14793b7 100644 (file)
@@ -10,17 +10,58 @@ namespace DependencyLogViewer
     public partial class NodeForm : Form
     {
         private readonly Graph _graph;
-        private readonly Node _node;
+        private Node _node;
 
         public NodeForm(Graph g, Node n)
         {
             _graph = g;
-            _node = n;
-
             InitializeComponent();
+            SetNode(n);
+            btnBack.Visible = btnForward.Visible = chkSameWindowNav.Checked;
+            var fixControls = new Control[] {btnBack, btnForward, chkSameWindowNav, exploreDependent, dependentsListBox, exploreDependee, dependeesListBox, this, this.splitContainer1 };
+            foreach (var cntrl in fixControls)
+            {
+                cntrl.PreviewKeyDown += Cntrl_PreviewKeyDown;
+                cntrl.KeyDown += Cntrl_KeyDown;
+            }
+        }
+
+
+        private void Cntrl_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) {
+            if (!chkSameWindowNav.Checked)
+                return;
+            if (e.KeyCode == Keys.Left || e.KeyCode == Keys.Right)
+                e.IsInputKey = true;
+        }
+
+        private void Cntrl_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (!chkSameWindowNav.Checked)
+                return;
+            if (e.KeyCode == Keys.Left)
+            {
+                if (btnBack.Enabled)
+                    btnBack.PerformClick();
+            }
+            else if (e.KeyCode == Keys.Right)
+            {
+                if (btnForward.Enabled)
+                    btnForward.PerformClick();
+            }
+            else
+                return;
+            e.SuppressKeyPress = true;
+            e.Handled = true;
+        }
+
+        public void SetNode(Node n)
+        {
+
+            _node = n;
 
             this.Text = $"Graph Pid: {_graph.PID}, ID: {_graph.ID}, Node: {_node.ToString}";
-            this.nodeTitle.Text = $"Current Node: {_node}";
+            var nodeStr = _node.ToString().Replace(", ", "\n");
+            this.nodeTitle.Text = $"Current Node: {nodeStr}";
 
             lock (GraphCollection.Singleton)
             {
@@ -39,6 +80,9 @@ namespace DependencyLogViewer
                 this.dependentsListBox.DataSource = sourceNodes;
                 this.dependeesListBox.DataSource = targetNodes;
             }
+            if (CurSpotInHistory == -1 && chkSameWindowNav.Checked)//if we are in history we dont modify history
+                AddSelfToHistory();
+            SetNavButtonStates();
         }
 
         private static void ExploreSelectedItem(Graph graph, ListBox listbox)
@@ -54,14 +98,71 @@ namespace DependencyLogViewer
 
         private void exploreDependee_Click(object sender, EventArgs e)
         {
-            ExploreSelectedItem(_graph, dependeesListBox);
+            if (chkSameWindowNav.Checked != true)
+            {
+                ExploreSelectedItem(_graph, dependeesListBox);
+                return;
+            }
+            ClearHistoryIfIn();
+            var selected = (BoxDisplay)dependeesListBox.SelectedItem;
+            SetNode(selected.node);
         }
 
         private void exploreDependent_Click(object sender, EventArgs e)
         {
-            ExploreSelectedItem(_graph, dependentsListBox);
+            if (chkSameWindowNav.Checked != true)
+            {
+                ExploreSelectedItem(_graph, dependentsListBox);
+                return;
+            }
+            ClearHistoryIfIn();
+            var selected = (BoxDisplay)dependentsListBox.SelectedItem;
+            SetNode(selected.node);
+        }
+        private void AddSelfToHistory()
+        {
+            History.Add(_node);
+        }
+        private void ClearHistoryIfIn()
+        {
+
+            if (CurSpotInHistory != -1)
+            {
+                var removeAfter = CurSpotInHistory + 1;
+                if (removeAfter != History.Count)
+                    History.RemoveRange(removeAfter, History.Count - removeAfter);
+                CurSpotInHistory = -1;
+            }
         }
+        public int CurSpotInHistory = -1;
+        private List<Node> History = new();
 
+        private void btnBack_Click(object sender, EventArgs e)
+        {
+            if (CurSpotInHistory == -1)
+                CurSpotInHistory = History.Count - 2;
+            else if (CurSpotInHistory == 0) // should not get here
+                return;
+            else
+                CurSpotInHistory--;
+            SetNode(History[CurSpotInHistory]);
+        }
+        private void btnForward_Click(object sender, EventArgs e)
+        {
+            if (CurSpotInHistory == -1)// should not get here
+                return;
+            else if (CurSpotInHistory == History.Count - 1) // should not get here
+                return;
+            else
+                CurSpotInHistory++;
+            SetNode(History[CurSpotInHistory]);
+        }
+        private void SetNavButtonStates()
+        {
+            btnBack.Enabled = CurSpotInHistory != 0 && History.Count > 1;
+            btnForward.Enabled = CurSpotInHistory != -1 && CurSpotInHistory != History.Count - 1;
+        }
+        private void ChkSameWindowNav_CheckedChanged(object sender, System.EventArgs e) => btnBack.Visible = btnForward.Visible = chkSameWindowNav.Checked;
         private void infoButton_LinkClicked(object sender, EventArgs e)
         {
             string dMessage = "Dependent nodes depend on the current node. The current node depends on the dependees.";