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.awt.BorderLayout;
23  import java.awt.FlowLayout;
24  import java.awt.Font;
25  import java.awt.GridBagLayout;
26  import java.awt.event.ActionEvent;
27  import java.awt.event.ActionListener;
28  import java.util.Enumeration;
29  
30  import javax.swing.AbstractAction;
31  import javax.swing.Action;
32  import javax.swing.JCheckBox;
33  import javax.swing.JLabel;
34  import javax.swing.JPanel;
35  import javax.swing.JScrollPane;
36  import javax.swing.JSplitPane;
37  import javax.swing.event.TreeSelectionEvent;
38  import javax.swing.event.TreeSelectionListener;
39  
40  import org.xnap.XNap;
41  import org.xnap.gui.component.ProgressDialog;
42  import org.xnap.gui.component.XNapButton;
43  import org.xnap.gui.event.DoubleClickListener;
44  import org.xnap.gui.util.GUIHelper;
45  import org.xnap.gui.util.GridBagHelper;
46  import org.xnap.pkg.PackageInfo;
47  import org.xnap.pkg.XNapPackageManager;
48  import org.xnap.plugin.PluginInfo;
49  import org.xnap.plugin.PluginManager;
50  
51  public class PluginPanel extends JPanel
52      implements ActionListener, TreeSelectionListener {
53  
54      //--- Constant(s) ---
55  
56      //--- Data field(s) ---
57  
58      private PluginTree pluginTree;
59      private JCheckBox installCheckBox;
60      private JCheckBox updateCheckBox;
61      private JCheckBox removeCheckBox;
62  	private JLabel authorsLabel;
63      private JLabel descriptionLabel;
64      private JLabel longDescriptionLabel;
65      private JLabel nameLabel;
66  	private JPanel infoPanel;
67      private JLabel statusLabel;
68  	private PluginNode node;
69  	private JPanel buttonsPanel;
70  
71  	private Action acDisable = new DisablePluginAction();
72  	private Action acEnable = new EnablePluginAction();
73  	private Action detailsAction = new DetailsAction();
74  
75      //--- Constructor(s) ---
76  
77      public PluginPanel(boolean showButtons) 
78      {
79  		// plugin list
80  		pluginTree = new PluginTree();
81  		pluginTree.setCellRenderer(new PluginTreeCellRenderer());
82  		pluginTree.addTreeSelectionListener(this);
83  		DoubleClickListener.install(pluginTree, new DoubleClickAction());
84  
85  		// info panel
86  		infoPanel = new JPanel();
87  		infoPanel.setLayout(new GridBagLayout());
88  
89  		nameLabel = GridBagHelper.addLabel(infoPanel, "", true);
90  		nameLabel.setFont(nameLabel.getFont().deriveFont(Font.BOLD));
91  
92  		descriptionLabel = new JLabel();
93  		GridBagHelper.add(infoPanel, descriptionLabel);
94  
95  		longDescriptionLabel = new JLabel();
96  		GridBagHelper.add(infoPanel, longDescriptionLabel);
97  
98  		GridBagHelper.addVerticalSpacer(infoPanel);
99  
100 		// info panel actions
101 		JPanel actionsPanel = new JPanel(new GridBagLayout());
102 		actionsPanel.setBorder
103 			(GUIHelper.createDefaultBorder(XNap.tr("Action")));
104 		GridBagHelper.add(infoPanel, actionsPanel);
105 
106 		installCheckBox = new JCheckBox(XNap.tr("Install"));
107 		installCheckBox.addActionListener(this);
108 		GridBagHelper.add(actionsPanel, installCheckBox);
109 
110 		updateCheckBox = new JCheckBox(XNap.tr("Update"));
111 		updateCheckBox.addActionListener(this);
112 		GridBagHelper.add(actionsPanel, updateCheckBox);
113 
114 		removeCheckBox = new JCheckBox(XNap.tr("Remove"));
115 		// FIX: GridBagHelper.add(actionsPanel, removeCheckBox);
116 
117 		// info panel buttons
118 		buttonsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
119 		GridBagHelper.add(infoPanel, buttonsPanel);
120 
121 		buttonsPanel.add(new XNapButton(detailsAction));
122 		if (showButtons) {
123 			buttonsPanel.add(new XNapButton(acEnable));
124 			buttonsPanel.add(new XNapButton(acDisable));
125 		}
126 
127 		// status
128 		JLabel statusLabel = new JLabel("");
129 
130 		// splitter
131 		JSplitPane jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
132 		jsp.setDividerSize(2);
133 		jsp.setDividerLocation(200);
134 		jsp.setBorder(GUIHelper.createEmptyBorder());
135 		jsp.add(new JScrollPane(pluginTree, 
136 								JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
137 								JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), 
138 				JSplitPane.LEFT);
139 		jsp.add(new JScrollPane(infoPanel), JSplitPane.RIGHT);
140 
141 		// content
142 		setLayout(new BorderLayout());
143 		add(jsp, BorderLayout.CENTER);
144 		add(statusLabel, BorderLayout.SOUTH);
145 
146 		// initialize
147 		valueChanged();
148     }
149 
150     //--- Method(s) ---
151 
152 	/***
153 	 * Invoked when one of the action buttons was selected.
154 	 */
155 	public void actionPerformed(ActionEvent event) 
156 	{
157 		if (installCheckBox.isSelected() || updateCheckBox.isSelected()) {
158 			node.setAction("install");
159 		}
160 		else {
161 			node.setAction("purge");
162 		}
163 	}
164 
165 	
166 	/***
167 	 * Sets the selected actions for all packages.
168 	 */
169 	public void apply()
170 	{
171 		Enumeration it = pluginTree.getRoot().depthFirstEnumeration();
172 		while (it.hasMoreElements()) {
173 			Object o = it.nextElement();
174 			if (o instanceof PluginNode) {
175 				PluginNode node = (PluginNode)o;
176 				node.getPackageInfo().setAction(node.getAction());
177 			}
178 		}
179 	}
180 
181 	public JPanel getButtonPanel()
182 	{
183 		return buttonsPanel;
184 	}
185 
186 	public PluginTree getPluginTree()
187 	{
188 		return pluginTree;
189 	}
190 	
191 	/***
192 	 * Returns the currently selected plugin or null if no plugin is selected. 
193 	 */
194 	public PluginInfo getSelectedPlugin()
195 	{
196 		PluginNode node = pluginTree.getSelectedNode();
197 		return (node != null) ? node.getPluginInfo() : null;
198 	}
199 	
200 	/***
201      * Updates the info panel.
202      */
203 	public void setNode(PluginNode node)
204     {
205 		this.node = node;
206 
207 		PackageInfo info = node.getPackageInfo();
208 		nameLabel.setText(info.getName() + " " + info.getVersion());
209 		descriptionLabel.setText(info.getDescription());
210 		longDescriptionLabel.setText(GUIHelper.tt(info.getLongDescription()));
211 
212 		installCheckBox.setEnabled(!info.isInstalled());
213 		// node.isUpdateAvailable() implies info.isInstalled() 
214 		updateCheckBox.setEnabled(node.isUpdateAvailable()); 
215 
216 		installCheckBox.setSelected(!info.isInstalled() 
217 									&& "install".equals(node.getAction()));
218 		updateCheckBox.setSelected(node.isUpdateAvailable()
219 								   && "install".equals(node.getAction()));
220 
221 		PluginInfo pluginInfo = node.getPluginInfo();
222 		if (pluginInfo != null && pluginInfo.isPlugin()) {
223 			acEnable.setEnabled(!pluginInfo.isEnabled());
224 			acDisable.setEnabled(pluginInfo.isEnabled());
225 		}
226 		else {
227 			acEnable.setEnabled(false);
228 			acDisable.setEnabled(false);
229 		}
230     }
231 
232 	public void setStatus(String status)
233 	{
234 		statusLabel.setText(status);
235 	}
236 
237 	/***
238 	 * Updates the plugin tree.
239 	 */
240 	public void update()
241 	{
242 		PluginManager.getInstance().updateFromPackageManager();
243 		pluginTree.update();
244 	}			
245 
246 	/***
247 	 * Updates the list of packages and invokes {@link #update()}.
248 	 *
249 	 * @see XNapPackageManager.update(ProgressMonitor)
250 	 */
251 	public void updatePackageManager()
252 	{
253 		ProgressDialog dialog
254 			= new ProgressDialog(XNap.tr("Updating packages"));
255 		XNapPackageManager.getInstance().update(dialog);
256 		dialog.show(this);
257 
258 		update();
259 		XNapPackageManager.getInstance().write();
260 	}
261 
262     /***
263      * Updates the plugin info panel.
264      */
265     public void valueChanged(TreeSelectionEvent e)
266     {
267 		PluginNode node = pluginTree.getSelectedNode();
268 		if (node != null) {
269 			setNode(node);
270 		}
271 		infoPanel.setVisible(node != null);
272     }
273 
274 	public void valueChanged()
275 	{
276 		valueChanged(null);
277 	}
278 
279     // --- Inner Class(es) ---
280 
281     private class DoubleClickAction implements ActionListener {
282     
283         public void actionPerformed(ActionEvent event) 
284 		{
285 			if (acEnable.isEnabled()) {
286 				acEnable.actionPerformed(event);
287 			}
288 			else if (acDisable.isEnabled()) {
289 				acDisable.actionPerformed(event);
290 			}
291 		}
292 
293 	}
294 
295     private class DetailsAction extends AbstractAction
296     {
297     
298 		public DetailsAction()
299 		{	
300 			putValue(Action.NAME, XNap.tr("Details"));
301 			putValue(Action.SHORT_DESCRIPTION, 
302 					 XNap.tr("Shows a dialog with detailed information about the plugin."));
303 		}
304 	
305 		//--- Method(s) ---
306 	
307         public void actionPerformed(ActionEvent event) 
308 		{
309 			PluginInfo info = getSelectedPlugin();
310 			if (info != null) {
311 				PluginDetailsDialog dialog = new PluginDetailsDialog(info);
312 				dialog.setLocationRelativeTo(PluginPanel.this);
313 				dialog.setVisible(true);
314 			}
315 		}
316 	}
317 
318     private class EnablePluginAction extends AbstractAction
319     {
320     
321 		public EnablePluginAction()
322 		{	
323 			putValue(Action.NAME, XNap.tr("Enable"));
324 			putValue(Action.SHORT_DESCRIPTION, 
325 					 XNap.tr("Enables the plugin."));
326 		}
327 	
328 		//--- Method(s) ---
329 	
330         public void actionPerformed(ActionEvent event) 
331 		{
332 			PluginInfo info = getSelectedPlugin();
333 			if (info != null) {
334 				if (PluginHelper.enablePlugin(PluginPanel.this, info)) {
335 					valueChanged();
336 					pluginTree.selectedNodeChanged();
337 				}
338 			}
339 		}
340 	}
341 
342     private class DisablePluginAction extends AbstractAction
343     {
344     
345 		public DisablePluginAction()
346 		{	
347 			putValue(Action.NAME, XNap.tr("Disable"));
348 			putValue(Action.SHORT_DESCRIPTION, 
349 					 XNap.tr("Disables the plugin."));
350 		}
351 		
352 		//--- Method(s) ---
353 		
354         public void actionPerformed(ActionEvent event) 
355 		{
356 			PluginInfo info = getSelectedPlugin();
357 			if (info != null) {
358 				if (PluginHelper.disablePlugin(PluginPanel.this, info)) {
359 					valueChanged();
360 					pluginTree.selectedNodeChanged();
361 				}
362 			}
363 		}
364 
365 	}
366 	
367 }