PageRenderTime 55ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

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