8043126: move awt automated functional tests from AWT_Events/Lw and AWT_Events/AWT to OpenJDK repository
Reviewed-by: pchelko
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/KeyEvent/ExtendedModifiersTest/ExtendedModifiersTest.java Tue Jul 08 16:01:18 2014 +0400
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2001, 2014, 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.
+ */
+
+
+/*
+ * @test
+ * @bug 8043126
+ * @summary Check whether
+ * 1. correct extended modifiers are returned
+ * by KeyEvent.getModifiersEx()
+ * 2. InputEvent.getModifiersExText() returns
+ * correct extended modifier keys description
+ *
+ * @library ../../../../../lib/testlibrary/ ../../helpers/lwcomponents/
+ * @build LWComponent
+ * @build LWButton
+ * @build LWList
+ * @build ExtendedRobot
+ * @run main/timeout=600 ExtendedModifiersTest
+ */
+
+
+import java.awt.*;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.util.ArrayList;
+
+import static jdk.testlibrary.Asserts.*;
+import test.java.awt.event.helpers.lwcomponents.LWButton;
+import test.java.awt.event.helpers.lwcomponents.LWList;
+
+
+public class ExtendedModifiersTest implements KeyListener {
+
+ Frame frame;
+
+ Button button;
+ LWButton buttonLW;
+ TextField textField;
+ TextArea textArea;
+ List list;
+ LWList listLW;
+
+ private final ExtendedRobot robot;
+ private final static int robotDelay = 1000;
+ private final static int waitDelay = 5000;
+ private final static int keyDelay = 500;
+
+ private final Object lock;
+
+ private boolean keyPressedFlag = false;
+
+ private int modifiersEx = 0;
+ private String exText = "";
+
+
+ @Override
+ public void keyTyped(KeyEvent e) {}
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+ return;
+ }
+
+ modifiersEx = e.getModifiersEx();
+ exText = InputEvent.getModifiersExText(modifiersEx);
+ keyPressedFlag = true;
+
+ synchronized (lock) { lock.notifyAll(); }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {}
+
+
+ public void createGUI() {
+
+ frame = new Frame();
+ frame.setTitle("ExtendedModifiersTest");
+ frame.setLayout(new GridLayout(1, 6));
+
+ button = new Button();
+ button.addKeyListener(this);
+ frame.add(button);
+
+ buttonLW = new LWButton();
+ buttonLW.addKeyListener(this);
+ frame.add(buttonLW);
+
+ textField = new TextField(5);
+ textField.addKeyListener(this);
+ frame.add(textField);
+
+ textArea = new TextArea(5, 5);
+ textArea.addKeyListener(this);
+ frame.add(textArea);
+
+ list = new List();
+ for (int i = 1; i <= 5; ++i) { list.add("item " + i); }
+ list.addKeyListener(this);
+ frame.add(list);
+
+ listLW = new LWList();
+ for (int i = 1; i <= 5; ++i) { listLW.add("item " + i); }
+ listLW.addKeyListener(this);
+ frame.add(listLW);
+
+ frame.setBackground(Color.gray);
+ frame.setSize(500, 100);
+ frame.setVisible(true);
+ frame.toFront();
+ }
+
+ public ExtendedModifiersTest() throws Exception {
+ lock = new Object();
+ robot = new ExtendedRobot();
+ EventQueue.invokeAndWait( this::createGUI );
+ }
+
+
+ private void runScenario(int keys[], int refMask) {
+
+ if (keys.length < 1) { return; }
+
+ for (int k = 0; k < keys.length; ++k) {
+
+ keyPressedFlag = false;
+ robot.keyPress(keys[k]);
+ robot.delay(keyDelay);
+
+ if (!keyPressedFlag) {
+ synchronized (lock) {
+ try {
+ lock.wait(waitDelay);
+ } catch (InterruptedException ex) {}
+ }
+ }
+
+ if (!keyPressedFlag) {
+ robot.keyRelease(keys[k]);
+ robot.delay(keyDelay);
+ assertTrue(false, "key press event was not received");
+ }
+ }
+
+ int modEx = modifiersEx & refMask;
+
+ for (int k = keys.length - 1; k >=0; --k) {
+ robot.keyRelease(keys[k]);
+ robot.delay(keyDelay);
+ }
+
+
+ assertEQ(modifiersEx, modEx, "invalid extended modifiers");
+
+ for (int k = 0; k < keys.length; ++k) {
+ String keyText = KeyEvent.getKeyText(keys[k]).toLowerCase();
+ assertTrue(exText.toLowerCase().contains(keyText), "invalid extended modifier keys description");
+ }
+
+ System.out.println(exText + " : passed");
+
+ robot.type(KeyEvent.VK_ESCAPE);
+
+ robot.delay(robotDelay);
+ }
+
+ private void doTest() throws Exception {
+
+ ArrayList<Component> components = new ArrayList();
+ components.add(button);
+ components.add(buttonLW);
+ components.add(textField);
+ components.add(textArea);
+ components.add(list);
+ components.add(listLW);
+
+ String OS = System.getProperty("os.name").toLowerCase();
+ System.out.println(OS);
+
+ for (Component c: components) {
+
+ String className = c.getClass().getName();
+ System.out.println("component class : " + className);
+
+ Point origin = c.getLocationOnScreen();
+ int xc = origin.x + c.getWidth() / 2;
+ int yc = origin.y + c.getHeight() / 2;
+ Point center = new Point(xc, yc);
+
+ robot.delay(robotDelay);
+ robot.glide(origin, center);
+ robot.click();
+ robot.delay(robotDelay);
+
+ // 1. shift + control
+ runScenario(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL},
+ InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK);
+
+ // 2. alt + shift + control
+ runScenario(new int[]{KeyEvent.VK_ALT, KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL},
+ InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK);
+
+ // 3. shift
+ runScenario(new int[]{KeyEvent.VK_SHIFT},
+ InputEvent.SHIFT_DOWN_MASK);
+
+ // 4. alt + control
+ runScenario(new int[]{KeyEvent.VK_ALT, KeyEvent.VK_CONTROL},
+ InputEvent.ALT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK);
+
+ // 5. shift + alt
+ runScenario(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_ALT},
+ InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
+
+
+ if (OS.contains("os x") || OS.contains("sunos")) {
+ // 6. meta
+ runScenario(new int[]{KeyEvent.VK_META}, InputEvent.META_DOWN_MASK);
+
+ // 7. shift + ctrl + alt + meta
+ runScenario(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL, KeyEvent.VK_ALT, KeyEvent.VK_META},
+ InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK | InputEvent.META_DOWN_MASK);
+
+ // 8. meta + shift + ctrl
+ runScenario(new int[]{KeyEvent.VK_META, KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL},
+ InputEvent.META_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK);
+
+ // 9. meta + shift + alt
+ runScenario(new int[]{KeyEvent.VK_META, KeyEvent.VK_SHIFT, KeyEvent.VK_ALT},
+ InputEvent.META_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
+
+ // 10. meta + ctrl + alt
+ runScenario(new int[]{KeyEvent.VK_META, KeyEvent.VK_CONTROL, KeyEvent.VK_ALT},
+ InputEvent.META_DOWN_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
+ }
+ }
+
+ robot.waitForIdle();
+ frame.dispose();
+ }
+
+ public static void main(String[] args) throws Exception {
+ ExtendedModifiersTest test = new ExtendedModifiersTest();
+ test.doTest();
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/KeyEvent/KeyMaskTest/KeyMaskTest.java Tue Jul 08 16:01:18 2014 +0400
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2001, 2014, 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.
+ */
+
+
+/*
+ * @test
+ * @bug 8043126
+ * @summary Check whether KeyEvent.getModifiers() returns correct modifiers
+ * when Ctrl, Alt or Shift keys are pressed.
+ *
+ * @library ../../../../../lib/testlibrary/ ../../helpers/lwcomponents/
+ * @build LWComponent
+ * @build LWButton
+ * @build LWList
+ * @build ExtendedRobot
+ * @run main/timeout=600 KeyMaskTest
+ */
+
+
+import java.awt.*;
+import java.awt.event.InputEvent;
+
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+
+import java.util.ArrayList;
+
+import static jdk.testlibrary.Asserts.*;
+
+import test.java.awt.event.helpers.lwcomponents.LWButton;
+import test.java.awt.event.helpers.lwcomponents.LWList;
+
+
+
+public class KeyMaskTest extends KeyAdapter {
+
+ Frame frame;
+
+ Button button;
+ LWButton buttonLW;
+ TextField textField;
+ TextArea textArea;
+ List list;
+ LWList listLW;
+
+ int buttonPressedNumber;
+ int buttonReleasedNumber;
+
+ ExtendedRobot robot;
+
+ private final static int robotDelay = 1500;
+ private final static int waitDelay = 3500;
+
+ final Object lock;
+
+ private boolean keyPressReceived = false;
+ private int keyCode = -1;
+
+ KeyMaskTest() throws Exception {
+ lock = new Object();
+ robot = new ExtendedRobot();
+ EventQueue.invokeAndWait( this::createGUI );
+ }
+
+ public void createGUI() {
+
+ frame = new Frame();
+ frame.setTitle("KeyMaskTest");
+ frame.setLayout(new GridLayout(1, 6));
+
+ button = new Button();
+ button.addKeyListener(this);
+ frame.add(button);
+
+ buttonLW = new LWButton();
+ buttonLW.addKeyListener(this);
+ frame.add(buttonLW);
+
+ textField = new TextField(5);
+ textField.addKeyListener(this);
+ frame.add(textField);
+
+ textArea = new TextArea(5, 5);
+ textArea.addKeyListener(this);
+ frame.add(textArea);
+
+ list = new List();
+ for (int i = 1; i <= 5; ++i) { list.add("item " + i); }
+ list.addKeyListener(this);
+ frame.add(list);
+
+ listLW = new LWList();
+ for (int i = 1; i <= 5; ++i) { listLW.add("item " + i); }
+ listLW.addKeyListener(this);
+ frame.add(listLW);
+
+
+ frame.setBackground(Color.gray);
+ frame.setSize(500, 100);
+ frame.setVisible(true);
+ frame.toFront();
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+
+ keyPressReceived = true;
+
+ int code = e.getKeyCode();
+
+ assertEQ(code, keyCode, "wrong key code");
+
+ int mask = 0;
+
+ if (code == KeyEvent.VK_SHIFT) {
+ mask = InputEvent.SHIFT_MASK;
+ } else if (code == KeyEvent.VK_CONTROL) {
+ mask = InputEvent.CTRL_MASK;
+ } else if (code == KeyEvent.VK_ALT) {
+ mask = InputEvent.ALT_MASK;
+ } else if (code == KeyEvent.VK_META) {
+ mask = InputEvent.META_MASK;
+ }
+
+ int mod = e.getModifiers() & mask;
+ assertEQ(mod, mask, "invalid key mask");
+
+ synchronized (lock) { lock.notifyAll(); }
+ }
+
+
+ void doTest() throws Exception {
+
+ ArrayList<Component> components = new ArrayList();
+ components.add(button);
+ components.add(buttonLW);
+ components.add(textField);
+ components.add(textArea);
+ components.add(list);
+ components.add(listLW);
+
+ int keys[];
+ String OS = System.getProperty("os.name").toLowerCase();
+ System.out.println(OS);
+ if (OS.contains("os x") || OS.contains("sunos")) {
+ keys = new int[] {KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL, KeyEvent.VK_ALT, KeyEvent.VK_META};
+ } else {
+ keys = new int[] {KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL, KeyEvent.VK_ALT};
+ }
+
+ for (Component c: components) {
+
+ System.out.print(c.getClass().getName() + ": ");
+
+ Point origin = c.getLocationOnScreen();
+ int xc = origin.x + c.getWidth() / 2;
+ int yc = origin.y + c.getHeight() / 2;
+ Point center = new Point(xc, yc);
+
+ robot.delay(robotDelay);
+ robot.glide(origin, center);
+ robot.click();
+ robot.delay(robotDelay);
+
+ for (int k = 0; k < keys.length; ++k) {
+
+ keyPressReceived = false;
+
+ keyCode = keys[k];
+
+ robot.type(keyCode);
+
+ robot.delay(robotDelay);
+
+ if (!keyPressReceived) {
+ synchronized (lock) {
+ try {
+ lock.wait(waitDelay);
+ } catch (InterruptedException e) {}
+ }
+ }
+
+ assertTrue(keyPressReceived, "key press event was not received");
+ }
+
+ System.out.println("passed");
+ }
+
+ robot.waitForIdle();
+ frame.dispose();
+ }
+
+
+ public static void main(String[] args) throws Exception {
+
+ KeyMaskTest test = new KeyMaskTest();
+ test.doTest();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/MouseEvent/MouseButtonsAndKeyMasksTest/MouseButtonsAndKeyMasksTest.java Tue Jul 08 16:01:18 2014 +0400
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2001, 2014, 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 java.awt.*;
+
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.util.ArrayList;
+
+import static jdk.testlibrary.Asserts.*;
+
+
+import test.java.awt.event.helpers.lwcomponents.LWButton;
+import test.java.awt.event.helpers.lwcomponents.LWList;
+
+
+/*
+ * @test
+ * @bug 8043126
+ * @summary Check whether MouseEvent.getModifiers(), MouseEvent.getModifiersEx()
+ * and KeyEvent.getModifiers() return correct modifiers when pressing
+ * keys Ctrl, Alt, Shift, Meta and mouse buttons sequentially
+ *
+ * @library ../../../../../lib/testlibrary/ ../../helpers/lwcomponents/
+ * @build LWComponent
+ * @build LWButton
+ * @build LWList
+ * @build ExtendedRobot
+ * @run main/timeout=600 MouseButtonsAndKeyMasksTest
+ */
+
+public class MouseButtonsAndKeyMasksTest implements MouseListener, KeyListener {
+
+ Frame frame;
+
+ Button button;
+ LWButton buttonLW;
+ TextField textField;
+ TextArea textArea;
+ List list;
+ LWList listLW;
+
+ ExtendedRobot robot;
+
+ private final static int robotDelay = 1500;
+ private final static int keyDelay = 500;
+ private final static int waitDelay = 5000;
+
+ int modMouse = 0, modMouseEx = 0, modKey = 0, modAction = 0;
+
+ boolean mousePressFired = false;
+ boolean keyPressFired = false;
+
+ final Object lock;
+
+ MouseButtonsAndKeyMasksTest() throws Exception {
+ lock = new Object();
+ robot = new ExtendedRobot();
+ EventQueue.invokeAndWait( this::createGUI );
+ }
+
+ public void createGUI() {
+
+ frame = new Frame();
+ frame.setTitle("MouseButtonsAndKeysTest");
+ frame.setLayout(new GridLayout(1, 6));
+
+ button = new Button();
+ button.addKeyListener(this);
+ button.addMouseListener(this);
+ frame.add(button);
+
+ buttonLW = new LWButton();
+ buttonLW.addKeyListener(this);
+ buttonLW.addMouseListener(this);
+ frame.add(buttonLW);
+
+ textField = new TextField(5);
+ textField.addKeyListener(this);
+ textField.addMouseListener(this);
+ frame.add(textField);
+
+ textArea = new TextArea(5, 5);
+ textArea.addKeyListener(this);
+ textArea.addMouseListener(this);
+ frame.add(textArea);
+
+ list = new List();
+ for (int i = 1; i <= 5; ++i) { list.add("item " + i); }
+ list.addKeyListener(this);
+ list.addMouseListener(this);
+ frame.add(list);
+
+ listLW = new LWList();
+ for (int i = 1; i <= 5; ++i) { listLW.add("item " + i); }
+ listLW.addKeyListener(this);
+ listLW.addMouseListener(this);
+ frame.add(listLW);
+
+
+ frame.setBackground(Color.gray);
+ frame.setSize(500, 80);
+ frame.setVisible(true);
+ frame.toFront();
+ }
+
+
+ @Override
+ public void mouseClicked(MouseEvent e) {}
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+
+ modMouse = e.getModifiers();
+ modMouseEx = e.getModifiersEx();
+ mousePressFired = true;
+ synchronized (lock) { lock.notifyAll(); }
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {}
+ @Override
+ public void mouseEntered(MouseEvent e) {}
+ @Override
+ public void mouseExited(MouseEvent e) {}
+
+
+ @Override
+ public void keyTyped(KeyEvent e) {}
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { return; }
+
+ keyPressFired = true;
+ modKey = e.getModifiers();
+
+ synchronized (lock) { lock.notifyAll(); }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {}
+
+ void doTest() throws Exception {
+
+ int buttons[] = new int[]{
+ InputEvent.BUTTON1_MASK, InputEvent.BUTTON2_MASK, InputEvent.BUTTON3_MASK};
+
+ int buttonsEx[] = new int[]{
+ InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON2_DOWN_MASK, InputEvent.BUTTON3_DOWN_MASK};
+
+ String OS = System.getProperty("os.name").toLowerCase();
+ System.out.println(OS);
+
+ int keyMods[], keyModsEx[], keys[];
+
+
+ if (OS.contains("linux")) {
+ keyMods = new int[]{InputEvent.SHIFT_MASK, InputEvent.CTRL_MASK};
+ keyModsEx = new int[]{InputEvent.SHIFT_DOWN_MASK, InputEvent.CTRL_DOWN_MASK};
+ keys = new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL};
+ } else if (OS.contains("os x")) {
+ keyMods = new int[]{
+ InputEvent.SHIFT_MASK, InputEvent.CTRL_MASK, InputEvent.ALT_MASK, InputEvent.META_MASK};
+ keyModsEx = new int[]{
+ InputEvent.SHIFT_DOWN_MASK, InputEvent.CTRL_DOWN_MASK, InputEvent.ALT_DOWN_MASK, InputEvent.META_DOWN_MASK};
+ keys = new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL, KeyEvent.VK_ALT, KeyEvent.VK_META};
+ } else if (OS.contains("sunos")) {
+ keyMods = new int[]{InputEvent.SHIFT_MASK, InputEvent.META_MASK};
+ keyModsEx = new int[]{InputEvent.SHIFT_DOWN_MASK, InputEvent.META_DOWN_MASK};
+ keys = new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_META};
+ } else {
+ keyMods = new int[]{
+ InputEvent.SHIFT_MASK, InputEvent.CTRL_MASK, InputEvent.ALT_MASK};
+ keyModsEx = new int[]{
+ InputEvent.SHIFT_DOWN_MASK, InputEvent.CTRL_DOWN_MASK, InputEvent.ALT_DOWN_MASK};
+ keys = new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL, KeyEvent.VK_ALT};
+ }
+
+
+ ArrayList<Component> components = new ArrayList();
+ components.add(button);
+ components.add(buttonLW);
+ components.add(textField);
+ components.add(textArea);
+ components.add(list);
+ components.add(listLW);
+
+ for (Component c: components) {
+
+ System.out.println(c.getClass().getName() + ":");
+
+ Point origin = c.getLocationOnScreen();
+ int xc = origin.x + c.getWidth() / 2;
+ int yc = origin.y + c.getHeight() / 2;
+ Point center = new Point(xc, yc);
+
+ robot.delay(robotDelay);
+ robot.glide(origin, center);
+ robot.click();
+ robot.delay(robotDelay);
+
+ for (int b = 0; b < buttons.length; ++b) {
+
+ int btn = buttons[b];
+
+ for (int k = 0; k < keys.length; ++k) {
+
+ int key = keys[k];
+
+ System.out.print(KeyEvent.getKeyText(key) + " + button " + (b + 1));
+
+ robot.delay(robotDelay);
+
+ robot.keyPress(key);
+ robot.delay(keyDelay);
+
+ if (!keyPressFired) {
+ synchronized (lock) {
+ try {
+ lock.wait(waitDelay);
+ } catch (InterruptedException ex) {}
+ }
+ }
+
+ if (!keyPressFired) {
+ robot.keyRelease(key);
+ assertTrue(false, "key press event was not received");
+ }
+
+ robot.mousePress(btn);
+ robot.delay(robotDelay);
+
+ if (!mousePressFired) {
+ synchronized (lock) {
+ try {
+ lock.wait(waitDelay);
+ } catch (InterruptedException ex) {}
+ }
+ }
+
+ assertTrue(mousePressFired, "mouse press event was not received");
+
+ robot.mouseRelease(btn);
+ robot.delay(robotDelay);
+
+ // do checks
+ assertEQ(modMouse & btn, btn, "invalid mouse button mask");
+ assertEQ(modKey & keyMods[k], keyMods[k], "invalid key mask");
+ assertEQ(buttonsEx[b] | keyModsEx[k], modMouseEx, "invalid extended modifiers");
+
+ mousePressFired = false;
+ keyPressFired = false;
+
+ robot.keyRelease(key);
+ robot.delay(keyDelay);
+
+ robot.type(KeyEvent.VK_ESCAPE);
+
+ robot.delay(robotDelay);
+
+ System.out.println(" - passed");
+ }
+ }
+ }
+
+ robot.waitForIdle();
+ frame.dispose();
+ }
+
+
+ public static void main(String[] args) throws Exception {
+
+ MouseButtonsAndKeyMasksTest test = new MouseButtonsAndKeyMasksTest();
+ test.doTest();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/MouseEvent/MouseButtonsTest/MouseButtonsTest.java Tue Jul 08 16:01:18 2014 +0400
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2001, 2014, 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 java.awt.*;
+
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+
+import test.java.awt.event.helpers.lwcomponents.LWButton;
+import test.java.awt.event.helpers.lwcomponents.LWList;
+
+import java.util.ArrayList;
+
+import static jdk.testlibrary.Asserts.*;
+
+/*
+ * @test
+ * @bug 8043126
+ * @summary Check whether getButton() returns correct mouse button
+ * number when the mouse buttons are pressed and getModifiers()
+ * returns correct modifiers
+ *
+ * @library ../../../../../lib/testlibrary/ ../../helpers/lwcomponents/
+ * @build LWComponent
+ * @build LWButton
+ * @build LWList
+ * @build ExtendedRobot
+ * @run main/timeout=600 MouseButtonsTest
+ */
+
+public class MouseButtonsTest implements MouseListener {
+
+ private Frame frame;
+
+ private Button button;
+ private LWButton buttonLW;
+ private TextField textField;
+ private TextArea textArea;
+ private List list;
+ private LWList listLW;
+
+ private int buttonPressedNumber = 0;
+ private int buttonReleasedNumber = 0;
+ private int modifiers = 0;
+
+
+ private final ExtendedRobot robot;
+
+ private final static int robotDelay = 1000;
+ private final static int waitDelay = 3500;
+
+ private boolean released = false;
+ private boolean pressed = false;
+ private final Object lock;
+
+
+ MouseButtonsTest() throws Exception {
+ lock = new Object();
+ robot = new ExtendedRobot();
+ EventQueue.invokeAndWait( this::createGUI );
+ }
+
+ public void createGUI() {
+
+ frame = new Frame();
+ frame.setTitle("MouseButtonsTest");
+ frame.setLayout(new GridLayout(1, 6));
+
+ button = new Button();
+ button.addMouseListener(this);
+ frame.add(button);
+
+ buttonLW = new LWButton();
+ buttonLW.addMouseListener(this);
+ frame.add(buttonLW);
+
+ textField = new TextField(5);
+ textField.addMouseListener(this);
+ frame.add(textField);
+
+ textArea = new TextArea(5, 5);
+ textArea.addMouseListener(this);
+ frame.add(textArea);
+
+ list = new List();
+ for (int i = 1; i <= 5; ++i) { list.add("item " + i); }
+ list.addMouseListener(this);
+ frame.add(list);
+
+ listLW = new LWList();
+ for (int i = 1; i <= 5; ++i) { listLW.add("item " + i); }
+ listLW.addMouseListener(this);
+ frame.add(listLW);
+
+
+ frame.setBackground(Color.gray);
+ frame.setSize(500, 100);
+ frame.setVisible(true);
+ frame.toFront();
+ }
+
+
+ @Override
+ public void mouseClicked(MouseEvent e) {}
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+
+ assertFalse(e.getButton() == MouseEvent.NOBUTTON, "invalid button");
+
+ buttonPressedNumber = e.getButton();
+ modifiers = e.getModifiers();
+
+ pressed = true;
+
+ synchronized (lock) {
+ try {
+ lock.notifyAll();
+ } catch (Exception ex) {}
+ }
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+
+ assertFalse(e.getButton() == MouseEvent.NOBUTTON, "invalid button");
+
+ buttonReleasedNumber = e.getButton();
+ modifiers = e.getModifiers();
+
+ released = true;
+
+ synchronized (lock) {
+ try {
+ lock.notifyAll();
+ } catch (Exception ex) {}
+ }
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent e) {}
+
+ @Override
+ public void mouseExited(MouseEvent e) {}
+
+
+ void doTest() throws Exception {
+
+ int masks[] = new int[]{
+ InputEvent.BUTTON1_MASK, InputEvent.BUTTON2_MASK, InputEvent.BUTTON3_MASK};
+
+ int buttons[] = new int[]{
+ MouseEvent.BUTTON1, MouseEvent.BUTTON2, MouseEvent.BUTTON3};
+
+ ArrayList<Component> components = new ArrayList();
+ components.add(button);
+ components.add(buttonLW);
+ components.add(textField);
+ components.add(textArea);
+ components.add(list);
+ components.add(listLW);
+
+ for (Component c: components) {
+
+ System.out.println(c.getClass().getName() + ":");
+
+ Point origin = c.getLocationOnScreen();
+ int xc = origin.x + c.getWidth() / 2;
+ int yc = origin.y + c.getHeight() / 2;
+ Point center = new Point(xc, yc);
+
+ robot.delay(robotDelay);
+ robot.glide(origin, center);
+ robot.click();
+ robot.delay(robotDelay);
+
+ for (int i = 0; i < masks.length; ++i) {
+
+ pressed = false;
+ released = false;
+
+ int mask = masks[i];
+ robot.mousePress(mask);
+ robot.delay(robotDelay);
+
+ if (!pressed) {
+ synchronized (lock) {
+ try {
+ lock.wait(waitDelay);
+ } catch (InterruptedException ex) {}
+ }
+ }
+
+ assertTrue(pressed, "mouse press event was not received");
+ assertEQ((modifiers & mask), mask, "invalid mask modifiers");
+
+ robot.mouseRelease(mask);
+ robot.delay(robotDelay);
+
+ if (!released) {
+ synchronized (lock) {
+ try {
+ lock.wait(waitDelay);
+ } catch (InterruptedException ex) {}
+ }
+ }
+
+ assertTrue(released, "mouse release event was not received");
+ assertEQ((modifiers & mask), mask, "invalid mask modifiers");
+
+ assertEquals(buttonPressedNumber, buttons[i]);
+ assertEquals(buttonReleasedNumber, buttons[i]);
+
+ robot.type(KeyEvent.VK_ESCAPE);
+ robot.delay(robotDelay);
+
+ System.out.println("button " + buttons[i] + " - passed");
+ }
+ }
+
+ robot.waitForIdle();
+ frame.dispose();
+ }
+
+
+ public static void main(String[] args) throws Exception {
+
+ MouseButtonsTest test = new MouseButtonsTest();
+ test.doTest();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/MouseEvent/MultipleMouseButtonsTest/MultipleMouseButtonsTest.java Tue Jul 08 16:01:18 2014 +0400
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2001, 2014, 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 java.awt.*;
+import java.awt.event.*;
+import java.util.ArrayList;
+
+import test.java.awt.event.helpers.lwcomponents.LWButton;
+import test.java.awt.event.helpers.lwcomponents.LWList;
+
+import static jdk.testlibrary.Asserts.*;
+
+/*
+ * @test
+ * @bug 8043126
+ * @summary Check whether correct modifiers set when multiple mouse buttons were pressed;
+ * check number of received events.
+ *
+ * @library ../../../../../lib/testlibrary/ ../../helpers/lwcomponents/
+ * @build LWComponent
+ * @build LWButton
+ * @build LWList
+ * @build ExtendedRobot
+ * @run main/timeout=600 MultipleMouseButtonsTest
+ */
+
+
+public class MultipleMouseButtonsTest implements MouseListener {
+
+ private final static int robotDelay = 1000;
+
+ private final ExtendedRobot robot;
+ private final Object lock = new Object();
+
+ private Frame frame;
+
+ private Button button;
+ private LWButton buttonLW;
+ private TextField textField;
+ private TextArea textArea;
+ private List list;
+ private LWList listLW;
+
+ private int eventCount;
+ private int testCount;
+ private boolean pressed = false;
+ private int modifiers = 0;
+ private int modifiersEx = 0;
+
+ private boolean countEvents = false;
+
+
+ public void createGUI() {
+
+ frame = new Frame("MultipleMouseButtonTest");
+ frame.setLayout(new GridLayout(1, 6));
+
+ button = new Button();
+ button.addMouseListener(this);
+ frame.add(button);
+
+ buttonLW = new LWButton();
+ buttonLW.addMouseListener(this);
+ frame.add(buttonLW);
+
+ textField = new TextField(5);
+ textField.addMouseListener(this);
+ frame.add(textField);
+
+ textArea = new TextArea(5, 5);
+ textArea.addMouseListener(this);
+ frame.add(textArea);
+
+ list = new List();
+ for (int i = 1; i <= 5; ++i) { list.add("item " + i); }
+ list.addMouseListener(this);
+ frame.add(list);
+
+ listLW = new LWList();
+ for (int i = 1; i <= 5; ++i) { listLW.add("item " + i); }
+ listLW.addMouseListener(this);
+ frame.add(listLW);
+
+ frame.setBackground(Color.gray);
+ frame.setSize(500, 100);
+ frame.setVisible(true);
+ frame.toFront();
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {}
+ @Override
+ public void mouseEntered(MouseEvent e) {}
+ @Override
+ public void mouseExited (MouseEvent e) {}
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+
+ if (!countEvents) { return; }
+
+ ++eventCount;
+
+ pressed = true;
+ modifiers = e.getModifiers();
+ modifiersEx = e.getModifiersEx();
+
+ synchronized (lock) { lock.notifyAll(); }
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+
+ if (countEvents) {
+ ++eventCount;
+ }
+ }
+
+ MultipleMouseButtonsTest() throws Exception {
+ this.robot = new ExtendedRobot();
+ EventQueue.invokeAndWait( this::createGUI );
+ }
+
+ void doTest() throws Exception {
+
+ int masks[] = new int[]{InputEvent.BUTTON1_MASK, InputEvent.BUTTON2_MASK, InputEvent.BUTTON3_MASK};
+ int masksEx[] = new int[]{InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON2_DOWN_MASK, InputEvent.BUTTON3_DOWN_MASK};
+
+ robot.waitForIdle();
+
+ ArrayList<Component> components = new ArrayList();
+ components.add(button);
+ components.add(buttonLW);
+ components.add(textField);
+ components.add(textArea);
+ components.add(list);
+ components.add(listLW);
+
+ for (Component c: components) {
+
+ System.out.println(c.getClass().getName() + ": ");
+
+ Point origin = c.getLocationOnScreen();
+
+ int xc = origin.x + c.getWidth() / 2;
+ int yc = origin.y + c.getHeight() / 2;
+ Point center = new Point(xc, yc);
+
+ robot.delay(robotDelay);
+ robot.mouseMove(origin);
+ robot.delay(robotDelay);
+ robot.glide(origin, center);
+ robot.delay(robotDelay);
+ robot.click();
+ robot.delay(robotDelay);
+
+ testCount = 0;
+ eventCount = 0;
+
+ for (int i = 0; i < masks.length; ++i) {
+
+ for (int k = 0; k < masks.length; ++k) {
+ if (k == i) { continue; }
+
+ countEvents = false;
+ robot.mousePress(masks[i]);
+ robot.delay(robotDelay);
+
+ countEvents = true;
+
+ pressed = false;
+
+ robot.mousePress(masks[k]);
+ robot.delay(robotDelay);
+ ++testCount;
+
+ if (!pressed) {
+ synchronized (lock) {
+ try {
+ lock.wait(3 * robotDelay);
+ } catch (InterruptedException ex) {}
+ }
+ }
+
+ assertTrue(pressed, "mouse press event was not received");
+
+ assertEQ(modifiers & masks[k], masks[k], "invalid modifiers");
+ assertEQ(modifiersEx & masksEx[i], masksEx[i], "invalid extended modifiers");
+
+ robot.mouseRelease(masks[k]);
+ robot.delay(robotDelay);
+ ++testCount;
+
+ countEvents = false;
+
+ robot.mouseRelease(masks[i]);
+ robot.delay(robotDelay);
+
+ robot.type(KeyEvent.VK_ESCAPE);
+ robot.delay(robotDelay);
+ } //k
+ } //i
+
+ assertEquals(testCount, eventCount, "different amount of sent and received events");
+ System.out.println("passed");
+ } //component
+
+ robot.waitForIdle();
+ frame.dispose();
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ MultipleMouseButtonsTest test = new MultipleMouseButtonsTest();
+ test.doTest();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/helpers/lwcomponents/LWButton.java Tue Jul 08 16:01:18 2014 +0400
@@ -0,0 +1,418 @@
+/*
+ * Copyright (c) 2001, 2014, 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 test.java.awt.event.helpers.lwcomponents;
+
+import java.awt.*;
+import java.awt.event.*;
+
+/**
+ * Lightweight <i>Button</i> component with some nice features. This
+ * component provides the capabilities of Buttons, namely that you it
+ * displays a label string and, when clicked, causes the
+ * ActionListener method to be called.<p>
+ *
+ * The look of the button is a little unusual. There are three
+ * rectangles drawn at the border that indicate various states
+ * of the button. These are (listed from outside in)<p>
+ * <ol>
+ * <li><b>Focus</b>: Indicates that the LWButton has the focus.
+ * <li><b>Mouse Over</b>: Indicates that the mouse is over the component.
+ * <li><b>Mouse Pressed</b>: Indicates that the mouse has been pressed.
+ * </ol>
+ *
+ * In addition, when the button has been activated (mouse clicked or
+ * via keyboard activation) the button flashes briefly.
+ */
+
+public class LWButton extends LWComponent {
+
+ /*
+ * The button's Label.
+ * If Label is not specified it will default to "".
+ * @serial
+ * @see getLabel()
+ * @see setLabel()
+ */
+ private String label;
+ private boolean isInClick = false;
+
+ private static final String base = "LWButton";
+ private static int nameCounter = 0;
+
+ private transient ActionListener actionListener;
+
+ /*
+ * The action to be performaed once a button has been
+ * pressed.
+ * actionCommand can be null.
+ * @serial
+ * @see getActionCommand()
+ * @see setActionCommand()
+ */
+ String actionCommand;
+
+ Color colMousePressed;
+
+ public LWButton() { this(""); }
+
+ public LWButton(String label) {
+ this(label, Color.red, Color.green, Color.white);
+ }
+
+ /**
+ * Initialize the LWButton, fully specifying all parameters.
+ * @param label The string to display.
+ * @param fgnd The color to draw the label in.
+ * @param bkgnd The color of the button itself.
+ * @param mousePressed The Color of the MousePressed rectangle.
+ */
+ public LWButton(String label, Color fgnd, Color bkgnd, Color mousePressed) {
+ super();
+ this.label = label;
+ setBackground(fgnd);
+ setForeground(bkgnd);
+ colMousePressed = mousePressed;
+ setName(makeComponentName());
+
+ enableEvents( AWTEvent.MOUSE_EVENT_MASK
+ | AWTEvent.KEY_EVENT_MASK
+ | AWTEvent.ACTION_EVENT_MASK);
+ setEnabled(true);
+ }
+
+ /**
+ * Make the component flash briefly.
+ */
+ public void flash() {
+ isInClick = true;
+ repaint();
+
+ class unClicker implements Runnable {
+ @Override
+ public void run() {
+ try { Thread.sleep(100); } catch (InterruptedException ee) {}
+ isInClick = false;
+ repaint();
+ }
+ }
+ try {
+ unClicker uc = new unClicker();
+ new Thread(uc).start();
+ } catch (Exception e) {
+ // In case we're in an applet and the security has not been
+ // turned off (in which case we can't start a new thread)
+ // we can catch that and set the flag back to how it should be.
+ isInClick = false;
+ repaint();
+ }
+ }
+
+ /**
+ * Set the MousePressed color (the color shown in the MousePressed rectangle
+ * when the mouse is over the component).
+ * @param c The color of the MousePressed rectangle.
+ */
+ public void setMousePressedColor(Color c) { colMousePressed = c; }
+
+ /**
+ * Get the MousePressed color.
+ * @return The color of the MousePressed rectangle.
+ */
+ public Color getMousePressedColor() { return colMousePressed; }
+
+ /**
+ * Used to dispatch out the ActionEvent for a corresponding InputEvent.
+ * @param e The InputEvent that is causing the ActionEvent dispatch.
+ */
+ private void sendActionEvent(InputEvent e) {
+
+ int modifiers = e.getModifiers();
+ int aModifiers = 0;
+
+ if ((modifiers & MouseEvent.SHIFT_MASK) != 0) {
+ aModifiers |= ActionEvent.SHIFT_MASK;
+ }
+ if ((modifiers & MouseEvent.CTRL_MASK) != 0) {
+ aModifiers |= ActionEvent.CTRL_MASK;
+ }
+ if ((modifiers & MouseEvent.META_MASK) != 0) {
+ aModifiers |= ActionEvent.META_MASK;
+ }
+ if ((modifiers & MouseEvent.ALT_MASK) != 0) {
+ aModifiers |= ActionEvent.ALT_MASK;
+ }
+
+ ActionEvent ae = new ActionEvent(this,
+ ActionEvent.ACTION_PERFORMED,
+ actionCommand,
+ aModifiers);
+ // XXX: What's the right way to send out the ActionEvent?
+ // My assumption was to put it into the system event queue
+ // and the it will be dispatched back into <i>processEvent</i>
+ // for us. However this doesn't happen...?
+ if (actionListener != null) {
+ actionListener.actionPerformed(ae);
+ }
+ //Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ae);
+ }
+
+ /**
+ * Set whether the component is enabled ({@code true}) or not.
+ * @param enabled If {@code true}, the component is to be enabled.
+ */
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+
+ if (enabled) {
+ enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
+ } else {
+ disableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
+ }
+ repaint(1);
+ }
+
+ /**
+ * Indicates that LWButton component can receive focus.
+ * @return {@code true} if the LWButton component can receive focus
+ */
+ @Override
+ public boolean isFocusTraversable() { return true; }
+
+ /**
+ * Construct a name for this component. Called by getName() when the
+ * name is null.
+ */
+ String makeComponentName() {
+ synchronized (getClass()) {
+ return base + nameCounter++;
+ }
+ }
+
+ /**
+ * Handle painting the enabled version of the component.
+ *
+ * ASSUMES: g.color may be changed
+ */
+ @Override
+ public void paint(Graphics g) {
+
+ super.paint(g);
+ restrictGraphicsToClientArea(g);
+
+ Dimension dim = getClientSize();
+
+ int s = Math.min(dim.width - 1, dim.height - 1);
+
+ if (isInClick) {
+ g.setColor(Color.white);
+ } else {
+ g.setColor(getBackground());
+ }
+
+ // In jdk 1.2 (pre-release) there was a bug using clearRect
+ // to paint the background of a lightweight.
+ //g.clearRect(loc.x, loc.y, dim.width, dim.height);
+ g.fillRect(0, 0, dim.width, dim.height);
+
+ if (mouseB1Pressed) {
+ g.setColor(colMousePressed);
+ //LWComponent.traceMsg("paint mousePressed " + this.toString());
+ g.drawRect(1, 1, dim.width - 3, dim.height - 3);
+ }
+
+ Font f = getFont();
+ if (f != null) {
+ FontMetrics fm = getFontMetrics(f);
+ g.setColor(getForeground());
+ g.drawString(label,
+ s/2 - fm.stringWidth(label)/2,
+ s/2 + fm.getMaxDescent());
+ }
+
+ unrestrictGraphicsFromClientArea(g);
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ Font f = getFont();
+ if (f != null) {
+ FontMetrics fm = getFontMetrics(f);
+ int max = Math.max(fm.stringWidth(label) + 40, fm.getHeight() + 40);
+ return new Dimension(max, max);
+ } else {
+ return new Dimension(100, 100);
+ }
+ }
+
+ @Override
+ public Dimension getMinimumSize() {
+ return getPreferredSize();
+ }
+
+ /**
+ * Get the text displayed in the LWButton.
+ * @return the text displayed in the LWButton
+ */
+ public String getText() { return label; }
+
+ /**
+ * Set the text displayed in the LWButton.
+ * @param s The text to be displayed.
+ */
+ public void setText(String s) {
+ Font f = getFont();
+ int oWidth = 0;
+ int oHeight = 0;
+ int nWidth = 0;
+ int nHeight = 0;
+ int invalidated = 0;
+ FontMetrics fm = null;
+
+ if (f != null) {
+ fm = getFontMetrics(f);
+ oWidth = fm.stringWidth(label);
+ oHeight = fm.getHeight();
+ }
+
+ this.label = s;
+
+ if (f != null) {
+ nWidth = fm.stringWidth(label);
+ nHeight = fm.getHeight();
+
+ if ((nWidth > oWidth) || (nHeight > oHeight)) {
+ invalidate();
+ invalidated = 1;
+ }
+ }
+
+ if (invalidated == 0) {
+ repaint();
+ }
+ }
+
+ /**
+ * Set the command name for the action event fired
+ * by this button. By default this action command is
+ * set to match the label of the button.
+ * @param command A string used to set the button's
+ * action command.
+ * If the string is <code>null</code> then the action command
+ * is set to match the label of the button.
+ * @see java.awt.event.ActionEvent
+ * @since JDK1.1
+ */
+ public void setActionCommand(String command) {
+ actionCommand = command;
+ }
+
+ /**
+ * Returns the command name of the action event fired by this button.
+ * If the command name is {@code null} (default) then this method
+ * returns the label of the button.
+ *
+ * @return the command name of the action event fired by this button
+ * or the label of the button (in case of {@code null})
+ */
+ public String getActionCommand() {
+ return (actionCommand == null? label : actionCommand);
+ }
+
+ /**
+ * Add the specified action listener to receive action events from
+ * this button. Action events occur when a user presses or releases
+ * the mouse over this button.
+ * @param l the action listener.
+ * @see java.awt.event.ActionListener
+ * @see #removeActionListener
+ * @since JDK1.1
+ */
+ public synchronized void addActionListener(ActionListener l) {
+ actionListener = AWTEventMulticaster.add(actionListener, l);
+ enableEvents(AWTEvent.MOUSE_EVENT_MASK);
+ }
+
+ /**
+ * Remove the specified action listener so that it no longer
+ * receives action events from this button. Action events occur
+ * when a user presses or releases the mouse over this button.
+ * @param l the action listener.
+ * @see java.awt.event.ActionListener
+ * @see #addActionListener
+ * @since JDK1.1
+ */
+ public synchronized void removeActionListener(ActionListener l) {
+ actionListener = AWTEventMulticaster.remove(actionListener, l);
+ }
+
+ @Override
+ protected void processKeyEvent(KeyEvent e) {
+ super.processKeyEvent(e);
+ if (!isEnabled()) { return; }
+ switch(e.getID()) {
+ case KeyEvent.KEY_TYPED:
+ switch (e.getKeyCode()) {
+ case KeyEvent.VK_ENTER:
+ case KeyEvent.VK_SPACE:
+ flash();
+ sendActionEvent(e);
+ break;
+ }
+ break;
+ }
+ }
+
+ @Override
+ protected void processMouseEvent(MouseEvent e) {
+ super.processMouseEvent(e);
+ if (!isEnabled()) { return; }
+ switch(e.getID()) {
+ case MouseEvent.MOUSE_PRESSED:
+ requestFocus();
+ repaint();
+ break;
+ case MouseEvent.MOUSE_RELEASED:
+ repaint();
+ break;
+ case MouseEvent.MOUSE_CLICKED:
+ if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0) {
+ flash();
+ sendActionEvent(e);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Returns the parameter string representing the state of this
+ * button. This string is useful for debugging.
+ * @return the parameter string of this button.
+ */
+ @Override
+ protected String paramString() {
+ return super.paramString() + ", label = " + label;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/helpers/lwcomponents/LWComponent.java Tue Jul 08 16:01:18 2014 +0400
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2001, 2014, 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 test.java.awt.event.helpers.lwcomponents;
+
+import java.io.*;
+import java.awt.*;
+import java.awt.event.*;
+
+/**
+ * This is experimental - The idea is to subclass all the LW components
+ * from LWComponent to provide for some common capabilities. The main
+ * capability to be provided is the status rectangles as done for LWButton.
+ * In particular the Focus and MouseOver rectangles are generically
+ * useful, while other rectangles might be useful to other components.<p>
+ *
+ * To implement that, here is the idea ... borrowed from Win32 ... Each
+ * of the LW components has both a client and non-client region. We
+ * call paintNC to paint the non-client region (Focus and MouseOver
+ * rectangles), and the subclass might be permitted to implement paintNC
+ * but for now they aren't.<p>
+ *
+ * Then the paint{Enabled,Disabled} methods are called as appropriate.
+ * Note that paintDisabled is implemented in LWComponent to call paintEnabled
+ * then stipple over the top of it.<p>
+ *
+ * So it is paintEnabled that the component should implement. This method
+ * needs to know the dimensions of the client area (getClientRegion?) and
+ * the Graphics needs to have it's clip region set appropriately.<p>
+ *
+ * <b>KVETCHING</b>: <i>Kvetch</i> is a Yiddish word which means, basically,
+ * to complain very precisely. The LWComponent family tracks various pieces
+ * of information over time that are used to check closely for correct behavior
+ * in some circumstances. The method <i>kvetch</i> is where this code lives
+ * and is intended to check a broad range of conditions.<p>
+ *
+ * To turn off specific kvetch's, one simply specifies a System property
+ * as in this table:<p>
+ *
+ * <table border="1">
+ * <tr><th>Property name</th><th>Value</th><th>Discussion</th></tr>
+ * <tr>
+ * <th>javasoft.awtsqe.lw.IGNORE_FOCUS_KVETCH</th>
+ * <th>true or false</th>
+ * <td>Specify whether the <i>hasFocus</i> kvetch is checked.</td>
+ * </tr>
+ * </table><p>
+ *
+ * <b>XXX To implement</b> - specifying colors. NCBackground,
+ * FocusRectColor, MouseOverColor are the threee colors. paintNC
+ * fills the NC region with NCBackground, and then pains the two
+ * colors as appropriate. There needs to be methods to get/specify
+ * these colors.<p>
+ *
+ * <b>XXX To implement</b> - Specifying the component name and toString().
+ * The subclass should only give the base class name, and a method
+ * in LWComponent should construct a name from that. For toString()
+ * there needs to be a small amount of infrastructure built.<p>
+ */
+
+public abstract class LWComponent extends Component {
+
+ protected static Color ncBackgroundColor;
+ protected static Color focusColor;
+ protected static Color focusWrongColor;
+ protected static Color mouseOverColor;
+
+ static {
+ ncBackgroundColor = Color.white;
+ focusColor = Color.black;
+ focusWrongColor = Color.magenta;
+ mouseOverColor = Color.blue;
+ }
+
+ /**
+ * Flag indicating whether our records indicate that the component
+ * should have focus.
+ */
+ protected boolean _shouldHaveFocus = false;
+ protected boolean _shouldBeShowing = false;
+
+ protected boolean mouseB1Pressed = false;
+ protected boolean mouseB2Pressed = false;
+ protected boolean mouseB3Pressed = false;
+ protected boolean mouseInside = false;
+
+ protected static boolean tracingOn = false;
+ protected static PrintStream traceOutput = null;
+
+ // Uncommenting these lines turns on tracing for the package.
+ // static {
+ // tracingOn = true;
+ // traceOutput = System.err;
+ // }
+
+ public LWComponent() {
+ enableEvents(AWTEvent.MOUSE_EVENT_MASK
+ /*| AWTEvent.MOUSE_MOTION_EVENT_MASK*/
+ | AWTEvent.FOCUS_EVENT_MASK
+ | AWTEvent.COMPONENT_EVENT_MASK);
+ }
+
+ /**
+ * Print out an error message.
+ * @param msg the message
+ */
+ public static void errorMsg(String msg) {
+ System.err.println("ERROR: " + msg);
+ }
+
+ /**
+ * Print out a tracing message
+ * @param msg the message
+ */
+ public static void traceMsg(String msg) {
+ if (LWComponent.tracingOn) {
+ LWComponent.traceOutput.println(msg);
+ }
+ }
+
+ /////////////////////////////////////////////
+ /////// FLAGS FOR IGNORING KVETCH's /////////
+ /////////////////////////////////////////////
+
+ static boolean bIgnFocus = false;
+
+ static {
+ // Initialize the kvetch ignoring flags here.
+ String ignFocus = System.getProperty("javasoft.awtsqe.lw.IGNORE_FOCUS_KVETCH",
+ "false");
+ bIgnFocus = ignFocus.trim().toLowerCase().equals("true");
+ }
+
+ /**
+ * Check the <i>shoulds</i> and return a string indicating which
+ * do not match the components actual state.
+ *
+ * @return the string indicating which do not match the components actual state
+ */
+ public String kvetch() {
+ String ret = this.toString();
+ boolean errors = false;
+
+ if (!bIgnFocus) {
+ if (hasFocus()) {
+ if (!shouldHaveFocus()) {
+ ret += "\nERROR: hasFocus indicates we have Focus, when we shouldn't.";
+ errors = true;
+ }
+ } else {
+ if (shouldHaveFocus()) {
+ ret += "\nERROR: (see bug#4233658) hasFocus does not indicate we have Focus, when we should.";
+ errors = true;
+ }
+ }
+ }
+
+ if (errors) {
+ return ret;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Check the <i>shoulds</i> and return a string indicating which
+ * do not match the components actual state. Prints the output
+ * to the given PrintStream.
+ * @param out The PrintStream to print to.
+ */
+ public void kvetch(PrintStream out) {
+ if (out != null) {
+ String s = kvetch();
+ if (s != null) {
+ LWComponent.errorMsg(s);
+ }
+ }
+ }
+
+ /**
+ * Turn on tracing for the LWComponent family.
+ * @param out the output stream
+ */
+ public static void startTracing(PrintStream out) {
+ tracingOn = true;
+ traceOutput = out;
+ }
+
+ /**
+ * Turn off tracing for the LWComponent family.
+ */
+ public static void stopTracing() { tracingOn = false; traceOutput = null; }
+
+ /**
+ * Indicate whether it is believed the component should have focus.
+ * @return {@code true} if the component should have focus
+ */
+ public boolean shouldHaveFocus() { return _shouldHaveFocus; }
+
+ /**
+ * Indicate whether it is believed the component should be showing.
+ * @return {@code true} if the component should be showing
+ */
+ public boolean shouldBeShowing() { return _shouldBeShowing; }
+
+ @Override
+ protected void processFocusEvent(FocusEvent e) {
+ super.processFocusEvent(e);
+ LWComponent.traceMsg("processFocusEvent " + e.toString());
+ switch (e.getID()) {
+ case FocusEvent.FOCUS_GAINED:
+ _shouldHaveFocus = true;
+ repaint();
+ break;
+ case FocusEvent.FOCUS_LOST:
+ _shouldHaveFocus = false;
+ repaint();
+ break;
+ }
+ }
+
+ @Override
+ protected void processComponentEvent(ComponentEvent e) {
+ super.processComponentEvent(e);
+ LWComponent.traceMsg("processComponentEvent " + e.toString());
+ switch (e.getID()) {
+ case ComponentEvent.COMPONENT_MOVED: break;
+ case ComponentEvent.COMPONENT_RESIZED: break;
+ case ComponentEvent.COMPONENT_SHOWN: _shouldBeShowing = true; break;
+ case ComponentEvent.COMPONENT_HIDDEN: _shouldBeShowing = false; break;
+ }
+ }
+
+ @Override
+ protected void processMouseEvent(MouseEvent e) {
+ int mod = e.getModifiers();
+ super.processMouseEvent(e);
+ LWComponent.traceMsg("processMouseEvent " + e.toString());
+ switch (e.getID()) {
+ case MouseEvent.MOUSE_PRESSED:
+ if ((mod & MouseEvent.BUTTON1_MASK) != 0) {
+ if (mouseB1Pressed) {
+ errorMsg("ERROR: MOUSE_PRESSED for B1 when already pressed, on "
+ + this.toString());
+ }
+ mouseB1Pressed = true;
+ break;
+ }
+ if ((mod & MouseEvent.BUTTON2_MASK) != 0) {
+ if (mouseB2Pressed) {
+ errorMsg("ERROR: MOUSE_PRESSED for B2 when already pressed, on "
+ + this.toString());
+ }
+ mouseB2Pressed = true;
+ break;
+ }
+ if ((mod & MouseEvent.BUTTON3_MASK) != 0) {
+ if (mouseB3Pressed) {
+ errorMsg("ERROR: MOUSE_PRESSED for B3 when already pressed, on "
+ + this.toString());
+ }
+ mouseB3Pressed = true;
+ break;
+ }
+ repaint();
+ break;
+ case MouseEvent.MOUSE_RELEASED:
+ if ((mod & MouseEvent.BUTTON1_MASK) != 0) {
+ if (!mouseB1Pressed) {
+ errorMsg("ERROR: MOUSE_RELEASED for B1 when not pressed, on "
+ + this.toString());
+ }
+ mouseB1Pressed = false;
+ break;
+ }
+ if ((mod & MouseEvent.BUTTON2_MASK) != 0) {
+ if (!mouseB2Pressed) {
+ errorMsg("ERROR: MOUSE_RELEASED for B2 when not pressed, on "
+ + this.toString());
+ }
+ mouseB2Pressed = false;
+ break;
+ }
+ if ((mod & MouseEvent.BUTTON3_MASK) != 0) {
+ if (!mouseB3Pressed) {
+ errorMsg("ERROR: MOUSE_RELEASED for B3 when not pressed, on "
+ + this.toString());
+ }
+ mouseB3Pressed = false;
+ break;
+ }
+ repaint();
+ break;
+ case MouseEvent.MOUSE_CLICKED:
+ break;
+ case MouseEvent.MOUSE_ENTERED:
+ if (mouseInside) {
+ errorMsg("ERROR: MOUSE_ENTERED when mouse already inside component, on "
+ + this.toString());
+ }
+ mouseInside = true;
+ repaint();
+ break;
+ case MouseEvent.MOUSE_EXITED:
+ if (!mouseInside) {
+ errorMsg("ERROR: MOUSE_EXITED when mouse not inside component, on "
+ + this.toString());
+ }
+ mouseInside = false;
+ repaint();
+ break;
+ case MouseEvent.MOUSE_MOVED:
+ break;
+ case MouseEvent.MOUSE_DRAGGED:
+ break;
+ }
+ }
+
+ public Point getClientLocation() {
+ return new Point(5, 5);
+ }
+
+ public Dimension getClientSize() {
+ Dimension dim = getSize();
+ dim.width -= 10;
+ dim.height -= 10;
+ return dim;
+ }
+
+ public Rectangle getClientBounds() {
+ Dimension dim = getClientSize();
+ return new Rectangle(5, 5, dim.width, dim.height);
+ }
+
+ public int getClientX() { return 5; }
+ public int getClientY() { return 5; }
+
+ /**
+ * Set the color used for painting the non-client area of the component.
+ * The default for this is Color.white.
+ *
+ * @param c The new color to use.
+ */
+ public void setNonClientColor(Color c) {
+ LWComponent.ncBackgroundColor = c;
+ }
+
+ /**
+ * Handle painting for the component.
+ */
+ @Override
+ public void paint(Graphics g) {
+ Dimension dim = getSize();
+
+ kvetch(System.err);
+
+ Color saveColor = g.getColor();
+ super.paint(g);
+
+ // ------------------- Paint the background -----------------
+
+ // In jdk 1.2 (pre-release) there was a bug using clearRect
+ // to paint the background of a lightweight.
+ //g.clearRect(0, 0, dim.width, dim.height);
+ g.setColor(getBackground());
+ g.fillRect(0, 0, dim.width, dim.height);
+
+ // ------------------- Paint the non-client area ------------
+
+ g.setColor(ncBackgroundColor);
+ // x y width height
+ g.fillRect(0, 0, dim.width, 5);
+ g.fillRect(0, 5, 5, dim.height - 10);
+ g.fillRect(dim.width - 5, 5, 5, dim.height - 10);
+ g.fillRect(0, dim.height - 5, dim.width, 5);
+
+ if (shouldHaveFocus() || hasFocus()) {
+ g.setColor(shouldHaveFocus() && hasFocus()
+ ? focusColor
+ : focusWrongColor);
+ g.drawRect(1, 1, dim.width - 3, dim.height - 3);
+ }
+
+ if (mouseInside) {
+ g.setColor(mouseOverColor);
+ g.drawRect(3, 3, dim.width - 7, dim.height - 7);
+ }
+
+ // ------------------- Paint disabledness, if true -----------
+
+ if (!isEnabled()) {
+ g.setColor(getBackground());
+ Dimension size = getSize();
+ int borderThickness = 0;
+ int startX = borderThickness;
+ int startY = borderThickness;
+ int endX = startX + size.width - 2 * borderThickness - 2;
+ int endY = startY + size.height - 2 * borderThickness - 2;
+ int x, y;
+ for (y = startY; y <= endY; y += 1) {
+ for (x = startX + (y % 2); x <= endX; x += 2) {
+ g.fillRect(x, y, 1, 1);
+ } // x
+ } // y
+ }
+
+ g.setColor(saveColor);
+ }
+
+ /**
+ * Restricts the Graphics to be within the "client area" of the
+ * component. Recall that the LWComponent series of components has
+ * a "non-client area" of 5 pixels wide in which it draws two
+ * status rectangles showing mouse-over and has-focus status. <p>
+ *
+ * Child classes of LWComponent are to call {@code restrictGraphicsToClientArea}
+ * at the beginning of their {@code paint} method, and then call
+ * {@code unrestrictGraphicsFromClientArea} afterwards.<p>
+ *
+ * In order to make those paint methods as convenient as possible, these
+ * two methods make it appear as if the Graphics available to the
+ * component is slightly smaller than it really is, by the amount
+ * used in the non-client area (5 pixel wide border).<p>
+ *
+ * @param g The Graphics to restrict.
+ */
+ public void restrictGraphicsToClientArea(Graphics g) {
+ Dimension dim = getSize();
+ g.translate(5, 5);
+ g.setClip(0, 0, dim.width - 10, dim.height - 10);
+ }
+
+ /**
+ * Undo the restriction done in restrictGraphicsToClientArea.
+ *
+ * @param g The Graphics to unrestrict.
+ */
+ public void unrestrictGraphicsFromClientArea(Graphics g) {
+ g.translate(-5, -5);
+ Dimension dim = getSize();
+ g.setClip(0, 0, dim.width, dim.height);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/helpers/lwcomponents/LWList.java Tue Jul 08 16:01:18 2014 +0400
@@ -0,0 +1,726 @@
+/*
+ * Copyright (c) 1999, 2014, 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 test.java.awt.event.helpers.lwcomponents;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.Vector;
+import java.util.Enumeration;
+
+/**
+ * Remarks : Source for LightWeight component - List.
+ *
+ * Scroll bar support is not available for this component, so if the
+ * items exceeds visibility those items will be truncated. Also, here
+ * double buffering is not used so there will be little bit flickering
+ * while it repaints. Item listener support is not enabled in this
+ * component. Listeners handled were Mouse, Key and Focus.
+ *
+ * @author R.Govindarajan (govind@siptech.co.in), G.N.V.Sekhar (sekharv@siptech.co.in)
+ */
+
+public class LWList extends LWComponent implements ItemSelectable {
+
+ // Constants used for component size
+ private final int MIN_WIDTH = 100;
+ private final int MIN_HEIGHT = 100;
+ private final int PREF_WIDTH = 100;
+ private final int PREF_HEIGHT = 100;
+
+ // Constants used for setting color for component
+ private final Color BACK_COLOR = Color.white;
+ private final Color FRONT_COLOR = Color.black;
+ private final Color BORDER_COLOR = Color.darkGray;
+ private final Color FOCUS_COLOR = Color.blue;
+ private final Color FOCUS_FORECOLOR = Color.white;
+ private final Color FOCUS_ENABLED_COLOR = Color.red;
+ private final int BORDER_WIDTH = 2;
+
+ private Vector stringList; // List of items
+ private Vector selList; // List of selected items
+ private int rows; // Visible rows
+ private int focusIndex, prevfocusIndex;
+ private Dimension minSize;
+ private Dimension prefSize;
+ private boolean pressed, eventOccurred, focusEnabled;
+ private boolean multipleMode;
+
+ // Listeners handled for this component
+ private ActionListener actionListener;
+ private KeyListener keyListener;
+ private FocusListener focusListener;
+ private ItemListener itemListener;
+
+ private static int nameCounter = 0;
+
+ /**
+ * Creates a new list.
+ */
+ public LWList() {
+ this(0);
+ }
+
+ /**
+ * Creates a new list with the specified number of rows;
+ * multiple selection mode is disabled.
+ *
+ * @param i the number of rows
+ */
+ public LWList(int i) {
+ this(i, false);
+ }
+
+ /**
+ * Creates a new list with the specified number of rows and multiple selection mode.
+ *
+ * @param rows the number of rows
+ * @param flag determines whether the list allows multiple selections
+ */
+ public LWList(int rows, boolean flag) {
+ multipleMode = flag;
+ this.rows = rows;
+ minSize = new Dimension(MIN_WIDTH, MIN_HEIGHT);
+ prefSize = new Dimension(PREF_WIDTH, PREF_HEIGHT);
+ stringList = new Vector();
+ selList = new Vector();
+ selList.addElement(0);
+ focusIndex = -1;
+ prevfocusIndex = focusIndex;
+ enableEvents(AWTEvent.MOUSE_EVENT_MASK);
+ enableEvents(AWTEvent.KEY_EVENT_MASK);
+ enableEvents(AWTEvent.FOCUS_EVENT_MASK);
+ enableEvents(AWTEvent.ITEM_EVENT_MASK);
+ setName(makeComponentName()); // set the name to the component
+ }
+
+ String makeComponentName() {
+ String s = "LWList" + nameCounter++;
+ return s;
+ }
+
+ /**
+ * Set whether the component is enabled or not.
+ * @param enabled if {@code true}, the component is to be enabled
+ */
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+
+ if (enabled) {
+ enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
+ } else {
+ disableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
+ }
+ repaint(1);
+ }
+
+ /**
+ * Set the selection mode.
+ *
+ * @param flag determines whether the list allows multiple selections
+ */
+ public void setSelectionMode(boolean flag) {
+ multipleMode = flag;
+ }
+
+ /**
+ * Check if the list allows multiple selections.
+ *
+ * @return {@code true} if the list allows multiple selections
+ */
+ public boolean isMultipleMode() {
+ return multipleMode;
+ }
+
+ /**
+ * Add the specified item.
+ *
+ * @param listItem the item
+ */
+ public void add(String listItem) {
+ stringList.addElement(listItem);
+ invalidate();
+ repaint();
+ }
+
+ /**
+ * Get minimum dimension for the list.
+ *
+ * @return the minimum dimensions for displaying
+ */
+ @Override
+ public Dimension getMinimumSize() {
+ return minSize;
+ }
+
+ /**
+ * Get the preferred size of the list.
+ *
+ * @return the preferred dimensions for displaying
+ */
+ @Override
+ public Dimension getPreferredSize() {
+ return prefSize;
+ }
+
+ /**
+ * Get the background color for the component.
+ *
+ * @return the background color for the component
+ */
+ @Override
+ public Color getBackground() {
+ return BACK_COLOR;
+ }
+
+ /**
+ * Get the foreground color for the component.
+ *
+ * @return the foreground color for the component
+ */
+ @Override
+ public Color getForeground() {
+ return FRONT_COLOR;
+ }
+
+ /**
+ * Get the border color for the component.
+ *
+ * @return the border color for the component
+ */
+ public Color getBorder() {
+ return BORDER_COLOR;
+ }
+
+ /**
+ * Get background color for the selected item.
+ *
+ * @return the color for the selected item
+ */
+ public Color getFocusColor() {
+ return FOCUS_COLOR;
+ }
+
+ /**
+ * Get foreground color for the selected item.
+ *
+ * @return the foreground color for the selected item
+ */
+ public Color getFocusForeColor() {
+ return FOCUS_FORECOLOR;
+ }
+
+ /**
+ * Get a "focus enabled" color - a small rectangle around the item
+ * should be drawn when the component got the focus.
+ *
+ * @return the "focus enabled" color
+ */
+ public Color getFocusEnabledColor() {
+ return FOCUS_ENABLED_COLOR;
+ }
+
+ /**
+ * Get border width.
+ *
+ * @return the border width
+ */
+ public int getBorderWidth() {
+ return BORDER_WIDTH;
+ }
+
+ /**
+ * Get the list item count.
+ *
+ * @return the count of items
+ */
+ public int getItemCount() {
+ return stringList.size();
+ }
+
+ /**
+ * Get the specified item from the list.
+ *
+ * @param index the index
+ * @return the item string
+ */
+ public String getItem(int index) {
+ return (String)stringList.elementAt(index);
+ }
+
+ /**
+ * Get array of items from the list.
+ *
+ * @return the array of item strings
+ */
+ public String[] getItems() {
+ String str[] = new String[getItemCount()];
+ int count = 0;
+ for (Enumeration e = stringList.elements(); e.hasMoreElements(); ) {
+ str[count++] = (String)e.nextElement();
+ }
+ return str;
+ }
+
+ /**
+ * Check whether the component can be a focus owner (explicitly enabled here).
+ *
+ * @return {@code true} if the component is focusable
+ */
+ @Override
+ public boolean isFocusTraversable() {
+ return true;
+ }
+
+ /**
+ * Check whether mouse click point lies within the list of items.
+ *
+ * @param pt the click point
+ * @return {@code true} if the click point lies within the list of items
+ */
+ @Override
+ public boolean contains(Point pt) {
+ Rectangle rect = new Rectangle();
+ Dimension d = getSize();
+ rect.x = getBorderWidth();
+ rect.y = getBorderWidth();
+ rect.width = d.width - (getBorderWidth() * 2);
+ rect.height = d.height - (getBorderWidth() * 2);
+ return rect.contains(pt);
+ }
+
+ /**
+ * Given a click point the item that has to be selected is found from the list
+ * and focusIndex variable is set accordingly.
+ *
+ * @param pt the click point
+ */
+ private void findSelectedIndex(Point pt) {
+ Font f = getFont();
+ FontMetrics fm = getFontMetrics(f);
+ focusIndex = pt.y / fm.getHeight() - 1;
+ if (multipleMode) {
+ Integer fi = focusIndex;
+ if (selList.contains(fi)) {
+ int i = selList.indexOf(fi);
+ selList.removeElementAt(i);
+ } else {
+ selList.addElement(fi);
+ }
+ }
+ }
+
+ /**
+ * Set index of the selected item.
+ *
+ * @param index the index
+ */
+ public void setSelectedIndex(int index) {
+ prevfocusIndex = focusIndex;
+ focusIndex = index;
+ }
+
+ /**
+ * Get the selected item index.
+ *
+ * @return the selected item index.
+ */
+ public int getSelectedIndex() {
+ return focusIndex;
+ }
+
+ /**
+ * Get an array of the selected Objects.
+ *
+ * @return array of the Objects
+ */
+ @Override
+ public Object[] getSelectedObjects() {
+ int ai[] = getSelectedIndexes();
+ Object aobj[] = new Object[selList.size()];
+ for (int i = 0; i < selList.size(); i++) {
+ aobj[i] = stringList.elementAt(ai[i]);
+ }
+ return aobj;
+ }
+
+ /**
+ * Get an array of the selected item indices.
+ *
+ * @return the array of the indices
+ */
+ public int[] getSelectedIndexes() {
+ int ai[] = new int[selList.size()];
+ for (int i = 0; i < selList.size(); i++) {
+ ai[i] = ((Integer)selList.elementAt(i));
+ }
+ return ai;
+ }
+
+ /**
+ * Add the specified item listener to receive item events from the list.
+ *
+ * @param itemlistener the item listener
+ */
+ @Override
+ public synchronized void addItemListener(ItemListener itemlistener) {
+ itemListener = AWTEventMulticaster.add(itemListener, itemlistener);
+ enableEvents(AWTEvent.ITEM_EVENT_MASK);
+ }
+
+ /**
+ * Remove the specified item listener so
+ * that it no longer receives item events from this list.
+ *
+ * @param itemlistener the item listener
+ */
+ @Override
+ public synchronized void removeItemListener(ItemListener itemlistener) {
+ itemListener = AWTEventMulticaster.remove(itemListener, itemlistener);
+ }
+
+ /**
+ * Add the specified action listener to receive action events from this list.
+ *
+ * @param listener the action listener
+ */
+ public synchronized void addActionListener(ActionListener listener) {
+ actionListener = AWTEventMulticaster.add(actionListener, listener);
+ enableEvents(AWTEvent.MOUSE_EVENT_MASK);
+ }
+
+ /**
+ * Remove the specified action listener so
+ * that it no longer receives action events from this list.
+ *
+ * @param listener the action listener
+ */
+ public synchronized void removeActionListener(ActionListener listener) {
+ actionListener = AWTEventMulticaster.remove(actionListener, listener);
+ }
+
+ /**
+ * Add the specified key listener to receive key events from this component.
+ *
+ * @param listener the key listener
+ */
+ @Override
+ public synchronized void addKeyListener(KeyListener listener) {
+ keyListener = AWTEventMulticaster.add(keyListener, listener);
+ enableEvents(AWTEvent.KEY_EVENT_MASK);
+ }
+
+ /**
+ * Remove the specified key listener so
+ * that it no longer receives key events from this component.
+ *
+ * @param listener the key listener
+ */
+ @Override
+ public synchronized void removeKeyListener(KeyListener listener) {
+ keyListener = AWTEventMulticaster.remove(keyListener, listener);
+ }
+
+ /**
+ * Add the specified focus listener to receive focus events
+ * from this component when it gains input focus.
+ *
+ * @param listener the focus listener
+ */
+ @Override
+ public synchronized void addFocusListener(FocusListener listener) {
+ focusListener = AWTEventMulticaster.add(focusListener, listener);
+ enableEvents(AWTEvent.FOCUS_EVENT_MASK);
+ }
+
+ /**
+ * Remove the specified focus listener so
+ * that it no longer receives focus events from this component.
+ *
+ * @param listener the focus listener
+ */
+ @Override
+ public synchronized void removeFocusListener(FocusListener listener) {
+ focusListener = AWTEventMulticaster.remove(focusListener, listener);
+ }
+
+ @Override
+ protected void processEvent(AWTEvent awtevent) {
+
+ if (awtevent instanceof FocusEvent) {
+ processFocusEvent((FocusEvent)awtevent);
+ } else if (awtevent instanceof ItemEvent) {
+ processItemEvent((ItemEvent)awtevent);
+ } else if (awtevent instanceof KeyEvent) {
+ processKeyEvent((KeyEvent)awtevent);
+ } else if (awtevent instanceof MouseEvent) {
+ switch (awtevent.getID()) {
+ case MouseEvent.MOUSE_CLICKED:
+ case MouseEvent.MOUSE_PRESSED:
+ case MouseEvent.MOUSE_RELEASED:
+ case MouseEvent.MOUSE_ENTERED:
+ case MouseEvent.MOUSE_EXITED:
+ processMouseEvent((MouseEvent)awtevent);
+ break;
+
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ super.processEvent((MouseEvent)awtevent);
+ break;
+ }
+ } else {
+ if (awtevent instanceof ComponentEvent)
+ super.processComponentEvent((ComponentEvent)awtevent);
+ else
+ super.processEvent(awtevent);
+ }
+ }
+
+ protected void processItemEvent(ItemEvent itemevent) {
+ if (itemListener != null) {
+ itemListener.itemStateChanged(itemevent);
+ }
+ }
+
+ @Override
+ protected void processFocusEvent(FocusEvent e) {
+ switch (e.getID()) {
+ case FocusEvent.FOCUS_GAINED:
+ if (focusListener != null) { focusListener.focusGained(e); }
+ if (getSelectedIndex() == -1) { setSelectedIndex(0); }
+ focusEnabled = true;
+ repaint();
+ break;
+ case FocusEvent.FOCUS_LOST:
+ if (focusListener != null) {
+ focusListener.focusLost(e);
+ }
+ focusEnabled = false;
+ repaint();
+ break;
+ }
+ super.processFocusEvent(e);
+ }
+
+ @Override
+ protected void processKeyEvent(KeyEvent e) {
+ rows = getItemCount();
+
+ switch (e.getID()) {
+
+ case KeyEvent.KEY_TYPED:
+ if (keyListener != null) {
+ keyListener.keyTyped(e);
+ }
+ break;
+
+ case KeyEvent.KEY_PRESSED:
+ if (keyListener != null) {
+ keyListener.keyPressed(e);
+ }
+ if (e.getKeyCode() == KeyEvent.VK_DOWN) {
+ prevfocusIndex = focusIndex;
+ int index = getSelectedIndex() + 1;
+ if (index > rows) { break; }
+ setSelectedIndex(index);
+ processItemEvent(new ItemEvent(this, 0, index, 0));
+ eventOccurred = true;
+ repaint();
+ } else if (e.getKeyCode() == KeyEvent.VK_UP) {
+ int index = getSelectedIndex()-1;
+ if (index >= 0) {
+ setSelectedIndex(index);
+ if (e.getID() != 400) {
+ processItemEvent(new ItemEvent(this, 0, index, 0));
+ }
+ eventOccurred = true;
+ repaint();
+ }
+ }
+ break;
+
+ case KeyEvent.KEY_RELEASED:
+ if (keyListener != null) {
+ keyListener.keyReleased(e);
+ }
+ if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+ eventOccurred = true;
+
+ // ActionEvent is fired here
+ if (actionListener != null) {
+ actionListener.actionPerformed( new ActionEvent(
+ this, ActionEvent.ACTION_PERFORMED, null));
+ }
+ repaint();
+ }
+ break;
+ } // switch
+ super.processKeyEvent(e);
+ }
+
+ @Override
+ protected void processMouseEvent(MouseEvent e) {
+ switch (e.getID()) {
+ case MouseEvent.MOUSE_PRESSED:
+ pressed = true;
+ if (contains(e.getPoint())) {
+ findSelectedIndex(e.getPoint());
+ processItemEvent(new ItemEvent(this, 0, focusIndex, 0));
+ eventOccurred = true;
+ }
+ repaint();
+ break;
+
+ case MouseEvent.MOUSE_RELEASED:
+ if (pressed) { requestFocus(); }
+
+ if (contains(e.getPoint())) {
+ findSelectedIndex(e.getPoint());
+ eventOccurred = true;
+ }
+ // ActionEvent is fired here
+ if (actionListener != null) {
+ actionListener.actionPerformed(new ActionEvent(
+ this, ActionEvent.ACTION_PERFORMED, null));
+ }
+
+ if (pressed) {
+ pressed = false;
+ repaint();
+ }
+ break;
+ }
+ super.processMouseEvent(e);
+ }
+
+ @Override
+ /**
+ * Paint the list.
+ *
+ * @param g the graphics context to be used for testing
+ */
+ public void paint(Graphics g) {
+ super.paint(g);
+ restrictGraphicsToClientArea(g);
+
+ Point loc = getClientLocation();
+ Dimension dim = getClientSize();
+ Color prevColor = g.getColor();
+
+ // List border is drawn here
+ g.setColor(getBackground());
+ g.fillRect(0, 0, dim.width - 2, dim.height - 2);
+ g.setColor(getBorder());
+ g.drawRect(0, 0, dim.width - 2, dim.height - 2);
+
+ if (getItemCount() > 0) {
+ Font f = getFont();
+ if (f != null) {
+ String str[] = getItems();
+ FontMetrics fm = getFontMetrics(f);
+ int drawRow = loc.x + getBorderWidth() + fm.getAscent();
+ int drawCol = loc.y + getBorderWidth();
+ int rectRow = loc.y + getBorderWidth();
+ int i = 0;
+
+ // Draw items (if the items exceeds visibility those items will be truncated
+ // as scrollbar support is not enabled
+
+ for (;
+ i < str.length && drawRow < (dim.height - getBorderWidth());
+ i++) {
+ if (fm.stringWidth(str[i]) < (dim.width - (getBorderWidth() * 2))) {
+ drawItem(g, i, drawCol, drawRow, rectRow, fm);
+ drawRow += fm.getHeight();
+ rectRow += fm.getHeight();
+ } else {
+ LWComponent.errorMsg("string width exceeds list width");
+ LWComponent.errorMsg("Horizontal scrollbar support is not available");
+ }
+ } // for
+
+ if ( (drawRow > (dim.height - getBorderWidth())) && (str.length > i) ) {
+ //LWComponent.errorMsg("no of strings exceeds list height");
+ //LWComponent.errorMsg("Vertical scrollbar support is not available");
+ }
+ } else { LWComponent.errorMsg("Font not available.."); }
+ }
+
+ eventOccurred = false;
+ g.setColor(prevColor);
+ unrestrictGraphicsFromClientArea(g);
+ }
+
+ // Draw String items
+ private void drawItem(Graphics g, int listIndex, int drawCol,
+ int drawRow, int rectRow, FontMetrics fm) {
+ Point loc = getClientLocation();
+ Dimension dim = getClientSize();
+ String str = getItem(listIndex);
+ if (multipleMode) {
+ for (int i1 = 0; i1 < selList.size(); i1++) {
+ if (listIndex == ((Integer)selList.elementAt(i1))) {
+ g.setColor(getFocusColor());
+ g.fillRect(loc.x + getBorderWidth(),
+ rectRow,
+ dim.width - getBorderWidth() * 2,
+ fm.getHeight());
+ g.setColor(getFocusEnabledColor());
+ g.drawRect(loc.x + getBorderWidth(),
+ rectRow,
+ dim.width - getBorderWidth() * 2,
+ fm.getHeight());
+ }
+ } // for
+ } else {
+ if (listIndex == getSelectedIndex() && !multipleMode) {
+ g.setColor(getFocusColor());
+ g.fillRect(loc.x + getBorderWidth(),
+ rectRow,
+ dim.width - getBorderWidth() * 2,
+ fm.getHeight());
+ g.setColor(getFocusForeColor());
+ }
+ if ((listIndex == prevfocusIndex) && (prevfocusIndex != getSelectedIndex()) && !multipleMode) {
+ g.setColor(getBackground());
+ g.fillRect(loc.x + getBorderWidth(),
+ rectRow,
+ dim.width - getBorderWidth() * 2,
+ fm.getHeight());
+ prevfocusIndex = getSelectedIndex();
+ }
+ if (focusEnabled && listIndex == getSelectedIndex() && !multipleMode) {
+ g.setColor(getFocusEnabledColor());
+ g.drawRect(loc.x + getBorderWidth(),
+ rectRow,
+ dim.width - getBorderWidth() * 2,
+ fm.getHeight());
+ }
+ }
+ g.setColor(getForeground());
+ g.drawString(str,drawCol,drawRow);
+ }
+
+}
+