package com.kartoflane.superluminal2.ui;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import com.kartoflane.common.selfpatch.SPDownloadWindow;
import com.kartoflane.superluminal2.Superluminal;
public class DownloadDialog implements SPDownloadWindow {
private static DownloadDialog instance = null;
private Shell shell = null;
private Composite barHolder = null;
private ProgressBar barProgress = null;
private Text txtStatus = null;
private Button btnContinue = null;
private Thread taskThread = null;
private boolean progressIndeterminate = false;
private boolean done = false;
private boolean succeeded = false;
public DownloadDialog( Shell parent ) {
if ( instance != null )
throw new IllegalStateException( "Previous instance has not been disposed!" );
instance = this;
shell = new Shell( parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL );
shell.setText( Superluminal.APP_NAME + " - Downloading" );
GridLayout gl_shell = new GridLayout( 1, false );
shell.setLayout( gl_shell );
barHolder = new Composite( shell, SWT.NONE );
barHolder.setLayoutData( new GridData( SWT.FILL, SWT.CENTER, true, false, 1, 1 ) );
barHolder.setLayout( new FillLayout( SWT.HORIZONTAL ) );
barProgress = new ProgressBar( barHolder, SWT.SMOOTH );
txtStatus = new Text( shell, SWT.BORDER );
txtStatus.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true, 1, 1 ) );
txtStatus.setEditable( false );
btnContinue = new Button( shell, SWT.NONE );
GridData gd_btnContinue = new GridData( SWT.CENTER, SWT.CENTER, true, false, 1, 1 );
gd_btnContinue.widthHint = 80;
btnContinue.setLayoutData( gd_btnContinue );
btnContinue.setText( "Continue" );
btnContinue.setEnabled( false );
shell.setSize( 400, 140 );
Point size = shell.getSize();
shell.setSize( size.x + 5, size.y );
Point parSize = parent.getSize();
Point parLoc = parent.getLocation();
shell.setLocation( parLoc.x + parSize.x / 2 - size.x / 2, parLoc.y + parSize.y / 3 - size.y / 2 );
btnContinue.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected( SelectionEvent e ) {
dispose();
}
} );
shell.addListener( SWT.Close, new Listener() {
@Override
public void handleEvent( Event e ) {
e.doit = false;
dispose();
}
} );
}
private void setIndeterminate( boolean indeterminate ) {
progressIndeterminate = indeterminate;
if ( barProgress != null && !barProgress.isDisposed() )
barProgress.dispose();
barProgress = new ProgressBar( barHolder, SWT.SMOOTH | ( indeterminate ? SWT.INDETERMINATE : SWT.NONE ) );
}
/**
* Updates the text area's content. (Thread-safe)
*
* @param message
* a string, or null
*/
public void setStatusTextLater( final String message ) {
shell.getDisplay().asyncExec( new Runnable() {
public void run() {
setStatusText( message != null ? message : "..." );
}
} );
}
protected void setStatusText( String message ) {
txtStatus.setText( message != null ? message : "..." );
}
/**
* Updates the progress bar. (Thread-safe)
*
* If the arg is -1, the bar will become indeterminate.
*
* @param value
* the new value
*/
public void setProgressLater( final int value ) {
shell.getDisplay().asyncExec( new Runnable() {
@Override
public void run() {
if ( value >= 0 ) {
if ( progressIndeterminate )
setIndeterminate( false );
barProgress.setSelection( value );
}
else {
if ( !progressIndeterminate )
setIndeterminate( true );
barProgress.setSelection( 0 );
}
}
} );
}
/**
* Updates the progress bar. (Thread-safe)
*
* If either arg is -1, the bar will become indeterminate.
*
* @param value
* the new value
* @param max
* the new maximum
*/
public void setProgressLater( final int value, final int max ) {
shell.getDisplay().asyncExec( new Runnable() {
@Override
public void run() {
if ( value >= 0 && max >= 0 ) {
if ( progressIndeterminate )
setIndeterminate( false );
if ( barProgress.getMaximum() != max ) {
barProgress.setSelection( 0 );
barProgress.setMaximum( max );
}
barProgress.setSelection( value );
}
else {
if ( !progressIndeterminate )
setIndeterminate( true );
barProgress.setSelection( 0 );
}
}
} );
}
/**
* Triggers a response to the immediate task ending. (Thread-safe)
*
* If anything went wrong, e may be non-null.
*/
public void setTaskOutcomeLater( final boolean success, final Exception e ) {
shell.getDisplay().asyncExec( new Runnable() {
@Override
public void run() {
setTaskOutcome( success, e );
}
} );
}
protected void setTaskOutcome( final boolean outcome, final Exception e ) {
done = true;
succeeded = outcome;
if ( !shell.isVisible() ) {
// The window's not visible, no continueBtn to click.
dispose();
}
btnContinue.setEnabled( true );
btnContinue.setFocus();
}
@Override
public void taskProgress( int value, int max ) {
this.setProgressLater( value, max );
}
@Override
public void taskStatus( String message ) {
setStatusTextLater( message != null ? message : "..." );
}
@Override
public void taskFinished( boolean outcome, Exception e ) {
setTaskOutcomeLater( outcome, e );
}
@Override
public void spShow() {
shell.open();
Display display = shell.getDisplay();
while ( !shell.isDisposed() ) {
if ( !display.readAndDispatch() )
display.sleep();
}
}
@Override
public void setTaskThread( Thread thread ) {
taskThread = thread;
}
public void dispose() {
if ( !done ) {
if ( taskThread != null ) {
taskThread.interrupt();
}
setProgressLater( 0, 100 );
setStatusTextLater( "Aborted by user." );
setTaskOutcomeLater( false, null );
}
else {
shell.dispose();
instance = null;
}
}
}