pvbemu/src/desktop/app/Window.java

219 lines
6.6 KiB
Java

package app;
// Java imports
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.swing.*;
import javax.swing.filechooser.*;
// Project imports
import util.*;
// Main application window
class Window extends JFrame {
// Instance fields
private App app; // Containing application
private int number; // Window number within application
private boolean only; // This is the only application window
private File romFile; // Currently loaded ROM file
// UI components
private File pwd; // Most recent working directory
private JPanel video; // Video output
///////////////////////////////////////////////////////////////////////////
// Constants //
///////////////////////////////////////////////////////////////////////////
// Application icon
private static final BufferedImage APPICON;
// Static initializer
static {
APPICON = Util.imageRead("images/app_icon.png");
}
///////////////////////////////////////////////////////////////////////////
// Constructors //
///////////////////////////////////////////////////////////////////////////
// Default constructor
Window(App app) {
super();
// Configure instance fields
this.app = app;
// Configure video pane
video = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
onPaintVideo((Graphics2D) g, getWidth(), getHeight());
}
};
video.setPreferredSize(new Dimension(384, 224));
// Configure window
addWindowListener(Util.onClose(e->onClose()));
setContentPane(video);
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
setIconImage(APPICON);
setJMenuBar(initMenus());
app.getLocalizer().add(this, "app.title.default");
// Display window
pack();
setLocationRelativeTo(null);
setVisible(true);
}
///////////////////////////////////////////////////////////////////////////
// Menu Constructors //
///////////////////////////////////////////////////////////////////////////
// Produce the window's menu bar
private JMenuBar initMenus() {
var bar = new JMenuBar();
var loc = app.getLocalizer();
bar.setBorder(null);
bar.add(initMenuFile(loc));
return bar;
}
// Initialize the File menu
private JMenu initMenuFile(Localizer loc) {
var mnuFile = new JMenu();
loc.add(mnuFile, "app.file.(menu)");
var mnuFileLoadRom = new JMenuItem();
loc.add(mnuFileLoadRom, "app.file.load_rom");
mnuFileLoadRom.addActionListener(e->onLoadROM());
mnuFile.add(mnuFileLoadRom);
mnuFile.addSeparator();
var mnuFileNewWindow = new JMenuItem();
loc.add(mnuFileNewWindow, "app.file.new_window");
mnuFileNewWindow.addActionListener(e->onNewWindow());
mnuFile.add(mnuFileNewWindow);
var mnuFileExit = new JMenuItem();
loc.add(mnuFileExit, "app.file.exit");
mnuFileExit.addActionListener(e->onClose());
mnuFile.add(mnuFileExit);
return mnuFile;
}
///////////////////////////////////////////////////////////////////////////
// Package Methods //
///////////////////////////////////////////////////////////////////////////
// A window has been added to or removed from the program state
void windowsChanged(int number, boolean only) {
this.number = number;
this.only = only;
app.getLocalizer().put(this, "ctrl.number", "" + number);
updateTitle();
}
///////////////////////////////////////////////////////////////////////////
// Event Handlers //
///////////////////////////////////////////////////////////////////////////
// Window close, File -> Exit
private void onClose() {
app.removeWindow(this);
dispose();
}
// File -> Load ROM
private void onLoadROM() {
var loc = app.getLocalizer();
// Prompt the user to select a file
var dlgFile = new JFileChooser(pwd);
dlgFile.addChoosableFileFilter(new FileNameExtensionFilter(
"Virtual Boy ROMs (*.vb)", "vb"));
dlgFile.addChoosableFileFilter(new FileNameExtensionFilter(
"ISX modules (*.isx)", "isx"));
dlgFile.setAcceptAllFileFilterUsed(true);
dlgFile.setDialogTitle(loc.get("dialog.load_rom"));
int option = dlgFile.showDialog(this, loc.get("dialog.load"));
// The user did not select a file
var file = dlgFile.getSelectedFile();
if (option != JFileChooser.APPROVE_OPTION || file == null)
return;
// Update the current directory
pwd = file.getParentFile();
// Attempt to load the ROM file
var data = Util.fileRead(file);
if (data == null) {
JOptionPane.showMessageDialog(this,
loc.get("dialog.load_rom_error"),
loc.get("dialog.load_rom"),
JOptionPane.ERROR_MESSAGE
);
return;
}
// Update the emulation state
romFile = file;
loc.put(this, "ctrl.filename", file.getName());
updateTitle();
}
// File -> New window
private void onNewWindow() {
app.addWindow();
}
// Video paint
private void onPaintVideo(Graphics2D g, int width, int height) {
int scale = Math.max(1, Math.min(width / 384, height / 224));
g.translate(
Math.max(0, (width - scale * 384) / 2),
Math.max(0, (height - scale * 224) / 2)
);
g.scale(scale, scale);
g.setColor(Color.black);
g.fillRect(0, 0, 384, 224);
}
///////////////////////////////////////////////////////////////////////////
// Private Methods //
///////////////////////////////////////////////////////////////////////////
// Update the window title
private void updateTitle() {
app.getLocalizer().add(this,
only ? romFile != null ?
"app.title.rom" :
"app.title.default"
: romFile != null ?
"app.title.mixed" :
"app.title.number"
);
}
}