/* A BeanShell macro script to search and open a recent file or a file in the current directory. * * * * This Script is a modification of Recent_Files.bsh, written by * Jeroen Budts and Ollie Rutherfurd. * Copyright (C) 2001-2004 Ollie Rutherfurd, oliver@rutherfurd.net * Modified by AhLeung Cheng * * {{{ License * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with the jEdit program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ import java.util.regex.Pattern; class Entry { Entry(String p, Icon i) { int sep = p.lastIndexOf(File.separator)+1; name = p.substring(sep); dir = p.substring(0, sep); icon = i; } String name, dir; Icon icon; } BufferCellRenderer() { Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Entry v = (Entry)value; l = new JLabel(""+v.name+" "+v.dir+""); l.setOpaque(true); l.setIcon(v.icon); l.setBorder(new javax.swing.border.EmptyBorder(2,2,2,2)); if (isSelected) { l.setBackground(list.getSelectionBackground()); l.setForeground(list.getSelectionForeground()); } return l; } return this; } SearchRecentAndCurrentDirDialog(doModal, dialogDimension) { JList fileList = new JList(); JTextField textField = new JTextField(); textField.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "esc"); textField.getActionMap().put("esc", new AbstractAction() { public void actionPerformed(ActionEvent e) { dialog.dispose(); }} ); textField.getActionMap().put("up", new AbstractAction() { public void actionPerformed(ActionEvent e) { move(-1); }} ); textField.getActionMap().put("down", new AbstractAction() { public void actionPerformed(ActionEvent e) { move(1); }} ); JPanel content = new JPanel(new BorderLayout()); content.add(textField, BorderLayout.NORTH); content.add(new JScrollPane(fileList), BorderLayout.CENTER); dialog = new JDialog(view, doModal); dialog.setContentPane(content); dialog.setSize(dialogDimension); dialog.setLocationRelativeTo(view); dialog.setVisible(true); SwingUtilities.invokeLater(this); // i.e., the run() method will be invoked later void move(int d) { int len = fileList.getModel().getSize(); int i = (fileList.getSelectedIndex() + len + d) % len; fileList.setSelectedIndex(i); fileList.ensureIndexIsVisible(i); } void actionPerformed(ActionEvent e) { if (textField.getText().startsWith(":")) { // if input starts with ':', go to that line line = Integer.parseInt(textField.getText().substring(1)); if ((line < 1) || (line > buffer.getLineCount())) view.getToolkit().beep(); // ref: http://community.jedit.org/?q=node/view/2609 else textArea.setCaretPosition(textArea.getLineStartOffset(line - 1)); } else { Entry f = fileList.getSelectedValue(); jEdit.openFile(view, f.dir+f.name); } dialog.dispose(); } // DocumentListener void changedUpdate(e) {} void removeUpdate(e) { SwingUtilities.invokeLater(this); } void insertUpdate(e) { SwingUtilities.invokeLater(this); } // MouseListener void mouseEntered(e) {} void mouseExited(e) {} void mousePressed(e) {} void mouseReleased(e) {} void mouseClicked(e) { if (SwingUtilities.isLeftMouseButton(e)) { actionPerformed(null); } } Vector allEntries = null; String keyword = null; void run() { if (allEntries==null) { // initialize the list here to speed up dialog display time HashMap icons = new HashMap(); for (Buffer b:jEdit.getBuffers()) icons.put(b.getPath(), b.getIcon()); List historyList = BufferHistory.getHistory(); allEntries = new Vector(historyList.size() + 100); final Icon emptyIcon = new Icon() { int getIconHeight() { return 10; } int getIconWidth() { return 10; } void paintIcon(Component c, Graphics g, int x, int y) {}}; final Icon dotIcon = new Icon() { int getIconHeight() { return 10; } int getIconWidth() { return 10; } void paintIcon(Component c, Graphics g, int x, int y) { g.setColor(Color.black); g.fillOval(x+4, y+4, 2, 2); }}; for (BufferHistory.Entry h:historyList) { Icon icon = icons.get(h.path); allEntries.add(new Entry(h.path, icon==null? emptyIcon:icon)); if (icon==null) icons.put(h.path, null); // to avoid duplicated entry when adding current dir files } for (f : new File(buffer.getDirectory()).listFiles()) { // TODO: use file filter? http://www.avajava.com/tutorials/lessons/how-do-i-use-a-filefilter-to-display-only-the-directories-within-a-directory.html if (!f.isDirectory()) { p = f.getCanonicalPath(); if (!icons.containsKey(p)) allEntries.add(new Entry(p, dotIcon)); } } textField.setFocusTraversalKeysEnabled(false); // to capture TAB and S+TAB im = textField.getInputMap(); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "down"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK), "up"); im.put(KeyStroke.getKeyStroke("DOWN"), "down"); im.put(KeyStroke.getKeyStroke("UP"), "up"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_J, InputEvent.CTRL_DOWN_MASK), "down"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_J, InputEvent.ALT_DOWN_MASK), "down"); // support both CTRL and ALT im.put(KeyStroke.getKeyStroke(KeyEvent.VK_K, InputEvent.CTRL_DOWN_MASK), "up"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_K, InputEvent.ALT_DOWN_MASK), "up"); textField.getDocument().addDocumentListener(this); textField.addActionListener(this); fileList.setCellRenderer(BufferCellRenderer()); fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); fileList.addMouseListener(this); } if (textField.getText().equals(keyword)) return; keyword = textField.getText(); if (keyword.equals("")) { fileList.setListData(allEntries); fileList.setSelectedIndex(1); // initially select the next recent buffer } else { Vector v = new Vector(); for (Entry f:allEntries) if (Pattern.compile(Pattern.quote(keyword), Pattern.CASE_INSENSITIVE).matcher(f.name).find()) v.add(f); fileList.setListData(v); // ref: JList.setListData threading issues http://stackoverflow.com/questions/4547113 fileList.setSelectedIndex(0); // select the top match } }; } SearchRecentAndCurrentDirDialog(false, new Dimension(700, 600));