Beispiel #1
0
 // {{{ updateMultiStatus() method
 private void updateMultiStatus() {
   if (multiStatus)
     multi.setIcon(
         GUIUtilities.loadIcon(jEdit.getProperty("hypersearch-results.multi.multiple.icon")));
   else
     multi.setIcon(
         GUIUtilities.loadIcon(jEdit.getProperty("hypersearch-results.multi.single.icon")));
 } // }}}
Beispiel #2
0
 // {{{ updateHighlightStatus() method
 private void updateHighlightStatus() {
   String prop = jEdit.getProperty(HIGHLIGHT_PROP);
   if (prop != null && !prop.isEmpty())
     highlight.setIcon(
         GUIUtilities.loadIcon(jEdit.getProperty("hypersearch-results.match.highlight.icon")));
   else
     highlight.setIcon(
         GUIUtilities.loadIcon(jEdit.getProperty("hypersearch-results.match.normal.icon")));
   resultTree.repaint();
 } // }}}
  // {{{ init() method
  private void init() {
    EditBus.addToBus(this);

    /* Setup panes */
    JPanel content = new JPanel(new BorderLayout(12, 12));
    content.setBorder(new EmptyBorder(12, 12, 12, 12));
    setContentPane(content);

    tabPane = new JTabbedPane();
    tabPane.addTab(jEdit.getProperty("manage-plugins.title"), manager = new ManagePanel(this));
    tabPane.addTab(
        jEdit.getProperty("update-plugins.title"), updater = new InstallPanel(this, true));
    tabPane.addTab(
        jEdit.getProperty("install-plugins.title"), installer = new InstallPanel(this, false));
    EditBus.addToBus(installer);
    content.add(BorderLayout.CENTER, tabPane);

    tabPane.addChangeListener(new ListUpdater());

    /* Create the buttons */
    Box buttons = new Box(BoxLayout.X_AXIS);

    ActionListener al = new ActionHandler();
    mgrOptions = new JButton(jEdit.getProperty("plugin-manager.mgr-options"));
    mgrOptions.addActionListener(al);
    pluginOptions = new JButton(jEdit.getProperty("plugin-manager.plugin-options"));
    pluginOptions.addActionListener(al);
    done = new JButton(jEdit.getProperty("plugin-manager.done"));
    done.addActionListener(al);

    buttons.add(Box.createGlue());
    buttons.add(mgrOptions);
    buttons.add(Box.createHorizontalStrut(6));
    buttons.add(pluginOptions);
    buttons.add(Box.createHorizontalStrut(6));
    buttons.add(done);
    buttons.add(Box.createGlue());

    getRootPane().setDefaultButton(done);

    content.add(BorderLayout.SOUTH, buttons);

    setDefaultCloseOperation(DISPOSE_ON_CLOSE);

    setIconImage(GUIUtilities.getPluginIcon());

    pack();
    GUIUtilities.loadGeometry(this, parent, "plugin-manager");
    GUIUtilities.addSizeSaver(this, parent, "plugin-manager");
    setVisible(true);
  } // }}}
  // {{{ showFilePopup() method
  private void showFilePopup(VFSFile[] files, Component comp, Point point) {
    popup = new BrowserCommandsMenu(browser, files);
    // for the parent directory right-click; on the click we select
    // the clicked item, but when the popup goes away we select the
    // currently showing directory.
    popup.addPopupMenuListener(
        new PopupMenuListener() {
          public void popupMenuCanceled(PopupMenuEvent e) {}

          public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}

          public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
            // we use SwingUtilities.invokeLater()
            // so that the action is executed before
            // the popup is hidden.
            EventQueue.invokeLater(
                new Runnable() {
                  public void run() {
                    int index = parentDirectories.getModel().getSize() - 1;
                    parentDirectories.setSelectedIndex(index);
                  }
                });
          }
        });
    GUIUtilities.showPopupMenu(popup, comp, point.x, point.y);
  } // }}}
    @Override
    public void mouseReleased(MouseEvent evt) {
      if (evt.getClickCount() % 2 != 0 && !GUIUtilities.isMiddleButton(evt.getModifiers())) return;

      int row = parentDirectories.locationToIndex(evt.getPoint());
      if (row != -1) {
        Object obj = parentDirectories.getModel().getElementAt(row);
        if (obj instanceof VFSFile) {
          VFSFile dirEntry = (VFSFile) obj;
          if (!GUIUtilities.isPopupTrigger(evt)) {
            browser.setDirectory(dirEntry.getPath());
            if (browser.getMode() == VFSBrowser.BROWSER) focusOnFileView();
          }
        }
      }
    }
  // {{{ updatePluginList() method
  private void updatePluginList() {
    if (jEdit.getSettingsDirectory() == null && jEdit.getJEditHome() == null) {
      GUIUtilities.error(this, "no-settings", null);
      return;
    }
    if (!shouldUpdatePluginList()) {
      return;
    }

    ThreadUtilities.runInBackground(
        new Task() {
          @Override
          public void _run() {
            try {
              downloadingPluginList = true;
              setStatus(jEdit.getProperty("plugin-manager.list-download-connect"));
              pluginList = new PluginList(this);
            } finally {
              downloadingPluginList = false;
            }
            ThreadUtilities.runInDispatchThread(
                new Runnable() {
                  public void run() {
                    pluginListUpdated();
                  }
                });
          }
        });
  } // }}}
Beispiel #7
0
    @Override
    public void actionPerformed(ActionEvent evt) {
      Object source = evt.getSource();
      if (source == highlight) {
        String prop = jEdit.getProperty(HIGHLIGHT_PROP);
        Font f = (resultTree != null) ? resultTree.getFont() : UIManager.getFont("Tree.font");
        SyntaxStyle style =
            new StyleEditor(
                    jEdit.getActiveView(),
                    HtmlUtilities.parseHighlightStyle(prop, f),
                    "hypersearch")
                .getStyle();
        if (style != null) jEdit.setProperty(HIGHLIGHT_PROP, GUIUtilities.getStyleString(style));
        updateHighlightStatus();
      } else if (source == clear) {
        removeAllNodes();
      } else if (source == multi) {
        multiStatus = !multiStatus;
        updateMultiStatus();

        if (!multiStatus) {
          for (int i = resultTreeRoot.getChildCount() - 2; i >= 0; i--) {
            resultTreeModel.removeNodeFromParent((MutableTreeNode) resultTreeRoot.getChildAt(i));
          }
        }
      } else if (source == stop) {
        jEdit.setTemporaryProperty("hyperSearch-stopButton", "true");
      }
    }
Beispiel #8
0
  public ActionBar(View view, boolean temp) {
    setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

    this.view = view;
    this.temp = temp;

    add(Box.createHorizontalStrut(2));

    JLabel label = new JLabel(jEdit.getProperty("view.action.prompt"));
    add(label);
    add(Box.createHorizontalStrut(12));
    add(action = new ActionTextField());
    action.setEnterAddsToHistory(false);
    Dimension max = action.getPreferredSize();
    max.width = Integer.MAX_VALUE;
    action.setMaximumSize(max);
    action.addActionListener(new ActionHandler());
    action.getDocument().addDocumentListener(new DocumentHandler());

    if (temp) {
      close = new RolloverButton(GUIUtilities.loadIcon("closebox.gif"));
      close.addActionListener(new ActionHandler());
      close.setToolTipText(jEdit.getProperty("view.action.close-tooltip"));
      add(close);
    }

    this.temp = temp;
  }
Beispiel #9
0
    // {{{ mousePressed() method
    @Override
    public void mousePressed(MouseEvent evt) {
      if (evt.isConsumed()) return;

      TreePath path1 = resultTree.getPathForLocation(evt.getX(), evt.getY());
      if (path1 == null) return;

      resultTree.setSelectionPath(path1);
      if (GUIUtilities.isPopupTrigger(evt)) showPopupMenu(evt);
      else {
        goToSelectedNode(M_OPEN);
      }
    } // }}}
Beispiel #10
0
    // {{{ mousePressed() method
    @Override
    public void mousePressed(MouseEvent evt) {
      Point p = evt.getPoint();
      if (evt.getSource() != table) {
        p.x -= table.getX();
        p.y -= table.getY();
      }

      int row = table.rowAtPoint(p);
      int column = table.columnAtPoint(p);
      if (column == 0 && row != -1) {
        VFSDirectoryEntryTableModel.Entry entry =
            (VFSDirectoryEntryTableModel.Entry) table.getModel().getValueAt(row, 0);
        if (FileCellRenderer.ExpansionToggleBorder.isExpansionToggle(entry.level, p.x)) {
          table.toggleExpanded(row);
          return;
        }
      }

      if (GUIUtilities.isMiddleButton(evt.getModifiers())) {
        if (row == -1) /* nothing */ ;
        else if (evt.isShiftDown()) table.getSelectionModel().addSelectionInterval(row, row);
        else table.getSelectionModel().setSelectionInterval(row, row);
      } else if (GUIUtilities.isPopupTrigger(evt)) {
        if (popup != null && popup.isVisible()) {
          popup.setVisible(false);
          popup = null;
          return;
        }

        if (row == -1) showFilePopup(null, table, evt.getPoint());
        else {
          if (!table.getSelectionModel().isSelectedIndex(row))
            table.getSelectionModel().setSelectionInterval(row, row);
          showFilePopup(getSelectedFiles(), table, evt.getPoint());
        }
      }
    } // }}}
 private void buildMainFrame() {
   DesktopContext context = getDesktopContext();
   mainFrame = new JFrame(PRIDE_GUI + " " + context.getProperty("pride.inspector.version"));
   ImageIcon icon =
       GUIUtilities.loadImageIcon(context.getProperty("pride.inspector.logo.medium.icon"));
   mainFrame.setIconImage(icon.getImage());
   try {
     UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
   } catch (Exception e) {
     logger.error("Failed to set the look and feel", e);
   }
   // ToDo: proper exit hooke
   mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 }
    @Override
    public void actionPerformed(ActionEvent evt) {
      if (pluginModel.isDownloadingList()) return;

      boolean downloadSource = jEdit.getBooleanProperty("plugin-manager.downloadSource");
      boolean installUser = jEdit.getBooleanProperty("plugin-manager.installUser");
      Roster roster = new Roster();
      String installDirectory;
      if (installUser) {
        installDirectory = MiscUtilities.constructPath(jEdit.getSettingsDirectory(), "jars");
      } else {
        installDirectory = MiscUtilities.constructPath(jEdit.getJEditHome(), "jars");
      }

      int length = pluginModel.entries.size();
      int instcount = 0;
      for (int i = 0; i < length; i++) {
        Entry entry = (Entry) pluginModel.entries.get(i);
        if (entry.install) {
          entry.plugin.install(roster, installDirectory, downloadSource);
          if (updates)
            entry
                .plugin
                .getCompatibleBranch()
                .satisfyDependencies(roster, installDirectory, downloadSource);
          instcount++;
        }
      }

      if (roster.isEmpty()) return;

      boolean cancel = false;
      if (updates && roster.getOperationCount() > instcount)
        if (GUIUtilities.confirm(
                window,
                "install-plugins.depend",
                null,
                JOptionPane.OK_CANCEL_OPTION,
                JOptionPane.WARNING_MESSAGE)
            == JOptionPane.CANCEL_OPTION) cancel = true;

      if (!cancel) {
        new PluginManagerProgress(window, roster);

        roster.performOperationsInAWTThread(window);
        pluginModel.update();
      }
    }
    // {{{ deselectParents() method
    private void deselectParents(Entry entry) {
      Entry[] parents = entry.getParents();

      if (parents.length == 0) return;

      String[] args = {entry.name};
      int result = GUIUtilities.listConfirm(window, "plugin-manager.dependency", args, parents);
      if (result != JOptionPane.OK_OPTION) {
        entry.install = true;
        return;
      }

      for (int i = 0; i < parents.length; i++) parents[i].install = false;

      fireTableRowsUpdated(0, getRowCount() - 1);
    } // }}}
Beispiel #14
0
  // {{{ userInput() method
  protected void userInput(char ch) {
    lastActionCount = 0;

    JEditTextArea textArea = view.getTextArea();

    /* Buffer buffer = view.getBuffer();
    if(!buffer.insideCompoundEdit())
    	buffer.beginCompoundEdit(); */

    if (repeatCount == 1) textArea.userInput(ch);
    else {
      // stop people doing dumb stuff like C+ENTER 100 C+n
      if (repeatCount > REPEAT_COUNT_THRESHOLD) {
        Object[] pp = {String.valueOf(ch), repeatCount};

        if (GUIUtilities.confirm(
                view,
                "large-repeat-count.user-input",
                pp,
                JOptionPane.WARNING_MESSAGE,
                JOptionPane.YES_NO_OPTION)
            != JOptionPane.YES_OPTION) {
          repeatCount = 1;
          view.getStatus().setMessage(null);
          return;
        }
      }

      JEditBuffer buffer = view.getBuffer();
      try {
        if (repeatCount != 1) buffer.beginCompoundEdit();
        for (int i = 0; i < repeatCount; i++) textArea.userInput(ch);
      } finally {
        if (repeatCount != 1) buffer.endCompoundEdit();
      }
    }

    Macros.Recorder recorder = view.getMacroRecorder();

    if (recorder != null) {
      recorder.recordInput(repeatCount, ch, textArea.isOverwriteEnabled());
    }

    repeatCount = 1;
  } // }}}
    // {{{ actionPerformed() method
    @Override
    public void actionPerformed(ActionEvent ae) {

      path =
          jEdit.getProperty(
              PluginManager.PROPERTY_PLUGINSET, jEdit.getSettingsDirectory() + File.separator);
      String[] selectedFiles =
          GUIUtilities.showVFSFileDialog(
              InstallPanel.this.window, jEdit.getActiveView(), path, VFSBrowser.OPEN_DIALOG, false);
      if (selectedFiles == null || selectedFiles.length != 1) return;

      path = selectedFiles[0];
      boolean success = loadPluginSet(path);
      if (success) {
        jEdit.setProperty(PluginManager.PROPERTY_PLUGINSET, path);
      }
      updateUI();
    } // }}}
Beispiel #16
0
 @Override
 public void mousePressed(MouseEvent evt) {
   int row = parentDirectories.locationToIndex(evt.getPoint());
   if (row != -1) {
     Object obj = parentDirectories.getModel().getElementAt(row);
     if (obj instanceof VFSFile) {
       VFSFile dirEntry = (VFSFile) obj;
       if (GUIUtilities.isPopupTrigger(evt)) {
         if (popup != null && popup.isVisible()) {
           popup.setVisible(false);
           popup = null;
         } else {
           parentDirectories.setSelectedIndex(row);
           showFilePopup(new VFSFile[] {dirEntry}, parentDirectories, evt.getPoint());
         }
       }
     }
   }
 }
Beispiel #17
0
    public void actionPerformed(ActionEvent evt) {
      Font font;

      JDialog dialog = GUIUtilities.getParentDialog(FontSelector.this);
      if (dialog == null) {
        font =
            new FontSelectorDialog(
                    JOptionPane.getFrameForComponent(FontSelector.this),
                    getFont(),
                    FontSelector.this)
                .getSelectedFont();
      } else {
        font = new FontSelectorDialog(dialog, getFont(), FontSelector.this).getSelectedFont();
      }

      if (font != null) {
        setFont(font);
        updateText();
      }
    }
Beispiel #18
0
    CompletionPopup(String[] actions) {
      super(view);

      setContentPane(
          new JPanel(new BorderLayout()) {

            public boolean isManagingFocus() {
              return false;
            }

            public boolean getFocusTraversalKeysEnabled() {
              return false;
            }
          });

      list = new CompletionList(actions);
      list.setVisibleRowCount(8);
      list.addMouseListener(new MouseHandler());
      list.setSelectedIndex(0);
      list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

      JScrollPane scroller =
          new JScrollPane(
              list,
              ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
              ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

      getContentPane().add(scroller, BorderLayout.CENTER);

      GUIUtilities.requestFocus(this, list);

      pack();
      Point p = new Point(0, -getHeight());
      SwingUtilities.convertPointToScreen(p, action);
      setLocation(p);
      setVisible(true);

      KeyHandler keyHandler = new KeyHandler();
      addKeyListener(keyHandler);
      list.addKeyListener(keyHandler);
    }
Beispiel #19
0
    // {{{ mouseClicked() method
    @Override
    public void mouseClicked(MouseEvent evt) {
      Point p = evt.getPoint();
      int row = table.rowAtPoint(p);
      int column = table.columnAtPoint(p);
      if (row == -1) return;
      if (column == 0) {
        VFSDirectoryEntryTableModel.Entry entry =
            (VFSDirectoryEntryTableModel.Entry) table.getModel().getValueAt(row, 0);
        if (FileCellRenderer.ExpansionToggleBorder.isExpansionToggle(entry.level, p.x)) {
          return;
        }
      }

      if ((evt.getModifiers() & InputEvent.BUTTON1_MASK) != 0 && evt.getClickCount() % 2 == 0) {
        browser.filesActivated(
            evt.isShiftDown() ? VFSBrowser.M_OPEN_NEW_VIEW : VFSBrowser.M_OPEN, true);
      } else if (GUIUtilities.isMiddleButton(evt.getModifiers())) {
        if (evt.isShiftDown()) table.getSelectionModel().addSelectionInterval(row, row);
        else table.getSelectionModel().setSelectionInterval(row, row);
        browser.filesActivated(
            evt.isShiftDown() ? VFSBrowser.M_OPEN_NEW_VIEW : VFSBrowser.M_OPEN, true);
      }
    } // }}}
    public void actionPerformed(ActionEvent evt) {
      Object source = evt.getSource();
      if (source instanceof JRadioButton) updateEnabled();
      if (source == ok) ok();
      else if (source == cancel) cancel();
      else if (source == combo) updateList();
      else if (source == fileButton) {
        String directory;
        if (fileIcon == null) directory = null;
        else directory = MiscUtilities.getParentOfPath(fileIcon);
        String paths[] =
            GUIUtilities.showVFSFileDialog(null, directory, VFSBrowser.OPEN_DIALOG, false);
        if (paths == null) return;

        fileIcon = "file:" + paths[0];

        try {
          fileButton.setIcon(new ImageIcon(new URL(fileIcon)));
        } catch (MalformedURLException mf) {
          Log.log(Log.ERROR, this, mf);
        }
        fileButton.setText(MiscUtilities.getFileName(fileIcon));
      }
    }
Beispiel #21
0
    // {{{ showPopupMenu method
    private void showPopupMenu(MouseEvent evt) {
      TreePath path = resultTree.getSelectionPath();
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();

      popupMenu = new JPopupMenu();
      Object userObj = node.getUserObject();
      if (userObj instanceof HyperSearchFileNode || userObj instanceof HyperSearchResult) {
        popupMenu.add(new GoToNodeAction("hypersearch-results.open", M_OPEN));
        popupMenu.add(new GoToNodeAction("hypersearch-results.open-view", M_OPEN_NEW_VIEW));
        popupMenu.add(
            new GoToNodeAction("hypersearch-results.open-plain-view", M_OPEN_NEW_PLAIN_VIEW));
        popupMenu.add(new GoToNodeAction("hypersearch-results.open-split", M_OPEN_NEW_SPLIT));
      }
      if (!(userObj instanceof HyperSearchFolderNode)) popupMenu.add(new RemoveTreeNodeAction());
      popupMenu.add(new ExpandChildTreeNodesAction());
      if (userObj instanceof HyperSearchFolderNode || userObj instanceof HyperSearchOperationNode) {
        popupMenu.add(new CollapseChildTreeNodesAction());
        if (userObj instanceof HyperSearchFolderNode) popupMenu.add(new NewSearchAction());
      }
      if (userObj instanceof HyperSearchOperationNode) {
        popupMenu.add(new JPopupMenu.Separator());
        HyperSearchOperationNode resultNode = (HyperSearchOperationNode) userObj;
        JCheckBoxMenuItem chkItem =
            new JCheckBoxMenuItem(
                jEdit.getProperty("hypersearch-results.tree-view"),
                resultNode.isTreeViewDisplayed());
        chkItem.addActionListener(new TreeDisplayAction());
        popupMenu.add(chkItem);

        popupMenu.add(new RedoSearchAction((HyperSearchOperationNode) userObj));
      }
      popupMenu.add(new CopyToClipboardAction());

      GUIUtilities.showPopupMenu(popupMenu, evt.getComponent(), evt.getX(), evt.getY());
      evt.consume();
    } // }}}
Beispiel #22
0
 // {{{ mouseReleased() method
 @Override
 public void mouseReleased(MouseEvent evt) {
   if (!GUIUtilities.isPopupTrigger(evt) && table.getSelectedRow() != -1) {
     browser.filesSelected();
   }
 } // }}}
 Button(String actionName, String iconName, Icon icon, String label) {
   this.actionName = actionName;
   this.iconName = iconName;
   this.icon = icon;
   this.label = GUIUtilities.prettifyMenuLabel(label);
 }
  protected void _init() {
    setLayout(new BorderLayout());

    JPanel panel = new JPanel(new GridLayout(2, 1));

    showToolbar = new JCheckBox(jEdit.getProperty("options.toolbar.showToolbar"));
    showToolbar.setSelected(jEdit.getBooleanProperty("view.showToolbar"));
    panel.add(showToolbar);

    panel.add(new JLabel(jEdit.getProperty("options.toolbar.caption")));

    add(BorderLayout.NORTH, panel);

    String toolbar = jEdit.getProperty("view.toolbar");
    StringTokenizer st = new StringTokenizer(toolbar);
    listModel = new DefaultListModel();
    while (st.hasMoreTokens()) {
      String actionName = (String) st.nextToken();
      if (actionName.equals("-"))
        listModel.addElement(new ToolBarOptionPane.Button("-", null, null, "-"));
      else {
        EditAction action = jEdit.getAction(actionName);
        if (action == null) continue;
        String label = action.getLabel();
        if (label == null) continue;

        Icon icon;
        String iconName;
        if (actionName.equals("-")) {
          iconName = null;
          icon = null;
        } else {
          iconName = jEdit.getProperty(actionName + ".icon");
          if (iconName == null) icon = GUIUtilities.loadIcon("BrokenImage.png");
          else {
            icon = GUIUtilities.loadIcon(iconName);
            if (icon == null) icon = GUIUtilities.loadIcon("BrokenImage.png");
          }
        }
        listModel.addElement(new Button(actionName, iconName, icon, label));
      }
    }

    list = new JList(listModel);
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    list.addListSelectionListener(new ListHandler());
    list.setCellRenderer(new ButtonCellRenderer());

    add(BorderLayout.CENTER, new JScrollPane(list));

    JPanel buttons = new JPanel();
    buttons.setBorder(new EmptyBorder(3, 0, 0, 0));
    buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS));
    ActionHandler actionHandler = new ActionHandler();
    add = new RolloverButton(GUIUtilities.loadIcon("Plus.png"));
    add.setToolTipText(jEdit.getProperty("options.toolbar.add"));
    add.addActionListener(actionHandler);
    buttons.add(add);
    buttons.add(Box.createHorizontalStrut(6));
    remove = new RolloverButton(GUIUtilities.loadIcon("Minus.png"));
    remove.setToolTipText(jEdit.getProperty("options.toolbar.remove"));
    remove.addActionListener(actionHandler);
    buttons.add(remove);
    buttons.add(Box.createHorizontalStrut(6));
    moveUp = new RolloverButton(GUIUtilities.loadIcon("ArrowU.png"));
    moveUp.setToolTipText(jEdit.getProperty("options.toolbar.moveUp"));
    moveUp.addActionListener(actionHandler);
    buttons.add(moveUp);
    buttons.add(Box.createHorizontalStrut(6));
    moveDown = new RolloverButton(GUIUtilities.loadIcon("ArrowD.png"));
    moveDown.setToolTipText(jEdit.getProperty("options.toolbar.moveDown"));
    moveDown.addActionListener(actionHandler);
    buttons.add(moveDown);
    buttons.add(Box.createHorizontalStrut(6));
    edit = new RolloverButton(GUIUtilities.loadIcon("ButtonProperties.png"));
    edit.setToolTipText(jEdit.getProperty("options.toolbar.edit"));
    edit.addActionListener(actionHandler);
    buttons.add(edit);
    buttons.add(Box.createGlue());

    updateButtons();
    add(BorderLayout.SOUTH, buttons);

    iconList = new DefaultComboBoxModel();
    st = new StringTokenizer(jEdit.getProperty("icons"));
    while (st.hasMoreElements()) {
      String icon = st.nextToken();
      iconList.addElement(new IconListEntry(GUIUtilities.loadIcon(icon), icon));
    }
  }
 // {{{ ClearPluginSet constructor
 ClearPluginSet() {
   setIcon(GUIUtilities.loadIcon(jEdit.getProperty("install-plugins.clear-plugin-set.icon")));
   setToolTipText("clear plugin set");
   addActionListener(this);
 } // }}}
 // {{{ ChoosePluginSet constructor
 ChoosePluginSet() {
   setIcon(GUIUtilities.loadIcon(jEdit.getProperty("install-plugins.choose-plugin-set.icon")));
   addActionListener(this);
   updateUI();
 } // }}}
/** @version $Id: InstallPanel.java 20362 2011-11-17 08:23:36Z kpouer $ */
class InstallPanel extends JPanel implements EBComponent {

  // {{{ Variables
  private final JTable table;
  private final JScrollPane scrollpane;
  private final PluginTableModel pluginModel;
  private final PluginManager window;
  private final PluginInfoBox infoBox;
  private final ChoosePluginSet chooseButton;
  private final boolean updates;

  private final Collection<String> pluginSet = new HashSet<String>();
  // }}}

  // {{{ InstallPanel constructor
  InstallPanel(PluginManager window, boolean updates) {
    super(new BorderLayout(12, 12));

    this.window = window;
    this.updates = updates;

    setBorder(new EmptyBorder(12, 12, 12, 12));

    final JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
    split.setResizeWeight(0.75);
    /* Setup the table */
    table = new JTable(pluginModel = new PluginTableModel());
    table.setShowGrid(false);
    table.setIntercellSpacing(new Dimension(0, 0));
    table.setRowHeight(table.getRowHeight() + 2);
    table.setPreferredScrollableViewportSize(new Dimension(500, 200));
    table.setDefaultRenderer(
        Object.class,
        new TextRenderer((DefaultTableCellRenderer) table.getDefaultRenderer(Object.class)));
    table.addFocusListener(new TableFocusHandler());
    InputMap tableInputMap = table.getInputMap(JComponent.WHEN_FOCUSED);
    ActionMap tableActionMap = table.getActionMap();
    tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "tabOutForward");
    tableActionMap.put("tabOutForward", new KeyboardAction(KeyboardCommand.TAB_OUT_FORWARD));
    tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK), "tabOutBack");
    tableActionMap.put("tabOutBack", new KeyboardAction(KeyboardCommand.TAB_OUT_BACK));
    tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "editPlugin");
    tableActionMap.put("editPlugin", new KeyboardAction(KeyboardCommand.EDIT_PLUGIN));
    tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "closePluginManager");
    tableActionMap.put(
        "closePluginManager", new KeyboardAction(KeyboardCommand.CLOSE_PLUGIN_MANAGER));

    TableColumn col1 = table.getColumnModel().getColumn(0);
    TableColumn col2 = table.getColumnModel().getColumn(1);
    TableColumn col3 = table.getColumnModel().getColumn(2);
    TableColumn col4 = table.getColumnModel().getColumn(3);
    TableColumn col5 = table.getColumnModel().getColumn(4);

    col1.setPreferredWidth(30);
    col1.setMinWidth(30);
    col1.setMaxWidth(30);
    col1.setResizable(false);

    col2.setPreferredWidth(180);
    col3.setPreferredWidth(130);
    col4.setPreferredWidth(70);
    col5.setPreferredWidth(70);

    JTableHeader header = table.getTableHeader();
    header.setReorderingAllowed(false);
    header.addMouseListener(new HeaderMouseHandler());
    header.setDefaultRenderer(
        new HeaderRenderer((DefaultTableCellRenderer) header.getDefaultRenderer()));

    scrollpane = new JScrollPane(table);
    scrollpane.getViewport().setBackground(table.getBackground());
    split.setTopComponent(scrollpane);

    /* Create description */
    JScrollPane infoPane = new JScrollPane(infoBox = new PluginInfoBox());
    infoPane.setPreferredSize(new Dimension(500, 100));
    split.setBottomComponent(infoPane);

    EventQueue.invokeLater(
        new Runnable() {
          @Override
          public void run() {
            split.setDividerLocation(0.75);
          }
        });

    final JTextField searchField = new JTextField();
    searchField.addKeyListener(
        new KeyAdapter() {
          @Override
          public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_UP) {
              table.dispatchEvent(e);
              table.requestFocus();
            }
          }
        });
    searchField
        .getDocument()
        .addDocumentListener(
            new DocumentListener() {
              void update() {
                pluginModel.setFilterString(searchField.getText());
              }

              @Override
              public void changedUpdate(DocumentEvent e) {
                update();
              }

              @Override
              public void insertUpdate(DocumentEvent e) {
                update();
              }

              @Override
              public void removeUpdate(DocumentEvent e) {
                update();
              }
            });
    table.addKeyListener(
        new KeyAdapter() {
          @Override
          public void keyPressed(KeyEvent e) {
            int i = table.getSelectedRow(), n = table.getModel().getRowCount();
            if (e.getKeyCode() == KeyEvent.VK_DOWN && i == (n - 1)
                || e.getKeyCode() == KeyEvent.VK_UP && i == 0) {
              searchField.requestFocus();
              searchField.selectAll();
            }
          }
        });
    Box filterBox = Box.createHorizontalBox();
    filterBox.add(new JLabel("Filter : "));
    filterBox.add(searchField);
    add(BorderLayout.NORTH, filterBox);
    add(BorderLayout.CENTER, split);

    /* Create buttons */
    Box buttons = new Box(BoxLayout.X_AXIS);

    buttons.add(new InstallButton());
    buttons.add(Box.createHorizontalStrut(12));
    buttons.add(new SelectallButton());
    buttons.add(chooseButton = new ChoosePluginSet());
    buttons.add(new ClearPluginSet());
    buttons.add(Box.createGlue());
    buttons.add(new SizeLabel());

    add(BorderLayout.SOUTH, buttons);
    String path = jEdit.getProperty(PluginManager.PROPERTY_PLUGINSET, "");
    if (!path.isEmpty()) {
      loadPluginSet(path);
    }
  } // }}}

  // {{{ loadPluginSet() method
  /**
   * loads a pluginSet xml file and updates the model to reflect certain checked selections
   *
   * @since jEdit 4.3pre10
   * @author Alan Ezust
   */
  boolean loadPluginSet(String path) {
    pluginSet.clear();
    pluginModel.restoreSelection(new HashSet<String>(), new HashSet<String>());

    VFS vfs = VFSManager.getVFSForPath(path);
    Object session = vfs.createVFSSession(path, InstallPanel.this);
    try {
      InputStream is = vfs._createInputStream(session, path, false, InstallPanel.this);
      XMLUtilities.parseXML(is, new StringMapHandler());
    } catch (Exception e) {
      Log.log(Log.WARNING, this, "Loading Pluginset failed:" + e.getMessage());
      return false;
    }
    pluginModel.update();
    return true;
  } // }}}

  // {{{ updateModel() method
  public void updateModel() {
    final Set<String> savedChecked = new HashSet<String>();
    final Set<String> savedSelection = new HashSet<String>();
    pluginModel.saveSelection(savedChecked, savedSelection);
    pluginModel.clear();
    infoBox.setText(jEdit.getProperty("plugin-manager.list-download"));

    ThreadUtilities.runInDispatchThread(
        new Runnable() {
          @Override
          public void run() {
            infoBox.setText(null);
            pluginModel.update();
            pluginModel.restoreSelection(savedChecked, savedSelection);
          }
        });
  } // }}}

  // {{{ handleMessage() method
  @Override
  public void handleMessage(EBMessage message) {
    if (message.getSource() == PluginManager.getInstance()) {
      chooseButton.path = jEdit.getProperty(PluginManager.PROPERTY_PLUGINSET, "");
      if (chooseButton.path.length() > 0) {
        loadPluginSet(chooseButton.path);
        pluginModel.restoreSelection(new HashSet<String>(), new HashSet<String>());
        chooseButton.updateUI();
      }
    }
  } // }}}

  // {{{ Private members

  // {{{ formatSize() method
  private static String formatSize(int size) {
    NumberFormat df = NumberFormat.getInstance();
    df.setMaximumFractionDigits(1);
    df.setMinimumFractionDigits(0);
    String sizeText;
    if (size < 1048576) sizeText = (size >> 10) + "KB";
    else sizeText = df.format(size / 1048576.0d) + "MB";
    return sizeText;
  } // }}}

  // }}}

  // {{{ Inner classes

  // {{{ PluginTableModel class
  private class PluginTableModel extends AbstractTableModel {
    /** This List can contain String or Entry. */
    private final List entries = new ArrayList();

    private final List filteredEntries = new ArrayList();
    private int sortType = EntryCompare.COLUMN_NAME;
    private String filterString;
    int sortDirection = 1;

    // {{{ setFilterString() method
    public void setFilterString(String filterString) {
      this.filterString = filterString;
      updateFilteredEntries();
    } // }}}

    // {{{ updateFilteredEntries() method
    void updateFilteredEntries() {
      filteredEntries.clear();
      if (filterString == null) filteredEntries.addAll(entries);
      else {
        String[] words = filterString.toLowerCase().split("\\s+");
        for (Object o : entries) {
          if (!(o instanceof Entry)) continue;
          Entry e = (Entry) o;

          if (e.install) {
            filteredEntries.add(e);
            continue;
          }

          String s = (e.name + ' ' + e.set + ' ' + e.description).toLowerCase();
          boolean hasAll = true;
          boolean negative = false;
          for (String word : words) {
            if (word.startsWith("-")) {
              word = word.substring(1);
              negative = true;
            }
            if (word.length() == 0) continue;

            if (negative == s.contains(word)) {
              hasAll = false;
              break;
            }
            negative = false;
          }
          if (hasAll) filteredEntries.add(e);
        }
      }
      fireTableChanged(new TableModelEvent(PluginTableModel.this));
    } // }}}

    // {{{ getColumnClass() method
    @Override
    public Class getColumnClass(int columnIndex) {
      switch (columnIndex) {
        case 0:
          return Boolean.class;
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
          return Object.class;
        default:
          throw new Error("Column out of range");
      }
    } // }}}

    // {{{ getColumnCount() method
    @Override
    public int getColumnCount() {
      return 6;
    } // }}}

    // {{{ getColumnName() method
    @Override
    public String getColumnName(int column) {
      switch (column) {
        case 0:
          return " ";
        case 1:
          return ' ' + jEdit.getProperty("install-plugins.info.name");
        case 2:
          return ' ' + jEdit.getProperty("install-plugins.info.category");
        case 3:
          return ' ' + jEdit.getProperty("install-plugins.info.version");
        case 4:
          return ' ' + jEdit.getProperty("install-plugins.info.size");
        case 5:
          return ' ' + jEdit.getProperty("install-plugins.info.releaseDate");
        default:
          throw new Error("Column out of range");
      }
    } // }}}

    // {{{ getRowCount() method
    @Override
    public int getRowCount() {
      return filteredEntries.size();
    } // }}}

    // {{{ getValueAt() method
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
      Object obj = filteredEntries.get(rowIndex);
      if (obj instanceof String) {
        if (columnIndex == 1) return obj;
        else return null;
      } else {
        Entry entry = (Entry) obj;

        switch (columnIndex) {
          case 0:
            return entry.install;
          case 1:
            return entry.name;
          case 2:
            return entry.set;
          case 3:
            if (updates) return entry.installedVersion + "->" + entry.version;
            return entry.version;
          case 4:
            return formatSize(entry.size);
          case 5:
            return entry.date;
          default:
            throw new Error("Column out of range");
        }
      }
    } // }}}

    // {{{ isCellEditable() method
    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
      return columnIndex == 0;
    } // }}}

    // {{{ setSelectAll() method
    public void setSelectAll(boolean b) {
      if (isDownloadingList()) return;

      int length = getRowCount();
      for (int i = 0; i < length; i++) {
        if (b) setValueAt(Boolean.TRUE, i, 0);
        else {
          Entry entry = (Entry) filteredEntries.get(i);
          entry.parents = new LinkedList<Entry>();
          entry.install = false;
        }
      }
      fireTableChanged(new TableModelEvent(this));
    } // }}}

    // {{{ setSortType() method
    public void setSortType(int type) {
      sortType = type;
      sort(type);
    } // }}}

    // {{{ deselectParents() method
    private void deselectParents(Entry entry) {
      Entry[] parents = entry.getParents();

      if (parents.length == 0) return;

      String[] args = {entry.name};
      int result = GUIUtilities.listConfirm(window, "plugin-manager.dependency", args, parents);
      if (result != JOptionPane.OK_OPTION) {
        entry.install = true;
        return;
      }

      for (int i = 0; i < parents.length; i++) parents[i].install = false;

      fireTableRowsUpdated(0, getRowCount() - 1);
    } // }}}

    // {{{ setValueAt() method
    @Override
    public void setValueAt(Object aValue, int row, int column) {
      if (column != 0) return;

      Object obj = filteredEntries.get(row);
      if (obj instanceof String) return;

      Entry entry = (Entry) obj;
      boolean before = entry.install;
      entry.install = Boolean.TRUE.equals(aValue);
      if (before == entry.install) return;
      if (!entry.install) deselectParents(entry);

      List<PluginList.Dependency> deps = entry.plugin.getCompatibleBranch().deps;

      for (int i = 0; i < deps.size(); i++) {
        PluginList.Dependency dep = deps.get(i);
        if ("plugin".equals(dep.what)) {
          boolean found = false;
          for (int j = 0; j < filteredEntries.size(); j++) {
            Entry temp = (Entry) filteredEntries.get(j);
            if (temp.plugin == dep.plugin) {
              found = true;
              if (entry.install) {
                temp.parents.add(entry);
                setValueAt(Boolean.TRUE, j, 0);
              } else temp.parents.remove(entry);

              break;
            }
          }
          if (!found) {
            // the dependency was not found in the filtered list so we search in
            // global list.
            for (int a = 0; a < entries.size(); a++) {
              Entry temp = (Entry) entries.get(a);
              if (temp.plugin == dep.plugin) {
                if (entry.install) {
                  temp.parents.add(entry);
                  temp.install = true;
                } else temp.parents.remove(entry);
                break;
              }
            }
          }
        }
      }
      updateFilteredEntries();
    } // }}}

    // {{{ sort() method
    public void sort(int type) {
      Set<String> savedChecked = new HashSet<String>();
      Set<String> savedSelection = new HashSet<String>();
      saveSelection(savedChecked, savedSelection);

      if (sortType != type) {
        sortDirection = 1;
      }
      sortType = type;

      if (isDownloadingList()) return;

      Collections.sort(entries, new EntryCompare(type, sortDirection));
      updateFilteredEntries();
      restoreSelection(savedChecked, savedSelection);
      table.getTableHeader().repaint();
    }
    // }}}

    // {{{ isDownloadingList() method
    private boolean isDownloadingList() {
      return entries.size() == 1 && entries.get(0) instanceof String;
    } // }}}

    // {{{ clear() method
    public void clear() {
      entries.clear();
      updateFilteredEntries();
    } // }}}

    // {{{ update() method
    public void update() {
      Set<String> savedChecked = new HashSet<String>();
      Set<String> savedSelection = new HashSet<String>();
      saveSelection(savedChecked, savedSelection);

      PluginList pluginList = window.getPluginList();

      if (pluginList == null) return;

      entries.clear();

      for (int i = 0; i < pluginList.pluginSets.size(); i++) {
        PluginList.PluginSet set = pluginList.pluginSets.get(i);
        for (int j = 0; j < set.plugins.size(); j++) {
          PluginList.Plugin plugin = pluginList.pluginHash.get(set.plugins.get(j));
          PluginList.Branch branch = plugin.getCompatibleBranch();
          String installedVersion = plugin.getInstalledVersion();
          if (updates) {
            if (branch != null
                && branch.canSatisfyDependencies()
                && installedVersion != null
                && StandardUtilities.compareStrings(branch.version, installedVersion, false) > 0) {
              entries.add(new Entry(plugin, set.name));
            }
          } else {
            if (installedVersion == null && plugin.canBeInstalled())
              entries.add(new Entry(plugin, set.name));
          }
        }
      }

      sort(sortType);
      updateFilteredEntries();
      restoreSelection(savedChecked, savedSelection);
    } // }}}

    // {{{ saveSelection() method
    public void saveSelection(Set<String> savedChecked, Set<String> savedSelection) {
      if (entries.isEmpty()) return;
      for (int i = 0, c = getRowCount(); i < c; i++) {
        if ((Boolean) getValueAt(i, 0)) {
          savedChecked.add(filteredEntries.get(i).toString());
        }
      }
      int[] rows = table.getSelectedRows();
      for (int i = 0; i < rows.length; i++) {
        savedSelection.add(filteredEntries.get(rows[i]).toString());
      }
    } // }}}

    // {{{ restoreSelection() method
    public void restoreSelection(Set<String> savedChecked, Set<String> savedSelection) {
      for (int i = 0, c = getRowCount(); i < c; i++) {
        Object obj = filteredEntries.get(i);
        String name = obj.toString();
        if (obj instanceof Entry) {
          name = ((Entry) obj).plugin.jar;
        }
        if (pluginSet.contains(name)) setValueAt(true, i, 0);
        else setValueAt(savedChecked.contains(name), i, 0);
      }
      if (table == null) return;

      table.setColumnSelectionInterval(0, 0);
      if (!savedSelection.isEmpty()) {
        int i = 0;
        int rowCount = getRowCount();
        for (; i < rowCount; i++) {
          String name = filteredEntries.get(i).toString();
          if (savedSelection.contains(name)) {
            table.setRowSelectionInterval(i, i);
            break;
          }
        }
        ListSelectionModel lsm = table.getSelectionModel();
        for (; i < rowCount; i++) {
          String name = filteredEntries.get(i).toString();
          if (savedSelection.contains(name)) {
            lsm.addSelectionInterval(i, i);
          }
        }
      } else {
        if (table.getRowCount() != 0) table.setRowSelectionInterval(0, 0);
        JScrollBar scrollbar = scrollpane.getVerticalScrollBar();
        scrollbar.setValue(scrollbar.getMinimum());
      }
    } // }}}
  } // }}}

  // {{{ Entry class
  private static class Entry {
    String name, installedVersion, version, author, date, description, set;

    long timestamp;
    int size;
    boolean install;
    PluginList.Plugin plugin;
    List<Entry> parents = new LinkedList<Entry>();

    Entry(PluginList.Plugin plugin, String set) {
      PluginList.Branch branch = plugin.getCompatibleBranch();
      boolean downloadSource = jEdit.getBooleanProperty("plugin-manager.downloadSource");
      int size = downloadSource ? branch.downloadSourceSize : branch.downloadSize;

      this.name = plugin.name;
      this.author = plugin.author;
      this.installedVersion = plugin.getInstalledVersion();
      this.version = branch.version;
      this.size = size;
      this.date = branch.date;
      this.description = plugin.description;
      this.set = set;
      this.install = false;
      this.plugin = plugin;
      SimpleDateFormat format = new SimpleDateFormat("d MMMM yyyy", Locale.ENGLISH);
      try {
        timestamp = format.parse(date).getTime();
      } catch (ParseException e) {
        Log.log(Log.ERROR, this, e);
      }
    }

    private void getParents(List<Entry> list) {
      for (Entry entry : parents) {
        if (entry.install && !list.contains(entry)) {
          list.add(entry);
          entry.getParents(list);
        }
      }
    }

    Entry[] getParents() {
      List<Entry> list = new ArrayList<Entry>();
      getParents(list);
      Entry[] array = list.toArray(new Entry[list.size()]);
      Arrays.sort(array, new StandardUtilities.StringCompare<Entry>(true));
      return array;
    }

    @Override
    public String toString() {
      return name;
    }
  } // }}}

  // {{{ PluginInfoBox class
  /** @TODO refactor to use the PluginDetailPanel? */
  private class PluginInfoBox extends JTextPane implements ListSelectionListener {
    private final String[] params;

    PluginInfoBox() {
      setBackground(jEdit.getColorProperty("view.bgColor"));
      setForeground(jEdit.getColorProperty("view.fgColor"));
      putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, true);
      setEditable(false);
      setEditorKit(new HTMLEditorKit());
      //			setLineWrap(true);
      //			setWrapStyleWord(true);
      params = new String[3];
      table.getSelectionModel().addListSelectionListener(this);
    }

    @Override
    public void valueChanged(ListSelectionEvent e) {
      String text = "";
      if (table.getSelectedRowCount() == 1) {
        Entry entry = (Entry) pluginModel.filteredEntries.get(table.getSelectedRow());
        params[0] = entry.author;
        params[1] = entry.date;
        params[2] = entry.description;
        text = jEdit.getProperty("install-plugins.info", params);
        text = text.replace("\n", "<br>");
        text = "<html>" + text + "</html>";
      }
      setText(text);
      setCaretPosition(0);
    }
  } // }}}

  // {{{ SizeLabel class
  private class SizeLabel extends JLabel implements TableModelListener {
    private int size;
    private int nbPlugins;

    SizeLabel() {
      update();
      pluginModel.addTableModelListener(this);
    }

    @Override
    public void tableChanged(TableModelEvent e) {
      if (e.getType() == TableModelEvent.UPDATE) {
        if (pluginModel.isDownloadingList()) return;

        size = 0;
        nbPlugins = 0;
        int length = pluginModel.entries.size();
        for (int i = 0; i < length; i++) {
          Entry entry = (Entry) pluginModel.entries.get(i);
          if (entry.install) {
            nbPlugins++;
            size += entry.size;
          }
        }
        update();
      }
    }

    private void update() {
      Object[] args = {nbPlugins, formatSize(size)};
      setText(jEdit.getProperty("install-plugins.totalSize", args));
    }
  } // }}}

  // {{{ SelectallButton class
  private class SelectallButton extends JCheckBox implements ActionListener, TableModelListener {
    SelectallButton() {
      super(jEdit.getProperty("install-plugins.select-all"));
      addActionListener(this);
      pluginModel.addTableModelListener(this);
      setEnabled(false);
    }

    @Override
    public void actionPerformed(ActionEvent evt) {
      pluginModel.setSelectAll(isSelected());
    }

    @Override
    public void tableChanged(TableModelEvent e) {
      if (pluginModel.isDownloadingList()) return;

      setEnabled(pluginModel.getRowCount() != 0);
      if (e.getType() == TableModelEvent.UPDATE) {
        int length = pluginModel.getRowCount();
        for (int i = 0; i < length; i++)
          if (!((Boolean) pluginModel.getValueAt(i, 0)).booleanValue()) {
            setSelected(false);
            return;
          }
        if (length > 0) setSelected(true);
      }
    }
  } // }}}

  // {{{ StringMapHandler class
  /** For parsing the pluginset xml files into pluginSet */
  private class StringMapHandler extends DefaultHandler {
    StringMapHandler() {
      pluginSet.clear();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attrs)
        throws SAXException {
      if ("plugin".equals(localName)) {
        pluginSet.add(attrs.getValue("jar"));
      }
    }
  } // }}}

  // {{{ ChoosePluginSet class
  private class ChoosePluginSet extends RolloverButton implements ActionListener {
    private String path;

    // {{{ ChoosePluginSet constructor
    ChoosePluginSet() {
      setIcon(GUIUtilities.loadIcon(jEdit.getProperty("install-plugins.choose-plugin-set.icon")));
      addActionListener(this);
      updateUI();
    } // }}}

    // {{{ updateUI method
    @Override
    public void updateUI() {
      path = jEdit.getProperty(PluginManager.PROPERTY_PLUGINSET, "");
      if (path.length() < 1) setToolTipText("Click here to choose a predefined plugin set");
      else setToolTipText("Choose pluginset (" + path + ')');
      super.updateUI();
    } // }}}

    // {{{ actionPerformed() method
    @Override
    public void actionPerformed(ActionEvent ae) {

      path =
          jEdit.getProperty(
              PluginManager.PROPERTY_PLUGINSET, jEdit.getSettingsDirectory() + File.separator);
      String[] selectedFiles =
          GUIUtilities.showVFSFileDialog(
              InstallPanel.this.window, jEdit.getActiveView(), path, VFSBrowser.OPEN_DIALOG, false);
      if (selectedFiles == null || selectedFiles.length != 1) return;

      path = selectedFiles[0];
      boolean success = loadPluginSet(path);
      if (success) {
        jEdit.setProperty(PluginManager.PROPERTY_PLUGINSET, path);
      }
      updateUI();
    } // }}}
  } // }}}

  // {{{ ClearPluginSet class
  private class ClearPluginSet extends RolloverButton implements ActionListener {
    // {{{ ClearPluginSet constructor
    ClearPluginSet() {
      setIcon(GUIUtilities.loadIcon(jEdit.getProperty("install-plugins.clear-plugin-set.icon")));
      setToolTipText("clear plugin set");
      addActionListener(this);
    } // }}}

    // {{{ actionPerformed() method
    @Override
    public void actionPerformed(ActionEvent e) {
      pluginSet.clear();
      pluginModel.restoreSelection(new HashSet<String>(), new HashSet<String>());
      jEdit.unsetProperty(PluginManager.PROPERTY_PLUGINSET);
      chooseButton.updateUI();
    } // }}}
  } // }}}

  // {{{ InstallButton class
  private class InstallButton extends JButton implements ActionListener, TableModelListener {
    InstallButton() {
      super(jEdit.getProperty("install-plugins.install"));
      pluginModel.addTableModelListener(this);
      addActionListener(this);
      setEnabled(false);
    }

    @Override
    public void actionPerformed(ActionEvent evt) {
      if (pluginModel.isDownloadingList()) return;

      boolean downloadSource = jEdit.getBooleanProperty("plugin-manager.downloadSource");
      boolean installUser = jEdit.getBooleanProperty("plugin-manager.installUser");
      Roster roster = new Roster();
      String installDirectory;
      if (installUser) {
        installDirectory = MiscUtilities.constructPath(jEdit.getSettingsDirectory(), "jars");
      } else {
        installDirectory = MiscUtilities.constructPath(jEdit.getJEditHome(), "jars");
      }

      int length = pluginModel.entries.size();
      int instcount = 0;
      for (int i = 0; i < length; i++) {
        Entry entry = (Entry) pluginModel.entries.get(i);
        if (entry.install) {
          entry.plugin.install(roster, installDirectory, downloadSource);
          if (updates)
            entry
                .plugin
                .getCompatibleBranch()
                .satisfyDependencies(roster, installDirectory, downloadSource);
          instcount++;
        }
      }

      if (roster.isEmpty()) return;

      boolean cancel = false;
      if (updates && roster.getOperationCount() > instcount)
        if (GUIUtilities.confirm(
                window,
                "install-plugins.depend",
                null,
                JOptionPane.OK_CANCEL_OPTION,
                JOptionPane.WARNING_MESSAGE)
            == JOptionPane.CANCEL_OPTION) cancel = true;

      if (!cancel) {
        new PluginManagerProgress(window, roster);

        roster.performOperationsInAWTThread(window);
        pluginModel.update();
      }
    }

    @Override
    public void tableChanged(TableModelEvent e) {
      if (pluginModel.isDownloadingList()) return;

      if (e.getType() == TableModelEvent.UPDATE) {
        int length = pluginModel.getRowCount();
        for (int i = 0; i < length; i++)
          if (((Boolean) pluginModel.getValueAt(i, 0)).booleanValue()) {
            setEnabled(true);
            return;
          }
        setEnabled(false);
      }
    }
  } // }}}

  // {{{ EntryCompare class
  private static class EntryCompare implements Comparator<Entry> {
    private static final int COLUMN_INSTALL = 0;
    private static final int COLUMN_NAME = 1;
    private static final int COLUMN_CATEGORY = 2;
    private static final int COLUMN_VERSION = 3;
    private static final int COLUMN_SIZE = 4;
    private static final int COLUMN_RELEASE = 5;

    private final int type;

    /** 1=up, -1=down */
    private final int sortDirection;

    EntryCompare(int type, int sortDirection) {
      this.type = type;
      this.sortDirection = sortDirection;
    }

    @Override
    public int compare(Entry e1, Entry e2) {
      int result;

      switch (type) {
        case COLUMN_INSTALL:
          result = (e1.install == e2.install) ? 0 : (e1.install ? 1 : -1);
          break;
        case COLUMN_NAME:
          result = e1.name.compareToIgnoreCase(e2.name);
          break;
        case COLUMN_CATEGORY:
          result = e1.set.compareToIgnoreCase(e2.set);
          if (result == 0) {
            result = e1.name.compareToIgnoreCase(e2.name);
          }
          break;
        case COLUMN_VERSION:
          // lets avoid NPE. Maybe we should move
          // this code to StandardUtilities.compareStrings
          if (e1.version == e2.version) {
            result = 0;
          } else if (e1.version == null) {
            result = -1;
          } else if (e2.version == null) {
            result = 1;
          } else {
            result = StandardUtilities.compareStrings(e1.version, e2.version, true);
          }
          break;
        case COLUMN_SIZE:
          result = (e1.size < e2.size) ? -1 : ((e1.size == e2.size) ? 0 : 1);
          break;
        case COLUMN_RELEASE:
          result = (e1.timestamp < e2.timestamp) ? -1 : ((e1.timestamp == e2.timestamp) ? 0 : 1);
          break;
        default:
          result = 0;
      }
      return result * sortDirection;
    }
  } // }}}

  // {{{ HeaderMouseHandler class
  private class HeaderMouseHandler extends MouseAdapter {
    @Override
    public void mouseClicked(MouseEvent evt) {
      int column = table.getTableHeader().columnAtPoint(evt.getPoint());
      pluginModel.sortDirection *= -1;
      pluginModel.sort(column);
    }
  } // }}}

  // {{{ TextRenderer
  private static class TextRenderer extends DefaultTableCellRenderer {
    private final DefaultTableCellRenderer tcr;

    TextRenderer(DefaultTableCellRenderer tcr) {
      this.tcr = tcr;
    }

    @Override
    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
      if (column == 5) tcr.setHorizontalAlignment(TRAILING);
      else tcr.setHorizontalAlignment(LEADING);
      return tcr.getTableCellRendererComponent(table, value, isSelected, false, row, column);
    }
  } // }}}

  // {{{ KeyboardAction class
  private class KeyboardAction extends AbstractAction {
    private KeyboardCommand command = KeyboardCommand.NONE;

    KeyboardAction(KeyboardCommand command) {
      this.command = command;
    }

    @Override
    public void actionPerformed(ActionEvent evt) {
      switch (command) {
        case TAB_OUT_FORWARD:
          KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
          break;
        case TAB_OUT_BACK:
          KeyboardFocusManager.getCurrentKeyboardFocusManager().focusPreviousComponent();
          break;
        case EDIT_PLUGIN:
          int[] rows = table.getSelectedRows();
          Object[] state = new Object[rows.length];
          for (int i = 0; i < rows.length; i++) {
            state[i] = pluginModel.getValueAt(rows[i], 0);
          }
          for (int i = 0; i < rows.length; i++) {
            pluginModel.setValueAt(state[i].equals(Boolean.FALSE), rows[i], 0);
          }
          break;
        case CLOSE_PLUGIN_MANAGER:
          window.ok();
          break;
        default:
          throw new InternalError();
      }
    }
  } // }}}

  // {{{ TableFocusHandler class
  private class TableFocusHandler extends FocusAdapter {
    @Override
    public void focusGained(FocusEvent fe) {
      if (-1 == table.getSelectedRow() && table.getRowCount() > 0) {
        table.setRowSelectionInterval(0, 0);
        JScrollBar scrollbar = scrollpane.getVerticalScrollBar();
        scrollbar.setValue(scrollbar.getMinimum());
      }
      if (-1 == table.getSelectedColumn()) {
        table.setColumnSelectionInterval(0, 0);
      }
    }
  } // }}}

  // {{{ HeaderRenderer
  private static class HeaderRenderer extends DefaultTableCellRenderer {
    private final DefaultTableCellRenderer tcr;

    HeaderRenderer(DefaultTableCellRenderer tcr) {
      this.tcr = tcr;
    }

    @Override
    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
      JLabel l =
          (JLabel)
              tcr.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
      PluginTableModel model = (PluginTableModel) table.getModel();
      Icon icon =
          (column == model.sortType) ? (model.sortDirection == 1) ? ASC_ICON : DESC_ICON : null;
      l.setIcon(icon);
      // l.setHorizontalTextPosition(l.LEADING);
      return l;
    }
  } // }}}

  // }}}

  static final Icon ASC_ICON = GUIUtilities.loadIcon("arrow-asc.png");
  static final Icon DESC_ICON = GUIUtilities.loadIcon("arrow-desc.png");
}
  /**
   * Finds the next occurrence of the search string.
   *
   * @param view The view
   * @return True if the operation was successful, false otherwise
   */
  public static boolean find(View view) {
    // component that will parent any dialog boxes
    Component comp = SearchDialog.getSearchDialog(view);
    if (comp == null || !comp.isShowing()) comp = view;

    String path = fileset.getNextFile(view, null);
    if (path == null) {
      GUIUtilities.error(comp, "empty-fileset", null);
      return false;
    }

    try {
      view.showWaitCursor();

      SearchMatcher matcher = getSearchMatcher();
      if (matcher == null) {
        view.getToolkit().beep();
        return false;
      }

      record(view, "find(view)", false, true);

      boolean repeat = false;
      loop:
      for (; ; ) {
        while (path != null) {
          Buffer buffer = jEdit.openTemporary(view, null, path, false);

          /* this is stupid and misleading.
           * but 'path' is not used anywhere except
           * the above line, and if this is done
           * after the 'continue', then we will
           * either hang, or be forced to duplicate
           * it inside the buffer == null, or add
           * a 'finally' clause. you decide which one's
           * worse. */
          if (reverse) {
            path = fileset.getPrevFile(view, path);
          } else {
            path = fileset.getNextFile(view, path);
          }

          if (buffer == null) continue loop;

          // Wait for the buffer to load
          if (!buffer.isLoaded()) VFSManager.waitForRequests();

          int start;

          if (view.getBuffer() == buffer && !repeat) {
            JEditTextArea textArea = view.getTextArea();
            Selection s = textArea.getSelectionAtOffset(textArea.getCaretPosition());
            if (s == null) start = textArea.getCaretPosition();
            else if (reverse) start = s.getStart();
            else start = s.getEnd();
          } else if (reverse) start = buffer.getLength();
          else start = 0;

          if (find(view, buffer, start, repeat, reverse)) return true;
        }

        if (repeat) {
          if (!BeanShell.isScriptRunning()) {
            view.getStatus().setMessageAndClear(jEdit.getProperty("view.status.search-not-found"));

            view.getToolkit().beep();
          }
          return false;
        }

        boolean restart;

        // if auto wrap is on, always restart search.
        // if auto wrap is off, and we're called from
        // a macro, stop search. If we're called
        // interactively, ask the user what to do.
        if (wrap) {
          if (!BeanShell.isScriptRunning()) {
            view.getStatus().setMessageAndClear(jEdit.getProperty("view.status.auto-wrap"));
            // beep if beep property set
            if (jEdit.getBooleanProperty("search.beepOnSearchAutoWrap")) {
              view.getToolkit().beep();
            }
          }
          restart = true;
        } else if (BeanShell.isScriptRunning()) {
          restart = false;
        } else {
          Integer[] args = {Integer.valueOf(reverse ? 1 : 0)};
          int result =
              GUIUtilities.confirm(
                  comp,
                  "keepsearching",
                  args,
                  JOptionPane.YES_NO_OPTION,
                  JOptionPane.QUESTION_MESSAGE);
          restart = (result == JOptionPane.YES_OPTION);
        }

        if (restart) {
          // start search from beginning
          path = fileset.getFirstFile(view);
          repeat = true;
        } else break loop;
      }
    } catch (Exception e) {
      handleError(comp, e);
    } finally {
      view.hideWaitCursor();
    }

    return false;
  } // }}}
  public ToolBarEditDialog(
      Component comp, DefaultComboBoxModel iconListModel, ToolBarOptionPane.Button current) {
    super(
        GUIUtilities.getParentDialog(comp), jEdit.getProperty("options.toolbar.edit.title"), true);

    JPanel content = new JPanel(new BorderLayout());
    content.setBorder(new EmptyBorder(12, 12, 12, 12));
    setContentPane(content);

    ActionHandler actionHandler = new ActionHandler();
    ButtonGroup grp = new ButtonGroup();

    JPanel typePanel = new JPanel(new GridLayout(3, 1, 6, 6));
    typePanel.setBorder(new EmptyBorder(0, 0, 6, 0));
    typePanel.add(new JLabel(jEdit.getProperty("options.toolbar.edit.caption")));

    separator = new JRadioButton(jEdit.getProperty("options.toolbar" + ".edit.separator"));
    separator.addActionListener(actionHandler);
    grp.add(separator);
    typePanel.add(separator);

    action = new JRadioButton(jEdit.getProperty("options.toolbar" + ".edit.action"));
    action.addActionListener(actionHandler);
    grp.add(action);
    typePanel.add(action);

    content.add(BorderLayout.NORTH, typePanel);

    JPanel actionPanel = new JPanel(new BorderLayout(6, 6));

    ActionSet[] actionsList = jEdit.getActionSets();
    Vector vec = new Vector(actionsList.length);
    for (int i = 0; i < actionsList.length; i++) {
      ActionSet actionSet = actionsList[i];
      if (actionSet.getActionCount() != 0) vec.addElement(actionSet);
    }
    combo = new JComboBox(vec);
    combo.addActionListener(actionHandler);
    actionPanel.add(BorderLayout.NORTH, combo);

    list = new JList();
    list.setVisibleRowCount(8);
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    actionPanel.add(BorderLayout.CENTER, new JScrollPane(list));

    JPanel iconPanel = new JPanel(new BorderLayout(0, 3));
    JPanel labelPanel = new JPanel(new GridLayout(2, 1));
    labelPanel.setBorder(new EmptyBorder(0, 0, 0, 12));
    JPanel compPanel = new JPanel(new GridLayout(2, 1));
    grp = new ButtonGroup();
    labelPanel.add(builtin = new JRadioButton(jEdit.getProperty("options.toolbar.edit.builtin")));
    builtin.addActionListener(actionHandler);
    grp.add(builtin);
    labelPanel.add(file = new JRadioButton(jEdit.getProperty("options.toolbar.edit.file")));
    grp.add(file);
    file.addActionListener(actionHandler);
    iconPanel.add(BorderLayout.WEST, labelPanel);
    builtinCombo = new JComboBox(iconListModel);
    builtinCombo.setRenderer(new ToolBarOptionPane.IconCellRenderer());
    compPanel.add(builtinCombo);

    fileButton = new JButton(jEdit.getProperty("options.toolbar.edit.no-icon"));
    fileButton.setMargin(new Insets(1, 1, 1, 1));
    fileButton.setIcon(GUIUtilities.loadIcon("Blank24.gif"));
    fileButton.setHorizontalAlignment(SwingConstants.LEFT);
    fileButton.addActionListener(actionHandler);
    compPanel.add(fileButton);
    iconPanel.add(BorderLayout.CENTER, compPanel);
    actionPanel.add(BorderLayout.SOUTH, iconPanel);

    content.add(BorderLayout.CENTER, actionPanel);

    JPanel southPanel = new JPanel();
    southPanel.setLayout(new BoxLayout(southPanel, BoxLayout.X_AXIS));
    southPanel.setBorder(new EmptyBorder(12, 0, 0, 0));
    southPanel.add(Box.createGlue());
    ok = new JButton(jEdit.getProperty("common.ok"));
    ok.addActionListener(actionHandler);
    getRootPane().setDefaultButton(ok);
    southPanel.add(ok);
    southPanel.add(Box.createHorizontalStrut(6));
    cancel = new JButton(jEdit.getProperty("common.cancel"));
    cancel.addActionListener(actionHandler);
    southPanel.add(cancel);
    southPanel.add(Box.createGlue());

    content.add(BorderLayout.SOUTH, southPanel);

    if (current == null) {
      action.setSelected(true);
      builtin.setSelected(true);
      updateList();
    } else {
      if (current.actionName.equals("-")) {
        separator.setSelected(true);
        builtin.setSelected(true);
      } else {
        action.setSelected(true);
        ActionSet set = jEdit.getActionSetForAction(current.actionName);
        combo.setSelectedItem(set);
        updateList();
        list.setSelectedValue(current, true);

        if (MiscUtilities.isURL(current.iconName)) {
          file.setSelected(true);
          fileIcon = current.iconName;
          try {
            fileButton.setIcon(new ImageIcon(new URL(fileIcon)));
          } catch (MalformedURLException mf) {
            Log.log(Log.ERROR, this, mf);
          }
          fileButton.setText(MiscUtilities.getFileName(fileIcon));
        } else {
          String iconName = MiscUtilities.getFileName(current.iconName);
          builtin.setSelected(true);
          ListModel model = builtinCombo.getModel();
          for (int i = 0; i < model.getSize(); i++) {
            ToolBarOptionPane.IconListEntry entry =
                (ToolBarOptionPane.IconListEntry) model.getElementAt(i);
            if (entry.name.equals(iconName)) {
              builtinCombo.setSelectedIndex(i);
              break;
            }
          }
        }
      }
    }

    updateEnabled();

    pack();
    setLocationRelativeTo(GUIUtilities.getParentDialog(comp));
    show();
  }
  /**
   * Replaces all occurrences of the search string with the replacement string.
   *
   * @param view The view
   * @param dontOpenChangedFiles Whether to open changed files or to autosave them quietly
   * @return the number of modified files
   */
  public static boolean replaceAll(View view, boolean dontOpenChangedFiles) {
    // component that will parent any dialog boxes
    Component comp = SearchDialog.getSearchDialog(view);
    if (comp == null) comp = view;

    if (fileset.getFileCount(view) == 0) {
      GUIUtilities.error(comp, "empty-fileset", null);
      return false;
    }

    record(view, "replaceAll(view)", true, true);

    view.showWaitCursor();

    boolean smartCaseReplace = getSmartCaseReplace();

    int fileCount = 0;
    int occurCount = 0;
    try {
      SearchMatcher matcher = getSearchMatcher();
      if (matcher == null) return false;

      initReplace();

      String path = fileset.getFirstFile(view);
      loop:
      while (path != null) {
        Buffer buffer = jEdit.openTemporary(view, null, path, false);

        /* this is stupid and misleading.
         * but 'path' is not used anywhere except
         * the above line, and if this is done
         * after the 'continue', then we will
         * either hang, or be forced to duplicate
         * it inside the buffer == null, or add
         * a 'finally' clause. you decide which one's
         * worse. */
        path = fileset.getNextFile(view, path);

        if (buffer == null) continue loop;

        // Wait for buffer to finish loading
        if (buffer.isPerformingIO()) VFSManager.waitForRequests();

        if (!buffer.isEditable()) continue loop;

        // Leave buffer in a consistent state if
        // an error occurs
        int retVal = 0;

        try {
          buffer.beginCompoundEdit();
          retVal = _replace(view, buffer, matcher, 0, buffer.getLength(), smartCaseReplace);
        } finally {
          buffer.endCompoundEdit();
        }

        if (retVal != 0) {
          fileCount++;
          occurCount += retVal;
          if (dontOpenChangedFiles) {
            buffer.save(null, null);
          } else {
            jEdit.commitTemporary(buffer);
            jEdit.getBufferSetManager().addBuffer(view, buffer);
          }
        }
      }
    } catch (Exception e) {
      handleError(comp, e);
    } finally {
      view.hideWaitCursor();
    }

    /* Don't do this when playing a macro, cos it's annoying */
    if (!BeanShell.isScriptRunning()) {
      Object[] args = {Integer.valueOf(occurCount), Integer.valueOf(fileCount)};
      view.getStatus().setMessageAndClear(jEdit.getProperty("view.status.replace-all", args));
      if (occurCount == 0) view.getToolkit().beep();
    }

    return (fileCount != 0);
  } // }}}