All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.swt.widgets.FileDialog Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2000, 2024 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    IBM Corporation - initial API and implementation
 *    Austin Riddle (Texas Center for Applied Technology) - RAP implementation
 *    EclipseSource - ongoing development
 *******************************************************************************/
package org.eclipse.swt.widgets;

import static org.eclipse.swt.internal.widgets.LayoutUtil.createButtonLayoutData;
import static org.eclipse.swt.internal.widgets.LayoutUtil.createFillData;
import static org.eclipse.swt.internal.widgets.LayoutUtil.createGridLayout;
import static org.eclipse.swt.internal.widgets.LayoutUtil.createHorizontalFillData;

import java.io.File;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.eclipse.rap.fileupload.DiskFileUploadReceiver;
import org.eclipse.rap.fileupload.FileUploadHandler;
import org.eclipse.rap.fileupload.UploadSizeLimitExceededException;
import org.eclipse.rap.fileupload.UploadTimeLimitExceededException;
import org.eclipse.rap.rwt.client.ClientFile;
import org.eclipse.rap.rwt.dnd.ClientFileTransfer;
import org.eclipse.rap.rwt.internal.RWTMessages;
import org.eclipse.rap.rwt.service.ServerPushSession;
import org.eclipse.rap.rwt.widgets.FileUpload;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.internal.widgets.FileUploadRunnable;
import org.eclipse.swt.internal.widgets.ProgressCollector;
import org.eclipse.swt.internal.widgets.UploadPanel;
import org.eclipse.swt.internal.widgets.Uploader;
import org.eclipse.swt.internal.widgets.UploaderService;
import org.eclipse.swt.internal.widgets.UploaderWidget;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;


/**
 * Instances of this class allow the user to navigate the file system and select
 * a file name. The selected file will be uploaded to the server and the path
 * made available as the result of the dialog.
 * 
*
Styles:
*
MULTI
*
Events:
*
(none)
*
*

* The OPEN style is applied by default and setting any other styles has no * effect. *

*

* IMPORTANT: This class is intended to be subclassed only within the * SWT implementation. *

* * @see FileDialog * snippets * @see SWT Example: * ControlExample, Dialog tab * @see Sample code and further * information */ @SuppressWarnings( "restriction" ) public class FileDialog extends Dialog { private static final String[] EMPTY_ARRAY = new String[ 0 ]; private final ServerPushSession pushSession; private ThreadPoolExecutor singleThreadExecutor; private Display display; private ScrolledComposite uploadsScroller; private Button okButton; private Label spacer; private UploadPanel placeHolder; private ProgressCollector progressCollector; private ClientFile[] clientFiles; private String[] filterExtensions; private long sizeLimit = -1; private long timeLimit = -1; private File uploadDirectory; /** * Constructs a new instance of this class given only its parent. * * @param parent a shell which will be the parent of the new instance * @exception IllegalArgumentException
    *
  • ERROR_NULL_ARGUMENT - if the parent is null
  • *
* @exception SWTException
    *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the parent
  • *
  • ERROR_INVALID_SUBCLASS - if this class is not an allowed * subclass
  • *
*/ public FileDialog( Shell parent ) { this( parent, SWT.TITLE | SWT.BORDER | SWT.APPLICATION_MODAL ); } /** * Constructs a new instance of this class given its parent and a style value * describing its behavior and appearance. *

* The style value is either one of the style constants defined in class * SWT which is applicable to instances of this class, or must be * built by bitwise OR'ing together (that is, using the * int "|" operator) two or more of those SWT style * constants. The class description lists the style constants that are * applicable to the class. Style bits are also inherited from superclasses. *

* * @param parent a shell which will be the parent of the new instance * @param style the style of dialog to construct * @exception IllegalArgumentException
    *
  • ERROR_NULL_ARGUMENT - if the parent is null
  • *
* @exception SWTException
    *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the parent
  • *
  • ERROR_INVALID_SUBCLASS - if this class is not an allowed * subclass
  • *
*/ public FileDialog( Shell parent, int style ) { super( parent, checkStyle( parent, style ) ); checkSubclass(); pushSession = new ServerPushSession(); } /** * Returns the path of the first file that was selected in the dialog relative * to the filter path, or an empty string if no such file has been selected. * * @return the relative path of the file */ public String getFileName() { String[] fileNames = getFileNames(); return fileNames.length == 0 ? "" : fileNames[ 0 ]; } /** * Returns a (possibly empty) array with the paths of all files that were * selected in the dialog relative to the filter path. * * @return the relative paths of the files */ public String[] getFileNames() { if( returnCode == SWT.OK ) { String[] completedFileNames = getCompletedFileNames(); if( isMulti() || completedFileNames.length == 0 ) { return completedFileNames; } return new String[] { completedFileNames[ completedFileNames.length - 1 ] }; } return EMPTY_ARRAY; } /** * Set the file extensions which the dialog will * use to filter the files it shows to the argument, * which may be null. *

* An extension filter string must be of the form ".extension". *

* * @param extensions the file extension filter * * @since 3.2 */ public void setFilterExtensions( String[] extensions ) { filterExtensions = extensions; } /** * Returns the file extensions which the dialog will * use to filter the files it shows. * * @return the file extensions filter * * @since 3.2 */ public String[] getFilterExtensions() { return filterExtensions; } /** * Sets initial client files to be uploaded. The upload of these files will start immediately * after opening the dialog. Hence, this method must be called before opening the dialog. *

* A user can drag and drop files from the client operating system on any control with a drop * listener attached. In this case, the client files can be obtained from the * {@link ClientFileTransfer} object. This FileDialog can then be used to handle the upload and * display upload progress. *

* * @param files an array of client files to be added to the dialog * * @rwtextension This method is not available in SWT. * @since 3.1 */ public void setClientFiles( ClientFile[] files ) { clientFiles = files; } /** * Sets the maximum upload size in bytes. If upload size is bigger it will be interrupted. * A value of -1 indicates no limit. * * @param limit the maximum upload size in bytes * * @see UploadSizeLimitExceededException * * @rwtextension This method is not available in SWT. * @since 3.3 */ public void setUploadSizeLimit( long limit ) { sizeLimit = limit; } /** * Returns the maximum upload size in bytes. The default value of -1 indicates no limit. * * @rwtextension This method is not available in SWT. * @since 3.3 */ public long getUploadSizeLimit() { return sizeLimit; } /** * Set the directory where the files should be uploaded to. If no directory is set or it is set to * null a temporary directory is used. * * @param directory the directory to upload to * @rwtextension This method is not available in SWT. * @since 3.7 */ public void setUploadDirectory( File directory ) { uploadDirectory = directory; } /** * Returns the directory where the files should be uploaded to, or null * when a temporary directory is used. * * @rwtextension This method is not available in SWT. * @since 3.7 */ public File getUploadDirectory() { return uploadDirectory; } /** * Sets the maximum upload duration in milliseconds. If upload takes longer it will be * interrupted. The default value of -1 indicates no limit. * * @param limit the maximum upload duration in milliseconds * * @see UploadTimeLimitExceededException * * @rwtextension This method is not available in SWT. * @since 3.3 */ public void setUploadTimeLimit( long limit ) { timeLimit = limit; } /** * Returns the maximum upload duration in milliseconds. The default value of -1 indicates no * limit. * * @rwtextension This method is not available in SWT. * @since 3.3 */ public long getUploadTimeLimit() { return timeLimit; } /** * Returns a list with exceptions thrown during the file upload. Will never return null. * * @see UploadSizeLimitExceededException * @see UploadTimeLimitExceededException * * @rwtextension This method is not available in SWT. * @since 3.3 */ public java.util.List getExceptions() { return progressCollector.getUploadExceptions(); } /** * Makes the dialog visible and brings it to the front * of the display. * * *

RAP Note: This method is not supported when running the application in * JEE_COMPATIBILITY mode. Use Dialog#open(DialogCallback) instead.

* * * @return a string describing the absolute path of the first selected file, * or null if the dialog was cancelled or an error occurred * * @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the dialog has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog
  • *
*/ public String open() { checkOperationMode(); prepareOpen(); runEventLoop( shell ); String fileName = getFileName(); return returnCode == SWT.CANCEL || "".equals( fileName ) ? null : fileName; } @Override protected void prepareOpen() { createShell(); createControls(); initializeBounds(); initializeDefaults(); pushSession.start(); singleThreadExecutor = createSingleThreadExecutor(); if( clientFiles != null && clientFiles.length > 0 ) { handleFileDrop( clientFiles ); } } private void createShell() { shell = new Shell( getParent(), getStyle() ); shell.setText( getText() ); shell.addDisposeListener( new DisposeListener() { @Override public void widgetDisposed( DisposeEvent event ) { cleanup(); } } ); display = shell.getDisplay(); } private void initializeBounds() { Point prefSize = shell.computeSize( SWT.DEFAULT, SWT.DEFAULT ); prefSize.y += isMulti() ? 165 : 10; shell.setMinimumSize( prefSize ); Rectangle displaySize = getParent().getDisplay().getBounds(); int locationX = ( displaySize.width - prefSize.x ) / 2 + displaySize.x; int locationY = ( displaySize.height - prefSize.y ) / 2 + displaySize.y; shell.setBounds( locationX, locationY, prefSize.x, prefSize.y ); // set spacer real layout data after shell prefer size calculation spacer.setLayoutData( createHorizontalFillData() ); } private void initializeDefaults() { setReturnCode( SWT.CANCEL ); } private void createControls() { shell.setLayout( createGridLayout( 1, 10, 10 ) ); createDialogArea( shell ); createButtonsArea( shell ); } private void createDialogArea( Composite parent ) { Composite dialogArea = new Composite( parent, SWT.NONE ); dialogArea.setLayoutData( createFillData() ); dialogArea.setLayout( createGridLayout( 1, 0, 5 ) ); createUploadsArea( dialogArea ); createProgressArea( dialogArea ); createDropTarget( dialogArea ); } private void createUploadsArea( Composite parent ) { uploadsScroller = new ScrolledComposite( parent, isMulti() ? SWT.V_SCROLL : SWT.NONE ); uploadsScroller.setLayoutData( createFillData() ); uploadsScroller.setExpandHorizontal( true ); uploadsScroller.setExpandVertical( true ); Composite scrolledContent = new Composite( uploadsScroller, SWT.NONE ); scrolledContent.setLayout( new GridLayout( 1, false ) ); uploadsScroller.setContent( scrolledContent ); uploadsScroller.addControlListener( new ControlAdapter() { @Override public void controlResized( ControlEvent event ) { updateScrolledComposite(); } } ); placeHolder = createPlaceHolder( scrolledContent ); } private UploadPanel createPlaceHolder( Composite parent ) { String text = isMulti() ? RWTMessages.getMessage( "RWT_FileDialogMultiUploadPanelMessage" ) : RWTMessages.getMessage( "RWT_FileDialogSingleUploadPanelMessage" ); UploadPanel panel = new UploadPanel( parent, new String[] { text } ); panel.setLayoutData( createHorizontalFillData() ); return panel; } private void createProgressArea( Composite parent ) { progressCollector = new ProgressCollector( parent ); progressCollector.setLayoutData( createHorizontalFillData() ); } private void createDropTarget( Control control ) { DropTarget dropTarget = new DropTarget( control, DND.DROP_MOVE | DND.DROP_COPY ); dropTarget.setTransfer( new Transfer[] { ClientFileTransfer.getInstance() } ); dropTarget.addDropListener( new DropTargetAdapter() { @Override public void dropAccept( DropTargetEvent event ) { if( !ClientFileTransfer.getInstance().isSupportedType( event.currentDataType ) ) { event.detail = DND.DROP_NONE; } } @Override public void drop( DropTargetEvent event ) { handleFileDrop( ( ClientFile[] )event.data ); } } ); } private void handleFileDrop( ClientFile[] clientFiles ) { placeHolder.dispose(); if( !isMulti() ) { clearUploadArea(); } ClientFile[] files = isMulti() ? clientFiles : new ClientFile[] { clientFiles[ 0 ] }; UploadPanel uploadPanel = createUploadPanel( getFileNames( files ) ); updateScrolledComposite(); Uploader uploader = new UploaderService( files ); DiskFileUploadReceiver receiver = new DiskFileUploadReceiver(); receiver.setUploadDirectory( uploadDirectory ); FileUploadHandler handler = new FileUploadHandler(receiver); handler.setMaxFileSize( sizeLimit ); handler.setUploadTimeLimit( timeLimit ); FileUploadRunnable uploadRunnable = new FileUploadRunnable( uploadPanel, progressCollector, uploader, handler ); singleThreadExecutor.execute( uploadRunnable ); } private static String[] getFileNames( ClientFile[] clientFiles ) { String[] fileNames = new String[ clientFiles.length ]; for( int i = 0; i < fileNames.length; i++ ) { fileNames[ i ] = clientFiles[ i ].getName(); } return fileNames; } private void createButtonsArea( Composite parent ) { Composite buttonsArea = new Composite( parent, SWT.NONE ); buttonsArea.setLayout( createGridLayout( 4, 0, 5 ) ); buttonsArea.setLayoutData( createHorizontalFillData() ); String text = isMulti() ? SWT.getMessage( "SWT_Add" ) : SWT.getMessage( "SWT_Browse" ); createFileUpload( buttonsArea, text ); createSpacer( buttonsArea ); okButton = createButton( buttonsArea, SWT.getMessage( "SWT_OK" ) ); parent.getShell().setDefaultButton( okButton ); okButton.forceFocus(); okButton.addListener( SWT.Selection, new Listener() { @Override public void handleEvent( Event event ) { okPressed(); } } ); Button cancelButton = createButton( buttonsArea, SWT.getMessage( "SWT_Cancel" ) ); cancelButton.addListener( SWT.Selection, new Listener() { @Override public void handleEvent( Event event ) { cancelPressed(); } } ); } protected FileUpload createFileUpload( Composite parent, String text ) { FileUpload fileUpload = new FileUpload( parent, isMulti() ? SWT.MULTI : SWT.NONE ); fileUpload.setText( text ); fileUpload.setLayoutData( createButtonLayoutData( fileUpload ) ); if( filterExtensions != null ) { fileUpload.setFilterExtensions( filterExtensions ); } fileUpload.addListener( SWT.Selection, new Listener() { @Override public void handleEvent( Event event ) { handleFileUploadSelection( ( FileUpload )event.widget ); } } ); fileUpload.moveAbove( null ); return fileUpload; } private void createSpacer( Composite buttonArea ) { spacer = new Label( buttonArea, SWT.NONE ); spacer.setLayoutData( createButtonLayoutData( spacer ) ); } protected Button createButton( Composite parent, String text ) { Button button = new Button( parent, SWT.PUSH ); button.setText( text ); button.setLayoutData( createButtonLayoutData( button ) ); return button; } private void handleFileUploadSelection( FileUpload fileUpload ) { placeHolder.dispose(); if( !isMulti() ) { clearUploadArea(); } UploadPanel uploadPanel = createUploadPanel( fileUpload.getFileNames() ); updateScrolledComposite(); updateButtonsArea( fileUpload ); Uploader uploader = new UploaderWidget( fileUpload ); DiskFileUploadReceiver receiver = new DiskFileUploadReceiver(); receiver.setUploadDirectory( uploadDirectory ); FileUploadHandler handler = new FileUploadHandler( receiver ); handler.setMaxFileSize( sizeLimit ); handler.setUploadTimeLimit( timeLimit ); FileUploadRunnable uploadRunnable = new FileUploadRunnable( uploadPanel, progressCollector, uploader, handler ); singleThreadExecutor.execute( uploadRunnable ); } private void updateScrolledComposite() { Composite content = ( Composite )uploadsScroller.getContent(); for( int i = 0; i < 2; i++ ) { // workaround for bug 414868 Rectangle clientArea = uploadsScroller.getClientArea(); Point minSize = content.computeSize( clientArea.width, SWT.DEFAULT ); uploadsScroller.setMinSize( minSize ); } uploadsScroller.setOrigin( 0, 10000 ); content.layout(); } private void updateButtonsArea( FileUpload fileUpload ) { Composite buttonsArea = fileUpload.getParent(); hideControl( fileUpload ); String text = isMulti() ? SWT.getMessage( "SWT_Add" ) : SWT.getMessage( "SWT_Browse" ); createFileUpload( buttonsArea, text ); buttonsArea.layout(); } private UploadPanel createUploadPanel( String[] fileNames ) { Composite parent = ( Composite )uploadsScroller.getContent(); UploadPanel uploadPanel = new UploadPanel( parent, fileNames ); uploadPanel.setLayoutData( createHorizontalFillData() ); return uploadPanel; } private void clearUploadArea() { Composite parent = ( Composite )uploadsScroller.getContent(); for( Control child : parent.getChildren() ) { child.dispose(); } } private static void hideControl( Control control ) { if( control != null ) { GridData layoutData = ( GridData )control.getLayoutData(); layoutData.exclude = true; control.setVisible( false ); } } private void setButtonEnabled( final boolean enabled ) { if( !display.isDisposed() ) { display.asyncExec( new Runnable() { @Override public void run() { if( !okButton.isDisposed() ) { okButton.setEnabled( enabled ); } } } ); } } private void okPressed() { setReturnCode( SWT.OK ); close(); } private void cancelPressed() { setReturnCode( SWT.CANCEL ); close(); } private void setReturnCode( int code ) { returnCode = code; } private boolean isMulti() { return ( getStyle() & SWT.MULTI ) != 0; } private void close() { shell.close(); } private void cleanup() { pushSession.stop(); singleThreadExecutor.shutdownNow(); if( returnCode == SWT.CANCEL ) { deleteUploadedFiles( progressCollector.getCompletedFileNames() ); } } void deleteUploadedFiles( String[] fileNames ) { for( String fileName : fileNames ) { File file = new File( fileName ); if( file.exists() ) { file.delete(); } } } static int checkStyle( Shell parent, int style ) { int result = style; int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL; if( ( result & SWT.SHEET ) != 0 ) { result &= ~SWT.SHEET; if( ( result & mask ) == 0 ) { result |= parent == null ? SWT.APPLICATION_MODAL : SWT.PRIMARY_MODAL; } } if( ( result & mask ) == 0 ) { result |= SWT.APPLICATION_MODAL; } if( ( result & ( SWT.LEFT_TO_RIGHT ) ) == 0 ) { if( parent != null ) { if( ( parent.getStyle() & SWT.LEFT_TO_RIGHT ) != 0 ) { result |= SWT.LEFT_TO_RIGHT; } } } result |= SWT.TITLE | SWT.BORDER; result &= ~SWT.MIN; return result; } String[] getCompletedFileNames() { return progressCollector.getCompletedFileNames(); } ThreadPoolExecutor createSingleThreadExecutor() { return new SingleThreadExecutor(); } private final class SingleThreadExecutor extends ThreadPoolExecutor { public SingleThreadExecutor() { super( 1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>() ); } @Override public void execute( Runnable command ) { setButtonEnabled( false ); super.execute( command ); } @Override protected void afterExecute( Runnable runnable, Throwable throwable ) { if( getQueue().size() == 0 ) { setButtonEnabled( true ); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy