/*
* Zettelkasten - nach Luhmann
* Copyright (C) 2001-2015 by Daniel Lüdecke (http://www.danielluedecke.de)
*
* Homepage: http://zettelkasten.danielluedecke.de
*
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This program 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 for more details.
*
* You should have received a copy of the GNU General Public License along with this program;
* if not, see <http://www.gnu.org/licenses/>.
*
*
* Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU
* General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben
* und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (wenn Sie möchten)
* jeder späteren Version.
*
* Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein
* wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die implizite Garantie der MARKTREIFE oder
* der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der
* GNU General Public License.
*
* Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm
* erhalten haben. Falls nicht, siehe <http://www.gnu.org/licenses/>.
*/
package de.danielluedecke.zettelkasten.util;
import de.danielluedecke.zettelkasten.database.Daten;
import de.danielluedecke.zettelkasten.util.classes.TreeUserObject;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
/**
*
* @author Luedeke
*/
public class TreeUtil {
private static final List<String> collapsedNodes = new ArrayList<>();
private static int expandLevel = -1;
/**
* Sets the level to which sub branches a tree will be expanded.
*
* @param level the "depth" of the tree expansion.
*/
public static void setExpandLevel(int level) {
expandLevel = level;
}
public static int getExpandLevel() {
return expandLevel;
}
/**
* This method extracts a node's ID.
*
* @param node the node where we want to extract the ID
* @return the ID of the node's name (userobject) as string, or {@code null}
* if an error occured or nothing was found.
*/
public static boolean nodeIsRoot(DefaultMutableTreeNode node) {
if (node != null) {
TreeUserObject userObject = (TreeUserObject) node.getUserObject();
return userObject.getId().equals(Constants.ROOT_ID_NAME);
}
return false;
}
/**
* This method returns the text of a node which is used in the DesktopFrame.
* This node usually has an id in its text. This method cuts off this id, so
* only the "cleaned" node-text wil be returned.
*
* @param node the node which text should be retrieved
* @return a "cleaned" node-text with the id truncated, or {@code null} if
* an error occured.
*/
public static String getNodeText(DefaultMutableTreeNode node) {
String uebertext = null;
if (node != null) {
TreeUserObject userObject = (TreeUserObject) node.getUserObject();
uebertext = userObject.toString();
}
return uebertext;
}
/**
* This method extracts a node's ID.
*
* @param node the node where we want to extract the ID
* @return the ID of the node's name (userobject) as string, or {@code null}
* if an error occured or nothing was found.
*/
public static String getNodeID(DefaultMutableTreeNode node) {
if (node != null) {
TreeUserObject userObject = (TreeUserObject) node.getUserObject();
return userObject.getId();
}
return null;
}
/**
* This method extracts the timestamp-id of a node's name.
*
* @param node the node where we want to extract the timestamp-id
* @return the timestamp-id of the node's name (userobject) as string, or
* {@code null} if an error occured or nothing was found.
*/
public static String getNodeTimestamp(DefaultMutableTreeNode node) {
if (node != null) {
TreeUserObject userObject = (TreeUserObject) node.getUserObject();
return userObject.getId();
}
return null;
}
/**
* This method extracts an entry's number from a node's text (userobject)
* and returns it as integer-value
*
* @param node the node from which the entry-number should be extracted
* @return the entry-number, or -1 if an error occured.
*/
public static int extractEntryNumberFromNode(DefaultMutableTreeNode node) {
TreeUserObject userObject = (TreeUserObject) node.getUserObject();
String entrynumber = userObject.getNr();
if (entrynumber != null && !entrynumber.isEmpty()) {
try {
return Integer.parseInt(entrynumber);
} catch (NumberFormatException e) {
return -1;
}
}
return -1;
}
private static void expandAllTrees(TreePath parent, JTree tree) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) parent.getLastPathComponent();
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements();) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
expandAllTrees(path, tree);
}
}
// retrieve treenode user object
TreeUserObject userObject = (TreeUserObject) node.getUserObject();
// check whether deepest level is reached.
if ((expandLevel != -1 && node.getLevel() < expandLevel) || -1 == expandLevel) {
// check whether treenode-id is in the list of collapsed items
if (userObject != null && collapsedNodes.contains(userObject.getId())) {
// if yes, collapse treenode
tree.collapsePath(parent);
} else {
// else expand it
tree.expandPath(parent);
}
} else {
tree.collapsePath(parent);
}
}
/**
* If expand is true, expands all nodes in the tree. Otherwise, collapses
* all nodes in the tree.
*
* @param tree
*/
public static void expandAllTrees(JTree tree) {
DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();
expandAllTrees(new TreePath(root), tree);
}
private static void expandAllTrees(TreePath parent, boolean expand, JTree tree) {
TreeNode node = (TreeNode) parent.getLastPathComponent();
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements();) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
expandAllTrees(path, expand, tree);
}
}
if (expand) {
tree.expandPath(parent);
} else {
tree.collapsePath(parent);
}
}
/**
* If expand is true, expands all nodes in the tree. Otherwise, collapses
* all nodes in the tree.
*
* @param expand
* @param tree
*/
public static void expandAllTrees(boolean expand, JTree tree) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
expandAllTrees(new TreePath(root), expand, tree);
}
private static void retrieveCollapsedNodes(TreePath parent, JTree tree) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) parent.getLastPathComponent();
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements();) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
retrieveCollapsedNodes(path, tree);
}
}
// retrieve treenode user object
TreeUserObject userObject = (TreeUserObject) node.getUserObject();
// check for valid value
if (userObject != null && userObject.isCollapsed()) {
// if treenode is collapsed, remember state
collapsedNodes.add(userObject.getId());
}
}
/**
* If expand is true, expands all nodes in the tree. Otherwise, collapses
* all nodes in the tree.
*
* @param tree
* @return
*/
public static List<String> retrieveCollapsedNodes(JTree tree) {
// clear collapsed nodes
collapsedNodes.clear();
// if we have no tree, do nothing
if (null == tree) {
return null;
}
// get root
DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();
// if we have no root, return
if (null == root) {
return null;
}
// else retrieve all collapsed nodes and save their ID's in a list
retrieveCollapsedNodes(new TreePath(root), tree);
return collapsedNodes;
}
public static String retrieveNodeTitle(Daten data, boolean showNumber, String nr) {
StringBuilder sb = new StringBuilder("");
String zettelTitle = data.getZettelTitle(Integer.parseInt(nr));
if (showNumber || zettelTitle.isEmpty()) {
sb.append(nr);
if (!zettelTitle.isEmpty()) {
sb.append(": ");
}
}
if (!zettelTitle.isEmpty()) {
sb.append(zettelTitle);
}
return sb.toString();
}
/**
* Clears the array that saves all currently collapsed nodes from the
* jLuhmannTree, so the tree cabn be fully expanded.
*/
public static void resetCollapsedNodes() {
// clear collapsed nodes
collapsedNodes.clear();
}
/**
* This method selects the first entry in a jTree that start with the text
* that is entered in the filter-textfield.
*
* @param tree the jTree where the item should be selected
* @param textfield the related filtertextfield that contains the user-input
*/
public static void selectByTyping(javax.swing.JTree tree, javax.swing.JTextField textfield) {
DefaultTreeModel dtm = (DefaultTreeModel) tree.getModel();
MutableTreeNode root = (MutableTreeNode) dtm.getRoot();
String text = textfield.getText().toLowerCase();
if (root != null && !text.isEmpty()) {
for (int cnt = 0; cnt < dtm.getChildCount(root); cnt++) {
MutableTreeNode child = (MutableTreeNode) dtm.getChild(root, cnt);
String childtext = child.toString().toLowerCase();
if (childtext.startsWith(text)) {
TreePath tp = new TreePath(root);
tp = tp.pathByAddingChild(child);
tree.setSelectionPath(tp);
tree.scrollPathToVisible(tp);
return;
}
}
}
}
}