package uk.co.bytemark.vm.enigma.inquisition.gui.quizchooser; import java.util.Collection; 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.TreePath; import javax.swing.tree.TreeSelectionModel; import uk.co.bytemark.vm.enigma.inquisition.misc.ToStringWrapper; import uk.co.bytemark.vm.enigma.inquisition.questions.QuestionSet; public class QuestionSetTree extends JTree { private static final String ROOT_NODE_NAME = "Root"; private static final String DEFAULT_CATEGORY_NAME = "Other"; private DefaultMutableTreeNode rootNode; private DefaultTreeModel defaultTreeModel; private DefaultMutableTreeNode defaultNode = null; public QuestionSetTree() { // setCellRenderer(new NonLeafItalicTreeCellRenderer()); getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); setRootVisible(false); setNewDefaultTreeModel(); } public void initialise(Collection<QuestionSet> bundledQuestionSets) { setNewDefaultTreeModel(); for (QuestionSet questionSet : bundledQuestionSets) addQuestionSetToTree(questionSet); defaultTreeModel.reload(); for (int i = 0; i < getRowCount(); i++) expandRow(i); } private void setNewDefaultTreeModel() { rootNode = new DefaultMutableTreeNode(ROOT_NODE_NAME); defaultTreeModel = new DefaultTreeModel(rootNode); setModel(defaultTreeModel); } public TreePath addQuestionSetToTree(QuestionSet questionSet) { List<String> categorySequenceList = questionSet.getCategoryList(); if (categorySequenceList.size() == 0) return addQuestionSetToDefaultCategory(questionSet); else return addQuestionSetToCategoryHierarchy(questionSet, categorySequenceList); } public boolean isAQuestionSetSelected() { DefaultMutableTreeNode node = (DefaultMutableTreeNode) getLastSelectedPathComponent(); return (node != null && node.isLeaf()); } @SuppressWarnings("unchecked") public QuestionSet getSelectedQuestionSet() { DefaultMutableTreeNode node = (DefaultMutableTreeNode) getLastSelectedPathComponent(); if (node == null || !node.isLeaf()) return null; ToStringWrapper<QuestionSet> toStringWrapper = (ToStringWrapper<QuestionSet>) node.getUserObject(); return toStringWrapper.getWrappedObject(); } private TreePath addQuestionSetToCategoryHierarchy(QuestionSet questionSet, List<String> categorySequenceList) { TreePath path = new TreePath(rootNode); DefaultMutableTreeNode previousNode = rootNode; for (String categoryString : categorySequenceList) { DefaultMutableTreeNode matchingChildNode = searchChildNodes(previousNode, categoryString); if (matchingChildNode != null) { previousNode = matchingChildNode; } else { DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(categoryString); addChildToTreeNode(previousNode, newNode); previousNode = newNode; } path = path.pathByAddingChild(previousNode); } DefaultMutableTreeNode leafNode = new DefaultMutableTreeNode(new ToStringWrapper<QuestionSet>(questionSet, questionSet.getName())); addChildToTreeNode(previousNode, leafNode); path = path.pathByAddingChild(leafNode); return path; } private TreePath addQuestionSetToDefaultCategory(QuestionSet questionSet) { if (defaultNode == null) { defaultNode = new DefaultMutableTreeNode(DEFAULT_CATEGORY_NAME); addChildToTreeNode(rootNode, defaultNode); } DefaultMutableTreeNode leafNode = new DefaultMutableTreeNode(new ToStringWrapper<QuestionSet>(questionSet, questionSet.getName())); addChildToTreeNode(defaultNode, leafNode); TreePath path = new TreePath(new Object[] { rootNode, defaultNode, leafNode }); return path; } private void addChildToTreeNode(DefaultMutableTreeNode parent, DefaultMutableTreeNode child) { int position = -1; for (int pos = 0; pos < parent.getChildCount(); pos++) { DefaultMutableTreeNode otherChild = (DefaultMutableTreeNode) parent.getChildAt(pos); if (otherChild.toString().compareTo(child.toString()) > 0) { position = pos; break; } } if (position >= 0) parent.insert(child, position); else parent.add(child); int[] indexes = new int[] { defaultTreeModel.getIndexOfChild(parent, child) }; defaultTreeModel.nodesWereInserted(parent, indexes); } private DefaultMutableTreeNode searchChildNodes(DefaultMutableTreeNode node, String name) { Enumeration<?> enumeration = node.children(); DefaultMutableTreeNode matchingChild = null; while (enumeration.hasMoreElements()) { DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) enumeration.nextElement(); Object userObject = childNode.getUserObject(); if (userObject instanceof String) { String nodeName = (String) userObject; if (nodeName.equals(name)) { matchingChild = childNode; break; } } } return matchingChild; } // // private final static class NonLeafItalicTreeCellRenderer extends DefaultTreeCellRenderer { // @Override // public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, // boolean leaf, int row, boolean myHasFocus) { // JLabel renderedLabel = (JLabel) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, // myHasFocus); // Font font; // if (leaf) // font = renderedLabel.getFont().deriveFont(Font.PLAIN); // else // font = renderedLabel.getFont().deriveFont(Font.ITALIC); // renderedLabel.setFont(font); // return renderedLabel; // } // } }