8200605: Create test for GridBagLayoutDemo
authorvagarwal
Tue, 19 Jun 2018 12:04:01 +0530
changeset 50661 81affcb6832c
parent 50659 9ff8428f3e51
child 50662 681b118332d7
8200605: Create test for GridBagLayoutDemo Reviewed-by: serb, shurailine
test/jdk/sanity/client/SwingSet/src/GridBagLayoutDemoTest.java
test/jdk/sanity/client/SwingSet/src/TestHelpers.java
test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/gridbaglayout/Calculator.java
test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/gridbaglayout/GridBagLayoutDemo.java
test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/gridbaglayout/resources/GridBagLayoutDemo.properties
test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/gridbaglayout/resources/images/GridBagLayoutDemo.gif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/SwingSet/src/GridBagLayoutDemoTest.java	Tue Jun 19 12:04:01 2018 +0530
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import org.jtregext.GuiTestListener;
+import com.sun.swingset3.demos.gridbaglayout.GridBagLayoutDemo;
+import static com.sun.swingset3.demos.gridbaglayout.GridBagLayoutDemo.*;
+import static com.sun.swingset3.demos.gridbaglayout.Calculator.*;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Point;
+import javax.swing.JButton;
+import javax.swing.UIManager;
+import org.testng.annotations.Test;
+import org.netbeans.jemmy.ClassReference;
+import org.netbeans.jemmy.operators.JFrameOperator;
+import org.netbeans.jemmy.operators.JButtonOperator;
+import org.netbeans.jemmy.operators.JTextFieldOperator;
+import org.testng.annotations.Listeners;
+import static org.jemmy2ext.JemmyExt.EXACT_STRING_COMPARATOR;
+import static org.jemmy2ext.JemmyExt.getUIValue;
+/*
+ * @test
+ * @key headful
+ * @summary Verifies SwingSet3 GridBagLayoutDemo by checking the relative
+ *  location of all the components before and after resizing the frame,
+ *  interacting with all the controls and checking this interaction on the
+ *  text field display.
+ *
+ * @library /sanity/client/lib/jemmy/src
+ * @library /sanity/client/lib/Extensions/src
+ * @library /sanity/client/lib/SwingSet3/src
+ * @modules java.desktop
+ *          java.logging
+ * @build com.sun.swingset3.demos.gridbaglayout.GridBagLayoutDemo
+ * @run testng GridBagLayoutDemoTest
+ */
+
+@Listeners(GuiTestListener.class)
+public class GridBagLayoutDemoTest {
+
+    private JTextFieldOperator tfScreen;
+    private JButtonOperator buttonZero;
+    private JButtonOperator buttonOne;
+    private JButtonOperator buttonTwo;
+    private JButtonOperator buttonThree;
+    private JButtonOperator buttonFour;
+    private JButtonOperator buttonFive;
+    private JButtonOperator buttonSix;
+    private JButtonOperator buttonSeven;
+    private JButtonOperator buttonEight;
+    private JButtonOperator buttonNine;
+    private JButtonOperator buttonPlus;
+    private JButtonOperator buttonMinus;
+    private JButtonOperator buttonMultiply;
+    private JButtonOperator buttonDivide;
+    private JButtonOperator buttonComma;
+    private JButtonOperator buttonSqrt;
+    private JButtonOperator buttonReciprocal;
+    private JButtonOperator buttonToggleSign;
+    private JButtonOperator buttonEquals;
+    private JButtonOperator backspaceButton;
+    private JButtonOperator resetButton;
+    private JFrameOperator mainFrame;
+
+    @Test(dataProvider = "availableLookAndFeels", dataProviderClass = TestHelpers.class)
+    public void test(String lookAndFeel) throws Exception {
+        initializeUIComponents(lookAndFeel);
+        // Check that the relative location of buttons is as expected.
+        checkRelativeLocations();
+        // Interact with buttons and check the result on the display.
+        checkInteractionOnDisplay();
+        // Change the location and check that the relative location of buttons is same as before.
+        checkChangeLocation();
+        // Change the size and check that the relative location of buttons is same as before.
+        checkChangeSize();
+    }
+
+    private double x(Component component) {
+        return component.getLocation().getX();
+    }
+
+    private double y(Component component) {
+        return component.getLocation().getY();
+    }
+
+    private void checkRight(JButtonOperator currentButton, JButtonOperator rightButton) {
+        // Check that x coordinate of right button is greater than that of right
+        // end of current button
+        currentButton.waitStateOnQueue(button -> x(button) + button.getWidth() < x(rightButton.getSource()));
+        // Check that the y coordinate of the button is same as the button to
+        // the right
+        currentButton.waitStateOnQueue(button -> y(button) == y(rightButton.getSource()));
+        // Check that the height of the button is same as the button to the
+        // right
+        currentButton.waitStateOnQueue(button -> button.getHeight() == rightButton.getHeight());
+    }
+
+    private void checkBelow(JButtonOperator currentButton, JButtonOperator buttonBelow) {
+        // Check that y coordinate of button below is greater than that of
+        // bottom end of current button
+        currentButton.waitStateOnQueue(button -> y(button) + button.getHeight() < y(buttonBelow.getSource()));
+        // Check that the x coordinate of the button is same as the button below
+        currentButton.waitStateOnQueue(button -> x(button) == x(buttonBelow.getSource()));
+        // Check that the width of the button is same as the button below
+        currentButton.waitStateOnQueue(button -> button.getWidth() == buttonBelow.getWidth());
+    }
+
+    private void checkRelativeLocations() {
+        // Check relative location of button 7
+        checkRight(buttonSeven, buttonEight);
+        checkBelow(buttonSeven, buttonFour);
+
+        // Check relative location of button 8
+        checkRight(buttonEight, buttonNine);
+        checkBelow(buttonEight, buttonFive);
+
+        // Check relative location of button 9
+        checkRight(buttonNine, buttonDivide);
+        checkBelow(buttonNine, buttonSix);
+
+        // Check relative location of Division button
+        checkRight(buttonDivide, buttonReciprocal);
+        checkBelow(buttonDivide, buttonMultiply);
+
+        // Check relative location of Reciprocal and Sqrt buttons
+        checkBelow(buttonReciprocal, buttonSqrt);
+
+        // Check relative location of button 4
+        checkRight(buttonFour, buttonFive);
+        checkBelow(buttonFour, buttonOne);
+
+        // Check relative location of button 5
+        checkRight(buttonFive, buttonSix);
+        checkBelow(buttonFive, buttonTwo);
+
+        // Check relative location of button 6
+        checkRight(buttonSix, buttonMultiply);
+        checkBelow(buttonSix, buttonThree);
+
+        // Check relative location of Multiply button
+        checkRight(buttonMultiply, buttonSqrt);
+        checkBelow(buttonMultiply, buttonMinus);
+
+        // Check relative location of button 1
+        checkRight(buttonOne, buttonTwo);
+        checkBelow(buttonOne, buttonZero);
+
+        // Check relative location of button 2
+        checkRight(buttonTwo, buttonThree);
+        checkBelow(buttonTwo, buttonToggleSign);
+
+        // Check relative location of button 3
+        checkRight(buttonThree, buttonMinus);
+        checkBelow(buttonThree, buttonComma);
+
+        // Check relative location of Minus button
+        checkBelow(buttonMinus, buttonPlus);
+
+        // Check relative location of button 0
+        checkRight(buttonZero, buttonToggleSign);
+
+        // Check relative location of Sign Toggle Button
+        checkRight(buttonToggleSign, buttonComma);
+
+        // Check relative location of Comma button
+        checkRight(buttonComma, buttonPlus);
+
+        // Check relative location of plus and Equals buttons
+        checkRight(buttonPlus, buttonEquals);
+
+        // Check relative location of JPanel containing Backspace and Reset
+        // buttons
+        Point parentLocation = getUIValue(backspaceButton, (JButton button) -> button.getParent().getLocation());
+        // Check that the y coordinate of bottom of the screen is
+        // less than that of parent of backspace button
+        tfScreen.waitStateOnQueue(screen -> y(screen) + screen.getHeight() < parentLocation.getY());
+        // Check that the y coordinate of the button 7 is greater
+        // than that of parent of backspace
+        buttonSeven.waitStateOnQueue(button -> parentLocation.getY() < y(button));
+        // Check that the y coordinate of reciprocal button is greater
+        // than that of parent of backspace
+        buttonReciprocal.waitStateOnQueue(button -> parentLocation.getY() < y(button));
+        // Check that x coordinate of screen is same as that of parent of
+        // backspace
+        tfScreen.waitStateOnQueue(screen -> x(screen) == parentLocation.getX());
+        // Check that x coordinate of button 7 is same as that of parent of
+        // backspace
+        buttonSeven.waitStateOnQueue(button -> x(button) == parentLocation.getX());
+
+        // Check relative location of Backspace button
+        // Check that the x coordinate of right of backspace button
+        // is less than that of reset button
+        backspaceButton.waitStateOnQueue(button -> x(button) + button.getWidth() < x(resetButton.getSource()));
+        // Check that the height of backspace button is same as that of reset
+        // button
+        backspaceButton.waitStateOnQueue(button -> button.getHeight() == resetButton.getHeight());
+        // Check that the y coordinate bottom of backspace button is less that
+        // that of button 7
+        backspaceButton.waitStateOnQueue(
+                button -> parentLocation.getY() + button.getParent().getHeight() < y(buttonSeven.getSource()));
+
+        // Check that the x coordinate of reset button is greater than that
+        // of right of backspace button
+        resetButton.waitStateOnQueue(button -> x(backspaceButton.getSource()) + backspaceButton.getWidth() < x(button));
+
+        // Check that the height of reset button is same as that of backspace
+        // button
+        resetButton.waitStateOnQueue(button -> backspaceButton.getHeight() == button.getHeight());
+
+        // Check that the y coordinate of bottom of reset button is less
+        // than that of divide button.
+        resetButton.waitStateOnQueue(
+                button -> parentLocation.getY() + button.getParent().getHeight() < y(buttonDivide.getSource()));
+
+        // Check that the y coordinate of top of screen is lower
+        // than that of parent of backspace button
+        tfScreen.waitStateOnQueue(screen -> y(screen) + screen.getHeight() < parentLocation.getY());
+    }
+
+    private void checkInteractionOnDisplay() {
+        // Check buttons: 1,2,+,=,C
+        buttonOne.push();
+        tfScreen.waitText("1");
+        buttonPlus.push();
+        tfScreen.waitText("1");
+        buttonTwo.push();
+        tfScreen.waitText("2");
+        buttonEquals.push();
+        tfScreen.waitText("3");
+        resetButton.push();
+        tfScreen.waitText("0");
+
+        // Check buttons: 3,4,-
+        buttonFour.push();
+        tfScreen.waitText("4");
+        buttonMinus.push();
+        tfScreen.waitText("4");
+        buttonThree.push();
+        tfScreen.waitText("3");
+        buttonEquals.push();
+        tfScreen.waitText("1");
+        reset();
+
+        // Check buttons: 5,6,*
+        buttonFive.push();
+        tfScreen.waitText("5");
+        buttonMultiply.push();
+        tfScreen.waitText("5");
+        buttonSix.push();
+        tfScreen.waitText("6");
+        buttonEquals.push();
+        tfScreen.waitText("30");
+        reset();
+
+        // Check buttons: 8,9,/
+        buttonNine.push();
+        buttonNine.push();
+        tfScreen.waitText("99");
+        buttonDivide.push();
+        tfScreen.waitText("99");
+        buttonEight.push();
+        tfScreen.waitText("8");
+        buttonEquals.push();
+        tfScreen.waitText("12.375");
+        reset();
+
+        // Check buttons: 7,0,[+/-],Backspace
+        buttonSeven.push();
+        tfScreen.waitText("7");
+        buttonZero.push();
+        tfScreen.waitText("70");
+        buttonToggleSign.push();
+        tfScreen.waitText("-70");
+        buttonToggleSign.push();
+        tfScreen.waitText("70");
+        backspaceButton.push();
+        tfScreen.waitText("7");
+        reset();
+
+        // Check Sqrt Button
+        buttonFour.push();
+        buttonNine.push();
+        tfScreen.waitText("49");
+        buttonSqrt.push();
+        tfScreen.waitText("7");
+        reset();
+
+        // Check Reciprocal Button
+        buttonFour.push();
+        tfScreen.waitText("4");
+        buttonReciprocal.push();
+        tfScreen.waitText("0.25");
+        reset();
+
+        // Check Comma button
+        buttonFour.push();
+        buttonComma.push();
+        tfScreen.waitText("4,");
+    }
+
+    private void reset() {
+        resetButton.push();
+        tfScreen.waitText("0");
+    }
+
+    private void initializeUIComponents(String lookAndFeel) throws Exception {
+        UIManager.setLookAndFeel(lookAndFeel);
+        new ClassReference(GridBagLayoutDemo.class.getCanonicalName()).startApplication();
+        mainFrame = new JFrameOperator(GRID_BAG_LAYOUT_DEMO_TITLE);
+        mainFrame.setComparator(EXACT_STRING_COMPARATOR);
+        buttonZero = new JButtonOperator(mainFrame, ZERO_BUTTON_TITLE);
+        buttonOne = new JButtonOperator(mainFrame, ONE_BUTTON_TITLE);
+        buttonTwo = new JButtonOperator(mainFrame, TWO_BUTTON_TITLE);
+        buttonThree = new JButtonOperator(mainFrame, THREE_BUTTON_TITLE);
+        buttonFour = new JButtonOperator(mainFrame, FOUR_BUTTON_TITLE);
+        buttonFive = new JButtonOperator(mainFrame, FIVE_BUTTON_TITLE);
+        buttonSix = new JButtonOperator(mainFrame, SIX_BUTTON_TITLE);
+        buttonSeven = new JButtonOperator(mainFrame, SEVEN_BUTTON_TITLE);
+        buttonEight = new JButtonOperator(mainFrame, EIGHT_BUTTON_TITLE);
+        buttonNine = new JButtonOperator(mainFrame, NINE_BUTTON_TITLE);
+        buttonPlus = new JButtonOperator(mainFrame, PLUS_BUTTON_TITLE);
+        buttonMinus = new JButtonOperator(mainFrame, MINUS_BUTTON_TITLE);
+        buttonMultiply = new JButtonOperator(mainFrame, MULTIPLY_BUTTON_TITLE);
+        buttonDivide = new JButtonOperator(mainFrame, DIVIDE_BUTTON_TITLE);
+        buttonComma = new JButtonOperator(mainFrame, ",");
+        buttonSqrt = new JButtonOperator(mainFrame, SQRT_BUTTON_TITLE);
+        buttonReciprocal = new JButtonOperator(mainFrame, INVERSE_BUTTON_TITLE);
+        buttonToggleSign = new JButtonOperator(mainFrame, SWAPSIGN_BUTTON_TITLE);
+        buttonEquals = new JButtonOperator(mainFrame, EQUALS_BUTTON_TITLE);
+        resetButton = new JButtonOperator(mainFrame, C_BUTTON_TITLE);
+        backspaceButton = new JButtonOperator(mainFrame, BACKSPACE_BUTTON_TITLE);
+        tfScreen = new JTextFieldOperator(mainFrame, 0);
+    }
+
+    private void checkChangeLocation() {
+        Point startingPoint = new Point(100, 100);
+        mainFrame.setLocation(startingPoint);
+        mainFrame.waitComponentLocation(startingPoint);
+        checkRelativeLocations();
+    }
+
+    private void checkChangeSize() {
+        Dimension newSize = new Dimension((int) mainFrame.getToolkit().getScreenSize().getWidth() / 2,
+                (int) mainFrame.getToolkit().getScreenSize().getHeight() / 2);
+        mainFrame.setSize(newSize);
+        mainFrame.waitComponentSize(newSize);
+        checkRelativeLocations();
+    }
+}
--- a/test/jdk/sanity/client/SwingSet/src/TestHelpers.java	Fri Jun 15 13:07:46 2018 -0700
+++ b/test/jdk/sanity/client/SwingSet/src/TestHelpers.java	Tue Jun 19 12:04:01 2018 +0530
@@ -1,17 +1,40 @@
-
 import java.awt.Dimension;
 import java.awt.Point;
-
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.nio.file.Path;
+import javax.swing.UIManager;
 import org.netbeans.jemmy.operators.ComponentOperator;
+import org.testng.annotations.DataProvider;
 
 public class TestHelpers {
 
+    /**
+     * A DataProvider having the class name of all the available look and feels
+     *
+     * @return a 2d Object array containing the class name of all the available
+     * look and feels
+     */
+    @DataProvider(name = "availableLookAndFeels")
+    public static Object[][] provideAvailableLookAndFeels() {
+        UIManager.LookAndFeelInfo LookAndFeelInfos[]
+                = UIManager.getInstalledLookAndFeels();
+        Object[][] lookAndFeels = new Object[LookAndFeelInfos.length][1];
+        for (int i = 0; i < LookAndFeelInfos.length; i++) {
+            lookAndFeels[i][0] = LookAndFeelInfos[i].getClassName();
+        }
+        return lookAndFeels;
+    }
+
     public static void checkChangeLocation(ComponentOperator component,
             Point finalLocation) {
         Point initialLocation = component.getLocation();
         component.setLocation(finalLocation);
         component.waitComponentLocation(finalLocation);
         component.setLocation(initialLocation);
+        component.waitComponentLocation(initialLocation);
     }
 
     public static void checkChangeSize(ComponentOperator component,
@@ -20,5 +43,7 @@
         component.setSize(dimensionFinal);
         component.waitComponentSize(dimensionFinal);
         component.setSize(dimensionInitial);
+        component.waitComponentSize(dimensionInitial);
     }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/gridbaglayout/Calculator.java	Tue Jun 19 12:04:01 2018 +0530
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2007, 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.swingset3.demos.gridbaglayout;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import javax.swing.*;
+
+/**
+ * Calculator
+ *
+ * @author Pavel Porvatov
+ */
+public class Calculator extends JComponent {
+
+    private static final String ZERO = "0";
+
+    private static final char DECIMAL_SEPARATOR = ',';
+
+    private final JTextField tfScreen = new JTextField();
+
+    private enum State {
+
+        INPUT_X,
+        INPUT_X_FINISHED,
+        INPUT_Y,
+        INPUT_Y_FINISHED
+    }
+
+    private enum Operator {
+
+        ADDITION,
+        SUBTRACTION,
+        MULTIPLICATION,
+        DIVISION,
+        SQRT,
+        INVERSE,
+        EQUALS
+    }
+
+    private final Map<Character, Operator> keyMapping = new HashMap<Character, Operator>();
+
+    private String operand_x;
+
+    private Operator operator;
+
+    private State state;
+
+    public static final String ZERO_BUTTON_TITLE = "0";
+    public static final String ONE_BUTTON_TITLE = "1";
+    public static final String TWO_BUTTON_TITLE = "2";
+    public static final String THREE_BUTTON_TITLE = "3";
+    public static final String FOUR_BUTTON_TITLE = "4";
+    public static final String FIVE_BUTTON_TITLE = "5";
+    public static final String SIX_BUTTON_TITLE = "6";
+    public static final String SEVEN_BUTTON_TITLE = "7";
+    public static final String EIGHT_BUTTON_TITLE = "8";
+    public static final String NINE_BUTTON_TITLE = "9";
+    public static final String PLUS_BUTTON_TITLE = "+";
+    public static final String MINUS_BUTTON_TITLE = "-";
+    public static final String DIVIDE_BUTTON_TITLE = "/";
+    public static final String MULTIPLY_BUTTON_TITLE = "*";
+    public static final String BACKSPACE_BUTTON_TITLE = "Backspace";
+    public static final String C_BUTTON_TITLE = "C";
+    public static final String EQUALS_BUTTON_TITLE = "=";
+    public static final String SWAPSIGN_BUTTON_TITLE = "+/-";
+    public static final String INVERSE_BUTTON_TITLE = "1/x";
+    public static final String SQRT_BUTTON_TITLE = "sqrt";
+    public static final String COMMA_BUTTON_TITLE = ",";
+
+    private static DecimalFormatSymbols decimalFormatSymbols;
+    private static DecimalFormat decimalFormat;
+
+    public Calculator() {
+        keyMapping.put('/', Operator.DIVISION);
+        keyMapping.put('*', Operator.MULTIPLICATION);
+        keyMapping.put('+', Operator.ADDITION);
+        keyMapping.put('-', Operator.SUBTRACTION);
+        keyMapping.put('\n', Operator.EQUALS);
+
+        decimalFormatSymbols = new DecimalFormatSymbols(Locale.US);
+        decimalFormatSymbols.setDecimalSeparator('.');
+        decimalFormat = new DecimalFormat("##0.###", decimalFormatSymbols);
+
+        initUI();
+
+        addKeyListener(new KeyAdapter() {
+            public void keyTyped(KeyEvent e) {
+                char c = e.getKeyChar();
+
+                if (Character.isDigit(c)) {
+                    doProcessChar(c);
+                } else if (c == '.' || c == ',') {
+                    doProcessChar(DECIMAL_SEPARATOR);
+                } else {
+                    Operator operator = keyMapping.get(c);
+
+                    if (operator != null) {
+                        doProcessOperator(operator);
+                    }
+                }
+            }
+
+            public void keyPressed(KeyEvent e) {
+                switch (e.getKeyCode()) {
+                    case KeyEvent.VK_BACK_SPACE:
+                        doProcessBackspace();
+
+                        break;
+
+                    case KeyEvent.VK_DELETE:
+                        doReset();
+                }
+            }
+        });
+
+        doReset();
+    }
+
+    private void initUI() {
+        tfScreen.setHorizontalAlignment(JTextField.RIGHT);
+
+        JButton btnBackspace = new JButton(BACKSPACE_BUTTON_TITLE);
+
+        btnBackspace.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                doProcessBackspace();
+            }
+        });
+
+        JButton btnReset = new JButton(C_BUTTON_TITLE);
+
+        btnReset.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                doReset();
+            }
+        });
+
+        JPanel pnGridPanel = new JPanel(new GridLayout(1, 2, 8, 8));
+
+        pnGridPanel.add(btnBackspace);
+        pnGridPanel.add(btnReset);
+
+        setLayout(new GridBagLayout());
+
+        JButton btnSwapSign = new SquareButton(SWAPSIGN_BUTTON_TITLE);
+
+        btnSwapSign.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                doSwapSign();
+            }
+        });
+
+        addComp(tfScreen, 0, 0, 5, 1);
+        addComp(pnGridPanel, 0, 1, 5, 1);
+
+        addComp(new CharButton(SEVEN_BUTTON_TITLE.charAt(0)), 0, 2, 1, 1);
+        addComp(new CharButton(EIGHT_BUTTON_TITLE.charAt(0)), 1, 2, 1, 1);
+        addComp(new CharButton(NINE_BUTTON_TITLE.charAt(0)), 2, 2, 1, 1);
+        addComp(new OperatorButton(Operator.DIVISION, DIVIDE_BUTTON_TITLE), 3, 2, 1, 1);
+        addComp(new OperatorButton(Operator.INVERSE, INVERSE_BUTTON_TITLE), 4, 2, 1, 1);
+
+        addComp(new CharButton(FOUR_BUTTON_TITLE.charAt(0)), 0, 3, 1, 1);
+        addComp(new CharButton(FIVE_BUTTON_TITLE.charAt(0)), 1, 3, 1, 1);
+        addComp(new CharButton(SIX_BUTTON_TITLE.charAt(0)), 2, 3, 1, 1);
+        addComp(new OperatorButton(Operator.MULTIPLICATION, MULTIPLY_BUTTON_TITLE), 3, 3, 1, 1);
+        addComp(new OperatorButton(Operator.SQRT, SQRT_BUTTON_TITLE), 4, 3, 1, 1);
+
+        addComp(new CharButton(ONE_BUTTON_TITLE.charAt(0)), 0, 4, 1, 1);
+        addComp(new CharButton(TWO_BUTTON_TITLE.charAt(0)), 1, 4, 1, 1);
+        addComp(new CharButton(THREE_BUTTON_TITLE.charAt(0)), 2, 4, 1, 1);
+        addComp(new OperatorButton(Operator.SUBTRACTION, MINUS_BUTTON_TITLE), 3, 4, 1, 1);
+
+        addComp(new CharButton(ZERO_BUTTON_TITLE.charAt(0)), 0, 5, 1, 1);
+        addComp(btnSwapSign, 1, 5, 1, 1);
+        addComp(new CharButton(COMMA_BUTTON_TITLE.charAt(0)), 2, 5, 1, 1);
+        addComp(new OperatorButton(Operator.ADDITION, PLUS_BUTTON_TITLE), 3, 5, 1, 1);
+        addComp(new OperatorButton(Operator.EQUALS, EQUALS_BUTTON_TITLE), 4, 5, 1, 1);
+
+        // Set focusable false
+        resetFocusable(this);
+
+        setFocusable(true);
+    }
+
+    private static void resetFocusable(Component component) {
+        component.setFocusable(false);
+
+        if (component instanceof Container) {
+            for (Component c : ((Container) component).getComponents()) {
+                resetFocusable(c);
+            }
+        }
+    }
+
+    private void doReset() {
+        synchronized (this) {
+            operand_x = null;
+            operator = null;
+            state = State.INPUT_X;
+        }
+        tfScreen.setText(ZERO);
+    }
+
+    private void doProcessChar(char c) {
+        String text = tfScreen.getText();
+
+        String newValue;
+
+        synchronized (this) {
+            if (state == State.INPUT_X || state == State.INPUT_Y) {
+                newValue = attachChar(text, c);
+
+                if (stringToValue(newValue) == null) {
+                    return;
+                }
+            } else {
+                newValue = attachChar("0", c);
+
+                if (stringToValue(newValue) == null) {
+                    return;
+                }
+
+                if (operator == null) {
+                    operand_x = null;
+                    state = State.INPUT_X;
+                } else {
+                    operand_x = text;
+                    state = State.INPUT_Y;
+                }
+            }
+        }
+        tfScreen.setText(newValue);
+    }
+
+    private static String attachChar(String s, char c) {
+        if (Character.isDigit(c)) {
+            if (s.equals(ZERO)) {
+                return Character.toString(c);
+            }
+
+            if (s.equals("-" + ZERO)) {
+                return "-" + Character.toString(c);
+            }
+
+            return s + Character.toString(c);
+        } else {
+            return s + Character.toString(c);
+        }
+    }
+
+    private void doSwapSign() {
+        String text = tfScreen.getText();
+
+        tfScreen.setText(text.startsWith("-") ? text.substring(1) : "-" + text);
+    }
+
+    private void doProcessBackspace() {
+        String text = tfScreen.getText();
+
+        if (text.length() > 0) {
+            text = text.substring(0, text.length() - 1);
+        }
+
+        if (text.length() == 0 || text.equals("-")) {
+            text = ZERO;
+        }
+
+        if (stringToValue(text) != null) {
+            tfScreen.setText(text);
+        }
+    }
+
+    private void doProcessOperator(Operator operator) {
+        double y = stringToValue(tfScreen.getText());
+
+        // Process unary operators
+        boolean isUnary;
+
+        switch (operator) {
+            case SQRT:
+                tfScreen.setText(valueToString(Math.sqrt(y)));
+
+                isUnary = true;
+
+                break;
+
+            case INVERSE:
+                tfScreen.setText(valueToString(1 / y));
+
+                isUnary = true;
+
+                break;
+
+            default:
+                isUnary = false;
+        }
+
+        synchronized (this) {
+            if (isUnary) {
+                if (state == State.INPUT_X) {
+                    state = State.INPUT_X_FINISHED;
+                }
+
+                if (state == State.INPUT_Y) {
+                    state = State.INPUT_Y_FINISHED;
+                }
+
+                return;
+            }
+
+            // Process binary operators
+            if (state == State.INPUT_Y || state == State.INPUT_Y_FINISHED) {
+                double x = stringToValue(operand_x);
+                double result;
+
+                switch (this.operator) {
+                    case ADDITION:
+                        result = x + y;
+
+                        break;
+
+                    case SUBTRACTION:
+                        result = x - y;
+
+                        break;
+
+                    case MULTIPLICATION:
+                        result = x * y;
+
+                        break;
+
+                    case DIVISION:
+                        result = x / y;
+
+                        break;
+
+                    default:
+                        throw new IllegalStateException("Unsupported operation " + operator);
+                }
+
+                tfScreen.setText(valueToString(result));
+            }
+
+            this.operator = operator == Operator.EQUALS ? null : operator;
+            operand_x = null;
+
+            state = State.INPUT_X_FINISHED;
+        }
+    }
+
+    private static Double stringToValue(String value) {
+        try {
+            return new Double(value.replace(DECIMAL_SEPARATOR, '.'));
+        } catch (NumberFormatException e) {
+            // Continue convertion
+        }
+
+        if (value.endsWith(String.valueOf(DECIMAL_SEPARATOR))) {
+            try {
+                // Try convert uncompleted value
+                return new Double(value.substring(0, value.length() - 1));
+            } catch (NumberFormatException e) {
+                // Continue convertion
+            }
+        }
+
+        return null;
+    }
+
+    private static String valueToString(Double value) {
+        if (value == null) {
+            return ZERO;
+        } else {
+            String result = decimalFormat.format(value);
+
+            if (result.endsWith(".0")) {
+                result = result.substring(0, result.length() - 2);
+            }
+
+            if (result.equals("-0")) {
+                result = ZERO;
+            }
+
+            return result;
+        }
+    }
+
+    private void addComp(Component comp, int gridx, int gridy,
+            int gridwidth, int gridheight) {
+        add(comp, new GridBagConstraints(gridx, gridy, gridwidth, gridheight,
+                1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+                new Insets(4, 4, 4, 4), 0, 0));
+    }
+
+    private static class SquareButton extends JButton {
+
+        private SquareButton(String text) {
+            super(text);
+
+            setMargin(new Insets(2, 0, 2, 0));
+        }
+
+        public Dimension getMinimumSize() {
+            Dimension result = super.getMinimumSize();
+
+            if (result.width < result.height) {
+                result.width = result.height;
+            }
+
+            return result;
+        }
+
+        public Dimension getPreferredSize() {
+            return getMinimumSize();
+        }
+    }
+
+    private class CharButton extends SquareButton {
+
+        private CharButton(final char c) {
+            super(String.valueOf(c));
+
+            addActionListener(new ActionListener() {
+                public void actionPerformed(ActionEvent e) {
+                    doProcessChar(c);
+                }
+            });
+        }
+    }
+
+    private class OperatorButton extends SquareButton {
+
+        private OperatorButton(final Operator operator, String text) {
+            super(text);
+
+            addActionListener(new ActionListener() {
+                public void actionPerformed(ActionEvent e) {
+                    doProcessOperator(operator);
+                }
+            });
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/gridbaglayout/GridBagLayoutDemo.java	Tue Jun 19 12:04:01 2018 +0530
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2007, 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.swingset3.demos.gridbaglayout;
+
+import java.awt.*;
+import javax.swing.*;
+
+import com.sun.swingset3.demos.JGridPanel;
+import com.sun.swingset3.demos.ResourceManager;
+import com.sun.swingset3.DemoProperties;
+
+/**
+ * GridBagLayout Demo
+ *
+ * @author Pavel Porvatov
+ */
+@DemoProperties(
+        value = "GridBagLayout Demo",
+        category = "Containers",
+        description = "Demonstrates GridBagLayout, a layout which allows to arrange components in containers.",
+        sourceFiles = {
+            "com/sun/swingset3/demos/gridbaglayout/GridBagLayoutDemo.java",
+            "com/sun/swingset3/demos/gridbaglayout/Calculator.java",
+            "com/sun/swingset3/demos/JGridPanel.java",
+            "com/sun/swingset3/demos/ResourceManager.java",
+            "com/sun/swingset3/demos/gridbaglayout/resources/GridBagLayoutDemo.properties",
+            "com/sun/swingset3/demos/gridbaglayout/resources/images/GridBagLayoutDemo.gif"
+        }
+)
+public class GridBagLayoutDemo extends JPanel {
+
+    private final ResourceManager resourceManager = new ResourceManager(this.getClass());
+
+    private final JLabel lbCaption = new JLabel("<html>"
+            + resourceManager.getString("GridBagLayoutDemo.caption.text") + "</html>");
+
+    private final Calculator calculator = new Calculator();
+
+    public static final String GRID_BAG_LAYOUT_DEMO_TITLE = GridBagLayoutDemo.class
+            .getAnnotation(DemoProperties.class).value();
+
+    /**
+     * main method allows us to run as a standalone demo.
+     */
+    public static void main(String[] args) {
+        JFrame frame = new JFrame(GRID_BAG_LAYOUT_DEMO_TITLE);
+
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        frame.getContentPane().add(new GridBagLayoutDemo());
+        frame.setPreferredSize(new Dimension(800, 600));
+        frame.pack();
+        frame.setLocationRelativeTo(null);
+        frame.setVisible(true);
+    }
+
+    public GridBagLayoutDemo() {
+        setLayout(new BorderLayout());
+
+        initUI();
+    }
+
+    private void initUI() {
+        JGridPanel pnContent = new JGridPanel(1, 0, 2);
+
+        pnContent.setBorderEqual(10);
+
+        pnContent.cell(lbCaption, JGridPanel.Layout.FILL).
+                cell().
+                cell(calculator, JGridPanel.Layout.CENTER, JGridPanel.Layout.FIRST).
+                cell();
+
+        add(pnContent);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/gridbaglayout/resources/GridBagLayoutDemo.properties	Tue Jun 19 12:04:01 2018 +0530
@@ -0,0 +1,4 @@
+### GridBagLayout Demo ###
+
+GridBagLayoutDemo.caption.text = This calculator uses the GridBagLayout layout manager to arrange components. \
+  GridBagLayout is very useful when you need to place components in a grid of rows and columns.
Binary file test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/gridbaglayout/resources/images/GridBagLayoutDemo.gif has changed