/* Copyright 2006 Rene Grothmann, modified by Eric Hakenholz This file is part of C.a.R. software. C.a.R. is a 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, version 3 of the License. C.a.R. 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, see . */ package rene.dialogs; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Component; import java.awt.FileDialog; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.GridLayout; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.FocusEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.File; import java.io.FilenameFilter; import java.util.Enumeration; import eric.JEricPanel; import rene.gui.ButtonAction; import rene.gui.CloseDialog; import rene.gui.CloseFrame; import rene.gui.DoActionListener; import rene.gui.Global; import rene.gui.HistoryTextField; import rene.gui.HistoryTextFieldChoice; import rene.gui.MyLabel; import rene.gui.MyPanel; import rene.gui.Panel3D; import rene.gui.TextFieldAction; import rene.lister.Lister; import rene.lister.ListerMouseEvent; import rene.util.FileList; import rene.util.FileName; import rene.util.MyVector; class DirFieldListener implements DoActionListener { MyFileDialog T; public DirFieldListener(final MyFileDialog t) { T = t; } public void doAction(final String o) { T.setFile(o); } public void itemAction(final String o, final boolean flag) { } } /** * This is a file dialog. It is easy to handle, remembers its position and size, * and performs pattern matching. The calls needs the rene.viewer.* class, * unless you replace Lister with List everywhere. Moreover it needs the * rene.gui.Global class to store field histories and determine the background * color. Finally, it uses the FileList class to get the list of files. *

* The dialog does never check for files to exists. This must be done by the * application. *

* There is a static main method, which demonstrates everything. */ public class MyFileDialog extends CloseDialog implements ItemListener, FilenameFilter, MouseListener { // java.awt.List Dirs,Files; /** * */ private static final long serialVersionUID = 1L; Lister Dirs, Files; HistoryTextField DirField, FileField, PatternField; HistoryTextFieldChoice DirHistory, FileHistory; TextField Chosen; String CurrentDir = "."; boolean Aborted = true; String DirAppend = "", PatternAppend = "", FileAppend = ""; Button Home; Frame F; /** * @param title * The dialog title. * @param action * The button string for the main action (e.g. Load) * @param saving * True, if this is a saving dialog. */ public MyFileDialog(final Frame f, final String title, final String action, final boolean saving, final boolean help) { super(f, title, true); F = f; setLayout(new BorderLayout()); // title prompt add("North", new Panel3D(Chosen = new TextFieldAction(this, ""))); Chosen.setEditable(false); // center panels final JEricPanel center = new MyPanel(); center.setLayout(new GridLayout(1, 2, 5, 0)); Dirs = new Lister(); if (Global.NormalFont != null) Dirs.setFont(Global.NormalFont); Dirs.addActionListener(this); Dirs.setMode(false, false, false, false); center.add(Dirs); Files = new Lister(); if (Global.NormalFont != null) Files.setFont(Global.NormalFont); Files.addActionListener(this); Files.setMode(false, false, true, false); center.add(Files); add("Center", new Panel3D(center)); // south panel final JEricPanel south = new MyPanel(); south.setLayout(new BorderLayout()); final JEricPanel px = new MyPanel(); px.setLayout(new BorderLayout()); final JEricPanel p0 = new MyPanel(); p0.setLayout(new GridLayout(0, 1)); final JEricPanel p1 = new MyPanel(); p1.setLayout(new BorderLayout()); p1.add("North", linePanel(new MyLabel(Global.name("myfiledialog.dir")), DirField = new HistoryTextField(this, "Dir", 32) { /** * */ private static final long serialVersionUID = 1L; @Override public boolean filterHistory(final String name) // avoid a Windows bug with C: instead of c: { if (name.length() < 2) return true; if (name.charAt(1) == ':' && Character.isUpperCase(name.charAt(0))) return false; return true; } })); DirField.setText("."); p1.add("South", linePanel(new MyLabel(Global.name( "myfiledialog.olddirs", "")), DirHistory = new HistoryTextFieldChoice(DirField))); p0.add(new Panel3D(p1)); final JEricPanel p2 = new MyPanel(); p2.setLayout(new BorderLayout()); p2.add("North", linePanel( new MyLabel(Global.name("myfiledialog.file")), FileField = new HistoryTextField(this, "File"))); p2.add("South", linePanel(new MyLabel(Global.name( "myfiledialog.oldfiles", "")), FileHistory = new HistoryTextFieldChoice(FileField))); p0.add(new Panel3D(p2)); px.add("Center", p0); px.add("South", new Panel3D(linePanel(new MyLabel(Global .name("myfiledialog.pattern")), PatternField = new HistoryTextField(this, "Pattern")))); PatternField.setText("*"); south.add("Center", px); final JEricPanel buttons = new MyPanel(); buttons.setLayout(new FlowLayout(FlowLayout.RIGHT)); // buttons.add(Home = new ButtonAction(this, Global.name( // "myfiledialog.home", "Home"), "Home")); buttons.add(new ButtonAction(this, Global.name("myfiledialog.mkdir", "Create Directory"), "Create")); buttons.add(new ButtonAction(this, Global.name("myfiledialog.back", "Back"), "Back")); buttons.add(new MyLabel("")); buttons.add(new ButtonAction(this, action, "Action")); buttons.add(new ButtonAction(this, Global.name("abort"), "Close")); if (help) { addHelp(buttons, "filedialog"); } south.add("South", buttons); add("South", new Panel3D(south)); // set sizes pack(); setSize("myfiledialog"); addKeyListener(this); DirField.addKeyListener(this); DirField.setTrigger(true); FileHistory.setDoActionListener(new DirFieldListener(this)); PatternField.addKeyListener(this); PatternField.setTrigger(true); FileField.addKeyListener(this); FileField.setTrigger(true); Home.addMouseListener(this); } JEricPanel linePanel(final Component x, final Component y) { final JEricPanel p = new MyPanel(); p.setLayout(new GridLayout(1, 0)); p.add(x); p.add(y); return p; } public MyFileDialog(final Frame f, final String title, final String action, final boolean saving) { this(f, title, action, saving, false); } FileDialog FD; public MyFileDialog(final Frame f, final String title, final boolean saving) { super(f, "", true); FD = new FileDialog(f, title, saving ? FileDialog.SAVE : FileDialog.LOAD); } boolean HomeShiftControl = false; public void mousePressed(final MouseEvent e) { HomeShiftControl = e.isShiftDown() && e.isControlDown(); } public void mouseReleased(final MouseEvent e) { } public void mouseClicked(final MouseEvent e) { } public void mouseEntered(final MouseEvent e) { } public void mouseExited(final MouseEvent e) { } @Override public void doAction(final String o) { if (o.equals("Dir") || o.equals("Pattern")) { if (updateDir()) updateFiles(); PatternField.remember(PatternField.getText()); } else if (o.equals("File") || o.equals("Action")) { if (FileField.getText().equals("")) return; leave(); } else if (o.equals("Home")) { if (HomeShiftControl) { final String s = Global.getParameter("myfiledialog.homdir", ""); if (s.equals("")) Global.setParameter("myfiledialog.homdir", DirField .getText()); else Global.setParameter("myfiledialog.homdir", ""); } try { final String s = Global.getParameter("myfiledialog.homdir", ""); if (s.equals("")) { final String s1 = System.getProperty("user.home"); final String s2 = Global.name("myfiledialog.windowshome", ""); final String s3 = Global.name("myfiledialog.homedir", ""); final String sep = System.getProperty("file.separator"); if (new File(s1 + sep + s2 + sep + s3).exists()) DirField.setText(s1 + sep + s2 + sep + s3); else if (new File(s1 + sep + s2).exists()) DirField.setText(s1 + sep + s2); else DirField.setText(s1); } else DirField.setText(s); updateDir(); updateFiles(); } catch (final Exception e) { } } else if (o.equals("Create")) { try { final File f = new File(DirField.getText()); if (!f.exists()) { f.mkdir(); } updateDir(); updateFiles(); } catch (final Exception e) { } } else if (o.equals("Back")) { final String dir = getUndo(); if (!dir.equals("")) { DirField.setText(dir); updateDir(); updateFiles(); } } else super.doAction(o); } @Override public void actionPerformed(final ActionEvent e) { if (e.getSource() == Dirs) { final String s = Dirs.getSelectedItem(); if (s == null) return; if (s.equals("..")) dirup(); else dirdown(s); } if (e.getSource() == Files) { if (e instanceof ListerMouseEvent) { final ListerMouseEvent em = (ListerMouseEvent) e; if (em.clickCount() >= 2) leave(); else { final String s = Files.getSelectedItem(); if (s != null) FileField.setText(s); } } } else super.actionPerformed(e); } public void setFile(final String s) { DirField.setText(FileName.path(s)); FileField.setText(FileName.filename(s)); // System.out.println(s); update(false); } public void dirup() { DirField.setText(FileName.path(CurrentDir)); if (DirField.getText().equals("")) DirField.setText("" + File.separatorChar); if (updateDir()) updateFiles(); } public void dirdown(final String subdir) { DirField.setText(CurrentDir + File.separatorChar + subdir); if (updateDir()) updateFiles(); } /** * Leave the dialog and remember settings. */ void leave() { if (FD != null) return; if (!FileField.getText().equals("")) Aborted = false; if (!Aborted) { noteSize("myfiledialog"); DirField.remember(DirField.getText()); DirField.saveHistory("myfiledialog.dir.history" + DirAppend); PatternField.saveHistory("myfiledialog.pattern.history" + PatternAppend); FileField.remember(getFilePath()); FileField.saveHistory("myfiledialog.file.history" + FileAppend); } doclose(); } /** * Update the directory list. * * @return if the current content of DirField is indeed a directory. */ public boolean updateDir() { if (FD != null) return true; final File dir = new File(DirField.getText() + File.separatorChar); if (!dir.isDirectory()) return false; try { final String s = FileName.canonical(dir.getCanonicalPath()); addUndo(s); DirField.setText(s); Chosen.setText(FileName.chop(16, DirField.getText() + File.separatorChar + PatternField.getText(), 48)); } catch (final Exception e) { return false; } return true; } MyVector Undo = new MyVector(); /** * Note the directory in a history list. */ public void addUndo(final String dir) { if (Undo.size() > 0 && ((String) Undo.elementAt(Undo.size() - 1)).equals(dir)) return; Undo.addElement(dir); } /** * Get the undo directory and remove it. */ public String getUndo() { if (Undo.size() < 2) return ""; final String s = (String) Undo.elementAt(Undo.size() - 2); Undo.truncate(Undo.size() - 1); return s; } /** * Update the file list. */ public void updateFiles() { if (FD != null) return; final File dir = new File(DirField.getText()); if (!dir.isDirectory()) return; CurrentDir = DirField.getText(); if (PatternField.getText().equals("")) PatternField.setText("*"); try { Files.clear(); Dirs.clear(); final FileList l = new FileList(DirField.getText(), PatternField .getText(), false); l.setCase(Global.getParameter("filedialog.usecaps", false)); l.search(); l.sort(); Enumeration e = l.files(); while (e.hasMoreElements()) { final File f = (File) e.nextElement(); Files.addElement(FileName.filename(f.getCanonicalPath())); } Dirs.addElement(".."); e = l.dirs(); while (e.hasMoreElements()) { final File f = (File) e.nextElement(); Dirs.addElement(FileName.filename(f.getCanonicalPath())); } } catch (final Exception e) { } Dirs.updateDisplay(); Files.updateDisplay(); Files.requestFocus(); } public void setDirectory(final String dir) { if (FD != null) FD.setDirectory(dir); else DirField.setText(dir); } public void setPattern(final String pattern) { if (FD != null) { FD.setFilenameFilter(this); // does not work final String s = pattern.replace(' ', ';'); FD.setFile(s); } else PatternField.setText(pattern); } public void setFilePath(final String file) { if (FD != null) { FD.setFile(file); return; } final String dir = FileName.path(file); if (!dir.equals("")) { DirField.setText(dir); FileField.setText(FileName.filename(file)); } else FileField.setText(file); } /** * Check, if the dialog was aborted. */ @Override public boolean isAborted() { if (FD != null) return FD.getFile() == null || FD.getFile().equals(""); else return Aborted; } /** * @return The file plus its path. */ public String getFilePath() { if (FD != null) { if (FD.getFile() != null) return FD.getDirectory() + FD.getFile(); else return ""; } final String file = FileField.getText(); if (!FileName.path(file).equals("")) return file; else return CurrentDir + File.separatorChar + FileField.getText(); } /** * This should be called at the start. */ public void update(final boolean recent) { if (FD != null) return; loadHistories(recent); setFilePath(FileField.getText()); if (updateDir()) updateFiles(); Aborted = true; } public void update() { update(true); } @Override public void setVisible(final boolean flag) { if (FD != null) FD.setVisible(flag); else super.setVisible(flag); } @Override public void center(final Frame f) { if (FD != null) CloseDialog.center(f, FD); else super.center(f); } public static void main(final String args[]) { final Frame f = new CloseFrame() { /** * */ private static final long serialVersionUID = 1L; @Override public void doclose() { System.exit(0); } }; f.setSize(500, 500); f.setLocation(400, 400); f.setVisible(true); final MyFileDialog d = new MyFileDialog(f, "Title", "Save", false); d.center(f); d.update(); d.setVisible(true); } @Override public void focusGained(final FocusEvent e) { FileField.requestFocus(); } /** * Can be overwritten by instances to accept only some files. */ public boolean accept(final File dir, final String file) { return true; } public void loadHistories(final boolean recent) { if (FD != null) return; DirField.loadHistory("myfiledialog.dir.history" + DirAppend); DirHistory.update(); if (recent) setDirectory(DirHistory.getRecent()); if (updateDir()) updateFiles(); PatternField .loadHistory("myfiledialog.pattern.history" + PatternAppend); FileField.loadHistory("myfiledialog.file.history" + FileAppend); FileHistory.update(); } public void loadHistories() { loadHistories(true); } /** * Loads the histories from the configuration file. If you want a unique * history for your instance, you need to give a string unique for your * instance. There are three types of histories. * * @param dir * @param pattern * @param file * @see loadHistories */ public void loadHistories(final String dir, final String pattern, final String file) { setAppend(dir, pattern, file); loadHistories(); } /** * Histories are used for the directories, the files and the patterns. The * dialog can use different histories for each instance of this class. If * you want that, you need to determine the history for the instance with a * string, unique for the instance. If a string is empty, "default" is used. * * @param dir * @param pattern * @param file */ public void setAppend(final String dir, final String pattern, final String file) { if (FD != null) return; if (!dir.equals("")) DirAppend = "." + dir; else DirAppend = ".default"; if (!pattern.equals("")) PatternAppend = "." + pattern; else PatternAppend = ".default"; if (!file.equals("")) FileAppend = "." + file; else FileAppend = ".default"; } public void itemStateChanged(final ItemEvent e) { } }