/jEdit/branches/new_bufferset_api/org/gjt/sp/jedit/pluginmgr/InstallPanel.java

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