diff --git a/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java b/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java index 1aa83339701d7ce7934d17a1ac31eaf9cfc2c939..50656c0f2ccf397937e54a9f80baba8b4c617972 100644 --- a/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java +++ b/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java @@ -54,6 +54,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import javax.imageio.ImageIO; +import javax.swing.Box; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; @@ -156,6 +157,7 @@ import static javax.swing.SwingUtilities.isEventDispatchThread; * <li>the title of the instruction UI,</li> * <li>the timeout of the test,</li> * <li>the size of the instruction UI via rows and columns, and</li> + * <li>to add a log area</li>, * <li>to enable screenshots.</li> * </ul> */ @@ -205,6 +207,8 @@ public final class PassFailJFrame { private static Robot robot; + private static JTextArea logArea; + public enum Position {HORIZONTAL, VERTICAL, TOP_LEFT_CORNER} public PassFailJFrame(String instructions) throws InterruptedException, @@ -374,6 +378,20 @@ public final class PassFailJFrame { } } + /** + * Does the same as {@link #invokeOnEDT(Runnable)}, but does not throw + * any checked exceptions. + * + * @param doRun an operation to run on EDT + */ + private static void invokeOnEDTUncheckedException(Runnable doRun) { + try { + invokeOnEDT(doRun); + } catch (InterruptedException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + private static void createUI(String title, String instructions, long testTimeOut, int rows, int columns, boolean enableScreenCapture) { @@ -385,7 +403,8 @@ public final class PassFailJFrame { frame.add(createInstructionUIPanel(instructions, testTimeOut, rows, columns, - enableScreenCapture), + enableScreenCapture, + false, 0), BorderLayout.CENTER); frame.pack(); frame.setLocationRelativeTo(null); @@ -402,8 +421,9 @@ public final class PassFailJFrame { createInstructionUIPanel(builder.instructions, builder.testTimeOut, builder.rows, builder.columns, - builder.screenCapture); - + builder.screenCapture, + builder.addLogArea, + builder.logAreaRows); if (builder.splitUI) { JSplitPane splitPane = new JSplitPane( builder.splitUIOrientation, @@ -422,7 +442,9 @@ public final class PassFailJFrame { private static JComponent createInstructionUIPanel(String instructions, long testTimeOut, int rows, int columns, - boolean enableScreenCapture) { + boolean enableScreenCapture, + boolean addLogArea, + int logAreaRows) { JPanel main = new JPanel(new BorderLayout()); timeoutHandlerPanel = new TimeoutHandlerPanel(testTimeOut); main.add(timeoutHandlerPanel, BorderLayout.NORTH); @@ -454,7 +476,20 @@ public final class PassFailJFrame { buttonsPanel.add(createCapturePanel()); } - main.add(buttonsPanel, BorderLayout.SOUTH); + if (addLogArea) { + logArea = new JTextArea(logAreaRows, columns); + logArea.setEditable(false); + + Box buttonsLogPanel = Box.createVerticalBox(); + + buttonsLogPanel.add(buttonsPanel); + buttonsLogPanel.add(new JScrollPane(logArea)); + + main.add(buttonsLogPanel, BorderLayout.SOUTH); + } else { + main.add(buttonsPanel, BorderLayout.SOUTH); + } + main.setMinimumSize(main.getPreferredSize()); return main; @@ -1072,6 +1107,36 @@ public final class PassFailJFrame { latch.countDown(); } + /** + * Adds a {@code message} to the log area, if enabled by + * {@link Builder#logArea()} or {@link Builder#logArea(int)}. + * + * @param message to log + */ + public static void log(String message) { + System.out.println("PassFailJFrame: " + message); + invokeOnEDTUncheckedException(() -> logArea.append(message + "\n")); + } + + /** + * Clears the log area, if enabled by + * {@link Builder#logArea()} or {@link Builder#logArea(int)}. + */ + public static void logClear() { + System.out.println("\nPassFailJFrame: log cleared\n"); + invokeOnEDTUncheckedException(() -> logArea.setText("")); + } + + /** + * Replaces the log area content with provided {@code text}, if enabled by + * {@link Builder#logArea()} or {@link Builder#logArea(int)}. + * @param text new text for the log area + */ + public static void logSet(String text) { + System.out.println("\nPassFailJFrame: log set to:\n" + text + "\n"); + invokeOnEDTUncheckedException(() -> logArea.setText(text)); + } + public static final class Builder { private String title; private String instructions; @@ -1079,6 +1144,8 @@ public final class PassFailJFrame { private int rows; private int columns; private boolean screenCapture; + private boolean addLogArea; + private int logAreaRows = 10; private List<? extends Window> testWindows; private WindowListCreator windowListCreator; @@ -1120,6 +1187,37 @@ public final class PassFailJFrame { return this; } + /** + * Adds a log area below the "Pass", "Fail" buttons. + * <p> + * The log area can be controlled by {@link #log(String)}, + * {@link #logClear()} and {@link #logSet(String)}. + * + * @return this builder + */ + public Builder logArea() { + this.addLogArea = true; + return this; + } + + /** + * Adds a log area below the "Pass", "Fail" buttons. + * <p> + * The log area can be controlled by {@link #log(String)}, + * {@link #logClear()} and {@link #logSet(String)}. + * <p> + * The number of columns is taken from the number of + * columns in the instructional JTextArea. + * + * @param rows of the log area + * @return this builder + */ + public Builder logArea(int rows) { + this.addLogArea = true; + this.logAreaRows = rows; + return this; + } + /** * Adds a {@code WindowCreator} which the framework will use * to create the test UI window.