Project: CIShell
/* **************************************************************************** 
 * CIShell: Cyberinfrastructure Shell, An Algorithm Integration Framework. 
 *  
 * All rights reserved. This program and the accompanying materials are made 
 * available under the terms of the Apache License v2.0 which accompanies 
 * this distribution, and is available at: 
 * http://www.apache.org/licenses/LICENSE-2.0.html 
 *  
 * Created on Sep 14, 2006 at Indiana University. 
 *  
 * Contributors: 
 *     Indiana University -  
 * ***************************************************************************/
package org.cishell.reference.gui.guibuilder.swt; 
 
import java.util.Dictionary; 
 
import org.cishell.reference.gui.guibuilder.swt.builder.GUIComponent; 
import org.cishell.reference.gui.guibuilder.swt.builder.UpdateListener; 
import org.cishell.service.guibuilder.GUI; 
import org.cishell.service.guibuilder.SelectionListener; 
import org.eclipse.swt.SWT; 
import org.eclipse.swt.events.DisposeEvent; 
import org.eclipse.swt.events.DisposeListener; 
import org.eclipse.swt.events.SelectionAdapter; 
import org.eclipse.swt.events.SelectionEvent; 
import org.eclipse.swt.graphics.Font; 
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.Label; 
import org.eclipse.swt.widgets.Shell; 
import org.osgi.service.metatype.MetaTypeProvider; 
import org.osgi.service.metatype.ObjectClassDefinition; 
 
public class SWTGui implements GUI, UpdateListener {     
 private static final int MAXIMUM_INITIAL_DIALOGUE_HEIGHT = 500
 
 public static final int TEXT_WRAP_LENGTH = 350
  
    private Shell shell; 
    private SWTGuiComposite composite; 
    private SelectionListener listener; 
    private boolean hitOk = false
     
    private Button okButton; 
 
    public SWTGui(final Shell shell, int style, String id, MetaTypeProvider provider) { 
        this.shell = shell; 
         
        if (provider == null) { 
            throw new IllegalArgumentException("Null MetaTypeProvider given"); 
        } 
         
        ObjectClassDefinition ocd = provider.getObjectClassDefinition(id, null); 
        this.shell.setText(ocd.getName()); 
 
        GridLayout gridLayout = new GridLayout(); 
        gridLayout.numColumns = 1
        this.shell.setLayout(gridLayout); 
 
        Font defaultFont = new Font(this.shell.getDisplay(), "SanSerif"8, SWT.NONE); 
         
        //stuff to display a message 
        String message = ocd.getDescription(); 
        if(message != null && !message.equals("")){ 
            Label msg = new Label(this.shell, SWT.WRAP); 
            msg.setText(message); 
            msg.pack(true); 
            GridData labelData = new GridData(); 
            labelData.horizontalAlignment = GridData.CENTER; 
            labelData.grabExcessHorizontalSpace = true
            if (msg.getSize().x > TEXT_WRAP_LENGTH) { 
             labelData.widthHint = TEXT_WRAP_LENGTH; 
            } 
            msg.setLayoutData(labelData); 
        } 
 
        //set up the user area where the main GUI will be set up using Parameters 
        composite = new SWTGuiComposite(this.shell, style, id, provider); 
        composite.addUpdateListener(this); 
         
        //the group w/ ok and cancel 
        Composite buttonsGroup = new Composite(this.shell, SWT.NONE); 
        FillLayout rowLayout = new FillLayout(); 
        rowLayout.spacing = 5
        buttonsGroup.setLayout(rowLayout); 
 
        //place them at the bottom right 
        GridData gridData = new GridData(); 
        gridData.horizontalAlignment = GridData.END; 
        gridData.grabExcessHorizontalSpace = false
        buttonsGroup.setLayoutData(gridData); 
 
        this.okButton = new Button(buttonsGroup, SWT.PUSH); 
        this.okButton.setText("OK"); 
        this.okButton.setSize(4020); 
        this.okButton.setFont(defaultFont); 
        this.okButton.addSelectionListener(new SelectionAdapter() { 
            public void widgetSelected(SelectionEvent e) { 
                hitOk = true
                close(); 
                 
                if (listener != null) { 
                    listener.hitOk(composite.getEnteredResponses()); 
                } 
            } 
        }); 
 
        Button cancel = new Button(buttonsGroup, SWT.NONE); 
        cancel.setText("Cancel"); 
        cancel.setSize(4020); 
        cancel.setFont(defaultFont); 
        cancel.addSelectionListener(new SelectionAdapter() { 
                public void widgetSelected(SelectionEvent e) {                     
                    close(); 
                } 
            }); 
 
         
        this.shell.addDisposeListener(new DisposeListener() { 
            public void widgetDisposed(DisposeEvent e) { 
                if (!hitOk && listener != null) { 
                    listener.cancelled(); 
                } 
            }}); 
         
        this.shell.setDefaultButton(this.okButton); 
         
        validate(); 
    } 
     
    /**
     * @see org.cishell.service.guibuilder.GUI#close() 
     */
 
    public void close() { 
        this.shell.getDisplay().syncExec(new Runnable() { 
            public void run() { 
                SWTGui.this.shell.close(); 
                SWTGui.this.shell.dispose(); 
            }}); 
    } 
 
    /**
     * @see org.cishell.service.guibuilder.GUI#isClosed() 
     */
 
    public boolean isClosed() { 
        return this.shell.isDisposed(); 
    } 
 
    /**
     * @see org.cishell.service.guibuilder.GUI#open() 
     */
 
    public void open() { 
        this.shell.getDisplay().syncExec(new Runnable() { 
            public void run() { 
                SWTGui.this.shell.pack(); 
                resizeShell(SWTGui.this.shell); 
                SWTGui.this.shell.open(); 
            } 
 
   private void resizeShell(Shell shell) { 
    Point shellSize = shell.getSize(); 
    shell.setSize(shellSize.x, calculateNewDialogHeight(shellSize.y)); 
   
 
   private int calculateNewDialogHeight(int proposedHeight) { 
    return Math.min(MAXIMUM_INITIAL_DIALOGUE_HEIGHT, proposedHeight); 
   }}); 
    } 
 
    /**
     * @see org.cishell.service.guibuilder.GUI#openAndWait() 
     */
 
    public Dictionary<String, Object> openAndWait() { 
        open(); 
        final Display display = shell.getDisplay(); 
         
        OpenAndWaitListener listener = new OpenAndWaitListener(); 
        setSelectionListener(listener); 
         
        display.syncExec(new Runnable() { 
            public void run() { 
                while (!isClosed()) { 
                    if (!display.readAndDispatch()) display.sleep(); 
                } 
            }}); 
         
        return listener.valuesEntered; 
    } 
     
    private static class OpenAndWaitListener implements SelectionListener { 
        Dictionary<String, Object> valuesEntered = null
 
        public void cancelled() {} 
 
        public void hitOk(Dictionary<String, Object> valuesEntered) { 
            this.valuesEntered = valuesEntered; 
        } 
    } 
 
    /**
     * @see org.cishell.service.guibuilder.GUI#setSelectionListener(org.cishell.service.guibuilder.SelectionListener) 
     */
 
    public void setSelectionListener(SelectionListener listener) { 
        this.listener = listener; 
    } 
     
    public String validate() { 
        String valid = composite.validate(); 
         
        // If valid is a string then the string is the error message. 
        if ((valid != null) && (valid.length() > 0)) { 
            this.okButton.setEnabled(false); 
        } else { 
            this.okButton.setEnabled(true); 
        } 
         
        return valid; 
    } 
 
    public void componentUpdated(GUIComponent component) { 
        validate(); 
    } 
}