/jEdit/tags/jedit-4-4-1/org/gjt/sp/jedit/pluginmgr/InstallPanel.java

# · Java · 1154 lines · 935 code · 126 blank · 93 comment · 136 complexity · c7b78ada932ff8dab999dee805977f63 MD5 · raw file

  1. /*
  2. * InstallPanel.java - For installing 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 org.gjt.sp.jedit.*;
  25. import org.gjt.sp.jedit.browser.VFSBrowser;
  26. import org.gjt.sp.jedit.gui.RolloverButton;
  27. import org.gjt.sp.jedit.io.VFS;
  28. import org.gjt.sp.jedit.io.VFSManager;
  29. import org.gjt.sp.util.Log;
  30. import org.gjt.sp.util.StandardUtilities;
  31. import org.gjt.sp.util.ThreadUtilities;
  32. import org.gjt.sp.util.XMLUtilities;
  33. import org.xml.sax.Attributes;
  34. import org.xml.sax.SAXException;
  35. import org.xml.sax.helpers.DefaultHandler;
  36. import javax.swing.*;
  37. import javax.swing.border.EmptyBorder;
  38. import javax.swing.event.ListSelectionEvent;
  39. import javax.swing.event.ListSelectionListener;
  40. import javax.swing.event.TableModelEvent;
  41. import javax.swing.event.TableModelListener;
  42. import javax.swing.table.AbstractTableModel;
  43. import javax.swing.table.DefaultTableCellRenderer;
  44. import javax.swing.table.JTableHeader;
  45. import javax.swing.table.TableColumn;
  46. import javax.swing.text.html.HTMLEditorKit;
  47. import java.awt.*;
  48. import java.awt.event.*;
  49. import java.io.File;
  50. import java.io.InputStream;
  51. import java.text.NumberFormat;
  52. import java.text.ParseException;
  53. import java.text.SimpleDateFormat;
  54. import java.util.*;
  55. import java.util.List;
  56. //}}}
  57. /**
  58. * @version $Id: InstallPanel.java 18335 2010-08-12 09:25:34Z kpouer $
  59. */
  60. class InstallPanel extends JPanel implements EBComponent
  61. {
  62. //{{{ Variables
  63. private final JTable table;
  64. private JScrollPane scrollpane;
  65. private PluginTableModel pluginModel;
  66. private PluginManager window;
  67. private PluginInfoBox infoBox;
  68. private ChoosePluginSet chooseButton;
  69. private boolean updates;
  70. private final Set<String> pluginSet = new HashSet<String>();
  71. //}}}
  72. //{{{ InstallPanel constructor
  73. InstallPanel(PluginManager window, boolean updates)
  74. {
  75. super(new BorderLayout(12,12));
  76. this.window = window;
  77. this.updates = updates;
  78. setBorder(new EmptyBorder(12,12,12,12));
  79. final JSplitPane split = new JSplitPane(
  80. JSplitPane.VERTICAL_SPLIT, jEdit.getBooleanProperty("appearance.continuousLayout"));
  81. split.setResizeWeight(0.75);
  82. /* Setup the table */
  83. table = new JTable(pluginModel = new PluginTableModel());
  84. table.setShowGrid(false);
  85. table.setIntercellSpacing(new Dimension(0,0));
  86. table.setRowHeight(table.getRowHeight() + 2);
  87. table.setPreferredScrollableViewportSize(new Dimension(500,200));
  88. table.setDefaultRenderer(Object.class, new TextRenderer(
  89. (DefaultTableCellRenderer)table.getDefaultRenderer(Object.class)));
  90. table.addFocusListener(new TableFocusHandler());
  91. InputMap tableInputMap = table.getInputMap(JComponent.WHEN_FOCUSED);
  92. ActionMap tableActionMap = table.getActionMap();
  93. tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,0),"tabOutForward");
  94. tableActionMap.put("tabOutForward",new KeyboardAction(KeyboardCommand.TAB_OUT_FORWARD));
  95. tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,InputEvent.SHIFT_MASK),"tabOutBack");
  96. tableActionMap.put("tabOutBack",new KeyboardAction(KeyboardCommand.TAB_OUT_BACK));
  97. tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0),"editPlugin");
  98. tableActionMap.put("editPlugin",new KeyboardAction(KeyboardCommand.EDIT_PLUGIN));
  99. tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0),"closePluginManager");
  100. tableActionMap.put("closePluginManager",new KeyboardAction(KeyboardCommand.CLOSE_PLUGIN_MANAGER));
  101. TableColumn col1 = table.getColumnModel().getColumn(0);
  102. TableColumn col2 = table.getColumnModel().getColumn(1);
  103. TableColumn col3 = table.getColumnModel().getColumn(2);
  104. TableColumn col4 = table.getColumnModel().getColumn(3);
  105. TableColumn col5 = table.getColumnModel().getColumn(4);
  106. col1.setPreferredWidth(30);
  107. col1.setMinWidth(30);
  108. col1.setMaxWidth(30);
  109. col1.setResizable(false);
  110. col2.setPreferredWidth(180);
  111. col3.setPreferredWidth(130);
  112. col4.setPreferredWidth(70);
  113. col5.setPreferredWidth(70);
  114. JTableHeader header = table.getTableHeader();
  115. header.setReorderingAllowed(false);
  116. header.addMouseListener(new HeaderMouseHandler());
  117. header.setDefaultRenderer(new HeaderRenderer(
  118. (DefaultTableCellRenderer)header.getDefaultRenderer()));
  119. scrollpane = new JScrollPane(table);
  120. scrollpane.getViewport().setBackground(table.getBackground());
  121. split.setTopComponent(scrollpane);
  122. /* Create description */
  123. JScrollPane infoPane = new JScrollPane(
  124. infoBox = new PluginInfoBox());
  125. infoPane.setPreferredSize(new Dimension(500,100));
  126. split.setBottomComponent(infoPane);
  127. SwingUtilities.invokeLater(new Runnable()
  128. {
  129. public void run()
  130. {
  131. split.setDividerLocation(0.75);
  132. }
  133. });
  134. add(BorderLayout.CENTER,split);
  135. /* Create buttons */
  136. Box buttons = new Box(BoxLayout.X_AXIS);
  137. buttons.add(new InstallButton());
  138. buttons.add(Box.createHorizontalStrut(12));
  139. buttons.add(new SelectallButton());
  140. buttons.add(chooseButton = new ChoosePluginSet());
  141. buttons.add(new ClearPluginSet());
  142. buttons.add(Box.createGlue());
  143. buttons.add(new SizeLabel());
  144. add(BorderLayout.SOUTH,buttons);
  145. String path = jEdit.getProperty(PluginManager.PROPERTY_PLUGINSET, "");
  146. if (!path.equals(""))
  147. {
  148. loadPluginSet(path);
  149. }
  150. } //}}}
  151. //{{{ loadPluginSet() method
  152. /** loads a pluginSet xml file and updates the model to reflect
  153. certain checked selections
  154. @since jEdit 4.3pre10
  155. @author Alan Ezust
  156. */
  157. boolean loadPluginSet(String path)
  158. {
  159. pluginSet.clear();
  160. pluginModel.restoreSelection(new HashSet<String>(), new HashSet<String>());
  161. VFS vfs = VFSManager.getVFSForPath(path);
  162. Object session = vfs.createVFSSession(path, InstallPanel.this);
  163. try
  164. {
  165. InputStream is = vfs._createInputStream(session, path, false, InstallPanel.this);
  166. XMLUtilities.parseXML(is, new StringMapHandler());
  167. }
  168. catch (Exception e)
  169. {
  170. Log.log(Log.WARNING, this, "Loading Pluginset failed:" + e.getMessage());
  171. return false;
  172. }
  173. pluginModel.update();
  174. return true;
  175. } //}}}
  176. //{{{ updateModel() method
  177. public void updateModel()
  178. {
  179. final Set<String> savedChecked = new HashSet<String>();
  180. final Set<String> savedSelection = new HashSet<String>();
  181. pluginModel.saveSelection(savedChecked, savedSelection);
  182. pluginModel.clear();
  183. infoBox.setText(jEdit.getProperty("plugin-manager.list-download"));
  184. ThreadUtilities.runInDispatchThread(new Runnable()
  185. {
  186. public void run()
  187. {
  188. infoBox.setText(null);
  189. pluginModel.update();
  190. pluginModel.restoreSelection(savedChecked, savedSelection);
  191. }
  192. });
  193. } //}}}
  194. //{{{ handleMessage() method
  195. public void handleMessage(EBMessage message)
  196. {
  197. if (message.getSource() == PluginManager.getInstance())
  198. {
  199. chooseButton.path = jEdit.getProperty(PluginManager.PROPERTY_PLUGINSET, "");
  200. if (chooseButton.path.length() > 0)
  201. {
  202. loadPluginSet(chooseButton.path);
  203. pluginModel.restoreSelection(new HashSet<String>(), new HashSet<String>());
  204. chooseButton.updateUI();
  205. }
  206. }
  207. } //}}}
  208. //{{{ Private members
  209. //{{{ formatSize() method
  210. private static String formatSize(int size)
  211. {
  212. NumberFormat df = NumberFormat.getInstance();
  213. df.setMaximumFractionDigits(1);
  214. df.setMinimumFractionDigits(0);
  215. String sizeText;
  216. if (size < 1048576)
  217. sizeText = (size >> 10) + "KB";
  218. else
  219. sizeText = df.format(size/ 1048576.0d) + "MB";
  220. return sizeText;
  221. } //}}}
  222. //}}}
  223. //{{{ Inner classes
  224. //{{{ PluginTableModel class
  225. private class PluginTableModel extends AbstractTableModel
  226. {
  227. /** This List can contain String or Entry. */
  228. private List entries = new ArrayList();
  229. private int sortType = EntryCompare.COLUMN_NAME;
  230. int sortDirection = 1;
  231. //{{{ getColumnClass() method
  232. @Override
  233. public Class getColumnClass(int columnIndex)
  234. {
  235. switch (columnIndex)
  236. {
  237. case 0: return Boolean.class;
  238. case 1:
  239. case 2:
  240. case 3:
  241. case 4:
  242. case 5: return Object.class;
  243. default: throw new Error("Column out of range");
  244. }
  245. } //}}}
  246. //{{{ getColumnCount() method
  247. public int getColumnCount()
  248. {
  249. return 6;
  250. } //}}}
  251. //{{{ getColumnName() method
  252. @Override
  253. public String getColumnName(int column)
  254. {
  255. switch (column)
  256. {
  257. case 0: return " ";
  258. case 1: return ' '+jEdit.getProperty("install-plugins.info.name");
  259. case 2: return ' '+jEdit.getProperty("install-plugins.info.category");
  260. case 3: return ' '+jEdit.getProperty("install-plugins.info.version");
  261. case 4: return ' '+jEdit.getProperty("install-plugins.info.size");
  262. case 5: return ' '+jEdit.getProperty("install-plugins.info.releaseDate");
  263. default: throw new Error("Column out of range");
  264. }
  265. } //}}}
  266. //{{{ getRowCount() method
  267. public int getRowCount()
  268. {
  269. return entries.size();
  270. } //}}}
  271. //{{{ getValueAt() method
  272. public Object getValueAt(int rowIndex,int columnIndex)
  273. {
  274. Object obj = entries.get(rowIndex);
  275. if(obj instanceof String)
  276. {
  277. if(columnIndex == 1)
  278. return obj;
  279. else
  280. return null;
  281. }
  282. else
  283. {
  284. Entry entry = (Entry)obj;
  285. switch (columnIndex)
  286. {
  287. case 0:
  288. return entry.install;
  289. case 1:
  290. return entry.name;
  291. case 2:
  292. return entry.set;
  293. case 3:
  294. if (updates)
  295. return entry.installedVersion + "->" + entry.version;
  296. return entry.version;
  297. case 4:
  298. return formatSize(entry.size);
  299. case 5:
  300. return entry.date;
  301. default:
  302. throw new Error("Column out of range");
  303. }
  304. }
  305. } //}}}
  306. //{{{ isCellEditable() method
  307. @Override
  308. public boolean isCellEditable(int rowIndex, int columnIndex)
  309. {
  310. return columnIndex == 0;
  311. } //}}}
  312. //{{{ setSelectAll() method
  313. public void setSelectAll(boolean b)
  314. {
  315. if(isDownloadingList())
  316. return;
  317. int length = getRowCount();
  318. for (int i = 0; i < length; i++)
  319. {
  320. if (b)
  321. setValueAt(Boolean.TRUE,i,0);
  322. else
  323. {
  324. Entry entry = (Entry)entries.get(i);
  325. entry.parents = new LinkedList<Entry>();
  326. entry.install = false;
  327. }
  328. }
  329. fireTableChanged(new TableModelEvent(this));
  330. } //}}}
  331. //{{{ setSortType() method
  332. public void setSortType(int type)
  333. {
  334. sortType = type;
  335. sort(type);
  336. } //}}}
  337. //{{{ deselectParents() method
  338. private void deselectParents(Entry entry)
  339. {
  340. Entry[] parents = entry.getParents();
  341. if (parents.length == 0)
  342. return;
  343. String[] args = { entry.name };
  344. int result = GUIUtilities.listConfirm(
  345. window,"plugin-manager.dependency",
  346. args,parents);
  347. if (result != JOptionPane.OK_OPTION)
  348. {
  349. entry.install = true;
  350. return;
  351. }
  352. for(int i = 0; i < parents.length; i++)
  353. parents[i].install = false;
  354. fireTableRowsUpdated(0,getRowCount() - 1);
  355. } //}}}
  356. //{{{ setValueAt() method
  357. @Override
  358. public void setValueAt(Object aValue, int row, int column)
  359. {
  360. if (column != 0) return;
  361. Object obj = entries.get(row);
  362. if(obj instanceof String)
  363. return;
  364. Entry entry = (Entry)obj;
  365. boolean before = entry.install;
  366. entry.install = Boolean.TRUE.equals(aValue);
  367. if (before == entry.install) return;
  368. if (!entry.install)
  369. deselectParents(entry);
  370. List<PluginList.Dependency> deps = entry.plugin.getCompatibleBranch().deps;
  371. for (int i = 0; i < deps.size(); i++)
  372. {
  373. PluginList.Dependency dep = deps.get(i);
  374. if (dep.what.equals("plugin"))
  375. {
  376. for (int j = 0; j < entries.size(); j++)
  377. {
  378. Entry temp = (Entry)entries.get(j);
  379. if (temp.plugin == dep.plugin)
  380. {
  381. if (entry.install)
  382. {
  383. temp.parents.add(entry);
  384. setValueAt(Boolean.TRUE,j,0);
  385. }
  386. else
  387. temp.parents.remove(entry);
  388. }
  389. }
  390. }
  391. }
  392. fireTableCellUpdated(row,column);
  393. } //}}}
  394. //{{{ sort() method
  395. public void sort(int type)
  396. {
  397. Set<String> savedChecked = new HashSet<String>();
  398. Set<String> savedSelection = new HashSet<String>();
  399. saveSelection(savedChecked,savedSelection);
  400. if (sortType != type)
  401. {
  402. sortDirection = 1;
  403. }
  404. sortType = type;
  405. if(isDownloadingList())
  406. return;
  407. Collections.sort(entries,new EntryCompare(type, sortDirection));
  408. fireTableChanged(new TableModelEvent(this));
  409. restoreSelection(savedChecked,savedSelection);
  410. table.getTableHeader().repaint();
  411. }
  412. //}}}
  413. //{{{ isDownloadingList() method
  414. private boolean isDownloadingList()
  415. {
  416. return entries.size() == 1 && entries.get(0) instanceof String;
  417. } //}}}
  418. //{{{ clear() method
  419. public void clear()
  420. {
  421. entries = new ArrayList();
  422. fireTableChanged(new TableModelEvent(this));
  423. } //}}}
  424. //{{{ update() method
  425. public void update()
  426. {
  427. Set<String> savedChecked = new HashSet<String>();
  428. Set<String> savedSelection = new HashSet<String>();
  429. saveSelection(savedChecked,savedSelection);
  430. PluginList pluginList = window.getPluginList();
  431. if (pluginList == null) return;
  432. entries = new ArrayList();
  433. for(int i = 0; i < pluginList.pluginSets.size(); i++)
  434. {
  435. PluginList.PluginSet set = pluginList.pluginSets.get(i);
  436. for(int j = 0; j < set.plugins.size(); j++)
  437. {
  438. PluginList.Plugin plugin = pluginList.pluginHash.get(set.plugins.get(j));
  439. PluginList.Branch branch = plugin.getCompatibleBranch();
  440. String installedVersion =
  441. plugin.getInstalledVersion();
  442. if (updates)
  443. {
  444. if(branch != null
  445. && branch.canSatisfyDependencies()
  446. && installedVersion != null
  447. && StandardUtilities.compareStrings(branch.version,
  448. installedVersion,false) > 0)
  449. {
  450. entries.add(new Entry(plugin, set.name));
  451. }
  452. }
  453. else
  454. {
  455. if(installedVersion == null && plugin.canBeInstalled())
  456. entries.add(new Entry(plugin,set.name));
  457. }
  458. }
  459. }
  460. sort(sortType);
  461. fireTableChanged(new TableModelEvent(this));
  462. restoreSelection(savedChecked, savedSelection);
  463. } //}}}
  464. //{{{ saveSelection() method
  465. public void saveSelection(Set<String> savedChecked, Set<String> savedSelection)
  466. {
  467. if (entries.isEmpty())
  468. return;
  469. for (int i=0, c=getRowCount() ; i<c ; i++)
  470. {
  471. if ((Boolean)getValueAt(i,0))
  472. {
  473. savedChecked.add(entries.get(i).toString());
  474. }
  475. }
  476. int[] rows = table.getSelectedRows();
  477. for (int i=0 ; i<rows.length ; i++)
  478. {
  479. savedSelection.add(entries.get(rows[i]).toString());
  480. }
  481. } //}}}
  482. //{{{ restoreSelection() method
  483. public void restoreSelection(Set<String> savedChecked, Set<String> savedSelection)
  484. {
  485. for (int i=0, c=getRowCount() ; i<c ; i++)
  486. {
  487. Object obj = entries.get(i);
  488. String name = obj.toString();
  489. if (obj instanceof Entry) {
  490. name = ((Entry)obj).plugin.jar;
  491. }
  492. if (pluginSet.contains(name))
  493. setValueAt(true, i, 0);
  494. else setValueAt(savedChecked.contains(name), i, 0);
  495. }
  496. if (table == null) return;
  497. table.setColumnSelectionInterval(0,0);
  498. if (!savedSelection.isEmpty())
  499. {
  500. int i = 0;
  501. int rowCount = getRowCount();
  502. for ( ; i<rowCount ; i++)
  503. {
  504. String name = entries.get(i).toString();
  505. if (savedSelection.contains(name))
  506. {
  507. table.setRowSelectionInterval(i,i);
  508. break;
  509. }
  510. }
  511. ListSelectionModel lsm = table.getSelectionModel();
  512. for ( ; i<rowCount ; i++)
  513. {
  514. String name = entries.get(i).toString();
  515. if (savedSelection.contains(name))
  516. {
  517. lsm.addSelectionInterval(i,i);
  518. }
  519. }
  520. }
  521. else
  522. {
  523. if (table.getRowCount() != 0)
  524. table.setRowSelectionInterval(0,0);
  525. JScrollBar scrollbar = scrollpane.getVerticalScrollBar();
  526. scrollbar.setValue(scrollbar.getMinimum());
  527. }
  528. } //}}}
  529. } //}}}
  530. //{{{ Entry class
  531. private static class Entry
  532. {
  533. String name, installedVersion, version, author, date, description, set;
  534. long timestamp;
  535. int size;
  536. boolean install;
  537. PluginList.Plugin plugin;
  538. List<Entry> parents = new LinkedList<Entry>();
  539. Entry(PluginList.Plugin plugin, String set)
  540. {
  541. PluginList.Branch branch = plugin.getCompatibleBranch();
  542. boolean downloadSource = jEdit.getBooleanProperty("plugin-manager.downloadSource");
  543. int size = downloadSource ? branch.downloadSourceSize : branch.downloadSize;
  544. this.name = plugin.name;
  545. this.author = plugin.author;
  546. this.installedVersion = plugin.getInstalledVersion();
  547. this.version = branch.version;
  548. this.size = size;
  549. this.date = branch.date;
  550. this.description = plugin.description;
  551. this.set = set;
  552. this.install = false;
  553. this.plugin = plugin;
  554. SimpleDateFormat format = new SimpleDateFormat("d MMMM yyyy", Locale.ENGLISH);
  555. try
  556. {
  557. timestamp = format.parse(date).getTime();
  558. }
  559. catch (ParseException e)
  560. {
  561. Log.log(Log.ERROR, this, e);
  562. }
  563. }
  564. private void getParents(List<Entry> list)
  565. {
  566. for (Entry entry : parents)
  567. {
  568. if (entry.install && !list.contains(entry))
  569. {
  570. list.add(entry);
  571. entry.getParents(list);
  572. }
  573. }
  574. }
  575. Entry[] getParents()
  576. {
  577. List<Entry> list = new ArrayList<Entry>();
  578. getParents(list);
  579. Entry[] array = list.toArray(new Entry[list.size()]);
  580. Arrays.sort(array,new StandardUtilities.StringCompare<Entry>(true));
  581. return array;
  582. }
  583. @Override
  584. public String toString()
  585. {
  586. return name;
  587. }
  588. } //}}}
  589. //{{{ PluginInfoBox class
  590. /**
  591. * @TODO refactor to use the PluginDetailPanel?
  592. */
  593. private class PluginInfoBox extends JTextPane implements ListSelectionListener
  594. {
  595. private final String[] params;
  596. PluginInfoBox()
  597. {
  598. setBackground(jEdit.getColorProperty("view.bgColor"));
  599. setForeground(jEdit.getColorProperty("view.fgColor"));
  600. putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, true);
  601. setEditable(false);
  602. setEditorKit(new HTMLEditorKit());
  603. // setLineWrap(true);
  604. // setWrapStyleWord(true);
  605. params = new String[3];
  606. table.getSelectionModel().addListSelectionListener(this);
  607. }
  608. public void valueChanged(ListSelectionEvent e)
  609. {
  610. String text = "";
  611. if (table.getSelectedRowCount() == 1)
  612. {
  613. Entry entry = (Entry) pluginModel.entries
  614. .get(table.getSelectedRow());
  615. params[0] = entry.author;
  616. params[1] = entry.date;
  617. params[2] = entry.description;
  618. text = jEdit.getProperty("install-plugins.info", params);
  619. text = text.replace("\n", "<br>");
  620. text = "<html>" + text + "</html>";
  621. }
  622. setText(text);
  623. setCaretPosition(0);
  624. }
  625. } //}}}
  626. //{{{ SizeLabel class
  627. private class SizeLabel extends JLabel implements TableModelListener
  628. {
  629. private int size;
  630. SizeLabel()
  631. {
  632. size = 0;
  633. setText(jEdit.getProperty("install-plugins.totalSize")+formatSize(size));
  634. pluginModel.addTableModelListener(this);
  635. }
  636. public void tableChanged(TableModelEvent e)
  637. {
  638. if (e.getType() == TableModelEvent.UPDATE)
  639. {
  640. if(pluginModel.isDownloadingList())
  641. return;
  642. size = 0;
  643. int length = pluginModel.getRowCount();
  644. for (int i = 0; i < length; i++)
  645. {
  646. Entry entry = (Entry)pluginModel
  647. .entries.get(i);
  648. if (entry.install)
  649. size += entry.size;
  650. }
  651. setText(jEdit.getProperty("install-plugins.totalSize")+formatSize(size));
  652. }
  653. }
  654. } //}}}
  655. //{{{ SelectallButton class
  656. private class SelectallButton extends JCheckBox implements ActionListener, TableModelListener
  657. {
  658. SelectallButton()
  659. {
  660. super(jEdit.getProperty("install-plugins.select-all"));
  661. addActionListener(this);
  662. pluginModel.addTableModelListener(this);
  663. setEnabled(false);
  664. }
  665. public void actionPerformed(ActionEvent evt)
  666. {
  667. pluginModel.setSelectAll(isSelected());
  668. }
  669. public void tableChanged(TableModelEvent e)
  670. {
  671. if(pluginModel.isDownloadingList())
  672. return;
  673. setEnabled(pluginModel.getRowCount() != 0);
  674. if (e.getType() == TableModelEvent.UPDATE)
  675. {
  676. int length = pluginModel.getRowCount();
  677. for (int i = 0; i < length; i++)
  678. if (!((Boolean)pluginModel.getValueAt(i,0)).booleanValue())
  679. {
  680. setSelected(false);
  681. return;
  682. }
  683. if (length > 0)
  684. setSelected(true);
  685. }
  686. }
  687. } //}}}
  688. //{{{ StringMapHandler class
  689. /** For parsing the pluginset xml files into pluginSet */
  690. private class StringMapHandler extends DefaultHandler
  691. {
  692. StringMapHandler()
  693. {
  694. pluginSet.clear();
  695. }
  696. @Override
  697. public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException
  698. {
  699. if (localName.equals("plugin"))
  700. {
  701. pluginSet.add(attrs.getValue("jar"));
  702. }
  703. }
  704. } //}}}
  705. //{{{ ChoosePluginSet class
  706. private class ChoosePluginSet extends RolloverButton implements ActionListener
  707. {
  708. private String path;
  709. //{{{ ChoosePluginSet constructor
  710. ChoosePluginSet()
  711. {
  712. setIcon(GUIUtilities.loadIcon(jEdit.getProperty("install-plugins.choose-plugin-set.icon")));
  713. addActionListener(this);
  714. updateUI();
  715. } //}}}
  716. //{{{ updateUI method
  717. @Override
  718. public void updateUI()
  719. {
  720. path = jEdit.getProperty(PluginManager.PROPERTY_PLUGINSET, "");
  721. if (path.length()<1) setToolTipText ("Click here to choose a predefined plugin set");
  722. else setToolTipText ("Choose pluginset (" + path + ')');
  723. super.updateUI();
  724. }//}}}
  725. //{{{ actionPerformed() method
  726. public void actionPerformed(ActionEvent ae)
  727. {
  728. path = jEdit.getProperty(PluginManager.PROPERTY_PLUGINSET,
  729. jEdit.getSettingsDirectory() + File.separator);
  730. String[] selectedFiles = GUIUtilities.showVFSFileDialog(InstallPanel.this.window,
  731. jEdit.getActiveView(), path, VFSBrowser.OPEN_DIALOG, false);
  732. if (selectedFiles == null || selectedFiles.length != 1) return;
  733. path = selectedFiles[0];
  734. boolean success = loadPluginSet(path);
  735. if (success)
  736. {
  737. jEdit.setProperty(PluginManager.PROPERTY_PLUGINSET, path);
  738. }
  739. updateUI();
  740. } //}}}
  741. }//}}}
  742. //{{{ ClearPluginSet class
  743. private class ClearPluginSet extends RolloverButton implements ActionListener
  744. {
  745. //{{{ ClearPluginSet constructor
  746. ClearPluginSet()
  747. {
  748. setIcon(GUIUtilities.loadIcon(jEdit.getProperty("install-plugins.clear-plugin-set.icon")));
  749. setToolTipText("clear plugin set");
  750. addActionListener(this);
  751. } //}}}
  752. //{{{ actionPerformed() method
  753. public void actionPerformed(ActionEvent e)
  754. {
  755. pluginSet.clear();
  756. pluginModel.restoreSelection(new HashSet<String>(), new HashSet<String>());
  757. jEdit.unsetProperty(PluginManager.PROPERTY_PLUGINSET);
  758. chooseButton.updateUI();
  759. } //}}}
  760. } //}}}
  761. //{{{ InstallButton class
  762. private class InstallButton extends JButton implements ActionListener, TableModelListener
  763. {
  764. InstallButton()
  765. {
  766. super(jEdit.getProperty("install-plugins.install"));
  767. pluginModel.addTableModelListener(this);
  768. addActionListener(this);
  769. setEnabled(false);
  770. }
  771. public void actionPerformed(ActionEvent evt)
  772. {
  773. if(pluginModel.isDownloadingList())
  774. return;
  775. boolean downloadSource = jEdit.getBooleanProperty(
  776. "plugin-manager.downloadSource");
  777. boolean installUser = jEdit.getBooleanProperty(
  778. "plugin-manager.installUser");
  779. Roster roster = new Roster();
  780. String installDirectory;
  781. if(installUser)
  782. {
  783. installDirectory = MiscUtilities.constructPath(
  784. jEdit.getSettingsDirectory(),"jars");
  785. }
  786. else
  787. {
  788. installDirectory = MiscUtilities.constructPath(
  789. jEdit.getJEditHome(),"jars");
  790. }
  791. int length = pluginModel.getRowCount();
  792. int instcount = 0;
  793. for (int i = 0; i < length; i++)
  794. {
  795. Entry entry = (Entry)pluginModel.entries.get(i);
  796. if (entry.install)
  797. {
  798. entry.plugin.install(roster,installDirectory,downloadSource);
  799. if (updates)
  800. entry.plugin.getCompatibleBranch().satisfyDependencies(
  801. roster,installDirectory,downloadSource);
  802. instcount++;
  803. }
  804. }
  805. if(roster.isEmpty())
  806. return;
  807. boolean cancel = false;
  808. if (updates && roster.getOperationCount() > instcount)
  809. if (GUIUtilities.confirm(window,
  810. "install-plugins.depend",
  811. null,
  812. JOptionPane.OK_CANCEL_OPTION,
  813. JOptionPane.WARNING_MESSAGE) == JOptionPane.CANCEL_OPTION)
  814. cancel = true;
  815. if (!cancel)
  816. {
  817. new PluginManagerProgress(window,roster);
  818. roster.performOperationsInAWTThread(window);
  819. pluginModel.update();
  820. }
  821. }
  822. public void tableChanged(TableModelEvent e)
  823. {
  824. if(pluginModel.isDownloadingList())
  825. return;
  826. if (e.getType() == TableModelEvent.UPDATE)
  827. {
  828. int length = pluginModel.getRowCount();
  829. for (int i = 0; i < length; i++)
  830. if (((Boolean)pluginModel.getValueAt(i,0)).booleanValue())
  831. {
  832. setEnabled(true);
  833. return;
  834. }
  835. setEnabled(false);
  836. }
  837. }
  838. } //}}}
  839. //{{{ EntryCompare class
  840. private static class EntryCompare implements Comparator<Entry>
  841. {
  842. private static final int COLUMN_INSTALL = 0;
  843. private static final int COLUMN_NAME = 1;
  844. private static final int COLUMN_CATEGORY = 2;
  845. private static final int COLUMN_VERSION = 3;
  846. private static final int COLUMN_SIZE = 4;
  847. private static final int COLUMN_RELEASE = 5;
  848. private int type;
  849. /** 1=up, -1=down */
  850. private int sortDirection;
  851. EntryCompare(int type, int sortDirection)
  852. {
  853. this.type = type;
  854. this.sortDirection = sortDirection;
  855. }
  856. public int compare(Entry e1, Entry e2)
  857. {
  858. int result;
  859. switch (type)
  860. {
  861. case COLUMN_INSTALL:
  862. result = (e1.install == e2.install) ? 0 : (e1.install ? 1 : -1);
  863. break;
  864. case COLUMN_NAME:
  865. result = e1.name.compareToIgnoreCase(e2.name);
  866. break;
  867. case COLUMN_CATEGORY:
  868. result = e1.set.compareToIgnoreCase(e2.set);
  869. if (result == 0)
  870. {
  871. result = e1.name.compareToIgnoreCase(e2.name);
  872. }
  873. break;
  874. case COLUMN_VERSION:
  875. // lets avoid NPE. Maybe we should move
  876. // this code to StandardUtilities.compareStrings
  877. if (e1.version == e2.version)
  878. {
  879. result = 0;
  880. }
  881. else if (e1.version == null)
  882. {
  883. result = -1;
  884. }
  885. else if(e2.version == null)
  886. {
  887. result = 1;
  888. }
  889. else
  890. {
  891. result = StandardUtilities.compareStrings(e1.version,
  892. e2.version,
  893. true);
  894. }
  895. break;
  896. case COLUMN_SIZE:
  897. result = (e1.size < e2.size)
  898. ? -1
  899. : ((e1.size == e2.size)
  900. ? 0
  901. : 1);
  902. break;
  903. case COLUMN_RELEASE:
  904. result = (e1.timestamp < e2.timestamp)
  905. ? -1
  906. : ((e1.timestamp == e2.timestamp)
  907. ? 0
  908. : 1);
  909. break;
  910. default:
  911. result = 0;
  912. }
  913. return result * sortDirection;
  914. }
  915. } //}}}
  916. //{{{ HeaderMouseHandler class
  917. private class HeaderMouseHandler extends MouseAdapter
  918. {
  919. @Override
  920. public void mouseClicked(MouseEvent evt)
  921. {
  922. int column = table.getTableHeader().columnAtPoint(evt.getPoint());
  923. pluginModel.sortDirection *= -1;
  924. pluginModel.sort(column);
  925. }
  926. } //}}}
  927. //{{{ TextRenderer
  928. private static class TextRenderer extends DefaultTableCellRenderer
  929. {
  930. private DefaultTableCellRenderer tcr;
  931. TextRenderer(DefaultTableCellRenderer tcr)
  932. {
  933. this.tcr = tcr;
  934. }
  935. @Override
  936. public Component getTableCellRendererComponent(JTable table, Object value,
  937. boolean isSelected, boolean hasFocus, int row, int column)
  938. {
  939. if (column == 5)
  940. tcr.setHorizontalAlignment(TRAILING);
  941. else
  942. tcr.setHorizontalAlignment(LEADING);
  943. return tcr.getTableCellRendererComponent(table,value,isSelected,false,row,column);
  944. }
  945. } //}}}
  946. //{{{ KeyboardAction class
  947. private class KeyboardAction extends AbstractAction
  948. {
  949. private KeyboardCommand command = KeyboardCommand.NONE;
  950. KeyboardAction(KeyboardCommand command)
  951. {
  952. this.command = command;
  953. }
  954. public void actionPerformed(ActionEvent evt)
  955. {
  956. switch (command)
  957. {
  958. case TAB_OUT_FORWARD:
  959. KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
  960. break;
  961. case TAB_OUT_BACK:
  962. KeyboardFocusManager.getCurrentKeyboardFocusManager().focusPreviousComponent();
  963. break;
  964. case EDIT_PLUGIN:
  965. int[] rows = table.getSelectedRows();
  966. Object[] state = new Object[rows.length];
  967. for (int i=0 ; i<rows.length ; i++)
  968. {
  969. state[i] = pluginModel.getValueAt(rows[i],0);
  970. }
  971. for (int i=0 ; i<rows.length ; i++)
  972. {
  973. pluginModel.setValueAt(state[i].equals(Boolean.FALSE),rows[i],0);
  974. }
  975. break;
  976. case CLOSE_PLUGIN_MANAGER:
  977. window.ok();
  978. break;
  979. default:
  980. throw new InternalError();
  981. }
  982. }
  983. } //}}}
  984. //{{{ TableFocusHandler class
  985. private class TableFocusHandler extends FocusAdapter
  986. {
  987. @Override
  988. public void focusGained(FocusEvent fe)
  989. {
  990. if (-1 == table.getSelectedRow() && table.getRowCount() > 0)
  991. {
  992. table.setRowSelectionInterval(0,0);
  993. JScrollBar scrollbar = scrollpane.getVerticalScrollBar();
  994. scrollbar.setValue(scrollbar.getMinimum());
  995. }
  996. if (-1 == table.getSelectedColumn())
  997. {
  998. table.setColumnSelectionInterval(0,0);
  999. }
  1000. }
  1001. } //}}}
  1002. //{{{ HeaderRenderer
  1003. private static class HeaderRenderer extends DefaultTableCellRenderer
  1004. {
  1005. private DefaultTableCellRenderer tcr;
  1006. HeaderRenderer(DefaultTableCellRenderer tcr)
  1007. {
  1008. this.tcr = tcr;
  1009. }
  1010. @Override
  1011. public Component getTableCellRendererComponent(JTable table, Object value,
  1012. boolean isSelected, boolean hasFocus,
  1013. int row, int column)
  1014. {
  1015. JLabel l = (JLabel)tcr.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
  1016. PluginTableModel model = (PluginTableModel) table.getModel();
  1017. Icon icon = (column == model.sortType)
  1018. ? (model.sortDirection == 1) ? ASC_ICON : DESC_ICON
  1019. : null;
  1020. l.setIcon(icon);
  1021. // l.setHorizontalTextPosition(l.LEADING);
  1022. return l;
  1023. }
  1024. } //}}}
  1025. //}}}
  1026. static final Icon ASC_ICON = GUIUtilities.loadIcon("arrow-asc.png");
  1027. static final Icon DESC_ICON = GUIUtilities.loadIcon("arrow-desc.png");
  1028. }