From bf2e39681bc16c1fd0053dd63fb82e07ac6984c1 Mon Sep 17 00:00:00 2001 From: Peter Jakubco Date: Sun, 28 Jan 2024 11:33:33 +0100 Subject: [PATCH 1/4] [#314] zx-spectrum: keyboard handling wip --- .../device/zxspectrum/ula/DeviceImpl.java | 8 +- .../plugins/device/zxspectrum/ula/ULA.java | 245 +++++++++--------- .../zxspectrum/ula/gui/DisplayWindow.java | 11 +- .../zxspectrum/ula/gui/KeyboardCanvas.java | 29 +-- ...{Keyboard.java => KeyboardDispatcher.java} | 56 ++-- 5 files changed, 163 insertions(+), 186 deletions(-) rename plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/{Keyboard.java => KeyboardDispatcher.java} (57%) diff --git a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/DeviceImpl.java b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/DeviceImpl.java index c715cffcd..bc9f39ce7 100644 --- a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/DeviceImpl.java +++ b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/DeviceImpl.java @@ -23,10 +23,8 @@ import net.emustudio.emulib.plugins.annotations.PluginRoot; import net.emustudio.emulib.plugins.device.AbstractDevice; import net.emustudio.emulib.runtime.ApplicationApi; -import net.emustudio.emulib.runtime.interaction.GuiUtils; import net.emustudio.emulib.runtime.settings.PluginSettings; import net.emustudio.plugins.device.zxspectrum.bus.api.ZxSpectrumBus; -import net.emustudio.plugins.device.zxspectrum.ula.gui.Keyboard; import net.emustudio.plugins.device.zxspectrum.ula.gui.DisplayWindow; import javax.swing.*; @@ -39,7 +37,6 @@ public class DeviceImpl extends AbstractDevice { private final boolean guiSupported; - private final Keyboard keyboard = new Keyboard(); private boolean guiIOset = false; private ULA ula; @@ -58,7 +55,6 @@ public void initialize() throws PluginInitializationException { this.ula = new ULA(bus); this.passedCyclesMediator = new PassedCyclesMediator(ula); bus.addPassedCyclesListener(passedCyclesMediator); - keyboard.addOnKeyListener(ula); bus.attachDevice(0xFE, ula); } @@ -69,7 +65,6 @@ public void reset() { @Override public void destroy() { - keyboard.close(); if (guiIOset || gui != null) { gui.destroy(); gui = null; @@ -91,9 +86,8 @@ public boolean isShowSettingsSupported() { public void showGUI(JFrame parent) { if (guiSupported) { if (!guiIOset) { - this.gui = new DisplayWindow(parent, ula, keyboard); + this.gui = new DisplayWindow(parent, ula); passedCyclesMediator.setCanvas(gui.getCanvas()); - GuiUtils.addKeyListener(gui, keyboard); guiIOset = true; this.gui.setVisible(true); } diff --git a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/ULA.java b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/ULA.java index f4a781675..c239f0def 100644 --- a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/ULA.java +++ b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/ULA.java @@ -20,14 +20,16 @@ import net.emustudio.plugins.cpu.intel8080.api.Context8080; import net.emustudio.plugins.device.zxspectrum.bus.api.ZxSpectrumBus; -import net.emustudio.plugins.device.zxspectrum.ula.gui.Keyboard; +import net.emustudio.plugins.device.zxspectrum.ula.gui.KeyboardDispatcher; import java.awt.event.KeyEvent; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.function.BiConsumer; +import static java.awt.event.KeyEvent.*; import static net.emustudio.plugins.device.zxspectrum.ula.ZxParameters.*; /** @@ -74,7 +76,7 @@ * - P2 to P0 is the PAPER colour * - I2 to I0 is the INK colour */ -public class ULA implements Context8080.CpuPortDevice, Keyboard.OnKeyListener { +public class ULA implements Context8080.CpuPortDevice, KeyboardDispatcher.OnKeyListener { private final static byte[] RST_7 = new byte[0x38]; // works for IM1 and IM2 modes private final static byte[] KEY_SHIFT = new byte[]{0, 1}; private final static byte[] KEY_SYM_SHIFT = new byte[]{7, 2}; @@ -88,49 +90,72 @@ public class ULA implements Context8080.CpuPortDevice, Keyboard.OnKeyListener { // maps host characters to ZX Spectrum key "commands" // Byte[] = {keymap index, "zero" value, shift, symshift} - private final static Map CHAR_MAPPING = new HashMap<>(); + private final static Map CHAR_MAPPING = new HashMap<>(); static { - CHAR_MAPPING.put('Z', new Byte[]{0, 2, -1, -1}); // z, COPY, ":" - CHAR_MAPPING.put('X', new Byte[]{0, 4, -1, -1}); // x, CLEAR, "£" - CHAR_MAPPING.put('C', new Byte[]{0, 8, -1, -1}); // c, CONT, "?" - CHAR_MAPPING.put('V', new Byte[]{0, 16, -1, -1}); // v, CLS, "/" - CHAR_MAPPING.put('B', new Byte[]{7, 16, -1, -1}); // b, BORDER, "*" - CHAR_MAPPING.put('N', new Byte[]{7, 8, -1, -1}); // n, NEXT, "," - CHAR_MAPPING.put('M', new Byte[]{7, 4, -1, -1}); // m, PAUSE, "." - CHAR_MAPPING.put(' ', new Byte[]{7, 1, -1, -1}); // " " - CHAR_MAPPING.put('\n', new Byte[]{6, 1, -1, -1}); // ENTER - CHAR_MAPPING.put('A', new Byte[]{1, 1, -1, -1}); // a, NEW, "STOP" - CHAR_MAPPING.put('S', new Byte[]{1, 2, -1, -1}); // s, SAVE, "NOT" - CHAR_MAPPING.put('D', new Byte[]{1, 4, -1, -1}); // d, DIM, "STEP" - CHAR_MAPPING.put('F', new Byte[]{1, 8, -1, -1}); // f, FOR, "TO" - CHAR_MAPPING.put('G', new Byte[]{1, 16, -1, -1}); // g, GOTO, "THEN" - CHAR_MAPPING.put('H', new Byte[]{6, 16, -1, -1}); // h, GOSUB, "↑" - CHAR_MAPPING.put('J', new Byte[]{6, 8, -1, -1}); // j, LOAD, "-" - CHAR_MAPPING.put('K', new Byte[]{6, 4, -1, -1}); // k, LIST, "+" - CHAR_MAPPING.put('L', new Byte[]{6, 2, -1, -1}); // l, LET, "=" - CHAR_MAPPING.put('Q', new Byte[]{2, 1, -1, -1}); // q, PLOT, "<=" - CHAR_MAPPING.put('W', new Byte[]{2, 2, -1, -1}); // w, DRAW, "<>" - CHAR_MAPPING.put('E', new Byte[]{2, 4, -1, -1}); // e, REM, ">=" - CHAR_MAPPING.put('R', new Byte[]{2, 8, -1, -1}); // r, RUN, "<" - CHAR_MAPPING.put('T', new Byte[]{2, 16, -1, -1}); // t, RAND, ">" - CHAR_MAPPING.put('Y', new Byte[]{5, 16, -1, -1}); // y, RETURN, "AND" - CHAR_MAPPING.put('U', new Byte[]{5, 8, -1, -1}); // u, IF, "OR" - CHAR_MAPPING.put('I', new Byte[]{5, 4, -1, -1}); // i, INPUT, "AT" - CHAR_MAPPING.put('O', new Byte[]{5, 2, -1, -1}); // o, POKE, ";" - CHAR_MAPPING.put('P', new Byte[]{5, 1, -1, -1}); // p, PRINT, " - CHAR_MAPPING.put('1', new Byte[]{3, 1, -1, -1}); // 1, "!" - CHAR_MAPPING.put('2', new Byte[]{3, 2, -1, -1}); // 2, "@" - CHAR_MAPPING.put('3', new Byte[]{3, 4, -1, -1}); // 3, "#" - CHAR_MAPPING.put('4', new Byte[]{3, 8, -1, -1}); // 4, "$" - CHAR_MAPPING.put('5', new Byte[]{3, 16, -1, -1}); // 5, "%" - CHAR_MAPPING.put('6', new Byte[]{4, 16, -1, -1}); // 6, "&" - CHAR_MAPPING.put('7', new Byte[]{4, 8, -1, -1}); // 7, "'" - CHAR_MAPPING.put('8', new Byte[]{4, 4, -1, -1}); // 8, "(" - CHAR_MAPPING.put('9', new Byte[]{4, 2, -1, -1}); // 9, ")" - CHAR_MAPPING.put('0', new Byte[]{4, 1, -1, -1}); // 0, "_" - CHAR_MAPPING.put('\b', new Byte[]{4, 1, 1, -1}); // backspace - CHAR_MAPPING.put((char) 127, new Byte[]{4, 1, 1, -1}); // delete + CHAR_MAPPING.put(VK_Z, new Byte[]{0, 2, -1, -1}); // z, COPY, ":" + CHAR_MAPPING.put(VK_COLON, new Byte[]{0, 2, 0, 1}); + CHAR_MAPPING.put(VK_X, new Byte[]{0, 4, -1, -1}); // x, CLEAR, "£" + CHAR_MAPPING.put(VK_C, new Byte[]{0, 8, -1, -1}); // c, CONT, "?" + CHAR_MAPPING.put(VK_V, new Byte[]{0, 16, -1, -1}); // v, CLS, "/" + CHAR_MAPPING.put(VK_SLASH, new Byte[]{0, 16, 0, 1}); + CHAR_MAPPING.put(VK_B, new Byte[]{7, 16, -1, -1}); // b, BORDER, "*" + CHAR_MAPPING.put(VK_ASTERISK, new Byte[]{7, 16, 0, 1}); + CHAR_MAPPING.put(VK_N, new Byte[]{7, 8, -1, -1}); // n, NEXT, "," + CHAR_MAPPING.put(VK_COMMA, new Byte[]{7, 8, 0, 1}); + CHAR_MAPPING.put(VK_M, new Byte[]{7, 4, -1, -1}); // m, PAUSE, "." + CHAR_MAPPING.put(VK_DECIMAL, new Byte[]{7, 4, 0, 1}); + CHAR_MAPPING.put(VK_PERIOD, new Byte[]{7, 4, 0, 1}); + CHAR_MAPPING.put(VK_SPACE, new Byte[]{7, 1, -1, -1}); // " " + CHAR_MAPPING.put(VK_ENTER, new Byte[]{6, 1, -1, -1}); // ENTER + CHAR_MAPPING.put(VK_A, new Byte[]{1, 1, -1, -1}); // a, NEW, "STOP" + CHAR_MAPPING.put(VK_S, new Byte[]{1, 2, -1, -1}); // s, SAVE, "NOT" + CHAR_MAPPING.put(VK_D, new Byte[]{1, 4, -1, -1}); // d, DIM, "STEP" + CHAR_MAPPING.put(VK_F, new Byte[]{1, 8, -1, -1}); // f, FOR, "TO" + CHAR_MAPPING.put(VK_G, new Byte[]{1, 16, -1, -1}); // g, GOTO, "THEN" + CHAR_MAPPING.put(VK_H, new Byte[]{6, 16, -1, -1}); // h, GOSUB, "↑" + CHAR_MAPPING.put(VK_UP, new Byte[]{6, 16, 0, 1}); + CHAR_MAPPING.put(VK_J, new Byte[]{6, 8, -1, -1}); // j, LOAD, "-" + CHAR_MAPPING.put(VK_SUBTRACT, new Byte[]{6, 8, 0, 1}); + CHAR_MAPPING.put(VK_K, new Byte[]{6, 4, -1, -1}); // k, LIST, "+" + CHAR_MAPPING.put(VK_ADD, new Byte[]{6, 4, 0, 1}); + CHAR_MAPPING.put(VK_L, new Byte[]{6, 2, -1, -1}); // l, LET, "=" + CHAR_MAPPING.put(VK_EQUALS, new Byte[]{6, 2, 0, 1}); + CHAR_MAPPING.put(VK_Q, new Byte[]{2, 1, -1, -1}); // q, PLOT, "<=" + CHAR_MAPPING.put(VK_W, new Byte[]{2, 2, -1, -1}); // w, DRAW, "<>" + CHAR_MAPPING.put(VK_E, new Byte[]{2, 4, -1, -1}); // e, REM, ">=" + CHAR_MAPPING.put(VK_R, new Byte[]{2, 8, -1, -1}); // r, RUN, "<" + CHAR_MAPPING.put(VK_LESS, new Byte[]{2, 8, 0, 1}); + CHAR_MAPPING.put(VK_T, new Byte[]{2, 16, -1, -1}); // t, RAND, ">" + CHAR_MAPPING.put(VK_GREATER, new Byte[]{2, 16, 0, 1}); + CHAR_MAPPING.put(VK_Y, new Byte[]{5, 16, -1, -1}); // y, RETURN, "AND" + CHAR_MAPPING.put(VK_U, new Byte[]{5, 8, -1, -1}); // u, IF, "OR" + CHAR_MAPPING.put(VK_I, new Byte[]{5, 4, -1, -1}); // i, INPUT, "AT" + CHAR_MAPPING.put(VK_O, new Byte[]{5, 2, -1, -1}); // o, POKE, ";" + CHAR_MAPPING.put(VK_SEMICOLON, new Byte[]{5, 2, 0, 1}); + CHAR_MAPPING.put(VK_P, new Byte[]{5, 1, -1, -1}); // p, PRINT, " + CHAR_MAPPING.put(VK_QUOTEDBL, new Byte[]{5, 1, 0, 1}); + CHAR_MAPPING.put(VK_1, new Byte[]{3, 1, -1, -1}); // 1, "!" + CHAR_MAPPING.put(VK_EXCLAMATION_MARK, new Byte[]{3, 1, 0, 1}); + CHAR_MAPPING.put(VK_2, new Byte[]{3, 2, -1, -1}); // 2, "@" + CHAR_MAPPING.put(VK_AT, new Byte[]{3, 2, 0, 1}); + CHAR_MAPPING.put(VK_3, new Byte[]{3, 4, -1, -1}); // 3, "#" + CHAR_MAPPING.put(VK_NUMBER_SIGN, new Byte[]{3, 4, 0, 1}); + CHAR_MAPPING.put(VK_4, new Byte[]{3, 8, -1, -1}); // 4, "$" + CHAR_MAPPING.put(VK_DOLLAR, new Byte[]{3, 8, 0, 1}); + CHAR_MAPPING.put(VK_5, new Byte[]{3, 16, -1, -1}); // 5, "%" + CHAR_MAPPING.put(VK_6, new Byte[]{4, 16, -1, -1}); // 6, "&" + CHAR_MAPPING.put(VK_AMPERSAND, new Byte[]{4, 16, 0, 1}); + CHAR_MAPPING.put(VK_7, new Byte[]{4, 8, -1, -1}); // 7, "'" + CHAR_MAPPING.put(VK_QUOTE, new Byte[]{4, 8, 0, 1}); + CHAR_MAPPING.put(VK_8, new Byte[]{4, 4, -1, -1}); // 8, "(" + CHAR_MAPPING.put(VK_LEFT_PARENTHESIS, new Byte[]{4, 4, 0, 1}); + CHAR_MAPPING.put(VK_9, new Byte[]{4, 2, -1, -1}); // 9, ")" + CHAR_MAPPING.put(VK_RIGHT_PARENTHESIS, new Byte[]{4, 2, 0, 1}); + CHAR_MAPPING.put(VK_0, new Byte[]{4, 1, -1, -1}); // 0, "_" + CHAR_MAPPING.put(VK_UNDERSCORE, new Byte[]{4, 1, 0, 1}); + CHAR_MAPPING.put(VK_BACK_SPACE, new Byte[]{4, 1, 1, 0}); // backspace + CHAR_MAPPING.put(VK_DELETE, new Byte[]{4, 1, 1, 0}); // delete } public boolean videoFlash = false; @@ -187,30 +212,23 @@ public byte read(int portAddress) { // If more than one address line is made low, the result is the logical AND of all single inputs byte result = (byte) 0xBF; // 1011 1111 // no EAR input - if ((portAddress & 0xFEFE) == 0xFEFE) { - // SHIFT, Z, X, C, V - result &= keymap[0]; - } else if ((portAddress & 0xFDFE) == 0xFDFE) { - // A, S, D, F, G - result &= keymap[1]; - } else if ((portAddress & 0xFBFE) == 0xFBFE) { - // Q, W, E, R, T - result &= keymap[2]; - } else if ((portAddress & 0xF7FE) == 0xF7FE) { - // 1, 2, 3, 4, 5 - result &= keymap[3]; - } else if ((portAddress & 0xEFFE) == 0xEFFE) { - // 0, 9, 8, 7, 6 - result &= keymap[4]; - } else if ((portAddress & 0xDFFE) == 0xDFFE) { - // P, O, I, U, Y - result &= keymap[5]; - } else if ((portAddress & 0xBFFE) == 0xBFFE) { - // ENTER, L, K, J, H - result &= keymap[6]; - } else if ((portAddress & 0x7FFE) == 0x7FFE) { - // SPACE, SYM SHIFT, M, N, B - result &= keymap[7]; + if ((portAddress & 0xFE) == 0xFE) { + int keyLine = 0; + portAddress >>>= 8; + while ((portAddress & 1) != 0) { + portAddress >>>= 1; + keyLine++; + } + + // FE = 0 1111 1110 + // FD = 1 1111 1101 + // FB = 2 1111 1011 + // F7 = 3 1111 0111 + // EF = 4 1110 1111 + // DF = 5 1101 1111 + // BF = 6 1011 1111 + // 7F = 7 0111 1111 + result &= keymap[keyLine]; } // LINE IN? @@ -235,61 +253,54 @@ public String toString() { } @Override - public void onKeyUp(KeyEvent evt) { - int keyCode = evt.getExtendedKeyCode(); - switch (keyCode) { - case KeyEvent.VK_CONTROL: - keymap[KEY_SYM_SHIFT[0]] |= KEY_SYM_SHIFT[1]; - break; - case KeyEvent.VK_SHIFT: - keymap[KEY_SHIFT[0]] |= KEY_SHIFT[1]; - break; - default: - Byte[] command = CHAR_MAPPING.get((char) keyCode); - if (command != null) { - if (command[2] == 1) { - keymap[KEY_SHIFT[0]] |= KEY_SHIFT[1]; - } else if (command[2] == 0) { - keymap[KEY_SHIFT[0]] &= (byte) ((~KEY_SHIFT[1]) & 0xFF); - } - if (command[3] == 1) { - keymap[KEY_SYM_SHIFT[0]] |= KEY_SYM_SHIFT[1]; - } else if (command[3] == 0) { - keymap[KEY_SYM_SHIFT[0]] &= (byte) ((~KEY_SYM_SHIFT[1]) & 0xFF); - } - keymap[command[0]] |= command[1]; - } + public void onKeyEvent(KeyEvent e) { + boolean pressed = e.getID() == KEY_PRESSED; + if (!pressed && e.getID() != KEY_RELEASED) { + return; } - } + BiConsumer keySet = pressed ? this::andKeyMap : this::orKeyMap; + BiConsumer keyUnset = pressed ? this::orKeyMap : this::andKeyMap; - @Override - public void onKeyDown(KeyEvent evt) { - int keyCode = evt.getExtendedKeyCode(); - switch (keyCode) { - case KeyEvent.VK_CONTROL: - keymap[KEY_SYM_SHIFT[0]] &= (byte) ((~KEY_SYM_SHIFT[1]) & 0xFF); - break; - case KeyEvent.VK_SHIFT: - keymap[KEY_SHIFT[0]] &= (byte) ((~KEY_SHIFT[1]) & 0xFF); - break; - default: - Byte[] command = CHAR_MAPPING.get((char) keyCode); - if (command != null) { - if (command[2] == 1) { - keymap[KEY_SHIFT[0]] &= (byte) ((~KEY_SHIFT[1]) & 0xFF); - } else if (command[2] == 0) { - keymap[KEY_SHIFT[0]] |= KEY_SHIFT[1]; - } - if (command[3] == 1) { - keymap[KEY_SYM_SHIFT[0]] &= (byte) ((~KEY_SYM_SHIFT[1]) & 0xFF); - } else if (command[3] == 0) { - keymap[KEY_SYM_SHIFT[0]] |= KEY_SYM_SHIFT[1]; - } - keymap[command[0]] &= (byte) ((~command[1]) & 0xFF); - } + // shift / alt / ctrl are visible in modifiersEx only if pressed = true + boolean symShift = (e.getModifiersEx() & (KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)) != 0; + boolean shift = (e.getModifiersEx() & (KeyEvent.SHIFT_DOWN_MASK)) != 0; + + Byte[] command = CHAR_MAPPING.get(e.getKeyCode()); + if (command != null) { + if (command[2] == 1 || (command[2] == -1 && shift)) { + keySet.accept(KEY_SHIFT[0], KEY_SHIFT[1]); + } else if (command[2] == 0 || !shift) { + keyUnset.accept(KEY_SHIFT[0], KEY_SHIFT[1]); + } + if (command[3] == 1 || (command[3] == -1 && symShift)) { + keySet.accept(KEY_SYM_SHIFT[0], KEY_SYM_SHIFT[1]); + } else if (command[3] == 0 || !symShift) { + keyUnset.accept(KEY_SYM_SHIFT[0], KEY_SYM_SHIFT[1]); + } + // TODO: shift/symshift are toggling for some reason + keySet.accept(command[0], command[1]); + } else { + if (shift) { + keySet.accept(KEY_SHIFT[0], KEY_SHIFT[1]); + } else { + keyUnset.accept(KEY_SHIFT[0], KEY_SHIFT[1]); + } + if (symShift) { + keySet.accept(KEY_SYM_SHIFT[0], KEY_SYM_SHIFT[1]); + } else { + keyUnset.accept(KEY_SYM_SHIFT[0], KEY_SYM_SHIFT[1]); + } } } + private void andKeyMap(byte key, byte value) { + keymap[key] &= (byte) ((~value) & 0xFF); + } + + private void orKeyMap(byte key, byte value) { + keymap[key] |= value; + } + /** * Computes address offsets for each line in the screen. *

diff --git a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java index babd58519..8d0d6c339 100644 --- a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java +++ b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java @@ -21,6 +21,7 @@ import net.emustudio.plugins.device.zxspectrum.ula.ULA; import javax.swing.*; +import java.awt.*; import java.awt.event.WindowEvent; import static net.emustudio.plugins.device.zxspectrum.ula.ZxParameters.SCREEN_IMAGE_HEIGHT; @@ -32,10 +33,10 @@ public class DisplayWindow extends JDialog { public final static int MARGIN = 30; - public DisplayWindow(JFrame parent, ULA ula, Keyboard keyboard) { + public DisplayWindow(JFrame parent, ULA ula) { super(parent); this.canvas = new DisplayCanvas(ula); - this.keyboardCanvas = new KeyboardCanvas(keyboard); + this.keyboardCanvas = new KeyboardCanvas(); initComponents(); setLocationRelativeTo(parent); @@ -49,6 +50,12 @@ public void windowActivated(WindowEvent winEvt) { canvas.redrawNow(); } }); + KeyboardDispatcher keyboardDispatcher = new KeyboardDispatcher(); + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + manager.addKeyEventDispatcher(keyboardDispatcher); + + keyboardDispatcher.addOnKeyListener(keyboardCanvas); + keyboardDispatcher.addOnKeyListener(ula); } public void destroy() { diff --git a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java index d09e36925..bfbb15bd6 100644 --- a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java +++ b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java @@ -5,6 +5,8 @@ import java.awt.event.KeyEvent; import java.awt.font.GlyphVector; +import static java.awt.event.KeyEvent.KEY_PRESSED; +import static java.awt.event.KeyEvent.KEY_RELEASED; import static net.emustudio.plugins.device.zxspectrum.ula.ZxParameters.SCREEN_IMAGE_WIDTH; import static net.emustudio.plugins.device.zxspectrum.ula.gui.DisplayCanvas.ZOOM; import static net.emustudio.plugins.device.zxspectrum.ula.gui.DisplayWindow.MARGIN; @@ -12,7 +14,7 @@ /** * Host-ZX Keyboard mapping visual representation. */ -public class KeyboardCanvas extends JComponent implements Keyboard.OnKeyListener { +public class KeyboardCanvas extends JComponent implements KeyboardDispatcher.OnKeyListener { private final static int bw = 45; // button width private final static int bh = 33; // button height private final static int bsw = 70; // backspace width @@ -104,30 +106,19 @@ public class KeyboardCanvas extends JComponent implements Keyboard.OnKeyListener private boolean symShift = false; private boolean shift = false; - public KeyboardCanvas(Keyboard keyboard) { + public KeyboardCanvas() { setDoubleBuffered(true); - keyboard.addOnKeyListener(this); } @Override - public void onKeyDown(KeyEvent evt) { - int keyCode = evt.getExtendedKeyCode(); - if (keyCode == KeyEvent.VK_CONTROL) { - symShift = true; - } else if (keyCode == KeyEvent.VK_SHIFT) { - shift = true; + public void onKeyEvent(KeyEvent e) { + boolean pressed = e.getID() == KEY_PRESSED; + if (!pressed && e.getID() != KEY_RELEASED) { + return; } - repaint(); - } - @Override - public void onKeyUp(KeyEvent evt) { - int keyCode = evt.getExtendedKeyCode(); - if (keyCode == KeyEvent.VK_CONTROL) { - symShift = false; - } else if (evt.getKeyCode() == KeyEvent.VK_SHIFT) { - shift = false; - } + symShift = (e.getModifiersEx() & (KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)) != 0; + shift = (e.getModifiersEx() & (KeyEvent.SHIFT_DOWN_MASK)) != 0; repaint(); } diff --git a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/Keyboard.java b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardDispatcher.java similarity index 57% rename from plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/Keyboard.java rename to plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardDispatcher.java index 9710a1f61..3f313b463 100644 --- a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/Keyboard.java +++ b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardDispatcher.java @@ -18,66 +18,40 @@ */ package net.emustudio.plugins.device.zxspectrum.ula.gui; -import net.emustudio.emulib.runtime.interaction.GuiUtils; import net.jcip.annotations.ThreadSafe; -import java.awt.event.ContainerEvent; -import java.awt.event.ContainerListener; +import java.awt.*; import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; import java.util.List; import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; @ThreadSafe -public class Keyboard implements AutoCloseable, KeyListener, ContainerListener { +public class KeyboardDispatcher implements AutoCloseable, KeyEventDispatcher { private final List onKeyListeners = new CopyOnWriteArrayList<>(); public interface OnKeyListener { - void onKeyDown(KeyEvent evt); - - void onKeyUp(KeyEvent evt); - } - - public void addOnKeyListener(OnKeyListener onKeyListener) { - onKeyListeners.add(Objects.requireNonNull(onKeyListener)); - } - - protected void notifyOnKeyDown(KeyEvent evt) { - onKeyListeners.forEach(c -> c.onKeyDown(evt)); - } - - protected void notifyOnKeyUp(KeyEvent evt) { - onKeyListeners.forEach(c -> c.onKeyUp(evt)); - } - - public void close() { - onKeyListeners.clear(); + void onKeyEvent(KeyEvent e); } @Override - public void keyTyped(KeyEvent e) { - - } - - @Override - public void keyPressed(KeyEvent evt) { - notifyOnKeyDown(evt); - } - - @Override - public void keyReleased(KeyEvent evt) { - notifyOnKeyUp(evt); + public boolean dispatchKeyEvent(KeyEvent e) { + boolean isConsumed = false; + if (!e.isConsumed()) { + onKeyListeners.forEach(c -> c.onKeyEvent(e)); + e.consume(); + isConsumed = true; + } + return isConsumed; } @Override - public void componentAdded(ContainerEvent e) { - GuiUtils.addKeyListener(e.getChild(), this); + public void close() { + onKeyListeners.clear(); } - @Override - public void componentRemoved(ContainerEvent e) { - GuiUtils.removeKeyListener(e.getChild(), this); + public void addOnKeyListener(OnKeyListener onKeyListener) { + onKeyListeners.add(Objects.requireNonNull(onKeyListener)); } } From 739a32b77e12ecec09feb325824a9fd8691d3038 Mon Sep 17 00:00:00 2001 From: Peter Jakubco Date: Mon, 20 May 2024 08:25:19 +0200 Subject: [PATCH 2/4] [#314] ZX Keyboard inside draw canvas --- .../plugins/device/zxspectrum/ula/ULA.java | 7 +- .../zxspectrum/ula/gui/DisplayCanvas.java | 11 ++- .../zxspectrum/ula/gui/DisplayWindow.java | 22 ++--- .../zxspectrum/ula/gui/KeyboardCanvas.java | 86 +++++++++++-------- .../ula/gui/KeyboardDispatcher.java | 13 ++- 5 files changed, 80 insertions(+), 59 deletions(-) diff --git a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/ULA.java b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/ULA.java index c239f0def..1835cef30 100644 --- a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/ULA.java +++ b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/ULA.java @@ -253,10 +253,10 @@ public String toString() { } @Override - public void onKeyEvent(KeyEvent e) { + public boolean onKeyEvent(KeyEvent e) { boolean pressed = e.getID() == KEY_PRESSED; if (!pressed && e.getID() != KEY_RELEASED) { - return; + return false; } BiConsumer keySet = pressed ? this::andKeyMap : this::orKeyMap; BiConsumer keyUnset = pressed ? this::orKeyMap : this::andKeyMap; @@ -264,7 +264,7 @@ public void onKeyEvent(KeyEvent e) { // shift / alt / ctrl are visible in modifiersEx only if pressed = true boolean symShift = (e.getModifiersEx() & (KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)) != 0; boolean shift = (e.getModifiersEx() & (KeyEvent.SHIFT_DOWN_MASK)) != 0; - + Byte[] command = CHAR_MAPPING.get(e.getKeyCode()); if (command != null) { if (command[2] == 1 || (command[2] == -1 && shift)) { @@ -291,6 +291,7 @@ public void onKeyEvent(KeyEvent e) { keyUnset.accept(KEY_SYM_SHIFT[0], KEY_SYM_SHIFT[1]); } } + return true; } private void andKeyMap(byte key, byte value) { diff --git a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayCanvas.java b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayCanvas.java index 8880a7e80..7f5cda2e0 100644 --- a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayCanvas.java +++ b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayCanvas.java @@ -64,9 +64,11 @@ public class DisplayCanvas extends Canvas implements AutoCloseable { private final ULA ula; private final PaintCycle paintCycle = new PaintCycle(); + private final KeyboardCanvas keyboardCanvas; - public DisplayCanvas(ULA ula) { + public DisplayCanvas(ULA ula, KeyboardCanvas keyboardCanvas) { this.ula = Objects.requireNonNull(ula); + this.keyboardCanvas = Objects.requireNonNull(keyboardCanvas); this.screenImage.setAccelerationPriority(1.0f); this.screenImageData = ((DataBufferInt) this.screenImage.getRaster().getDataBuffer()).getData(); } @@ -185,6 +187,13 @@ protected void paint() { graphics.drawImage( screenImage, MARGIN, MARGIN, (int) (SCREEN_IMAGE_WIDTH * ZOOM), (int) (SCREEN_IMAGE_HEIGHT * ZOOM), null); + + Color color = graphics.getColor(); + graphics.setColor(new Color(0, 0, 0, 127)); + graphics.translate(0, SCREEN_IMAGE_HEIGHT * ZOOM - KeyboardCanvas.KEYBOARD_HEIGHT + MARGIN); + keyboardCanvas.paint(graphics); + graphics.setColor(color); + graphics.dispose(); } while (strategy.contentsRestored()); diff --git a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java index 8d0d6c339..7426ab332 100644 --- a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java +++ b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java @@ -28,15 +28,17 @@ import static net.emustudio.plugins.device.zxspectrum.ula.ZxParameters.SCREEN_IMAGE_WIDTH; public class DisplayWindow extends JDialog { - private final DisplayCanvas canvas; - private final KeyboardCanvas keyboardCanvas; - public final static int MARGIN = 30; + private final static int BOUND_X = (int) (DisplayCanvas.ZOOM * SCREEN_IMAGE_WIDTH + 2 * MARGIN); + private final static int BOUND_Y = (int) (DisplayCanvas.ZOOM * SCREEN_IMAGE_HEIGHT + 2 * MARGIN); + + private final DisplayCanvas canvas; + public DisplayWindow(JFrame parent, ULA ula) { super(parent); - this.canvas = new DisplayCanvas(ula); - this.keyboardCanvas = new KeyboardCanvas(); + KeyboardCanvas keyboardCanvas = new KeyboardCanvas(70); + this.canvas = new DisplayCanvas(ula, keyboardCanvas); initComponents(); setLocationRelativeTo(parent); @@ -66,23 +68,17 @@ public void destroy() { private void initComponents() { setTitle("ZX Spectrum48K"); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - canvas.setBounds( - MARGIN, MARGIN, - (int) (DisplayCanvas.ZOOM * SCREEN_IMAGE_WIDTH + 2 * MARGIN), - (int) (DisplayCanvas.ZOOM * SCREEN_IMAGE_HEIGHT + 2 * MARGIN)); + canvas.setBounds(MARGIN, MARGIN, BOUND_X, BOUND_Y); GroupLayout layout = new GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(canvas) - .addComponent(keyboardCanvas)); + .addComponent(canvas)); layout.setVerticalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(canvas, GroupLayout.DEFAULT_SIZE, 407, Short.MAX_VALUE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(keyboardCanvas, GroupLayout.DEFAULT_SIZE, KeyboardCanvas.KEYBOARD_HEIGHT + 3, Short.MAX_VALUE) .addContainerGap())); pack(); } diff --git a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java index bfbb15bd6..28c670d32 100644 --- a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java +++ b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java @@ -15,26 +15,25 @@ * Host-ZX Keyboard mapping visual representation. */ public class KeyboardCanvas extends JComponent implements KeyboardDispatcher.OnKeyListener { - private final static int bw = 45; // button width + private final static int bw = 42; // button width private final static int bh = 33; // button height private final static int bsw = 70; // backspace width private final static int tabw = 60; // tab width private final static int lshiftw = 55; // left shift width - private final static int brakew = 300; // break width + private final static int brakew = 270; // break width private final static int s = 5; // space between buttons + private final static double sHalf = s / 2.0; // space between buttons private final static int arc = 15; // arc radius private final static int margin = 10; - private final static int rshiftw = 3 * bw - 3 * s - margin; // right shift width + private final static int rshiftw = 3 * bw - 3 * s - margin + (int)sHalf; // right shift width - public final static int KEYBOARD_WIDTH = 13 * (bw + s) + 10 + bsw + 10; - public final static int KEYBOARD_HEIGHT = 5 * (bh + s) + 2 * margin; + public final static int KEYBOARD_WIDTH = 13 * (bw + s) + bsw + 10 + 10; + public final static int KEYBOARD_HEIGHT = 5 * (bh + s) + 2 * margin - s; private final static int X_SHIFT = (int) ((ZOOM * SCREEN_IMAGE_WIDTH + 2 * MARGIN - KEYBOARD_WIDTH) / 2.0); private final static int X_SHIFT_L = X_SHIFT + margin; private final static int Y_SHIFT_T = margin; - - private final static Color USABLE_BUTTON_COLOR = Color.LIGHT_GRAY; - + private final static int STROKE_WIDTH = 3; private final static double[][] KEY_MAP = new double[][]{ new double[]{bw + s + bw / 2.0, bh}, // 1 @@ -47,7 +46,7 @@ public class KeyboardCanvas extends JComponent implements KeyboardDispatcher.OnK new double[]{bw + s, 0}, // 8 new double[]{bw + s, 0}, // 9 new double[]{bw + s, 0}, // 0, - new double[]{-(11 * bw + s) + tabw + s, bh + s}, // Q + new double[]{-(11 * bw + s) + tabw + sHalf, bh + s}, // Q new double[]{bw + s, 0}, // W new double[]{bw + s, 0}, // E new double[]{bw + s, 0}, // R @@ -57,7 +56,7 @@ public class KeyboardCanvas extends JComponent implements KeyboardDispatcher.OnK new double[]{bw + s, 0}, // I new double[]{bw + s, 0}, // O new double[]{bw + s, 0}, // P - new double[]{-(10 * bw + s) - tabw + bsw + s, bh + s}, // A + new double[]{-(10 * bw + s) - tabw + bsw + sHalf, bh + s}, // A new double[]{bw + s, 0}, // S new double[]{bw + s, 0}, // D new double[]{bw + s, 0}, // F @@ -101,25 +100,35 @@ public class KeyboardCanvas extends JComponent implements KeyboardDispatcher.OnK "SHIFT", ":", "£", "?", "/", "*", ",", ".", "SHIFT", "SYM", "SYM" }; - private final BasicStroke outlineStroke = new BasicStroke(3.0f); + private final BasicStroke outlineStroke = new BasicStroke(STROKE_WIDTH); + private final Color usableButtonColor; + private final Color outlineColor; + private final Color brightColor; private boolean symShift = false; private boolean shift = false; - public KeyboardCanvas() { + public KeyboardCanvas(int alpha) { setDoubleBuffered(true); + this.usableButtonColor = new Color( + Color.LIGHT_GRAY.getRed(), + Color.LIGHT_GRAY.getGreen(), + Color.LIGHT_GRAY.getBlue(), alpha); + this.outlineColor = new Color(0, 0, 0, alpha); + this.brightColor = new Color(255, 255, 255, alpha); } @Override - public void onKeyEvent(KeyEvent e) { + public boolean onKeyEvent(KeyEvent e) { boolean pressed = e.getID() == KEY_PRESSED; if (!pressed && e.getID() != KEY_RELEASED) { - return; + return false; } symShift = (e.getModifiersEx() & (KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)) != 0; shift = (e.getModifiersEx() & (KeyEvent.SHIFT_DOWN_MASK)) != 0; repaint(); + return true; } public void paint(Graphics g) { @@ -133,7 +142,7 @@ public void paint(Graphics g) { g2d.setFont(new Font("SansSerif", Font.PLAIN, 11)); g2d.setStroke(outlineStroke); - g2d.setColor(Color.WHITE); + g2d.setColor(brightColor); g2d.translate(X_SHIFT_L, 0); for (int i = 0; i < KEY_MAP.length; i++) { @@ -152,7 +161,7 @@ public void paint(Graphics g) { int sw = g2d.getFontMetrics().stringWidth(text); g2d.translate(KEY_MAP[i][0] - sw / 2.0, KEY_MAP[i][1]); - g2d.setColor(Color.BLACK); + g2d.setColor(outlineColor); g2d.fill(textShape); g2d.translate(sw / 2.0, 0); } @@ -163,14 +172,15 @@ private void drawKeyboard(Graphics2D g) { // keyboard shape g.setStroke(stroke); - g.drawRoundRect(X_SHIFT, 0, KEYBOARD_WIDTH, KEYBOARD_HEIGHT, arc, arc); + g.setColor(outlineColor); + g.drawRoundRect(X_SHIFT, -STROKE_WIDTH, KEYBOARD_WIDTH, KEYBOARD_HEIGHT, arc, arc); // top row for (int i = 0; i < 13; i++) { if (i >= 1 && i <= 10) { - g.setColor(USABLE_BUTTON_COLOR); + g.setColor(usableButtonColor); g.fillRoundRect(X_SHIFT_L + i * (bw + s), Y_SHIFT_T, bw, bh, arc, arc); - g.setColor(Color.BLACK); + g.setColor(outlineColor); } g.drawRoundRect(X_SHIFT_L + i * (bw + s), Y_SHIFT_T, bw, bh, arc, arc); } @@ -183,9 +193,9 @@ private void drawKeyboard(Graphics2D g) { g.drawRoundRect(X_SHIFT_L, y1, tabw, bh, arc, arc); for (int i = 0; i < 12; i++) { if (i < 10) { - g.setColor(USABLE_BUTTON_COLOR); + g.setColor(usableButtonColor); g.fillRoundRect(X_SHIFT_L + i * (bw + s) + tabw + s, y1, bw, bh, arc, arc); - g.setColor(Color.BLACK); + g.setColor(outlineColor); } g.drawRoundRect(X_SHIFT_L + i * (bw + s) + tabw + s, y1, bw, bh, arc, arc); } @@ -194,14 +204,14 @@ private void drawKeyboard(Graphics2D g) { int x0 = X_SHIFT_L + 12 * (bw + s) + tabw + s; int y0 = Y_SHIFT_T + bh + s; Polygon enterPolygon = new Polygon( - new int[]{x0, x0 + tabw - s, x0 + tabw - s, x0 + 2 * s, x0 + 2 * s, x0}, + new int[]{x0, x0 + tabw - 2 * s, x0 + tabw - 2 * s, x0 + 2 * s, x0 + 2 * s, x0}, new int[]{y0, y0, y0 + 2 * bh + s, y0 + 2 * bh + s, y0 + bh, y0 + bh}, 6 ); - g.setColor(USABLE_BUTTON_COLOR); + g.setColor(usableButtonColor); g.fillPolygon(enterPolygon); - g.setColor(Color.BLACK); + g.setColor(outlineColor); g.drawPolygon(enterPolygon); // caps lock @@ -209,9 +219,9 @@ private void drawKeyboard(Graphics2D g) { g.drawRoundRect(X_SHIFT_L, y2, bsw, bh, arc, arc); for (int i = 0; i < 12; i++) { if (i < 9) { - g.setColor(USABLE_BUTTON_COLOR); + g.setColor(usableButtonColor); g.fillRoundRect(X_SHIFT_L + i * (bw + s) + bsw + s, y2, bw, bh, arc, arc); - g.setColor(Color.BLACK); + g.setColor(outlineColor); } g.drawRoundRect(X_SHIFT_L + i * (bw + s) + bsw + s, y2, bw, bh, arc, arc); } @@ -219,41 +229,41 @@ private void drawKeyboard(Graphics2D g) { // l shift int y3 = Y_SHIFT_T + (bh + s) * 3; - g.setColor(USABLE_BUTTON_COLOR); + g.setColor(usableButtonColor); g.fillRoundRect(X_SHIFT_L, y3, lshiftw, bh, arc, arc); - g.setColor(Color.BLACK); + g.setColor(outlineColor); g.drawRoundRect(X_SHIFT_L, y3, lshiftw, bh, arc, arc); for (int i = 0; i < 11; i++) { if (i >= 1 && i < 8) { - g.setColor(USABLE_BUTTON_COLOR); + g.setColor(usableButtonColor); g.fillRoundRect(X_SHIFT_L + i * (bw + s) + lshiftw + s, y3, bw, bh, arc, arc); - g.setColor(Color.BLACK); + g.setColor(outlineColor); } g.drawRoundRect(X_SHIFT_L + i * (bw + s) + lshiftw + s, y3, bw, bh, arc, arc); } - g.setColor(USABLE_BUTTON_COLOR); + g.setColor(usableButtonColor); g.fillRoundRect(X_SHIFT_L + 11 * (bw + s) + lshiftw + s, y3, rshiftw, bh, arc, arc); - g.setColor(Color.BLACK); + g.setColor(outlineColor); g.drawRoundRect(X_SHIFT_L + 11 * (bw + s) + lshiftw + s, y3, rshiftw, bh, arc, arc); // l ctrl int y4 = Y_SHIFT_T + (bh + s) * 4; - g.setColor(USABLE_BUTTON_COLOR); + g.setColor(usableButtonColor); g.fillRoundRect(X_SHIFT_L, y4, tabw, bh, arc, arc); - g.setColor(Color.BLACK); + g.setColor(outlineColor); g.drawRoundRect(X_SHIFT_L, y4, tabw, bh, arc, arc); g.drawRoundRect(X_SHIFT_L + tabw + s, y4, bw, bh, arc, arc); g.drawRoundRect(X_SHIFT_L + tabw + bw + 2 * s, y4, tabw, bh, arc, arc); - g.setColor(USABLE_BUTTON_COLOR); + g.setColor(usableButtonColor); g.fillRoundRect(X_SHIFT_L + 2 * (tabw + s) + bw + 2 * s, y4, brakew, bh, arc, arc); - g.setColor(Color.BLACK); + g.setColor(outlineColor); g.drawRoundRect(X_SHIFT_L + 2 * (tabw + s) + bw + 2 * s, y4, brakew, bh, arc, arc); g.drawRoundRect(X_SHIFT_L + 2 * (tabw + s) + bw + 4 * s + brakew, y4, tabw, bh, arc, arc); - g.setColor(USABLE_BUTTON_COLOR); + g.setColor(usableButtonColor); g.fillRoundRect(X_SHIFT_L + 3 * (tabw + s) + bw + 4 * s + brakew, y4, bw, bh, arc, arc); - g.setColor(Color.BLACK); + g.setColor(outlineColor); g.drawRoundRect(X_SHIFT_L + 3 * (tabw + s) + bw + 4 * s + brakew, y4, bw, bh, arc, arc); // RCTRL g.drawRoundRect(X_SHIFT_L + 3 * (tabw + s) + 2 * bw + 5 * s + brakew, y4, bw, bh, arc, arc); g.drawRoundRect(X_SHIFT_L + 3 * (tabw + s) + 3 * bw + 6 * s + brakew, y4, tabw, bh, arc, arc); diff --git a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardDispatcher.java b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardDispatcher.java index 3f313b463..bbb15e52a 100644 --- a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardDispatcher.java +++ b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardDispatcher.java @@ -32,16 +32,21 @@ public class KeyboardDispatcher implements AutoCloseable, KeyEventDispatcher { public interface OnKeyListener { - void onKeyEvent(KeyEvent e); + boolean onKeyEvent(KeyEvent e); } @Override public boolean dispatchKeyEvent(KeyEvent e) { boolean isConsumed = false; if (!e.isConsumed()) { - onKeyListeners.forEach(c -> c.onKeyEvent(e)); - e.consume(); - isConsumed = true; + boolean consumed = false; + for (OnKeyListener listener : onKeyListeners) { + consumed |= listener.onKeyEvent(e); + } + if (consumed) { + e.consume(); + isConsumed = true; + } } return isConsumed; } From 3868b534cc0262dd9f272bd02a26a6e85fd5e272 Mon Sep 17 00:00:00 2001 From: Peter Jakubco Date: Mon, 3 Jun 2024 09:50:01 +0200 Subject: [PATCH 3/4] [#314] Add keyboard opacity to ZX ULA --- .../application/gui/dialogs/EditorPanel.java | 1 - .../zxspectrum/ula/gui/DisplayWindow.java | 24 ++++++- .../zxspectrum/ula/gui/KeyboardCanvas.java | 67 ++++++++++++------- 3 files changed, 64 insertions(+), 28 deletions(-) diff --git a/application/src/main/java/net/emustudio/application/gui/dialogs/EditorPanel.java b/application/src/main/java/net/emustudio/application/gui/dialogs/EditorPanel.java index 4ba7c313c..25e46ff03 100644 --- a/application/src/main/java/net/emustudio/application/gui/dialogs/EditorPanel.java +++ b/application/src/main/java/net/emustudio/application/gui/dialogs/EditorPanel.java @@ -18,7 +18,6 @@ */ package net.emustudio.application.gui.dialogs; -import net.emustudio.application.Constants; import net.emustudio.application.gui.actions.CompileAction; import net.emustudio.application.gui.actions.editor.*; import net.emustudio.application.gui.editor.Editor; diff --git a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java index 7426ab332..aef8d64b4 100644 --- a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java +++ b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java @@ -21,6 +21,7 @@ import net.emustudio.plugins.device.zxspectrum.ula.ULA; import javax.swing.*; +import javax.swing.border.BevelBorder; import java.awt.*; import java.awt.event.WindowEvent; @@ -34,10 +35,11 @@ public class DisplayWindow extends JDialog { private final static int BOUND_Y = (int) (DisplayCanvas.ZOOM * SCREEN_IMAGE_HEIGHT + 2 * MARGIN); private final DisplayCanvas canvas; + private final KeyboardCanvas keyboardCanvas = new KeyboardCanvas(70); + private final JPanel statusBar = new JPanel(); public DisplayWindow(JFrame parent, ULA ula) { super(parent); - KeyboardCanvas keyboardCanvas = new KeyboardCanvas(70); this.canvas = new DisplayCanvas(ula, keyboardCanvas); initComponents(); @@ -70,16 +72,32 @@ private void initComponents() { setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); canvas.setBounds(MARGIN, MARGIN, BOUND_X, BOUND_Y); + statusBar.setLayout(new BoxLayout(statusBar, BoxLayout.X_AXIS)); + statusBar.setBorder(new BevelBorder(BevelBorder.LOWERED)); + + JLabel labelOpacity = new JLabel("Keyboard opacity:"); + labelOpacity.setHorizontalAlignment(SwingConstants.LEFT); + statusBar.add(labelOpacity); + + JSlider sliderOpacity = new JSlider(); + sliderOpacity.setMinimum(0); + sliderOpacity.setMaximum(100); + sliderOpacity.setValue(keyboardCanvas.getAlpha()); + sliderOpacity.addChangeListener(e -> keyboardCanvas.setAlpha(sliderOpacity.getValue())); + statusBar.add(sliderOpacity); + GroupLayout layout = new GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(canvas)); + .addComponent(canvas) + .addComponent(statusBar, GroupLayout.DEFAULT_SIZE, 407, Short.MAX_VALUE)); layout.setVerticalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(canvas, GroupLayout.DEFAULT_SIZE, 407, Short.MAX_VALUE) - .addContainerGap())); + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(statusBar, GroupLayout.PREFERRED_SIZE, 46, GroupLayout.PREFERRED_SIZE))); pack(); } diff --git a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java index 28c670d32..27085d2b2 100644 --- a/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java +++ b/plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java @@ -25,7 +25,7 @@ public class KeyboardCanvas extends JComponent implements KeyboardDispatcher.OnK private final static double sHalf = s / 2.0; // space between buttons private final static int arc = 15; // arc radius private final static int margin = 10; - private final static int rshiftw = 3 * bw - 3 * s - margin + (int)sHalf; // right shift width + private final static int rshiftw = 3 * bw - 3 * s - margin + (int) sHalf; // right shift width public final static int KEYBOARD_WIDTH = 13 * (bw + s) + bsw + 10 + 10; public final static int KEYBOARD_HEIGHT = 5 * (bh + s) + 2 * margin - s; @@ -104,12 +104,14 @@ public class KeyboardCanvas extends JComponent implements KeyboardDispatcher.OnK private final Color usableButtonColor; private final Color outlineColor; private final Color brightColor; + private int alpha; private boolean symShift = false; private boolean shift = false; public KeyboardCanvas(int alpha) { setDoubleBuffered(true); + this.alpha = alpha; this.usableButtonColor = new Color( Color.LIGHT_GRAY.getRed(), Color.LIGHT_GRAY.getGreen(), @@ -131,6 +133,14 @@ public boolean onKeyEvent(KeyEvent e) { return true; } + public int getAlpha() { + return alpha; + } + + public void setAlpha(int alpha) { + this.alpha = alpha; + } + public void paint(Graphics g) { Graphics2D g2d = (Graphics2D) g; // we must set RenderingHints before any drawing @@ -142,7 +152,7 @@ public void paint(Graphics g) { g2d.setFont(new Font("SansSerif", Font.PLAIN, 11)); g2d.setStroke(outlineStroke); - g2d.setColor(brightColor); + g2d.setColor(adjustAlpha(brightColor)); g2d.translate(X_SHIFT_L, 0); for (int i = 0; i < KEY_MAP.length; i++) { @@ -161,7 +171,7 @@ public void paint(Graphics g) { int sw = g2d.getFontMetrics().stringWidth(text); g2d.translate(KEY_MAP[i][0] - sw / 2.0, KEY_MAP[i][1]); - g2d.setColor(outlineColor); + g2d.setColor(adjustAlpha(outlineColor)); g2d.fill(textShape); g2d.translate(sw / 2.0, 0); } @@ -169,18 +179,20 @@ public void paint(Graphics g) { private void drawKeyboard(Graphics2D g) { BasicStroke stroke = new BasicStroke(2.0f); + Color adjUsableButtonColor = adjustAlpha(usableButtonColor); + Color adjOutlineColor = adjustAlpha(outlineColor); // keyboard shape g.setStroke(stroke); - g.setColor(outlineColor); + g.setColor(adjOutlineColor); g.drawRoundRect(X_SHIFT, -STROKE_WIDTH, KEYBOARD_WIDTH, KEYBOARD_HEIGHT, arc, arc); // top row for (int i = 0; i < 13; i++) { if (i >= 1 && i <= 10) { - g.setColor(usableButtonColor); + g.setColor(adjUsableButtonColor); g.fillRoundRect(X_SHIFT_L + i * (bw + s), Y_SHIFT_T, bw, bh, arc, arc); - g.setColor(outlineColor); + g.setColor(adjOutlineColor); } g.drawRoundRect(X_SHIFT_L + i * (bw + s), Y_SHIFT_T, bw, bh, arc, arc); } @@ -193,9 +205,9 @@ private void drawKeyboard(Graphics2D g) { g.drawRoundRect(X_SHIFT_L, y1, tabw, bh, arc, arc); for (int i = 0; i < 12; i++) { if (i < 10) { - g.setColor(usableButtonColor); + g.setColor(adjUsableButtonColor); g.fillRoundRect(X_SHIFT_L + i * (bw + s) + tabw + s, y1, bw, bh, arc, arc); - g.setColor(outlineColor); + g.setColor(adjOutlineColor); } g.drawRoundRect(X_SHIFT_L + i * (bw + s) + tabw + s, y1, bw, bh, arc, arc); } @@ -209,9 +221,9 @@ private void drawKeyboard(Graphics2D g) { 6 ); - g.setColor(usableButtonColor); + g.setColor(adjUsableButtonColor); g.fillPolygon(enterPolygon); - g.setColor(outlineColor); + g.setColor(adjOutlineColor); g.drawPolygon(enterPolygon); // caps lock @@ -219,9 +231,9 @@ private void drawKeyboard(Graphics2D g) { g.drawRoundRect(X_SHIFT_L, y2, bsw, bh, arc, arc); for (int i = 0; i < 12; i++) { if (i < 9) { - g.setColor(usableButtonColor); + g.setColor(adjUsableButtonColor); g.fillRoundRect(X_SHIFT_L + i * (bw + s) + bsw + s, y2, bw, bh, arc, arc); - g.setColor(outlineColor); + g.setColor(adjOutlineColor); } g.drawRoundRect(X_SHIFT_L + i * (bw + s) + bsw + s, y2, bw, bh, arc, arc); } @@ -229,43 +241,50 @@ private void drawKeyboard(Graphics2D g) { // l shift int y3 = Y_SHIFT_T + (bh + s) * 3; - g.setColor(usableButtonColor); + g.setColor(adjUsableButtonColor); g.fillRoundRect(X_SHIFT_L, y3, lshiftw, bh, arc, arc); - g.setColor(outlineColor); + g.setColor(adjOutlineColor); g.drawRoundRect(X_SHIFT_L, y3, lshiftw, bh, arc, arc); for (int i = 0; i < 11; i++) { if (i >= 1 && i < 8) { - g.setColor(usableButtonColor); + g.setColor(adjUsableButtonColor); g.fillRoundRect(X_SHIFT_L + i * (bw + s) + lshiftw + s, y3, bw, bh, arc, arc); - g.setColor(outlineColor); + g.setColor(adjOutlineColor); } g.drawRoundRect(X_SHIFT_L + i * (bw + s) + lshiftw + s, y3, bw, bh, arc, arc); } - g.setColor(usableButtonColor); + g.setColor(adjUsableButtonColor); g.fillRoundRect(X_SHIFT_L + 11 * (bw + s) + lshiftw + s, y3, rshiftw, bh, arc, arc); - g.setColor(outlineColor); + g.setColor(adjOutlineColor); g.drawRoundRect(X_SHIFT_L + 11 * (bw + s) + lshiftw + s, y3, rshiftw, bh, arc, arc); // l ctrl int y4 = Y_SHIFT_T + (bh + s) * 4; - g.setColor(usableButtonColor); + g.setColor(adjUsableButtonColor); g.fillRoundRect(X_SHIFT_L, y4, tabw, bh, arc, arc); - g.setColor(outlineColor); + g.setColor(adjOutlineColor); g.drawRoundRect(X_SHIFT_L, y4, tabw, bh, arc, arc); g.drawRoundRect(X_SHIFT_L + tabw + s, y4, bw, bh, arc, arc); g.drawRoundRect(X_SHIFT_L + tabw + bw + 2 * s, y4, tabw, bh, arc, arc); - g.setColor(usableButtonColor); + g.setColor(adjUsableButtonColor); g.fillRoundRect(X_SHIFT_L + 2 * (tabw + s) + bw + 2 * s, y4, brakew, bh, arc, arc); - g.setColor(outlineColor); + g.setColor(adjOutlineColor); g.drawRoundRect(X_SHIFT_L + 2 * (tabw + s) + bw + 2 * s, y4, brakew, bh, arc, arc); g.drawRoundRect(X_SHIFT_L + 2 * (tabw + s) + bw + 4 * s + brakew, y4, tabw, bh, arc, arc); - g.setColor(usableButtonColor); + g.setColor(adjUsableButtonColor); g.fillRoundRect(X_SHIFT_L + 3 * (tabw + s) + bw + 4 * s + brakew, y4, bw, bh, arc, arc); - g.setColor(outlineColor); + g.setColor(adjOutlineColor); g.drawRoundRect(X_SHIFT_L + 3 * (tabw + s) + bw + 4 * s + brakew, y4, bw, bh, arc, arc); // RCTRL g.drawRoundRect(X_SHIFT_L + 3 * (tabw + s) + 2 * bw + 5 * s + brakew, y4, bw, bh, arc, arc); g.drawRoundRect(X_SHIFT_L + 3 * (tabw + s) + 3 * bw + 6 * s + brakew, y4, tabw, bh, arc, arc); } + + private Color adjustAlpha(Color color) { + int r = color.getRed(); + int g = color.getGreen(); + int b = color.getBlue(); + return new Color(r, g, b, this.alpha); + } } From 156666ba869a34526539e2e185cb5346c725a9f4 Mon Sep 17 00:00:00 2001 From: Peter Jakubco Date: Thu, 14 Aug 2025 17:43:07 +0200 Subject: [PATCH 4/4] UTF-8 reading of files in compilers --- .../emustudio/application/cmdline/Runner.java | 3 +++ .../compiler/as8080/Assembler8080.java | 4 +++- .../plugins/compiler/ssem/SSEMCompiler.java | 4 +++- .../plugins/compiler/asZ80/AssemblerZ80.java | 4 +++- .../compiler/brainduck/CompilerBrainduck.java | 4 +++- .../plugins/compiler/ram/CompilerRAM.java | 4 +++- .../plugins/compiler/rasp/CompilerRASP.java | 4 +++- .../device/mits88dcdd/cmdline/Cpmfs.java | 4 +++- .../device/audiotape_player/gui/.DS_Store | Bin 6148 -> 0 bytes .../plugins/device/simh/commands/ReadURL.java | 2 ++ .../zxspectrum/ula/gui/DisplayWindow.java | 19 ++++++++++++------ .../plugins/memory/ram/MemoryContextImpl.java | 9 +++------ .../memory/rasp/MemoryContextImpl.java | 9 +++------ 13 files changed, 45 insertions(+), 25 deletions(-) delete mode 100644 plugins/device/audiotape-player/src/main/resources/net/emustudio/plugins/device/audiotape_player/gui/.DS_Store diff --git a/application/src/main/java/net/emustudio/application/cmdline/Runner.java b/application/src/main/java/net/emustudio/application/cmdline/Runner.java index 3a4a2a4de..2f5334198 100644 --- a/application/src/main/java/net/emustudio/application/cmdline/Runner.java +++ b/application/src/main/java/net/emustudio/application/cmdline/Runner.java @@ -54,10 +54,13 @@ public class Runner implements Runnable { private static final Logger LOGGER = LoggerFactory.getLogger(Runner.class); // if a command is being run, default behavior is: do nothing private static boolean runsSomeCommand; + @CommandLine.ArgGroup(heading = "Virtual computer%n") public Exclusive exclusive; + @CommandLine.Option(names = {"-i", "--input-file"}, description = "input file name (source code)", paramLabel = "FILE") public Path inputFile; + @CommandLine.Option(names = {"-cl", "--computers-list"}, description = "list all existing virtual computers") private boolean listConfigs; diff --git a/plugins/compiler/as-8080/src/main/java/net/emustudio/plugins/compiler/as8080/Assembler8080.java b/plugins/compiler/as-8080/src/main/java/net/emustudio/plugins/compiler/as8080/Assembler8080.java index 91d807c57..ba96d1e76 100644 --- a/plugins/compiler/as-8080/src/main/java/net/emustudio/plugins/compiler/as8080/Assembler8080.java +++ b/plugins/compiler/as-8080/src/main/java/net/emustudio/plugins/compiler/as8080/Assembler8080.java @@ -43,6 +43,8 @@ import java.io.FileReader; import java.io.IOException; import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.MissingResourceException; @@ -111,7 +113,7 @@ public void compile(Path inputPath, Optional outputPath) { notifyInfo(getTitle() + ", version " + getVersion()); Path finalOutputPath = outputPath.orElse(convertInputToOutputPath(inputPath, ".hex")); - try (Reader reader = new FileReader(inputPath.toFile())) { + try (Reader reader = Files.newBufferedReader(inputPath, StandardCharsets.UTF_8)) { org.antlr.v4.runtime.Lexer lexer = createLexer(CharStreams.fromReader(reader)); lexer.addErrorListener(new ParserErrorListener(inputPath.toString())); CommonTokenStream tokens = new CommonTokenStream(lexer); diff --git a/plugins/compiler/as-ssem/src/main/java/net/emustudio/plugins/compiler/ssem/SSEMCompiler.java b/plugins/compiler/as-ssem/src/main/java/net/emustudio/plugins/compiler/ssem/SSEMCompiler.java index 771eb2a8e..306fd35ff 100644 --- a/plugins/compiler/as-ssem/src/main/java/net/emustudio/plugins/compiler/ssem/SSEMCompiler.java +++ b/plugins/compiler/as-ssem/src/main/java/net/emustudio/plugins/compiler/ssem/SSEMCompiler.java @@ -42,6 +42,8 @@ import java.io.IOException; import java.io.Reader; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.MissingResourceException; @@ -88,7 +90,7 @@ public void compile(Path inputPath, Optional outputPath) { notifyInfo(getTitle() + ", version " + getVersion()); Path finalOutputPath = outputPath.orElse(convertInputToOutputPath(inputPath, ".bssem")); - try (Reader reader = new FileReader(inputPath.toFile())) { + try (Reader reader = Files.newBufferedReader(inputPath, StandardCharsets.UTF_8)) { Lexer lexer = createLexer(CharStreams.fromReader(reader)); lexer.addErrorListener(new ParserErrorListener(inputPath.toString())); CommonTokenStream tokens = new CommonTokenStream(lexer); diff --git a/plugins/compiler/as-z80/src/main/java/net/emustudio/plugins/compiler/asZ80/AssemblerZ80.java b/plugins/compiler/as-z80/src/main/java/net/emustudio/plugins/compiler/asZ80/AssemblerZ80.java index b7f645d3e..70211a99d 100644 --- a/plugins/compiler/as-z80/src/main/java/net/emustudio/plugins/compiler/asZ80/AssemblerZ80.java +++ b/plugins/compiler/as-z80/src/main/java/net/emustudio/plugins/compiler/asZ80/AssemblerZ80.java @@ -43,6 +43,8 @@ import java.io.FileReader; import java.io.IOException; import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.MissingResourceException; @@ -111,7 +113,7 @@ public void compile(Path inputPath, Optional outputPath) { notifyInfo(getTitle() + ", version " + getVersion()); Path finalOutputPath = outputPath.orElse(convertInputToOutputPath(inputPath, ".hex")); - try (Reader reader = new FileReader(inputPath.toFile())) { + try (Reader reader = Files.newBufferedReader(inputPath, StandardCharsets.UTF_8)) { AsZ80Lexer lexer = createLexer(CharStreams.fromReader(reader)); lexer.addErrorListener(new ParserErrorListener(inputPath.toString())); CommonTokenStream tokens = new CommonTokenStream(lexer); diff --git a/plugins/compiler/brainc-brainduck/src/main/java/net/emustudio/plugins/compiler/brainduck/CompilerBrainduck.java b/plugins/compiler/brainc-brainduck/src/main/java/net/emustudio/plugins/compiler/brainduck/CompilerBrainduck.java index de49a7090..41ce14e55 100644 --- a/plugins/compiler/brainc-brainduck/src/main/java/net/emustudio/plugins/compiler/brainduck/CompilerBrainduck.java +++ b/plugins/compiler/brainc-brainduck/src/main/java/net/emustudio/plugins/compiler/brainduck/CompilerBrainduck.java @@ -41,6 +41,8 @@ import java.io.FileReader; import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -135,7 +137,7 @@ private IntelHEX compileToHex(Path inputPath) throws Exception { Objects.requireNonNull(inputPath); notifyInfo(getTitle() + ", version " + getVersion()); - try (Reader reader = new FileReader(inputPath.toFile())) { + try (Reader reader = Files.newBufferedReader(inputPath, StandardCharsets.UTF_8)) { org.antlr.v4.runtime.Lexer lexer = createLexer(CharStreams.fromReader(reader)); lexer.addErrorListener(new ParserErrorListener()); CommonTokenStream tokens = new CommonTokenStream(lexer); diff --git a/plugins/compiler/ramc-ram/src/main/java/net/emustudio/plugins/compiler/ram/CompilerRAM.java b/plugins/compiler/ramc-ram/src/main/java/net/emustudio/plugins/compiler/ram/CompilerRAM.java index fac8060eb..0d62ec713 100644 --- a/plugins/compiler/ramc-ram/src/main/java/net/emustudio/plugins/compiler/ram/CompilerRAM.java +++ b/plugins/compiler/ramc-ram/src/main/java/net/emustudio/plugins/compiler/ram/CompilerRAM.java @@ -38,6 +38,8 @@ import java.io.FileReader; import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.MissingResourceException; @@ -90,7 +92,7 @@ public void compile(Path inputPath, Optional outputPath) { notifyInfo(getTitle() + ", version " + getVersion()); Path finalOutputPath = outputPath.orElse(convertInputToOutputPath(inputPath, ".bram")); - try (Reader reader = new FileReader(inputPath.toFile())) { + try (Reader reader = Files.newBufferedReader(inputPath, StandardCharsets.UTF_8)) { org.antlr.v4.runtime.Lexer lexer = createLexer(CharStreams.fromReader(reader)); lexer.addErrorListener(new ParserErrorListener()); CommonTokenStream tokens = new CommonTokenStream(lexer); diff --git a/plugins/compiler/raspc-rasp/src/main/java/net/emustudio/plugins/compiler/rasp/CompilerRASP.java b/plugins/compiler/raspc-rasp/src/main/java/net/emustudio/plugins/compiler/rasp/CompilerRASP.java index 754737c00..71d83447a 100644 --- a/plugins/compiler/raspc-rasp/src/main/java/net/emustudio/plugins/compiler/rasp/CompilerRASP.java +++ b/plugins/compiler/raspc-rasp/src/main/java/net/emustudio/plugins/compiler/rasp/CompilerRASP.java @@ -40,6 +40,8 @@ import java.io.FileReader; import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -77,7 +79,7 @@ public void compile(Path inputPath, Optional outputPathX) { notifyInfo(getTitle() + ", version " + getVersion()); Path finalOutputPath = outputPathX.orElse(convertInputToOutputPath(inputPath, ".brasp")); - try (Reader reader = new FileReader(inputPath.toFile())) { + try (Reader reader = Files.newBufferedReader(inputPath, StandardCharsets.UTF_8)) { org.antlr.v4.runtime.Lexer lexer = createLexer(CharStreams.fromReader(reader)); lexer.addErrorListener(new ParserErrorListener()); CommonTokenStream tokens = new CommonTokenStream(lexer); diff --git a/plugins/device/88-dcdd/src/main/java/net/emustudio/plugins/device/mits88dcdd/cmdline/Cpmfs.java b/plugins/device/88-dcdd/src/main/java/net/emustudio/plugins/device/mits88dcdd/cmdline/Cpmfs.java index fe0875c27..9b114b458 100644 --- a/plugins/device/88-dcdd/src/main/java/net/emustudio/plugins/device/mits88dcdd/cmdline/Cpmfs.java +++ b/plugins/device/88-dcdd/src/main/java/net/emustudio/plugins/device/mits88dcdd/cmdline/Cpmfs.java @@ -27,6 +27,8 @@ import picocli.CommandLine.ParentCommand; import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.List; import java.util.Locale; @@ -83,7 +85,7 @@ public void copy(@Parameters(paramLabel = "SRC_FILE", index = "0", description = if (srcInCpm) { content.append(cpmfs.readFile(realSrc)); } else { - try (Reader reader = new FileReader(realSrc)) { + try (Reader reader = Files.newBufferedReader(new File(realSrc).toPath(), StandardCharsets.UTF_8)) { reader.transferTo(content); } } diff --git a/plugins/device/audiotape-player/src/main/resources/net/emustudio/plugins/device/audiotape_player/gui/.DS_Store b/plugins/device/audiotape-player/src/main/resources/net/emustudio/plugins/device/audiotape_player/gui/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 keyboardCanvas.setAlpha(sliderOpacity.getValue())); statusBar.add(sliderOpacity); + JLabel lblOpacityPercent = new JLabel(keyboardCanvas.getAlpha() + "%"); + statusBar.add(lblOpacityPercent); + sliderOpacity.addChangeListener(e -> { + int value = sliderOpacity.getValue(); + keyboardCanvas.setAlpha(value); + lblOpacityPercent.setText(value + "%"); + }); + GroupLayout layout = new GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(canvas) - .addComponent(statusBar, GroupLayout.DEFAULT_SIZE, 407, Short.MAX_VALUE)); + .addComponent(statusBar, GroupLayout.DEFAULT_SIZE, 400, 400)); // TODO: gap? layout.setVerticalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() diff --git a/plugins/memory/ram-mem/src/main/java/net/emustudio/plugins/memory/ram/MemoryContextImpl.java b/plugins/memory/ram-mem/src/main/java/net/emustudio/plugins/memory/ram/MemoryContextImpl.java index af3c3f369..c3bec6e10 100644 --- a/plugins/memory/ram-mem/src/main/java/net/emustudio/plugins/memory/ram/MemoryContextImpl.java +++ b/plugins/memory/ram-mem/src/main/java/net/emustudio/plugins/memory/ram/MemoryContextImpl.java @@ -135,10 +135,9 @@ public void setInputs(List inputs) { @SuppressWarnings("unchecked") public void deserialize(String filename) throws IOException, ClassNotFoundException { rwl.lockWrite(() -> { - try { - InputStream file = new FileInputStream(filename); - InputStream buffer = new BufferedInputStream(file); - ObjectInput input = new ObjectInputStream(buffer); + try (InputStream file = new FileInputStream(filename); + InputStream buffer = new BufferedInputStream(file); + ObjectInput input = new ObjectInputStream(buffer)) { labels.clear(); inputs.clear(); @@ -161,8 +160,6 @@ public String getLabel() { inputs.addAll((List) input.readObject()); memory.putAll((Map) input.readObject()); - - input.close(); } finally { notifyMemoryContentChanged(-1); notifyMemorySizeChanged(); diff --git a/plugins/memory/rasp-mem/src/main/java/net/emustudio/plugins/memory/rasp/MemoryContextImpl.java b/plugins/memory/rasp-mem/src/main/java/net/emustudio/plugins/memory/rasp/MemoryContextImpl.java index b615e3bc7..26887306b 100644 --- a/plugins/memory/rasp-mem/src/main/java/net/emustudio/plugins/memory/rasp/MemoryContextImpl.java +++ b/plugins/memory/rasp-mem/src/main/java/net/emustudio/plugins/memory/rasp/MemoryContextImpl.java @@ -141,10 +141,9 @@ public RaspMemory getSnapshot() { @SuppressWarnings("unchecked") public void deserialize(String filename, Consumer setProgramLocation) throws IOException, ClassNotFoundException { rwl.lockWrite(() -> { - try { - InputStream file = new FileInputStream(filename); - InputStream buffer = new BufferedInputStream(file); - ObjectInput input = new ObjectInputStream(buffer); + try (InputStream file = new FileInputStream(filename); + InputStream buffer = new BufferedInputStream(file); + ObjectInput input = new ObjectInputStream(buffer)) { labels.clear(); inputs.clear(); @@ -170,8 +169,6 @@ public String getLabel() { inputs.addAll((List) input.readObject()); memory.putAll((Map) input.readObject()); - - input.close(); } finally { notifyMemorySizeChanged(); notifyMemoryContentChanged(-1);