001 /* 002 * CRIMSON 003 * Copyright (c) 2006, Stephen Fisher, Susan Davidson, and Junhyong Kim, 004 * University of Pennsylvania. 005 * 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU General Public License as 008 * published by the Free Software Foundation; either version 2 of the 009 * License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, but 012 * WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 * 02110-1301 USA. 020 * 021 * @(#)GUIUtils.java 022 */ 023 024 package edu.upenn.crimson.gui; 025 026 import edu.upenn.crimson.*; 027 import edu.upenn.crimson.io.*; 028 import java.io.File; 029 import java.util.ArrayList; 030 import java.awt.*; 031 import java.awt.Toolkit; 032 import javax.swing.*; 033 import javax.swing.filechooser.*; 034 import javax.swing.text.*; 035 import walrus.*; 036 037 /** 038 * Static methods used throughout the GUI. 039 * 040 * @XXX The global file type descriptions and extensions be user 041 * modifiable. 042 * 043 * @author Stephen Fisher 044 * @version $Id: GUIUtils.java,v 1.40 2007/05/16 18:55:58 fisher Exp $ 045 */ 046 047 public class GUIUtils { 048 /** 049 * The file chooser begins with the current working directory. 050 * This is not saved across sessions. 051 */ 052 private static JFileChooser fileChooser = new JFileChooser("."); 053 054 /** 055 * By using global static variables, these values will persist 056 * across instances of the open/save fileChoosers. 057 */ 058 private static boolean SHOW_ALL_FILES = CrimsonMain.userDefaults.getBoolean("SHOW_ALL_FILES", 059 false); 060 private static boolean USE_FILE_EXTENSIONS = CrimsonMain.userDefaults.getBoolean("USE_FILE_EXTENSIONS", 061 false); 062 063 //-------------------------------------------------------------------------- 064 // Getters and Setters 065 066 /** Set the SHOW_ALL_FILES flag. */ 067 public static void setShowAllFiles(boolean showAllFiles) { 068 SHOW_ALL_FILES = showAllFiles; 069 CrimsonMain.userDefaults.putBoolean("SHOW_ALL_FILES", showAllFiles); 070 } 071 072 public static boolean showAllFiles() { return SHOW_ALL_FILES; } 073 074 /** Set the USE_FILE_EXTENSIONS flag. */ 075 public static void setUseFileExtensions(boolean useFileExtensions) { 076 USE_FILE_EXTENSIONS = useFileExtensions; 077 CrimsonMain.userDefaults.putBoolean("USE_FILE_EXTENSIONS", useFileExtensions); 078 } 079 080 public static boolean useFileExtensions() { return USE_FILE_EXTENSIONS; } 081 082 public static FileFilter getPyFilter() { return new PyFilter(); } 083 084 public static DocumentFilter getDocLengthFilter() { return new DocumentLengthFilter(); } 085 086 //-------------------------------------------------------------------------- 087 // Miscellaneous Methods 088 089 /** This will start a Walrus 3D session using the file given. */ 090 public static void launchWalrus(String filename) { 091 H3Main w = new H3Main(); 092 w.userLoadFile(filename); 093 w.handleStartRenderingRequest(); 094 } 095 096 /** RE-set GUI user defaults. */ 097 public static void resetGUIDefaults() { 098 setShowAllFiles(false); 099 setUseFileExtensions(false); 100 } 101 102 /** 103 * On Windows machines the path contains "\\", however, when 104 * converted to a String, this becomes "\". So we are doubling 105 * them here, to preserver the "\\". 106 */ 107 public static String getFilename(File file) { 108 if (file == null) return ""; 109 else return file.getAbsolutePath().replaceAll("\\\\","\\\\\\\\"); 110 } 111 112 public static void setDBType() { 113 if (Database.isOpen()) { 114 String msg = "A database is already open. Continuing will close the current database."; 115 Object[] options = {"Continue", "Cancel"}; 116 int flag = JOptionPane.showOptionDialog(null, msg, 117 "Open Database Confirmation", 118 JOptionPane.YES_NO_OPTION, 119 JOptionPane.QUESTION_MESSAGE, 120 null, 121 options, 122 options[1]); 123 if (flag == JOptionPane.NO_OPTION) { // "Cancel" 124 return; 125 } 126 } 127 128 ArrayList out = new ArrayList(); 129 new ObjectSelectorDialog("Database Selector", SQL.getDBTypes(), out); 130 131 if (out.size() > 0) { 132 // if a database is open, then close it now 133 if (Database.isOpen()) Database.close(); 134 135 Root.runCommand("setDBType(\"" + (String) out.get(0) + "\")"); 136 } 137 } 138 139 140 /** 141 * Use a FieldEditDialog to query the user for 'username', 142 * 'password', and 'database' info and then use this info to open 143 * a connection to the database. The 'username' and 'database' 144 * will be saved as an application preference so they can be used 145 * as defaults the next time around. 146 */ 147 public static void openDatabase() { 148 String[] labels = {" Username", " Password:", " " + SQL.getDBType().toUpperCase() + " Server", " Port", " Database (SID)"}; 149 150 // use this to get the return value from FieldEditDialog 151 ArrayList textFields = new ArrayList(); 152 153 // get the values the user entered the last time, for 154 // 'username' and 'database,' and use them as the default 155 // values here 156 JTextField username = new JTextField(20); 157 username.setText(CrimsonUtils.getUsername()); 158 JTextField server = new JTextField(30); 159 server.setText(CrimsonUtils.getServer()); 160 JTextField port = new JTextField(5); 161 port.setText(Integer.toString(CrimsonUtils.getPort())); 162 JTextField database = new JTextField(30); 163 database.setText(CrimsonUtils.getDatabase()); 164 165 textFields.add(username); 166 textFields.add(new JPasswordField(20)); 167 textFields.add(server); 168 textFields.add(port); 169 textFields.add(database); 170 171 new FieldEditDialog("Open Database", labels, textFields); 172 173 // check "exit code" for FieldEditDialog, if false then exit 174 Boolean exitCode = (Boolean) textFields.get(textFields.size()-1); 175 if (! exitCode.booleanValue()) return; 176 177 // Don't actually include password here or it would print on 178 // the screen. Because we don't want to the password to show, 179 // we have to run the command directly, not through console. 180 String msg = "openDatabase(\"" + username.getText(); 181 msg += "\", \"******\", \"" + server.getText() + "\", "; 182 msg += port.getText() + ", \"" + database.getText() + "\")"; 183 Root.runCommand(msg, false); 184 185 // open the database connection. If successful, the username, 186 // database, server, and port values will be saved as defaults 187 String password = ((JTextField) textFields.get(1)).getText(); 188 Database.open(username.getText(), password, server.getText(), 189 Integer.parseInt(port.getText()), database.getText()); 190 } 191 192 /** Create a file chooser for selecting a directory. */ 193 public static File directoryChooser() { 194 // use the current working directory 195 // fileChooser = new JFileChooser("."); 196 197 // set the title 198 fileChooser.setDialogTitle("Select Directory"); 199 200 // set the default filename 201 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 202 203 // save the file chooser 204 int status = fileChooser.showOpenDialog(null); 205 if (status == JFileChooser.APPROVE_OPTION) { 206 File file = fileChooser.getSelectedFile(); 207 208 if (file.exists()) return file; 209 210 // the file exist, so rerun the file chooser 211 String msg = "The directory \"" + getFilename(file) + "\" doesn't exist.\n"; 212 msg += "Do you want to create the directory?"; 213 int flag = JOptionPane.showConfirmDialog(null, msg, 214 "Overwrite Confirmation", 215 JOptionPane.YES_NO_OPTION); 216 if (flag == JOptionPane.YES_OPTION) { // "Create" 217 file.mkdir(); 218 return file; 219 } else { 220 return directoryChooser(); 221 } 222 } 223 224 return null; 225 } 226 227 /** Create a file chooser for opening files. */ 228 public static File openFileChooser(String title, FileFilter filter) { 229 // use the current working directory 230 // fileChooser = new JFileChooser("."); 231 232 // set the title 233 fileChooser.setDialogTitle(title); 234 235 // set the file filter 236 if (filter != null) fileChooser.setFileFilter(filter); 237 238 // open the file chooser 239 int status = fileChooser.showOpenDialog(null); 240 if (status == JFileChooser.APPROVE_OPTION) { 241 File file = fileChooser.getSelectedFile(); 242 243 if (file.exists()) return file; 244 245 // the file doesn't exist, so rerun the file chooser 246 JOptionPane.showMessageDialog(new Frame(), 247 "The file \"" + getFilename(file) 248 + "\" does not exist.", title, 249 JOptionPane.ERROR_MESSAGE); 250 return openFileChooser(title, filter); 251 } 252 253 return null; 254 } 255 256 /** Create a file chooser for saving files. */ 257 public static File saveFileChooser(String title, String name, FileFilter filter) { 258 // use the current working directory 259 // fileChooser = new JFileChooser("."); 260 261 // set the title 262 fileChooser.setDialogTitle(title); 263 264 // set the default filename 265 fileChooser.setSelectedFile(new File(name)); 266 267 // set the file filter 268 if (filter != null) fileChooser.setFileFilter(filter); 269 270 // save the file chooser 271 int status = fileChooser.showSaveDialog(null); 272 if (status == JFileChooser.APPROVE_OPTION) { 273 File file = fileChooser.getSelectedFile(); 274 275 if (! file.exists()) return file; 276 277 // the file exist, so rerun the file chooser 278 String msg = "The file \"" + getFilename(file) + "\" already exists.\n"; 279 msg += "Do you want to overwrite the file?"; 280 Object[] options = {"Overwrite", "Cancel"}; 281 int flag = JOptionPane.showOptionDialog(null, msg, 282 "Overwrite Confirmation", 283 JOptionPane.YES_NO_OPTION, 284 JOptionPane.QUESTION_MESSAGE, 285 null, 286 options, 287 options[1]); 288 if (flag == JOptionPane.YES_OPTION) { // "Overwrite" 289 return file; 290 } else { 291 return saveFileChooser(title, name, filter); 292 } 293 } 294 295 return null; 296 } 297 298 /** Python specific FileFilter. */ 299 public static class PyFilter extends FileFilter { 300 public boolean accept(File f) { 301 // accept directories 302 if (f.isDirectory()) return true; 303 304 // accept files ending in '.py' 305 if ((f.getName()).endsWith(".py")) return true; 306 307 return false; 308 } 309 310 public String getDescription() { return "Python scripts"; } 311 } 312 313 /** Filter used to limit JTextAreas to 4000 characters. */ 314 public static class DocumentLengthFilter extends DocumentFilter { 315 final int MAX_LENGTH = 4000; 316 317 public void insertString(FilterBypass doc, int offset, String str, 318 AttributeSet attrib) throws BadLocationException { 319 if ((doc.getDocument().getLength() + str.length()) <= MAX_LENGTH) 320 // the text fits, so add it 321 super.insertString(doc, offset, str, attrib); 322 else { 323 // the string is to large so only add up to the limit 324 int avail = MAX_LENGTH - doc.getDocument().getLength(); 325 if (avail > 0) super.insertString(doc, offset, str.substring(0,avail), attrib); 326 Toolkit.getDefaultToolkit().beep(); 327 } 328 } 329 330 public void replace(FilterBypass doc, int offset, int len, String str, 331 AttributeSet attrib) throws BadLocationException { 332 if ((doc.getDocument().getLength() + str.length() - len) <= MAX_LENGTH) 333 // the text fits, so add it 334 super.replace(doc, offset, len, str, attrib); 335 else { 336 // the string is to large so only add up to the limit 337 int avail = MAX_LENGTH - (doc.getDocument().getLength() - len); 338 if (avail > 0) super.replace(doc, offset, len, str.substring(0,avail), attrib); 339 Toolkit.getDefaultToolkit().beep(); 340 } 341 } 342 343 } 344 } // GUIUtils.java