/* * CMISBox - Synchronize and share your files with your CMIS Repository * * Copyright (C) 2011 - Andrea Agili * * CMISBox 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. * * CMISBox 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 CMISBox. If not, see <http://www.gnu.org/licenses/>. * */ package com.github.cmisbox.ui; import java.util.ArrayList; import java.util.Map.Entry; import java.util.TreeMap; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeWillExpandListener; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.ExpandVetoException; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeNode; import com.github.cmisbox.remote.CMISRepository; public class LazyTreeModel extends DefaultTreeModel implements TreeWillExpandListener { class LoadNodesWorker extends Thread { private LazyTreeNode parentNode; LoadNodesWorker(LazyTreeNode parent) { this.parentNode = parent; } public void run() { final LazyTreeNode[] treeNodes = LazyTreeModel.this .loadChildren(this.parentNode); if (treeNodes == null) { return; } SwingUtilities.invokeLater(new Runnable() { public void run() { LoadNodesWorker.this.parentNode.setLoaded(true); LazyTreeModel.this.setChildren( LoadNodesWorker.this.parentNode, treeNodes); } }); } } /** * */ private static final long serialVersionUID = 4860297919675952275L; public LazyTreeModel(TreeNode root, JTree tree) { super(root); this.setAsksAllowsChildren(true); tree.addTreeWillExpandListener(this); tree.setModel(this); } protected LazyTreeNode createLoadingNode() { return new LazyTreeNode(null, "Loading..."); } protected LazyTreeNode createReloadingNode() { return new LazyTreeNode(null, "Refreshing..."); } private LazyTreeNode findNode(String id) { return this.findNode(id, (LazyTreeNode) this.getRoot()); } private LazyTreeNode findNode(String id, LazyTreeNode parent) { int count = parent.getChildCount(); for (int i = 0; i < count; i++) { LazyTreeNode node = (LazyTreeNode) parent.getChildAt(i); if (id.equals(node.getId())) { return node; } if (node.isLoaded()) { node = this.findNode(id, node); if (node != null) { return node; } } } return null; } public LazyTreeNode findParent(String id) { LazyTreeNode node = this.findNode(id); if ((node != null) && (node.getParent() != null)) { return (LazyTreeNode) node.getParent(); } return null; } public LazyTreeNode[] loadChildren(LazyTreeNode parentNode) { String id = parentNode.getId(); TreeMap<String, String> res; if (!"ROOT".equals(id)) { res = CMISRepository.getInstance().getChildrenFolders(id); } else { res = CMISRepository.getInstance().getRoots(); } ArrayList<LazyTreeNode> children = new ArrayList<LazyTreeNode>(); for (Entry<String, String> e : res.entrySet()) { children.add(new LazyTreeNode(e.getValue(), e.getKey())); } return children.toArray(new LazyTreeNode[] {}); } public void loadFirstLevel() { this.setLoading((LazyTreeNode) this.getRoot(), false); new LoadNodesWorker((LazyTreeNode) this.getRoot()).start(); } public void reloadNode(String id) { LazyTreeNode node = this.findNode(id); if (node != null) { node.setLoaded(false); this.setLoading(node, true); new LoadNodesWorker(node).start(); } } public void reloadParentNode(String id) { LazyTreeNode node = this.findParent(id); if (node != null) { node.setLoaded(false); this.setLoading(node, true); new LoadNodesWorker(node).start(); } } protected void setChildren(LazyTreeNode parentNode, LazyTreeNode... nodes) { if (nodes == null) { return; } int childCount = parentNode.getChildCount(); if (childCount > 0) { for (int i = 0; i < childCount; i++) { this.removeNodeFromParent((MutableTreeNode) parentNode .getChildAt(0)); } } for (int i = 0; i < nodes.length; i++) { this.insertNodeInto(nodes[i], parentNode, i); } } private void setLoading(final LazyTreeNode parentNode, final boolean reload) { if (SwingUtilities.isEventDispatchThread()) { this.setLoading2(parentNode, reload); } else { try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { LazyTreeModel.this.setLoading2(parentNode, reload); } }); } catch (Exception e) { e.printStackTrace(); } } } private void setLoading2(final LazyTreeNode parentNode, final boolean reload) { if (reload) { this.setChildren(parentNode, this.createReloadingNode()); } else { this.setChildren(parentNode, this.createLoadingNode()); } } public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException { } public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException { LazyTreeNode node = (LazyTreeNode) event.getPath() .getLastPathComponent(); if (node.isLoaded()) { return; } this.setLoading(node, false); new LoadNodesWorker(node).start(); } }