Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -36,7 +36,6 @@
import javafx.geometry.VPos;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.Accordion;
import javafx.scene.control.Control;
import javafx.scene.control.SkinBase;
import javafx.scene.control.SplitPane;
Expand Down Expand Up @@ -65,6 +64,13 @@ public class SplitPaneSkin extends SkinBase<SplitPane> {
private ObservableList<Content> contentRegions;
private ObservableList<ContentDivider> contentDividers;
private boolean horizontal;
/**
* Flag which is used to determine whether we need to request layout when a divider position changed or not.
* E.g. We don't want to request layout when we are changing the divider position in
* {@link #layoutChildren(double, double, double, double)} since we are currently doing the layout.
* See also: JDK-8277122
*/
private boolean duringLayout;



Expand Down Expand Up @@ -216,8 +222,8 @@ public SplitPaneSkin(final SplitPane control) {
previousSize = horizontal ? sw : sh;
}

// If the window is less than the min size we want to resize
// proportionally
duringLayout = true;
// If the window is less than the min size we want to resize proportionally
double minSize = totalMinSize();
if (minSize > (horizontal ? w : h)) {
double percentage = 0;
Expand All @@ -235,6 +241,7 @@ public SplitPaneSkin(final SplitPane control) {
setupContentAndDividerForLayout();
layoutDividersAndContent(w, h);
resize = false;
duringLayout = false;
return;
}

Expand Down Expand Up @@ -411,6 +418,7 @@ public SplitPaneSkin(final SplitPane control) {
}

layoutDividersAndContent(w, h);
duringLayout = false;
resize = false;
}

Expand Down Expand Up @@ -617,7 +625,7 @@ private void addDivider(SplitPane.Divider d) {
ChangeListener<Number> posPropertyListener = new PosPropertyListener(c);
c.setPosPropertyListener(posPropertyListener);
d.positionProperty().addListener(posPropertyListener);
initializeDivderEventHandlers(c);
initializeDividerEventHandlers(c);
contentDividers.add(c);
getChildren().add(c);
}
Expand All @@ -633,7 +641,7 @@ private void removeAllDividers() {
lastDividerUpdate = 0;
}

private void initializeDivderEventHandlers(final ContentDivider divider) {
private void initializeDividerEventHandlers(final ContentDivider divider) {
// TODO: do we need to consume all mouse events?
// they only bubble to the skin which consumes them by default
divider.addEventHandler(MouseEvent.ANY, event -> {
Expand Down Expand Up @@ -954,7 +962,9 @@ public PosPropertyListener(ContentDivider divider) {
// When checking is enforced, we know that the position was set explicitly
divider.posExplicit = true;
}
getSkinnable().requestLayout();
if (!duringLayout) {
getSkinnable().requestLayout();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -25,6 +25,11 @@

package test.javafx.scene.control;

import javafx.collections.FXCollections;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import org.junit.After;
import test.com.sun.javafx.scene.control.infrastructure.StageLoader;
import javafx.css.CssMetaData;
import static test.com.sun.javafx.scene.control.infrastructure.ControlTestUtils.*;
Expand Down Expand Up @@ -53,6 +58,8 @@
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.atomic.AtomicInteger;

/**
*
* @author srikalyc
Expand All @@ -65,6 +72,7 @@ public class SplitPaneTest {
private Scene scene;
private Stage stage;
private StackPane root;
private StageLoader stageLoader;

@Before public void setup() {
tk = (StubToolkit)Toolkit.getToolkit();//This step is not needed (Just to make sure StubToolkit is loaded into VM)
Expand All @@ -79,6 +87,11 @@ public class SplitPaneTest {
stage.setScene(scene);
}

@After
public void cleanup() {
if (stageLoader != null) stageLoader.dispose();
}

/*********************************************************************
* Helper methods (NOTE TESTS) *
********************************************************************/
Expand Down Expand Up @@ -1329,4 +1342,56 @@ private double convertDividerPostionToAbsolutePostion(double pos, double edge) {

sl.dispose();
}

/**
* Verifies that a divider position change of the {@link SplitPane} does not hang the layout.
* Previously, this may happen when the divider position changed to a large number (>1),
* which can hang the layout as it resulted in multiple layout requests (through SplitPaneSkin.layoutChildren).
* See also: JDK-8277122
*/
@Test
public void testDividerOverOneDoesNotHangLayout() {
testSetDividerPositionDoesNotHangLayout(10);
}

/**
* Verifies that a divider position change of the {@link SplitPane} does not hang the layout.
* Previously, this may happen when the divider position changed to a negative number (<1),
* which can hang the layout as it resulted in multiple layout requests (through SplitPaneSkin.layoutChildren).
* See also: JDK-8277122
*/
@Test
public void testDividerUnderZeroDoesNotHangLayout() {
testSetDividerPositionDoesNotHangLayout(-1);
}

private void testSetDividerPositionDoesNotHangLayout(double dividerPosition) {
AtomicInteger layoutCounter = new AtomicInteger();
ComboBox<String> cbx = new ComboBox<>(FXCollections.observableArrayList("1", "2", "3")) {
@Override
protected void layoutChildren() {
layoutCounter.incrementAndGet();
super.layoutChildren();
}
};
SplitPane pane = new SplitPane(new Label("AAAAA"), new TabPane(new Tab("Test", cbx)));
StackPane root = new StackPane(pane);

stageLoader = new StageLoader(root);

Toolkit.getToolkit().firePulse();

pane.setDividerPosition(0, dividerPosition);

Toolkit.getToolkit().firePulse();

// Reset layout counter
layoutCounter.set(0);

cbx.getSelectionModel().select(0);
Toolkit.getToolkit().firePulse();

assertTrue(layoutCounter.get() > 0);
}

}