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  package org.xnap.gui.pkg;
20  
21  import java.awt.BorderLayout;
22  import java.awt.Component;
23  import java.awt.FlowLayout;
24  import java.awt.event.ActionEvent;
25  import java.awt.event.WindowAdapter;
26  import java.awt.event.WindowEvent;
27  
28  import javax.swing.AbstractAction;
29  import javax.swing.Action;
30  import javax.swing.JLabel;
31  import javax.swing.JPanel;
32  import javax.swing.JScrollPane;
33  import javax.swing.JSplitPane;
34  import javax.swing.SwingConstants;
35  import javax.swing.border.EmptyBorder;
36  import javax.swing.event.TreeSelectionEvent;
37  import javax.swing.event.TreeSelectionListener;
38  
39  import org.apache.log4j.Logger;
40  import org.xnap.XNap;
41  import org.xnap.gui.Dialogs;
42  import org.xnap.gui.StatusBar;
43  import org.xnap.gui.component.DefaultDialog;
44  import org.xnap.gui.component.ProgressDialog;
45  import org.xnap.gui.component.XNapButton;
46  import org.xnap.pkg.DefaultDependencyParser;
47  import org.xnap.pkg.DefaultResolver;
48  import org.xnap.pkg.DependencyGraph;
49  import org.xnap.pkg.PackageInfo;
50  import org.xnap.pkg.ParseException;
51  import org.xnap.pkg.UnsatisfiedDependenciesException;
52  import org.xnap.pkg.XNapPackageManager;
53  
54  public class PackageDialog extends DefaultDialog 
55      implements TreeSelectionListener {
56  
57      //--- Constant(s) ---
58  
59      //--- Data field(s) ---
60  
61      private static Logger logger = Logger.getLogger(PackageDialog.class);
62      private static PackageDialog me = null;
63  
64      private JLabel jlStatus;
65      private PackageInfoTree jtPackages;
66  	private PackageInfoPanel jpInfo;
67  	private boolean canClose = true;
68  
69      private Action acInstall = new InstallAction();
70      private Action acRemove = new RemoveAction();
71      private Action acShowDepends = new ShowDependsAction();
72      private Action acUpdateList = new UpdateListAction();
73  
74      //--- Constructor(s) ---
75  
76      private PackageDialog() 
77      {
78  		super(BUTTON_CLOSE);
79  
80  		StatusBar.setText(XNap.tr("Reading list of packages") + "...");
81  		XNapPackageManager.getInstance().initialize();
82  		StatusBar.setText("");
83  
84  		initialize();
85  
86  		pack();
87  		setSize(600, 500);
88  
89  		jtPackages.updatePackages
90  			(XNapPackageManager.getInstance().packages());
91  		valueChanged();
92      }
93  
94      //--- Method(s) ---
95  
96  	private void initialize()
97      {
98          setTitle(XNap.tr("Manage Packages"));
99  
100 		// info
101 		JPanel jpIconInfo = new JPanel(new FlowLayout(FlowLayout.LEFT));
102 		jpIconInfo.add(new JLabel(XNap.tr("Available"),
103 								  PackageInfoCellRenderer.ICON_NOT_INSTALLED,
104 								  SwingConstants.LEFT));
105 		jpIconInfo.add(new JLabel(XNap.tr("Installed"),
106 								  PackageInfoCellRenderer.ICON_INSTALLED,
107 								  SwingConstants.LEFT));
108 		jpIconInfo.add
109 			(new JLabel(XNap.tr("Update Available"), 
110 						PackageInfoCellRenderer.ICON_UPDATE_AVAILABLE,
111 						SwingConstants.LEFT));
112 		jpIconInfo.add(new JLabel(XNap.tr("New"),
113 								  PackageInfoCellRenderer.ICON_NEW,
114 								  SwingConstants.LEFT));
115 
116 		// status
117 		jlStatus = new JLabel(" ");
118 		jlStatus.setBorder(new EmptyBorder(5, 5, 5, 5));
119 
120 		// package list
121 		jtPackages = new PackageInfoTree();
122 		jtPackages.setCellRenderer(new PackageInfoCellRenderer());
123 		jtPackages.addTreeSelectionListener(this);
124 
125 		// info panel
126 		jpInfo = new PackageInfoPanel();
127 
128 		jpInfo.getButtonPanel().add(new XNapButton(acInstall));
129 		jpInfo.getButtonPanel().add(new XNapButton(acRemove));
130 		jpInfo.getButtonPanel().add(new XNapButton(acShowDepends));
131 
132 
133 		JSplitPane jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
134 		jsp.setDividerSize(2);
135 		jsp.setDividerLocation(180);
136 		jsp.add(new JScrollPane(jtPackages), JSplitPane.LEFT);
137 		jsp.add(new JScrollPane(jpInfo), JSplitPane.RIGHT);
138 
139 		getMainPanel().setLayout(new BorderLayout());
140 		getMainPanel().add(jpIconInfo, BorderLayout.NORTH);
141 		getMainPanel().add(jsp, BorderLayout.CENTER);
142 		getMainPanel().add(jlStatus, BorderLayout.SOUTH);
143 
144 		getButtonPanel().add(new XNapButton(acUpdateList), 1);
145     }
146 
147     public static void showDialog(Component c)
148     {
149 		if (me == null) {
150 			me = new PackageDialog();
151 		}
152 		me.show(c);
153     }
154 
155 	public void close()
156 	{
157 		if (canClose) {
158 			dispose();
159 			me = null;
160 		}
161 	}
162 
163     private void setStatus(String newValue)
164     {
165 		jlStatus.setText(newValue);
166 		jlStatus.setToolTipText(newValue);
167     }
168 
169     /***
170      * Updates the package info panel.
171      */
172     public void valueChanged(TreeSelectionEvent e)
173     {
174 		PackageInfo info = jtPackages.getSelectedInfo();
175 		if (info != null) {
176 			if (!canClose) {
177 				return;
178 			}
179 
180 			jpInfo.setInfo(info);
181 			acInstall.setEnabled(!info.isInstalled());
182 			acRemove.setEnabled(false);
183 		}
184 
185 		jpInfo.setVisible(info != null);
186     }
187 
188 	public void valueChanged()
189 	{
190 		valueChanged(null);
191 	}
192 
193 	private DependencyGraph buildGraph()
194 	{
195 		DependencyGraph graph
196 			= new DependencyGraph(XNapPackageManager.getInstance());
197 		graph.add(jtPackages.getSelectedInfo());
198 
199 		try {
200 			graph.buildDependencies(new DefaultDependencyParser());
201 		}
202 		catch (ParseException e) {
203 			Dialogs.error(PackageDialog.this, e.getLocalizedMessage());
204 			return null;
205 		}
206 
207 		return graph;
208 	}
209 
210 	/***
211 	 * Enables or disables all widgets.
212 	 */
213 	public void setDialogEnabled(boolean enabled)
214 	{
215 		acInstall.setEnabled(enabled);
216 		acRemove.setEnabled(enabled);
217 		
218 		canClose = enabled;
219 		if (enabled) {
220 			valueChanged();
221 		}
222 	}
223 
224     // --- Inner Class(es) ---
225 
226     private class InstallAction extends AbstractAction {
227 
228         public InstallAction() 
229 		{
230             putValue(Action.NAME, XNap.tr("Install") + "...");
231             putValue(Action.SHORT_DESCRIPTION, 
232 					 XNap.tr("Downloads the selected package."));
233         }
234 
235         public void actionPerformed(ActionEvent event) 
236 		{
237 			DependencyGraph graph = buildGraph();
238 			if (graph != null) {
239 				PackageInfo[] packages;
240 				try {
241 					DefaultResolver r = new DefaultResolver(graph, false);
242 					r.resolve();
243 					packages = r.getRequiredUninstalled();
244 				}
245 				catch (UnsatisfiedDependenciesException e) {
246 					String message
247 						= XNap.tr("Unsatisfied dependency: Missing {0}.", 
248 								  e.getLocalizedMessage());
249 					Dialogs.error(PackageDialog.this, message);
250 					return;
251 				}
252 				
253 				PackageInstallerDialog d 
254 					PackageInstallerDialog(packages)/package-summary.html">= new PackageInstallerDialog(packages);
255 				d.addWindowListener(new DisposeListener());
256 				d.show(PackageDialog.this);
257 
258 				setDialogEnabled(false);
259 		}
260         }
261 
262 		private class DisposeListener extends WindowAdapter
263 		{
264 
265 			public void windowClosed(WindowEvent event) 
266 			{
267 				// update
268 				jtPackages.reload();
269 				valueChanged(null);
270 
271 				XNapPackageManager.getInstance().write();
272 
273 				setDialogEnabled(true);
274 			}
275 		}
276 
277     }
278 
279     private class RemoveAction extends AbstractAction {
280 
281         public RemoveAction() 
282 		{
283             putValue(Action.NAME, XNap.tr("Remove") + "...");
284             putValue(Action.SHORT_DESCRIPTION, 
285 					 XNap.tr("Removes the package."));
286         }
287 
288         public void actionPerformed(ActionEvent event) 
289 		{
290 		}
291     }
292 
293     private class ShowDependsAction extends AbstractAction {
294 
295         public ShowDependsAction() 
296 		{
297             putValue(Action.NAME, XNap.tr("Dependencies") + "...");
298             putValue(Action.SHORT_DESCRIPTION, 
299 					 XNap.tr("Shows the dependency graph."));
300         }
301 
302         public void actionPerformed(ActionEvent event) 
303 		{
304 			DependencyGraph graph = buildGraph();
305 			if (graph != null) {
306 				DependencyGraphDialog d = new DependencyGraphDialog(graph);
307 				d.setModal(true);
308 				d.show(PackageDialog.this);
309 			}
310 		}
311     }
312 
313     private class UpdateListAction extends AbstractAction {
314 
315         public UpdateListAction() 
316 		{
317             putValue(Action.NAME, XNap.tr("Update List"));
318             putValue(Action.SHORT_DESCRIPTION, 
319 					 XNap.tr("Updates the list packages from the internet."));
320         }
321 
322         public void actionPerformed(ActionEvent event) 
323 		{
324 			setStatus(XNap.tr("Getting list of packages") + "...");
325 
326 			ProgressDialog dialog
327 				= new ProgressDialog(XNap.tr("Updating packages"));
328 			XNapPackageManager.getInstance().update(dialog);
329 			dialog.show(PackageDialog.this);
330 
331 			int count = XNapPackageManager.getInstance().getPackageCount();
332 			setStatus(XNap.tr("{0} packages available", new Integer(count)));
333 
334 			jtPackages.updatePackages
335 				(XNapPackageManager.getInstance().packages());
336 		}
337     }
338 	
339 }