001: /*
002: * SaveFileDialog.java
003: *
004: * Copyright (C) 1998-2004 Peter Graves
005: * $Id: SaveFileDialog.java,v 1.5 2004/09/12 23:49:03 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: import java.awt.BorderLayout;
025: import java.awt.event.FocusEvent;
026: import java.awt.event.FocusListener;
027: import java.awt.event.InputEvent;
028: import java.awt.event.KeyEvent;
029: import java.awt.event.KeyListener;
030: import java.util.Vector;
031: import javax.swing.BoxLayout;
032: import javax.swing.JDialog;
033: import javax.swing.JLabel;
034: import javax.swing.JPanel;
035: import javax.swing.border.EmptyBorder;
036:
037: public class SaveFileDialog extends JDialog implements FocusListener,
038: KeyListener {
039: private File destination;
040:
041: protected final Editor editor;
042: protected final String title;
043: protected String defaultName;
044: protected HistoryTextField textField;
045: protected History history;
046:
047: private final String prompt;
048: private Vector completions;
049: private int index;
050: private boolean completionsIgnoreCase;
051: private boolean allowDirectory;
052: private boolean confirmOverwrite = true;
053:
054: public SaveFileDialog(Editor editor, String title) {
055: super (editor.getFrame(), title, true);
056: this .editor = editor;
057: this .title = title;
058: prompt = "File:";
059: init();
060: }
061:
062: public SaveFileDialog(Editor editor, String title, String prompt) {
063: super (editor.getFrame(), title, true);
064: this .editor = editor;
065: this .title = title;
066: this .prompt = prompt;
067: init();
068: }
069:
070: public SaveFileDialog(Editor editor, String title, String prompt,
071: String defaultName) {
072: super (editor.getFrame(), title, true);
073: this .editor = editor;
074: this .title = title;
075: this .prompt = prompt;
076: this .defaultName = defaultName;
077: init();
078: }
079:
080: public final File getDestination() {
081: return destination;
082: }
083:
084: public final void setAllowDirectory(boolean b) {
085: allowDirectory = b;
086: }
087:
088: public final void setConfirmOverwrite(boolean b) {
089: confirmOverwrite = b;
090: }
091:
092: public final void setInitialText(String s) {
093: textField.setText(s);
094: }
095:
096: private void init() {
097: if (Platform.isPlatformWindows())
098: completionsIgnoreCase = true;
099: else
100: completionsIgnoreCase = Editor.preferences()
101: .getBooleanProperty(
102: Property.FILENAME_COMPLETIONS_IGNORE_CASE);
103: JPanel panel = new JPanel();
104: panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
105: panel.setBorder(new EmptyBorder(5, 5, 5, 5));
106: panel.add(new Label(prompt));
107: textField = new HistoryTextField(20);
108: history = new History("saveFile.file");
109: textField.setHistory(history);
110: if (defaultName != null && defaultName.length() > 0) {
111: File directory = editor.getCurrentDirectory();
112: if (directory == null || directory.isRemote())
113: directory = Directories.getUserHomeDirectory();
114: File file = File.getInstance(directory, defaultName);
115: if (file != null)
116: textField.setText(file.canonicalPath());
117: }
118: panel.add(textField);
119: getContentPane().add(panel, BorderLayout.CENTER);
120: pack();
121: textField.setFocusTraversalKeysEnabled(false);
122: addFocusListener(this );
123: addKeyListener(this );
124: textField.addKeyListener(this );
125: textField.requestFocus();
126: textField.selectAll();
127: }
128:
129: public void focusGained(FocusEvent e) {
130: textField.requestFocus();
131: }
132:
133: public void focusLost(FocusEvent e) {
134: }
135:
136: public void keyPressed(KeyEvent e) {
137: int keyCode = e.getKeyCode();
138: int modifiers = e.getModifiers();
139: switch (keyCode) {
140: case KeyEvent.VK_TAB: {
141: String s = null;
142: String entry = textField.getText();
143: if (modifiers == InputEvent.SHIFT_MASK)
144: s = previousGuess();
145: else {
146: File dir = editor.getCurrentDirectory();
147: if (dir != null && !dir.isRemote()) {
148: File file = File.getInstance(dir, entry);
149: if (file != null)
150: s = guess(file.canonicalPath());
151: }
152: }
153: e.consume();
154: if (s != null) {
155: textField.setText(s);
156: textField.setCaretPosition(s.length());
157: }
158: return;
159: }
160: case KeyEvent.VK_ENTER:
161: e.consume();
162: enter();
163: return;
164: case KeyEvent.VK_ESCAPE:
165: e.consume();
166: destination = null;
167: dispose();
168: return;
169: // Ignore modifiers.
170: case KeyEvent.VK_SHIFT:
171: case KeyEvent.VK_CONTROL:
172: case KeyEvent.VK_ALT:
173: case KeyEvent.VK_META:
174: return;
175: // Anything but tab, start over.
176: default:
177: completions = null;
178: return;
179: }
180: }
181:
182: public void keyReleased(KeyEvent e) {
183: }
184:
185: public void keyTyped(KeyEvent e) {
186: }
187:
188: protected void enter() {
189: final String entry = textField.getText().trim();
190: if (entry.length() == 0) {
191: destination = null;
192: dispose();
193: return;
194: }
195: File file;
196: if (Utilities.isFilenameAbsolute(entry)) {
197: file = File.getInstance(entry);
198: } else {
199: File directory = editor.getCurrentDirectory();
200: if (directory == null || directory.isRemote())
201: directory = Directories.getUserHomeDirectory();
202: file = File.getInstance(directory, entry);
203: }
204: if (file == null) {
205: dispose();
206: return;
207: }
208: if (file.isRemote()) {
209: destination = file;
210: } else {
211: if (file.isDirectory()) {
212: if (defaultName != null)
213: file = File.getInstance(file, defaultName);
214: if (file.isDirectory() && !allowDirectory) {
215: String message = file.canonicalPath()
216: + " is a directory";
217: MessageDialog.showMessageDialog(editor, message,
218: title);
219: requestFocus();
220: return;
221: }
222: }
223: if (file.isFile()) {
224: if (file.canWrite()) {
225: String message = "Overwrite existing file "
226: + file.canonicalPath() + "?";
227: if (!confirmOverwrite
228: || editor.confirm(title, message)) {
229: destination = file;
230: history.append(file.canonicalPath());
231: history.save();
232: dispose();
233: }
234: return;
235: } else {
236: // File is read only.
237: String message = file.canonicalPath()
238: + " is read only";
239: MessageDialog.showMessageDialog(editor, message,
240: title);
241: return;
242: }
243: }
244: // File (if specified) does not exist.
245: // Make sure parent directory exists.
246: File parentDir = file.isDirectory() ? file : file
247: .getParentFile();
248: if (parentDir == null || !parentDir.isDirectory()) {
249: String message = "Invalid path";
250: MessageDialog.showMessageDialog(editor, message, title);
251: requestFocus();
252: return;
253: }
254: // Make sure parent directory is writable.
255: if (!Utilities.isDirectoryWritable(parentDir)) {
256: String message = "Directory "
257: + parentDir.canonicalPath()
258: + " is not writable";
259: MessageDialog.showMessageDialog(editor, message, title);
260: requestFocus();
261: return;
262: }
263: destination = file;
264: }
265: history.append(destination.netPath());
266: history.save();
267: dispose();
268: }
269:
270: private String guess(String prefix) {
271: if (completions != null) {
272: if (index < completions.size())
273: return (String) completions.get(index++);
274: index = 0;
275: if (index < completions.size())
276: return (String) completions.get(index++);
277: return null;
278: }
279: completions = getCompletions(prefix);
280: index = 0;
281: if (completions.size() > 0)
282: return (String) completions.get(index++);
283: return null;
284: }
285:
286: private String previousGuess() {
287: if (completions != null) {
288: if (completions.size() > 1) {
289: index -= 2;
290: if (index < 0)
291: index += completions.size();
292: return (String) completions.get(index++);
293: }
294: }
295: return null;
296: }
297:
298: private Vector getCompletions(String prefix) {
299: Vector v = new Vector();
300: File currentDir = editor.getCurrentDirectory();
301: File dir = null;
302: boolean isShortName = false;
303: if (Utilities.isFilenameAbsolute(prefix)
304: || prefix.indexOf(LocalFile.getSeparatorChar()) >= 0) {
305: File f = File.getInstance(currentDir, prefix);
306: dir = f.getParentFile();
307: prefix = f.getName();
308: } else {
309: dir = currentDir;
310: isShortName = true;
311: }
312: String[] names = dir.list();
313: if (names != null) {
314: for (int i = 0; i < names.length; i++) {
315: boolean matches = false;
316: if (completionsIgnoreCase)
317: matches = names[i].regionMatches(true, 0, prefix,
318: 0, prefix.length());
319: else
320: matches = names[i].startsWith(prefix);
321: if (matches) {
322: File file = File.getInstance(dir, names[i]);
323: String name = dir == currentDir ? file.getName()
324: : file.getAbsolutePath();
325: if (file.isDirectory()) {
326: v.add(name + LocalFile.getSeparator());
327: continue;
328: }
329: v.add(name);
330: }
331: }
332: }
333: return v;
334: }
335:
336: public void dispose() {
337: super .dispose();
338: editor.restoreFocus();
339: }
340:
341: public static File getSaveFile(Editor editor, String dialogTitle) {
342: final File file = editor.getBuffer().getFile();
343: final String defaultName = file != null ? file.getName() : null;
344: SaveFileDialog d = new SaveFileDialog(editor, dialogTitle,
345: "File:", defaultName);
346: editor.centerDialog(d);
347: d.show();
348: return d.getDestination();
349: }
350:
351: public static void writeGlobalKeyMap() {
352: final Editor editor = Editor.currentEditor();
353: SaveFileDialog d = new SaveFileDialog(editor,
354: "Write Global Key Map");
355: editor.centerDialog(d);
356: d.show();
357: File file = d.getDestination();
358: if (file != null)
359: KeyMap.getGlobalKeyMap().writeKeyMap(file);
360: }
361:
362: public static void writeLocalKeyMap() {
363: final Editor editor = Editor.currentEditor();
364: SaveFileDialog d = new SaveFileDialog(editor,
365: "Write Local Key Map");
366: editor.centerDialog(d);
367: d.show();
368: File file = d.getDestination();
369: if (file != null)
370: editor.getBuffer().getKeyMapForMode().writeKeyMap(file);
371: }
372: }
|