1 /* 2 * Copyright (c) 2012, 2014, 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; 27 28 import java.util.List; 29 30 /** 31 * A package protected util class used by TreeView and TreeTableView to reduce 32 * the level of code duplication. 33 */ 34 class TreeUtil { 35 36 static <T> int getExpandedDescendantCount(TreeItem<T> node, boolean treeItemCountDirty) { 37 if (node == null) return 0; 38 if (node.isLeaf()) return 1; 39 40 return node.getExpandedDescendentCount(treeItemCountDirty); 41 } 42 43 static int updateExpandedItemCount(TreeItem treeItem, boolean treeItemCountDirty, boolean isShowRoot) { 44 if (treeItem == null) { 45 return 0; 46 } else if (! treeItem.isExpanded()) { 47 return 1; 48 } else { 49 int count = getExpandedDescendantCount(treeItem, treeItemCountDirty); 50 if (! isShowRoot) count--; 51 52 return count; 53 } 54 } 55 56 static <T> TreeItem<T> getItem(TreeItem<T> parent, int itemIndex, boolean treeItemCountDirty) { 57 if (parent == null) return null; 58 59 // if itemIndex is 0 then our parent is what we were looking for 60 if (itemIndex == 0) return parent; 61 62 // if itemIndex is > the total item count, then it is out of range 63 if (itemIndex >= getExpandedDescendantCount(parent, treeItemCountDirty)) return null; 64 65 // if we got here, then one of our descendants is the item we're after 66 List<TreeItem<T>> children = parent.getChildren(); 67 if (children == null) return null; 68 69 int idx = itemIndex - 1; 70 71 TreeItem<T> child; 72 for (int i = 0, max = children.size(); i < max; i++) { 73 child = children.get(i); 74 if (idx == 0) return child; 75 76 if (child.isLeaf() || ! child.isExpanded()) { 77 idx--; 78 continue; 79 } 80 81 int expandedChildCount = getExpandedDescendantCount(child, treeItemCountDirty); 82 if (idx >= expandedChildCount) { 83 idx -= expandedChildCount; 84 continue; 85 } 86 87 TreeItem<T> result = getItem(child, idx, treeItemCountDirty); 88 if (result != null) return result; 89 idx--; 90 } 91 92 // We might get here if getItem(0) is called on an empty tree 93 return null; 94 } 95 96 static <T> int getRow(TreeItem<T> item, TreeItem<T> root, boolean treeItemCountDirty, boolean isShowRoot) { 97 if (item == null) { 98 return -1; 99 } else if (isShowRoot && item.equals(root)) { 100 return 0; 101 } 102 103 int row = 0; 104 TreeItem<T> i = item; 105 TreeItem<T> p = item.getParent(); 106 107 TreeItem<T> sibling; 108 List<TreeItem<T>> siblings; 109 boolean parentIsCollapsed = false; 110 111 while (!i.equals(root) && p != null) { 112 if (!p.isExpanded()) { 113 parentIsCollapsed = true; 114 break; 115 } 116 117 siblings = p.children; 118 119 // work up each sibling, from the current item 120 int itemIndex = siblings.indexOf(i); 121 for (int pos = itemIndex - 1; pos > -1; pos--) { 122 sibling = siblings.get(pos); 123 if (sibling == null) continue; 124 125 row += getExpandedDescendantCount(sibling, treeItemCountDirty); 126 127 if (sibling.equals(root)) { 128 if (! isShowRoot) { 129 // special case: we've found out that our sibling is 130 // actually the root node AND we aren't showing root nodes. 131 // This means that the item shouldn't actually be shown. 132 return -1; 133 } 134 return row; 135 } 136 } 137 138 i = p; 139 p = p.getParent(); 140 row++; 141 } 142 143 return (p == null && row == 0) || parentIsCollapsed ? -1 : isShowRoot ? row : row - 1; 144 } 145 }