0001: /*
0002: * InstallPanel.java - For installing plugins
0003: * :tabSize=8:indentSize=8:noTabs=false:
0004: * :folding=explicit:collapseFolds=1:
0005: *
0006: * Copyright (C) 2002 Kris Kopicki
0007: *
0008: * This program is free software; you can redistribute it and/or
0009: * modify it under the terms of the GNU General Public License
0010: * as published by the Free Software Foundation; either version 2
0011: * of the License, or any later version.
0012: *
0013: * This program is distributed in the hope that it will be useful,
0014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0016: * GNU General Public License for more details.
0017: *
0018: * You should have received a copy of the GNU General Public License
0019: * along with this program; if not, write to the Free Software
0020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0021: */
0022:
0023: package org.gjt.sp.jedit.pluginmgr;
0024:
0025: //{{{ Imports
0026:
0027: import org.gjt.sp.jedit.*;
0028: import org.gjt.sp.jedit.browser.VFSBrowser;
0029: import org.gjt.sp.jedit.gui.RolloverButton;
0030: import org.gjt.sp.jedit.io.VFS;
0031: import org.gjt.sp.jedit.io.VFSManager;
0032: import org.gjt.sp.util.Log;
0033: import org.gjt.sp.util.StandardUtilities;
0034: import org.gjt.sp.util.XMLUtilities;
0035: import org.xml.sax.Attributes;
0036: import org.xml.sax.SAXException;
0037: import org.xml.sax.helpers.DefaultHandler;
0038:
0039: import javax.swing.*;
0040: import javax.swing.border.EmptyBorder;
0041: import javax.swing.event.ListSelectionEvent;
0042: import javax.swing.event.ListSelectionListener;
0043: import javax.swing.event.TableModelEvent;
0044: import javax.swing.event.TableModelListener;
0045: import javax.swing.table.AbstractTableModel;
0046: import javax.swing.table.DefaultTableCellRenderer;
0047: import javax.swing.table.JTableHeader;
0048: import javax.swing.table.TableColumn;
0049: import javax.swing.text.html.HTMLEditorKit;
0050: import java.awt.*;
0051: import java.awt.event.*;
0052: import java.io.File;
0053: import java.io.InputStream;
0054: import java.text.NumberFormat;
0055: import java.text.ParseException;
0056: import java.text.SimpleDateFormat;
0057: import java.util.*;
0058: import java.util.List;
0059:
0060: //}}}
0061:
0062: /**
0063: * @version $Id: InstallPanel.java 11188 2007-12-04 11:16:23Z kpouer $
0064: */
0065: class InstallPanel extends JPanel implements EBComponent {
0066:
0067: //{{{ Variables
0068: private final JTable table;
0069: private JScrollPane scrollpane;
0070: private PluginTableModel pluginModel;
0071: private PluginManager window;
0072: private PluginInfoBox infoBox;
0073: ChoosePluginSet chooseButton;
0074: private boolean updates;
0075:
0076: final HashSet<String> pluginSet = new HashSet<String>();
0077:
0078: //}}}
0079:
0080: //{{{ InstallPanel constructor
0081: InstallPanel(PluginManager window, boolean updates) {
0082: super (new BorderLayout(12, 12));
0083:
0084: this .window = window;
0085: this .updates = updates;
0086:
0087: setBorder(new EmptyBorder(12, 12, 12, 12));
0088:
0089: final JSplitPane split = new JSplitPane(
0090: JSplitPane.VERTICAL_SPLIT,
0091: jEdit.getBooleanProperty("appearance.continuousLayout"));
0092:
0093: /* Setup the table */
0094: table = new JTable(pluginModel = new PluginTableModel());
0095: table.setShowGrid(false);
0096: table.setIntercellSpacing(new Dimension(0, 0));
0097: table.setRowHeight(table.getRowHeight() + 2);
0098: table
0099: .setPreferredScrollableViewportSize(new Dimension(500,
0100: 200));
0101: table.setDefaultRenderer(Object.class, new TextRenderer(
0102: (DefaultTableCellRenderer) table
0103: .getDefaultRenderer(Object.class)));
0104: table.addFocusListener(new TableFocusHandler());
0105: InputMap tableInputMap = table
0106: .getInputMap(JComponent.WHEN_FOCUSED);
0107: ActionMap tableActionMap = table.getActionMap();
0108: tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0),
0109: "tabOutForward");
0110: tableActionMap.put("tabOutForward", new KeyboardAction(
0111: KeyboardCommand.TAB_OUT_FORWARD));
0112: tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
0113: InputEvent.SHIFT_MASK), "tabOutBack");
0114: tableActionMap.put("tabOutBack", new KeyboardAction(
0115: KeyboardCommand.TAB_OUT_BACK));
0116: tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
0117: "editPlugin");
0118: tableActionMap.put("editPlugin", new KeyboardAction(
0119: KeyboardCommand.EDIT_PLUGIN));
0120: tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
0121: "closePluginManager");
0122: tableActionMap.put("closePluginManager", new KeyboardAction(
0123: KeyboardCommand.CLOSE_PLUGIN_MANAGER));
0124:
0125: TableColumn col1 = table.getColumnModel().getColumn(0);
0126: TableColumn col2 = table.getColumnModel().getColumn(1);
0127: TableColumn col3 = table.getColumnModel().getColumn(2);
0128: TableColumn col4 = table.getColumnModel().getColumn(3);
0129: TableColumn col5 = table.getColumnModel().getColumn(4);
0130:
0131: col1.setPreferredWidth(30);
0132: col1.setMinWidth(30);
0133: col1.setMaxWidth(30);
0134: col1.setResizable(false);
0135:
0136: col2.setPreferredWidth(180);
0137: col3.setPreferredWidth(130);
0138: col4.setPreferredWidth(70);
0139: col5.setPreferredWidth(70);
0140:
0141: JTableHeader header = table.getTableHeader();
0142: header.setReorderingAllowed(false);
0143: header.addMouseListener(new HeaderMouseHandler());
0144: header
0145: .setDefaultRenderer(new HeaderRenderer(
0146: (DefaultTableCellRenderer) header
0147: .getDefaultRenderer()));
0148:
0149: scrollpane = new JScrollPane(table);
0150: scrollpane.getViewport().setBackground(table.getBackground());
0151: split.setTopComponent(scrollpane);
0152:
0153: /* Create description */
0154: JScrollPane infoPane = new JScrollPane(
0155: infoBox = new PluginInfoBox());
0156: infoPane.setPreferredSize(new Dimension(500, 100));
0157: split.setBottomComponent(infoPane);
0158:
0159: SwingUtilities.invokeLater(new Runnable() {
0160: public void run() {
0161: split.setDividerLocation(0.75);
0162: }
0163: });
0164:
0165: add(BorderLayout.CENTER, split);
0166:
0167: /* Create buttons */
0168: Box buttons = new Box(BoxLayout.X_AXIS);
0169:
0170: buttons.add(new InstallButton());
0171: buttons.add(Box.createHorizontalStrut(12));
0172: buttons.add(new SelectallButton());
0173: buttons.add(chooseButton = new ChoosePluginSet());
0174: buttons.add(new ClearPluginSet());
0175: buttons.add(Box.createGlue());
0176: buttons.add(new SizeLabel());
0177:
0178: add(BorderLayout.SOUTH, buttons);
0179: String path = jEdit.getProperty(
0180: PluginManager.PROPERTY_PLUGINSET, "");
0181: if (!path.equals("")) {
0182: loadPluginSet(path);
0183: }
0184: } //}}}
0185:
0186: //{{{ loadPluginSet() method
0187: /** loads a pluginSet xml file and updates the model to reflect
0188: certain checked selections
0189: @since jEdit 4.3pre10
0190: @author Alan Ezust
0191: */
0192: boolean loadPluginSet(String path) {
0193: VFS vfs = VFSManager.getVFSForPath(path);
0194: Object session = vfs.createVFSSession(path, InstallPanel.this );
0195: try {
0196: InputStream is = vfs._createInputStream(session, path,
0197: false, InstallPanel.this );
0198: XMLUtilities.parseXML(is, new StringMapHandler());
0199: } catch (Exception e) {
0200: Log.log(Log.ERROR, this , "Loading Pluginset Error", e);
0201: return false;
0202: }
0203: pluginModel.update();
0204: return true;
0205: } //}}}
0206:
0207: //{{{ updateModel() method
0208: public void updateModel() {
0209: final Set<String> savedChecked = new HashSet<String>();
0210: final Set<String> savedSelection = new HashSet<String>();
0211: pluginModel.saveSelection(savedChecked, savedSelection);
0212: pluginModel.clear();
0213: infoBox.setText(jEdit
0214: .getProperty("plugin-manager.list-download"));
0215:
0216: VFSManager.runInAWTThread(new Runnable() {
0217: public void run() {
0218: infoBox.setText(null);
0219: pluginModel.update();
0220: pluginModel.restoreSelection(savedChecked,
0221: savedSelection);
0222: }
0223: });
0224: } //}}}
0225:
0226: //{{{ handleMessage() method
0227: public void handleMessage(EBMessage message) {
0228: if (message.getSource() == PluginManager.getInstance()) {
0229: chooseButton.path = jEdit.getProperty(
0230: PluginManager.PROPERTY_PLUGINSET, "");
0231: if (chooseButton.path.length() > 0) {
0232: loadPluginSet(chooseButton.path);
0233: pluginModel.restoreSelection(new HashSet<String>(),
0234: new HashSet<String>());
0235: chooseButton.updateUI();
0236: }
0237: }
0238: } //}}}
0239:
0240: //{{{ Private members
0241:
0242: //{{{ formatSize() method
0243: private static String formatSize(int size) {
0244: NumberFormat df = NumberFormat.getInstance();
0245: df.setMaximumFractionDigits(1);
0246: df.setMinimumFractionDigits(0);
0247: String sizeText;
0248: if (size < 1048576)
0249: sizeText = (size >> 10) + "KB";
0250: else
0251: sizeText = df.format(size / 1048576.0d) + "MB";
0252: return sizeText;
0253: } //}}}
0254:
0255: //}}}
0256:
0257: //{{{ Inner classes
0258:
0259: //{{{ KeyboardCommand enum
0260: public enum KeyboardCommand {
0261: NONE, TAB_OUT_FORWARD, TAB_OUT_BACK, EDIT_PLUGIN, CLOSE_PLUGIN_MANAGER
0262: } //}}}
0263:
0264: //{{{ PluginTableModel class
0265: class PluginTableModel extends AbstractTableModel {
0266: /** This List can contain String or Entry. */
0267: private List entries = new ArrayList();
0268: private int sortType = EntryCompare.COLUMN_NAME;
0269: int sortDirection = 1;
0270:
0271: //{{{ getColumnClass() method
0272: public Class getColumnClass(int columnIndex) {
0273: switch (columnIndex) {
0274: case 0:
0275: return Boolean.class;
0276: case 1:
0277: case 2:
0278: case 3:
0279: case 4:
0280: case 5:
0281: return Object.class;
0282: default:
0283: throw new Error("Column out of range");
0284: }
0285: } //}}}
0286:
0287: //{{{ getColumnCount() method
0288: public int getColumnCount() {
0289: return 6;
0290: } //}}}
0291:
0292: //{{{ getColumnName() method
0293: public String getColumnName(int column) {
0294: switch (column) {
0295: case 0:
0296: return " ";
0297: case 1:
0298: return ' ' + jEdit
0299: .getProperty("install-plugins.info.name");
0300: case 2:
0301: return ' ' + jEdit
0302: .getProperty("install-plugins.info.category");
0303: case 3:
0304: return ' ' + jEdit
0305: .getProperty("install-plugins.info.version");
0306: case 4:
0307: return ' ' + jEdit
0308: .getProperty("install-plugins.info.size");
0309: case 5:
0310: return ' ' + "Release date";
0311: default:
0312: throw new Error("Column out of range");
0313: }
0314: } //}}}
0315:
0316: //{{{ getRowCount() method
0317: public int getRowCount() {
0318: return entries.size();
0319: } //}}}
0320:
0321: //{{{ getValueAt() method
0322: public Object getValueAt(int rowIndex, int columnIndex) {
0323: Object obj = entries.get(rowIndex);
0324: if (obj instanceof String) {
0325: if (columnIndex == 1)
0326: return obj;
0327: else
0328: return null;
0329: } else {
0330: Entry entry = (Entry) obj;
0331:
0332: switch (columnIndex) {
0333: case 0:
0334: return entry.install;
0335: case 1:
0336: return entry.name;
0337: case 2:
0338: return entry.set;
0339: case 3:
0340: if (updates)
0341: return entry.installedVersion + "->"
0342: + entry.version;
0343: return entry.version;
0344: case 4:
0345: return formatSize(entry.size);
0346: case 5:
0347: return entry.date;
0348: default:
0349: throw new Error("Column out of range");
0350: }
0351: }
0352: } //}}}
0353:
0354: //{{{ isCellEditable() method
0355: public boolean isCellEditable(int rowIndex, int columnIndex) {
0356: return columnIndex == 0;
0357: } //}}}
0358:
0359: //{{{ setSelectAll() method
0360: public void setSelectAll(boolean b) {
0361: if (isDownloadingList())
0362: return;
0363:
0364: int length = getRowCount();
0365: for (int i = 0; i < length; i++) {
0366: if (b)
0367: setValueAt(Boolean.TRUE, i, 0);
0368: else {
0369: Entry entry = (Entry) entries.get(i);
0370: entry.parents = new LinkedList<Entry>();
0371: entry.install = false;
0372: }
0373: }
0374: fireTableChanged(new TableModelEvent(this ));
0375: } //}}}
0376:
0377: //{{{ setSortType() method
0378: public void setSortType(int type) {
0379: sortType = type;
0380: sort(type);
0381: } //}}}
0382:
0383: //{{{ deselectParents() method
0384: private void deselectParents(Entry entry) {
0385: Entry[] parents = entry.getParents();
0386:
0387: if (parents.length == 0)
0388: return;
0389:
0390: String[] args = { entry.name };
0391:
0392: int result = GUIUtilities.listConfirm(window,
0393: "plugin-manager.dependency", args, parents);
0394: if (result != JOptionPane.OK_OPTION) {
0395: entry.install = true;
0396: return;
0397: }
0398:
0399: for (int i = 0; i < parents.length; i++)
0400: parents[i].install = false;
0401:
0402: fireTableRowsUpdated(0, getRowCount() - 1);
0403: } //}}}
0404:
0405: //{{{ setValueAt() method
0406: public void setValueAt(Object aValue, int row, int column) {
0407: if (column != 0)
0408: return;
0409:
0410: Object obj = entries.get(row);
0411: if (obj instanceof String)
0412: return;
0413:
0414: Entry entry = (Entry) obj;
0415: entry.install = Boolean.TRUE.equals(aValue);
0416:
0417: if (!entry.install)
0418: deselectParents(entry);
0419:
0420: List<PluginList.Dependency> deps = entry.plugin
0421: .getCompatibleBranch().deps;
0422:
0423: for (int i = 0; i < deps.size(); i++) {
0424: PluginList.Dependency dep = deps.get(i);
0425: if (dep.what.equals("plugin")) {
0426: for (int j = 0; j < entries.size(); j++) {
0427: Entry temp = (Entry) entries.get(j);
0428: if (temp.plugin == dep.plugin) {
0429: if (entry.install) {
0430: temp.parents.add(entry);
0431: setValueAt(Boolean.TRUE, j, 0);
0432: } else
0433: temp.parents.remove(entry);
0434: }
0435: }
0436: }
0437: }
0438:
0439: fireTableCellUpdated(row, column);
0440: } //}}}
0441:
0442: //{{{ sort() method
0443: public void sort(int type) {
0444: Set<String> savedChecked = new HashSet<String>();
0445: Set<String> savedSelection = new HashSet<String>();
0446: saveSelection(savedChecked, savedSelection);
0447:
0448: if (sortType != type) {
0449: sortDirection = 1;
0450: }
0451: sortType = type;
0452:
0453: if (isDownloadingList())
0454: return;
0455:
0456: Collections.sort(entries, new EntryCompare(type,
0457: sortDirection));
0458: fireTableChanged(new TableModelEvent(this ));
0459: restoreSelection(savedChecked, savedSelection);
0460: table.getTableHeader().repaint();
0461: }
0462:
0463: //}}}
0464:
0465: //{{{ isDownloadingList() method
0466: private boolean isDownloadingList() {
0467: return entries.size() == 1
0468: && entries.get(0) instanceof String;
0469: } //}}}
0470:
0471: //{{{ clear() method
0472: public void clear() {
0473: entries = new ArrayList();
0474: fireTableChanged(new TableModelEvent(this ));
0475: } //}}}
0476:
0477: //{{{ update() method
0478: public void update() {
0479: Set<String> savedChecked = new HashSet<String>();
0480: Set<String> savedSelection = new HashSet<String>();
0481: saveSelection(savedChecked, savedSelection);
0482:
0483: PluginList pluginList = window.getPluginList();
0484:
0485: if (pluginList == null)
0486: return;
0487:
0488: entries = new ArrayList();
0489:
0490: for (int i = 0; i < pluginList.pluginSets.size(); i++) {
0491: PluginList.PluginSet set = pluginList.pluginSets.get(i);
0492: for (int j = 0; j < set.plugins.size(); j++) {
0493: PluginList.Plugin plugin = pluginList.pluginHash
0494: .get(set.plugins.get(j));
0495: PluginList.Branch branch = plugin
0496: .getCompatibleBranch();
0497: String installedVersion = plugin
0498: .getInstalledVersion();
0499: if (updates) {
0500: if (branch != null
0501: && branch.canSatisfyDependencies()
0502: && installedVersion != null
0503: && StandardUtilities.compareStrings(
0504: branch.version,
0505: installedVersion, false) > 0) {
0506: entries.add(new Entry(plugin, set.name));
0507: }
0508: } else {
0509: if (installedVersion == null
0510: && plugin.canBeInstalled())
0511: entries.add(new Entry(plugin, set.name));
0512: }
0513: }
0514: }
0515:
0516: sort(sortType);
0517:
0518: fireTableChanged(new TableModelEvent(this ));
0519: restoreSelection(savedChecked, savedSelection);
0520: } //}}}
0521:
0522: //{{{ saveSelection() method
0523: public void saveSelection(Set<String> savedChecked,
0524: Set<String> savedSelection) {
0525: if (entries.isEmpty())
0526: return;
0527: for (int i = 0, c = getRowCount(); i < c; i++) {
0528: if ((Boolean) getValueAt(i, 0)) {
0529: savedChecked.add(entries.get(i).toString());
0530: }
0531: }
0532: int[] rows = table.getSelectedRows();
0533: for (int i = 0; i < rows.length; i++) {
0534: savedSelection.add(entries.get(rows[i]).toString());
0535: }
0536: } //}}}
0537:
0538: //{{{ restoreSelection() method
0539: public void restoreSelection(Set<String> savedChecked,
0540: Set<String> savedSelection) {
0541: for (int i = 0, c = getRowCount(); i < c; i++) {
0542: String name = entries.get(i).toString();
0543: if (pluginSet.contains(name))
0544: setValueAt(true, i, 0);
0545: else
0546: setValueAt(savedChecked.contains(name), i, 0);
0547: }
0548:
0549: if (null != table) {
0550: table.setColumnSelectionInterval(0, 0);
0551: if (!savedSelection.isEmpty()) {
0552: int i = 0;
0553: int rowCount = getRowCount();
0554: for (; i < rowCount; i++) {
0555: String name = entries.get(i).toString();
0556: if (savedSelection.contains(name)) {
0557: table.setRowSelectionInterval(i, i);
0558: break;
0559: }
0560: }
0561: ListSelectionModel lsm = table.getSelectionModel();
0562: for (; i < rowCount; i++) {
0563: String name = entries.get(i).toString();
0564: if (savedSelection.contains(name)) {
0565: lsm.addSelectionInterval(i, i);
0566: }
0567: }
0568: } else {
0569: if (table.getRowCount() != 0)
0570: table.setRowSelectionInterval(0, 0);
0571: JScrollBar scrollbar = scrollpane
0572: .getVerticalScrollBar();
0573: scrollbar.setValue(scrollbar.getMinimum());
0574: }
0575: }
0576: } //}}}
0577: } //}}}
0578:
0579: //{{{ Entry class
0580: class Entry {
0581: String name, installedVersion, version, author, date,
0582: description, set;
0583:
0584: long timestamp;
0585: int size;
0586: boolean install;
0587: PluginList.Plugin plugin;
0588: List<Entry> parents = new LinkedList<Entry>();
0589:
0590: Entry(PluginList.Plugin plugin, String set) {
0591: PluginList.Branch branch = plugin.getCompatibleBranch();
0592: boolean downloadSource = jEdit
0593: .getBooleanProperty("plugin-manager.downloadSource");
0594: int size = downloadSource ? branch.downloadSourceSize
0595: : branch.downloadSize;
0596:
0597: this .name = plugin.name;
0598: this .author = plugin.author;
0599: this .installedVersion = plugin.getInstalledVersion();
0600: this .version = branch.version;
0601: this .size = size;
0602: this .date = branch.date;
0603: this .description = plugin.description;
0604: this .set = set;
0605: this .install = false;
0606: this .plugin = plugin;
0607: SimpleDateFormat format = new SimpleDateFormat(
0608: "d MMMM yyyy", Locale.ENGLISH);
0609: try {
0610: timestamp = format.parse(date).getTime();
0611: } catch (ParseException e) {
0612: Log.log(Log.ERROR, this , e);
0613: }
0614: }
0615:
0616: private void getParents(List<Entry> list) {
0617: for (Entry entry : parents) {
0618: if (entry.install && !list.contains(entry)) {
0619: list.add(entry);
0620: entry.getParents(list);
0621: }
0622: }
0623: }
0624:
0625: Entry[] getParents() {
0626: List<Entry> list = new ArrayList<Entry>();
0627: getParents(list);
0628: Entry[] array = list.toArray(new Entry[list.size()]);
0629: Arrays.sort(array, new MiscUtilities.StringICaseCompare());
0630: return array;
0631: }
0632:
0633: public String toString() {
0634: return name;
0635: }
0636: } //}}}
0637:
0638: //{{{ PluginInfoBox class
0639: class PluginInfoBox extends JTextPane implements
0640: ListSelectionListener {
0641: private final String[] params;
0642:
0643: PluginInfoBox() {
0644: setEditable(false);
0645: setEditorKit(new HTMLEditorKit());
0646: // setLineWrap(true);
0647: // setWrapStyleWord(true);
0648: params = new String[3];
0649: table.getSelectionModel().addListSelectionListener(this );
0650: }
0651:
0652: public void valueChanged(ListSelectionEvent e) {
0653: String text = "";
0654: if (table.getSelectedRowCount() == 1) {
0655: Entry entry = (Entry) pluginModel.entries.get(table
0656: .getSelectedRow());
0657: params[0] = entry.author;
0658: params[1] = entry.date;
0659: params[2] = entry.description;
0660: text = jEdit
0661: .getProperty("install-plugins.info", params);
0662: text = text.replace("\n", "<br>");
0663: text = "<html>" + text + "</html>";
0664: }
0665: setText(text);
0666: setCaretPosition(0);
0667: }
0668: } //}}}
0669:
0670: //{{{ SizeLabel class
0671: class SizeLabel extends JLabel implements TableModelListener {
0672: private int size;
0673:
0674: SizeLabel() {
0675: size = 0;
0676: setText(jEdit.getProperty("install-plugins.totalSize")
0677: + formatSize(size));
0678: pluginModel.addTableModelListener(this );
0679: }
0680:
0681: public void tableChanged(TableModelEvent e) {
0682: if (e.getType() == TableModelEvent.UPDATE) {
0683: if (pluginModel.isDownloadingList())
0684: return;
0685:
0686: size = 0;
0687: int length = pluginModel.getRowCount();
0688: for (int i = 0; i < length; i++) {
0689: Entry entry = (Entry) pluginModel.entries.get(i);
0690: if (entry.install)
0691: size += entry.size;
0692: }
0693: setText(jEdit.getProperty("install-plugins.totalSize")
0694: + formatSize(size));
0695: }
0696: }
0697: } //}}}
0698:
0699: //{{{ SelectallButton class
0700: class SelectallButton extends JCheckBox implements ActionListener,
0701: TableModelListener {
0702: SelectallButton() {
0703: super (jEdit.getProperty("install-plugins.select-all"));
0704: addActionListener(this );
0705: pluginModel.addTableModelListener(this );
0706: setEnabled(false);
0707: }
0708:
0709: public void actionPerformed(ActionEvent evt) {
0710: pluginModel.setSelectAll(isSelected());
0711: }
0712:
0713: public void tableChanged(TableModelEvent e) {
0714: if (pluginModel.isDownloadingList())
0715: return;
0716:
0717: setEnabled(pluginModel.getRowCount() != 0);
0718: if (e.getType() == TableModelEvent.UPDATE) {
0719: int length = pluginModel.getRowCount();
0720: for (int i = 0; i < length; i++)
0721: if (!((Boolean) pluginModel.getValueAt(i, 0))
0722: .booleanValue()) {
0723: setSelected(false);
0724: return;
0725: }
0726: if (length > 0)
0727: setSelected(true);
0728: }
0729: }
0730: } //}}}
0731:
0732: //{{{ StringMapHandler class
0733: /** For parsing the pluginset xml files into pluginSet */
0734: class StringMapHandler extends DefaultHandler {
0735: StringMapHandler() {
0736: pluginSet.clear();
0737: }
0738:
0739: public void startElement(String uri, String localName,
0740: String qName, Attributes attrs) throws SAXException {
0741: if (localName.equals("plugin")) {
0742: pluginSet.add(attrs.getValue("name"));
0743: }
0744: }
0745: } //}}}
0746:
0747: //{{{ ChoosePluginSet class
0748: class ChoosePluginSet extends RolloverButton implements
0749: ActionListener {
0750: String path;
0751:
0752: //{{{ ChoosePluginSet constructor
0753: ChoosePluginSet() {
0754: setIcon(GUIUtilities.loadIcon("OpenFile.png"));
0755: addActionListener(this );
0756: updateUI();
0757: } //}}}
0758:
0759: //{{{ updateUI method
0760: public void updateUI() {
0761: path = jEdit.getProperty(PluginManager.PROPERTY_PLUGINSET,
0762: "");
0763: if (path.length() < 1)
0764: setToolTipText("Click here to choose a predefined plugin set");
0765: else
0766: setToolTipText("Choose pluginset (" + path + ')');
0767: super .updateUI();
0768: }//}}}
0769:
0770: //{{{ actionPerformed() method
0771: public void actionPerformed(ActionEvent ae) {
0772: path = jEdit.getProperty(PluginManager.PROPERTY_PLUGINSET,
0773: jEdit.getSettingsDirectory() + File.separator);
0774: String[] selectedFiles = GUIUtilities.showVFSFileDialog(
0775: InstallPanel.this .window, jEdit.getActiveView(),
0776: path, VFSBrowser.OPEN_DIALOG, false);
0777: if (selectedFiles == null || selectedFiles.length != 1)
0778: return;
0779: path = selectedFiles[0];
0780: boolean success = loadPluginSet(path);
0781: if (success) {
0782: jEdit.setProperty(PluginManager.PROPERTY_PLUGINSET,
0783: path);
0784: }
0785: updateUI();
0786: } //}}}
0787: }//}}}
0788:
0789: //{{{ ClearPluginSet class
0790: class ClearPluginSet extends RolloverButton implements
0791: ActionListener {
0792: //{{{ ClearPluginSet constructor
0793: ClearPluginSet() {
0794: setIcon(GUIUtilities.loadIcon("Clear.png"));
0795: setToolTipText("clear plugin set");
0796: addActionListener(this );
0797: } //}}}
0798:
0799: //{{{ actionPerformed() method
0800: public void actionPerformed(ActionEvent e) {
0801: pluginSet.clear();
0802: pluginModel.restoreSelection(new HashSet<String>(),
0803: new HashSet<String>());
0804: jEdit.unsetProperty(PluginManager.PROPERTY_PLUGINSET);
0805: chooseButton.updateUI();
0806: } //}}}
0807: } //}}}
0808:
0809: //{{{ InstallButton class
0810: class InstallButton extends JButton implements ActionListener,
0811: TableModelListener {
0812: InstallButton() {
0813: super (jEdit.getProperty("install-plugins.install"));
0814: pluginModel.addTableModelListener(this );
0815: addActionListener(this );
0816: setEnabled(false);
0817: }
0818:
0819: public void actionPerformed(ActionEvent evt) {
0820: if (pluginModel.isDownloadingList())
0821: return;
0822:
0823: boolean downloadSource = jEdit
0824: .getBooleanProperty("plugin-manager.downloadSource");
0825: boolean installUser = jEdit
0826: .getBooleanProperty("plugin-manager.installUser");
0827: Roster roster = new Roster();
0828: String installDirectory;
0829: if (installUser) {
0830: installDirectory = MiscUtilities.constructPath(jEdit
0831: .getSettingsDirectory(), "jars");
0832: } else {
0833: installDirectory = MiscUtilities.constructPath(jEdit
0834: .getJEditHome(), "jars");
0835: }
0836:
0837: int length = pluginModel.getRowCount();
0838: int instcount = 0;
0839: for (int i = 0; i < length; i++) {
0840: Entry entry = (Entry) pluginModel.entries.get(i);
0841: if (entry.install) {
0842: entry.plugin.install(roster, installDirectory,
0843: downloadSource);
0844: if (updates)
0845: entry.plugin.getCompatibleBranch()
0846: .satisfyDependencies(roster,
0847: installDirectory,
0848: downloadSource);
0849: instcount++;
0850: }
0851: }
0852:
0853: if (roster.isEmpty())
0854: return;
0855:
0856: boolean cancel = false;
0857: if (updates && roster.getOperationCount() > instcount)
0858: if (GUIUtilities.confirm(window,
0859: "install-plugins.depend", null,
0860: JOptionPane.OK_CANCEL_OPTION,
0861: JOptionPane.WARNING_MESSAGE) == JOptionPane.CANCEL_OPTION)
0862: cancel = true;
0863:
0864: if (!cancel) {
0865: new PluginManagerProgress(window, roster);
0866:
0867: roster.performOperationsInAWTThread(window);
0868: pluginModel.update();
0869: }
0870: }
0871:
0872: public void tableChanged(TableModelEvent e) {
0873: if (pluginModel.isDownloadingList())
0874: return;
0875:
0876: if (e.getType() == TableModelEvent.UPDATE) {
0877: int length = pluginModel.getRowCount();
0878: for (int i = 0; i < length; i++)
0879: if (((Boolean) pluginModel.getValueAt(i, 0))
0880: .booleanValue()) {
0881: setEnabled(true);
0882: return;
0883: }
0884: setEnabled(false);
0885: }
0886: }
0887: } //}}}
0888:
0889: //{{{ EntryCompare class
0890: static class EntryCompare implements Comparator {
0891: private static final int COLUMN_INSTALL = 0;
0892: private static final int COLUMN_NAME = 1;
0893: private static final int COLUMN_CATEGORY = 2;
0894: private static final int COLUMN_VERSION = 3;
0895: private static final int COLUMN_SIZE = 4;
0896: private static final int COLUMN_RELEASE = 5;
0897:
0898: private int type;
0899:
0900: /** 1=up, -1=down */
0901: private int sortDirection;
0902:
0903: EntryCompare(int type, int sortDirection) {
0904: this .type = type;
0905: this .sortDirection = sortDirection;
0906: }
0907:
0908: public int compare(Object o1, Object o2) {
0909: InstallPanel.Entry e1 = (InstallPanel.Entry) o1;
0910: InstallPanel.Entry e2 = (InstallPanel.Entry) o2;
0911: int result;
0912:
0913: switch (type) {
0914: case COLUMN_INSTALL:
0915: result = (e1.install == e2.install) ? 0
0916: : (e1.install ? 1 : -1);
0917: break;
0918: case COLUMN_NAME:
0919: result = e1.name.compareToIgnoreCase(e2.name);
0920: break;
0921: case COLUMN_CATEGORY:
0922: result = e1.set.compareToIgnoreCase(e2.set);
0923: if (result == 0) {
0924: result = e1.name.compareToIgnoreCase(e2.name);
0925: }
0926: break;
0927: case COLUMN_VERSION:
0928: // lets avoid NPE. Maybe we should move
0929: // this code to StandardUtilities.compareStrings
0930: if (e1.version == e2.version) {
0931: result = 0;
0932: } else if (e1.version == null) {
0933: result = -1;
0934: } else if (e2.version == null) {
0935: result = 1;
0936: } else {
0937: result = StandardUtilities.compareStrings(
0938: e1.version, e2.version, true);
0939: }
0940: break;
0941: case COLUMN_SIZE:
0942: result = (e1.size < e2.size) ? -1
0943: : ((e1.size == e2.size) ? 0 : 1);
0944: break;
0945: case COLUMN_RELEASE:
0946: result = (e1.timestamp < e2.timestamp) ? -1
0947: : ((e1.timestamp == e2.timestamp) ? 0 : 1);
0948: break;
0949: default:
0950: result = 0;
0951: }
0952: return result * sortDirection;
0953: }
0954: } //}}}
0955:
0956: //{{{ HeaderMouseHandler class
0957: class HeaderMouseHandler extends MouseAdapter {
0958: public void mouseClicked(MouseEvent evt) {
0959: int column = table.getTableHeader().columnAtPoint(
0960: evt.getPoint());
0961: pluginModel.sortDirection *= -1;
0962: pluginModel.sort(column);
0963: }
0964: } //}}}
0965:
0966: //{{{ TextRenderer
0967: static class TextRenderer extends DefaultTableCellRenderer {
0968: private DefaultTableCellRenderer tcr;
0969:
0970: TextRenderer(DefaultTableCellRenderer tcr) {
0971: this .tcr = tcr;
0972: }
0973:
0974: public Component getTableCellRendererComponent(JTable table,
0975: Object value, boolean isSelected, boolean hasFocus,
0976: int row, int column) {
0977: if (column == 5)
0978: tcr.setHorizontalAlignment(SwingConstants.TRAILING);
0979: else
0980: tcr.setHorizontalAlignment(SwingConstants.LEADING);
0981: return tcr.getTableCellRendererComponent(table, value,
0982: isSelected, false, row, column);
0983: }
0984: } //}}}
0985:
0986: //{{{ KeyboardAction class
0987: class KeyboardAction extends AbstractAction {
0988: private KeyboardCommand command = KeyboardCommand.NONE;
0989:
0990: KeyboardAction(KeyboardCommand command) {
0991: this .command = command;
0992: }
0993:
0994: public void actionPerformed(ActionEvent evt) {
0995: switch (command) {
0996: case TAB_OUT_FORWARD:
0997: KeyboardFocusManager.getCurrentKeyboardFocusManager()
0998: .focusNextComponent();
0999: break;
1000: case TAB_OUT_BACK:
1001: KeyboardFocusManager.getCurrentKeyboardFocusManager()
1002: .focusPreviousComponent();
1003: break;
1004: case EDIT_PLUGIN:
1005: int[] rows = table.getSelectedRows();
1006: Object[] state = new Object[rows.length];
1007: for (int i = 0; i < rows.length; i++) {
1008: state[i] = pluginModel.getValueAt(rows[i], 0);
1009: }
1010: for (int i = 0; i < rows.length; i++) {
1011: pluginModel.setValueAt(state[i]
1012: .equals(Boolean.FALSE), rows[i], 0);
1013: }
1014: break;
1015: case CLOSE_PLUGIN_MANAGER:
1016: window.ok();
1017: break;
1018: default:
1019: throw new InternalError();
1020: }
1021: }
1022: } //}}}
1023:
1024: //{{{ TableFocusHandler class
1025: class TableFocusHandler extends FocusAdapter {
1026: public void focusGained(FocusEvent fe) {
1027: if (-1 == table.getSelectedRow() && table.getRowCount() > 0) {
1028: table.setRowSelectionInterval(0, 0);
1029: JScrollBar scrollbar = scrollpane
1030: .getVerticalScrollBar();
1031: scrollbar.setValue(scrollbar.getMinimum());
1032: }
1033: if (-1 == table.getSelectedColumn()) {
1034: table.setColumnSelectionInterval(0, 0);
1035: }
1036: }
1037: } //}}}
1038:
1039: //{{{ HeaderRenderer
1040: static class HeaderRenderer extends DefaultTableCellRenderer {
1041: private DefaultTableCellRenderer tcr;
1042:
1043: HeaderRenderer(DefaultTableCellRenderer tcr) {
1044: this .tcr = tcr;
1045: }
1046:
1047: public Component getTableCellRendererComponent(JTable table,
1048: Object value, boolean isSelected, boolean hasFocus,
1049: int row, int column) {
1050: JLabel l = (JLabel) tcr.getTableCellRendererComponent(
1051: table, value, isSelected, hasFocus, row, column);
1052: PluginTableModel model = (PluginTableModel) table
1053: .getModel();
1054: Icon icon = (column == model.sortType) ? (model.sortDirection == 1) ? ASC_ICON
1055: : DESC_ICON
1056: : null;
1057: l.setIcon(icon);
1058: // l.setHorizontalTextPosition(l.LEADING);
1059: return l;
1060: }
1061: } //}}}
1062:
1063: //}}}
1064:
1065: static final Icon ASC_ICON = GUIUtilities.loadIcon("arrow-asc.png");
1066: static final Icon DESC_ICON = GUIUtilities
1067: .loadIcon("arrow-desc.png");
1068: }
|