001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.util.swing;
038:
039: import javax.swing.*;
040: import javax.swing.filechooser.FileFilter;
041: import java.awt.*;
042: import java.awt.event.ActionEvent;
043: import java.awt.event.ActionListener;
044: import java.awt.event.FocusListener;
045: import java.awt.event.FocusEvent;
046: import java.io.*;
047:
048: /** A JPanel with a text box and a "..." button to select a file or directory. The file name is editable in the text
049: * box, and a JFileChooser is displayed if the user clicks the "..." button.
050: * @version $Id: DirectorySelectorComponent.java 4255 2007-08-28 19:17:37Z mgricken $
051: */
052: public class DirectorySelectorComponent extends JPanel {
053:
054: /** The default number of columns for the text box. */
055: public static final int DEFAULT_NUM_COLS = 30;
056:
057: /** The default font size for the text box. */
058: public static final float DEFAULT_FONT_SIZE = 10f;
059:
060: /** The parent component of this component. */
061: protected final Component _parent;
062:
063: /** Text field with the name of the selected file. */
064: protected final JTextField _fileField;
065:
066: /** "..." button to open the file chooser. */
067: protected final JButton _chooserButton;
068:
069: /** File chooser to open when clicking the "..." button. */
070: protected final DirectoryChooser _chooser;
071:
072: /** The current file */
073: protected File _file;
074:
075: /** true if the file specified must exist and a file that doesn't exist will be rejected. */
076: protected boolean _mustExist;
077:
078: /** Creates a new DirectorySelectorComponent with default dimensions whose file must exist.
079: * @param parent Parent of this component.
080: * @param chooser File chooser to display from the "..." button.
081: */
082: public DirectorySelectorComponent(Component parent,
083: DirectoryChooser chooser) {
084: this (parent, chooser, DEFAULT_NUM_COLS, DEFAULT_FONT_SIZE);
085: }
086:
087: /** Creates a new DirectorySelectorComponent whose file must exist.
088: * @param parent Parent of this component.
089: * @param chooser File chooser to display from the "..." button.
090: * @param numCols Number of columns to display in the text field
091: * @param fontSize Font size for the text field
092: */
093: public DirectorySelectorComponent(Component parent,
094: DirectoryChooser chooser, int numCols, float fontSize) {
095: this (parent, chooser, numCols, fontSize, true);
096: }
097:
098: /** Creates a new DirectorySelectorComponent.
099: * @param parent Parent of this component.
100: * @param chooser File chooser to display from the "..." button.
101: * @param numCols Number of columns to display in the text field
102: * @param fontSize Font size for the text field
103: * @param mustExist true if the file specified in the field must exist
104: */
105: public DirectorySelectorComponent(Component parent,
106: DirectoryChooser chooser, int numCols, float fontSize,
107: boolean mustExist) {
108:
109: _parent = parent;
110: _chooser = chooser;
111: _file = null;
112: _mustExist = mustExist;
113:
114: _fileField = new JTextField(numCols) {
115: public Dimension getMaximumSize() {
116: return new Dimension(Short.MAX_VALUE, super
117: .getPreferredSize().height);
118: }
119: };
120:
121: _fileField.setFont(_fileField.getFont().deriveFont(fontSize));
122: _fileField.setPreferredSize(new Dimension(22, 22));
123: _fileField.addActionListener(new ActionListener() {
124: public void actionPerformed(ActionEvent e) {
125: validateTextField();
126: }
127: });
128:
129: _fileField.addFocusListener(new FocusListener() {
130: public void focusGained(FocusEvent e) { /* validateTextField(); */
131: }
132:
133: public void focusLost(FocusEvent e) {
134: validateTextField();
135: }
136: });
137:
138: _chooserButton = new JButton("...");
139: _chooserButton.addActionListener(new ActionListener() {
140: public void actionPerformed(ActionEvent e) {
141: _chooseFile();
142: }
143: });
144:
145: _chooserButton.setMaximumSize(new Dimension(22, 22));
146: _chooserButton.setMargin(new Insets(0, 5, 0, 5));
147:
148: // Add components
149: this .setLayout(new BoxLayout(this , BoxLayout.X_AXIS));
150: this .add(_fileField);
151: this .add(_chooserButton);
152: }
153:
154: public void setEnabled(boolean isEnabled) {
155: _fileField.setEnabled(isEnabled);
156: _chooserButton.setEnabled(isEnabled);
157: super .setEnabled(isEnabled);
158: }
159:
160: /** Returns the file text field. */
161: public JTextField getFileField() {
162: return _fileField;
163: }
164:
165: /** Returns the file chooser. */
166: public DirectoryChooser getFileChooser() {
167: return _chooser;
168: }
169:
170: /** Returns the file currently typed into the file field. THE SIDE EFFECTS OF THIS METHOD ARE OBSCENE! Corky 2/5/06 */
171: public File getFileFromField() {
172: String txt = _fileField.getText().trim();
173: if (txt.equals(""))
174: _file = null;
175: else
176: _file = new File(txt);
177:
178: return _file;
179: }
180:
181: /** Sets the text of the file field to be the given file.
182: * @param file File to display in the file field.
183: */
184: public void setFileField(File file) {
185: _file = file;
186: if (file != null && !file.getPath().equals("")) {
187: try {
188: _file = file.getCanonicalFile();
189: } catch (IOException e) { /* do nothing */
190: }
191: }
192: resetFileField();
193: }
194:
195: public void resetFileField() {
196: if (_file == null)
197: _fileField.setText("");
198: else {
199: _fileField.setText(_file.toString());
200: _fileField.setCaretPosition(_fileField.getText().length());
201: }
202: }
203:
204: public void setToolTipText(String text) {
205: super .setToolTipText(text);
206: _fileField.setToolTipText(text);
207: _chooserButton.setToolTipText(text);
208: }
209:
210: /** Adds a filter to decide if a directory can be chosen. */
211: public void addChoosableFileFilter(FileFilter filter) {
212: _chooser.addChoosableFileFilter(filter);
213: }
214:
215: /** Removes the given filefilter from the chooser. */
216: public void removeChoosableFileFilter(FileFilter filter) {
217: _chooser.removeChoosableFileFilter(filter);
218: }
219:
220: public void clearChoosableFileFilters() {
221: _chooser.resetChoosableFileFilters();
222: }
223:
224: /** Flag indicating that validation by the focus listener or action listener is pending. The flag is used to avoid
225: * duplicating the validation process.
226: */
227: private boolean _validationInProgress = false;
228:
229: /** The chooser method for the validation of filenames that are manually entered into the text field.
230: * @return False, if file does not exist. True, otherwise.
231: */
232: public boolean validateTextField() {
233: if (_validationInProgress)
234: return true;
235: _validationInProgress = true;
236:
237: String newValue = _fileField.getText().trim();
238:
239: File newFile = null;
240: if (!newValue.equals("")) {
241: newFile = new File(newValue);
242: if (!newFile.isDirectory()
243: && _chooser.isFileSelectionEnabled())
244: newFile = newFile.getParentFile();
245: }
246:
247: if (newFile != null && _mustExist && !newFile.exists()) {
248: JOptionPane.showMessageDialog(_parent, "The file '"
249: + newValue
250: + "'\nis invalid because it does not exist.",
251: "Invalid File Name", JOptionPane.ERROR_MESSAGE);
252: resetFileField(); // revert if not valid
253: _validationInProgress = false;
254: return false;
255: } else {
256: setFileField(newFile);
257: _validationInProgress = false;
258: return true;
259: }
260: }
261:
262: /** Opens the file chooser to select a file, putting the result in the file field. */
263: private void _chooseFile() {
264:
265: // Get the file from the chooser
266: int returnValue = _chooser.showDialog(_file);
267: if (returnValue == DirectoryChooser.APPROVE_OPTION) {
268: File chosen = _chooser.getSelectedDirectory();
269: if (chosen != null)
270: setFileField(chosen);
271: }
272: }
273:
274: }
|