6864297: Right-to-left oriented JScrollPane is aligned to the wrong direction while resizing the container
Reviewed-by: peterz
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java Mon Jul 27 03:42:47 2009 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java Tue Jul 28 13:10:14 2009 +0400
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-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
@@ -37,17 +37,12 @@
import java.beans.PropertyChangeEvent;
import java.awt.Component;
-import java.awt.Container;
-import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Insets;
import java.awt.Graphics;
import java.awt.event.*;
-import java.io.Serializable;
-import java.awt.Toolkit;
-import java.awt.ComponentOrientation;
/**
* A default L&F implementation of ScrollPaneUI.
@@ -63,6 +58,7 @@
protected ChangeListener viewportChangeListener;
protected PropertyChangeListener spPropertyChangeListener;
private MouseWheelListener mouseScrollListener;
+ private int oldExtent = Integer.MIN_VALUE;
/**
* PropertyChangeListener installed on the vertical scrollbar.
@@ -327,9 +323,13 @@
* leave it until someone claims.
*/
value = Math.max(0, Math.min(max - extent, max - extent - viewPosition.x));
+ if (oldExtent > extent) {
+ value -= oldExtent - extent;
+ }
}
}
}
+ oldExtent = extent;
hsb.setValues(value, extent, 0, max);
}
@@ -1020,7 +1020,7 @@
if (viewport != null) {
if (e.getSource() == viewport) {
- viewportStateChanged(e);
+ syncScrollPaneWithViewport();
}
else {
JScrollBar hsb = scrollpane.getHorizontalScrollBar();
@@ -1077,11 +1077,6 @@
viewport.setViewPosition(p);
}
- private void viewportStateChanged(ChangeEvent e) {
- syncScrollPaneWithViewport();
- }
-
-
//
// PropertyChangeListener: This is installed on both the JScrollPane
// and the horizontal/vertical scrollbars.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JScrollPane/Test6526631.java Tue Jul 28 13:10:14 2009 +0400
@@ -0,0 +1,102 @@
+/*
+ * 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 6526631
+ * @summary Resizes right-oriented scroll pane
+ * @author Sergey Malenkov
+ * @library ..
+ * @build SwingTest
+ * @run main Test6526631
+ */
+
+import java.awt.Dimension;
+import javax.swing.JFrame;
+import javax.swing.JScrollBar;
+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) {
+ SwingTest.start(Test6526631.class);
+ }
+
+ private final JScrollPane pane;
+ private final JFrame frame;
+
+ public Test6526631(JFrame frame) {
+ this.pane = new JScrollPane(new JTextArea(ROWS, COLS));
+ this.pane.setComponentOrientation(RIGHT_TO_LEFT);
+ this.frame = frame;
+ this.frame.add(this.pane);
+ }
+
+ private void update(int offset) {
+ Dimension size = this.frame.getSize();
+ size.width += offset;
+ this.frame.setSize(size);
+ }
+
+ public void validateFirst() {
+ validateThird();
+ update(OFFSET);
+ }
+
+ public void validateSecond() {
+ validateThird();
+ update(-OFFSET);
+ }
+
+ 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");
+ }
+ int value = scroller.getValue();
+ if (value != 0) {
+ throw new IllegalStateException("unexpected scroll value");
+ }
+ int extent = viewport.getExtentSize().width;
+ if (extent != scroller.getVisibleAmount()) {
+ throw new IllegalStateException("unexpected visible amount");
+ }
+ int size = viewport.getViewSize().width;
+ if (size != scroller.getMaximum()) {
+ throw new IllegalStateException("unexpected maximum");
+ }
+ int pos = size - extent - value;
+ if (pos != viewport.getViewPosition().x) {
+ throw new IllegalStateException("unexpected position");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/SwingTest.java Tue Jul 28 13:10:14 2009 +0400
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.TreeSet;
+import javax.swing.JFrame;
+
+import static javax.swing.SwingUtilities.invokeLater;
+
+/**
+ * SwingTestHelper is a utility class for writing regression tests
+ * that require interacting with the UI.
+ *
+ * @author Sergey A. Malenkov
+ */
+final class SwingTest implements Runnable {
+
+ private static final int WIDTH = 640;
+ private static final int HEIGHT = 480;
+
+ public static void start(Class<?> type) {
+ new SwingTest(type).start();
+ }
+
+ private final PrintWriter writer = new PrintWriter(System.out, true);
+
+ private Class<?> type;
+ private JFrame frame;
+ private Iterator<Method> 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<Method> methods = new TreeSet<Method>(new Comparator<Method>() {
+ 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();
+ }
+ 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();
+ }
+ catch (InterruptedException exception) {
+ exception.printStackTrace(this.writer);
+ }
+ }
+ if ((this.frame == null) && (this.error != null)) {
+ throw new Error("unexpected error", this.error);
+ }
+ }
+ }
+ }
+
+ private void invoke() {
+ try {
+ if (this.method != null) {
+ this.writer.println(this.method);
+ this.method.invoke(this.object);
+ this.method = null;
+ }
+ else {
+ this.writer.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.frame.setVisible(true);
+ }
+ }
+ catch (NoSuchMethodException exception) {
+ this.error = exception;
+ }
+ catch (SecurityException exception) {
+ this.error = exception;
+ }
+ catch (IllegalAccessException exception) {
+ this.error = exception;
+ }
+ catch (IllegalArgumentException exception) {
+ this.error = exception;
+ }
+ catch (InstantiationException exception) {
+ this.error = exception;
+ }
+ catch (InvocationTargetException exception) {
+ this.error = exception.getTargetException();
+ }
+ }
+}