View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program is free software; you can redistribute it and/or modify
7    *  it under the terms of the GNU General Public License as published by
8    *  the Free Software Foundation.
9    *
10   *  This program is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   *  GNU General Public License for more details.
14   *
15   *  You should have received a copy of the GNU General Public License
16   *  along with this program; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.xnap.gui.plugin;
21  
22  import java.util.Enumeration;
23  import java.util.Hashtable;
24  import java.util.Iterator;
25  import java.util.LinkedList;
26  import java.util.StringTokenizer;
27  
28  import javax.swing.JTree;
29  import javax.swing.tree.DefaultMutableTreeNode;
30  import javax.swing.tree.DefaultTreeModel;
31  import javax.swing.tree.TreeNode;
32  import javax.swing.tree.TreePath;
33  
34  import org.xnap.XNap;
35  import org.xnap.gui.util.IconHelper;
36  import org.xnap.pkg.DefaultPackageSection;
37  import org.xnap.pkg.PackageInfo;
38  import org.xnap.pkg.PackageSection;
39  import org.xnap.pkg.XNapPackageManager;
40  import org.xnap.util.StringHelper;
41  
42  public class PluginTree extends JTree {
43      
44      //--- Data field(s) ---
45  
46  	private DefaultMutableTreeNode root;
47  	private DefaultTreeModel model;
48  	private Hashtable nodeBySectionName = new Hashtable();
49  	private Hashtable sectionByName = new Hashtable();
50  	
51      //--- Constructor(s) ---
52  	
53      public PluginTree()
54      {
55  		root = new DefaultMutableTreeNode(XNap.tr("Plugins"));
56  		model = new DefaultTreeModel(root);
57  
58  		setModel(model);
59  		setRootVisible(false);
60  
61  		mapSection("net", XNap.tr("Network"), "network.png");
62  		mapSection("chat", XNap.tr("Chat"), "mail_generic2.png");
63  		mapSection("laf", XNap.tr("Look and Feel"), "list.png");
64  		mapSection("lib", XNap.tr("Library"));
65  	}
66  	
67  	//--- Method(s) ---
68  	
69  	public void createPackageNode(DefaultMutableTreeNode parent,
70  								  PackageInfo info)
71  	{
72  		String section = "/" + info.getSection() + "/" + info.getName();
73  		DefaultMutableTreeNode node 
74  			= (DefaultMutableTreeNode)nodeBySectionName.get(section);
75  		if (node == null) {
76  			node = new PluginNode(info);
77  			nodeBySectionName.put(section, node);
78  			parent.add(node);
79  		}
80  		else if (node instanceof PluginNode) {
81  			PluginNode n = (PluginNode)node;
82  			n.setMarked(false);
83  			// always set the highest available version
84  			// info must be a higher version, since the packages
85  			// are sorted by lower version first
86  			n.setPackageInfo(info);
87  			// default to install for updated packages
88  			if (n.isUpdateAvailable() || n.getPluginInfo() != null) {
89  				n.setAction(PackageInfo.ACTION_INSTALL);
90  			}
91  		}
92  	}
93  
94  	/***
95  	 * Creates a section node and returns it.
96  	 */
97  	public DefaultMutableTreeNode createSectionNodes(String sectionName)
98  	{
99  		DefaultMutableTreeNode parent = root;
100 
101 		StringBuffer totalSection = new StringBuffer(sectionName.length());
102 		StringTokenizer t = new StringTokenizer(sectionName, "/");
103 		while (t.hasMoreTokens()) {
104 			totalSection.append("/");
105 			totalSection.append(t.nextToken());
106 
107 			DefaultMutableTreeNode node
108 				= getNodeBySection(parent, totalSection.toString());
109 			parent = node;
110 		}
111 		return parent;
112 	}
113 
114 	private DefaultMutableTreeNode getNodeBySection
115 		(DefaultMutableTreeNode parent, String section)
116 	{
117 		DefaultMutableTreeNode node 
118 			= (DefaultMutableTreeNode)nodeBySectionName.get(section);
119 		if (node == null) {
120 			String s = StringHelper.lastToken(section, "/");
121 			PackageSection ps = (PackageSection)sectionByName.get(s);
122 			if (ps == null) {
123 				ps = new DefaultPackageSection(StringHelper.toFirstUpper(s),
124 											   null);
125 				sectionByName.put(s, ps);
126 			}
127 			node = new DefaultMutableTreeNode(ps);
128 			nodeBySectionName.put(section, node);
129 			parent.add(node);
130 		}
131 		return node;
132 	}
133 
134 	public DefaultMutableTreeNode getRoot()
135 	{
136 		return root;
137 	}
138 
139 	public PluginNode getSelectedNode()
140 	{
141 		if (getSelectionPath() != null) {
142 			DefaultMutableTreeNode node = (DefaultMutableTreeNode)
143 				getSelectionPath().getLastPathComponent();
144 	
145 			if (node instanceof PluginNode) {
146 				return (PluginNode)node;
147 			}
148 		}
149 		return null;
150 	}
151 
152 	public PackageSection mapSection(String sectionName, String name,
153 									 String iconFilename)
154 	{
155 		PackageSection section = new DefaultPackageSection
156 			(name, (iconFilename != null) 
157 			 ? IconHelper.getIcon(iconFilename, 16, false)
158 			 : null);
159 		sectionByName.put(sectionName, section);
160 		return section;
161 	}
162 
163 	public PackageSection mapSection(String sectionName, String name)
164 	{
165 		return mapSection(sectionName, name, null);
166 	}
167 
168 
169 	public void pathChanged(TreePath path)
170 	{
171 		model.nodeChanged((TreeNode)path.getLastPathComponent());
172 	}
173 
174 	public void reload()
175 	{
176 		model.reload();
177 
178 		// expand important nodes
179 		expandRow(0);
180 		expandNodes(root.getChildAt(0));
181 		expandNodes(root.getChildAt(1));
182 	}
183 
184 	public void remove(PluginNode node)
185 	{
186 		PackageInfo info = node.getPackageInfo();
187 		String section = "/" + info.getSection() + "/" + info.getName();
188 
189 		((DefaultMutableTreeNode)node.getParent()).remove(node);
190 		nodeBySectionName.remove(section);
191 	}
192 
193 	/***
194 	 * Rebuilds the tree from the packages contained in XNapPackageManager.
195 	 */
196 	public void update()
197 	{
198 		// create default section
199 		createSectionNodes("plugin");
200 		createSectionNodes("base");
201 
202 		// remove packages that are not available anymore
203 		Enumeration it = root.depthFirstEnumeration();
204 		while (it.hasMoreElements()) {
205 			Object o = it.nextElement();
206 			if (o instanceof PluginNode) {
207 				PluginNode node = (PluginNode)o;
208 				node.setMarked(true);
209 			}
210 		}
211 
212 		// add all packages
213 		forg> (Iterator it2 = XNapPackageManager.getInstance().packages();
214 			 it2.hasNext();) {
215 
216 			PackageInfo info = (PackageInfo)it2.next();
217 			if (info.isPlugin() || info.isBase()) {
218 				DefaultMutableTreeNode parent
219 					= createSectionNodes(info.getSection());
220 				createPackageNode(parent, info);
221 			}
222 		}
223 
224 		// remove packages that are not available anymore
225 		LinkedList toRemove = new LinkedList();
226 		it = root.depthFirstEnumeration();
227 		while (it.hasMoreElements()) {
228 			Object o = it.nextElement();
229 			if (o instanceof PluginNode) {
230 				PluginNode node = (PluginNode)o;
231 				if (node.isMarked()) {
232 					toRemove.add(node);
233 				}
234 			}
235 		}
236 
237 		for (Iterator it2 = toRemove.iterator(); it2.hasNext();) {
238 			remove((PluginNode)it2.next());
239 		}
240 
241 		// update tree
242 		reload();
243 	}
244 
245 
246 	public void selectedNodeChanged()
247 	{
248 		model.nodeChanged
249 			((TreeNode)getSelectionPath().getLastPathComponent());
250 	}
251 
252 	private void expandNodes(TreeNode child)
253 	{
254 		expandPath(new TreePath(new Object[] { root, child }));
255 		for (int i = child.getChildCount() - 1; i >= 0; i--) {
256 			Object[] path 
257 				= new Object[] { root, child, child.getChildAt(i) };
258 			expandPath(new TreePath(path));
259 		}
260 	}
261 
262 }