Skip to content

Commit 739a32b

Browse files
committed
[#314] ZX Keyboard inside draw canvas
1 parent bf2e396 commit 739a32b

File tree

5 files changed

+80
-59
lines changed

5 files changed

+80
-59
lines changed

plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/ULA.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -253,18 +253,18 @@ public String toString() {
253253
}
254254

255255
@Override
256-
public void onKeyEvent(KeyEvent e) {
256+
public boolean onKeyEvent(KeyEvent e) {
257257
boolean pressed = e.getID() == KEY_PRESSED;
258258
if (!pressed && e.getID() != KEY_RELEASED) {
259-
return;
259+
return false;
260260
}
261261
BiConsumer<Byte, Byte> keySet = pressed ? this::andKeyMap : this::orKeyMap;
262262
BiConsumer<Byte, Byte> keyUnset = pressed ? this::orKeyMap : this::andKeyMap;
263263

264264
// shift / alt / ctrl are visible in modifiersEx only if pressed = true
265265
boolean symShift = (e.getModifiersEx() & (KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)) != 0;
266266
boolean shift = (e.getModifiersEx() & (KeyEvent.SHIFT_DOWN_MASK)) != 0;
267-
267+
268268
Byte[] command = CHAR_MAPPING.get(e.getKeyCode());
269269
if (command != null) {
270270
if (command[2] == 1 || (command[2] == -1 && shift)) {
@@ -291,6 +291,7 @@ public void onKeyEvent(KeyEvent e) {
291291
keyUnset.accept(KEY_SYM_SHIFT[0], KEY_SYM_SHIFT[1]);
292292
}
293293
}
294+
return true;
294295
}
295296

296297
private void andKeyMap(byte key, byte value) {

plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayCanvas.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,11 @@ public class DisplayCanvas extends Canvas implements AutoCloseable {
6464

6565
private final ULA ula;
6666
private final PaintCycle paintCycle = new PaintCycle();
67+
private final KeyboardCanvas keyboardCanvas;
6768

68-
public DisplayCanvas(ULA ula) {
69+
public DisplayCanvas(ULA ula, KeyboardCanvas keyboardCanvas) {
6970
this.ula = Objects.requireNonNull(ula);
71+
this.keyboardCanvas = Objects.requireNonNull(keyboardCanvas);
7072
this.screenImage.setAccelerationPriority(1.0f);
7173
this.screenImageData = ((DataBufferInt) this.screenImage.getRaster().getDataBuffer()).getData();
7274
}
@@ -185,6 +187,13 @@ protected void paint() {
185187
graphics.drawImage(
186188
screenImage, MARGIN, MARGIN,
187189
(int) (SCREEN_IMAGE_WIDTH * ZOOM), (int) (SCREEN_IMAGE_HEIGHT * ZOOM), null);
190+
191+
Color color = graphics.getColor();
192+
graphics.setColor(new Color(0, 0, 0, 127));
193+
graphics.translate(0, SCREEN_IMAGE_HEIGHT * ZOOM - KeyboardCanvas.KEYBOARD_HEIGHT + MARGIN);
194+
keyboardCanvas.paint(graphics);
195+
graphics.setColor(color);
196+
188197
graphics.dispose();
189198

190199
} while (strategy.contentsRestored());

plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/DisplayWindow.java

+9-13
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,17 @@
2828
import static net.emustudio.plugins.device.zxspectrum.ula.ZxParameters.SCREEN_IMAGE_WIDTH;
2929

3030
public class DisplayWindow extends JDialog {
31-
private final DisplayCanvas canvas;
32-
private final KeyboardCanvas keyboardCanvas;
33-
3431
public final static int MARGIN = 30;
3532

33+
private final static int BOUND_X = (int) (DisplayCanvas.ZOOM * SCREEN_IMAGE_WIDTH + 2 * MARGIN);
34+
private final static int BOUND_Y = (int) (DisplayCanvas.ZOOM * SCREEN_IMAGE_HEIGHT + 2 * MARGIN);
35+
36+
private final DisplayCanvas canvas;
37+
3638
public DisplayWindow(JFrame parent, ULA ula) {
3739
super(parent);
38-
this.canvas = new DisplayCanvas(ula);
39-
this.keyboardCanvas = new KeyboardCanvas();
40+
KeyboardCanvas keyboardCanvas = new KeyboardCanvas(70);
41+
this.canvas = new DisplayCanvas(ula, keyboardCanvas);
4042

4143
initComponents();
4244
setLocationRelativeTo(parent);
@@ -66,23 +68,17 @@ public void destroy() {
6668
private void initComponents() {
6769
setTitle("ZX Spectrum48K");
6870
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
69-
canvas.setBounds(
70-
MARGIN, MARGIN,
71-
(int) (DisplayCanvas.ZOOM * SCREEN_IMAGE_WIDTH + 2 * MARGIN),
72-
(int) (DisplayCanvas.ZOOM * SCREEN_IMAGE_HEIGHT + 2 * MARGIN));
71+
canvas.setBounds(MARGIN, MARGIN, BOUND_X, BOUND_Y);
7372

7473
GroupLayout layout = new GroupLayout(getContentPane());
7574
getContentPane().setLayout(layout);
7675
layout.setHorizontalGroup(
7776
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
78-
.addComponent(canvas)
79-
.addComponent(keyboardCanvas));
77+
.addComponent(canvas));
8078
layout.setVerticalGroup(
8179
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
8280
.addGroup(layout.createSequentialGroup()
8381
.addComponent(canvas, GroupLayout.DEFAULT_SIZE, 407, Short.MAX_VALUE)
84-
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
85-
.addComponent(keyboardCanvas, GroupLayout.DEFAULT_SIZE, KeyboardCanvas.KEYBOARD_HEIGHT + 3, Short.MAX_VALUE)
8682
.addContainerGap()));
8783
pack();
8884
}

plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardCanvas.java

+48-38
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,25 @@
1515
* Host-ZX Keyboard mapping visual representation.
1616
*/
1717
public class KeyboardCanvas extends JComponent implements KeyboardDispatcher.OnKeyListener {
18-
private final static int bw = 45; // button width
18+
private final static int bw = 42; // button width
1919
private final static int bh = 33; // button height
2020
private final static int bsw = 70; // backspace width
2121
private final static int tabw = 60; // tab width
2222
private final static int lshiftw = 55; // left shift width
23-
private final static int brakew = 300; // break width
23+
private final static int brakew = 270; // break width
2424
private final static int s = 5; // space between buttons
25+
private final static double sHalf = s / 2.0; // space between buttons
2526
private final static int arc = 15; // arc radius
2627
private final static int margin = 10;
27-
private final static int rshiftw = 3 * bw - 3 * s - margin; // right shift width
28+
private final static int rshiftw = 3 * bw - 3 * s - margin + (int)sHalf; // right shift width
2829

29-
public final static int KEYBOARD_WIDTH = 13 * (bw + s) + 10 + bsw + 10;
30-
public final static int KEYBOARD_HEIGHT = 5 * (bh + s) + 2 * margin;
30+
public final static int KEYBOARD_WIDTH = 13 * (bw + s) + bsw + 10 + 10;
31+
public final static int KEYBOARD_HEIGHT = 5 * (bh + s) + 2 * margin - s;
3132

3233
private final static int X_SHIFT = (int) ((ZOOM * SCREEN_IMAGE_WIDTH + 2 * MARGIN - KEYBOARD_WIDTH) / 2.0);
3334
private final static int X_SHIFT_L = X_SHIFT + margin;
3435
private final static int Y_SHIFT_T = margin;
35-
36-
private final static Color USABLE_BUTTON_COLOR = Color.LIGHT_GRAY;
37-
36+
private final static int STROKE_WIDTH = 3;
3837

3938
private final static double[][] KEY_MAP = new double[][]{
4039
new double[]{bw + s + bw / 2.0, bh}, // 1
@@ -47,7 +46,7 @@ public class KeyboardCanvas extends JComponent implements KeyboardDispatcher.OnK
4746
new double[]{bw + s, 0}, // 8
4847
new double[]{bw + s, 0}, // 9
4948
new double[]{bw + s, 0}, // 0,
50-
new double[]{-(11 * bw + s) + tabw + s, bh + s}, // Q
49+
new double[]{-(11 * bw + s) + tabw + sHalf, bh + s}, // Q
5150
new double[]{bw + s, 0}, // W
5251
new double[]{bw + s, 0}, // E
5352
new double[]{bw + s, 0}, // R
@@ -57,7 +56,7 @@ public class KeyboardCanvas extends JComponent implements KeyboardDispatcher.OnK
5756
new double[]{bw + s, 0}, // I
5857
new double[]{bw + s, 0}, // O
5958
new double[]{bw + s, 0}, // P
60-
new double[]{-(10 * bw + s) - tabw + bsw + s, bh + s}, // A
59+
new double[]{-(10 * bw + s) - tabw + bsw + sHalf, bh + s}, // A
6160
new double[]{bw + s, 0}, // S
6261
new double[]{bw + s, 0}, // D
6362
new double[]{bw + s, 0}, // F
@@ -101,25 +100,35 @@ public class KeyboardCanvas extends JComponent implements KeyboardDispatcher.OnK
101100
"SHIFT", ":", "£", "?", "/", "*", ",", ".", "SHIFT", "SYM", "SYM"
102101
};
103102

104-
private final BasicStroke outlineStroke = new BasicStroke(3.0f);
103+
private final BasicStroke outlineStroke = new BasicStroke(STROKE_WIDTH);
104+
private final Color usableButtonColor;
105+
private final Color outlineColor;
106+
private final Color brightColor;
105107

106108
private boolean symShift = false;
107109
private boolean shift = false;
108110

109-
public KeyboardCanvas() {
111+
public KeyboardCanvas(int alpha) {
110112
setDoubleBuffered(true);
113+
this.usableButtonColor = new Color(
114+
Color.LIGHT_GRAY.getRed(),
115+
Color.LIGHT_GRAY.getGreen(),
116+
Color.LIGHT_GRAY.getBlue(), alpha);
117+
this.outlineColor = new Color(0, 0, 0, alpha);
118+
this.brightColor = new Color(255, 255, 255, alpha);
111119
}
112120

113121
@Override
114-
public void onKeyEvent(KeyEvent e) {
122+
public boolean onKeyEvent(KeyEvent e) {
115123
boolean pressed = e.getID() == KEY_PRESSED;
116124
if (!pressed && e.getID() != KEY_RELEASED) {
117-
return;
125+
return false;
118126
}
119127

120128
symShift = (e.getModifiersEx() & (KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)) != 0;
121129
shift = (e.getModifiersEx() & (KeyEvent.SHIFT_DOWN_MASK)) != 0;
122130
repaint();
131+
return true;
123132
}
124133

125134
public void paint(Graphics g) {
@@ -133,7 +142,7 @@ public void paint(Graphics g) {
133142

134143
g2d.setFont(new Font("SansSerif", Font.PLAIN, 11));
135144
g2d.setStroke(outlineStroke);
136-
g2d.setColor(Color.WHITE);
145+
g2d.setColor(brightColor);
137146
g2d.translate(X_SHIFT_L, 0);
138147

139148
for (int i = 0; i < KEY_MAP.length; i++) {
@@ -152,7 +161,7 @@ public void paint(Graphics g) {
152161
int sw = g2d.getFontMetrics().stringWidth(text);
153162

154163
g2d.translate(KEY_MAP[i][0] - sw / 2.0, KEY_MAP[i][1]);
155-
g2d.setColor(Color.BLACK);
164+
g2d.setColor(outlineColor);
156165
g2d.fill(textShape);
157166
g2d.translate(sw / 2.0, 0);
158167
}
@@ -163,14 +172,15 @@ private void drawKeyboard(Graphics2D g) {
163172

164173
// keyboard shape
165174
g.setStroke(stroke);
166-
g.drawRoundRect(X_SHIFT, 0, KEYBOARD_WIDTH, KEYBOARD_HEIGHT, arc, arc);
175+
g.setColor(outlineColor);
176+
g.drawRoundRect(X_SHIFT, -STROKE_WIDTH, KEYBOARD_WIDTH, KEYBOARD_HEIGHT, arc, arc);
167177

168178
// top row
169179
for (int i = 0; i < 13; i++) {
170180
if (i >= 1 && i <= 10) {
171-
g.setColor(USABLE_BUTTON_COLOR);
181+
g.setColor(usableButtonColor);
172182
g.fillRoundRect(X_SHIFT_L + i * (bw + s), Y_SHIFT_T, bw, bh, arc, arc);
173-
g.setColor(Color.BLACK);
183+
g.setColor(outlineColor);
174184
}
175185
g.drawRoundRect(X_SHIFT_L + i * (bw + s), Y_SHIFT_T, bw, bh, arc, arc);
176186
}
@@ -183,9 +193,9 @@ private void drawKeyboard(Graphics2D g) {
183193
g.drawRoundRect(X_SHIFT_L, y1, tabw, bh, arc, arc);
184194
for (int i = 0; i < 12; i++) {
185195
if (i < 10) {
186-
g.setColor(USABLE_BUTTON_COLOR);
196+
g.setColor(usableButtonColor);
187197
g.fillRoundRect(X_SHIFT_L + i * (bw + s) + tabw + s, y1, bw, bh, arc, arc);
188-
g.setColor(Color.BLACK);
198+
g.setColor(outlineColor);
189199
}
190200
g.drawRoundRect(X_SHIFT_L + i * (bw + s) + tabw + s, y1, bw, bh, arc, arc);
191201
}
@@ -194,66 +204,66 @@ private void drawKeyboard(Graphics2D g) {
194204
int x0 = X_SHIFT_L + 12 * (bw + s) + tabw + s;
195205
int y0 = Y_SHIFT_T + bh + s;
196206
Polygon enterPolygon = new Polygon(
197-
new int[]{x0, x0 + tabw - s, x0 + tabw - s, x0 + 2 * s, x0 + 2 * s, x0},
207+
new int[]{x0, x0 + tabw - 2 * s, x0 + tabw - 2 * s, x0 + 2 * s, x0 + 2 * s, x0},
198208
new int[]{y0, y0, y0 + 2 * bh + s, y0 + 2 * bh + s, y0 + bh, y0 + bh},
199209
6
200210
);
201211

202-
g.setColor(USABLE_BUTTON_COLOR);
212+
g.setColor(usableButtonColor);
203213
g.fillPolygon(enterPolygon);
204-
g.setColor(Color.BLACK);
214+
g.setColor(outlineColor);
205215
g.drawPolygon(enterPolygon);
206216

207217
// caps lock
208218
int y2 = Y_SHIFT_T + (bh + s) * 2;
209219
g.drawRoundRect(X_SHIFT_L, y2, bsw, bh, arc, arc);
210220
for (int i = 0; i < 12; i++) {
211221
if (i < 9) {
212-
g.setColor(USABLE_BUTTON_COLOR);
222+
g.setColor(usableButtonColor);
213223
g.fillRoundRect(X_SHIFT_L + i * (bw + s) + bsw + s, y2, bw, bh, arc, arc);
214-
g.setColor(Color.BLACK);
224+
g.setColor(outlineColor);
215225
}
216226
g.drawRoundRect(X_SHIFT_L + i * (bw + s) + bsw + s, y2, bw, bh, arc, arc);
217227
}
218228

219229
// l shift
220230
int y3 = Y_SHIFT_T + (bh + s) * 3;
221231

222-
g.setColor(USABLE_BUTTON_COLOR);
232+
g.setColor(usableButtonColor);
223233
g.fillRoundRect(X_SHIFT_L, y3, lshiftw, bh, arc, arc);
224-
g.setColor(Color.BLACK);
234+
g.setColor(outlineColor);
225235
g.drawRoundRect(X_SHIFT_L, y3, lshiftw, bh, arc, arc);
226236
for (int i = 0; i < 11; i++) {
227237
if (i >= 1 && i < 8) {
228-
g.setColor(USABLE_BUTTON_COLOR);
238+
g.setColor(usableButtonColor);
229239
g.fillRoundRect(X_SHIFT_L + i * (bw + s) + lshiftw + s, y3, bw, bh, arc, arc);
230-
g.setColor(Color.BLACK);
240+
g.setColor(outlineColor);
231241
}
232242
g.drawRoundRect(X_SHIFT_L + i * (bw + s) + lshiftw + s, y3, bw, bh, arc, arc);
233243
}
234-
g.setColor(USABLE_BUTTON_COLOR);
244+
g.setColor(usableButtonColor);
235245
g.fillRoundRect(X_SHIFT_L + 11 * (bw + s) + lshiftw + s, y3, rshiftw, bh, arc, arc);
236-
g.setColor(Color.BLACK);
246+
g.setColor(outlineColor);
237247
g.drawRoundRect(X_SHIFT_L + 11 * (bw + s) + lshiftw + s, y3, rshiftw, bh, arc, arc);
238248

239249
// l ctrl
240250
int y4 = Y_SHIFT_T + (bh + s) * 4;
241-
g.setColor(USABLE_BUTTON_COLOR);
251+
g.setColor(usableButtonColor);
242252
g.fillRoundRect(X_SHIFT_L, y4, tabw, bh, arc, arc);
243-
g.setColor(Color.BLACK);
253+
g.setColor(outlineColor);
244254
g.drawRoundRect(X_SHIFT_L, y4, tabw, bh, arc, arc);
245255
g.drawRoundRect(X_SHIFT_L + tabw + s, y4, bw, bh, arc, arc);
246256
g.drawRoundRect(X_SHIFT_L + tabw + bw + 2 * s, y4, tabw, bh, arc, arc);
247257

248-
g.setColor(USABLE_BUTTON_COLOR);
258+
g.setColor(usableButtonColor);
249259
g.fillRoundRect(X_SHIFT_L + 2 * (tabw + s) + bw + 2 * s, y4, brakew, bh, arc, arc);
250-
g.setColor(Color.BLACK);
260+
g.setColor(outlineColor);
251261
g.drawRoundRect(X_SHIFT_L + 2 * (tabw + s) + bw + 2 * s, y4, brakew, bh, arc, arc);
252262
g.drawRoundRect(X_SHIFT_L + 2 * (tabw + s) + bw + 4 * s + brakew, y4, tabw, bh, arc, arc);
253263

254-
g.setColor(USABLE_BUTTON_COLOR);
264+
g.setColor(usableButtonColor);
255265
g.fillRoundRect(X_SHIFT_L + 3 * (tabw + s) + bw + 4 * s + brakew, y4, bw, bh, arc, arc);
256-
g.setColor(Color.BLACK);
266+
g.setColor(outlineColor);
257267
g.drawRoundRect(X_SHIFT_L + 3 * (tabw + s) + bw + 4 * s + brakew, y4, bw, bh, arc, arc); // RCTRL
258268
g.drawRoundRect(X_SHIFT_L + 3 * (tabw + s) + 2 * bw + 5 * s + brakew, y4, bw, bh, arc, arc);
259269
g.drawRoundRect(X_SHIFT_L + 3 * (tabw + s) + 3 * bw + 6 * s + brakew, y4, tabw, bh, arc, arc);

plugins/device/zxspectrum-ula/src/main/java/net/emustudio/plugins/device/zxspectrum/ula/gui/KeyboardDispatcher.java

+9-4
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,21 @@ public class KeyboardDispatcher implements AutoCloseable, KeyEventDispatcher {
3232

3333
public interface OnKeyListener {
3434

35-
void onKeyEvent(KeyEvent e);
35+
boolean onKeyEvent(KeyEvent e);
3636
}
3737

3838
@Override
3939
public boolean dispatchKeyEvent(KeyEvent e) {
4040
boolean isConsumed = false;
4141
if (!e.isConsumed()) {
42-
onKeyListeners.forEach(c -> c.onKeyEvent(e));
43-
e.consume();
44-
isConsumed = true;
42+
boolean consumed = false;
43+
for (OnKeyListener listener : onKeyListeners) {
44+
consumed |= listener.onKeyEvent(e);
45+
}
46+
if (consumed) {
47+
e.consume();
48+
isConsumed = true;
49+
}
4550
}
4651
return isConsumed;
4752
}

0 commit comments

Comments
 (0)