1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Drawing;
5 using System.Data;
6 using System.Linq;
7 using System.Text;
8 using System.Threading.Tasks;
9 using System.Windows.Forms;
10 using Mesen.GUI.Controls;
11 using System.Collections.ObjectModel;
12 using Mesen.GUI.Config;
13 
14 namespace Mesen.GUI.Debugger.Controls
15 {
16 	public partial class ctrlBreakpoints : BaseControl
17 	{
18 		public event EventHandler BreakpointNavigation;
19 		private Font _markedColumnFont;
20 
ctrlBreakpoints()21 		public ctrlBreakpoints()
22 		{
23 			InitializeComponent();
24 		}
25 
OnLoad(EventArgs e)26 		protected override void OnLoad(EventArgs e)
27 		{
28 			base.OnLoad(e);
29 			if(!IsDesignMode) {
30 				_markedColumnFont = new Font(this.Font.FontFamily, 13f);
31 
32 				mnuShowLabels.Checked = ConfigManager.Config.DebugInfo.ShowBreakpointLabels;
33 				mnuShowLabels.CheckedChanged += mnuShowLabels_CheckedChanged;
34 
35 				BreakpointManager.BreakpointsChanged += BreakpointManager_OnBreakpointChanged;
36 				mnuRemoveBreakpoint.Enabled = false;
37 				mnuEditBreakpoint.Enabled = false;
38 				mnuGoToLocation.Enabled = false;
39 
40 				InitShortcuts();
41 			}
42 		}
43 
InitShortcuts()44 		private void InitShortcuts()
45 		{
46 			mnuAddBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.BreakpointList_Add));
47 			mnuEditBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.BreakpointList_Edit));
48 			mnuRemoveBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.BreakpointList_Delete));
49 			mnuGoToLocation.InitShortcut(this, nameof(DebuggerShortcutsConfig.BreakpointList_GoToLocation));
50 		}
51 
BreakpointManager_OnBreakpointChanged(object sender, EventArgs e)52 		private void BreakpointManager_OnBreakpointChanged(object sender, EventArgs e)
53 		{
54 			if(this.InvokeRequired) {
55 				this.BeginInvoke((Action)(() => RefreshList()));
56 			} else {
57 				RefreshList();
58 			}
59 		}
60 
RefreshListAddresses()61 		public void RefreshListAddresses()
62 		{
63 			lstBreakpoints.BeginUpdate();
64 			ReadOnlyCollection<Breakpoint> breakpoints = BreakpointManager.Breakpoints;
65 			for(int i = 0; i < breakpoints.Count; i++) {
66 				lstBreakpoints.Items[i].SubItems[3].Text = breakpoints[i].GetAddressString(mnuShowLabels.Checked);
67 			}
68 			lstBreakpoints.EndUpdate();
69 		}
70 
RefreshList()71 		public void RefreshList()
72 		{
73 			lstBreakpoints.ItemChecked -= new ItemCheckedEventHandler(lstBreakpoints_ItemChecked);
74 
75 			int topIndex = lstBreakpoints.TopItem != null ? lstBreakpoints.TopItem.Index : 0;
76 			lstBreakpoints.BeginUpdate();
77 			lstBreakpoints.Items.Clear();
78 			foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) {
79 				ListViewItem item = new ListViewItem();
80 				item.Tag = breakpoint;
81 				item.Checked = breakpoint.Enabled;
82 				item.UseItemStyleForSubItems = false;
83 				item.SubItems.Add(breakpoint.MarkEvent ? "☑" : "☐").Font = _markedColumnFont;
84 				item.SubItems.Add(breakpoint.ToReadableType());
85 				item.SubItems.Add(breakpoint.GetAddressString(mnuShowLabels.Checked));
86 				item.SubItems.Add(breakpoint.Condition);
87 				lstBreakpoints.Items.Add(item);
88 			}
89 			lstBreakpoints.EndUpdate();
90 			if(lstBreakpoints.Items.Count > 0) {
91 				lstBreakpoints.TopItem = lstBreakpoints.Items[lstBreakpoints.Items.Count > topIndex ? topIndex : lstBreakpoints.Items.Count - 1];
92 			}
93 
94 			lstBreakpoints.ItemChecked += new ItemCheckedEventHandler(lstBreakpoints_ItemChecked);
95 		}
96 
lstBreakpoints_ItemChecked(object sender, ItemCheckedEventArgs e)97 		private void lstBreakpoints_ItemChecked(object sender, ItemCheckedEventArgs e)
98 		{
99 			if(((Breakpoint)e.Item.Tag).Enabled != e.Item.Checked) {
100 				((Breakpoint)e.Item.Tag).SetEnabled(e.Item.Checked);
101 			}
102 		}
103 
lstBreakpoints_DoubleClick(object sender, EventArgs e)104 		private void lstBreakpoints_DoubleClick(object sender, EventArgs e)
105 		{
106 			if(lstBreakpoints.SelectedItems.Count > 0) {
107 				BreakpointManager.EditBreakpoint(((Breakpoint)lstBreakpoints.SelectedItems[0].Tag));
108 			}
109 		}
110 
mnuRemoveBreakpoint_Click(object sender, EventArgs e)111 		private void mnuRemoveBreakpoint_Click(object sender, EventArgs e)
112 		{
113 			foreach(ListViewItem item in lstBreakpoints.SelectedItems) {
114 				BreakpointManager.RemoveBreakpoint((Breakpoint)item.Tag);
115 			}
116 		}
117 
mnuAddBreakpoint_Click(object sender, EventArgs e)118 		private void mnuAddBreakpoint_Click(object sender, EventArgs e)
119 		{
120 			Breakpoint breakpoint = new Breakpoint();
121 			if(new frmBreakpoint(breakpoint).ShowDialog() == DialogResult.OK) {
122 				BreakpointManager.AddBreakpoint(breakpoint);
123 			}
124 		}
125 
mnuGoToLocation_Click(object sender, EventArgs e)126 		private void mnuGoToLocation_Click(object sender, EventArgs e)
127 		{
128 			if(BreakpointNavigation != null) {
129 				Breakpoint bp = lstBreakpoints.SelectedItems[0].Tag as Breakpoint;
130 				if(bp.IsCpuBreakpoint && bp.GetRelativeAddress() >= 0) {
131 					BreakpointNavigation(bp, null);
132 				}
133 			}
134 		}
135 
mnuEditBreakpoint_Click(object sender, EventArgs e)136 		private void mnuEditBreakpoint_Click(object sender, EventArgs e)
137 		{
138 			if(lstBreakpoints.SelectedItems.Count > 0) {
139 				BreakpointManager.EditBreakpoint(((Breakpoint)lstBreakpoints.SelectedItems[0].Tag));
140 			}
141 		}
142 
lstBreakpoints_SelectedIndexChanged(object sender, EventArgs e)143 		private void lstBreakpoints_SelectedIndexChanged(object sender, EventArgs e)
144 		{
145 			mnuRemoveBreakpoint.Enabled = (lstBreakpoints.SelectedItems.Count > 0);
146 			mnuEditBreakpoint.Enabled = (lstBreakpoints.SelectedItems.Count == 1);
147 			if(lstBreakpoints.SelectedItems.Count == 1) {
148 				Breakpoint bp = lstBreakpoints.SelectedItems[0].Tag as Breakpoint;
149 				mnuGoToLocation.Enabled = bp.IsCpuBreakpoint && bp.GetRelativeAddress() >= 0;
150 			}
151 
152 		}
153 
mnuShowLabels_CheckedChanged(object sender, EventArgs e)154 		private void mnuShowLabels_CheckedChanged(object sender, EventArgs e)
155 		{
156 			ConfigManager.Config.DebugInfo.ShowBreakpointLabels = mnuShowLabels.Checked;
157 			ConfigManager.ApplyChanges();
158 
159 			this.RefreshListAddresses();
160 		}
161 
lstBreakpoints_MouseDown(object sender, MouseEventArgs e)162 		private void lstBreakpoints_MouseDown(object sender, MouseEventArgs e)
163 		{
164 			ListViewHitTestInfo info = lstBreakpoints.HitTest(e.X, e.Y);
165 			if(info != null && info.Item != null) {
166 				int row = info.Item.Index;
167 				int col = info.Item.SubItems.IndexOf(info.SubItem);
168 
169 				if(col == 1 && row < lstBreakpoints.Items.Count) {
170 					this.BeginInvoke((Action)(() => {
171 						Breakpoint bp = lstBreakpoints.Items[row].Tag as Breakpoint;
172 						bp?.SetMarked(!bp.MarkEvent);
173 					}));
174 				}
175 			}
176 		}
177 	}
178 }
179