7979import static javax .swing .SwingUtilities .isEventDispatchThread ;
8080
8181/**
82- * Provides a framework for manual tests to display test instructions and
83- * Pass/Fail buttons.
82+ * A framework for manual tests to display test instructions and
83+ * <i>Pass</i> / <i>Fail</i> buttons. The framework automatically
84+ * creates a frame to display the instructions, provides buttons
85+ * to select the test result, and handles test timeout.
86+ *
87+ * <p id="timeOutTimer">
88+ * The instruction UI frame displays a timer at the top which indicates
89+ * how much time is left. The timer can be paused using the <i>Pause</i>
90+ * button to the right of the time; the title of the button changes to
91+ * <i>Resume</i>. To resume the timer, use the <i>Resume</i> button.
92+ *
93+ * <p id="instructionText">
94+ * In the center, the instruction UI frame displays instructions for the
95+ * tester. The instructions can be either plain text or HTML. If the
96+ * text of the instructions starts with {@code "<html>"}, the
97+ * instructions are displayed as HTML, as supported by Swing, which
98+ * provides richer formatting options.
99+ * <p>
100+ * The instructions are displayed in a text component with word-wrapping
101+ * so that there's no horizontal scroll bar. If the text doesn't fit, a
102+ * vertical scroll bar is shown. Use {@code rows} and {@code columns}
103+ * parameters to change the size of this text component.
104+ * If possible, choose the number of rows and columns so that
105+ * the instructions fit and no scroll bars are shown.
106+ *
107+ * <p id="passFailButtons">
108+ * At the bottom, the instruction UI frame displays the
109+ * <i>Pass</i> and <i>Fail</i> buttons. The tester clicks either <i>Pass</i>
110+ * or <i>Fail</i> button to finish the test. When the tester clicks the
111+ * <i>Fail</i> button, the framework displays a dialog box prompting for
112+ * a reason why the test fails. The tester enters the reason and clicks
113+ * <i>OK</i> to close the dialog and fail the test,
114+ * or simply closes the dialog to fail the test without providing any reason.
115+ *
116+ * <p id="screenCapture">
117+ * If you enable the screenshot feature, a <i>Screenshot</i> button is
118+ * added to the right of the <i>Fail</i> button. The tester can choose either
119+ * <i>Capture Full Screen</i> (default) or <i>Capture Frames</i> and click the
120+ * <i>Screenshot</i> button to take a screenshot.
121+ * If there are multiple screens, screenshots of each screen are created.
122+ * If the tester selects the <i>Capture Frames</i> mode, screenshots of all
123+ * the windows or frames registered in the {@code PassFailJFrame} framework
124+ * are created.
125+ *
126+ * <p id="logArea">
127+ * If you enable a log area, the instruction UI frame adds a text component
128+ * to display log messages below the buttons.
129+ * Use {@link #log(String) log}, {@link #logSet(String) logSet}
130+ * and {@link #logClear() logClear} static methods of {@code PassFailJFrame}
131+ * to add or clear messages from the log area.
132+ *
133+ * <p id="awaitTestResult">
134+ * After you create an instance of {@code PassFailJFrame}, call the
135+ * {@link #awaitAndCheck() awaitAndCheck} method to stop the current thread
136+ * (usually the main thread) and wait until the tester clicks
137+ * either <i>Pass</i> or <i>Fail</i> button,
138+ * or until the test times out.
84139 * <p>
85- * Instructions for the user can be either plain text or HTML as supported
86- * by Swing. If the instructions start with {@code <html>}, the
87- * instructions are displayed as HTML.
140+ * The call to the {@code awaitAndCheck} method is usually the last
141+ * statement in the {@code main} method of your test.
142+ * If the test fails, an exception is thrown to signal the failure to jtreg.
143+ * The test fails if the tester clicks the <i>Fail</i> button,
144+ * if the timeout occurs,
145+ * or if any window or frame is closed.
88146 * <p>
147+ * Before returning from {@code awaitAndCheck}, the framework disposes of
148+ * all the windows and frames.
149+ *
150+ * <h2 id="sampleManualTest">Sample Manual Test</h2>
89151 * A simple test would look like this:
90- * <pre>{@code
152+ * {@snippet id='sampleManualTestCode' lang='java':
91153 * public class SampleManualTest {
92154 * private static final String INSTRUCTIONS =
93155 * "Click Pass, or click Fail if the test failed.";
94156 *
95157 * public static void main(String[] args) throws Exception {
96158 * PassFailJFrame.builder()
97159 * .instructions(INSTRUCTIONS)
98- * .testUI(() -> createTestUI() )
160+ * .testUI(SampleManualTest:: createTestUI)
99161 * .build()
100162 * .awaitAndCheck();
101163 * }
106168 * return testUI;
107169 * }
108170 * }
109- * }</pre>
171+ * }
110172 * <p>
111- * The above example uses the {@link Builder Builder} to set the parameters of
112- * the instruction frame. It is the recommended way.
173+ * The above example uses the {@link Builder Builder} class to set
174+ * the parameters of the instruction frame.
175+ * It is <em>the recommended way</em>.
176+ *
113177 * <p>
114- * The framework will create instruction UI, it will call
115- * the provided {@code createTestUI} on the Event Dispatch Thread (EDT),
116- * and it will automatically position the test UI and make it visible.
178+ * The framework will create an instruction UI frame, it will call
179+ * the provided {@code createTestUI} on the Event Dispatch Thread (<dfn>EDT</dfn>),
180+ * and it will automatically position the test UI frame and make it visible.
181+ *
182+ * <p id="jtregTagsForTest">
183+ * Add the following jtreg tags before the test class declaration
184+ * {@snippet :
185+ * /*
186+ * * @test
187+ * * @summary Sample manual test
188+ * * @library /java/awt/regtesthelpers
189+ * * @build PassFailJFrame
190+ * * @run main/manual SampleManualTest
191+ * }
192+ * and the closing comment tag <code>*/</code>.
117193 * <p>
194+ * The {@code @library} tag points to the location of the
195+ * {@code PassFailJFrame} class in the source code;
196+ * the {@code @build} tag makes jtreg compile the {@code PassFailJFrame} class,
197+ * and finally the {@code @run} tag specifies it is a manual
198+ * test and the class to run.
199+ *
200+ * <h2 id="usingBuilder">Using {@code Builder}</h2>
201+ * Use methods of the {@link Builder Builder} class to set or change
202+ * parameters of {@code PassFailJFrame} and its instruction UI:
203+ * <ul>
204+ * <li>{@link Builder#title(String) title} sets
205+ * the title of the instruction UI
206+ * (the default is {@value #TITLE});</li>
207+ * <li>{@link Builder#testTimeOut(long) testTimeOut} sets
208+ * the timeout of the test
209+ * (the default is {@value #TEST_TIMEOUT});</li>
210+ * <li>{@link Builder#rows(int) rows} and
211+ * {@link Builder#columns(int) columns} control the size
212+ * the text component which displays the instructions
213+ * (the default number of rows is the number of lines in the text
214+ * of the instructions,
215+ * the default number of columns is {@value #COLUMNS});</li>
216+ * <li>{@link Builder#logArea() logArea} adds a log area;</li>
217+ * <li>{@link Builder#screenCapture() screenCapture}
218+ * enables screenshots.</li>
219+ * </ul>
220+ *
221+ * <h3 id="builderTestUI">Using {@code testUI} and {@code splitUI}</h3>
118222 * The {@code Builder.testUI} methods accept interfaces which create one window
119223 * or a list of windows if the test needs multiple windows,
120224 * or directly a single window, an array of windows or a list of windows.
121225 * <p>
122- * For simple test UI, use {@code Builder.splitUI}, or explicitly
123- * {@code Builder.splitUIRight} or {@code Builder.splitUIBottom} with
124- * a {@code PanelCreator}. The framework will call the provided
125- * {@code createUIPanel} to create the component with test UI and
226+ * For simple test UI, use {@link Builder#splitUI(PanelCreator) splitUI},
227+ * or explicitly
228+ * {@link Builder#splitUIRight(PanelCreator) splitUIRight} or
229+ * {@link Builder#splitUIBottom(PanelCreator) splitUIBottom} with
230+ * a {@link PanelCreator PanelCreator}.
231+ * The framework will call the provided
232+ * {@code createUIPanel} method to create the component with test UI and
126233 * will place it as the right or bottom component in a split pane
127234 * along with instruction UI.
128235 * <p>
236+ * Note: <em>support for multiple windows is incomplete</em>.
237+ *
238+ * <h2 id="obsoleteSampleTest">Obsolete Sample Test</h2>
129239 * Alternatively, use one of the {@code PassFailJFrame} constructors to
130240 * create an object, then create secondary test UI, register it
131241 * with {@code PassFailJFrame}, position it and make it visible.
132242 * The following sample demonstrates it:
133- * <pre>{@code
134- * public class SampleOldManualTest {
243+ * {@snippet id='obsoleteSampleTestCode' lang='java':
244+ * public class ObsoleteManualTest {
135245 * private static final String INSTRUCTIONS =
136246 * "Click Pass, or click Fail if the test failed.";
137247 *
138248 * public static void main(String[] args) throws Exception {
139249 * PassFailJFrame passFail = new PassFailJFrame(INSTRUCTIONS);
140250 *
141- * SwingUtilities.invokeAndWait(() -> createTestUI() );
251+ * SwingUtilities.invokeAndWait(ObsoleteManualTest:: createTestUI);
142252 *
143253 * passFail.awaitAndCheck();
144254 * }
151261 * testUI.setVisible(true);
152262 * }
153263 * }
154- * }</pre>
264+ * }
155265 * <p>
156- * Use methods of the {@code Builder} class or constructors of the
157- * {@code PassFailJFrame} class to control other parameters:
158- * <ul>
159- * <li>the title of the instruction UI,</li>
160- * <li>the timeout of the test,</li>
161- * <li>the size of the instruction UI via rows and columns, and</li>
162- * <li>to add a log area,</li>
163- * <li>to enable screenshots.</li>
164- * </ul>
266+ * This sample uses {@link #PassFailJFrame(String) a constructor} of
267+ * {@code PassFailJFrame} to create its instance,
268+ * there are several overloads provided which allow changing other parameters.
269+ * <p>
270+ * When you use the constructors, you have to explicitly create
271+ * your test UI window on EDT. After you create the window,
272+ * you need to register it with the framework using
273+ * {@link #addTestWindow(Window) addTestWindow}
274+ * to ensure the window is disposed of when the test completes.
275+ * Before showing the window, you have to call
276+ * {@link #positionTestWindow(Window, Position) positionTestWindow}
277+ * to position the test window near the instruction UI frame provided
278+ * by the framework. And finally you have to explicitly show the test UI
279+ * window by calling {@code setVisible(true)}.
280+ * <p>
281+ * To avoid the complexity, use the {@link Builder Builder} class
282+ * which provides a streamlined way to configure and create an
283+ * instance of {@code PassFailJFrame}.
284+ * <p>
285+ * Consider updating tests which use {@code PassFailJFrame} constructors to
286+ * use the builder pattern.
165287 */
166288public final class PassFailJFrame {
167289
@@ -541,7 +663,11 @@ private static JComponent createInstructionUIPanel(String instructions,
541663 : configurePlainText (instructions , rows , columns );
542664 text .setEditable (false );
543665
544- main .add (new JScrollPane (text ), BorderLayout .CENTER );
666+ JPanel textPanel = new JPanel (new BorderLayout ());
667+ textPanel .setBorder (createEmptyBorder (4 , 0 , 0 , 0 ));
668+ textPanel .add (new JScrollPane (text ), BorderLayout .CENTER );
669+
670+ main .add (textPanel , BorderLayout .CENTER );
545671
546672 JButton btnPass = new JButton ("Pass" );
547673 btnPass .addActionListener ((e ) -> {
@@ -822,7 +948,7 @@ public void windowClosing(WindowEvent e) {
822948 private static JComponent createCapturePanel () {
823949 JComboBox <CaptureType > screenShortType = new JComboBox <>(CaptureType .values ());
824950
825- JButton capture = new JButton ("ScreenShot " );
951+ JButton capture = new JButton ("Screenshot " );
826952 capture .addActionListener ((e ) ->
827953 captureScreen ((CaptureType ) screenShortType .getSelectedItem ()));
828954
@@ -834,7 +960,7 @@ private static JComponent createCapturePanel() {
834960
835961 private enum CaptureType {
836962 FULL_SCREEN ("Capture Full Screen" ),
837- WINDOWS ("Capture Individual Frame " );
963+ WINDOWS ("Capture Frames " );
838964
839965 private final String type ;
840966 CaptureType (String type ) {
0 commit comments