changeset 1081:5399dddbbae1

Automated merge with ssh://jfxsrc.us.oracle.com//javafx/2.2/MASTER/jfx/rt
author kcr
date Wed, 16 May 2012 21:31:28 -0700
parents aeec67bbcaa2 57217d4635f1
children efa0fd389c78 34790ae10f52
files
diffstat 10 files changed, 197 insertions(+), 125 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-common/src/com/sun/javafx/embed/EmbeddedSceneInterface.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-common/src/com/sun/javafx/embed/EmbeddedSceneInterface.java	Wed May 16 21:31:28 2012 -0700
@@ -60,7 +60,12 @@
      * A notification about key event received by host container.
      */
     public void keyEvent(int type, int key, char[] chars, int modifiers);
-
+    
+    /*
+     * A notification about menu event received by host container.
+     */
+    public void menuEvent(int x, int y, int xAbs, int yAbs, boolean isKeyboardTrigger);
+    
     public boolean traverseOut(Direction dir);
     
     public void setDragStartListener(EmbeddedSceneDragStartListenerInterface l);
--- a/javafx-ui-common/src/com/sun/javafx/stage/PopupEventRedirector.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-common/src/com/sun/javafx/stage/PopupEventRedirector.java	Wed May 16 21:31:28 2012 -0700
@@ -94,13 +94,17 @@
 
         if ((event.getEventType() == KeyEvent.KEY_PRESSED)
                 && ESCAPE_KEY_COMBINATION.match(event)) {
-            handleEscapeKeyPressedEvent();
+            handleEscapeKeyPressedEvent(event);
         }
     }
 
-    private void handleEscapeKeyPressedEvent() {
+    private void handleEscapeKeyPressedEvent(final Event event) {
         if (popupWindow.isHideOnEscape()) {
             popupWindow.doAutoHide();
+
+            if (popupWindow.getConsumeAutoHidingEvents()) {
+                event.consume();
+            }
         }
     }
 
@@ -121,10 +125,9 @@
 
             popupWindow.doAutoHide();
 
-            // we can consume the press which caused the autohide here,
-            // if we do that it won't have any effect in the target window
-            // from discussions, not consuming it seems preferable
-            // event.consume();
+            if (popupWindow.getConsumeAutoHidingEvents()) {
+                event.consume();
+            }
         }
     }
 
--- a/javafx-ui-common/src/javafx/scene/image/Image.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-common/src/javafx/scene/image/Image.java	Wed May 16 21:31:28 2012 -0700
@@ -25,10 +25,7 @@
 
 package javafx.scene.image;
 
-import java.io.File;
 import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URI;
 import java.util.LinkedList;
 import java.util.Queue;
 
@@ -46,6 +43,8 @@
 import com.sun.javafx.runtime.async.AsyncOperationListener;
 import com.sun.javafx.tk.ImageLoader;
 import com.sun.javafx.tk.Toolkit;
+import java.net.MalformedURLException;
+import java.net.URL;
 import javafx.beans.property.ReadOnlyBooleanProperty;
 import javafx.beans.property.ReadOnlyBooleanWrapper;
 import javafx.beans.property.ReadOnlyDoubleProperty;
@@ -63,6 +62,12 @@
  * image's aspect ratio.
  * </p>
  *
+ * <p>
+ * All URLs supported by {@link URL} can be passed to the constructor.
+ * If the passed string is not a valid URL, but a path instead, the Image is
+ * searched on the classpath in that case.
+ * </p>
+ *
  * <p>Use {@link ImageView} for displaying images loaded with this
  * class. The same {@code Image} instance can be displayed by multiple
  * {@code ImageView}s.</p>
@@ -74,23 +79,30 @@
 
 // load an image in background, displaying a placeholder while it's loading
 // (assuming there's an ImageView node somewhere displaying this image)
-Image image1 = new Image("flower.png", true);
+// The image is located in default package of the classpath
+Image image1 = new Image("/flower.png", true);
 
 // load an image and resize it to 100x150 without preserving its original
 // aspect ratio
-Image image2 = new Image("flower.png", 100, 150, false, false);
+// The image is located in my.res package of the classpath
+Image image2 = new Image("my/res/flower.png", 100, 150, false, false);
 
 // load an image and resize it to width of 100 while preserving its
 // original aspect ratio, using faster filtering method
-Image image3 = new Image("flower.png", 100, 0, false, false);
+// The image is downloaded from the supplied URL through http protocol
+Image image3 = new Image("http://sample.com/res/flower.png", 100, 0, false, false);
 
 // load an image and resize it only in one dimension, to the height of 100 and
 // the original width, without preserving original aspect ratio
-Image image4 = new Image("flower.png", 0, 100, false, false);
+// The image is located in the current working directory
+Image image4 = new Image("file:flower.png", 0, 100, false, false);
 
 </PRE>
  */
 public class Image {
+
+    // Matches strings that start with a valid URI scheme
+    private static final String URL_QUICKMATCH = "^\\p{Alpha}[\\p{Alnum}+.-]*:.*$";
     /**
      * The string representing the URL to use in fetching the pixel data.
      *
@@ -503,11 +515,12 @@
     }
 
     /**
-     * Construct an {@code Image} which pixels are loaded from the specified
+     * Constructs an {@code Image} with content loaded from the specified
      * url.
      *
      * @param url the string representing the URL to use in fetching the pixel
      *      data
+     * @see #Image(java.lang.String, java.io.InputStream, double, double, boolean, boolean, boolean)
      * @throws NullPointerException if URL is null
      * @throws IllegalArgumentException if URL is invalid or unsupported
      */
@@ -521,6 +534,7 @@
      *
      * @param url the string representing the URL to use in fetching the pixel
      *      data
+     * @see #Image(java.lang.String, java.io.InputStream, double, double, boolean, boolean, boolean)
      * @param backgroundLoading indicates whether the image
      *      is being loaded in the background
      * @throws NullPointerException if URL is null
@@ -536,6 +550,7 @@
      *
      * @param url the string representing the URL to use in fetching the pixel
      *      data
+     * @see #Image(java.lang.String, java.io.InputStream, double, double, boolean, boolean, boolean)
      * @param requestedWidth the image's bounding box width
      * @param requestedHeight the image's bounding box height
      * @param preserveRatio indicates whether to preserve the aspect ratio of
@@ -557,6 +572,10 @@
     /**
      * Construct a new {@code Image} with the specified parameters.
      *
+     * The <i>url</i> without scheme is threated as relative to classpath,
+     * url with scheme is treated accordingly to the scheme using
+     * {@link URL#openStream()}
+     *
      * @param url the string representing the URL to use in fetching the pixel
      *      data
      * @param requestedWidth the image's bounding box width
@@ -585,7 +604,7 @@
     }
 
     /**
-     * Construct an {@code Image} which pixels are loaded from the specified
+     * Construct an {@code Image} with content loaded from the specified
      * input stream.
      *
      * @param is the stream from which to load the image
@@ -917,13 +936,22 @@
             throw new IllegalArgumentException("URL must not be empty");
         }
 
-        final URI baseUri = getBaseUri();
-        final URI resolvedUri;
         try {
-            resolvedUri = (baseUri != null) ? baseUri.resolve(url)
-                                            : URI.create(url);
-
-            return resolvedUri.toURL().toString();
+            if (!url.matches(URL_QUICKMATCH)) {
+                final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+                URL resource;
+                if (url.charAt(0) == '/') {
+                    resource = contextClassLoader.getResource(url.substring(1));
+                } else {
+                    resource = contextClassLoader.getResource(url);
+                }
+                if (resource == null) {
+                    throw new IllegalArgumentException("Invalid URL or resource not found");
+                }
+                return resource.toString();
+            }
+            // Use URL constructor for validation
+            return new URL(url).toString();
         } catch (final IllegalArgumentException e) {
             throw new IllegalArgumentException(
                     constructDetailedExceptionMessage("Invalid URL", e), e);
@@ -957,16 +985,6 @@
                        cause.getCause());
     }
 
-    private static URI getBaseUri() {
-        try {
-            // we might want to use getDocumentBase() from HostServices here,
-            // but that would be an incompatible change
-            return new File("").toURI();
-        } catch (final Exception e) {
-            return null;
-        }
-    }
-
     /**
      * This method converts a JavaFX Image to the specified image class or
      * to an image of the same class and the same format as specified image.
--- a/javafx-ui-common/src/javafx/stage/PopupWindow.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-common/src/javafx/stage/PopupWindow.java	Wed May 16 21:31:28 2012 -0700
@@ -246,6 +246,28 @@
     public final BooleanProperty hideOnEscapeProperty() { return hideOnEscape; }
 
     /**
+     * Specifies whether the event, which caused the Popup to hide, should be
+     * consumed. Having the event consumed prevents it from triggering some
+     * additional UI response in the Popup's owner window.
+     * @defaultValue true
+     */
+    private BooleanProperty consumeAutoHidingEvents =
+            new SimpleBooleanProperty(this, "consumeAutoHidingEvents",
+                                      true);
+
+    public final void setConsumeAutoHidingEvents(boolean value) {
+        consumeAutoHidingEvents.set(value);
+    }
+
+    public final boolean getConsumeAutoHidingEvents() {
+        return consumeAutoHidingEvents.get();
+    }
+
+    public final BooleanProperty consumeAutoHidingEventsProperty() {
+        return consumeAutoHidingEvents;
+    }
+
+    /**
      * Show the popup.
      * @param owner The owner of the popup. This must not be null.
      */
--- a/javafx-ui-common/test/unit/javafx/scene/Scenegraph_eventHandlers_Test.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-common/test/unit/javafx/scene/Scenegraph_eventHandlers_Test.java	Wed May 16 21:31:28 2012 -0700
@@ -45,6 +45,7 @@
 import org.junit.runners.Parameterized.Parameters;
 
 import com.sun.javafx.test.PropertyReference;
+import com.sun.javafx.test.MouseEventGenerator;
 
 @RunWith(Parameterized.class)
 public final class Scenegraph_eventHandlers_Test {
@@ -55,6 +56,8 @@
 
     @Parameters
     public static Collection data() {
+        final MouseEventGenerator mouseEventGenerator =
+                new MouseEventGenerator();
         return Arrays.asList(new Object[][] {
             {
                 KeyEvent.KEY_PRESSED,
@@ -71,31 +74,38 @@
             }, {
                 MouseEvent.MOUSE_PRESSED,
                 "onMousePressed",
-                createTestMouseEvent(MouseEvent.MOUSE_PRESSED)
+                mouseEventGenerator.generateMouseEvent(
+                        MouseEvent.MOUSE_PRESSED, 0, 0)
             }, {
                 MouseEvent.MOUSE_RELEASED,
                 "onMouseReleased",
-                createTestMouseEvent(MouseEvent.MOUSE_RELEASED)
+                mouseEventGenerator.generateMouseEvent(
+                        MouseEvent.MOUSE_RELEASED, 0, 0)
             }, {
                 MouseEvent.MOUSE_CLICKED,
                 "onMouseClicked",
-                createTestMouseEvent(MouseEvent.MOUSE_CLICKED)
+                mouseEventGenerator.generateMouseEvent(
+                        MouseEvent.MOUSE_CLICKED, 0, 0)
             }, {
                 MouseEvent.MOUSE_ENTERED,
                 "onMouseEntered",
-                createTestMouseEvent(MouseEvent.MOUSE_ENTERED)
+                mouseEventGenerator.generateMouseEvent(
+                        MouseEvent.MOUSE_ENTERED, 0, 0)
             }, {
                 MouseEvent.MOUSE_EXITED,
                 "onMouseExited",
-                createTestMouseEvent(MouseEvent.MOUSE_EXITED)
+                mouseEventGenerator.generateMouseEvent(
+                        MouseEvent.MOUSE_EXITED, 0, 0)
             }, {
                 MouseEvent.MOUSE_MOVED,
                 "onMouseMoved",
-                createTestMouseEvent(MouseEvent.MOUSE_MOVED)
+                mouseEventGenerator.generateMouseEvent(
+                        MouseEvent.MOUSE_MOVED, 0, 0)
             }, {
                 MouseEvent.MOUSE_DRAGGED,
                 "onMouseDragged",
-                createTestMouseEvent(MouseEvent.MOUSE_DRAGGED)
+                mouseEventGenerator.generateMouseEvent(
+                        MouseEvent.MOUSE_DRAGGED, 0, 0)
             }
         });
     }
@@ -313,29 +323,6 @@
                                       keyEventType);
     }
 
-    private static Event createTestMouseEvent(
-            final EventType<MouseEvent> mouseEventType) {
-        MouseButton button = MouseButton.NONE;
-        boolean primaryButtonDown = false;
-        int clickCount = 0;
-
-        if ((mouseEventType == MouseEvent.MOUSE_RELEASED)
-                || (mouseEventType == MouseEvent.MOUSE_CLICKED)) {
-            button = MouseButton.PRIMARY;
-            clickCount = 1;
-        } else if (mouseEventType == MouseEvent.MOUSE_PRESSED) {
-            button = MouseButton.PRIMARY;
-            primaryButtonDown = true;
-            clickCount = 1;
-        }
-
-        return MouseEvent.impl_mouseEvent(0, 0, 0, 0,
-                                          button, clickCount,
-                                          false, false, false, false,
-                                          false, primaryButtonDown,
-                                          false, false, false, mouseEventType);
-    }
-
     private static void setEventHandler(
             final Object bean,
             final PropertyReference handlerPropertyReference,
--- a/javafx-ui-common/test/unit/javafx/scene/effect/ImageInputTest.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-common/test/unit/javafx/scene/effect/ImageInputTest.java	Wed May 16 21:31:28 2012 -0700
@@ -85,7 +85,7 @@
     @Test
     public void testSetSource() {
         // try setting non-existing image
-        Image i = new Image("test");
+        Image i = new Image("javafx/scene/image/test.png");
         effect.setSource(i);
         assertEquals(i, effect.getSource());
         pulse();
--- a/javafx-ui-common/test/unit/javafx/scene/image/ImageTest.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-common/test/unit/javafx/scene/image/ImageTest.java	Wed May 16 21:31:28 2012 -0700
@@ -51,6 +51,7 @@
 
 import javafx.beans.InvalidationListener;
 import javafx.beans.Observable;
+import org.junit.Ignore;
 
 public final class ImageTest {
     private final StubToolkit toolkit;
@@ -507,6 +508,30 @@
         final Image image = Image.impl_fromExternalImage(fakeExternalImage);
         verifyLoadedImage(image, 0, 0, false, false, 123, 456);
     }
+    
+    @Test
+    public void createImageFromClasspathTest() {
+        final String url = "javafx/scene/image/test.png";
+        final String resolvedUrl = Thread.currentThread().getContextClassLoader().getResource(url).toString();
+        registerImage(resolvedUrl, 100, 200);
+        
+        final Image image = new Image(url);
+
+        assertEquals(resolvedUrl, image.impl_getUrl());
+        verifyLoadedImage(image, 0, 0, false, false, 100, 200);
+    }
+    
+    @Test
+    public void createImageFromClasspathTest_withLeadingSlash() {
+        final String url = "/javafx/scene/image/test.png";
+        final String resolvedUrl = Thread.currentThread().getContextClassLoader().getResource(url.substring(1)).toString();
+        registerImage(resolvedUrl, 100, 200);
+        
+        final Image image = new Image(url);
+
+        assertEquals(resolvedUrl, image.impl_getUrl());
+        verifyLoadedImage(image, 0, 0, false, false, 100, 200);
+    }
 
     @Test(expected=NullPointerException.class)
     public void createImageFromNullUrlTest() {
--- a/javafx-ui-common/test/unit/javafx/scene/input/DragAndDropTest.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-common/test/unit/javafx/scene/input/DragAndDropTest.java	Wed May 16 21:31:28 2012 -0700
@@ -56,6 +56,7 @@
 import com.sun.javafx.tk.TKDragSourceListener;
 import com.sun.javafx.tk.TKDropTargetListener;
 import com.sun.javafx.tk.Toolkit;
+import com.sun.javafx.test.MouseEventGenerator;
 
 public class DragAndDropTest {
     
@@ -1251,37 +1252,6 @@
         
     }
     
-    // Event generators
-    
-    private static class MouseEventGenerator {
-        private boolean primaryButtonDown = false;
-
-        public MouseEvent generateMouseEvent(EventType<MouseEvent> type,
-                double x, double y) {
-
-            MouseButton button = MouseButton.NONE;
-            if (type == MouseEvent.MOUSE_PRESSED ||
-                    type == MouseEvent.MOUSE_RELEASED ||
-                    type == MouseEvent.MOUSE_CLICKED) {
-                button = MouseButton.PRIMARY;
-            }
-
-            if (type == MouseEvent.MOUSE_PRESSED) {
-                primaryButtonDown = true;
-            }
-
-            MouseEvent event = MouseEvent.impl_mouseEvent(x, y, x, y, button,
-                    1, false, false, false, false, false, primaryButtonDown,
-                    false, false, false, type);
-
-            if (type == MouseEvent.MOUSE_RELEASED) {
-                primaryButtonDown = false;
-            }
-
-            return event;
-        }
-    }
-    
     private static class DragEventGenerator {
         public DragEvent generateDragEvent(double x,
                 double y, Dragboard db, TransferMode tm) {
--- a/javafx-ui-common/test/unit/javafx/scene/input/MouseDragEventTest.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-common/test/unit/javafx/scene/input/MouseDragEventTest.java	Wed May 16 21:31:28 2012 -0700
@@ -32,6 +32,8 @@
 import javafx.scene.shape.Rectangle;
 import javafx.stage.Stage;
 
+import com.sun.javafx.test.MouseEventGenerator;
+
 import static org.junit.Assert.*;
 import org.junit.Test;
 
@@ -530,37 +532,6 @@
         w.clear();
     }
 
-
-    private static class MouseEventGenerator {
-        private boolean primaryButtonDown = false;
-
-        public MouseEvent generateMouseEvent(EventType<MouseEvent> type,
-                double x, double y) {
-
-            MouseButton button = MouseButton.NONE;
-            if (type == MouseEvent.MOUSE_PRESSED ||
-                    type == MouseEvent.MOUSE_RELEASED ||
-                    type == MouseEvent.MOUSE_DRAGGED) {
-                button = MouseButton.PRIMARY;
-            }
-
-            if (type == MouseEvent.MOUSE_PRESSED ||
-                    type == MouseEvent.MOUSE_DRAGGED) {
-                primaryButtonDown = true;
-            }
-
-            if (type == MouseEvent.MOUSE_RELEASED) {
-                primaryButtonDown = false;
-            }
-
-            MouseEvent event = MouseEvent.impl_mouseEvent(x, y, x, y, button,
-                    1, false, false, false, false, false, primaryButtonDown,
-                    false, false, false, type);
-
-            return event;
-        }
-    }
-
     private class World {
         private HandledNode scene;
         private HandledNode source;
--- a/javafx-ui-common/test/unit/javafx/stage/PopupTest.java	Wed May 16 13:13:47 2012 -0400
+++ b/javafx-ui-common/test/unit/javafx/stage/PopupTest.java	Wed May 16 21:31:28 2012 -0700
@@ -27,6 +27,8 @@
 
 import com.sun.javafx.pgstub.StubToolkit.ScreenConfiguration;
 import com.sun.javafx.test.MouseEventGenerator;
+import javafx.scene.input.KeyCode;
+import javafx.scene.input.KeyEvent;
 import javafx.scene.input.MouseEvent;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -381,4 +383,73 @@
         assertEquals(200, popup.getWidth(), 1e-100);
         assertEquals(300, popup.getHeight(), 1e-100);
     }
+
+    @Test
+    public void testConsumeAutoHidingEventsProperty() {
+        final EventCounter mouseEventCounter = new EventCounter();
+        final EventCounter keyEventCounter = new EventCounter();
+
+        stage.addEventHandler(MouseEvent.MOUSE_PRESSED, mouseEventCounter);
+        stage.addEventHandler(KeyEvent.KEY_PRESSED, keyEventCounter);
+        try {
+            final MouseEventGenerator mouseEventGenerator =
+                    new MouseEventGenerator();
+
+            final Popup popup = new Popup();
+            popup.setAutoHide(true);
+
+            assertTrue(popup.getConsumeAutoHidingEvents());
+
+            popup.show(stage);
+            Event.fireEvent(stage,
+                            mouseEventGenerator.generateMouseEvent(
+                                MouseEvent.MOUSE_PRESSED, 0, 0));
+            assertEquals(0, mouseEventCounter.getValue());
+
+            popup.show(stage);
+            Event.fireEvent(stage,
+                            KeyEvent.impl_keyEvent(
+                                stage, KeyEvent.CHAR_UNDEFINED,
+                                KeyCode.ESCAPE.getName(),
+                                KeyCode.ESCAPE.impl_getCode(),
+                                false, false, false, false,
+                                KeyEvent.KEY_PRESSED));
+            assertEquals(0, keyEventCounter.getValue());
+
+            popup.setConsumeAutoHidingEvents(false);
+
+            popup.show(stage);
+            Event.fireEvent(stage,
+                            mouseEventGenerator.generateMouseEvent(
+                                MouseEvent.MOUSE_PRESSED, 0, 0));
+            assertEquals(1, mouseEventCounter.getValue());
+
+            popup.show(stage);
+            Event.fireEvent(stage,
+                            KeyEvent.impl_keyEvent(
+                                stage, KeyEvent.CHAR_UNDEFINED,
+                                KeyCode.ESCAPE.getName(),
+                                KeyCode.ESCAPE.impl_getCode(),
+                                false, false, false, false,
+                                KeyEvent.KEY_PRESSED));
+            assertEquals(1, keyEventCounter.getValue());
+            
+        } finally {
+            stage.removeEventHandler(MouseEvent.MOUSE_PRESSED,
+                                     mouseEventCounter);
+            stage.removeEventHandler(KeyEvent.KEY_PRESSED, keyEventCounter);
+        }
+    }
+
+    private static final class EventCounter implements EventHandler<Event> {
+        private int counter;
+
+        public int getValue() {
+            return counter;
+        }
+
+        public void handle(final Event event) {
+            ++counter;
+        }
+    }
 }