PageRenderTime 144ms CodeModel.GetById 84ms app.highlight 47ms RepoModel.GetById 1ms app.codeStats 1ms

/jEdit/tags/jedit-4-2-pre14/org/gjt/sp/jedit/pluginmgr/ManagePanel.java

#
Java | 678 lines | 526 code | 84 blank | 68 comment | 71 complexity | a6088a5f23f6d8c872d49ec1150b2199 MD5 | raw file
  1/*
  2 * ManagePanel.java - Manages plugins
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2002 Kris Kopicki
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * as published by the Free Software Foundation; either version 2
 11 * of the License, or any later version.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 21 */
 22
 23package org.gjt.sp.jedit.pluginmgr;
 24
 25//{{{ Imports
 26import javax.swing.border.*;
 27import javax.swing.event.*;
 28import javax.swing.table.*;
 29import javax.swing.*;
 30import java.awt.event.*;
 31import java.awt.BorderLayout;
 32import java.awt.Color;
 33import java.awt.Component;
 34import java.awt.Dimension;
 35import java.io.File;
 36import java.net.URL;
 37import java.util.*;
 38import org.gjt.sp.jedit.gui.*;
 39import org.gjt.sp.jedit.help.*;
 40import org.gjt.sp.jedit.*;
 41import org.gjt.sp.util.Log;
 42//}}}
 43
 44public class ManagePanel extends JPanel
 45{
 46	//{{{ ManagePanel constructor
 47	public ManagePanel(PluginManager window)
 48	{
 49		super(new BorderLayout(12,12));
 50
 51		this.window = window;
 52
 53		setBorder(new EmptyBorder(12,12,12,12));
 54
 55		Box topBox = new Box(BoxLayout.X_AXIS);
 56		topBox.add(hideLibraries = new HideLibrariesButton());
 57		add(BorderLayout.NORTH,topBox);
 58
 59		/* Create the plugin table */
 60		table = new JTable(pluginModel = new PluginTableModel());
 61		table.setShowGrid(false);
 62		table.setIntercellSpacing(new Dimension(0,0));
 63		table.setRowHeight(table.getRowHeight() + 2);
 64		table.setPreferredScrollableViewportSize(new Dimension(500,300));
 65		table.setRequestFocusEnabled(false);
 66		table.setDefaultRenderer(Object.class, new TextRenderer(
 67			(DefaultTableCellRenderer)table.getDefaultRenderer(Object.class)));
 68
 69		TableColumn col1 = table.getColumnModel().getColumn(0);
 70		TableColumn col2 = table.getColumnModel().getColumn(1);
 71		TableColumn col3 = table.getColumnModel().getColumn(2);
 72		TableColumn col4 = table.getColumnModel().getColumn(3);
 73
 74		col1.setPreferredWidth(30);
 75		col1.setMinWidth(30);
 76		col1.setMaxWidth(30);
 77		col1.setResizable(false);
 78
 79		col2.setPreferredWidth(300);
 80		col3.setPreferredWidth(100);
 81		col4.setPreferredWidth(100);
 82
 83		JTableHeader header = table.getTableHeader();
 84		header.setReorderingAllowed(false);
 85		header.addMouseListener(new HeaderMouseHandler());
 86
 87		JScrollPane scrollpane = new JScrollPane(table);
 88		scrollpane.getViewport().setBackground(table.getBackground());
 89		add(BorderLayout.CENTER,scrollpane);
 90
 91		/* Create button panel */
 92		Box buttons = new Box(BoxLayout.X_AXIS);
 93
 94		buttons.add(new RemoveButton());
 95		buttons.add(Box.createGlue());
 96		buttons.add(new HelpButton());
 97
 98		add(BorderLayout.SOUTH,buttons);
 99	} //}}}
100
101	//{{{ update() method
102	public void update()
103	{
104		pluginModel.update();
105	} //}}}
106
107	//{{{ Private members
108	private JCheckBox hideLibraries;
109	private JTable table;
110	private PluginTableModel pluginModel;
111	private PluginManager window;
112
113	//{{{ showListConfirm() method
114	private int showListConfirm(String name, String[] args,
115		Vector listModel)
116	{
117		JList list = new JList(listModel);
118		list.setVisibleRowCount(8);
119
120		Object[] message = {
121			jEdit.getProperty(name + ".message",args),
122			new JScrollPane(list)
123		};
124
125		return JOptionPane.showConfirmDialog(window,
126			message,
127			jEdit.getProperty(name + ".title"),
128			JOptionPane.YES_NO_OPTION,
129			JOptionPane.QUESTION_MESSAGE);
130	} //}}}
131
132	//}}}
133
134	//{{{ Inner classes
135
136	//{{{ Entry class
137	class Entry
138	{
139		static final String ERROR = "error";
140		static final String LOADED = "loaded";
141		static final String NOT_LOADED = "not-loaded";
142
143		String status;
144		String jar;
145
146		String clazz, name, version, author, docs;
147		List jars;
148
149		Entry(String jar)
150		{
151			jars = new LinkedList();
152			this.jar = jar;
153			jars.add(this.jar);
154			status = NOT_LOADED;
155		}
156
157		Entry(PluginJAR jar)
158		{
159			jars = new LinkedList();
160			this.jar = jar.getPath();
161			jars.add(this.jar);
162
163			EditPlugin plugin = jar.getPlugin();
164			if(plugin != null)
165			{
166				status = (plugin instanceof EditPlugin.Broken
167					? ERROR : LOADED);
168				clazz = plugin.getClassName();
169				name = jEdit.getProperty("plugin."+clazz+".name");
170				version = jEdit.getProperty("plugin."+clazz+".version");
171				author = jEdit.getProperty("plugin."+clazz+".author");
172				docs = jEdit.getProperty("plugin."+clazz+".docs");
173
174				String jarsProp = jEdit.getProperty("plugin."+clazz+".jars");
175
176				if(jarsProp != null)
177				{
178					String directory = MiscUtilities.getParentOfPath(this.jar);
179
180					StringTokenizer st = new StringTokenizer(jarsProp);
181					while(st.hasMoreElements())
182					{
183						jars.add(MiscUtilities.constructPath(
184							directory,st.nextToken()));
185					}
186				}
187			}
188			else
189				status = LOADED;
190		}
191	} //}}}
192
193	//{{{ PluginTableModel class
194	class PluginTableModel extends AbstractTableModel
195	{
196		private List entries;
197		private int sortType = EntryCompare.NAME;
198
199		//{{{ Constructor
200		public PluginTableModel()
201		{
202			entries = new ArrayList();
203			update();
204		} //}}}
205
206		//{{{ getColumnCount() method
207		public int getColumnCount()
208		{
209			return 4;
210		} //}}}
211
212		//{{{ getColumnClass() method
213		public Class getColumnClass(int columnIndex)
214		{
215			switch (columnIndex)
216			{
217				case 0: return Boolean.class;
218				default: return Object.class;
219			}
220		} //}}}
221
222		//{{{ getColumnName() method
223		public String getColumnName(int column)
224		{
225			switch (column)
226			{
227				case 0:
228					return " ";
229				case 1:
230					return jEdit.getProperty("manage-plugins.info.name");
231				case 2:
232					return jEdit.getProperty("manage-plugins.info.version");
233				case 3:
234					return jEdit.getProperty("manage-plugins.info.status");
235				default:
236					throw new Error("Column out of range");
237			}
238		} //}}}
239
240		//{{{ getEntry() method
241		public Entry getEntry(int rowIndex)
242		{
243			return (Entry)entries.get(rowIndex);
244		} //}}}
245
246		//{{{ getRowCount() method
247		public int getRowCount()
248		{
249			return entries.size();
250		} //}}}
251
252		//{{{ getValueAt() method
253		public Object getValueAt(int rowIndex,int columnIndex)
254		{
255			Entry entry = (Entry)entries.get(rowIndex);
256			switch (columnIndex)
257			{
258				case 0:
259					return Boolean.valueOf(
260						!entry.status.equals(
261						Entry.NOT_LOADED));
262				case 1:
263					if(entry.name == null)
264					{
265						return MiscUtilities.getFileName(entry.jar);
266					}
267					else
268						return entry.name;
269				case 2:
270					return entry.version;
271				case 3:
272					return jEdit.getProperty("plugin-manager.status."
273						+ entry.status);
274				default:
275					throw new Error("Column out of range");
276			}
277		} //}}}
278
279		//{{{ isCellEditable() method
280		public boolean isCellEditable(int rowIndex, int columnIndex)
281		{
282			return columnIndex == 0;
283		} //}}}
284
285		//{{{ setValueAt() method
286		public void setValueAt(Object value, int rowIndex,
287			int columnIndex)
288		{
289			Entry entry = (Entry)entries.get(rowIndex);
290			if(columnIndex == 0)
291			{
292				PluginJAR jar = jEdit.getPluginJAR(entry.jar);
293				if(jar == null)
294				{
295					if(value.equals(Boolean.FALSE))
296						return;
297
298					loadPluginJAR(entry.jar);
299				}
300				else
301				{
302					if(value.equals(Boolean.TRUE))
303						return;
304
305					unloadPluginJARWithDialog(jar);
306				}
307			}
308
309			update();
310		} //}}}
311
312		//{{{ setSortType() method
313		public void setSortType(int type)
314		{
315			sortType = type;
316			sort(type);
317		} //}}}
318
319		//{{{ sort() method
320		public void sort(int type)
321		{
322			Collections.sort(entries,new EntryCompare(type));
323			fireTableChanged(new TableModelEvent(this));
324		}
325		//}}}
326
327		//{{{ update() method
328		public void update()
329		{
330			entries.clear();
331
332			String systemJarDir = MiscUtilities.constructPath(
333				jEdit.getJEditHome(),"jars");
334			String userJarDir;
335			if(jEdit.getSettingsDirectory() == null)
336				userJarDir = null;
337			else
338			{
339				userJarDir = MiscUtilities.constructPath(
340					jEdit.getSettingsDirectory(),"jars");
341			}
342
343			PluginJAR[] plugins = jEdit.getPluginJARs();
344			for(int i = 0; i < plugins.length; i++)
345			{
346				String path = plugins[i].getPath();
347				if(path.startsWith(systemJarDir)
348					|| (userJarDir != null
349					&& path.startsWith(userJarDir)))
350				{
351					Entry e = new Entry(plugins[i]);
352					if(!hideLibraries.isSelected()
353						|| e.clazz != null)
354					{
355						entries.add(e);
356					}
357				}
358			}
359
360			String[] newPlugins = jEdit.getNotLoadedPluginJARs();
361			for(int i = 0; i < newPlugins.length; i++)
362			{
363				Entry e = new Entry(newPlugins[i]);
364				if(!hideLibraries.isSelected()
365					|| e.clazz != null)
366				{
367					entries.add(e);
368				}
369			}
370
371			sort(sortType);
372		} //}}}
373
374		//{{{ loadExtraJARsIfNecessary() method
375		/**
376		 * This should go into the core...
377		 */
378		private void loadPluginJAR(String jarPath)
379		{
380			jEdit.addPluginJAR(jarPath);
381			PluginJAR jar = jEdit.getPluginJAR(jarPath);
382			if(jar == null || jar.getPlugin() == null)
383				return;
384
385			String jars = jEdit.getProperty("plugin."
386				+ jar.getPlugin().getClassName() + ".jars");
387
388			if(jars != null)
389			{
390				String dir = MiscUtilities.getParentOfPath(
391					jarPath);
392
393				StringTokenizer st = new StringTokenizer(jars);
394				while(st.hasMoreTokens())
395				{
396					String _jarPath
397						= MiscUtilities.constructPath(
398						dir,st.nextToken());
399					PluginJAR _jar = jEdit.getPluginJAR(
400						_jarPath);
401					if(_jar == null)
402					{
403						jEdit.addPluginJAR(_jarPath);
404					}
405				}
406			}
407
408			jar.checkDependencies();
409			jar.activatePluginIfNecessary();
410		} //}}}
411
412		//{{{ unloadPluginJARWithDialog() method
413		private void unloadPluginJARWithDialog(PluginJAR jar)
414		{
415			String[] dependents = jar.getDependentPlugins();
416			if(dependents.length == 0)
417				unloadPluginJAR(jar);
418			else
419			{
420				Vector listModel = new Vector();
421				transitiveClosure(dependents,listModel);
422
423				int button = showListConfirm(
424					"plugin-manager.dependency",
425					new String[] { jar.getFile()
426					.getName() },listModel);
427				if(button == JOptionPane.YES_OPTION)
428					unloadPluginJAR(jar);
429			}
430		} //}}}
431
432		//{{{ transitiveClosure() method
433		/**
434		 * If plugin A is needed by B, and B is needed by C, we want to
435		 * tell the user that A is needed by B and C when they try to
436		 * unload A.
437		 */
438		private void transitiveClosure(String[] dependents,
439			Vector listModel)
440		{
441			for(int i = 0; i < dependents.length; i++)
442			{
443				String jarPath = dependents[i];
444				if(!listModel.contains(jarPath))
445				{
446					listModel.add(jarPath);
447					PluginJAR jar = jEdit.getPluginJAR(
448						jarPath);
449					transitiveClosure(jar.getDependentPlugins(),
450						listModel);
451				}
452			}
453		} //}}}
454
455		//{{{ unloadPluginJAR() method
456		/**
457		 * This should go into a public method somewhere.
458		 */
459		private void unloadPluginJAR(PluginJAR jar)
460		{
461			String[] dependents = jar.getDependentPlugins();
462			for(int i = 0; i < dependents.length; i++)
463			{
464				PluginJAR _jar = jEdit.getPluginJAR(
465					dependents[i]);
466				if(_jar != null)
467				{
468					unloadPluginJAR(_jar);
469				}
470			}
471
472			jEdit.removePluginJAR(jar,false);
473		} //}}}
474	} //}}}
475
476	//{{{ TextRenderer class
477	class TextRenderer extends DefaultTableCellRenderer
478	{
479		private DefaultTableCellRenderer tcr;
480
481		public TextRenderer(DefaultTableCellRenderer tcr)
482		{
483			this.tcr = tcr;
484		}
485
486		public Component getTableCellRendererComponent(JTable table, Object value,
487			boolean isSelected, boolean hasFocus, int row, int column)
488		{
489			Entry entry = pluginModel.getEntry(row);
490			if (entry.status.equals(Entry.ERROR))
491				tcr.setForeground(Color.red);
492			else
493				tcr.setForeground(UIManager.getColor("Table.foreground"));
494			return tcr.getTableCellRendererComponent(table,value,isSelected,false,row,column);
495		}
496	} //}}}
497
498	//{{{ HideLibrariesButton class
499	class HideLibrariesButton extends JCheckBox implements ActionListener
500	{
501		HideLibrariesButton()
502		{
503			super(jEdit.getProperty("plugin-manager.hide-libraries"));
504			setSelected(jEdit.getBooleanProperty(
505				"plugin-manager.hide-libraries.toggle"));
506			addActionListener(this);
507		}
508
509		public void actionPerformed(ActionEvent evt)
510		{
511			jEdit.setBooleanProperty(
512				"plugin-manager.hide-libraries.toggle",
513				isSelected());
514			ManagePanel.this.update();
515		}
516	} //}}}
517
518	//{{{ RemoveButton class
519	class RemoveButton extends JButton implements ListSelectionListener, ActionListener
520	{
521		public RemoveButton()
522		{
523			super(jEdit.getProperty("manage-plugins.remove"));
524			table.getSelectionModel().addListSelectionListener(this);
525			addActionListener(this);
526			setEnabled(false);
527		}
528
529		public void actionPerformed(ActionEvent evt)
530		{
531			int[] selected = table.getSelectedRows();
532
533			Vector listModel = new Vector();
534			Roster roster = new Roster();
535			for(int i = 0; i < selected.length; i++)
536			{
537				Entry entry = pluginModel.getEntry(selected[i]);
538				Iterator iter = entry.jars.iterator();
539				while(iter.hasNext())
540				{
541					String jar = (String)iter.next();
542					listModel.addElement(jar);
543					roster.addRemove(jar);
544				}
545			}
546
547			int button = showListConfirm(
548				"plugin-manager.remove-confirm",
549				null,listModel);
550			if(button == JOptionPane.YES_OPTION)
551			{
552				roster.performOperationsInAWTThread(window);
553				pluginModel.update();
554			}
555		}
556
557		public void valueChanged(ListSelectionEvent e)
558		{
559			if (table.getSelectedRowCount() == 0)
560				setEnabled(false);
561			else
562				setEnabled(true);
563		}
564	} //}}}
565
566	//{{{ HelpButton class
567	class HelpButton extends JButton implements ListSelectionListener, ActionListener
568	{
569		private URL docURL;
570
571		public HelpButton()
572		{
573			super(jEdit.getProperty("manage-plugins.help"));
574			table.getSelectionModel().addListSelectionListener(this);
575			addActionListener(this);
576			setEnabled(false);
577		}
578
579		public void actionPerformed(ActionEvent evt)
580		{
581			new HelpViewer(docURL);
582		}
583
584		public void valueChanged(ListSelectionEvent e)
585		{
586			if (table.getSelectedRowCount() == 1)
587			{
588				try
589				{
590					Entry entry = pluginModel.getEntry(table.getSelectedRow());
591					String label = entry.clazz;
592					String docs = entry.docs;
593					PluginJAR jar = jEdit.getPlugin(label)
594						.getPluginJAR();
595					if(jar != null && label != null && docs != null)
596					{
597						URL url = jar.getClassLoader()
598							.getResource(docs);
599						if(url != null)
600						{
601							docURL = url;
602							setEnabled(true);
603							return;
604						}
605					}
606				}
607				catch (Exception ex) {}
608			}
609			setEnabled(false);
610		}
611	} //}}}
612
613	//{{{ EntryCompare class
614	static class EntryCompare implements Comparator
615	{
616		public static final int NAME = 1;
617		public static final int STATUS = 2;
618
619		private int type;
620
621		public EntryCompare(int type)
622		{
623			this.type = type;
624		}
625
626		public int compare(Object o1, Object o2)
627		{
628			ManagePanel.Entry e1 = (ManagePanel.Entry)o1;
629			ManagePanel.Entry e2 = (ManagePanel.Entry)o2;
630
631			if (type == NAME)
632				return compareNames(e1,e2);
633			else
634			{
635				int result;
636				if ((result = e1.status.compareToIgnoreCase(e2.status)) == 0)
637					return compareNames(e1,e2);
638				return result;
639			}
640		}
641
642		private int compareNames(ManagePanel.Entry e1, ManagePanel.Entry e2)
643		{
644			String s1, s2;
645			if(e1.name == null)
646				s1 = MiscUtilities.getFileName(e1.jar);
647			else
648				s1 = e1.name;
649			if(e2.name == null)
650				s2 = MiscUtilities.getFileName(e2.jar);
651			else
652				s2 = e2.name;
653
654			return s1.compareToIgnoreCase(s2);
655		}
656	} //}}}
657
658	//{{{ HeaderMouseHandler class
659	class HeaderMouseHandler extends MouseAdapter
660	{
661		public void mouseClicked(MouseEvent evt)
662		{
663			switch(table.getTableHeader().columnAtPoint(evt.getPoint()))
664			{
665				case 1:
666					pluginModel.setSortType(EntryCompare.NAME);
667					break;
668				case 3:
669					pluginModel.setSortType(EntryCompare.STATUS);
670					break;
671				default:
672					break;
673			}
674		}
675	} //}}}
676
677	//}}}
678}