Skip to content

Commit 90d6ad0

Browse files
committed
8356594: JSplitPane loses divider location when reopened via JOptionPane.createDialog()
Reviewed-by: kizune
1 parent 3193a28 commit 90d6ad0

File tree

2 files changed

+204
-16
lines changed

2 files changed

+204
-16
lines changed

‎src/java.desktop/share/classes/javax/swing/JSplitPane.java

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -369,22 +369,25 @@ public JSplitPane(int newOrientation,
369369
*/
370370
@Override
371371
public void setComponentOrientation(ComponentOrientation orientation) {
372+
ComponentOrientation curOrn = this.getComponentOrientation();
372373
super.setComponentOrientation(orientation);
373-
Component leftComponent = this.getLeftComponent();
374-
Component rightComponent = this.getRightComponent();
375-
if (!this.getComponentOrientation().isLeftToRight()) {
376-
if (rightComponent != null) {
377-
setLeftComponent(rightComponent);
378-
}
379-
if (leftComponent != null) {
380-
setRightComponent(leftComponent);
381-
}
382-
} else {
383-
if (leftComponent != null) {
384-
setLeftComponent(leftComponent);
385-
}
386-
if (rightComponent != null) {
387-
setRightComponent(rightComponent);
374+
if (!orientation.equals(curOrn)) {
375+
Component leftComponent = this.getLeftComponent();
376+
Component rightComponent = this.getRightComponent();
377+
if (!this.getComponentOrientation().isLeftToRight()) {
378+
if (rightComponent != null) {
379+
setLeftComponent(rightComponent);
380+
}
381+
if (leftComponent != null) {
382+
setRightComponent(leftComponent);
383+
}
384+
} else {
385+
if (leftComponent != null) {
386+
setLeftComponent(leftComponent);
387+
}
388+
if (rightComponent != null) {
389+
setRightComponent(rightComponent);
390+
}
388391
}
389392
}
390393
}
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8356594
27+
* @key headful
28+
* @summary Verifies if JSplitPane loses divider location when
29+
* reopened via JOptionPane.createDialog()
30+
* @run main TestSplitPaneResetDividerLoc
31+
*/
32+
33+
import java.awt.BorderLayout;
34+
import java.awt.Color;
35+
import java.awt.Dimension;
36+
import java.awt.Point;
37+
import java.awt.Rectangle;
38+
import java.awt.Robot;
39+
import java.awt.event.ActionEvent;
40+
import java.awt.event.InputEvent;
41+
import java.awt.event.KeyEvent;
42+
43+
import javax.swing.AbstractAction;
44+
import javax.swing.JButton;
45+
import javax.swing.JDialog;
46+
import javax.swing.JFrame;
47+
import javax.swing.JOptionPane;
48+
import javax.swing.JPanel;
49+
import javax.swing.JSplitPane;
50+
import javax.swing.SwingUtilities;
51+
import javax.swing.UIManager;
52+
import javax.swing.UnsupportedLookAndFeelException;
53+
54+
public class TestSplitPaneResetDividerLoc {
55+
56+
private static JPanel lazyPanel;
57+
private static JSplitPane splitPane;
58+
private static JButton openDialogButton;
59+
private static JDialog dialog;
60+
private static JFrame frame;
61+
private static volatile Point point;
62+
private static volatile Rectangle size;
63+
private static volatile int setLoc;
64+
private static volatile int curLoc;
65+
66+
private static boolean setLookAndFeel(UIManager.LookAndFeelInfo laf) {
67+
try {
68+
UIManager.setLookAndFeel(laf.getClassName());
69+
return true;
70+
} catch (UnsupportedLookAndFeelException ignored) {
71+
System.out.println("Unsupported LAF: " + laf.getClassName());
72+
return false;
73+
} catch (ClassNotFoundException | InstantiationException
74+
| IllegalAccessException e) {
75+
throw new RuntimeException(e);
76+
}
77+
}
78+
79+
public static void main(String[] args) throws Exception {
80+
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
81+
System.out.println("Testing LAF : " + laf.getClassName());
82+
try {
83+
if (!setLookAndFeel(laf)) {
84+
continue;
85+
}
86+
SwingUtilities.invokeAndWait(TestSplitPaneResetDividerLoc::createAndShowUI);
87+
88+
Robot robot = new Robot();
89+
robot.waitForIdle();
90+
robot.delay(1000);
91+
SwingUtilities.invokeAndWait(() -> {
92+
point = openDialogButton.getLocationOnScreen();
93+
size = openDialogButton.getBounds();
94+
});
95+
robot.mouseMove(point.x + size.width / 2, point.y + size.height / 2);
96+
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
97+
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
98+
robot.waitForIdle();
99+
robot.delay(1000);
100+
101+
SwingUtilities.invokeAndWait(() -> {
102+
int divLoc = splitPane.getDividerLocation();
103+
splitPane.setDividerLocation(divLoc + 200);
104+
});
105+
robot.waitForIdle();
106+
robot.delay(1000);
107+
robot.keyPress(KeyEvent.VK_ESCAPE);
108+
robot.keyRelease(KeyEvent.VK_ESCAPE);
109+
110+
SwingUtilities.invokeAndWait(() -> {
111+
setLoc = splitPane.getDividerLocation();
112+
System.out.println(setLoc);
113+
});
114+
115+
robot.waitForIdle();
116+
robot.delay(1000);
117+
robot.mouseMove(point.x + size.width / 2, point.y + size.height / 2);
118+
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
119+
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
120+
robot.waitForIdle();
121+
robot.delay(1000);
122+
123+
SwingUtilities.invokeAndWait(() -> {
124+
curLoc = splitPane.getDividerLocation();
125+
System.out.println(curLoc);
126+
});
127+
128+
robot.keyPress(KeyEvent.VK_ESCAPE);
129+
robot.keyRelease(KeyEvent.VK_ESCAPE);
130+
131+
if (curLoc != setLoc) {
132+
throw new RuntimeException("Divider location is not preserved");
133+
}
134+
} finally {
135+
SwingUtilities.invokeAndWait(() -> {
136+
if (frame != null) {
137+
frame.dispose();
138+
}
139+
lazyPanel = null;
140+
});
141+
}
142+
}
143+
}
144+
145+
private static void createAndShowUI() {
146+
frame = new JFrame("JSplitPane Divider Location");
147+
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
148+
149+
openDialogButton = new JButton(new AbstractAction("Open Dialog") {
150+
public void actionPerformed(ActionEvent e) {
151+
openDialogFromOptionPane(frame);
152+
}
153+
});
154+
155+
frame.getContentPane().add(openDialogButton, BorderLayout.CENTER);
156+
frame.setSize(400, 100);
157+
frame.setLocationRelativeTo(null);
158+
frame.setVisible(true);
159+
}
160+
161+
private static void openDialogFromOptionPane(JFrame parent) {
162+
if (lazyPanel == null) {
163+
System.out.println("Creating lazy panel...");
164+
lazyPanel = new JPanel(new BorderLayout());
165+
166+
JPanel left = new JPanel();
167+
left.setBackground(Color.ORANGE);
168+
JPanel right = new JPanel();
169+
right.setBackground(Color.LIGHT_GRAY);
170+
171+
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, right);
172+
splitPane.setPreferredSize(new Dimension(400, 200));
173+
174+
// Set initial divider location — not preserved across dialog openings in OpenJDK 24
175+
splitPane.setDividerLocation(120);
176+
177+
lazyPanel.add(splitPane, BorderLayout.CENTER);
178+
}
179+
180+
JOptionPane optionPane = new JOptionPane(lazyPanel, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION);
181+
dialog = optionPane.createDialog(parent, "SplitPane Dialog (JOptionPane)");
182+
dialog.setModal(false);
183+
dialog.setVisible(true);
184+
}
185+
}

0 commit comments

Comments
 (0)