blob: a67f703fe0d94e33d9290a155ff9b6a0323e3257 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.tobago.model;
import javax.swing.tree.TreeNode;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* Manages the expanded state of an tree.
*
* @since 2.0.0
*/
public class ExpandedState implements Serializable {
private int defaultExpandedLevels;
private Set<TreePath> expandedSet;
private Set<TreePath> collapsedSet;
/**
* Creates a new state object to store which nodes of a tree are expanded and collapsed in a view.
*
* @param defaultExpandedLevels All nodes up to this level are expanded by default.
*/
public ExpandedState(final int defaultExpandedLevels) {
this.defaultExpandedLevels = defaultExpandedLevels;
this.expandedSet = new HashSet<>();
this.collapsedSet = new HashSet<>();
}
/**
* Checks if a node is expanded.
*
* @param node The node to check.
* @return Is the node expanded?
*/
public boolean isExpanded(final TreeNode node) {
final TreePath path = new TreePath(node);
return isExpanded(path);
}
/**
* Checks if a node is expanded.
*
* @param path The path of the node to check.
* @return Is the node behind this path is expanded?
*/
public boolean isExpanded(final TreePath path) {
if (expandedSet.contains(path)) {
return true;
}
if (collapsedSet.contains(path)) {
return false;
}
return path.getLength() < defaultExpandedLevels;
}
/**
* Expands a single node.
*
* @param node The node to expand. Also the parents will be expanded since Tobago 3.0.0.
*/
public void expand(final TreeNode node) {
expand(node, true);
}
/**
* Expands a single node.
*
* @param node The node to expand.
* @param parents Should the parents also be expanded?
*/
public void expand(final TreeNode node, final boolean parents) {
final TreePath path = new TreePath(node);
expand(path, parents);
}
/**
* Expands a single node.
*
* @param path The path of the node to expand. Also the parents will be expanded since Tobago 3.0.0.
*/
public void expand(final TreePath path) {
expand(path, true);
}
/**
* Expands a single node.
*
* @param path The path of the node to expand.
* @param parents Should the parents also be expanded?
*/
public void expand(final TreePath path, final boolean parents) {
if (path.getLength() >= defaultExpandedLevels) {
expandedSet.add(path);
} else {
collapsedSet.remove(path);
}
if (parents && !path.isRoot()) {
expand(path.getParent(), true);
}
}
/**
* Expands all nodes that level are lower or equals the parameter level.
*
* @param level The level to expand.
*/
public void expand(final int level) {
final ArrayList<TreePath> toRemove = new ArrayList<>();
if (level > defaultExpandedLevels) {
defaultExpandedLevels = level;
for (final TreePath treePath : expandedSet) {
if (treePath.getLength() < defaultExpandedLevels) {
toRemove.add(treePath);
}
}
expandedSet.removeAll(toRemove);
collapsedSet.clear();
} else {
for (final TreePath treePath : collapsedSet) {
if (treePath.getLength() < level) {
toRemove.add(treePath);
}
}
collapsedSet.removeAll(toRemove);
}
}
/**
* Expands a nodes of the tree.
*/
public void expandAll() {
defaultExpandedLevels = Integer.MAX_VALUE;
expandedSet.clear();
collapsedSet.clear();
}
/**
* Collapses a single node.
*
* @param node The node to collapse.
*/
public void collapse(final TreeNode node) {
final TreePath path = new TreePath(node);
collapse(path);
}
/**
* Collapses a single node.
*
* @param path The path of the node to collapse.
*/
public void collapse(final TreePath path) {
if (path.getLength() < defaultExpandedLevels) {
collapsedSet.add(path);
} else {
expandedSet.remove(path);
}
}
/**
* Collapses all nodes that level are higher or equals the parameter level.
*
* @param level The level to expand.
*/
public void collapse(final int level) {
int count = level;
// to use a symmetric algorithm like in expand
count--;
final ArrayList<TreePath> toRemove = new ArrayList<>();
if (count < defaultExpandedLevels) {
defaultExpandedLevels = count;
for (final TreePath treePath : collapsedSet) {
if (treePath.getLength() >= defaultExpandedLevels) {
toRemove.add(treePath);
}
}
collapsedSet.removeAll(toRemove);
expandedSet.clear();
} else {
for (final TreePath treePath : expandedSet) {
if (treePath.getLength() >= count) {
toRemove.add(treePath);
}
}
expandedSet.removeAll(toRemove);
}
}
/**
* Collapses a nodes of the tree.
*/
public void collapseAll() {
defaultExpandedLevels = 0;
expandedSet.clear();
collapsedSet.clear();
}
/**
* Collapses a nodes of the tree. The root node will be expanded.
*/
public void collapseAllButRoot() {
defaultExpandedLevels = 1;
expandedSet.clear();
collapsedSet.clear();
}
/**
* Resets the state to the defaults. After this call, the nodes with level smaller than defaultExpandedLevels
* are expanded, the other ones are collapsed.
*/
public void reset() {
expandedSet.clear();
collapsedSet.clear();
}
/**
* @return A unmodifiable set of paths of the expanded nodes.
*/
public Set<TreePath> getExpandedSet() {
return Collections.unmodifiableSet(expandedSet);
}
/**
* @return A unmodifiable set of paths of the collapsed nodes.
*/
public Set<TreePath> getCollapsedSet() {
return Collections.unmodifiableSet(collapsedSet);
}
}