import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; import javax.swing.*; import org.gjt.sp.jedit.*; import projectviewer.*; import projectviewer.vpt.*; int minimumAmountOfFiles = 2; // minimum amount of files needed in a project to allow searching int charTrigger = 2; // minimum amount of characters to trigger the search (probably 1 or 2) int maxDialogWidth = 700; // window width int maxDialogHeight = 300; // window height String regexpStarterChar = ">"; // very first character; triggers regexp parsing; very slow! String postDisplayFilterChar = "*"; // triggers a secondary filter (only for the display part, will not affect speed) String pathSplitterSequence = " | "; // separate filename from path part in the jlist with this string // TODO: clean up!!! // dock manager DockableWindowManager dwm = view.getDockableWindowManager(); if (dwm == null) { Macros.message(view, "Could not get the dockable window manager."); return; } // get the pv doc ProjectViewer pv = (ProjectViewer) dwm.getDockable("projectviewer"); if (pv == null) { Macros.message(view, "Could not get the project viewer window."); return; } // a project seems to be selected, but is this a root node? VPTNode node = pv.getSelectedNode(); rootNode = pv.getRoot(); if ((node != null) && (node.isProject())) rootNode = node; // is a node selected? if (!rootNode.isProject()) { Macros.message(view, "Please select a project in the dropdown... you're in " + rootNode.getName()); return; } // everything's okay, but do we have enough files? Collection openableNodes = rootNode.getOpenableNodes(); if (openableNodes.size() < minimumAmountOfFiles) { Macros.message(view, "This project doesn't have enough files..."); return; } String rootPath = rootNode.getNodePath(); String previousWord = ""; //read all paths, put them into an arraylist and then sort it ArrayList origFilePaths = new ArrayList(); ArrayList fileNameAL = new ArrayList(); ArrayList searchAL = new ArrayList(fileNameAL); for (Iterator iter = openableNodes.iterator(); iter.hasNext();) { VPTNode actNode = (VPTNode) iter.next(); String purePath = actNode.getNodePath() .replaceAll(Pattern.quote(rootPath), "") .replaceAll(Pattern.quote(actNode.getName()), ""); fileNameAL.add(actNode.getName() + pathSplitterSequence + purePath); //origFilePaths.add(actNode.getNodePath());//errm, sorry } Collections.sort(fileNameAL, String.CASE_INSENSITIVE_ORDER); //create the swing jlist + a scrollpane //JList swingList = new JList(fileNameAL.toArray()); DefaultListModel model = new DefaultListModel(); JList swingList = new JList(model); swingList.setFixedCellWidth(400); Font slDisplayFont = new Font("Monospaced", Font.PLAIN, 12); swingList.setFont(slDisplayFont); swingList.setSelectedIndex(0); JScrollPane scrollPane = new JScrollPane(swingList); //the opener (opens the file in the editor; not very nice) void openMessedUpFile(view, messedUpValue, pathSplitterSequence, rootPath) { String[] fileNameParts = messedUpValue.split(Pattern.quote(pathSplitterSequence)); realFinalName = rootPath + fileNameParts[1] + fileNameParts[0]; jEdit.openFile(view, realFinalName); } //create main window - mostly copy pasted from here and there String baseWindowTitle = rootNode.getName(); JDialog dialogBox = new JDialog(view, baseWindowTitle + " [" + fileNameAL.size() + "]", true); Container c = dialogBox.getContentPane(); //mainInput JTextField mainInput = new JTextField(); mainInput.setColumns(10); boolean processed = false; KeyListener mainKeyListener = new KeyListener() { public void keyPressed(KeyEvent e) { processed = false; if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { processed = true; dialogBox.setVisible(false); } else if (e.getKeyCode() == KeyEvent.VK_UP) { processed = true; swingList.processKeyEvent(e); } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { processed = true; swingList.processKeyEvent(e); } else if (e.getKeyCode() == KeyEvent.VK_ENTER) { processed = true; selInd = swingList.getSelectedIndex(); if (selInd > -1) { openMessedUpFile(view, swingList.getSelectedValue(), pathSplitterSequence, rootPath); dialogBox.setVisible(false); } } else if (e.getKeyCode() == KeyEvent.VK_PAGE_UP) {//todo swingList.setSelectedIndex(0); swingList.ensureIndexIsVisible(0); processed = true; } else if (e.getKeyCode() == KeyEvent.VK_PAGE_DOWN) { selInd = swingList.getModel().getSize() - 1; swingList.setSelectedIndex(selInd); swingList.ensureIndexIsVisible(selInd); processed = true; } } public void keyReleased(KeyEvent e) { if (processed) return; swingList.processKeyEvent(e); desSelIdx = -1; typedText = mainInput.getText(); pat1 = null; String postDisplayFilter = null; sensitivity = Pattern.CASE_INSENSITIVE; if ((postDisplayFilterChar != null) && (typedText.indexOf(postDisplayFilterChar) > -1)) { Pattern splitPat = Pattern.compile(postDisplayFilterChar, Pattern.LITERAL); String[] result = splitPat.split(typedText); if ((result.length > 1) && (!result[0].equals(regexpStarterChar))) { typedText = result[0]; if (!result[1].equals("")) { postDisplayFilter = result[1]; } else { } } Matcher repMat = splitPat.matcher(typedText); typedText = repMat.replaceAll("");//throw away all * } if (typedText.length() < charTrigger) { if (model.size() > 0) { model.clear(); } return; } //make search case sensitive if we have capitals if (!typedText.equals(typedText.toLowerCase())) { sensitivity = 0; } //regexp if first char is > if ((typedText != null) &&(!typedText.equals("")) && (typedText.substring(0,1).equals(regexpStarterChar))) { typedText = typedText.substring(1); pat1 = Pattern.compile(typedText, sensitivity); } actName = ""; // if not regexp, then reuse the previous resultset for this search if (pat1 == null) { //if it is the continuation of the previously started word if ((!previousWord.equals("")) && (typedText.indexOf(previousWord) > -1)) { //Macros.message(view, intToStr(searchAL.size())); } else { searchAL = new ArrayList(fileNameAL); } previousWord = typedText; } else { // this means that regexp works, but since it ignores previous resultsets, it's slow as hell... previousWord = ""; searchAL = new ArrayList(fileNameAL); } //this is quite terribly slow model.clear(); searchALSize = searchAL.size(); int addedCount = 0; int i = 0; ArrayList selectedItems = new ArrayList(); while (!(i == searchALSize)) { actName = searchAL.get(i); actNameCopy = actName; if (pat1 == null) { if (sensitivity != 0) { actNameCopy = actName.toLowerCase(); } matchPoint = actNameCopy.indexOf(typedText); if (matchPoint == 0) {//at the very beginning desSelIdx = i; //break; } else if ((matchPoint > -1) && (desSelIdx == -1)) {//somewhere in the text desSelIdx = i; //break; } } else {//regexp matcher1 = pat1.matcher(actNameCopy); if (matcher1.matches()) { desSelIdx = i; //break; } } //add to the list if (desSelIdx > -1) { selectedItems.add(actName); if (postDisplayFilter != null) { if (actNameCopy.indexOf(postDisplayFilter) > -1) { model.add(model.size(), actName); } } else { model.add(model.size(), actName); } addedCount++; } desSelIdx = -1; i++; } // if we have less selecteditems than we have in the search-arraylist // then use this for the next search (same as removing the unneeded items) if (selectedItems.size() < searchALSize) { searchAL = new ArrayList(selectedItems); } dialogBox.setTitle(baseWindowTitle + " [" + addedCount + "]"); if (desSelIdx > -1) { //swingList.setSelectedIndex(desSelIdx); //swingList.ensureIndexIsVisible(desSelIdx); } } public void keyTyped(KeyEvent keyEvent) {} }; mainInput.addKeyListener(mainKeyListener); //swinglist listener (simple + click) KeyListener swingListKeyListener = new KeyListener() { public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { dialogBox.setVisible(false); } else if (e.getKeyCode() == KeyEvent.VK_ENTER) { openMessedUpFile(view, swingList.getSelectedValue(), pathSplitterSequence, rootPath); dialogBox.setVisible(false); } } public void keyReleased(KeyEvent e) {} public void keyTyped(KeyEvent keyEvent) {} }; MouseListener mouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { int index = swingList.locationToIndex(e.getPoint()); openMessedUpFile(view, swingList.getSelectedValue(), pathSplitterSequence, rootPath); dialogBox.setVisible(false); } } }; swingList.addMouseListener(mouseListener); swingList.addKeyListener(swingListKeyListener); c.setPreferredSize(new Dimension(maxDialogWidth, maxDialogHeight)); c.add(mainInput, "North"); c.add(scrollPane, "Center"); dialogBox.pack(); dialogBox.setLocationRelativeTo(view); dialogBox.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); dialogBox.setVisible(true);