Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.stage; 027 028import java.io.File; 029import java.util.Arrays; 030import java.util.Collections; 031import java.util.List; 032 033import javafx.beans.property.ObjectProperty; 034import javafx.beans.property.SimpleObjectProperty; 035import javafx.beans.property.SimpleStringProperty; 036import javafx.beans.property.StringProperty; 037import javafx.collections.FXCollections; 038import javafx.collections.ObservableList; 039 040import com.sun.javafx.collections.annotations.ReturnsUnmodifiableCollection; 041import com.sun.javafx.tk.FileChooserType; 042import com.sun.javafx.tk.Toolkit; 043 044/** 045 * Provides support for standard platform file dialogs. These dialogs have look 046 * and feel of the platform UI components which is independent of JavaFX. 047 * <p> 048 * On some platforms where file access may be restricted or not part of the user 049 * model (for example, on some mobile or embedded devices), opening a file 050 * dialog may always result in a no-op (that is, null file(s) being returned). 051 * </p> 052 * <p> 053 * A {@code FileChooser} can be used to invoke file open dialogs for selecting 054 * single file ({@code showOpenDialog}), file open dialogs for selecting 055 * multiple files ({@code showOpenMultipleDialog}) and file save dialogs 056 * ({@code showSaveDialog}). The configuration of the displayed dialog is 057 * controlled by the values of the {@code FileChooser} properties set before the 058 * corresponding {@code show*Dialog} method is called. This configuration 059 * includes the dialog's title, the initial directory displayed in the dialog 060 * and the extension filter(s) for the listed files. For configuration 061 * properties which values haven't been set explicitly, the displayed dialog 062 * uses their platform default values. A call to a show dialog method is 063 * blocked until the user makes a choice or cancels the dialog. The return 064 * value specifies the selected file(s) or equals to {@code null} if the dialog 065 * has been canceled. 066 * </p> 067 * <p> 068 * Example: 069 * <pre><code> 070 * FileChooser fileChooser = new FileChooser(); 071 * fileChooser.setTitle("Open Resource File"); 072 * fileChooser.getExtensionFilters().addAll( 073 * new ExtensionFilter("Text Files", "*.txt"), 074 * new ExtensionFilter("Image Files", "*.png", "*.jpg", "*.gif"), 075 * new ExtensionFilter("Audio Files", "*.wav", "*.mp3", "*.aac"), 076 * new ExtensionFilter("All Files", "*.*")); 077 * File selectedFile = fileChooser.showOpenDialog(mainStage); 078 * if (selectedFile != null) { 079 * mainStage.display(selectedFile); 080 * } 081 * </code></pre> 082 * </p> 083 */ 084public final class FileChooser { 085 /** 086 * Defines an extension filter, used for filtering which files can be chosen 087 * in a FileDialog based on the file name extensions. 088 */ 089 public static final class ExtensionFilter { 090 private final String description; 091 private final List<String> extensions; 092 093 /** 094 * Creates an {@code ExtensionFilter} with the specified description 095 * and the file name extensions. 096 * <p> 097 * File name extension should be specified in the {@code *.<extension>} 098 * format. 099 * 100 * @param description the textual description for the filter 101 * @param extensions the accepted file name extensions 102 * @throws NullPointerException if the description or the extensions 103 * are {@code null} 104 * @throws IllegalArgumentException if the description or the extensions 105 * are empty 106 */ 107 public ExtensionFilter(final String description, 108 final String... extensions) { 109 validateArgs(description, extensions); 110 111 this.description = description; 112 this.extensions = Collections.unmodifiableList( 113 Arrays.asList(extensions.clone())); 114 } 115 116 /** 117 * Creates an {@code ExtensionFilter} with the specified description 118 * and the file name extensions. 119 * <p> 120 * File name extension should be specified in the {@code *.<extension>} 121 * format. 122 * 123 * @param description the textual description for the filter 124 * @param extensions the accepted file name extensions 125 * @throws NullPointerException if the description or the extensions 126 * are {@code null} 127 * @throws IllegalArgumentException if the description or the extensions 128 * are empty 129 */ 130 public ExtensionFilter(final String description, 131 final List<String> extensions) { 132 final String[] extensionsArray = 133 (extensions != null) ? extensions.toArray( 134 new String[extensions.size()]) 135 : null; 136 validateArgs(description, extensionsArray); 137 138 this.description = description; 139 this.extensions = Collections.unmodifiableList( 140 Arrays.asList(extensionsArray)); 141 } 142 143 /** 144 * Gets the description for this {@code ExtensionFilter}. 145 * 146 * @return the description 147 */ 148 public String getDescription() { 149 return description; 150 } 151 152 /** 153 * Gets the file name extensions for this {@code ExtensionFilter}. 154 * <p> 155 * The returned list is unmodifiable and will throw 156 * {@code UnsupportedOperationException} on each modification attempt. 157 * 158 * @return the file name extensions 159 */ 160 @ReturnsUnmodifiableCollection 161 public List<String> getExtensions() { 162 return extensions; 163 } 164 165 private static void validateArgs(final String description, 166 final String[] extensions) { 167 if (description == null) { 168 throw new NullPointerException("Description must not be null"); 169 } 170 171 if (description.isEmpty()) { 172 throw new IllegalArgumentException( 173 "Description must not be empty"); 174 } 175 176 if (extensions == null) { 177 throw new NullPointerException("Extensions must not be null"); 178 } 179 180 if (extensions.length == 0) { 181 throw new IllegalArgumentException( 182 "At least one extension must be defined"); 183 } 184 185 for (String extension : extensions) { 186 if (extension == null) { 187 throw new NullPointerException( 188 "Extension must not be null"); 189 } 190 191 if (extension.isEmpty()) { 192 throw new IllegalArgumentException( 193 "Extension must not be empty"); 194 } 195 } 196 } 197 } 198 199 /** 200 * The title of the displayed file dialog. 201 */ 202 private StringProperty title; 203 204 public final void setTitle(final String value) { 205 titleProperty().set(value); 206 } 207 208 public final String getTitle() { 209 return (title != null) ? title.get() : null; 210 } 211 212 public final StringProperty titleProperty() { 213 if (title == null) { 214 title = new SimpleStringProperty(this, "title"); 215 } 216 217 return title; 218 } 219 220 /** 221 * The initial directory for the displayed file dialog. 222 */ 223 private ObjectProperty<File> initialDirectory; 224 225 public final void setInitialDirectory(final File value) { 226 initialDirectoryProperty().set(value); 227 } 228 229 public final File getInitialDirectory() { 230 return (initialDirectory != null) ? initialDirectory.get() : null; 231 } 232 233 public final ObjectProperty<File> initialDirectoryProperty() { 234 if (initialDirectory == null) { 235 initialDirectory = 236 new SimpleObjectProperty<File>(this, "initialDirectory"); 237 } 238 239 return initialDirectory; 240 } 241 242 /** 243 * The initial file name for the displayed dialog. 244 * <p> 245 * This property is used mostly in the displayed file save dialogs as the 246 * initial file name for the file being saved. If set for a file open 247 * dialog it will have any impact on the displayed dialog only if the 248 * corresponding platform provides support for such property in its 249 * file open dialogs. 250 * </p> 251 * 252 * @since JavaFX 8.0 253 */ 254 private ObjectProperty<String> initialFileName; 255 256 public final void setInitialFileName(final String value) { 257 initialFileNameProperty().set(value); 258 } 259 260 public final String getInitialFileName() { 261 return (initialFileName != null) ? initialFileName.get() : null; 262 } 263 264 public final ObjectProperty<String> initialFileNameProperty() { 265 if (initialFileName == null) { 266 initialFileName = 267 new SimpleObjectProperty<String>(this, "initialFileName"); 268 } 269 270 return initialFileName; 271 } 272 273 /** 274 * Specifies the extension filters used in the displayed file dialog. 275 */ 276 private ObservableList<ExtensionFilter> extensionFilters = 277 FXCollections.<ExtensionFilter>observableArrayList(); 278 279 /** 280 * Gets the extension filters used in the displayed file dialog. Only 281 * one extension filter from the list is active at any time in the displayed 282 * dialog and only files which correspond to this extension filter are 283 * shown. The first extension filter from the list is activated when the 284 * dialog is invoked. Then the user can switch the active extension filter 285 * to any other extension filter from the list and in this way control the 286 * set of displayed files. 287 * 288 * @return An observable list of the extension filters used in this dialog 289 */ 290 public ObservableList<ExtensionFilter> getExtensionFilters() { 291 return extensionFilters; 292 } 293 294 /** 295 * Shows a new file open dialog. The method doesn't return until the 296 * displayed open dialog is dismissed. The return value specifies 297 * the file chosen by the user or {@code null} if no selection has been 298 * made. If the owner window for the file dialog is set, input to all 299 * windows in the dialog's owner chain is blocked while the file dialog 300 * is being shown. 301 * 302 * @param ownerWindow the owner window of the displayed file dialog 303 * @return the selected file or {@code null} if no file has been selected 304 */ 305 public File showOpenDialog(final Window ownerWindow) { 306 final List<File> selectedFiles = 307 showDialog(ownerWindow, FileChooserType.OPEN); 308 309 return ((selectedFiles != null) && (selectedFiles.size() > 0)) 310 ? selectedFiles.get(0) : null; 311 } 312 313 /** 314 * Shows a new file open dialog in which multiple files can be selected. 315 * The method doesn't return until the displayed open dialog is dismissed. 316 * The return value specifies the files chosen by the user or {@code null} 317 * if no selection has been made. If the owner window for the file dialog is 318 * set, input to all windows in the dialog's owner chain is blocked while 319 * the file dialog is being shown. 320 * <p> 321 * The returned list is unmodifiable and will throw 322 * {@code UnsupportedOperationException} on each modification attempt. 323 * 324 * @param ownerWindow the owner window of the displayed file dialog 325 * @return the selected files or {@code null} if no file has been selected 326 */ 327 @ReturnsUnmodifiableCollection 328 public List<File> showOpenMultipleDialog(final Window ownerWindow) { 329 final List<File> selectedFiles = 330 showDialog(ownerWindow, FileChooserType.OPEN_MULTIPLE); 331 332 return ((selectedFiles != null) && (selectedFiles.size() > 0)) 333 ? Collections.unmodifiableList(selectedFiles) 334 : null; 335 } 336 337 /** 338 * Shows a new file save dialog. The method doesn't return until the 339 * displayed file save dialog is dismissed. The return value specifies the 340 * file chosen by the user or {@code null} if no selection has been made. 341 * If the owner window for the file dialog is set, input to all windows in 342 * the dialog's owner chain is blocked while the file dialog is being shown. 343 * 344 * @param ownerWindow the owner window of the displayed file dialog 345 * @return the selected file or {@code null} if no file has been selected 346 */ 347 public File showSaveDialog(final Window ownerWindow) { 348 final List<File> selectedFiles = 349 showDialog(ownerWindow, FileChooserType.SAVE); 350 351 return ((selectedFiles != null) && (selectedFiles.size() > 0)) 352 ? selectedFiles.get(0) : null; 353 } 354 355 private List<File> showDialog(final Window ownerWindow, 356 final FileChooserType fileChooserType) { 357 return Toolkit.getToolkit().showFileChooser( 358 (ownerWindow != null) ? ownerWindow.impl_getPeer() : null, 359 getTitle(), 360 getInitialDirectory(), 361 getInitialFileName(), 362 fileChooserType, 363 extensionFilters); 364 365 } 366}