⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsacombobox.java

📁 具有不同语法高亮的编辑器实例
💻 JAVA
字号:
/*
 * 05/12/2004
 *
 * FSAComboBox.java - A "File System-Aware" combo box that keeps its drop-down
 *                    list popuplated with files matching the text typed in by
 *                    the user.
 * Copyright (C) 2004 Robert Futrell
 * email@address.com
 * www.website.com
 *
 * 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package org.fife.ui;

import java.io.File;
import java.io.FilenameFilter;
import javax.swing.*;
import javax.swing.event.*;


/**
 * A "File System-Aware" combo box.  When the user is typing into this
 * combo box, it automagically locates all files that begin with the
 * text typed in, and populates the combo box with file choices.  This
 * is similar to the combo box found in the "Run" dialog in Microsoft
 * Windows.<p>
 *
 * You should no longer use this class; use {@link FSATextField} instead.  It
 * has the same functionality but fewer problems.
 *
 * @author Robert Futrell
 * @version 0.1
 * @deprecated
 */
public class FSAComboBox extends JComboBox implements DocumentListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = -5747590228545687478L;

	/**
	 * <code>true</code> iff the OS is a Windows variant.  This tells us
	 * whether or not filename comparisons should be done case-sensitively
	 * or not.
	 */
	private static final boolean osIsWindows = System.getProperty("os.name").toLowerCase().indexOf("windows")>-1;

	/**
	 * The file separator for this OS.
	 */
	private static final String separator = System.getProperty("file.separator");

	/**
	 * File filter used if directories-only mode is set.
	 */	
	private FilenameFilter directoriesOnlyFilenameFilter;

	/**
	 * These are an attempt to speed things up in the "common" case.  If the
	 * user types a letter into the combo box but the last position of a
	 * file separator is the same as it was last time, then the "current
	 * directory" hasn't changed, so we can just keep the File instance for
	 * the directory we already have.  We do this because doing a regex match
	 * loop through possibly hundreds of file names can be slow on some systems.
	 */
	private int lastLastSeparator = -1;
	private File directory;
	private String dirName;

	/**
	 * Real variables used by the combo box.
	 */
	private JTextField textComponent;
	private boolean repopulatePopupList = true;
	private boolean directoriesOnly;
	private long lastCount = -1;

	/**
	 * Cached values of the files in the current directory and the number
	 * of files in the current directory.
	 */
	private String[] containedFiles;
	private int num;

	/**
	 * The "current directory;" if the user is typing a relative pathname
	 * (i.e., not absolute), then assume this is the root directory.
	 */
	private String currentDirectory;

	/**
	 * Whether or not the combo box pops up a list of matching files.
	 */
	private boolean fileSystemAware;

/*****************************************************************************/


	/**
	 * Creates a new FSAComboBox that previews both files and directories,
	 * and whose current directory is the program's current directory.
	 */
	public FSAComboBox() {
		this(false, System.getProperty("user.dir"));
	}


/*****************************************************************************/


	/**
	 * Creates a new FSAComboBox.
	 *
	 * @param directoriesOnly Whether this combo box should preview only
	 *                        directories (or both files and directories).
	 * @param currentDirectory The directory for which the combo box should
	 *                         assume relative filenames are in.
	 */
	public FSAComboBox(boolean directoriesOnly, File currentDirectory) {
		this(directoriesOnly, currentDirectory.getAbsolutePath());
	}


/*****************************************************************************/


	/**
	 * Creates a new FSAComboBox.
	 *
	 * @param directoriesOnly Whether this combo box should preview only
	 *                        directories (or both files and directories).
	 * @param currentDirectory The directory for which the combo box should
	 *                         assume relative filenames are in.
	 */
	public FSAComboBox(boolean directoriesOnly, String currentDirectory) {

		super();
		setEditable(true);

		setDirectoriesOnly(directoriesOnly);

		setCurrentDirectory(currentDirectory);

		fileSystemAware = true;

	}


/*****************************************************************************/


	/**
	 * Called when the text component's document receives a style change.
	 * Since it is a plain document, this is never called.
	 */
	public void changedUpdate(DocumentEvent e) {
	}


/*****************************************************************************/


	/**
	 * Returns the current directory for this combo box.
	 *
	 * @return The current directory.
	 * @see #setCurrentDirectory
	 */
	public String getCurrentDirectory() {
		return currentDirectory;
	}


/*****************************************************************************/


	/**
	 * Called when text is inserted into the text component's document.
	 */
	public void insertUpdate(DocumentEvent e) {
		if (repopulatePopupList && isShowing() && fileSystemAware)
			SwingUtilities.invokeLater(new Runnable() {
									public void run() {
										updateComboBoxContents();
									}
								});
	}


/*****************************************************************************/


	/**
	 * Returns whether or not this combo box previews both files and
	 * directories or just directories.
	 *
	 * @return Whether or not this combo box shows only directories.
	 * @see #setDirectoriesOnly
	 */
	public boolean isDirectoriesOnly() {
		return directoriesOnly;
	}


/*****************************************************************************/


	/**
	 * Returns whether or not this combo box is file-system-aware.  If it is,
	 * then the combo box expands to display all matching files/directories
	 * as the user types.
	 *
	 * @return Whether or not this combo box is file-system aware.
	 * @see #setFileSystemAware
	 */
	public boolean isFileSystemAware() {
		return fileSystemAware;
	}


/*****************************************************************************/


	/**
	 * Called when text is removed from the text component's document.
	 */
	public void removeUpdate(DocumentEvent e) {
		if (repopulatePopupList && isShowing() && fileSystemAware)
			SwingUtilities.invokeLater(new Runnable() {
									public void run() {
										updateComboBoxContents();
									}
								});
	}


/*****************************************************************************/


	/**
	 * Sets the current directory for this combo box.  The current directory
	 * is the directory in which the combo box assumes typed relative
	 * files reside in.
	 *
	 * @param currentDirectory The new "current directory" for this combo
	 *                         box.  This value should be an absolute
	 *                         pathname.
	 * @see #getCurrentDirectory
	 */
	public void setCurrentDirectory(File currentDirectory) {
		this.currentDirectory = currentDirectory.getAbsolutePath();
	}


/*****************************************************************************/


	/**
	 * Sets the current directory for this combo box.  The current directory
	 * is the directory in which the combo box assumes typed relative
	 * files reside in.
	 *
	 * @param currentDirectory The new "current directory" for this combo
	 *                         box.  This value should be an absolute
	 *                         pathname.
	 * @see #getCurrentDirectory
	 */
	public void setCurrentDirectory(String currentDirectory) {
		this.currentDirectory = currentDirectory;
	}


/*****************************************************************************/


	/**
	 * Sets whether or not this combo box previews both files and
	 * directories or just directories.
	 *
	 * @param directoriesOnly Whether or not to preview only directories.
	 * @see #isDirectoriesOnly
	 */
	public void setDirectoriesOnly(boolean directoriesOnly) {
		// Lazily create the file filter used.
		if (directoriesOnly) {
			directoriesOnlyFilenameFilter = new FilenameFilter() {
									public boolean accept(File parentDir, String fileName) {
										return new File(parentDir.getAbsolutePath() + separator + fileName).isDirectory();
									}
								};
		}
		this.directoriesOnly = directoriesOnly;
	}


/*****************************************************************************/


	/**
	 * Toggles whether or not this dialog is file-system-aware.  This
	 * property should be set to <code>false</code> when programmatically
	 * inserting text into the combo box; otherwise, it has a bad habit of
	 * stealing the focus from the currently focused component, etc.
	 *
	 * @param aware Whether or not this combo box should be file-system
	 *              aware.
	 * @see #isFileSystemAware
	 */
	public void setFileSystemAware(boolean aware) {
		fileSystemAware = aware;
	}


/*****************************************************************************/


	public void setSelectedIndex(int index) {
		repopulatePopupList = false;
		super.setSelectedIndex(index);
		repopulatePopupList = true;
	}


/*****************************************************************************/


	/**
	 * Updates the combo box's dropdown list to contain files matching
	 * the characters typed by the user into the combo box's text field.
	 */
	public void updateComboBoxContents() {

		String text = textComponent.getText();

		// We're nice and allow the user to type either '/' or '\\' as the separator on any OS.
		int lastSeparator = Math.max(text.lastIndexOf('/'), text.lastIndexOf('\\')) + 1;//text.lastIndexOf(separator);

		// Get the path for the file they're typing.  If they haven't typed a
		// separator char yet, assume it's a relative path from the current
		// directory (and they're typing the name of a file in that directory).
		// If they have typed a separator char, check to see if it's a relative
		// directory path or an absolute one.
		File t2 = null;
		if (lastSeparator!=0) {
			String pathPart = text.substring(0, lastSeparator);
			t2 = new File(pathPart);
			if (!t2.isAbsolute())
				t2 = new File(currentDirectory + separator + pathPart);
		}
		else {
			if (text.length()==0) {
				setPopupVisible(false);
				lastCount = 0;
				return;
			}
			t2 = new File(currentDirectory);
		}
	
		// An attempt to speed things up in the common case.  If the
		// directory they're working in hasn't changed, we don't
		// have to get the list of files in the directory (as it is cached).
		if (!t2.equals(directory)) {

			directory = t2;

			if (!directory.isDirectory()) {
				lastCount = -1;
				lastLastSeparator = 0;
				setPopupVisible(false);
				num = 0;
				containedFiles = null;
				return;
			}

			lastLastSeparator = lastSeparator;

			dirName = directory.getAbsolutePath();
			if (dirName.charAt(dirName.length()-1)!=separator.charAt(0))
				dirName += separator; // Only need to add slash if not == "C:\" on Windows.

			// If they only want to see directories, we have to take a little
			// more care.
			if (directoriesOnly) {
				containedFiles = directory.list(directoriesOnlyFilenameFilter);
			}
			else {
				containedFiles = directory.list();
			}

			// We must check for null here in case an IO error occurs.
			num = containedFiles!=null ? containedFiles.length : 0;

		} // End of if (lastSeparator!=lastLastSeparator).

		if (num > 0) {

			repopulatePopupList = false;
			removeAllItems();
			// We only match on the file name since the canonical-file path is
			// cached in dirName.
			String fpFileName = text.substring(lastSeparator);
			int fpFileNameLength = fpFileName.length();
			long count = 0;
			for (int i=0; i<num; i++) {
				// If fileName starts with fpFileName, matching case only in Windows...
				if (containedFiles[i].regionMatches(osIsWindows, 0, fpFileName, 0,fpFileNameLength)) {
					count++;
					addItem(dirName + containedFiles[i]);
				}
			}
			if (count!=lastCount && count>0) {
				setPopupVisible(false);
				setPopupVisible(true);	// This tricks the popup menu's list to "resize" properly.
			}
			else if (count==0)
				setPopupVisible(false);
			lastCount = count;
			textComponent.setText(text); // The text in the component gets goobered.
			repopulatePopupList = true;
		}

		else {
			lastCount = -1;
			lastSeparator = 0;
			setPopupVisible(false);
		}

	}


/*****************************************************************************/


	/**
	 * Overridden so that we always have a document listener on the text field
	 * contained by this combo box.
	 */
	public void setUI(javax.swing.plaf.ComboBoxUI ui) {
		if (textComponent!=null)
			textComponent.getDocument().removeDocumentListener(this);
		super.setUI(ui);
		textComponent = (JTextField)getEditor().getEditorComponent();
		textComponent.getDocument().addDocumentListener(this);
	}


/*****************************************************************************/

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -