/******************************************************************************* * Copyright (c) 2012, 2014 Original authors and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Original authors and others - initial API and implementation * Dirk Fauth <dirk.fauth@googlemail.com> - Bug 453707 ******************************************************************************/ package org.eclipse.nebula.widgets.nattable.tree; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Implementation of {@link ITreeRowModel} that is used to perform * expand/collapse operations using the approach of hiding and showing rows. * * @param <T> * The type of the elements in the tree */ public class TreeRowModel<T> extends AbstractTreeRowModel<T> { protected final Set<Integer> parentIndexes = new HashSet<Integer>(); public TreeRowModel(ITreeData<T> treeData) { super(treeData); } @Override public boolean isCollapsed(int index) { return this.parentIndexes.contains(index); } /** * Clears the parent indexes that indicate a collapsed node. * * @deprecated Since this is not specified by the ITreeRowModel interface, * this method shouldn't be used directly and therefore be * removed. */ @Deprecated public void clear() { this.parentIndexes.clear(); } @Override public List<Integer> collapse(int index) { this.parentIndexes.add(index); notifyListeners(); return getChildIndexes(index); } /** * Performs the collapse operation without notifying the listeners while * processing. * * @param index * The index of the node in the collection that should be * collapsed. * * @return The indexes of all children of the collapsed tree node that * become invisible by performing the collapse operation. */ protected Collection<Integer> internalCollapse(int index) { this.parentIndexes.add(index); return getChildIndexes(index); } @Override public List<Integer> collapseAll() { Set<Integer> collapsedChildren = new HashSet<Integer>(); for (int i = (getTreeData().getElementCount() - 1); i >= 0; i--) { if (hasChildren(i) && !isCollapsed(i)) { collapsedChildren.addAll(internalCollapse(i)); } } List<Integer> children = new ArrayList<Integer>(collapsedChildren); Collections.sort(children); notifyListeners(); return children; } @Override public List<Integer> expand(int index) { List<Integer> children = new ArrayList<Integer>(internalExpand(index)); Collections.sort(children); notifyListeners(); return children; } /** * Performs the expand operations iteratively without notifying the * listeners while processing. * * @param index * The index of the node in the collection that should be * expanded. * @return The indexes of all children of the expanded tree node that become * visible by performing the expand operation. */ protected Collection<Integer> internalExpand(int index) { this.parentIndexes.remove(index); List<Integer> directChildren = getDirectChildIndexes(index); Set<Integer> expandedChildren = new HashSet<Integer>(directChildren); for (Integer child : directChildren) { if (hasChildren(child) && !isCollapsed(child)) { expandedChildren.addAll(internalExpand(child)); } } return expandedChildren; } @Override public List<Integer> expandAll() { Set<Integer> expandedChildren = new HashSet<Integer>(); for (int index : this.parentIndexes) { expandedChildren.addAll(getChildIndexes(index)); } this.parentIndexes.clear(); List<Integer> children = new ArrayList<Integer>(expandedChildren); Collections.sort(children); notifyListeners(); return children; } @Override public List<Integer> expandToLevel(int level) { Set<Integer> expandedChildren = new HashSet<Integer>(); List<Integer> parentCopy = new ArrayList<Integer>(this.parentIndexes); for (int index : parentCopy) { expandedChildren.addAll(internalExpandToLevel(index, level)); } List<Integer> children = new ArrayList<Integer>(expandedChildren); Collections.sort(children); notifyListeners(); return children; } @Override public List<Integer> expandToLevel(int parentIndex, int level) { List<Integer> children = new ArrayList<Integer>(internalExpandToLevel(parentIndex, level)); Collections.sort(children); notifyListeners(); return children; } /** * Performs the expand operations iteratively without notifying the * listeners while processing. * * @param index * The index of the node in the collection that should be * expanded. * @param level * The level to which the tree nodes should be expanded. * * @return The indexes of all children of the expanded tree node that become * visible by performing the expand operation. */ protected Collection<Integer> internalExpandToLevel(int index, int level) { Set<Integer> expandedChildren = new HashSet<Integer>(); if (depth(index) <= (level - 1)) { this.parentIndexes.remove(index); List<Integer> directChildren = getDirectChildIndexes(index); for (Integer child : directChildren) { expandedChildren.add(child); if (hasChildren(child) && depth(child) <= (level - 1)) { expandedChildren.addAll(internalExpandToLevel(child, level)); } } } return expandedChildren; } }