diff --git a/modules/javafx.graphics/src/main/java/javafx/scene/input/KeyCharacterCombination.java b/modules/javafx.graphics/src/main/java/javafx/scene/input/KeyCharacterCombination.java index 2fc0df17a6e..e4e715774dd 100644 --- a/modules/javafx.graphics/src/main/java/javafx/scene/input/KeyCharacterCombination.java +++ b/modules/javafx.graphics/src/main/java/javafx/scene/input/KeyCharacterCombination.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,7 @@ */ public final class KeyCharacterCombination extends KeyCombination { /** The key character associated with this key combination. */ - private String character = ""; + private final String character; /** * Gets the key character associated with this key combination. diff --git a/modules/javafx.graphics/src/main/java/javafx/scene/input/KeyCodeCombination.java b/modules/javafx.graphics/src/main/java/javafx/scene/input/KeyCodeCombination.java index 65fe4639c49..744e81c4670 100644 --- a/modules/javafx.graphics/src/main/java/javafx/scene/input/KeyCodeCombination.java +++ b/modules/javafx.graphics/src/main/java/javafx/scene/input/KeyCodeCombination.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,7 @@ */ public final class KeyCodeCombination extends KeyCombination { /** The key code associated with this key combination. */ - private KeyCode code; + private final KeyCode code; /** * Gets the key code associated with this key combination. @@ -145,8 +145,8 @@ public String getDisplayText() { sb.append(super.getDisplayText()); final int initialLength = sb.length(); - char c = getSingleChar(code); - if (c != 0) { + String c = getSingleChar(code); + if (c != null) { sb.append(c); return sb.toString(); } @@ -218,74 +218,83 @@ private static void validateKeyCode(final KeyCode keyCode) { } } - /** Compute a single suitable char summarizing the code, if any, and 0 otherwise. */ - private static char getSingleChar(KeyCode code) { - switch (code) { - case ENTER: return '\u21B5'; - case LEFT: return '\u2190'; - case UP: return '\u2191'; - case RIGHT: return '\u2192'; - case DOWN: return '\u2193'; - case COMMA: return ','; - case MINUS: return '-'; - case PERIOD: return '.'; - case SLASH: return '/'; - case SEMICOLON: return ';'; - case EQUALS: return '='; - case OPEN_BRACKET: return '['; - case BACK_SLASH: return '\\'; - case CLOSE_BRACKET: return ']'; - case MULTIPLY: return '*'; - case ADD: return '+'; - case SUBTRACT: return '-'; - case DECIMAL: return '.'; - case DIVIDE: return '/'; - case BACK_QUOTE: return '`'; - case QUOTE: return '"'; - case AMPERSAND: return '&'; - case ASTERISK: return '*'; - case LESS: return '<'; - case GREATER: return '>'; - case BRACELEFT: return '{'; - case BRACERIGHT: return '}'; - case AT: return '@'; - case COLON: return ':'; - case CIRCUMFLEX: return '^'; - case DOLLAR: return '$'; - case EURO_SIGN: return '\u20AC'; - case EXCLAMATION_MARK: return '!'; - case LEFT_PARENTHESIS: return '('; - case NUMBER_SIGN: return '#'; - case PLUS: return '+'; - case RIGHT_PARENTHESIS: return ')'; - case UNDERSCORE: return '_'; - case DIGIT0: return '0'; - case DIGIT1: return '1'; - case DIGIT2: return '2'; - case DIGIT3: return '3'; - case DIGIT4: return '4'; - case DIGIT5: return '5'; - case DIGIT6: return '6'; - case DIGIT7: return '7'; - case DIGIT8: return '8'; - case DIGIT9: return '9'; - default: - break; - } - - /* - ** On Mac we display these unicode symbols, - ** otherwise we default to the Text version of the char. - */ + // Returns a suitable string representation of the key code or null + private static String getSingleChar(KeyCode code) { + // On Mac we display these unicode symbols, + // otherwise we default to the Text version of the char. if (com.sun.javafx.PlatformUtil.isMac()) { switch (code) { - case BACK_SPACE: return '\u232B'; - case ESCAPE: return '\u238B'; - case DELETE: return '\u2326'; - default: - break; + case BACK_SPACE: return "\u232B"; + case ESCAPE: return "\u238B"; + case DELETE: return "\u2326"; } } - return 0; + + switch (code) { + case ENTER: return "\u21B5"; + case LEFT: return "\u2190"; + case UP: return "\u2191"; + case RIGHT: return "\u2192"; + case DOWN: return "\u2193"; + case COMMA: return ","; + case MINUS: return "-"; + case PERIOD: return "."; + case SLASH: return "/"; + case SEMICOLON: return ";"; + case EQUALS: return "="; + case OPEN_BRACKET: return "["; + case BACK_SLASH: return "\\"; + case CLOSE_BRACKET: return "]"; + case MULTIPLY: return "NumPad *"; + case ADD: return "NumPad +"; + case SUBTRACT: return "NumPad -"; + case DECIMAL: return "NumPad ."; + case DIVIDE: return "NumPad /"; + case BACK_QUOTE: return "`"; + case QUOTE: return "\""; + case AMPERSAND: return "&"; + case ASTERISK: return "*"; + case LESS: return "<"; + case GREATER: return ">"; + case BRACELEFT: return "{"; + case BRACERIGHT: return "}"; + case AT: return "@"; + case COLON: return ":"; + case CIRCUMFLEX: return "^"; + case DOLLAR: return "$"; + case EURO_SIGN: return "\u20AC"; + case EXCLAMATION_MARK: return "!"; + case LEFT_PARENTHESIS: return "("; + case NUMBER_SIGN: return "#"; + case PLUS: return "+"; + case RIGHT_PARENTHESIS: return ")"; + case UNDERSCORE: return "_"; + case DIGIT0: return "0"; + case DIGIT1: return "1"; + case DIGIT2: return "2"; + case DIGIT3: return "3"; + case DIGIT4: return "4"; + case DIGIT5: return "5"; + case DIGIT6: return "6"; + case DIGIT7: return "7"; + case DIGIT8: return "8"; + case DIGIT9: return "9"; + case NUMPAD0: return "NumPad 0"; + case NUMPAD1: return "NumPad 1"; + case NUMPAD2: return "NumPad 2"; + case NUMPAD3: return "NumPad 3"; + case NUMPAD4: return "NumPad 4"; + case NUMPAD5: return "NumPad 5"; + case NUMPAD6: return "NumPad 6"; + case NUMPAD7: return "NumPad 7"; + case NUMPAD8: return "NumPad 8"; + case NUMPAD9: return "NumPad 9"; + case BACK_SPACE: return "Backspace"; + case ESCAPE: return "Esc"; + case PAGE_DOWN: return "PgDn"; + case PAGE_UP: return "PgUp"; + } + + return null; } } diff --git a/modules/javafx.graphics/src/test/java/test/javafx/scene/input/KeyCombinationTest.java b/modules/javafx.graphics/src/test/java/test/javafx/scene/input/KeyCombinationTest.java index 82e43d346a2..7ee804e37ab 100644 --- a/modules/javafx.graphics/src/test/java/test/javafx/scene/input/KeyCombinationTest.java +++ b/modules/javafx.graphics/src/test/java/test/javafx/scene/input/KeyCombinationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,29 +30,31 @@ import static javafx.scene.input.KeyCombination.CONTROL_DOWN; import static javafx.scene.input.KeyCombination.SHIFT_ANY; import static javafx.scene.input.KeyCombination.SHIFT_DOWN; - +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; - +import java.util.stream.Stream; import javafx.event.Event; -import javafx.scene.input.KeyCombination.ModifierValue; - -import test.com.sun.javafx.pgstub.StubToolkit; -import com.sun.javafx.scene.input.KeyCodeMap; -import com.sun.javafx.tk.Toolkit; import javafx.scene.input.KeyCharacterCombination; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCodeCombination; import javafx.scene.input.KeyCombination; +import javafx.scene.input.KeyCombination.ModifierValue; import javafx.scene.input.KeyEvent; - import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import com.sun.javafx.scene.input.KeyCodeMap; +import com.sun.javafx.tk.Toolkit; +import test.com.sun.javafx.pgstub.StubToolkit; public class KeyCombinationTest { @@ -605,12 +607,74 @@ private void assertPlatformEquals(KeyCombination expectedWin, KeyCombination exp assertEquals("[", acceleratorKeyCombo.getDisplayText()); } - /* - * check that the KeyCodeCombination for KeyCode.DELETE produces something printable. - * We only display the unicode DELETE char on mac, otherwise we use "Delete". + private static Stream platformSpecificCombinations() { + return Stream.of( + Arguments.of("Backspace", "\u232B", KeyCode.BACK_SPACE), + Arguments.of("Delete", "\u2326", KeyCode.DELETE), + Arguments.of("Esc", "\u238B", KeyCode.ESCAPE) + ); + } + + /** + * Checks keys that show different text between Windows/Linux and macOS. + */ + @ParameterizedTest + @MethodSource("platformSpecificCombinations") + public void platformSpecific(String win, String mac, KeyCode code) { + KeyCodeCombination k = new KeyCodeCombination(code); + assertPlatformEquals(win, mac, k.getDisplayText()); + } + + private static List commonCombinations() { + return toArgumentsList( + 2, + "NumPad 0", KeyCode.NUMPAD0, + "NumPad 1", KeyCode.NUMPAD1, + "NumPad 2", KeyCode.NUMPAD2, + "NumPad 3", KeyCode.NUMPAD3, + "NumPad 4", KeyCode.NUMPAD4, + "NumPad 5", KeyCode.NUMPAD5, + "NumPad 6", KeyCode.NUMPAD6, + "NumPad 7", KeyCode.NUMPAD7, + "NumPad 8", KeyCode.NUMPAD8, + "NumPad 9", KeyCode.NUMPAD9, + "NumPad *", KeyCode.MULTIPLY, + "NumPad +", KeyCode.ADD, + "NumPad -", KeyCode.SUBTRACT, + "NumPad .", KeyCode.DECIMAL, + "NumPad /", KeyCode.DIVIDE, + "PgDn", KeyCode.PAGE_DOWN, + "PgUp", KeyCode.PAGE_UP + ); + } + + // converts an array into a Stream with the specified arity (number of arguments) + // this should be a standard function in junit5 + private static List toArgumentsList(int arity, Object... items) { + if (arity <= 0) { + throw new IllegalArgumentException("arity must be > 0"); + } + if ((items.length % arity) != 0) { + throw new IllegalArgumentException("wrong number of items for arity=" + arity); + } + ArrayList a = new ArrayList<>(); + for (int i = 0; i < items.length;) { + Object[] v = new Object[arity]; + for (int j = 0; j < arity; ) { + v[j++] = items[i++]; + } + a.add(Arguments.of(v)); + } + return a; + } + + /** + * Checks numeric pad keys */ - @Test public void validStringForDELETE() { - KeyCodeCombination keyComboDELETE = new KeyCodeCombination(KeyCode.DELETE); - assertPlatformEquals("Delete", "\u2326", keyComboDELETE.getDisplayText()); + @ParameterizedTest + @MethodSource("commonCombinations") + public void numPadSymbols(String expected, KeyCode code) { + KeyCodeCombination k = new KeyCodeCombination(code); + assertEquals(expected, k.getDisplayText()); } }