pvbemu/src/desktop/app/App.java

171 lines
5.5 KiB
Java

package app;
// Java imports
import java.awt.*;
import java.util.*;
import javax.swing.*;
// Project imports
import util.*;
import vue.*;
// Top-level software state manager
public class App {
// Instance fields
private boolean useNative; // Produce native core contexts
private Localizer.Locale[] locales; // Language translations
private ArrayList<MainWindow> windows; // Application windows
// Configuration fields
Util.Font fntDialog; // Dialog font
Util.Font fntMono; // Monospaced font
int hexDigitWidth; // Width in pixels of one hex digit
Localizer localizer; // UI localization manager
int[][] rgbBase; // Base anaglyph filter colors
int rgbClear; // Transparent pixel color
///////////////////////////////////////////////////////////////////////////
// Constants //
///////////////////////////////////////////////////////////////////////////
// Anaglyph presets
static final int[] RED = { 0xFF, 0x00, 0x00 };
static final int[] CYAN = { 0x00, 0xC6, 0xF0 };
static final int[] GREEN = { 0x00, 0xB4, 0x00 };
static final int[] MAGENTA = { 0xC8, 0x00, 0xFF };
///////////////////////////////////////////////////////////////////////////
// Constructors //
///////////////////////////////////////////////////////////////////////////
// Default constructor
public App(boolean useNative) {
// Configure instance fields
localizer = new Localizer();
windows = new ArrayList<MainWindow>();
// Configure config fields
fntDialog = new Util.Font(new JLabel().getFont());
fntMono = new Util.Font(new Font(Util.fontFamily(new String[]
{ "Consolas", Font.MONOSPACED } ), Font.PLAIN, 14));
hexDigitWidth = hexDigitWidth();
rgbBase = new int[][] { GREEN, MAGENTA, RED };
rgbClear = 0x003050;
// Additional processing
setUseNative(useNative);
initLocales();
addWindow();
}
///////////////////////////////////////////////////////////////////////////
// Package Methods //
///////////////////////////////////////////////////////////////////////////
// Add a new program window
void addWindow() {
windows.add(new MainWindow(this));
windowsChanged();
}
// Determine whether the native module is in use
boolean getUseNative() {
return useNative;
}
// Retrieve a list of registered locales
Localizer.Locale[] listLocales() {
var ret = new Localizer.Locale[locales.length];
System.arraycopy(locales, 0, ret, 0, locales.length);
return ret;
}
// Determine the number of a window in the collection
int numberOf(MainWindow window) {
return windows.indexOf(window) + 1;
}
// Remove a program window
void removeWindow(MainWindow window) {
windows.remove(window);
windowsChanged();
}
// Specify whether using the native module
boolean setUseNative(boolean useNative) {
return this.useNative = useNative && Vue.getNativeID() != null;
}
///////////////////////////////////////////////////////////////////////////
// Private Methods //
///////////////////////////////////////////////////////////////////////////
// Calculate the maximum hexadecimal digit width
private int hexDigitWidth() {
int width = 0;
for (var digit : "0123456789ABCDEFabcdef".toCharArray())
width = Math.max(width, fntMono.metrics.charWidth(digit));
return width;
}
// Load and parse all locale translations
private void initLocales() {
// Process all locale files
var locales = new HashMap<String, Localizer.Locale>();
for (String file : Util.listFiles("locale")) {
// Process the file
try {
var locale = Localizer.parse(Util.textRead("locale/" + file));
String key = locale.id.toLowerCase();
// Register the locale
if (locales.containsKey(key)) throw new RuntimeException(
"Locale with ID '" + locale.id + "' already registered");
locales.put(key, locale);
// The locale matches the one in the config
if (key.equals("en-us"))
localizer.setLocale(locale);
}
// Could not process the file
catch (Exception e) {
System.err.println("Error parsing locale " +
file + ": " + e.getMessage());
}
}
// Produce the list of registered locales
this.locales = locales.values().toArray(
new Localizer.Locale[locales.size()]);
Arrays.sort(this.locales);
// Select a default locale
if (localizer.getLocale() != null || this.locales.length == 0)
return;
var locale = locales.get("en-us");
localizer.setLocale(locale != null ? locale : this.locales[0]);
}
// A window has been added to or removed from the program state
private void windowsChanged() {
int count = windows.size();
for (int x = 0; x < count; x++)
windows.get(x).windowsChanged(x + 1, count == 1);
}
}