2020-08-06 21:37:05 +00:00
|
|
|
package app;
|
|
|
|
|
|
|
|
// Java imports
|
|
|
|
import java.awt.*;
|
|
|
|
import java.awt.event.*;
|
|
|
|
import java.util.*;
|
|
|
|
import javax.swing.*;
|
|
|
|
|
|
|
|
// Project imports
|
|
|
|
import util.*;
|
|
|
|
import vue.*;
|
|
|
|
|
|
|
|
// Register list item
|
|
|
|
class Register {
|
|
|
|
|
|
|
|
// Instance fields
|
2020-08-08 23:40:22 +00:00
|
|
|
private boolean expandable; // The expansion area can be shown
|
|
|
|
private boolean expanded; // The expanded area is being shown
|
|
|
|
private int index; // Register index
|
|
|
|
private int mode; // Display mode for program registers
|
|
|
|
private String name; // Register name
|
|
|
|
private RegisterList parent; // Containing register list
|
|
|
|
private int type; // Expansion controls type
|
|
|
|
private int value; // Current register value
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
// UI components
|
2020-12-25 23:59:08 +00:00
|
|
|
UPanel expansion; // Expansion container
|
2020-08-08 23:40:22 +00:00
|
|
|
JLabel btnExpand; // Expand button
|
2020-12-25 23:59:08 +00:00
|
|
|
UPanel indent; // Expansion area indentation
|
2020-08-08 23:40:22 +00:00
|
|
|
JLabel lblName; // Register name
|
|
|
|
JTextField txtValue; // Register value
|
|
|
|
ArrayList<JComponent> controls; // Expansion controls
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Constants //
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Modes
|
|
|
|
static final int FLOAT = 3;
|
|
|
|
static final int HEX = 0;
|
|
|
|
static final int SIGNED = 1;
|
|
|
|
static final int UNSIGNED = 2;
|
|
|
|
|
|
|
|
// Types
|
2020-08-08 23:40:22 +00:00
|
|
|
static final int PLAIN = -2;
|
|
|
|
static final int PROGRAM = -3;
|
2020-08-06 21:37:05 +00:00
|
|
|
|
2020-12-23 18:26:02 +00:00
|
|
|
// Expand button labels
|
|
|
|
static final String COLLAPSE = "-";
|
|
|
|
static final String EXPAND = "+";
|
|
|
|
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Constructors //
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Default constructor
|
2020-08-08 23:40:22 +00:00
|
|
|
Register(RegisterList parent, String name, int index, int type) {
|
|
|
|
parent.add(index, this);
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
// Configure instance fields
|
|
|
|
controls = new ArrayList<JComponent>();
|
2020-08-08 23:40:22 +00:00
|
|
|
expandable = type != PLAIN && index != 0;
|
2020-08-06 21:37:05 +00:00
|
|
|
this.index = index;
|
2020-08-08 23:40:22 +00:00
|
|
|
mode = HEX;
|
|
|
|
this.name = name;
|
2020-08-06 21:37:05 +00:00
|
|
|
this.parent = parent;
|
|
|
|
this.type = type;
|
|
|
|
|
|
|
|
// Click handler for expand and name controls
|
2020-08-07 19:21:03 +00:00
|
|
|
MouseListener expand = !expandable ? null : Util.onMouse(e->{
|
2020-08-08 23:40:22 +00:00
|
|
|
if (e.getButton() == 1) setExpanded(!expanded); }, null);
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
// Expand button
|
2020-12-23 18:26:02 +00:00
|
|
|
btnExpand = new JLabel(expandable ? EXPAND : "");
|
2020-08-06 21:37:05 +00:00
|
|
|
btnExpand.setHorizontalAlignment(SwingConstants.CENTER);
|
2020-08-07 19:21:03 +00:00
|
|
|
if (expandable)
|
2020-08-06 21:37:05 +00:00
|
|
|
btnExpand.addMouseListener(expand);
|
|
|
|
var gbc = new GridBagConstraints();
|
|
|
|
gbc.anchor = GridBagConstraints.NORTH;
|
|
|
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
2020-08-08 23:40:22 +00:00
|
|
|
parent.add(gbc, btnExpand);
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
// Name label
|
2020-08-08 23:40:22 +00:00
|
|
|
lblName = new JLabel(" ");
|
2020-08-07 19:21:03 +00:00
|
|
|
if (expandable)
|
2020-08-06 21:37:05 +00:00
|
|
|
lblName.addMouseListener(expand);
|
|
|
|
gbc = new GridBagConstraints();
|
|
|
|
gbc.anchor = GridBagConstraints.NORTH;
|
|
|
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
|
|
|
gbc.weightx = 1;
|
2020-08-08 23:40:22 +00:00
|
|
|
parent.add(gbc, lblName);
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
// Value text box
|
|
|
|
txtValue = new JTextField();
|
|
|
|
txtValue.setBorder(null);
|
|
|
|
txtValue.setOpaque(false);
|
|
|
|
txtValue.setText("00000000");
|
|
|
|
gbc = new GridBagConstraints();
|
|
|
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
2020-08-07 19:21:03 +00:00
|
|
|
gbc.insets = new Insets(0, 4, 0, 0);
|
2020-08-08 23:40:22 +00:00
|
|
|
parent.add(gbc, txtValue);
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
// Value changed
|
2020-12-22 02:42:28 +00:00
|
|
|
txtValue.addActionListener(e->parent.requestFocus());
|
|
|
|
txtValue.addFocusListener(Util.onFocus(null, e->{
|
2020-08-06 21:37:05 +00:00
|
|
|
String text = txtValue.getText();
|
|
|
|
int val = value;
|
|
|
|
try { switch (mode) {
|
|
|
|
case HEX : val = (int) Long.parseLong(text, 16); break;
|
|
|
|
case SIGNED : // Fallthrough
|
|
|
|
case UNSIGNED: val = (int) Long.parseLong(text, 10); break;
|
|
|
|
case FLOAT : val =
|
|
|
|
Float.floatToIntBits(Float.parseFloat(text) ); break;
|
|
|
|
}} catch (Exception x) { }
|
|
|
|
setValue(val);
|
2020-12-22 02:42:28 +00:00
|
|
|
}));
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
// Expansion controls
|
|
|
|
switch (type) {
|
|
|
|
case PROGRAM : initProgram(); break;
|
2020-10-03 19:20:56 +00:00
|
|
|
case Vue.CHCW: initCHCW (); break;
|
|
|
|
case Vue.ECR : initECR (); break;
|
|
|
|
case Vue.PC : initPC (); break;
|
|
|
|
case Vue.PIR : initPIR (); break;
|
|
|
|
case Vue.PSW : initPSW (); break;
|
|
|
|
case Vue.TKCW: initTKCW (); break;
|
2020-12-23 18:26:02 +00:00
|
|
|
default: configure(); return;
|
2020-08-06 21:37:05 +00:00
|
|
|
}
|
|
|
|
|
2020-08-08 23:40:22 +00:00
|
|
|
// Expansion indentation
|
2020-10-03 19:20:56 +00:00
|
|
|
if (index != Vue.PC) {
|
2020-12-25 23:59:08 +00:00
|
|
|
indent = new UPanel();
|
2020-08-08 23:40:22 +00:00
|
|
|
indent.setOpaque(false);
|
|
|
|
indent.setPreferredSize(new Dimension(0, 0));
|
|
|
|
indent.setVisible(false);
|
2020-08-07 19:21:03 +00:00
|
|
|
gbc = new GridBagConstraints();
|
2020-08-08 23:40:22 +00:00
|
|
|
parent.add(gbc, indent);
|
2020-08-07 19:21:03 +00:00
|
|
|
}
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
// Expansion area
|
|
|
|
expansion.setOpaque(false);
|
|
|
|
expansion.setVisible(false);
|
|
|
|
gbc = new GridBagConstraints();
|
|
|
|
gbc.anchor = GridBagConstraints.WEST;
|
2020-10-03 19:20:56 +00:00
|
|
|
if (index == Vue.PC)
|
2020-08-07 19:21:03 +00:00
|
|
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
2020-08-06 21:37:05 +00:00
|
|
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
|
|
|
gbc.insets = new Insets(0, 4, 0, 0);
|
2020-08-07 19:21:03 +00:00
|
|
|
gbc.weightx = 1;
|
2020-08-08 23:40:22 +00:00
|
|
|
parent.add(gbc, expansion);
|
|
|
|
|
|
|
|
// Handling for PSW
|
2020-10-03 19:20:56 +00:00
|
|
|
if (index == Vue.PSW && type == Vue.PSW)
|
2020-08-08 23:40:22 +00:00
|
|
|
setExpanded(true);
|
2020-12-23 18:26:02 +00:00
|
|
|
|
|
|
|
// Apply application settings
|
|
|
|
configure();
|
2020-08-06 21:37:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Expansion Constructors //
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Expansion controls for CHCW
|
|
|
|
private void initCHCW() {
|
2020-12-25 23:59:08 +00:00
|
|
|
expansion = new UPanel(new GridBagLayout());
|
2020-08-08 23:40:22 +00:00
|
|
|
addCheckBox("ICE", 1, false, true);
|
2020-08-06 21:37:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Expansion controls for ECR
|
|
|
|
private void initECR() {
|
2020-12-25 23:59:08 +00:00
|
|
|
expansion = new UPanel(new GridBagLayout());
|
2020-08-08 23:40:22 +00:00
|
|
|
addTextBox("EICC", 0, 16, false, true);
|
|
|
|
addTextBox("FECC", 16, 16, false, true);
|
2020-08-06 21:37:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Expansion controls for program registers
|
|
|
|
private void initProgram() {
|
2020-12-25 23:59:08 +00:00
|
|
|
expansion = new UPanel(new GridBagLayout());
|
2020-08-06 21:37:05 +00:00
|
|
|
var group = new ButtonGroup();
|
|
|
|
group.add(addRadioButton("cpu.hex" , HEX ));
|
|
|
|
group.add(addRadioButton("cpu.signed" , SIGNED ));
|
|
|
|
group.add(addRadioButton("cpu.unsigned", UNSIGNED));
|
|
|
|
group.add(addRadioButton("cpu.float" , FLOAT ));
|
|
|
|
}
|
|
|
|
|
2020-08-07 19:21:03 +00:00
|
|
|
// Expansion controls for PC
|
|
|
|
private void initPC() {
|
2020-12-25 23:59:08 +00:00
|
|
|
expansion = new UPanel(new GridBagLayout());
|
2020-08-07 19:21:03 +00:00
|
|
|
|
|
|
|
// Configure controls
|
|
|
|
for (int x = 0; x < 2; x++) {
|
|
|
|
|
|
|
|
// Indentation
|
2020-12-25 23:59:08 +00:00
|
|
|
indent = new UPanel();
|
2020-08-08 23:40:22 +00:00
|
|
|
indent.setOpaque(false);
|
|
|
|
indent.setPreferredSize(new Dimension(0, 0));
|
2020-08-07 19:21:03 +00:00
|
|
|
var gbc = new GridBagConstraints();
|
|
|
|
gbc.weightx = 1;
|
2020-08-08 23:40:22 +00:00
|
|
|
expansion.add(indent, gbc);
|
2020-08-07 19:21:03 +00:00
|
|
|
|
|
|
|
// Name label
|
|
|
|
var label = new JLabel();
|
2020-08-08 23:40:22 +00:00
|
|
|
parent.parent.parent.app.localizer.add(label,
|
2020-08-07 19:21:03 +00:00
|
|
|
x == 0 ? "cpu.jump_from" : "cpu.jump_to" );
|
|
|
|
gbc = new GridBagConstraints();
|
|
|
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
|
|
|
expansion.add(label, gbc);
|
2020-08-08 23:40:22 +00:00
|
|
|
controls.add(label);
|
2020-08-07 19:21:03 +00:00
|
|
|
|
|
|
|
// Value text box
|
|
|
|
var txt = new JTextField();
|
2020-12-22 02:42:28 +00:00
|
|
|
txt.addActionListener(e->parent.requestFocus());
|
|
|
|
txt.addFocusListener(Util.onFocus(null,
|
|
|
|
e->txt.setText((String) txt.getClientProperty("text"))));
|
2020-08-08 23:40:22 +00:00
|
|
|
txt.putClientProperty("index",
|
2020-10-03 19:20:56 +00:00
|
|
|
x == 0 ? Vue.JUMP_FROM : Vue.JUMP_TO);
|
2020-08-07 19:21:03 +00:00
|
|
|
txt.setBorder(null);
|
|
|
|
txt.setOpaque(false);
|
|
|
|
gbc = new GridBagConstraints();
|
|
|
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
|
|
|
gbc.insets = new Insets(0, 4, 0, 0);
|
|
|
|
expansion.add(txt, gbc);
|
2020-08-08 23:40:22 +00:00
|
|
|
controls.add(txt);
|
2020-08-07 19:21:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-08-06 21:37:05 +00:00
|
|
|
// Expansion controls for PSW
|
|
|
|
private void initPSW() {
|
2020-12-25 23:59:08 +00:00
|
|
|
expansion = new UPanel(new GridBagLayout());
|
2020-08-08 23:40:22 +00:00
|
|
|
addCheckBox("Z" , 0, false, false);
|
|
|
|
addCheckBox("FRO", 9, false, true );
|
|
|
|
addCheckBox("S" , 1, false, false);
|
|
|
|
addCheckBox("FIV", 8, false, true );
|
|
|
|
addCheckBox("OV" , 2, false, false);
|
|
|
|
addCheckBox("FZD", 7, false, true );
|
|
|
|
addCheckBox("CY" , 3, false, false);
|
|
|
|
addCheckBox("FOV", 6, false, true );
|
|
|
|
addCheckBox("EP" , 14, false, false);
|
|
|
|
addCheckBox("FUD", 5, false, true );
|
|
|
|
addCheckBox("NP" , 15, false, false);
|
|
|
|
addCheckBox("FPR", 4, false, true );
|
|
|
|
addCheckBox("AE" , 13, false, true );
|
|
|
|
addCheckBox("ID" , 12, false, false);
|
|
|
|
addTextBox ("I" , 16, 4, false, false);
|
2020-08-06 21:37:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Expansion controls for PIR
|
|
|
|
private void initPIR() {
|
2020-12-25 23:59:08 +00:00
|
|
|
expansion = new UPanel(new GridBagLayout());
|
2020-08-08 23:40:22 +00:00
|
|
|
addTextBox("PT", 0, 16, true, true);
|
2020-08-06 21:37:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Expansion controls for TKCW
|
|
|
|
private void initTKCW() {
|
2020-12-25 23:59:08 +00:00
|
|
|
expansion = new UPanel(new GridBagLayout());
|
2020-08-08 23:40:22 +00:00
|
|
|
addCheckBox("OTM", 8, true, false);
|
|
|
|
addCheckBox("FVT", 5, true, true );
|
|
|
|
addCheckBox("FIT", 7, true, false);
|
|
|
|
addCheckBox("FUT", 4, true, true );
|
|
|
|
addCheckBox("FZT", 6, true, false);
|
|
|
|
addCheckBox("FPT", 3, true, true );
|
|
|
|
addCheckBox("RDI", 2, true, false);
|
|
|
|
addTextBox ("RD", 0, 2, true, false);
|
2020-08-06 21:37:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Package Methods //
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2020-08-08 23:40:22 +00:00
|
|
|
// Apply configuration settings
|
|
|
|
void configure() {
|
|
|
|
String name = null;
|
|
|
|
|
|
|
|
// System register
|
|
|
|
if (type != PROGRAM) {
|
|
|
|
name = this.name;
|
|
|
|
if (!Disassembler.systemCaps)
|
|
|
|
name = name.toLowerCase();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Program register
|
|
|
|
else {
|
|
|
|
if (Disassembler.programNames)
|
|
|
|
name = this.name;
|
|
|
|
if (name == null)
|
|
|
|
name = "r" + index;
|
|
|
|
if (Disassembler.programCaps)
|
|
|
|
name = name.toUpperCase();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Name label
|
|
|
|
lblName.setText(name);
|
|
|
|
|
|
|
|
// Expand button
|
2020-12-23 18:26:02 +00:00
|
|
|
var size = btnExpand.getPreferredSize();
|
|
|
|
var metrics = parent.parent.parent.app.fntDialog.metrics;
|
|
|
|
size.width = 4 + Math.max(
|
|
|
|
metrics.stringWidth(EXPAND), metrics.stringWidth(COLLAPSE));
|
2020-08-08 23:40:22 +00:00
|
|
|
btnExpand.setPreferredSize(size);
|
|
|
|
|
|
|
|
// Value text box
|
2020-12-23 18:26:02 +00:00
|
|
|
var fntMono = parent.parent.parent.app.fntMono;
|
|
|
|
int hexDigitWidth = parent.parent.parent.app.hexDigitWidth;
|
|
|
|
txtValue.setFont(fntMono);
|
|
|
|
txtValue.setPreferredSize(new Dimension(
|
|
|
|
hexDigitWidth * 8 + 4, fntMono.metrics.getHeight()));
|
2020-08-08 23:40:22 +00:00
|
|
|
|
|
|
|
// Expansion controls
|
|
|
|
for (var ctrl : controls) {
|
|
|
|
if (!(ctrl instanceof JTextField))
|
|
|
|
continue;
|
2020-10-03 19:20:56 +00:00
|
|
|
if (type == Vue.PC || (Boolean) ctrl.getClientProperty("hex"))
|
2020-12-23 18:26:02 +00:00
|
|
|
((JTextField) ctrl).setFont(fntMono);
|
2020-10-03 19:20:56 +00:00
|
|
|
int digits = type == Vue.PC ? 8 :
|
2020-08-08 23:40:22 +00:00
|
|
|
(Integer) ctrl.getClientProperty("digits");
|
|
|
|
size = ctrl.getPreferredSize();
|
2020-12-23 18:26:02 +00:00
|
|
|
size.width = digits * hexDigitWidth + 4;
|
2020-08-08 23:40:22 +00:00
|
|
|
ctrl.setPreferredSize(size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-06 21:37:05 +00:00
|
|
|
// Refresh controls
|
|
|
|
void refresh() {
|
2020-08-08 23:40:22 +00:00
|
|
|
var vue = parent.parent.parent.vue;
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
// Value text box
|
2020-08-08 23:40:22 +00:00
|
|
|
value = vue.getRegister(index, type != PROGRAM);
|
2020-08-06 21:37:05 +00:00
|
|
|
txtValue.setText(
|
|
|
|
type != PROGRAM || mode == HEX ?
|
|
|
|
String.format("%08X", value) :
|
2020-08-07 19:21:03 +00:00
|
|
|
mode == SIGNED ? Integer.toString(value) :
|
2020-08-06 21:37:05 +00:00
|
|
|
mode == UNSIGNED ? Long.toString(value & 0xFFFFFFFFL) :
|
|
|
|
Float.toString(Float.intBitsToFloat(value))
|
|
|
|
);
|
|
|
|
|
2020-08-08 23:40:22 +00:00
|
|
|
// Expansion controls
|
|
|
|
for (var control : controls) {
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
// Check box
|
|
|
|
if (control instanceof JCheckBox) {
|
|
|
|
var ctrl = (JCheckBox) control;
|
|
|
|
int bit = (Integer) ctrl.getClientProperty("bit");
|
|
|
|
ctrl.setSelected((value & 1 << bit) != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Text box
|
|
|
|
if (control instanceof JTextField) {
|
|
|
|
var ctrl = (JTextField) control;
|
2020-08-08 23:40:22 +00:00
|
|
|
int digits; // Maximum digits that can be displayed
|
|
|
|
boolean hex; // The value is hexadecimal
|
|
|
|
int val; // The value to be displayed
|
|
|
|
|
|
|
|
// Jump history
|
2020-10-03 19:20:56 +00:00
|
|
|
if (type == Vue.PC) {
|
2020-08-08 23:40:22 +00:00
|
|
|
digits = 8;
|
|
|
|
hex = true;
|
|
|
|
val = vue.getRegister((Integer)
|
|
|
|
ctrl.getClientProperty("index"), true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// All other values
|
|
|
|
else {
|
|
|
|
int bit = (Integer) ctrl.getClientProperty("bit" );
|
|
|
|
digits = (Integer) ctrl.getClientProperty("digits");
|
|
|
|
hex = (Boolean) ctrl.getClientProperty("hex");
|
|
|
|
int width = (Integer) ctrl.getClientProperty("width");
|
|
|
|
val = value >> bit & (1 << width) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the text
|
|
|
|
String text = !hex ? Integer.toString(val) : String.format(
|
|
|
|
"%0" + digits + (Disassembler.hexCaps ? "X" : "x"), val);
|
|
|
|
ctrl.putClientProperty("text", text);
|
|
|
|
ctrl.setText(text);
|
2020-08-06 21:37:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Specify whether the expansion area is expanded
|
|
|
|
void setExpanded(boolean expanded) {
|
|
|
|
|
|
|
|
// Error checking
|
2020-08-07 19:21:03 +00:00
|
|
|
if (!expandable)
|
2020-08-06 21:37:05 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Update controls
|
|
|
|
this.expanded = expanded;
|
2020-08-07 19:21:03 +00:00
|
|
|
btnExpand.setText(expanded ? "-" : "+");
|
2020-10-03 19:20:56 +00:00
|
|
|
if (type != Vue.PC)
|
2020-08-08 23:40:22 +00:00
|
|
|
indent.setVisible(expanded);
|
2020-08-06 21:37:05 +00:00
|
|
|
expansion.setVisible(expanded);
|
2020-08-08 23:40:22 +00:00
|
|
|
parent.revalidate();
|
2020-08-06 21:37:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Change the display mode of a program register
|
|
|
|
void setMode(int mode) {
|
|
|
|
this.mode = mode;
|
2020-12-23 18:26:02 +00:00
|
|
|
txtValue.setFont(mode!=HEX ? null : parent.parent.parent.app.fntMono);
|
2020-08-06 21:37:05 +00:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Private Methods //
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Add a check box to the expansion area
|
2020-08-08 23:40:22 +00:00
|
|
|
private void addCheckBox(String name, int bit, boolean readOnly,
|
|
|
|
boolean last) {
|
2020-08-06 21:37:05 +00:00
|
|
|
int mask = 1 << bit;
|
|
|
|
|
|
|
|
// Configure control
|
|
|
|
var ctrl = new JCheckBox(name);
|
|
|
|
ctrl.putClientProperty("bit", bit);
|
|
|
|
ctrl.setBorder(null);
|
|
|
|
ctrl.setEnabled(!readOnly);
|
|
|
|
ctrl.setFocusable(false);
|
|
|
|
ctrl.setOpaque(false);
|
|
|
|
controls.add(ctrl);
|
|
|
|
|
|
|
|
// Event handler
|
|
|
|
ctrl.addItemListener(e->setValue(
|
|
|
|
e.getStateChange() == ItemEvent.SELECTED ?
|
|
|
|
value | mask : value & ~mask
|
|
|
|
));
|
|
|
|
|
|
|
|
// Configure expansion area
|
|
|
|
var gbc = new GridBagConstraints();
|
|
|
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
2020-08-08 23:40:22 +00:00
|
|
|
gbc.gridwidth = last ? GridBagConstraints.REMAINDER : 2;
|
2020-08-07 19:21:03 +00:00
|
|
|
gbc.insets = new Insets(0, 4, 0, 4);
|
2020-08-06 21:37:05 +00:00
|
|
|
expansion.add(ctrl, gbc);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add a radio button to the expansion area
|
|
|
|
private JRadioButton addRadioButton(String key, int mode) {
|
|
|
|
|
|
|
|
// Configure control
|
|
|
|
var ctrl = new JRadioButton();
|
2020-08-08 23:40:22 +00:00
|
|
|
parent.parent.parent.app.localizer.add(ctrl, key);
|
2020-08-06 21:37:05 +00:00
|
|
|
ctrl.setBorder(null);
|
|
|
|
ctrl.setFocusable(false);
|
|
|
|
ctrl.setOpaque(false);
|
|
|
|
ctrl.setSelected(mode == HEX);
|
|
|
|
controls.add(ctrl);
|
|
|
|
|
|
|
|
// Event handler
|
|
|
|
ctrl.addItemListener(e->{
|
|
|
|
if (e.getStateChange() == ItemEvent.SELECTED) setMode(mode); });
|
|
|
|
|
|
|
|
// Configure expansion area
|
|
|
|
var gbc = new GridBagConstraints();
|
|
|
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
|
|
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
|
|
|
gbc.insets = new Insets(0, 4, 0, 0);
|
|
|
|
expansion.add(ctrl, gbc);
|
|
|
|
|
|
|
|
return ctrl;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add a text box to the expansion area
|
|
|
|
private void addTextBox(String name, int bit, int width, boolean readOnly,
|
|
|
|
boolean hex) {
|
|
|
|
int mask = (1 << width) - 1;
|
|
|
|
|
|
|
|
// Configure control
|
|
|
|
var ctrl = new JTextField();
|
|
|
|
ctrl.putClientProperty("bit", bit);
|
|
|
|
ctrl.putClientProperty("digits",
|
|
|
|
Integer.toString(mask, hex ? 16 : 10).length());
|
|
|
|
ctrl.putClientProperty("hex", hex);
|
|
|
|
ctrl.putClientProperty("width", width);
|
|
|
|
ctrl.setBorder(null);
|
|
|
|
ctrl.setEnabled(!readOnly);
|
|
|
|
ctrl.setOpaque(false);
|
|
|
|
controls.add(ctrl);
|
|
|
|
|
|
|
|
// Event handlers
|
2020-12-22 02:42:28 +00:00
|
|
|
ctrl.addActionListener(e->parent.requestFocus());
|
|
|
|
ctrl.addFocusListener(Util.onFocus(null, e->{
|
2020-08-06 21:37:05 +00:00
|
|
|
int val = value >> bit & mask;
|
|
|
|
try { val = Integer.parseInt(ctrl.getText(), hex ? 16 : 10); }
|
|
|
|
catch (Exception x) { }
|
|
|
|
setValue(value & ~(mask << bit) | (val & mask) << bit);
|
2020-12-22 02:42:28 +00:00
|
|
|
}));
|
2020-08-06 21:37:05 +00:00
|
|
|
|
|
|
|
// Configure expansion area
|
|
|
|
var label = new JLabel(name);
|
|
|
|
label.setEnabled(!readOnly);
|
2020-08-08 23:40:22 +00:00
|
|
|
var gbc = new GridBagConstraints();
|
2020-08-06 21:37:05 +00:00
|
|
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
|
|
|
gbc.insets = new Insets(0, 4, 0, 4);
|
|
|
|
expansion.add(label, gbc);
|
2020-08-08 23:40:22 +00:00
|
|
|
gbc = new GridBagConstraints();
|
2020-08-06 21:37:05 +00:00
|
|
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
2020-08-08 23:40:22 +00:00
|
|
|
gbc.insets = new Insets(0, 4, 0, 4);
|
|
|
|
expansion.add(ctrl , gbc);
|
2020-08-06 21:37:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Update the register value
|
|
|
|
private void setValue(int value) {
|
2020-08-08 23:40:22 +00:00
|
|
|
parent.parent.parent.vue.setRegister(index, type != PROGRAM, value);
|
2020-08-06 21:37:05 +00:00
|
|
|
refresh();
|
2020-10-03 19:20:56 +00:00
|
|
|
if (index == Vue.PSW && type == Vue.PSW)
|
|
|
|
parent.registers.get(Vue.PC).refresh();
|
2020-08-06 21:37:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|