changeset 3838:1ee27e0ef269

RT-24105 TabPane renders content of all tabs even only one is active.Optimization loads only the initially selected tabs and others get loaded on selection. To load content of other tabs lazily - -Djavafx.tabpane.loadTabsLazily property can be used. To load the content of alll tabs with out any optimization, -Djavafx.tabpane.maintainfullscenegraph property can be used.
author psomashe
date Tue, 04 Jun 2013 00:16:21 -0700
parents 93863dfb5745
children d59635859529
files javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TabPaneSkin.java
diffstat 1 files changed, 49 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TabPaneSkin.java	Mon Jun 03 16:18:30 2013 -0700
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TabPaneSkin.java	Tue Jun 04 00:16:21 2013 -0700
@@ -90,6 +90,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import javafx.application.Platform;
 import javafx.beans.property.ObjectProperty;
 import javafx.css.Styleable;
 import javafx.scene.input.*;
@@ -100,12 +101,16 @@
         GROW
         // In future we could add FADE, ...
     }
+    private static final double DEFAULT_PREF_SIZE = 200.0;
+
+    private static boolean LOAD_TABS_LAZILY = Boolean.getBoolean("javafx.tabpane.loadtabslazily");
+    private static boolean LOAD_ALL_TABS = Boolean.getBoolean("javafx.tabpane.maintainfullscenegraph");
     
     private ObjectProperty<TabAnimation> openTabAnimation = new StyleableObjectProperty<TabAnimation>(TabAnimation.GROW) {
         @Override public CssMetaData<TabPane,TabAnimation> getCssMetaData() {
             return StyleableProperties.OPEN_TAB_ANIMATION;
         }
-        
+
         @Override public Object getBean() {
             return TabPaneSkin.this;
         }
@@ -114,7 +119,7 @@
             return "openTabAnimation";
         }
     };
-    
+
     private ObjectProperty<TabAnimation> closeTabAnimation = new StyleableObjectProperty<TabAnimation>(TabAnimation.GROW) {
         @Override public CssMetaData<TabPane,TabAnimation> getCssMetaData() {
             return StyleableProperties.CLOSE_TAB_ANIMATION;
@@ -176,7 +181,8 @@
     private Tab selectedTab;
     private Tab previousSelectedTab;
     private boolean isSelectingTab;
-
+    private boolean tabSwitchAction = false;
+    
     public TabPaneSkin(TabPane tabPane) {
         super(tabPane, new TabPaneBehavior(tabPane));
 
@@ -185,8 +191,11 @@
 
         tabContentRegions = FXCollections.<TabContentRegion>observableArrayList();
 
-        for (Tab tab : getSkinnable().getTabs()) {
-            addTabContent(tab);
+        // If load all tabs is true - then load contents of all tabs
+        if (LOAD_ALL_TABS) {
+            for (Tab tab : getSkinnable().getTabs()) {
+                addTabContent(tab);
+            }
         }
 
         tabHeaderAreaClipRect = new Rectangle();
@@ -215,7 +224,11 @@
             // getSelectedItem and getSelectedIndex failed select the first.
             getSkinnable().getSelectionModel().selectFirst();
         } 
-        selectedTab = getSkinnable().getSelectionModel().getSelectedItem();        
+        selectedTab = getSkinnable().getSelectionModel().getSelectedItem();
+        // If load-selected-tab property is set - then load only the contents of selected tab.
+        if (!LOAD_ALL_TABS) {
+            addTabContent(selectedTab);
+        }
         isSelectingTab = false;
 
         initializeSwipeHandlers();
@@ -229,13 +242,19 @@
         }
         return null;
     }
-
+    
     @Override protected void handleControlPropertyChanged(String property) {
         super.handleControlPropertyChanged(property);
-        if ("SELECTED_TAB".equals(property)) {            
+        if ("SELECTED_TAB".equals(property)) {
             isSelectingTab = true;
             previousSelectedTab = selectedTab;
             selectedTab = getSkinnable().getSelectionModel().getSelectedItem();
+            if (!LOAD_ALL_TABS && !LOAD_TABS_LAZILY) {
+                // remove content from previous selected tab and add content to currently selected tab
+                removeTabContent(previousSelectedTab);
+                addTabContent(selectedTab);
+            }
+            tabSwitchAction = true;
             getSkinnable().requestLayout();
         } else if ("SIDE".equals(property)) {
             updateTabPosition();
@@ -447,26 +466,14 @@
 
     private double maxw = 0.0d;
     @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
-        // The TabPane can only be as wide as it widest content width.
-        for (TabContentRegion contentRegion: tabContentRegions) {
-             maxw = Math.max(maxw, snapSize(contentRegion.prefWidth(-1)));
-        }
-        double prefwidth = isHorizontal() ?
-            Math.max(maxw, snapSize(tabHeaderArea.prefWidth(-1))) : 
-                maxw + snapSize(tabHeaderArea.prefWidth(-1));
-        return snapSize(prefwidth) + rightInset + leftInset;
+        //RT-24105 optimization : hard coded value instead of the content of the tab 
+        return DEFAULT_PREF_SIZE;
     }
 
     private double maxh = 0.0d;
     @Override protected double computePrefHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
-        // The TabPane can only be as high as it highest content height.
-        for (TabContentRegion contentRegion: tabContentRegions) {
-             maxh = Math.max(maxh, snapSize(contentRegion.prefHeight(-1)));
-        }
-        double prefheight = isHorizontal()?
-             maxh + snapSize(tabHeaderArea.prefHeight(-1)) : 
-                Math.max(maxh, snapSize(tabHeaderArea.prefHeight(-1)));
-        return snapSize(prefheight) + topInset + bottomInset;
+        // RT-24105 optimization : hard coded value instead of the content of the tab
+        return DEFAULT_PREF_SIZE;
     }
 
     @Override public double computeBaselineOffset(double topInset, double rightInset, double bottomInset, double leftInset) {
@@ -552,7 +559,7 @@
 
         double contentWidth = w - (isHorizontal() ? 0 : headerHeight);
         double contentHeight = h - (isHorizontal() ? headerHeight: 0);
-        
+
         for (int i = 0, max = tabContentRegions.size(); i < max; i++) {
             TabContentRegion tabContent = tabContentRegions.get(i);
             
@@ -561,7 +568,7 @@
                 ((Rectangle)tabContent.getClip()).setWidth(contentWidth);
                 ((Rectangle)tabContent.getClip()).setHeight(contentHeight);
             }
-            
+
             // we need to size all tabs, even if they aren't visible. For example,
             // see RT-29167
             tabContent.resize(contentWidth, contentHeight);
@@ -572,8 +579,24 @@
                 content.setVisible(tabContent.getTab().equals(selectedTab));
             }
         }
+        // check for load lazy
+        if (LOAD_TABS_LAZILY && firstLayout && !LOAD_ALL_TABS) {
+            firstLayout = false;
+            Platform.runLater(new Runnable() {
+                @Override
+                public void run() {
+                    for (Tab tab : getSkinnable().getTabs()) {
+                        if (tab != selectedTab) {
+                            addTabContent(tab);
+                        }
+                    }
+                    tabPane.requestLayout();
+                }                        
+            });                    
+        }
     }
     
+    private boolean firstLayout = true;
     
    /**
     * Super-lazy instantiation pattern from Bill Pugh.
@@ -1481,17 +1504,6 @@
                     }
                 }
             };
-            tab.selectedProperty().addListener(new InvalidationListener() {
-                @Override public void invalidated(Observable valueModel) {
-                    setVisible(getTab().isSelected());
-                }
-            });
-            tab.contentProperty().addListener(new InvalidationListener() {
-                @Override public void invalidated(Observable valueModel) {
-                    getChildren().clear();
-                    updateContent();
-                }
-            });
 
             tab.selectedProperty().addListener(tabListener);
             tab.contentProperty().addListener(tabListener);