package info.opencards.ui.catui;
import info.opencards.core.CardFile;
import info.opencards.core.categories.Category;
import info.opencards.core.categories.CategoryChangeAdapter;
import info.opencards.core.categories.CategoryChangeListener;
import info.opencards.core.categories.CategoryUtils;
import javax.swing.*;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellEditor;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
public class CategoryTree extends JTree {
private CategoryModel catTreeModel;
private final List<CategoryTreeSelectionListener> cardSelectionListeners = new ArrayList<CategoryTreeSelectionListener>();
public CategoryTree() {
addMouseListener(new CatTreePopUp(this));
setDragEnabled(true);
setEditable(true);
setCellEditor(new CellEditor(this, new DefaultTreeCellRenderer()));
getModel().addTreeModelListener(new TreeModelListener() {
public void treeNodesChanged(TreeModelEvent e) {
expandTree();
}
public void treeNodesInserted(TreeModelEvent e) {
//select and expand
// expandPath(e.getTreePath());
expandTree();
}
public void treeNodesRemoved(TreeModelEvent e) {
// expandPath(e.getTreePath());
expandTree();
}
public void treeStructureChanged(TreeModelEvent e) {
// expandPath(e.getTreePath());
expandTree();
}
});
addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
informCardFileSelectionListeners();
}
});
DefaultTreeCellRenderer treeCellRenderer = (DefaultTreeCellRenderer) getCellRenderer();
treeCellRenderer.setLeafIcon(treeCellRenderer.getOpenIcon());
expandTree();
}
/**
* Sets the root cateogy for this tree. If <code>null</code> the current tree structure will be deleted if the tree
* already exists, and the default set of categories will be loaded.
*/
public void setRootCategory(Category rootCat) {
// deserialze categories or create dummy category model
if (rootCat == null) {
rootCat = CategoryModel.getDefaultCategory();
}
rootCat.addCategoryChangeListener(new CategoryChangeAdapter() {
public void addedChildCategory(Category category) {
expandTree();
informCardFileSelectionListeners();
}
public void removedChild(Category child) {
expandTree();
informCardFileSelectionListeners();
}
public void categoryRelocated(Category category, Category oldParent, Category newParent) {
expandTree();
informCardFileSelectionListeners();
}
public void registeredCardset(Category category, CardFile cardSet) {
informCardFileSelectionListeners();
}
public void unregisteredCardset(Category category, CardFile cardSet) {
informCardFileSelectionListeners();
}
});
if (catTreeModel != null) {
Collection<CategoryChangeListener> changeListeneres = new ArrayList<CategoryChangeListener>();
changeListeneres.addAll(catTreeModel.getRootCategory().getListeners());
for (CategoryChangeListener changeListener : changeListeneres) {
rootCat.addCategoryChangeListener(changeListener);
}
}
catTreeModel = new CategoryModel(new DefaultMutableTreeNode(rootCat), this);
// catTreeModel.getRootCategory().addCategoryChangeListener(new TreeModifier());
setModel(catTreeModel);
setTransferHandler(new CardCategoryTransferHandler());
setSelectionRow(0);
expandTree();
}
public void expandTree() {
for (int i = 0; i < getRowCount(); i++) {
expandRow(i);
}
}
public Category getSelectedCategory() {
TreePath path = getSelectionPath();
if (path == null)
return null;
DefaultMutableTreeNode selectedTreeNode = (DefaultMutableTreeNode) path.getLastPathComponent();
if (selectedTreeNode == null)
return null;
return (Category) selectedTreeNode.getUserObject();
}
public Category getRootCategory() {
return (Category) ((DefaultMutableTreeNode) getModel().getRoot()).getUserObject();
}
public void refire(TreePath pathForRow) {
fireValueChanged(new TreeSelectionEvent(this, pathForRow, true, pathForRow, pathForRow));
}
/**
* Adds a new listener.
*/
public void addCardFilesSelectionListener(CategoryTreeSelectionListener l) {
if (l == null)
return;
cardSelectionListeners.add(l);
// update the new listener to the current selection
informCardFileSelectionListeners(); // a little hacky but it does the job
}
/**
* Removes a listener.
*/
public void removeCardFilesSelectionListener(CategoryTreeSelectionListener l) {
if (l == null)
return;
cardSelectionListeners.remove(l);
}
public void informCardFileSelectionListeners() {
Set<Category> selCategories = new HashSet<Category>();
TreePath[] selectionPaths = getSelectionPaths();
if (selectionPaths == null) {
// JOptionPane.showConfirmDialog(this, "emtpy selection in tree");
return;
}
List<Category> allCats = CategoryUtils.recursiveCatCollect(catTreeModel.getRootCategory());
for (TreePath selectionPath : selectionPaths) {
Category category = (Category) ((DefaultMutableTreeNode) selectionPath.getLastPathComponent()).getUserObject();
if (allCats.contains(category))
selCategories.add(category);
}
// select the root-category if nothing is selected
if (selCategories.isEmpty())
selCategories.add(catTreeModel.getRootCategory());
// Collection<Category> selectedCategories = ((CardTableModel) cardfileTable.getModel()).getCurCatgories();
List<CardFile> selectedFiles = new ArrayList<CardFile>(CategoryUtils.extractSelectedFiles(selCategories));
for (CategoryTreeSelectionListener listener : cardSelectionListeners) {
listener.categorySelectionChanged(selectedFiles, selCategories);
}
}
class CellEditor extends DefaultTreeCellEditor {
public CellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
super(tree, renderer);
}
public boolean isCellEditable(EventObject event) {
if (event != null) {
MouseEvent e = (MouseEvent) event;
TreePath path = getPathForLocation(e.getX(), e.getY());
if (path != null) {
Category m_editedCategory = (Category) ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject();
// if (m_editedCategory.getName().equals("All"))
if (m_editedCategory.getParent() == null)
return false;
}
}
// make root not editable
return super.isCellEditable(event);
}
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
Category category = (Category) node.getUserObject();
return super.getTreeCellEditorComponent(tree, category.getName(), isSelected, expanded, leaf, row);
}
}
}