Skip to content

Commit 9c08095

Browse files
authored
Merge pull request #3 from Gibitop/master
Добавил вкладку отладки
2 parents 0132340 + 14d4e38 commit 9c08095

File tree

2 files changed

+330
-1
lines changed

2 files changed

+330
-1
lines changed

bcomp-ng-ui/src/main/java/ru/ifmo/cs/bcomp/ui/GUI.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ public void init() {
4545
final ActivateblePanel[] panels = {
4646
new BasicView(this, isHex),
4747
new AssemblerView(this),
48-
new TraceView(this)
48+
new TraceView(this),
49+
new DebugView(this)
4950
};
5051

5152
tabs = new JTabbedPane(){
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
package ru.ifmo.cs.bcomp.ui.components;
2+
3+
import ru.ifmo.cs.bcomp.CPU;
4+
import ru.ifmo.cs.bcomp.Reg;
5+
import ru.ifmo.cs.bcomp.ui.GUI;
6+
import ru.ifmo.cs.components.Memory;
7+
8+
import javax.swing.*;
9+
import javax.swing.event.DocumentEvent;
10+
import javax.swing.event.DocumentListener;
11+
import java.awt.*;
12+
import java.awt.event.*;
13+
import java.lang.reflect.Field;
14+
import java.util.ArrayList;
15+
16+
public class DebugView extends BCompPanel implements ActionListener {
17+
private final Memory memory;
18+
private final CPU cpu;
19+
private Field memoryArray;
20+
21+
private Component dumpComponent;
22+
private Component watchesComponent;
23+
private Component breakpointsComponent; // TODO: add breakpoints
24+
25+
private long[] dump = new long[0x800];
26+
private final ArrayList<Integer> watches;
27+
private int selectedWatch = -1;
28+
private int watchAddress = -1;
29+
30+
31+
private final Font font = new Font("Roboto", Font.PLAIN, 24);
32+
33+
public DebugView(GUI gui) {
34+
super(gui.getComponentManager(), null, null);
35+
this.setFont(font);
36+
this.cpu = gui.getCPU();
37+
this.memory = cpu.getMemory();
38+
this.watches = new ArrayList<>(0);
39+
this.addComponentListener(new ComponentListener() {
40+
@Override
41+
public void componentResized(ComponentEvent componentEvent) {
42+
DebugView.this.dumpComponent = DebugView.this.renderDumpComponent();
43+
DebugView.this.watchesComponent = DebugView.this.renderWatchesComponent();
44+
// TODO: add breakpoints
45+
// DebugView.this.breakpointsComponent = DebugView.this.renderBreakpointsComponent();
46+
DebugView.this.removeAll();
47+
DebugView.this.add(DebugView.this.renderMainComponent());
48+
}
49+
50+
@Override
51+
public void componentMoved(ComponentEvent componentEvent) {
52+
53+
}
54+
55+
@Override
56+
public void componentShown(ComponentEvent componentEvent) {
57+
58+
}
59+
60+
@Override
61+
public void componentHidden(ComponentEvent componentEvent) {
62+
63+
}
64+
});
65+
66+
try {
67+
this.memoryArray = Memory.class.getDeclaredField("memory");
68+
memoryArray.setAccessible(true);
69+
70+
this.dumpMemory();
71+
this.dumpComponent = renderDumpComponent();
72+
this.watchesComponent = renderWatchesComponent();
73+
// TODO: add breakpoints
74+
// this.breakpointsComponent = renderBreakpointsComponent();
75+
76+
setLayout(new BorderLayout());
77+
add(renderMainComponent());
78+
} catch (NoSuchFieldException e) {
79+
e.printStackTrace();
80+
}
81+
}
82+
83+
private Component renderMainComponent() {
84+
JPanel main = new JPanel();
85+
main.setLayout(new GridBagLayout());
86+
87+
GridBagConstraints c = new GridBagConstraints();
88+
c.fill = GridBagConstraints.BOTH;
89+
c.gridx = 0;
90+
c.weighty = 1;
91+
c.weightx = 0.25;
92+
93+
// Mounting watches component
94+
c.gridy = 0;
95+
main.add(watchesComponent, c);
96+
97+
// Mounting breakpoints panel
98+
// TODO: add breakpoints
99+
// c.weighty = 0.5;
100+
// c.gridy = 1;
101+
// main.add(breakpointsComponent, c);
102+
103+
// Mounting memory dump panel
104+
c.gridx = 1;
105+
c.gridy = 0;
106+
c.weightx = 1;
107+
c.gridheight = 2;
108+
main.add(dumpComponent, c);
109+
110+
return main;
111+
}
112+
113+
private Component renderDumpComponent() {
114+
JPanel dump = new JPanel();
115+
116+
dump.setLayout(new BorderLayout());
117+
118+
JLabel panelLabel = new JLabel("Memory dump", SwingConstants.CENTER);
119+
panelLabel.setFont(this.font.deriveFont(Font.BOLD));
120+
dump.add(panelLabel, BorderLayout.PAGE_START);
121+
122+
String[] humanReadableDump = new String[this.dump.length];
123+
for (int address = 0x000; address < this.dump.length; address++) {
124+
humanReadableDump[address] = String.format(
125+
"%03X: %04X ", address, this.dump[address]);
126+
}
127+
128+
JList<String> cells = new JList<>(humanReadableDump);
129+
cells.setFont(this.font);
130+
cells.setLayoutOrientation(JList.VERTICAL_WRAP);
131+
cells.setVisibleRowCount(this.getHeight() / (int) (getFontMetrics(this.font).getHeight() * 1.2));
132+
133+
dump.add(new JScrollPane(cells));
134+
135+
return dump;
136+
}
137+
138+
private Component renderWatchesComponent() {
139+
JPanel watches = new JPanel();
140+
watches.setLayout(new GridBagLayout());
141+
GridBagConstraints c = new GridBagConstraints();
142+
c.gridx = 0;
143+
c.weightx = 1;
144+
145+
146+
JLabel panelLabel = new JLabel("Watches", SwingConstants.CENTER);
147+
panelLabel.setFont(this.font.deriveFont(Font.BOLD));
148+
c.fill = GridBagConstraints.BOTH;
149+
c.gridy = 0;
150+
watches.add(panelLabel, c);
151+
152+
JPanel buttons = new JPanel();
153+
buttons.setLayout(new GridLayout());
154+
155+
JButton addWatch = new JButton("+");
156+
addWatch.setEnabled(false);
157+
addWatch.setFocusable(false); // Magic: this line makes the button work every time
158+
addWatch.addActionListener(actionEvent -> {
159+
DebugView.this.watches.add(DebugView.this.watchAddress);
160+
DebugView.this.watchesComponent = DebugView.this.renderWatchesComponent();
161+
DebugView.this.removeAll();
162+
DebugView.this.add(DebugView.this.renderMainComponent());
163+
});
164+
165+
JButton removeWatch = new JButton("-");
166+
removeWatch.setEnabled(false);
167+
removeWatch.addActionListener(actionEvent -> {
168+
DebugView.this.watches.remove(DebugView.this.selectedWatch);
169+
DebugView.this.watchesComponent = DebugView.this.renderWatchesComponent();
170+
DebugView.this.removeAll();
171+
DebugView.this.add(DebugView.this.renderMainComponent());
172+
});
173+
174+
String addressFieldPlaceholder = "Address";
175+
JFormattedTextField addressField = new JFormattedTextField(addressFieldPlaceholder);
176+
addressField.getDocument().addDocumentListener(new DocumentListener() {
177+
void handleNewValue() {
178+
try {
179+
DebugView.this.watchAddress = Integer.parseInt(addressField.getText(), 16);
180+
addWatch.setEnabled(DebugView.this.watchAddress >= 0 && DebugView.this.watchAddress < DebugView.this.dump.length);
181+
} catch (NumberFormatException e) {
182+
addWatch.setEnabled(false);
183+
}
184+
}
185+
186+
@Override
187+
public void insertUpdate(DocumentEvent documentEvent) {
188+
handleNewValue();
189+
}
190+
191+
@Override
192+
public void removeUpdate(DocumentEvent documentEvent) {
193+
handleNewValue();
194+
}
195+
196+
@Override
197+
public void changedUpdate(DocumentEvent documentEvent) {
198+
handleNewValue();
199+
}
200+
});
201+
addressField.setForeground(Color.GRAY);
202+
addressField.addFocusListener(new FocusListener() {
203+
@Override
204+
public void focusGained(FocusEvent e) {
205+
if (addressField.getText().equals(addressFieldPlaceholder)) {
206+
addressField.setText("");
207+
addressField.setForeground(Color.BLACK);
208+
}
209+
}
210+
211+
@Override
212+
public void focusLost(FocusEvent e) {
213+
if (addressField.getText().isEmpty()) {
214+
addressField.setForeground(Color.GRAY);
215+
addressField.setText(addressFieldPlaceholder);
216+
}
217+
}
218+
});
219+
220+
221+
buttons.add(addressField);
222+
buttons.add(addWatch);
223+
buttons.add(removeWatch);
224+
225+
c.gridy = 1;
226+
watches.add(buttons, c);
227+
228+
ArrayList<String> humanReadableWatches = new ArrayList<>();
229+
humanReadableWatches.add(String.format("IP : %03X", cpu.getRegister(Reg.IP).getValue()));
230+
humanReadableWatches.add(String.format("SP : %03X", cpu.getRegister(Reg.SP).getValue()));
231+
humanReadableWatches.add(String.format("AR : %03X", cpu.getRegister(Reg.AR).getValue()));
232+
humanReadableWatches.add(String.format("DR : %04X", cpu.getRegister(Reg.DR).getValue()));
233+
humanReadableWatches.add(String.format("CR : %04X", cpu.getRegister(Reg.CR).getValue()));
234+
humanReadableWatches.add(String.format("AC : %04X", cpu.getRegister(Reg.AC).getValue()));
235+
humanReadableWatches.add(String.format("BR : %04X", cpu.getRegister(Reg.BR).getValue()));
236+
237+
final int staticWatchCount = humanReadableWatches.size();
238+
239+
for (int watch : this.watches) {
240+
humanReadableWatches.add(String.format("%03X: %04X", watch, this.dump[watch]));
241+
}
242+
243+
JList<String> watchesList = new JList<>(humanReadableWatches.toArray(new String[]{}));
244+
watchesList.setFont(this.font);
245+
watchesList.addMouseListener(new MouseListener() {
246+
@Override
247+
public void mouseClicked(MouseEvent mouseEvent) {
248+
DebugView.this.selectedWatch = watchesList.getSelectedIndex() - staticWatchCount;
249+
removeWatch.setEnabled(DebugView.this.selectedWatch >= 0);
250+
}
251+
252+
@Override
253+
public void mousePressed(MouseEvent mouseEvent) {
254+
255+
}
256+
257+
@Override
258+
public void mouseReleased(MouseEvent mouseEvent) {
259+
260+
}
261+
262+
@Override
263+
public void mouseEntered(MouseEvent mouseEvent) {
264+
265+
}
266+
267+
@Override
268+
public void mouseExited(MouseEvent mouseEvent) {
269+
270+
}
271+
});
272+
c.weighty = 1;
273+
c.gridy = 2;
274+
watches.add(new JScrollPane(watchesList), c);
275+
276+
return watches;
277+
}
278+
279+
// TODO: add breakpoints
280+
private Component renderBreakpointsComponent() {
281+
JPanel breakpoints = new JPanel();
282+
283+
JLabel panelLabel = new JLabel("Breakpoints", SwingConstants.CENTER);
284+
panelLabel.setFont(this.font.deriveFont(Font.BOLD));
285+
breakpoints.add(panelLabel, BorderLayout.PAGE_START);
286+
287+
return breakpoints;
288+
}
289+
290+
// Full memory dump can take a long time
291+
private void dumpMemory() {
292+
try {
293+
this.dump = (long[]) memoryArray.get(this.memory);
294+
} catch (IllegalAccessException e) {
295+
e.printStackTrace();
296+
}
297+
}
298+
299+
300+
@Override
301+
public void panelActivate() {
302+
dumpMemory();
303+
this.dumpComponent = renderDumpComponent();
304+
this.watchesComponent = renderWatchesComponent();
305+
this.removeAll();
306+
this.add(renderMainComponent());
307+
}
308+
309+
@Override
310+
public void panelDeactivate() {
311+
312+
}
313+
314+
@Override
315+
public void actionPerformed(ActionEvent actionEvent) {
316+
317+
}
318+
319+
@Override
320+
public String getPanelName() {
321+
return "Отладка";
322+
}
323+
324+
@Override
325+
public void redrawArrows() {
326+
327+
}
328+
}

0 commit comments

Comments
 (0)