1 /* 2 * Copyright (c) 2010, 2015, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javafx.scene.control.skin; 27 28 import javafx.beans.property.ObjectProperty; 29 import javafx.beans.property.SimpleObjectProperty; 30 import javafx.scene.control.Cell; 31 import javafx.scene.control.Control; 32 import javafx.scene.control.IndexedCell; 33 import javafx.scene.control.ScrollToEvent; 34 import javafx.scene.control.SkinBase; 35 import javafx.util.Callback; 36 37 /** 38 * Parent class to control skins whose contents are virtualized and scrollable. 39 * This class handles the interaction with the VirtualFlow class, which is the 40 * main class handling the virtualization of the contents of this container. 41 */ 42 public abstract class VirtualContainerBase<C extends Control, I extends IndexedCell> extends SkinBase<C> { 43 44 /*************************************************************************** 45 * * 46 * Private fields * 47 * * 48 **************************************************************************/ 49 50 boolean rowCountDirty; 51 52 /** 53 * The virtualized container which handles the layout and scrolling of 54 * all the cells. 55 */ 56 private final VirtualFlow<I> flow; 57 58 59 60 /*************************************************************************** 61 * * 62 * Constructors * 63 * * 64 **************************************************************************/ 65 66 /** 67 * 68 * @param control 69 */ 70 public VirtualContainerBase(final C control) { 71 super(control); 72 flow = createVirtualFlow(); 73 74 control.addEventHandler(ScrollToEvent.scrollToTopIndex(), event -> { 75 // Fix for RT-24630: The row count in VirtualFlow was incorrect 76 // (normally zero), so the scrollTo call was misbehaving. 77 if (rowCountDirty) { 78 // update row count before we do a scroll 79 updateRowCount(); 80 rowCountDirty = false; 81 } 82 flow.scrollToTop(event.getScrollTarget()); 83 }); 84 } 85 86 87 88 /*************************************************************************** 89 * * 90 * Abstract API * 91 * * 92 **************************************************************************/ 93 94 /** 95 * Returns the total number of items in this container, including those 96 * that are currently hidden because they are out of view. 97 */ 98 abstract int getItemCount(); 99 100 abstract void updateRowCount(); 101 102 103 104 /*************************************************************************** 105 * * 106 * Public API * 107 * * 108 **************************************************************************/ 109 110 /** {@inheritDoc} */ 111 @Override protected void layoutChildren(double x, double y, double w, double h) { 112 checkState(); 113 } 114 115 116 117 /*************************************************************************** 118 * * 119 * Private methods * 120 * * 121 **************************************************************************/ 122 123 /** 124 * This enables skin subclasses to provide a custom VirtualFlow implementation, 125 * rather than have VirtualContainerBase instantiate the default instance. 126 */ 127 VirtualFlow<I> createVirtualFlow() { 128 return new VirtualFlow<>(); 129 } 130 131 final VirtualFlow<I> getVirtualFlow() { 132 return flow; 133 } 134 135 double getMaxCellWidth(int rowsToCount) { 136 return snappedLeftInset() + flow.getMaxCellWidth(rowsToCount) + snappedRightInset(); 137 } 138 139 double getVirtualFlowPreferredHeight(int rows) { 140 double height = 1.0; 141 142 for (int i = 0; i < rows && i < getItemCount(); i++) { 143 height += flow.getCellLength(i); 144 } 145 146 return height + snappedTopInset() + snappedBottomInset(); 147 } 148 149 void checkState() { 150 if (rowCountDirty) { 151 updateRowCount(); 152 rowCountDirty = false; 153 } 154 } 155 }