Windows application with Auto-complete using tab of unix machine files and directories

前端 未结 1 2045
刺人心
刺人心 2021-01-29 04:38

Unix / Linux support auto-complete of files and directories when pressing \"tab\". I need to create this ability in my windows application. I have a text field for user input of

相关标签:
1条回答
  • 2021-01-29 05:36

    First you want to have a text field without focus cycling, and tab suppression:

    jTextField1.setFocusCycleRoot(true);
    jTextField1.setFocusTraversalKeysEnabled(false);       
    

    Then a data model for the files (here local directory, but SSH is likewise):

    private File dir = new File("C:/Work");
    private String typedPrefix = null;
    private List<String> filesWithPrefix = new ArrayList<>();
    

    Then a key pressed handling for the TAB:

    • Consume the event.
    • Get the prefix upto the caret for searching file names.
    • If you merely need to restrict already found file names, so do, otherwise physical search them.
    • Look for the longest common prefix in the file names. Display that.

      private void jTextField1KeyPressed(java.awt.event.KeyEvent evt) {
      System.out.println("KeyPressed " + evt);
      
      if (evt.getKeyCode() == KeyEvent.VK_TAB) {
          evt.consume();
      
          int caretPos = jTextField1.getCaretPosition();
          try {
              final String newPrefix = jTextField1.getText(0, caretPos);
              System.out.println("newPrefix: " + newPrefix);
              if (!newPrefix.isEmpty()) {
                  if (typedPrefix == null || !newPrefix.startsWith(typedPrefix)) {
                      // Must physically reload possible values:
                      String[] fileNames = dir.list(new FilenameFilter() {
      
                          @Override
                          public boolean accept(File dir, String name) {
                              return name.startsWith(newPrefix);
                          }
                      });
                      filesWithPrefix.clear();
                      Collections.addAll(filesWithPrefix, fileNames);
                      typedPrefix = newPrefix;
                  } else {
                      // Can reduce prior selection:
                      for (ListIterator<String> it = filesWithPrefix.listIterator(); it.hasNext(); ) {
                          String fileName = it.next();
                          if (!fileName.startsWith(newPrefix)) {
                              it.remove();
                          }
                      }
                      typedPrefix = newPrefix;
                  }
                  System.out.println("filesWithPrefix: " +filesWithPrefix);
                  if (!filesWithPrefix.isEmpty()) {
                      // Find longest common prefix:
                      String longestCommonPrefix = null;
                      for (String fileName : filesWithPrefix) {
                          if (longestCommonPrefix == null) {
                              longestCommonPrefix = fileName;
                          } else {
                              while (!fileName.startsWith(longestCommonPrefix)) {
                                  longestCommonPrefix = longestCommonPrefix.substring(0, longestCommonPrefix.length() - 1);
                              }
                          }
                      }
                      if (longestCommonPrefix.length() > typedPrefix.length()) {
                          jTextField1.setText(longestCommonPrefix);
                          jTextField1.setCaretPosition(longestCommonPrefix.length());
                          typedPrefix = longestCommonPrefix;
                      }
                      if (filesWithPrefix.size() > 1) {
                          // Show popup:
                          ;;;
                      } else if (filesWithPrefix.size() == 1) {
                          // File selected:
                          System.beep();
                      }
                  }
              }
          } catch (BadLocationException ex) {
              Logger.getLogger(TabsJFrame.class.getName()).log(Level.SEVERE, null, ex);
          }
      }
      }
      

    What is missing is the display of the ambiguous file names. Popup menu would be nice, wouldn't it?

    Popup:

                        // Show popup:
                        JPopupMenu popup = new JPopupMenu();
                        for (String fileName : filesWithPrefix) {
                            popup.add(new AbstractAction(fileName) {
                                 @Override
                                public void actionPerformed(ActionEvent e) {
                                    jTextField1.setText(e.getActionCommand());
                                }
                            });
                        }
                        Point pt = jTextField1.getCaret().getMagicCaretPosition();
                        popup.show(jTextField1, pt.x, pt.y + 5);
    
    0 讨论(0)
提交回复
热议问题