/*
* Copyright (c) 2012, 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javafx.scene.control;
import java.util.List;
A package protected util class used by TreeView and TreeTableView to reduce
the level of code duplication.
/**
* A package protected util class used by TreeView and TreeTableView to reduce
* the level of code duplication.
*/
class TreeUtil {
static <T> int getExpandedDescendantCount(TreeItem<T> node, boolean treeItemCountDirty) {
if (node == null) return 0;
if (node.isLeaf()) return 1;
return node.getExpandedDescendentCount(treeItemCountDirty);
}
static int updateExpandedItemCount(TreeItem treeItem, boolean treeItemCountDirty, boolean isShowRoot) {
if (treeItem == null) {
return 0;
} else if (! treeItem.isExpanded()) {
return 1;
} else {
int count = getExpandedDescendantCount(treeItem, treeItemCountDirty);
if (! isShowRoot) count--;
return count;
}
}
static <T> TreeItem<T> getItem(TreeItem<T> parent, int itemIndex, boolean treeItemCountDirty) {
if (parent == null) return null;
// if itemIndex is 0 then our parent is what we were looking for
if (itemIndex == 0) return parent;
// if itemIndex is > the total item count, then it is out of range
if (itemIndex >= getExpandedDescendantCount(parent, treeItemCountDirty)) return null;
// if we got here, then one of our descendants is the item we're after
List<TreeItem<T>> children = parent.getChildren();
if (children == null) return null;
int idx = itemIndex - 1;
TreeItem<T> child;
for (int i = 0, max = children.size(); i < max; i++) {
child = children.get(i);
if (idx == 0) return child;
if (child.isLeaf() || ! child.isExpanded()) {
idx--;
continue;
}
int expandedChildCount = getExpandedDescendantCount(child, treeItemCountDirty);
if (idx >= expandedChildCount) {
idx -= expandedChildCount;
continue;
}
TreeItem<T> result = getItem(child, idx, treeItemCountDirty);
if (result != null) return result;
idx--;
}
// We might get here if getItem(0) is called on an empty tree
return null;
}
static <T> int getRow(TreeItem<T> item, TreeItem<T> root, boolean treeItemCountDirty, boolean isShowRoot) {
if (item == null) {
return -1;
} else if (isShowRoot && item.equals(root)) {
return 0;
}
int row = 0;
TreeItem<T> i = item;
TreeItem<T> p = item.getParent();
TreeItem<T> sibling;
List<TreeItem<T>> siblings;
boolean parentIsCollapsed = false;
while (!i.equals(root) && p != null) {
if (!p.isExpanded()) {
parentIsCollapsed = true;
break;
}
siblings = p.children;
// work up each sibling, from the current item
int itemIndex = siblings.indexOf(i);
for (int pos = itemIndex - 1; pos > -1; pos--) {
sibling = siblings.get(pos);
if (sibling == null) continue;
row += getExpandedDescendantCount(sibling, treeItemCountDirty);
if (sibling.equals(root)) {
if (! isShowRoot) {
// special case: we've found out that our sibling is
// actually the root node AND we aren't showing root nodes.
// This means that the item shouldn't actually be shown.
return -1;
}
return row;
}
}
i = p;
p = p.getParent();
// we are at the root, does the root match the given root?
// if not, the item does not exist in the current tree.
if (p == null && !i.equals(root)) {
return -1;
}
row++;
}
return (p == null && row == 0) || parentIsCollapsed ? -1 : isShowRoot ? row : row - 1;
}
}