From 47674a6b1a3e8cb14e7abeabe8b55ceac816615e Mon Sep 17 00:00:00 2001 From: Ambarish Rapte Date: Tue, 13 Oct 2020 13:41:59 +0100 Subject: [PATCH 1/4] 8242621: TabPane: Memory leak when switching skin --- .../scene/control/skin/TabPaneSkin.java | 67 ++++++++++++++----- .../control/skin/SkinMemoryLeakTest.java | 2 - 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TabPaneSkin.java b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TabPaneSkin.java index 494199e60cc..6ea58331003 100644 --- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TabPaneSkin.java +++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TabPaneSkin.java @@ -267,6 +267,16 @@ public TabPaneSkin(TabPane control) { /** {@inheritDoc} */ @Override public void dispose() { + if (getSkinnable() == null) return; + + getSkinnable().getTabs().removeListener(weakTabsListener); + + getChildren().remove(tabHeaderArea); + tabHeaderArea.removeListeners(); + + for (TabContentRegion contentRegion : tabContentRegions) { + contentRegion.dispose(); + } if (selectionModel != null) { selectionModel.selectedItemProperty().removeListener(weakSelectionChangeListener); selectionModel = null; @@ -579,8 +589,10 @@ private void addTabs(List addedList, int from) { } } + ListChangeListener tabsListener; + WeakListChangeListener weakTabsListener; private void initializeTabListener() { - getSkinnable().getTabs().addListener((ListChangeListener) c -> { + tabsListener = c -> { List tabsToRemove = new ArrayList<>(); List tabsToAdd = new ArrayList<>(); @@ -659,7 +671,9 @@ private void initializeTabListener() { // Fix for RT-34692 getSkinnable().requestLayout(); - }); + }; + weakTabsListener = new WeakListChangeListener<>(tabsListener); + getSkinnable().getTabs().addListener(weakTabsListener); } private void addTabContent(Tab tab) { @@ -673,8 +687,7 @@ private void addTabContent(Tab tab) { private void removeTabContent(Tab tab) { for (TabContentRegion contentRegion : tabContentRegions) { if (contentRegion.getTab().equals(tab)) { - contentRegion.removeListeners(tab); - getChildren().remove(contentRegion); + contentRegion.dispose(); tabContentRegions.remove(contentRegion); break; } @@ -700,7 +713,7 @@ private Timeline createTimeline(final TabHeaderSkin tabRegion, final Duration du } private boolean isHorizontal() { - Side tabPosition = getSkinnable().getSide(); + Side tabPosition = getSkinnable() != null ? getSkinnable().getSide() : Side.TOP; return Side.TOP.equals(tabPosition) || Side.BOTTOM.equals(tabPosition); } @@ -1208,6 +1221,14 @@ private double firstTabIndent() { positionInArea(controlButtons, controlStartX, controlStartY, btnWidth, btnHeight, /*baseline ignored*/0, HPos.CENTER, VPos.CENTER); } + + void removeListeners() { + for(Node child : headersRegion.getChildren()) { + TabHeaderSkin header = (TabHeaderSkin) child; + header.removeListeners(header.getTab()); + } + controlButtons.removeListeners(); + } } /* End TabHeaderArea */ @@ -1542,6 +1563,7 @@ private boolean showCloseButton() { }; private void removeListeners(Tab tab) { + tab.getStyleClass().removeListener(weakStyleClassListener); listener.dispose(); inner.getChildren().clear(); getChildren().clear(); @@ -1693,11 +1715,16 @@ private void updateContent() { } } - private void removeListeners(Tab tab) { + private void removeListeners() { tab.selectedProperty().removeListener(weakTabSelectedListener); tab.contentProperty().removeListener(weakTabContentListener); } + public void dispose() { + getChildren().clear(); + removeListeners(); + } + } /* End TabContentRegion */ /************************************************************************** @@ -1785,11 +1812,8 @@ private void positionArrow(Pane btn, StackPane arrow, double x, double y, double getChildren().add(inner); - tabPane.sideProperty().addListener(valueModel -> { - Side tabPosition = getSkinnable().getSide(); - downArrow.setRotate(tabPosition.equals(Side.BOTTOM)? 180.0F : 0.0F); - }); - tabPane.getTabs().addListener((ListChangeListener) c -> setupPopupMenu()); + tabPane.sideProperty().addListener(weakSidePropListener); + tabPane.getTabs().addListener(weakTabsListenerForPopup); showControlButtons = false; if (isShowTabsMenu()) { showControlButtons = true; @@ -1798,6 +1822,21 @@ private void positionArrow(Pane btn, StackPane arrow, double x, double y, double getProperties().put(ContextMenu.class, popup); } + InvalidationListener sidePropListener = e -> { + Side tabPosition = getSkinnable().getSide(); + downArrow.setRotate(tabPosition.equals(Side.BOTTOM)? 180.0F : 0.0F); + }; + ListChangeListener tabsListenerForPopup = e -> setupPopupMenu(); + WeakInvalidationListener weakSidePropListener = + new WeakInvalidationListener(sidePropListener); + WeakListChangeListener weakTabsListenerForPopup = + new WeakListChangeListener<>(tabsListenerForPopup); + + void removeListeners() { + getSkinnable().sideProperty().removeListener(weakSidePropListener); + getSkinnable().getTabs().removeListener(weakTabsListenerForPopup); + } + private boolean showTabsMenu = false; private void showTabsMenu(boolean value) { @@ -2058,11 +2097,7 @@ private void setupReordering(StackPane headersRegion) { dragState = DragState.NONE; this.headersRegion = headersRegion; updateListeners(); - getSkinnable().tabDragPolicyProperty().addListener((observable, oldValue, newValue) -> { - if (oldValue != newValue) { - updateListeners(); - } - }); + registerChangeListener(getSkinnable().tabDragPolicyProperty(), inv -> updateListeners()); } private void handleHeaderMousePressed(MouseEvent event) { diff --git a/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinMemoryLeakTest.java b/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinMemoryLeakTest.java index c3bd5acc490..24d2f47d537 100644 --- a/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinMemoryLeakTest.java +++ b/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinMemoryLeakTest.java @@ -122,8 +122,6 @@ public static Collection data() { SplitPane.class, TableRow.class, TableView.class, - // @Ignore("8242621") - TabPane.class, // @Ignore("8244419") TextArea.class, // @Ignore("8240506") From a3b57950bb124af1fc1c26a64bc01b8690ffc872 Mon Sep 17 00:00:00 2001 From: arapte Date: Mon, 21 Dec 2020 17:19:36 +0530 Subject: [PATCH 2/4] Review update --- .../scene/control/skin/TabPaneSkin.java | 32 +++++---- .../scene/control/skin/SkinCleanupTest.java | 65 +++++++++++++++++++ 2 files changed, 85 insertions(+), 12 deletions(-) diff --git a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TabPaneSkin.java b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TabPaneSkin.java index 6ea58331003..4a74fdc7c40 100644 --- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TabPaneSkin.java +++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TabPaneSkin.java @@ -269,18 +269,21 @@ public TabPaneSkin(TabPane control) { @Override public void dispose() { if (getSkinnable() == null) return; - getSkinnable().getTabs().removeListener(weakTabsListener); - - getChildren().remove(tabHeaderArea); - tabHeaderArea.removeListeners(); - - for (TabContentRegion contentRegion : tabContentRegions) { - contentRegion.dispose(); - } if (selectionModel != null) { selectionModel.selectedItemProperty().removeListener(weakSelectionChangeListener); selectionModel = null; } + getSkinnable().getTabs().removeListener(weakTabsListener); + tabHeaderArea.removeListeners(); + + + // Control and Skin share the list of children, so children that are + // added by Skin are actually added to control's list of children, + // so a skin should remove the children that it adds. + getChildren().remove(tabHeaderArea); + for (Tab tab : getSkinnable().getTabs()) { + removeTabContent(tab); + } super.dispose(); @@ -687,13 +690,18 @@ private void addTabContent(Tab tab) { private void removeTabContent(Tab tab) { for (TabContentRegion contentRegion : tabContentRegions) { if (contentRegion.getTab().equals(tab)) { - contentRegion.dispose(); - tabContentRegions.remove(contentRegion); + removeTabContent(contentRegion); break; } } } + private void removeTabContent(TabContentRegion contentRegion) { + contentRegion.dispose(); + tabContentRegions.remove(contentRegion); + getChildren().remove(contentRegion); + } + private void updateTabPosition() { tabHeaderArea.invalidateScrollOffset(); getSkinnable().applyCss(); @@ -713,7 +721,7 @@ private Timeline createTimeline(final TabHeaderSkin tabRegion, final Duration du } private boolean isHorizontal() { - Side tabPosition = getSkinnable() != null ? getSkinnable().getSide() : Side.TOP; + Side tabPosition = getSkinnable().getSide(); return Side.TOP.equals(tabPosition) || Side.BOTTOM.equals(tabPosition); } @@ -1223,7 +1231,7 @@ private double firstTabIndent() { } void removeListeners() { - for(Node child : headersRegion.getChildren()) { + for (Node child : headersRegion.getChildren()) { TabHeaderSkin header = (TabHeaderSkin) child; header.removeListeners(header.getTab()); } diff --git a/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinCleanupTest.java b/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinCleanupTest.java index da5df50b5d6..8f3b4e05c8e 100644 --- a/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinCleanupTest.java +++ b/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinCleanupTest.java @@ -37,11 +37,14 @@ import static test.com.sun.javafx.scene.control.infrastructure.ControlSkinFactory.*; import javafx.scene.Scene; +import javafx.scene.control.skin.TabPaneSkin; import javafx.scene.control.Button; import javafx.scene.control.ChoiceBox; import javafx.scene.control.Control; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; import javafx.scene.control.ToolBar; import javafx.scene.control.TreeCell; import javafx.scene.control.TreeItem; @@ -257,6 +260,68 @@ public void testToolBarFocus() { assertEquals("first item in toolbar must be focused", bar.getItems().get(0), scene.getFocusOwner()); } +//-------- TabPane + @Test + public void testChildrenCountAfterSkinIsReplaced() { + TabPane tabPane = new TabPane(); + tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); + showControl(tabPane, false); + assertEquals(3, tabPane.getChildrenUnmodifiable().size()); + TabPaneSkin skin1 = (TabPaneSkin)createAlternativeSkin(tabPane); + assertEquals(6, tabPane.getChildrenUnmodifiable().size()); + tabPane.setSkin(skin1); + assertEquals(3, tabPane.getChildrenUnmodifiable().size()); + } + + @Test + public void testChildrenCountAfterSkinIsRemoved() { + TabPane tabPane = new TabPane(); + assertEquals(0, tabPane.getChildrenUnmodifiable().size()); + tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); + showControl(tabPane, false); + assertEquals(3, tabPane.getChildrenUnmodifiable().size()); + root.getChildren().remove(tabPane); + assertTrue(tabPane.getSkin() instanceof TabPaneSkin); + assertEquals(3, tabPane.getChildrenUnmodifiable().size()); + tabPane.setSkin(null); + assertNull(tabPane.getSkin()); + assertEquals(0, tabPane.getChildrenUnmodifiable().size()); + } + + @Test + public void testNPEWhenAddTabsAfterSkinIsReplaced() { + TabPane tabPane = new TabPane(); + tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); + showControl(tabPane, false); + replaceSkin(tabPane); + tabPane.getTabs().addAll(new Tab("2"), new Tab("3")); + } + + @Test + public void testNPEWhenRemTabAfterSkinIsReplaced() { + TabPane tabPane = new TabPane(); + tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); + showControl(tabPane, false); + replaceSkin(tabPane); + tabPane.getTabs().remove(0); + } + + @Test + public void testAddRemTabsAfterSkinIsReplaced() { + TabPane tabPane = new TabPane(); + tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); + showControl(tabPane, false); + assertEquals(2, tabPane.getTabs().size()); + assertEquals(3, tabPane.getChildrenUnmodifiable().size()); + replaceSkin(tabPane); + tabPane.getTabs().addAll(new Tab("2"), new Tab("3")); + assertEquals(4, tabPane.getTabs().size()); + assertEquals(5, tabPane.getChildrenUnmodifiable().size()); + tabPane.getTabs().clear(); + assertEquals(0, tabPane.getTabs().size()); + assertEquals(1, tabPane.getChildrenUnmodifiable().size()); + } + //---------------- setup and initial /** From cc16aa5f06559549a3144b90d0ea731379fa3c74 Mon Sep 17 00:00:00 2001 From: Ambarish Rapte Date: Wed, 6 Jan 2021 11:11:07 +0000 Subject: [PATCH 3/4] Review update: cleanup and corrections --- .../scene/control/skin/TabPaneSkin.java | 26 +++++++----------- .../javafx/scene/control/TabPaneTest.java | 2 -- .../scene/control/skin/SkinCleanupTest.java | 27 ++++++++----------- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TabPaneSkin.java b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TabPaneSkin.java index 4a74fdc7c40..2140da2e0de 100644 --- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TabPaneSkin.java +++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TabPaneSkin.java @@ -274,8 +274,7 @@ public TabPaneSkin(TabPane control) { selectionModel = null; } getSkinnable().getTabs().removeListener(weakTabsListener); - tabHeaderArea.removeListeners(); - + tabHeaderArea.dispose(); // Control and Skin share the list of children, so children that are // added by Skin are actually added to control's list of children, @@ -512,7 +511,7 @@ private void removeTabs(List removedList) { if (tabRegion != null) { tabRegion.isClosing = true; - tabRegion.removeListeners(tab); + tabRegion.dispose(); removeTabContent(tab); EventHandler cleanup = ae -> { @@ -1230,12 +1229,12 @@ private double firstTabIndent() { /*baseline ignored*/0, HPos.CENTER, VPos.CENTER); } - void removeListeners() { + void dispose() { for (Node child : headersRegion.getChildren()) { TabHeaderSkin header = (TabHeaderSkin) child; - header.removeListeners(header.getTab()); + header.dispose(); } - controlButtons.removeListeners(); + controlButtons.dispose(); } } /* End TabHeaderArea */ @@ -1524,7 +1523,7 @@ public void handle(MouseEvent me) { if (me.getButton().equals(MouseButton.MIDDLE)) { if (showCloseButton()) { if (behavior.canCloseTab(tab)) { - removeListeners(tab); + dispose(); behavior.closeTab(tab); } } @@ -1570,11 +1569,9 @@ private boolean showCloseButton() { } }; - private void removeListeners(Tab tab) { + private void dispose() { tab.getStyleClass().removeListener(weakStyleClassListener); listener.dispose(); - inner.getChildren().clear(); - getChildren().clear(); setOnContextMenuRequested(null); setOnMousePressed(null); } @@ -1723,16 +1720,11 @@ private void updateContent() { } } - private void removeListeners() { + public void dispose() { tab.selectedProperty().removeListener(weakTabSelectedListener); tab.contentProperty().removeListener(weakTabContentListener); } - public void dispose() { - getChildren().clear(); - removeListeners(); - } - } /* End TabContentRegion */ /************************************************************************** @@ -1840,7 +1832,7 @@ private void positionArrow(Pane btn, StackPane arrow, double x, double y, double WeakListChangeListener weakTabsListenerForPopup = new WeakListChangeListener<>(tabsListenerForPopup); - void removeListeners() { + void dispose() { getSkinnable().sideProperty().removeListener(weakSidePropListener); getSkinnable().getTabs().removeListener(weakTabsListenerForPopup); } diff --git a/modules/javafx.controls/src/test/java/test/javafx/scene/control/TabPaneTest.java b/modules/javafx.controls/src/test/java/test/javafx/scene/control/TabPaneTest.java index d996538b65e..727210759c6 100644 --- a/modules/javafx.controls/src/test/java/test/javafx/scene/control/TabPaneTest.java +++ b/modules/javafx.controls/src/test/java/test/javafx/scene/control/TabPaneTest.java @@ -1213,10 +1213,8 @@ class TabPaneSkin1 extends TabPaneSkin { } } - @Ignore("JDK-8242621") @Test public void testNPEOnSwitchSkinAndChangeSelection() { - // Because of JDK-8242621, this test fails with NPE. tabPane.getTabs().addAll(tab1, tab2); root.getChildren().add(tabPane); stage.show(); diff --git a/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinCleanupTest.java b/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinCleanupTest.java index 8f3b4e05c8e..35870e8c0f8 100644 --- a/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinCleanupTest.java +++ b/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinCleanupTest.java @@ -265,12 +265,10 @@ public void testToolBarFocus() { public void testChildrenCountAfterSkinIsReplaced() { TabPane tabPane = new TabPane(); tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); - showControl(tabPane, false); - assertEquals(3, tabPane.getChildrenUnmodifiable().size()); - TabPaneSkin skin1 = (TabPaneSkin)createAlternativeSkin(tabPane); - assertEquals(6, tabPane.getChildrenUnmodifiable().size()); - tabPane.setSkin(skin1); - assertEquals(3, tabPane.getChildrenUnmodifiable().size()); + installDefaultSkin(tabPane); + int childrenCount = tabPane.getChildrenUnmodifiable().size(); + replaceSkin(tabPane); + assertEquals(childrenCount, tabPane.getChildrenUnmodifiable().size()); } @Test @@ -278,10 +276,7 @@ public void testChildrenCountAfterSkinIsRemoved() { TabPane tabPane = new TabPane(); assertEquals(0, tabPane.getChildrenUnmodifiable().size()); tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); - showControl(tabPane, false); - assertEquals(3, tabPane.getChildrenUnmodifiable().size()); - root.getChildren().remove(tabPane); - assertTrue(tabPane.getSkin() instanceof TabPaneSkin); + installDefaultSkin(tabPane); assertEquals(3, tabPane.getChildrenUnmodifiable().size()); tabPane.setSkin(null); assertNull(tabPane.getSkin()); @@ -289,28 +284,28 @@ public void testChildrenCountAfterSkinIsRemoved() { } @Test - public void testNPEWhenAddTabsAfterSkinIsReplaced() { + public void testNPEWhenTabsAddedAfterSkinIsReplaced() { TabPane tabPane = new TabPane(); tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); - showControl(tabPane, false); + installDefaultSkin(tabPane); replaceSkin(tabPane); tabPane.getTabs().addAll(new Tab("2"), new Tab("3")); } @Test - public void testNPEWhenRemTabAfterSkinIsReplaced() { + public void testNPEWhenTabRemovedAfterSkinIsReplaced() { TabPane tabPane = new TabPane(); tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); - showControl(tabPane, false); + installDefaultSkin(tabPane); replaceSkin(tabPane); tabPane.getTabs().remove(0); } @Test - public void testAddRemTabsAfterSkinIsReplaced() { + public void testAddRemoveTabsAfterSkinIsReplaced() { TabPane tabPane = new TabPane(); tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); - showControl(tabPane, false); + installDefaultSkin(tabPane); assertEquals(2, tabPane.getTabs().size()); assertEquals(3, tabPane.getChildrenUnmodifiable().size()); replaceSkin(tabPane); From 93e1645fd273b3f5790c328df27417d13865feef Mon Sep 17 00:00:00 2001 From: Ambarish Rapte Date: Wed, 6 Jan 2021 11:13:04 +0000 Subject: [PATCH 4/4] Space corrections in tests --- .../scene/control/skin/SkinCleanupTest.java | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinCleanupTest.java b/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinCleanupTest.java index 35870e8c0f8..0ee424eb8fa 100644 --- a/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinCleanupTest.java +++ b/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinCleanupTest.java @@ -263,58 +263,58 @@ public void testToolBarFocus() { //-------- TabPane @Test public void testChildrenCountAfterSkinIsReplaced() { - TabPane tabPane = new TabPane(); - tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); - installDefaultSkin(tabPane); - int childrenCount = tabPane.getChildrenUnmodifiable().size(); - replaceSkin(tabPane); - assertEquals(childrenCount, tabPane.getChildrenUnmodifiable().size()); + TabPane tabPane = new TabPane(); + tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); + installDefaultSkin(tabPane); + int childrenCount = tabPane.getChildrenUnmodifiable().size(); + replaceSkin(tabPane); + assertEquals(childrenCount, tabPane.getChildrenUnmodifiable().size()); } @Test public void testChildrenCountAfterSkinIsRemoved() { - TabPane tabPane = new TabPane(); - assertEquals(0, tabPane.getChildrenUnmodifiable().size()); - tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); - installDefaultSkin(tabPane); - assertEquals(3, tabPane.getChildrenUnmodifiable().size()); - tabPane.setSkin(null); - assertNull(tabPane.getSkin()); - assertEquals(0, tabPane.getChildrenUnmodifiable().size()); + TabPane tabPane = new TabPane(); + assertEquals(0, tabPane.getChildrenUnmodifiable().size()); + tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); + installDefaultSkin(tabPane); + assertEquals(3, tabPane.getChildrenUnmodifiable().size()); + tabPane.setSkin(null); + assertNull(tabPane.getSkin()); + assertEquals(0, tabPane.getChildrenUnmodifiable().size()); } @Test public void testNPEWhenTabsAddedAfterSkinIsReplaced() { - TabPane tabPane = new TabPane(); - tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); - installDefaultSkin(tabPane); - replaceSkin(tabPane); - tabPane.getTabs().addAll(new Tab("2"), new Tab("3")); + TabPane tabPane = new TabPane(); + tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); + installDefaultSkin(tabPane); + replaceSkin(tabPane); + tabPane.getTabs().addAll(new Tab("2"), new Tab("3")); } @Test public void testNPEWhenTabRemovedAfterSkinIsReplaced() { - TabPane tabPane = new TabPane(); - tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); - installDefaultSkin(tabPane); - replaceSkin(tabPane); - tabPane.getTabs().remove(0); + TabPane tabPane = new TabPane(); + tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); + installDefaultSkin(tabPane); + replaceSkin(tabPane); + tabPane.getTabs().remove(0); } @Test public void testAddRemoveTabsAfterSkinIsReplaced() { - TabPane tabPane = new TabPane(); - tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); - installDefaultSkin(tabPane); - assertEquals(2, tabPane.getTabs().size()); - assertEquals(3, tabPane.getChildrenUnmodifiable().size()); - replaceSkin(tabPane); - tabPane.getTabs().addAll(new Tab("2"), new Tab("3")); - assertEquals(4, tabPane.getTabs().size()); - assertEquals(5, tabPane.getChildrenUnmodifiable().size()); - tabPane.getTabs().clear(); - assertEquals(0, tabPane.getTabs().size()); - assertEquals(1, tabPane.getChildrenUnmodifiable().size()); + TabPane tabPane = new TabPane(); + tabPane.getTabs().addAll(new Tab("0"), new Tab("1")); + installDefaultSkin(tabPane); + assertEquals(2, tabPane.getTabs().size()); + assertEquals(3, tabPane.getChildrenUnmodifiable().size()); + replaceSkin(tabPane); + tabPane.getTabs().addAll(new Tab("2"), new Tab("3")); + assertEquals(4, tabPane.getTabs().size()); + assertEquals(5, tabPane.getChildrenUnmodifiable().size()); + tabPane.getTabs().clear(); + assertEquals(0, tabPane.getTabs().size()); + assertEquals(1, tabPane.getChildrenUnmodifiable().size()); } //---------------- setup and initial