pvbemu/src/desktop/app/RegisterList.java

204 lines
6.3 KiB
Java

package app;
// Java imports
import java.awt.*;
import java.util.*;
import javax.swing.*;
// Project imports
import util.*;
import vue.*;
// List of CPU registers
class RegisterList extends JScrollPane {
// Package fields
CPUWindow parent; // Containing CPU window
HashMap<Integer, Register> registers; // Register items
// Private fields
private boolean shown; // Component has been shown
// UI components
private UPanel client; // Client area
///////////////////////////////////////////////////////////////////////////
// Constructors //
///////////////////////////////////////////////////////////////////////////
// Default constructor
RegisterList(CPUWindow parent, boolean system) {
super(VERTICAL_SCROLLBAR_ALWAYS, HORIZONTAL_SCROLLBAR_AS_NEEDED);
// Configure instance fields
this.parent = parent;
registers = new HashMap<Integer, Register>();
shown = true;
// Configure client area
client = new UPanel(new GridBagLayout()) {
public Dimension getPreferredSize() {
var ret = super.getPreferredSize();
if (!shown) ret.height = system ? getInitialHeight() : 0;
return ret;
}
public void paintComponent(Graphics g) {
shown = true;
super.paintComponent(g);
}
};
client.addMouseListener(Util.onMouse(e->client.requestFocus(), null));
client.setBackground(SystemColor.window);
client.setFocusable(true);
// Initialize system registers
if (system) {
new Register(this, "PC" , Vue.PC , Vue.PC );
new Register(this, "PSW" , Vue.PSW , Vue.PSW );
new Register(this, "EIPC" , Vue.EIPC , Register.PLAIN);
new Register(this, "EIPSW", Vue.EIPSW, Vue.PSW );
new Register(this, "FEPC" , Vue.FEPC , Register.PLAIN);
new Register(this, "FEPSW", Vue.FEPSW, Vue.PSW );
new Register(this, "ECR" , Vue.ECR , Vue.ECR );
new Register(this, "ADTRE", Vue.ADTRE, Register.PLAIN);
new Register(this, "CHCW" , Vue.CHCW , Vue.CHCW );
new Register(this, "PIR" , Vue.PIR , Vue.PIR );
new Register(this, "TKCW" , Vue.TKCW , Vue.TKCW );
new Register(this, "29" , 29, Register.PLAIN);
new Register(this, "30" , 30, Register.PLAIN);
new Register(this, "31" , 31, Register.PLAIN);
}
// Initialize program registers
else for (int x = 0; x < 32; x++) {
String name = null;
switch (x) {
case Vue.GP: name = "gp"; break;
case Vue.HP: name = "hp"; break;
case Vue.LP: name = "lp"; break;
case Vue.SP: name = "sp"; break;
case Vue.TP: name = "tp"; break;
}
new Register(this, name, x, Register.PROGRAM);
}
// List terminator
var spacer = new UPanel();
spacer.setOpaque(false);
spacer.setPreferredSize(new Dimension(0, 0));
var gbc = new GridBagConstraints();
gbc.gridheight = GridBagConstraints.REMAINDER;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weighty = 1;
client.add(spacer, gbc);
// Configure component
shown = false;
setViewportView(client);
}
///////////////////////////////////////////////////////////////////////////
// Public Methods //
///////////////////////////////////////////////////////////////////////////
// Draw the component
public void paintComponent(Graphics g) {
if (!shown) {
shown = true;
revalidate();
}
super.paintComponent(g);
}
// Transfer focus to the client area
public void requestFocus() {
client.requestFocus();
}
// Recalculate layout
public void revalidate() {
if (client != null)
client.revalidate();
super.revalidate();
repaint();
}
///////////////////////////////////////////////////////////////////////////
// Package Methods //
///////////////////////////////////////////////////////////////////////////
// Add a register component to the client area
void add(GridBagConstraints gbc, JComponent comp) {
client.add(comp, gbc);
}
// Associate a register with its index
void add(int index, Register register) {
registers.put(index, register);
}
// Apply configuration settings
void configure2() {
// Configure registers
for (var reg : registers.values())
reg.configure();
// Configure component
getVerticalScrollBar().setUnitIncrement(
parent.parent.app.fntMono.metrics.getHeight());
}
// Update the display
void refresh() {
for (var reg : registers.values())
reg.refresh();
}
///////////////////////////////////////////////////////////////////////////
// Private Methods //
///////////////////////////////////////////////////////////////////////////
// Determine the initial height upon first show
private int getInitialHeight() {
int height = 0;
var layout = (GridBagLayout) client.getLayout();
int ret = 0;
int row = 0;
// Process controls until the target row is found
for (var control : client.getComponents()) {
var ctrl = (JComponent) control;
// Track the tallest control on the row
if (ctrl.isVisible())
height = Math.max(height, ctrl.getPreferredSize().height);
// This is not the last control on the row
if (layout.getConstraints(control).gridwidth !=
GridBagConstraints.REMAINDER)
continue;
// Advance to the next row
ret += height;
height = 0;
row++;
// The target row has been reached
if (row == 4)
break;
}
return ret;
}
}