diff --git a/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java b/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java index 3e1c37c2d57c17793e949aa0151a6361b61ec6a3..faab85cafa99eb84bd8e1f56ae5bd365775f8755 100644 --- a/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java +++ b/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java @@ -48,7 +48,7 @@ public final class BeanInfoFinder } private static boolean isValid(Class type, Method method) { - return (method != null) && type.equals(method.getDeclaringClass()); + return (method != null) && method.getDeclaringClass().isAssignableFrom(type); } @Override diff --git a/src/share/classes/java/lang/Character.java b/src/share/classes/java/lang/Character.java index f20f8e3d3b99386682fb6b24887c369ed60b8cec..56e763ee6a67b668965c0ac23f9b9cae5f76a2cd 100644 --- a/src/share/classes/java/lang/Character.java +++ b/src/share/classes/java/lang/Character.java @@ -38,7 +38,7 @@ import java.util.Locale; * a character's category (lowercase letter, digit, etc.) and for converting * characters from uppercase to lowercase and vice versa. *

- * Character information is based on the Unicode Standard, version 4.0. + * Character information is based on the Unicode Standard, version 5.1.0. *

* The methods and data of class Character are defined by * the information in the UnicodeData file that is part of the diff --git a/src/share/classes/javax/swing/JLayer.java b/src/share/classes/javax/swing/JLayer.java new file mode 100644 index 0000000000000000000000000000000000000000..b8cc69e9bcd1086dccd072b7ad82838310ac60ef --- /dev/null +++ b/src/share/classes/javax/swing/JLayer.java @@ -0,0 +1,788 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package javax.swing; + +import javax.swing.plaf.LayerUI; +import java.awt.*; +import java.awt.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Iterator; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * {@code JLayer} is a universal decorator for Swing components + * which enables you to implement various advanced painting effects as well as + * receive notifications of all {@code AWTEvent}s generated within its borders. + *

+ * {@code JLayer} delegates the handling of painting and input events to a + * {@link javax.swing.plaf.LayerUI} object, which performs the actual decoration. + *

+ * The custom painting implemented in the {@code LayerUI} and events notification + * work for the JLayer itself and all its subcomponents. + * This combination enables you to enrich existing components + * by adding new advanced functionality such as temporary locking of a hierarchy, + * data tips for compound components, enhanced mouse scrolling etc and so on. + *

+ * {@code JLayer} is a good solution if you only need to do custom painting + * over compound component or catch input events from its subcomponents. + *

+ *         // create a component to be decorated with the layer
+ *        JPanel panel = new JPanel();
+ *        panel.add(new JButton("JButton"));
+ *        // This custom layerUI will fill the layer with translucent green
+ *        // and print out all mouseMotion events generated within its borders
+ *        LayerUI<JPanel> layerUI = new LayerUI<JPanel>() {
+ *            public void paint(Graphics g, JCompo  nent c) {
+ *                // paint the layer as is
+ *                super.paint(g, c);
+ *                // fill it with the translucent green
+ *                g.setColor(new Color(0, 128, 0, 128));
+ *                g.fillRect(0, 0, c.getWidth(), c.getHeight());
+ *            }
+ *            // overridden method which catches MouseMotion events
+ *            public void eventDispatched(AWTEvent e, JLayer<JPanel> l) {
+ *                System.out.println("AWTEvent detected: " + e);
+ *            }
+ *        };
+ *        // create the layer for the panel using our custom layerUI
+ *        JLayer<JPanel> layer = new JLayer<JPanel>(panel, layerUI);
+ *        // work with the layer as with any other Swing component
+ *        frame.add(layer);
+ * 
+ * + * Note: {@code JLayer} doesn't support the following methods: + * + * using any of of them will cause {@code UnsupportedOperationException} to be thrown, + * to add a component to {@code JLayer} + * use {@link #setView(Component)} or {@link #setGlassPane(JPanel)}. + * + * @param the type of {@code JLayer}'s view component + * + * @see #JLayer(Component) + * @see #setView(Component) + * @see #getView() + * @see javax.swing.plaf.LayerUI + * @see #JLayer(Component, LayerUI) + * @see #setUI(javax.swing.plaf.LayerUI) + * @see #getUI() + * @since 1.7 + * + * @author Alexander Potochkin + */ +public final class JLayer + extends JComponent + implements Scrollable, PropertyChangeListener { + private V view; + // this field is necessary because JComponent.ui is transient + // when layerUI is serializable + private LayerUI layerUI; + private JPanel glassPane; + private boolean isPainting; + private static final DefaultLayerLayout sharedLayoutInstance = + new DefaultLayerLayout(); + private long eventMask; + + private static final LayerEventController eventController = + new LayerEventController(); + + private static final long ACCEPTED_EVENTS = + AWTEvent.COMPONENT_EVENT_MASK | + AWTEvent.CONTAINER_EVENT_MASK | + AWTEvent.FOCUS_EVENT_MASK | + AWTEvent.KEY_EVENT_MASK | + AWTEvent.MOUSE_WHEEL_EVENT_MASK | + AWTEvent.MOUSE_MOTION_EVENT_MASK | + AWTEvent.MOUSE_EVENT_MASK | + AWTEvent.INPUT_METHOD_EVENT_MASK | + AWTEvent.HIERARCHY_EVENT_MASK | + AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK; + + /** + * Creates a new {@code JLayer} object with a {@code null} view component + * and {@code null} {@link javax.swing.plaf.LayerUI}. + * + * @see #setView + * @see #setUI + */ + public JLayer() { + this(null); + } + + /** + * Creates a new {@code JLayer} object + * with {@code null} {@link javax.swing.plaf.LayerUI}. + * + * @param view the component to be decorated by this {@code JLayer} + * + * @see #setUI + */ + public JLayer(V view) { + this(view, null); + } + + /** + * Creates a new {@code JLayer} object with the specified view component + * and {@link javax.swing.plaf.LayerUI} object. + * + * @param view the component to be decorated + * @param ui the {@link javax.swing.plaf.LayerUI} delegate + * to be used by this {@code JLayer} + */ + public JLayer(V view, LayerUI ui) { + setLayout(sharedLayoutInstance); + setGlassPane(createGlassPane()); + setView(view); + setUI(ui); + } + + /** + * Returns the {@code JLayer}'s view component or {@code null}. + *
This is a bound property. + * + * @return the {@code JLayer}'s view component + * or {@code null} if none exists + * + * @see #setView(V) + */ + public V getView() { + return view; + } + + /** + * Sets the {@code JLayer}'s view component, which can be {@code null}. + *
This is a bound property. + * + * @param view the view component for this {@code JLayer} + * + * @see #getView() + */ + public void setView(V view) { + Component oldView = getView(); + if (oldView != null) { + super.remove(oldView); + } + if (view != null) { + super.addImpl(view, null, getComponentCount()); + } + this.view = view; + firePropertyChange("view", oldView, view); + revalidate(); + repaint(); + } + + /** + * Sets the {@link javax.swing.plaf.LayerUI} which will perform painting + * and receive input events for this {@code JLayer}. + * + * @param ui the {@link javax.swing.plaf.LayerUI} for this {@code JLayer} + */ + public void setUI(LayerUI ui) { + this.layerUI = ui; + super.setUI(ui); + } + + /** + * Returns the {@link javax.swing.plaf.LayerUI} for this {@code JLayer}. + * + * @return the {@code LayerUI} for this {@code JLayer} + */ + public LayerUI getUI() { + return layerUI; + } + + /** + * Returns the {@code JLayer}'s glassPane component or {@code null}. + *
This is a bound property. + * + * @return the {@code JLayer}'s glassPane component + * or {@code null} if none exists + * + * @see #setGlassPane(JPanel) + */ + public JPanel getGlassPane() { + return glassPane; + } + + /** + * Sets the {@code JLayer}'s glassPane component, which can be {@code null}. + *
This is a bound property. + * + * @param glassPane the glassPane component of this {@code JLayer} + * + * @see #getGlassPane() + */ + public void setGlassPane(JPanel glassPane) { + Component oldGlassPane = getGlassPane(); + if (oldGlassPane != null) { + super.remove(oldGlassPane); + } + if (glassPane != null) { + super.addImpl(glassPane, null, 0); + } + this.glassPane = glassPane; + firePropertyChange("glassPane", oldGlassPane, glassPane); + revalidate(); + repaint(); + } + + /** + * Called by the constructor methods to create a default {@code glassPane}. + * By default this method creates a new JPanel with visibility set to true + * and opacity set to false. + * + * @return the default {@code glassPane} + */ + public JPanel createGlassPane() { + return new DefaultLayerGlassPane(); + } + + /** + * This method is not supported by {@code JLayer} + * and always throws {@code UnsupportedOperationException} + * + * @throws UnsupportedOperationException this method is not supported + * + * @see #setView(Component) + * @see #setGlassPane(Component) + */ + protected void addImpl(Component comp, Object constraints, int index) { + throw new UnsupportedOperationException( + "Adding components to JLayer is not supported, " + + "use setView() or setGlassPane() instead"); + } + + /** + * {@inheritDoc} + */ + public void remove(Component comp) { + if (comp == getView()) { + setView(null); + } else if (comp == getGlassPane()) { + setGlassPane(null); + } else { + super.remove(comp); + } + } + + /** + * {@inheritDoc} + */ + public void removeAll() { + setView(null); + setGlassPane(null); + } + + /** + * Delegates all painting to the {@link javax.swing.plaf.LayerUI} object. + * + * @param g the {@code Graphics} to render to + */ + public void paint(Graphics g) { + if (!isPainting) { + isPainting = true; + super.paintComponent(g); + isPainting = false; + } else { + super.paint(g); + } + } + + /** + * This method is empty, because all painting is done by + * {@link #paint(Graphics)} and + * {@link javax.swing.plaf.LayerUI#update(Graphics, JComponent)} methods + */ + protected void paintComponent(Graphics g) { + } + + /** + * To enable the correct painting of the {@code glassPane} and view component, + * the {@code JLayer} overrides the default implementation of + * this method to return {@code false} when the {@code glassPane} is visible. + * + * @return false if {@code JLayer}'s {@code glassPane} is visible + */ + public boolean isOptimizedDrawingEnabled() { + return !glassPane.isVisible(); + } + + /** + * {@inheritDoc} + */ + public void propertyChange(PropertyChangeEvent evt) { + if (getUI() != null) { + getUI().applyPropertyChange(evt, this); + } + } + + /** + * Sets the bitmask of event types to receive by this {@code JLayer}. + * Here is the list of the supported event types: + *
    + *
  • AWTEvent.COMPONENT_EVENT_MASK
  • + *
  • AWTEvent.CONTAINER_EVENT_MASK
  • + *
  • AWTEvent.FOCUS_EVENT_MASK
  • + *
  • AWTEvent.KEY_EVENT_MASK
  • + *
  • AWTEvent.MOUSE_WHEEL_EVENT_MASK
  • + *
  • AWTEvent.MOUSE_MOTION_EVENT_MASK
  • + *
  • AWTEvent.MOUSE_EVENT_MASK
  • + *
  • AWTEvent.INPUT_METHOD_EVENT_MASK
  • + *
  • AWTEvent.HIERARCHY_EVENT_MASK
  • + *
  • AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK
  • + *
+ *

+ * If {@code LayerUI} is installed, + * {@link javax.swing.plaf.LayerUI#eventDispatched(AWTEvent, JLayer)} method + * will only receive events that match the event mask. + *

+ * The following example shows how to correclty use this method + * in the {@code LayerUI} implementations: + *

+     *    public void installUI(JComponent c) {
+     *       super.installUI(c);
+     *       JLayer l = (JLayer) c;
+     *       // this LayerUI will receive only key and focus events
+     *       l.setLayerEventMask(AWTEvent.KEY_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK);
+     *    }
+     *
+     *    public void uninstallUI(JComponent c) {
+     *       super.uninstallUI(c);
+     *       JLayer l = (JLayer) c;
+     *       // JLayer must be returned to its initial state
+     *       l.setLayerEventMask(0);
+     *    }
+     * 
+ * + * By default {@code JLayer} receives no events. + * + * @param layerEventMask the bitmask of event types to receive + * + * @throws IllegalArgumentException if the {@code layerEventMask} parameter + * contains unsupported event types + * @see #getLayerEventMask() + */ + public void setLayerEventMask(long layerEventMask) { + if (layerEventMask != (layerEventMask & ACCEPTED_EVENTS)) { + throw new IllegalArgumentException( + "The event bitmask contains unsupported event types"); + } + long oldEventMask = getLayerEventMask(); + this.eventMask = layerEventMask; + firePropertyChange("layerEventMask", oldEventMask, layerEventMask); + if (layerEventMask != oldEventMask) { + disableEvents(oldEventMask); + enableEvents(eventMask); + eventController.updateAWTEventListener(this); + } + } + + /** + * Returns the bitmap of event mask to receive by this {@code JLayer} + * and its {@code LayerUI}. + *

+ * It means that {@link javax.swing.plaf.LayerUI#eventDispatched(AWTEvent, JLayer)} method + * will only receive events that match the event mask. + *

+ * By default {@code JLayer} receives no events. + * + * @return the bitmask of event types to receive for this {@code JLayer} + */ + public long getLayerEventMask() { + return eventMask; + } + + /** + * Delegates its functionality to the {@link javax.swing.plaf.LayerUI#updateUI(JLayer)} method, + * if {@code LayerUI} is set. + */ + public void updateUI() { + if (getUI() != null) { + getUI().updateUI(this); + } + } + + /** + * Returns the preferred size of the viewport for a view component. + *

+ * If the ui delegate of this layer is not {@code null}, this method delegates its + * implementation to the {@code LayerUI.getPreferredScrollableViewportSize(JLayer)} + * + * @return the preferred size of the viewport for a view component + * + * @see Scrollable + * @see LayerUI#getPreferredScrollableViewportSize(JLayer) + */ + public Dimension getPreferredScrollableViewportSize() { + if (getUI() != null) { + return getUI().getPreferredScrollableViewportSize(this); + } + return getPreferredSize(); + } + + /** + * Returns a scroll increment, which is required for components + * that display logical rows or columns in order to completely expose + * one block of rows or columns, depending on the value of orientation. + *

+ * If the ui delegate of this layer is not {@code null}, this method delegates its + * implementation to the {@code LayerUI.getScrollableBlockIncrement(JLayer,Rectangle,int,int)} + * + * @return the "block" increment for scrolling in the specified direction + * + * @see Scrollable + * @see LayerUI#getScrollableBlockIncrement(JLayer, Rectangle, int, int) + */ + public int getScrollableBlockIncrement(Rectangle visibleRect, + int orientation, int direction) { + if (getUI() != null) { + return getUI().getScrollableBlockIncrement(this, visibleRect, + orientation, direction); + } + return (orientation == SwingConstants.VERTICAL) ? visibleRect.height : + visibleRect.width; + } + + /** + * Returns {@code false} to indicate that the height of the viewport does not + * determine the height of the layer, unless the preferred height + * of the layer is smaller than the height of the viewport. + *

+ * If the ui delegate of this layer is not null, this method delegates its + * implementation to the {@code LayerUI.getScrollableTracksViewportHeight(JLayer)} + * + * @return whether the layer should track the height of the viewport + * + * @see Scrollable + * @see LayerUI#getScrollableTracksViewportHeight(JLayer) + */ + public boolean getScrollableTracksViewportHeight() { + if (getUI() != null) { + return getUI().getScrollableTracksViewportHeight(this); + } + if (getParent() instanceof JViewport) { + return ((getParent()).getHeight() > getPreferredSize().height); + } + return false; + } + + /** + * Returns {@code false} to indicate that the width of the viewport does not + * determine the width of the layer, unless the preferred width + * of the layer is smaller than the width of the viewport. + *

+ * If the ui delegate of this layer is not null, this method delegates its + * implementation to the {@code LayerUI.getScrollableTracksViewportWidth(JLayer)} + * + * @return whether the layer should track the width of the viewport + * + * @see Scrollable + * @see LayerUI#getScrollableTracksViewportWidth(JLayer) + */ + public boolean getScrollableTracksViewportWidth() { + if (getUI() != null) { + return getUI().getScrollableTracksViewportWidth(this); + } + if (getParent() instanceof JViewport) { + return ((getParent()).getWidth() > getPreferredSize().width); + } + return false; + } + + /** + * Returns a scroll increment, which is required for components + * that display logical rows or columns in order to completely expose + * one new row or column, depending on the value of orientation. + * Ideally, components should handle a partially exposed row or column + * by returning the distance required to completely expose the item. + *

+ * Scrolling containers, like {@code JScrollPane}, will use this method + * each time the user requests a unit scroll. + *

+ * If the ui delegate of this layer is not {@code null}, this method delegates its + * implementation to the {@code LayerUI.getScrollableUnitIncrement(JLayer,Rectangle,int,int)} + * + * @return The "unit" increment for scrolling in the specified direction. + * This value should always be positive. + * + * @see Scrollable + * @see LayerUI#getScrollableUnitIncrement(JLayer, Rectangle, int, int) + */ + public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, + int direction) { + if (getUI() != null) { + return getUI().getScrollableUnitIncrement( + this, visibleRect, orientation, direction); + } + return 1; + } + + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + if (getUI() != null) { + setUI(getUI()); + } + if (getLayerEventMask() != 0) { + eventController.updateAWTEventListener(this); + } + } + + /** + * static AWTEventListener to be shared with all AbstractLayerUIs + */ + private static class LayerEventController implements AWTEventListener { + private ArrayList> layerList = + new ArrayList>(); + + private long currentEventMask; + + @SuppressWarnings("unchecked") + public void eventDispatched(AWTEvent event) { + Object source = event.getSource(); + if (source instanceof Component) { + Component component = (Component) source; + while (component != null) { + if (component instanceof JLayer) { + JLayer l = (JLayer) component; + LayerUI ui = l.getUI(); + if (ui != null && + isEventEnabled(l.getLayerEventMask(), + event.getID())) { + ui.eventDispatched(event, l); + } + } + component = component.getParent(); + } + } + } + + private boolean layerListContains(JLayer l) { + for (WeakReference layerWeakReference : layerList) { + if (layerWeakReference.get() == l) { + return true; + } + } + return false; + } + + private void updateAWTEventListener(JLayer layer) { + if (!layerListContains(layer) && layer.getLayerEventMask() != 0) { + layerList.add(new WeakReference(layer)); + } + long combinedMask = 0; + Iterator> it = layerList.iterator(); + while (it.hasNext()) { + WeakReference weakRef = it.next(); + JLayer currLayer = weakRef.get(); + if (currLayer == null) { + it.remove(); + } else { + combinedMask |= currLayer.getLayerEventMask(); + } + } + if (combinedMask == 0) { + removeAWTEventListener(); + layerList.clear(); + } else if (getCurrentEventMask() != combinedMask) { + removeAWTEventListener(); + addAWTEventListener(combinedMask); + } + } + + private long getCurrentEventMask() { + return currentEventMask; + } + + private void addAWTEventListener(final long eventMask) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + Toolkit.getDefaultToolkit(). + addAWTEventListener(LayerEventController.this, eventMask); + return null; + } + }); + currentEventMask = eventMask; + } + + private void removeAWTEventListener() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + Toolkit.getDefaultToolkit(). + removeAWTEventListener(LayerEventController.this); + return null; + } + }); + currentEventMask = 0; + } + + private boolean isEventEnabled(long eventMask, int id) { + return (((eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 && + id >= ComponentEvent.COMPONENT_FIRST && + id <= ComponentEvent.COMPONENT_LAST) + || ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 && + id >= ContainerEvent.CONTAINER_FIRST && + id <= ContainerEvent.CONTAINER_LAST) + || ((eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0 && + id >= FocusEvent.FOCUS_FIRST && + id <= FocusEvent.FOCUS_LAST) + || ((eventMask & AWTEvent.KEY_EVENT_MASK) != 0 && + id >= KeyEvent.KEY_FIRST && + id <= KeyEvent.KEY_LAST) + || ((eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0 && + id == MouseEvent.MOUSE_WHEEL) + || ((eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0 && + (id == MouseEvent.MOUSE_MOVED || + id == MouseEvent.MOUSE_DRAGGED)) + || ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0 && + id != MouseEvent.MOUSE_MOVED && + id != MouseEvent.MOUSE_DRAGGED && + id != MouseEvent.MOUSE_WHEEL && + id >= MouseEvent.MOUSE_FIRST && + id <= MouseEvent.MOUSE_LAST) + || ((eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0 && + id >= InputMethodEvent.INPUT_METHOD_FIRST && + id <= InputMethodEvent.INPUT_METHOD_LAST) + || ((eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 && + id == HierarchyEvent.HIERARCHY_CHANGED) + || ((eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 && + (id == HierarchyEvent.ANCESTOR_MOVED || + id == HierarchyEvent.ANCESTOR_RESIZED))); + } + } + + /** + * The default glassPane for the {@link javax.swing.JLayer}. + * It is a subclass of {@code JPanel} which is non opaque by default. + */ + private static class DefaultLayerGlassPane extends JPanel { + /** + * Creates a new {@link DefaultLayerGlassPane} + */ + public DefaultLayerGlassPane() { + setOpaque(false); + } + + /** + * First, implementatation of this method iterates through + * glassPane's child components and returns {@code true} + * if any of them is visible and contains passed x,y point. + * After that it checks if no mouseListeners is attached to this component + * and no mouse cursor is set, then it returns {@code false}, + * otherwise calls the super implementation of this method. + * + * @param x the x coordinate of the point + * @param y the y coordinate of the point + * @return true if this component logically contains x,y + */ + public boolean contains(int x, int y) { + for (int i = 0; i < getComponentCount(); i++) { + Component c = getComponent(i); + Point point = SwingUtilities.convertPoint(this, new Point(x, y), c); + if(c.isVisible() && c.contains(point)){ + return true; + } + } + if (getMouseListeners().length == 0 + && getMouseMotionListeners().length == 0 + && getMouseWheelListeners().length == 0 + && !isCursorSet()) { + return false; + } + return super.contains(x, y); + } + } + + /** + * The default layout manager for the {@link javax.swing.JLayer}.
+ * It places the glassPane on top of the view component + * and makes it the same size as {@code JLayer}, + * it also makes the view component the same size but minus layer's insets
+ */ + private static class DefaultLayerLayout implements LayoutManager, Serializable { + /** + * {@inheritDoc} + */ + public void layoutContainer(Container parent) { + JLayer layer = (JLayer) parent; + Component view = layer.getView(); + Component glassPane = layer.getGlassPane(); + if (view != null) { + Insets insets = layer.getInsets(); + view.setLocation(insets.left, insets.top); + view.setSize(layer.getWidth() - insets.left - insets.right, + layer.getHeight() - insets.top - insets.bottom); + } + if (glassPane != null) { + glassPane.setLocation(0, 0); + glassPane.setSize(layer.getWidth(), layer.getHeight()); + } + } + + /** + * {@inheritDoc} + */ + public Dimension minimumLayoutSize(Container parent) { + JLayer layer = (JLayer) parent; + Insets insets = layer.getInsets(); + Dimension ret = new Dimension(insets.left + insets.right, + insets.top + insets.bottom); + Component view = layer.getView(); + if (view != null) { + Dimension size = view.getMinimumSize(); + ret.width += size.width; + ret.height += size.height; + } + if (ret.width == 0 || ret.height == 0) { + ret.width = ret.height = 4; + } + return ret; + } + + /** + * {@inheritDoc} + */ + public Dimension preferredLayoutSize(Container parent) { + JLayer layer = (JLayer) parent; + Insets insets = layer.getInsets(); + Dimension ret = new Dimension(insets.left + insets.right, + insets.top + insets.bottom); + Component view = layer.getView(); + if (view != null) { + Dimension size = view.getPreferredSize(); + if (size.width > 0 && size.height > 0) { + ret.width += size.width; + ret.height += size.height; + } + } + return ret; + } + + /** + * {@inheritDoc} + */ + public void addLayoutComponent(String name, Component comp) { + } + + /** + * {@inheritDoc} + */ + public void removeLayoutComponent(Component comp) { + } + } +} \ No newline at end of file diff --git a/src/share/classes/javax/swing/filechooser/FileSystemView.java b/src/share/classes/javax/swing/filechooser/FileSystemView.java index c2ff7bb8df8e90a74f37ebeaedcbd4993cd9bd25..9f969796bddfdd64b1a26801a519298d9d67ce46 100644 --- a/src/share/classes/javax/swing/filechooser/FileSystemView.java +++ b/src/share/classes/javax/swing/filechooser/FileSystemView.java @@ -37,6 +37,8 @@ import java.util.Vector; import java.lang.ref.WeakReference; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; +import java.security.AccessController; +import java.security.PrivilegedAction; import sun.awt.shell.*; @@ -718,8 +720,13 @@ class WindowsFileSystemView extends FileSystemView { return isFileSystemRoot(dir); } - public boolean isFloppyDrive(File dir) { - String path = dir.getAbsolutePath(); + public boolean isFloppyDrive(final File dir) { + String path = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return dir.getAbsolutePath(); + } + }); + return (path != null && (path.equals("A:\\") || path.equals("B:\\"))); } diff --git a/src/share/classes/javax/swing/plaf/LayerUI.java b/src/share/classes/javax/swing/plaf/LayerUI.java new file mode 100644 index 0000000000000000000000000000000000000000..44c57ce3cad0ec6fca7c6f0d00ab1d243a81c202 --- /dev/null +++ b/src/share/classes/javax/swing/plaf/LayerUI.java @@ -0,0 +1,370 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package javax.swing.plaf; + +import javax.accessibility.Accessible; +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import java.awt.*; +import java.awt.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeSupport; +import java.beans.PropertyChangeListener; +import java.io.Serializable; + +/** + * The base class for all {@link javax.swing.JLayer}'s UI delegates. + *

+ * {@link #paint(java.awt.Graphics, javax.swing.JComponent)} method performes the + * painting of the {@code JLayer} + * and {@link #eventDispatched(AWTEvent, JLayer)} method is notified + * about any {@code AWTEvent}s which have been generated by a {@code JLayer} + * or any of its subcomponents. + *

+ * The {@code LayerUI} differs from the UI delegates of the other components, + * because it is LookAndFeel independent and is not updated by default when + * the system LookAndFeel is changed. + *

+ * The subclasses of {@code LayerUI} can either be stateless and shareable + * by multiple {@code JLayer}s or not shareable. + * + * @param one of the super types of {@code JLayer}'s view component + * + * @see JLayer#setUI(LayerUI) + * @see JLayer#setView(Component) + * @see JLayer#getView() + * @since 1.7 + * + * @author Alexander Potochkin + */ +public class LayerUI + extends ComponentUI implements Serializable { + + private final PropertyChangeSupport propertyChangeSupport = + new PropertyChangeSupport(this); + + /** + * Paints the specified component. + * Subclasses should override this method and use + * the specified {@code Graphics} object to + * render the content of the component. + * + * @param g the {@code Graphics} context in which to paint; + * @param c the component being painted; + * it can be safely cast to the {@code JLayer} + */ + @Override + public void paint(Graphics g, JComponent c) { + c.paint(g); + } + + /** + * Dispatches {@code AWTEvent}s for {@code JLayer} + * and all it subcomponents to this {@code LayerUI} instance. + *

+ * To enable the {@code AWTEvent} of the particular type, + * you call {@link javax.swing.JLayer#setLayerEventMask} + * in {@link #installUI(javax.swing.JComponent)} + * and set the layer event mask to {@code 0} + * in {@link #uninstallUI(javax.swing.JComponent)} after that + * + * @param e the event to be dispatched + * @param l the layer this LayerUI is set to + * + * @see JLayer#setLayerEventMask(long) + * @see javax.swing.JLayer#getLayerEventMask() + */ + public void eventDispatched(AWTEvent e, JLayer l){ + } + + /** + * Invoked when {@link javax.swing.JLayer#updateUI()} is called + * by the {@code JLayer} this {@code LayerUI} is set to. + * + * @param l the {@code JLayer} which UI is updated + */ + public void updateUI(JLayer l){ + } + + /** + * Configures the {@code JLayer} this {@code LayerUI} is set to. + * The default implementation registers the {@code LayerUI} + * as a property change listener for the passed {@code JLayer} component. + * + * @param c the {@code JLayer} component where this UI delegate is being installed + */ + public void installUI(JComponent c) { + addPropertyChangeListener((JLayer) c); + } + + /** + * Reverses the configuration which was previously set + * in the {@link #installUI(JComponent)} method. + * The default implementation unregisters the property change listener + * for the passed JLayer component. + * + * @param c the component from which this UI delegate is being removed. + */ + public void uninstallUI(JComponent c) { + removePropertyChangeListener((JLayer) c); + } + + /** + * Adds a PropertyChangeListener to the listener list. The listener is + * registered for all bound properties of this class. + *

+ * If {@code listener} is {@code null}, + * no exception is thrown and no action is performed. + * + * @param listener the property change listener to be added + * @see #removePropertyChangeListener + * @see #getPropertyChangeListeners + * @see #addPropertyChangeListener(String, java.beans.PropertyChangeListener) + */ + public void addPropertyChangeListener(PropertyChangeListener listener) { + propertyChangeSupport.addPropertyChangeListener(listener); + } + + /** + * Removes a PropertyChangeListener from the listener list. This method + * should be used to remove PropertyChangeListeners that were registered + * for all bound properties of this class. + *

+ * If {@code listener} is {@code null}, + * no exception is thrown and no action is performed. + * + * @param listener the PropertyChangeListener to be removed + * @see #addPropertyChangeListener + * @see #getPropertyChangeListeners + * @see #removePropertyChangeListener(String, PropertyChangeListener) + */ + public void removePropertyChangeListener(PropertyChangeListener listener) { + propertyChangeSupport.removePropertyChangeListener(listener); + } + + /** + * Returns an array of all the property change listeners + * registered on this component. + * + * @return all of this ui's {@code PropertyChangeListener}s + * or an empty array if no property change + * listeners are currently registered + * @see #addPropertyChangeListener + * @see #removePropertyChangeListener + * @see #getPropertyChangeListeners(String) + */ + public PropertyChangeListener[] getPropertyChangeListeners() { + return propertyChangeSupport.getPropertyChangeListeners(); + } + + /** + * Adds a PropertyChangeListener to the listener list for a specific + * property. + *

+ * If {@code propertyName} or {@code listener} is {@code null}, + * no exception is thrown and no action is taken. + * + * @param propertyName one of the property names listed above + * @param listener the property change listener to be added + * @see #removePropertyChangeListener(String, PropertyChangeListener) + * @see #getPropertyChangeListeners(String) + * @see #addPropertyChangeListener(String, PropertyChangeListener) + */ + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + propertyChangeSupport.addPropertyChangeListener(propertyName, listener); + } + + /** + * Removes a {@code PropertyChangeListener} from the listener + * list for a specific property. This method should be used to remove + * {@code PropertyChangeListener}s + * that were registered for a specific bound property. + *

+ * If {@code propertyName} or {@code listener} is {@code null}, + * no exception is thrown and no action is taken. + * + * @param propertyName a valid property name + * @param listener the PropertyChangeListener to be removed + * @see #addPropertyChangeListener(String, PropertyChangeListener) + * @see #getPropertyChangeListeners(String) + * @see #removePropertyChangeListener(PropertyChangeListener) + */ + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + propertyChangeSupport.removePropertyChangeListener(propertyName, listener); + } + + /** + * Returns an array of all the listeners which have been associated + * with the named property. + * + * @return all of the {@code PropertyChangeListener}s associated with + * the named property; if no such listeners have been added or + * if {@code propertyName} is {@code null}, an empty + * array is returned + * @see #addPropertyChangeListener(String, PropertyChangeListener) + * @see #removePropertyChangeListener(String, PropertyChangeListener) + * @see #getPropertyChangeListeners + */ + public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { + return propertyChangeSupport.getPropertyChangeListeners(propertyName); + } + + /** + * Support for reporting bound property changes for Object properties. + * This method can be called when a bound property has changed and it will + * send the appropriate PropertyChangeEvent to any registered + * PropertyChangeListeners. + * + * @param propertyName the property whose value has changed + * @param oldValue the property's previous value + * @param newValue the property's new value + */ + protected void firePropertyChange(String propertyName, + Object oldValue, Object newValue) { + propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); + } + + /** + * Notifies the {@code LayerUI} when any of its property are changed + * and enables updating every {@code JLayer} this {@code LayerUI} instance is set to. + * + * @param evt the PropertyChangeEvent generated by this {@code LayerUI} + * @param l the {@code JLayer} this LayerUI is set to + */ + public void applyPropertyChange(PropertyChangeEvent evt, JLayer l) { + } + + /** + * Returns the preferred size of the viewport for a view component. + * + * @return the preferred size of the viewport for a view component + * @see Scrollable#getPreferredScrollableViewportSize() + */ + public Dimension getPreferredScrollableViewportSize(JLayer l) { + if (l.getView() instanceof Scrollable) { + return ((Scrollable)l.getView()).getPreferredScrollableViewportSize(); + } + return l.getPreferredSize(); + } + + /** + * Returns a scroll increment, which is required for components + * that display logical rows or columns in order to completely expose + * one block of rows or columns, depending on the value of orientation. + * + * @return the "block" increment for scrolling in the specified direction + * @see Scrollable#getScrollableBlockIncrement(Rectangle, int, int) + */ + public int getScrollableBlockIncrement(JLayer l, + Rectangle visibleRect, + int orientation, int direction) { + if (l.getView() instanceof Scrollable) { + return ((Scrollable)l.getView()).getScrollableBlockIncrement( + visibleRect,orientation, direction); + } + return (orientation == SwingConstants.VERTICAL) ? visibleRect.height : + visibleRect.width; + } + + /** + * Returns {@code false} to indicate that the height of the viewport does not + * determine the height of the layer, unless the preferred height + * of the layer is smaller than the height of the viewport. + * + * @return whether the layer should track the height of the viewport + * @see Scrollable#getScrollableTracksViewportHeight() + */ + public boolean getScrollableTracksViewportHeight(JLayer l) { + if (l.getView() instanceof Scrollable) { + return ((Scrollable)l.getView()).getScrollableTracksViewportHeight(); + } + if (l.getParent() instanceof JViewport) { + return (((JViewport)l.getParent()).getHeight() > l.getPreferredSize().height); + } + return false; + } + + /** + * Returns {@code false} to indicate that the width of the viewport does not + * determine the width of the layer, unless the preferred width + * of the layer is smaller than the width of the viewport. + * + * @return whether the layer should track the width of the viewport + * @see Scrollable + * @see LayerUI#getScrollableTracksViewportWidth(JLayer) + */ + public boolean getScrollableTracksViewportWidth(JLayer l) { + if (l.getView() instanceof Scrollable) { + return ((Scrollable)l.getView()).getScrollableTracksViewportWidth(); + } + if (l.getParent() instanceof JViewport) { + return (((JViewport)l.getParent()).getWidth() > l.getPreferredSize().width); + } + return false; + } + + /** + * Returns a scroll increment, which is required for components + * that display logical rows or columns in order to completely expose + * one new row or column, depending on the value of orientation. + * Ideally, components should handle a partially exposed row or column + * by returning the distance required to completely expose the item. + *

+ * Scrolling containers, like JScrollPane, will use this method + * each time the user requests a unit scroll. + * + * @return The "unit" increment for scrolling in the specified direction. + * This value should always be positive. + * @see Scrollable#getScrollableUnitIncrement(Rectangle, int, int) + */ + public int getScrollableUnitIncrement(JLayer l, + Rectangle visibleRect, + int orientation, int direction) { + if (l.getView() instanceof Scrollable) { + return ((Scrollable)l.getView()).getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + return 1; + } + + /** + * If the {@code JLayer}'s view component is not {@code null}, + * this calls the view's {@code getBaseline()} method. + * Otherwise, the default implementation is called. + * + * @param c {@code JLayer} to return baseline resize behavior for + * @param width the width to get the baseline for + * @param height the height to get the baseline for + * @return baseline or a value < 0 indicating there is no reasonable + * baseline + */ + public int getBaseline(JComponent c, int width, int height) { + JLayer l = (JLayer) c; + if (l.getView() != null) { + return l.getView().getBaseline(width, height); + } + return super.getBaseline(c, width, height); + } + + /** + * If the {@code JLayer}'s view component is not {@code null}, + * this calls the view's {@code getBaselineResizeBehavior()} method. + * Otherwise, the default implementation is called. + * + * @param c {@code JLayer} to return baseline resize behavior for + * @return an enum indicating how the baseline changes as the component + * size changes + */ + public Component.BaselineResizeBehavior getBaselineResizeBehavior(JComponent c) { + JLayer l = (JLayer) c; + if (l.getView() != null) { + return l.getView().getBaselineResizeBehavior(); + } + return super.getBaselineResizeBehavior(c); + } +} \ No newline at end of file diff --git a/src/share/classes/javax/swing/text/GlyphView.java b/src/share/classes/javax/swing/text/GlyphView.java index 087e9201545612c1782d31028a03a7724abd328c..64db8cd6cd129dc8882decad8c8f6788ee5c47b6 100644 --- a/src/share/classes/javax/swing/text/GlyphView.java +++ b/src/share/classes/javax/swing/text/GlyphView.java @@ -540,30 +540,7 @@ public class GlyphView extends View implements TabableView, Cloneable { */ @Override public float getMinimumSpan(int axis) { - switch (axis) { - case View.X_AXIS: - if (minimumSpan < 0) { - minimumSpan = 0; - int p0 = getStartOffset(); - int p1 = getEndOffset(); - while (p1 > p0) { - int breakSpot = getBreakSpot(p0, p1); - if (breakSpot == BreakIterator.DONE) { - // the rest of the view is non-breakable - breakSpot = p0; - } - minimumSpan = Math.max(minimumSpan, - getPartialSpan(breakSpot, p1)); - // Note: getBreakSpot returns the *last* breakspot - p1 = breakSpot - 1; - } - } - return minimumSpan; - case View.Y_AXIS: - return super.getMinimumSpan(axis); - default: - throw new IllegalArgumentException("Invalid axis: " + axis); - } + return super.getMinimumSpan(axis); } /** diff --git a/src/share/classes/javax/swing/text/ParagraphView.java b/src/share/classes/javax/swing/text/ParagraphView.java index 2b5f7826a08bc047b424731a7e0251626a2e0b82..c02ea4d810ea86b0e8e82d818ead79a115590a52 100644 --- a/src/share/classes/javax/swing/text/ParagraphView.java +++ b/src/share/classes/javax/swing/text/ParagraphView.java @@ -721,35 +721,7 @@ public class ParagraphView extends FlowView implements TabExpander { @Override protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) { - r = super.calculateMinorAxisRequirements(axis, r); - - float min = 0; - float glue = 0; - int n = getLayoutViewCount(); - for (int i = 0; i < n; i++) { - View v = getLayoutView(i); - float span = v.getMinimumSpan(axis); - if (v.getBreakWeight(axis, 0, v.getMaximumSpan(axis)) - > View.BadBreakWeight) { - // find the longest non-breakable fragments at the view edges - int p0 = v.getStartOffset(); - int p1 = v.getEndOffset(); - float start = findEdgeSpan(v, axis, p0, p0, p1); - float end = findEdgeSpan(v, axis, p1, p0, p1); - glue += start; - min = Math.max(min, Math.max(span, glue)); - glue = end; - } else { - // non-breakable view - glue += span; - min = Math.max(min, glue); - } - } - r.minimum = Math.max(r.minimum, (int) min); - r.preferred = Math.max(r.minimum, r.preferred); - r.maximum = Math.max(r.preferred, r.maximum); - - return r; + return super.calculateMinorAxisRequirements(axis, r); } /** diff --git a/src/share/classes/javax/swing/text/WrappedPlainView.java b/src/share/classes/javax/swing/text/WrappedPlainView.java index fb7aede73748731833974d6593167329e460235f..b845419ad781599e5bf8f57e8ccf8f0b91fb560f 100644 --- a/src/share/classes/javax/swing/text/WrappedPlainView.java +++ b/src/share/classes/javax/swing/text/WrappedPlainView.java @@ -327,13 +327,45 @@ public class WrappedPlainView extends BoxView implements TabExpander { /** * Return reasonable default values for the view dimensions. The standard * text terminal size 80x24 is pretty suitable for the wrapped plain view. + * + * The size should not be larger than the component housing the view's + * container. */ private float getDefaultSpan(int axis) { + Container host = getContainer(); + Component parent = null; + + if (host != null) { + parent = host.getParent(); + } + switch (axis) { case View.X_AXIS: - return 80 * metrics.getWidths()['M']; + int defaultWidth = 80 * metrics.getWidths()['M']; + int parentWidth = 0; + + if (parent != null) { + parentWidth = parent.getWidth(); + } + + if (defaultWidth > parentWidth) { + return parentWidth; + } + return defaultWidth; + case View.Y_AXIS: - return 24 * metrics.getHeight(); + int defaultHeight = 24 * metrics.getHeight(); + int parentHeight = 0; + + if (parent != null) { + parentHeight = parent.getHeight(); + } + + if (defaultHeight > parentHeight) { + return parentHeight; + } + return defaultHeight; + default: throw new IllegalArgumentException("Invalid axis: " + axis); } diff --git a/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java b/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java index 1b81007fe8e95d6048727ed0d4a53dde037ab2a6..c1efb0de52c4c1f8f4a77742818251130b618ffb 100644 --- a/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java @@ -73,12 +73,7 @@ final class Win32ShellFolder2 extends ShellFolder { private static native void initIDs(); - private static final boolean is98; - static { - String osName = System.getProperty("os.name"); - is98 = (osName != null && osName.startsWith("Windows 98")); - initIDs(); } @@ -305,7 +300,6 @@ final class Win32ShellFolder2 extends ShellFolder { }, RuntimeException.class) ); this.disposer.relativePIDL = relativePIDL; - getAbsolutePath(); sun.java2d.Disposer.addRecord(this, disposer); } @@ -616,11 +610,8 @@ final class Win32ShellFolder2 extends ShellFolder { public boolean isDirectory() { if (isDir == null) { // Folders with SFGAO_BROWSABLE have "shell extension" handlers and are - // not traversable in JFileChooser. An exception is "My Documents" on - // Windows 98. - if (hasAttribute(ATTRIB_FOLDER) - && (!hasAttribute(ATTRIB_BROWSABLE) || - (is98 && equals(Win32ShellFolderManager2.getPersonal())))) { + // not traversable in JFileChooser. + if (hasAttribute(ATTRIB_FOLDER) && !hasAttribute(ATTRIB_BROWSABLE)) { isDir = Boolean.TRUE; } else if (isLink()) { ShellFolder linkLocation = getLinkLocation(false); diff --git a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java index 4471a3ec0daf3515cd0575b6aca0de766f6caea9..8b692fa685a09141bce7caef8fc7f799bf6dfd71 100644 --- a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java @@ -105,9 +105,11 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { private static Win32ShellFolder2 network; private static Win32ShellFolder2 personal; - private static String osVersion = System.getProperty("os.version"); - private static final boolean useShell32Icons = - (osVersion != null && osVersion.compareTo("5.1") >= 0); + private static final boolean USE_SHELL32_ICONS = AccessController.doPrivileged(new PrivilegedAction() { + public Boolean run() { + return OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_XP) >= 0; + } + }); static Win32ShellFolder2 getDesktop() { if (desktop == null) { @@ -307,15 +309,15 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { i = Integer.parseInt(name); } catch (NumberFormatException ex) { if (name.equals("ListView")) { - i = (useShell32Icons) ? 21 : 2; + i = (USE_SHELL32_ICONS) ? 21 : 2; } else if (name.equals("DetailsView")) { - i = (useShell32Icons) ? 23 : 3; + i = (USE_SHELL32_ICONS) ? 23 : 3; } else if (name.equals("UpFolder")) { - i = (useShell32Icons) ? 28 : 8; + i = (USE_SHELL32_ICONS) ? 28 : 8; } else if (name.equals("NewFolder")) { - i = (useShell32Icons) ? 31 : 11; + i = (USE_SHELL32_ICONS) ? 31 : 11; } else if (name.equals("ViewMenu")) { - i = (useShell32Icons) ? 21 : 2; + i = (USE_SHELL32_ICONS) ? 21 : 2; } } if (i >= 0) { @@ -352,11 +354,16 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { * Does dir represent a "computer" such as a node on the network, or * "My Computer" on the desktop. */ - public boolean isComputerNode(File dir) { + public boolean isComputerNode(final File dir) { if (dir != null && dir == getDrives()) { return true; } else { - String path = dir.getAbsolutePath(); + String path = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return dir.getAbsolutePath(); + } + }); + return (path.startsWith("\\\\") && path.indexOf("\\", 2) < 0); //Network path } } @@ -501,7 +508,7 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { // thread, we don't need to delegate the task return task.call(); } else { - Future future; + final Future future; try { future = submit(task); @@ -512,7 +519,13 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { try { return future.get(); } catch (InterruptedException e) { - future.cancel(true); + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + future.cancel(true); + + return null; + } + }); throw e; } catch (ExecutionException e) { diff --git a/src/windows/native/sun/windows/awt_Toolkit.cpp b/src/windows/native/sun/windows/awt_Toolkit.cpp index 5158ef6c43e13dccf703873be12af86fb8778b75..b612bd1bf16f14a8d328967dc853ebea952867ff 100644 --- a/src/windows/native/sun/windows/awt_Toolkit.cpp +++ b/src/windows/native/sun/windows/awt_Toolkit.cpp @@ -1596,18 +1596,18 @@ void AwtToolkit::RegisterEmbedderProcessId(HWND embedder) } JNIEnv* AwtToolkit::m_env; -HANDLE AwtToolkit::m_thread; +DWORD AwtToolkit::m_threadId; void AwtToolkit::SetEnv(JNIEnv *env) { if (m_env != NULL) { // If already cashed (by means of embeddedInit() call). return; } - m_thread = GetCurrentThread(); + m_threadId = GetCurrentThreadId(); m_env = env; } JNIEnv* AwtToolkit::GetEnv() { - return (m_env == NULL || m_thread != GetCurrentThread()) ? + return (m_env == NULL || m_threadId != GetCurrentThreadId()) ? (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_2) : m_env; } diff --git a/src/windows/native/sun/windows/awt_Toolkit.h b/src/windows/native/sun/windows/awt_Toolkit.h index 0673201d026808d1520cbe1140a211a7f3f48686..efaf9ff843238632b612c2fd627237f025e2e090 100644 --- a/src/windows/native/sun/windows/awt_Toolkit.h +++ b/src/windows/native/sun/windows/awt_Toolkit.h @@ -442,7 +442,7 @@ public: private: static JNIEnv *m_env; - static HANDLE m_thread; + static DWORD m_threadId; public: static void SetEnv(JNIEnv *env); static JNIEnv* GetEnv(); diff --git a/test/java/beans/Introspector/Test6868189.java b/test/java/beans/Introspector/Test6868189.java new file mode 100644 index 0000000000000000000000000000000000000000..3aa10aa6d86747d63a202cf0c1788611011a702d --- /dev/null +++ b/test/java/beans/Introspector/Test6868189.java @@ -0,0 +1,66 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6868189 + * @summary Tests custom BeanInfo in the same package + * @author Sergey Malenkov + */ + +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.beans.SimpleBeanInfo; + +public class Test6868189 { + + private static final String PROPERTY = "$?"; // NON-NLS: the property name + private static final String GETTER = "name"; // NON-NLS: the method name + private static final String SETTER = null; + + public static void main(String[] args) throws IntrospectionException { + PropertyDescriptor[] pds = Introspector.getBeanInfo(Enumeration.class).getPropertyDescriptors(); + if ((pds.length != 1)|| !PROPERTY.equals(pds[0].getName())){ + throw new Error("unexpected property"); + } + } + + public enum Enumeration { + FIRST, SECOND + } + + public static class EnumerationBeanInfo extends SimpleBeanInfo { + @Override + public PropertyDescriptor[] getPropertyDescriptors() { + try { + return new PropertyDescriptor[] { + new PropertyDescriptor(PROPERTY, Enumeration.class, GETTER, SETTER) + }; + } + catch (IntrospectionException exception) { + throw new Error("unexpected exception", exception); + } + } + } +} diff --git a/test/javax/swing/JInternalFrame/Test6325652.java b/test/javax/swing/JInternalFrame/Test6325652.java new file mode 100644 index 0000000000000000000000000000000000000000..d9fea4487cba452d753b8523cdecff1780275008 --- /dev/null +++ b/test/javax/swing/JInternalFrame/Test6325652.java @@ -0,0 +1,105 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6325652 + * @summary Tests keyboard shortcuts + * @author Sergey Malenkov + * @library .. + */ + +import java.awt.AWTException; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.beans.PropertyVetoException; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JTextArea; + +public class Test6325652 { + + private static final int WIDTH = 300; + private static final int HEIGHT = 300; + + public static void main(String[] args) throws Throwable { + SwingTest.start(Test6325652.class); + } + + private static Robot robot; + private JInternalFrame internal; + + public Test6325652(JFrame frame) { + JDesktopPane desktop = new JDesktopPane(); + desktop.add(create(0)); + desktop.add(this.internal = create(1)); + frame.add(desktop); + } + + public void select() throws PropertyVetoException { + this.internal.setSelected(true); + } + + public static void stepFirst() throws AWTException { + robot = new Robot(); // initialize shared static field first time + click(KeyEvent.VK_CONTROL, KeyEvent.VK_F9); // iconify internal frame + } + + public void stepFirstValidate() { + if (!this.internal.isIcon()) { + throw new Error("frame should be an icon"); + } + } + + public static void stepSecond() { + click(KeyEvent.VK_CONTROL, KeyEvent.VK_F6); // navigate to the icon + click(KeyEvent.VK_CONTROL, KeyEvent.VK_F5); // restore the icon + } + + public void stepSecondValidate() { + if (this.internal.isIcon()) { + throw new Error("frame should not be an icon"); + } + } + + private static void click(int... keys) { + for (int key : keys) { + robot.keyPress(key); + } + for (int key : keys) { + robot.keyRelease(key); + } + } + + private static JInternalFrame create(int index) { + String text = "test" + index; // NON-NLS: frame identification + index = index * 3 + 1; + + JInternalFrame internal = new JInternalFrame(text, true, true, true, true); + internal.getContentPane().add(new JTextArea(text)); + internal.setBounds(10 * index, 10 * index, WIDTH, HEIGHT); + internal.setVisible(true); + return internal; + } +} diff --git a/test/javax/swing/JInternalFrame/Test6505027.java b/test/javax/swing/JInternalFrame/Test6505027.java index 218769003cb478267c37e7ce34594fd9d098606c..42923ec5e0c9328d7cc42b4dbeb694a4c2566c2c 100644 --- a/test/javax/swing/JInternalFrame/Test6505027.java +++ b/test/javax/swing/JInternalFrame/Test6505027.java @@ -26,6 +26,7 @@ * @bug 6505027 * @summary Tests focus problem inside internal frame * @author Sergey Malenkov + * @library .. */ import java.awt.AWTException; @@ -45,11 +46,10 @@ import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.SwingUtilities; -import javax.swing.WindowConstants; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; -public class Test6505027 implements Runnable { +public class Test6505027 { private static final boolean INTERNAL = true; private static final boolean TERMINATE = true; @@ -57,80 +57,53 @@ public class Test6505027 implements Runnable { private static final int WIDTH = 450; private static final int HEIGHT = 200; private static final int OFFSET = 10; - private static final long PAUSE = 2048L; - private static final String[] COLUMNS = { "Size", "Shape" }; // NON-NLS - private static final String[] ITEMS = { "a", "b", "c", "d" }; // NON-NLS - private static final String KEY = "terminateEditOnFocusLost"; // NON-NLS + private static final String[] COLUMNS = { "Size", "Shape" }; // NON-NLS: column names + private static final String[] ITEMS = { "a", "b", "c", "d" }; // NON-NLS: combobox content + private static final String KEY = "terminateEditOnFocusLost"; // NON-NLS: property name - public static void main(String[] args) { - SwingUtilities.invokeLater(new Test6505027()); - - Component component = null; - while (component == null) { - try { - Thread.sleep(PAUSE); - } - catch (InterruptedException exception) { - // ignore interrupted exception - } - component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - } - if (!component.getClass().equals(JComboBox.class)) { - throw new Error("unexpected focus owner: " + component); - } - SwingUtilities.getWindowAncestor(component).dispose(); + public static void main(String[] args) throws Throwable { + SwingTest.start(Test6505027.class); } - private JTable table; - private Point point; + private final JTable table = new JTable(new DefaultTableModel(COLUMNS, 2)); + + public Test6505027(JFrame main) { + Container container = main; + if (INTERNAL) { + JInternalFrame frame = new JInternalFrame(); + frame.setBounds(OFFSET, OFFSET, WIDTH, HEIGHT); + frame.setVisible(true); - public void run() { - if (this.table == null) { - JFrame main = new JFrame(); - main.setSize(WIDTH + OFFSET * 3, HEIGHT + OFFSET * 5); - main.setLocationRelativeTo(null); - main.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - main.setVisible(true); + JDesktopPane desktop = new JDesktopPane(); + desktop.add(frame, new Integer(1)); - Container container = main; - if (INTERNAL) { - JInternalFrame frame = new JInternalFrame(); - frame.setBounds(OFFSET, OFFSET, WIDTH, HEIGHT); - frame.setVisible(true); + container.add(desktop); + container = frame; + } + if (TERMINATE) { + this.table.putClientProperty(KEY, Boolean.TRUE); + } + TableColumn column = this.table.getColumn(COLUMNS[1]); + column.setCellEditor(new DefaultCellEditor(new JComboBox(ITEMS))); - JDesktopPane desktop = new JDesktopPane(); - desktop.add(frame, new Integer(1)); + container.add(BorderLayout.NORTH, new JTextField()); + container.add(BorderLayout.CENTER, new JScrollPane(this.table)); + } - container.add(desktop); - container = frame; - } - this.table = new JTable(new DefaultTableModel(COLUMNS, 2)); - if (TERMINATE) { - this.table.putClientProperty(KEY, Boolean.TRUE); - } - TableColumn column = this.table.getColumn(COLUMNS[1]); - column.setCellEditor(new DefaultCellEditor(new JComboBox(ITEMS))); + public void press() throws AWTException { + Point point = this.table.getCellRect(1, 1, false).getLocation(); + SwingUtilities.convertPointToScreen(point, this.table); - container.add(BorderLayout.NORTH, new JTextField()); - container.add(BorderLayout.CENTER, new JScrollPane(this.table)); + Robot robot = new Robot(); + robot.mouseMove(point.x + 1, point.y + 1); + robot.mousePress(InputEvent.BUTTON1_MASK); + } - SwingUtilities.invokeLater(this); - } - else if (this.point == null) { - this.point = this.table.getCellRect(1, 1, false).getLocation(); - SwingUtilities.convertPointToScreen(this.point, this.table); - SwingUtilities.invokeLater(this); - } - else { - try { - Robot robot = new Robot(); - robot.mouseMove(this.point.x + 1, this.point.y + 1); - robot.mousePress(InputEvent.BUTTON1_MASK); - } - catch (AWTException exception) { - throw new Error("unexpected exception", exception); - } + public static void validate() { + Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + if (!component.getClass().equals(JComboBox.class)) { + throw new Error("unexpected focus owner: " + component); } } } diff --git a/test/javax/swing/JInternalFrame/Test6802868.java b/test/javax/swing/JInternalFrame/Test6802868.java index 74410df81fd1b96342f0efae8e3cc2985e3ecf0d..9f8eb9bb2e7c9e7f5ace066ecc0ce00dc9e354e1 100644 --- a/test/javax/swing/JInternalFrame/Test6802868.java +++ b/test/javax/swing/JInternalFrame/Test6802868.java @@ -26,83 +26,73 @@ * @bug 6802868 * @summary JInternalFrame is not maximized when maximized parent frame * @author Alexander Potochkin + * @library .. */ -import sun.awt.SunToolkit; - import java.awt.Dimension; import java.awt.Point; -import java.awt.Robot; -import java.awt.Toolkit; import java.beans.PropertyVetoException; import javax.swing.JDesktopPane; import javax.swing.JFrame; import javax.swing.JInternalFrame; -import javax.swing.SwingUtilities; public class Test6802868 { - static JInternalFrame jif; - static JFrame frame; - static Dimension size; - static Point location; - - public static void main(String[] args) throws Exception { - Robot robot = new Robot(); - robot.setAutoDelay(20); - SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); - - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - JDesktopPane jdp = new JDesktopPane(); - frame.getContentPane().add(jdp); - - jif = new JInternalFrame("Title", true, true, true, true); - jdp.add(jif); - jif.setVisible(true); - - frame.setSize(200, 200); - frame.setLocationRelativeTo(null); - frame.setVisible(true); - - try { - jif.setMaximum(true); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - toolkit.realSync(); - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - size = jif.getSize(); - frame.setSize(300, 300); - } - }); - toolkit.realSync(); - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - if (jif.getSize().equals(size)) { - throw new RuntimeException("InternalFrame hasn't changed its size"); - } - try { - jif.setIcon(true); - } catch (PropertyVetoException e) { - e.printStackTrace(); - } - location = jif.getDesktopIcon().getLocation(); - frame.setSize(400, 400); - } - }); - toolkit.realSync(); - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - if (jif.getDesktopIcon().getLocation().equals(location)) { - throw new RuntimeException("JDesktopIcon hasn't moved"); - } - } - }); + + public static void main(String[] args) throws Throwable { + SwingTest.start(Test6802868.class); + } + + private final JFrame frame; + private final JInternalFrame internal; + private Dimension size; + private Point location; + + public Test6802868(JFrame frame) { + JDesktopPane desktop = new JDesktopPane(); + + this.frame = frame; + this.frame.add(desktop); + + this.internal = new JInternalFrame(getClass().getName(), true, true, true, true); + this.internal.setVisible(true); + + desktop.add(this.internal); + } + + public void firstAction() throws PropertyVetoException { + this.internal.setMaximum(true); + } + + public void firstTest() { + this.size = this.internal.getSize(); + resizeFrame(); + } + + public void firstValidation() { + if (this.internal.getSize().equals(this.size)) { + throw new Error("InternalFrame hasn't changed its size"); + } + } + + public void secondAction() throws PropertyVetoException { + this.internal.setIcon(true); + } + + public void secondTest() { + this.location = this.internal.getDesktopIcon().getLocation(); + resizeFrame(); + } + + public void secondValidation() { + if (this.internal.getDesktopIcon().getLocation().equals(this.location)) { + throw new Error("JDesktopIcon hasn't moved"); + } + } + + private void resizeFrame() { + Dimension size = this.frame.getSize(); + size.width += 10; + size.height += 10; + this.frame.setSize(size); } } diff --git a/test/javax/swing/JLayer/SerializationTest/SerializationTest.java b/test/javax/swing/JLayer/SerializationTest/SerializationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0c18e41491e1f84543bdebf7ddb5373261957b3f --- /dev/null +++ b/test/javax/swing/JLayer/SerializationTest/SerializationTest.java @@ -0,0 +1,53 @@ +/* + * @test + * @summary Makes sure that JLayer is synchronizable + * @author Alexander Potochkin + * @run main SerializationTest + */ + +import javax.swing.*; +import javax.swing.plaf.LayerUI; +import java.io.ByteArrayInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectInputStream; +import java.io.ByteArrayOutputStream; + +public class SerializationTest { + + public static void main(String[] args) throws Exception { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream); + + JLayer layer = new JLayer(new JButton("Hello")); + + layer.setUI(new TestLayerUI()); + + outputStream.writeObject(layer); + outputStream.flush(); + + ByteArrayInputStream byteArrayInputStream = + new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); + ObjectInputStream inputStream = new ObjectInputStream(byteArrayInputStream); + + JLayer newLayer = (JLayer) inputStream.readObject(); + + if (newLayer.getLayout() == null) { + throw new RuntimeException("JLayer's layout is null"); + } + if (newLayer.getGlassPane() == null) { + throw new RuntimeException("JLayer's glassPane is null"); + } + if (newLayer.getUI().getClass() != layer.getUI().getClass()) { + throw new RuntimeException("Different UIs"); + } + if (newLayer.getView().getClass() != layer.getView().getClass()) { + throw new RuntimeException("Different Views"); + } + } + + static class TestLayerUI extends LayerUI { + public String toString() { + return "TestLayerUI"; + } + } +} \ No newline at end of file diff --git a/test/javax/swing/JScrollPane/Test6526631.java b/test/javax/swing/JScrollPane/Test6526631.java index ec324623ee531b348e8ccfae15d9098df10d17f9..61a39c6371e25e45bf4307580035fca643510b18 100644 --- a/test/javax/swing/JScrollPane/Test6526631.java +++ b/test/javax/swing/JScrollPane/Test6526631.java @@ -27,10 +27,9 @@ * @summary Resizes right-oriented scroll pane * @author Sergey Malenkov * @library .. - * @build SwingTest - * @run main Test6526631 */ +import java.awt.ComponentOrientation; import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.JScrollBar; @@ -38,15 +37,13 @@ import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JViewport; -import static java.awt.ComponentOrientation.RIGHT_TO_LEFT; - public class Test6526631 { private static final int COLS = 90; private static final int ROWS = 50; private static final int OFFSET = 10; - public static void main(String[] args) { + public static void main(String[] args) throws Throwable { SwingTest.start(Test6526631.class); } @@ -55,7 +52,7 @@ public class Test6526631 { public Test6526631(JFrame frame) { this.pane = new JScrollPane(new JTextArea(ROWS, COLS)); - this.pane.setComponentOrientation(RIGHT_TO_LEFT); + this.pane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); this.frame = frame; this.frame.add(this.pane); } @@ -79,24 +76,24 @@ public class Test6526631 { public void validateThird() { JViewport viewport = this.pane.getViewport(); JScrollBar scroller = this.pane.getHorizontalScrollBar(); - if (!scroller.getComponentOrientation().equals(RIGHT_TO_LEFT)) { - throw new IllegalStateException("unexpected component orientation"); + if (!scroller.getComponentOrientation().equals(ComponentOrientation.RIGHT_TO_LEFT)) { + throw new Error("unexpected component orientation"); } int value = scroller.getValue(); if (value != 0) { - throw new IllegalStateException("unexpected scroll value"); + throw new Error("unexpected scroll value"); } int extent = viewport.getExtentSize().width; if (extent != scroller.getVisibleAmount()) { - throw new IllegalStateException("unexpected visible amount"); + throw new Error("unexpected visible amount"); } int size = viewport.getViewSize().width; if (size != scroller.getMaximum()) { - throw new IllegalStateException("unexpected maximum"); + throw new Error("unexpected maximum"); } int pos = size - extent - value; if (pos != viewport.getViewPosition().x) { - throw new IllegalStateException("unexpected position"); + throw new Error("unexpected position"); } } } diff --git a/test/javax/swing/JTextArea/Test6593649.java b/test/javax/swing/JTextArea/Test6593649.java new file mode 100644 index 0000000000000000000000000000000000000000..8de478b382561cfb58e540135fe46edf5d0764a4 --- /dev/null +++ b/test/javax/swing/JTextArea/Test6593649.java @@ -0,0 +1,89 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 6593649 + @summary Word wrap does not work in JTextArea: long lines are not wrapped + @author Lillian Angel + @run main Test6593649 +*/ + +import javax.swing.*; +import java.awt.*; + +public class Test6593649 extends JFrame { + static JTextArea txt; + static JPanel innerPanel; + + public Test6593649(Dimension d) + { + super("Word Wrap Testcase"); + + setSize(d); + + final Container contentPane = getContentPane(); + + innerPanel = new JPanel(); + innerPanel.setLayout(new BoxLayout(innerPanel, BoxLayout.LINE_AXIS)); + + txt = new JTextArea("This is a long line that should wrap, but doesn't..."); + txt.setLineWrap(true); + txt.setWrapStyleWord(true); + + innerPanel.add(txt); + + contentPane.add(innerPanel, BorderLayout.SOUTH); + } + + public static void main(String[] args) throws InterruptedException + { + int size = 100; + Dimension d; + Test6593649 cp; + Dimension txtSize; + Dimension innerSize; + Dimension cpSize; + + while (size <= 600) + { + d = new Dimension(size, size); + cp = new Test6593649(d); + cp.setVisible(true); + + txtSize = txt.getPreferredSize(); + innerSize = innerPanel.getPreferredSize(); + cpSize = cp.getSize(); + + if (!(txtSize.getWidth() == innerPanel.getWidth() && txtSize.getHeight() == innerPanel.getHeight() && + txtSize.getWidth() <= cpSize.getWidth() && txtSize.getHeight() <= cpSize.getHeight())) + { + throw new RuntimeException("Test failed: Text area size does not properly match panel and frame sizes"); + } + + Thread.sleep(2000); + + cp.hide(); + size += 50; + } + } +} diff --git a/test/javax/swing/SwingTest.java b/test/javax/swing/SwingTest.java index 7f486122e8ca49a3fed32e72c747efac455ebdd7..006808880eb3182bb6ae169e01f7f7fd48fa4c17 100644 --- a/test/javax/swing/SwingTest.java +++ b/test/javax/swing/SwingTest.java @@ -21,7 +21,8 @@ * have any questions. */ -import java.io.PrintWriter; +import sun.awt.SunToolkit; +import java.awt.Toolkit; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -30,12 +31,18 @@ import java.util.Iterator; import java.util.Set; import java.util.TreeSet; import javax.swing.JFrame; - -import static javax.swing.SwingUtilities.invokeLater; +import javax.swing.SwingUtilities; /** - * SwingTestHelper is a utility class for writing regression tests + * SwingTest is a utility class for writing regression tests * that require interacting with the UI. + * It uses reflection to invoke all public methods without parameters. + * All static methods are starting on the current thread. + * Other methods including constructor are starting on the EDT. + * Between each method invocation all pending events are processed. + * The methods are sorted by name and invoked in that order. + * Failure of the test is signaled by any method throwing an exception. + * If no methods throw an exception the test is assumed to have passed. * * @author Sergey A. Malenkov */ @@ -44,99 +51,56 @@ final class SwingTest implements Runnable { private static final int WIDTH = 640; private static final int HEIGHT = 480; - public static void start(Class type) { + public static void start(Class type) throws Throwable { new SwingTest(type).start(); } - private final PrintWriter writer = new PrintWriter(System.out, true); + private final Class type; + private final Iterator methods; - private Class type; private JFrame frame; - private Iterator methods; private Object object; private Method method; private Throwable error; private SwingTest(Class type) { - this.type = type; - } - - public void run() { - synchronized (this.writer) { - if (this.error != null) { - this.frame.dispose(); - this.frame = null; - } - else if (this.object == null) { - invoke(); - Set methods = new TreeSet(new Comparator() { - public int compare(Method first, Method second) { - return first.getName().compareTo(second.getName()); - } - }); - for (Method method : this.type.getMethods()) { - if (method.getDeclaringClass().equals(this.type)) { - if (method.getReturnType().equals(void.class)) { - if (0 == method.getParameterTypes().length) { - methods.add(method); - } - } - } - } - this.methods = methods.iterator(); + Set methods = new TreeSet(new Comparator() { + public int compare(Method first, Method second) { + return first.getName().compareTo(second.getName()); } - else if (this.method != null) { - invoke(); - } - else if (this.methods.hasNext()) { - this.method = this.methods.next(); - } - else { - this.frame.dispose(); - this.frame = null; - this.type = null; - } - this.writer.notifyAll(); - } - } - - private void start() { - synchronized (this.writer) { - while (this.type != null) { - if ((this.method != null) && Modifier.isStatic(this.method.getModifiers())) { - invoke(); - } - else { - invokeLater(this); - try { - this.writer.wait(); + }); + for (Method method : type.getMethods()) { + if (method.getDeclaringClass().equals(type)) { + if (method.getReturnType().equals(void.class)) { + if (0 == method.getParameterTypes().length) { + methods.add(method); } - catch (InterruptedException exception) { - exception.printStackTrace(this.writer); - } - } - if ((this.frame == null) && (this.error != null)) { - throw new Error("unexpected error", this.error); } } } + this.type = type; + this.methods = methods.iterator(); } - private void invoke() { + public void run() { try { - if (this.method != null) { - this.writer.println(this.method); - this.method.invoke(this.object); - this.method = null; - } - else { - this.writer.println(this.type); + if (this.object == null) { + System.out.println(this.type); this.frame = new JFrame(this.type.getSimpleName()); this.frame.setSize(WIDTH, HEIGHT); this.frame.setLocationRelativeTo(null); - this.object = this.type.getConstructor(JFrame.class).newInstance(this.frame); + this.object = this.type.getConstructor(this.frame.getClass()).newInstance(this.frame); this.frame.setVisible(true); } + else if (this.method != null) { + System.out.println(this.method); + this.method.invoke(this.object); + } + else { + System.out.println((this.error == null) ? "PASSED" : "FAILED"); // NON-NLS: debug + this.frame.dispose(); + this.frame = null; + } } catch (NoSuchMethodException exception) { this.error = exception; @@ -156,5 +120,29 @@ final class SwingTest implements Runnable { catch (InvocationTargetException exception) { this.error = exception.getTargetException(); } + System.out.flush(); + this.method = this.methods.hasNext() && (this.error == null) + ? this.methods.next() + : null; + } + + private void start() throws Throwable { + do { + if ((this.method != null) && Modifier.isStatic(this.method.getModifiers())) { + run(); // invoke static method on the current thread + } + else { + SwingUtilities.invokeLater(this); // invoke on the event dispatch thread + } + Toolkit tk = Toolkit.getDefaultToolkit(); + if (tk instanceof SunToolkit) { + SunToolkit stk = (SunToolkit) tk; + stk.realSync(); // wait until done + } + } + while (this.frame != null); + if (this.error != null) { + throw this.error; + } } } diff --git a/test/javax/swing/text/GlyphView/6539700/bug6539700.java b/test/javax/swing/text/GlyphView/6539700/bug6539700.java new file mode 100644 index 0000000000000000000000000000000000000000..8d83f2e22d4b87b17a1667473b236b19b6f8d430 --- /dev/null +++ b/test/javax/swing/text/GlyphView/6539700/bug6539700.java @@ -0,0 +1,114 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6539700 + * @summary test that the long space-less lines are correctly soft-wrapped + * @author Sergey Groznyh + * @run main bug6539700 + */ + +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.text.ParagraphView; +import javax.swing.text.View; + +public class bug6539700 { + static JFrame f; + static JEditorPane ep; + static String text = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAA"; + static int size = 100; + static Class rowClass = null; + + static void createContentPane() { + ep = new JEditorPane(); + ep.setContentType("text/html"); + ep.setEditable(false); + ep.setText(text); + f = new JFrame(); + f.setSize(size, 2 * size); + f.add(ep); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.setVisible(true); + } + + static void checkRows(View v, boolean last) { + int width = (int) v.getPreferredSpan(View.X_AXIS); + + if (v.getClass() == rowClass) { + // Row width shouldn't exceed the container width + if (width > size) { + throw new RuntimeException("too long row: " + width); + } + + // Row shouldn't be too short (except for the last one) + if (!last) { + if (width < size * 2 / 3) { + throw new RuntimeException("too short row: " + width); + } + } + } + + int n = v.getViewCount(); + if (n > 0) { + for (int i = 0; i < n; i++) { + View c = v.getView(i); + checkRows(c, i == n - 1); + } + } + } + + public static void main(String[] argv) { + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createContentPane(); + } + }); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + + Class[] pvchildren = ParagraphView.class.getDeclaredClasses(); + for (Class c : pvchildren) { + if (c.getName().equals("javax.swing.text.ParagraphView$Row")) { + rowClass = c; + break; + } + } + if (rowClass == null) { + throw new RuntimeException("can't find ParagraphView.Row class"); + } + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + checkRows(ep.getUI().getRootView(ep), true); + } + }); + + System.out.println("OK"); + } +}