Changeset 1175

Show
Ignore:
Timestamp:
05/25/08 06:40:06 (3 months ago)
Author:
fraserofthenight
Message:

Ack; didn't realize I broke the build! Also, more UI.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/descent.building/src/descent/building/IDescentBuilderConstants.java

    r1174 r1175  
    6565     */ 
    6666    public static final String ATTR_COMPILER_ID = "descent.building.debuild.compiler_id"; 
     67     
     68    /** 
     69     * Specifies the target output type. Must be one of {@link #OUTPUT_TYPE_EXECUTABLE} 
     70     * or {@link #OUTPUT_TYPE_STATIC_LIBRARY}. Support may be added in the future for 
     71     * OS dynamic libraries (.dll/.so) and/or DDL. 
     72     *  
     73     * Type: String 
     74     */ 
     75    public static final String ATTR_OUTPUT_TYPE = "descent.building.debuild.output_type"; 
     76     
     77    /** 
     78     * Specifies the target output file location. 
     79     *  
     80     * Type: String 
     81     */ 
     82    public static final String ATTR_OUTPUT_FILE = "descent.building.debuild.output_file"; 
     83     
     84    /** 
     85     * Constant used for {@link #ATTR_OUTPUT_TYPE} to specify the output target 
     86     * should be an executable file. 
     87     */ 
     88    public static final String OUTPUT_TYPE_EXECUTABLE = "executable"; 
     89     
     90    /** 
     91     * Constant used for {@link #ATTR_OUTPUT_TYPE} to specify the output target 
     92     * should be a static library (.lib or .a) 
     93     */ 
     94    public static final String OUTPUT_TYPE_STATIC_LIBRARY = "static_library"; 
    6795} 
  • trunk/descent.building/src/descent/internal/building/debuild/DebuildBuilder.java

    r1174 r1175  
    1717import descent.core.IJavaProject; 
    1818import descent.core.JavaModelException; 
     19import descent.internal.building.BuilderUtil; 
    1920import descent.building.IDBuilder; 
    2021import descent.building.compiler.BuildError; 
     
    156157                case IClasspathEntry.CPE_SOURCE: 
    157158                case IClasspathEntry.CPE_LIBRARY: 
    158                     importPath.add(new File(Util.getAbsolutePath(entry.getPath()))); 
     159                    importPath.add(new File(BuilderUtil.getAbsolutePath(entry.getPath()))); 
    159160                    break; 
    160161                case IClasspathEntry.CPE_PROJECT: 
     
    191192            ICompilerInterface compilerInterface = req.getCompilerInterface(); 
    192193            IJavaProject project = req.getProject(); 
    193             String workingDirectory = Util.getAbsolutePath(project.getOutputLocation()); 
     194            String workingDirectory = BuilderUtil.getAbsolutePath(project.getOutputLocation()); 
    194195            File outputDirectory = new File(workingDirectory); 
    195196             
     
    298299        return EXECUTABLE_FILE_PREFIX + 
    299300            System.currentTimeMillis() + 
    300             (Util.isWindows() ? 
    301                 ".exe" : 
    302                 ""); 
     301            BuilderUtil.EXTENSION_EXECUTABLE; 
    303302    } 
    304303} 
  • trunk/descent.building/src/descent/internal/building/debuild/ObjectFile.java

    r1174 r1175  
    1515import descent.core.IJavaProject; 
    1616import descent.core.JavaModelException; 
     17import descent.internal.building.BuilderUtil; 
    1718import descent.internal.building.BuildingPlugin; 
    1819 
     
    337338    private String getExtension() 
    338339    { 
    339         return Util.isWindows() ? ".obj" : ".o"; 
    340     } 
    341      
    342     public static void main(String[] args) 
    343     { 
    344         for(Entry<Object, Object> prop : System.getProperties().entrySet()) 
    345             System.out.format("%1$s = %2$s\n", prop.getKey(), prop.getValue()); 
     340        return BuilderUtil.EXTENSION_OBJECT_FILE; 
    346341    } 
    347342     
     
    350345        try 
    351346        { 
    352             return Util.getAbsolutePath(project.getOutputLocation()); 
     347            return BuilderUtil.getAbsolutePath(project.getOutputLocation()); 
    353348        } 
    354349        catch(JavaModelException e) 
  • trunk/descent.building/src/descent/internal/building/debuild/RecursiveDependancyCollector.java

    r1174 r1175  
    2323import descent.core.IParent; 
    2424import descent.core.JavaModelException; 
     25import descent.internal.building.BuilderUtil; 
    2526/** 
    2627 * Class that can recurse through dependancies to generate a list of all files 
     
    145146    { 
    146147        return new ObjectFile(project, 
    147                 new File(Util.getAbsolutePath(cu.getPath())), 
     148                new File(BuilderUtil.getAbsolutePath(cu.getPath())), 
    148149                cu.getFullyQualifiedName(), 
    149150                isLibraryFile); 
  • trunk/descent.building/src/descent/internal/building/ui/AbstractBuilderTab.java

    r1174 r1175  
    66import org.eclipse.core.resources.IWorkspaceRoot; 
    77import org.eclipse.core.resources.ResourcesPlugin; 
     8import org.eclipse.core.runtime.CoreException; 
    89import org.eclipse.debug.core.ILaunchConfiguration; 
    910import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; 
     
    1314import org.eclipse.jface.resource.JFaceResources; 
    1415import org.eclipse.swt.SWT; 
     16import org.eclipse.swt.events.ModifyEvent; 
     17import org.eclipse.swt.events.ModifyListener; 
     18import org.eclipse.swt.events.SelectionAdapter; 
     19import org.eclipse.swt.events.SelectionEvent; 
     20import org.eclipse.swt.events.SelectionListener; 
    1521import org.eclipse.swt.graphics.Image; 
    1622import org.eclipse.swt.layout.GridData; 
     
    2127import org.eclipse.swt.widgets.Label; 
    2228import org.eclipse.swt.widgets.Layout; 
     29import org.eclipse.swt.widgets.Text; 
    2330import org.eclipse.ui.IEditorInput; 
    2431import org.eclipse.ui.IEditorPart; 
     
    3542import descent.internal.ui.util.PixelConverter; 
    3643 
    37 // TODO comments 
    38 public abstract class AbstractBuilderTab extends AbstractLaunchConfigurationTab 
     44/** 
     45 * Defines a shared implementation for all the builder tabs used in the Descent 
     46 * builder configuration. In addition to a number of useful convience methods, 
     47 * this provides a setting interface which implementations can use to encapsulate 
     48 * the various settings they provide. See {@link descent.internal.building.ui.AbstractBuilderTab.ISetting} 
     49 * for more information. 
     50 *  
     51 * @author Robert Fraser 
     52 */ 
     53/* package */ abstract class AbstractBuilderTab extends AbstractLaunchConfigurationTab 
    3954{ 
    4055    //-------------------------------------------------------------------------- 
    4156    // Setting interface 
    4257     
    43     protected interface ISetting 
    44     { 
     58    /** 
     59     * A setting is a way to encapsulate controls and UI logic related to a 
     60     * one or more attributes. Since a single tab page usually consists of many 
     61     * different settings that rarely interact, this is an way to avoid namespace 
     62     * clashes and ensure updates are applied throughout. An AbstractBuilderTab 
     63     * consists of one or more of these, set by the getSettings() method. 
     64     */ 
     65    protected static interface ISetting 
     66    { 
     67        /** 
     68         * Adds the settings to the control. Settings will be added in the order 
     69         * of the array returned by the getSettings() method. 
     70         *  
     71         * @param comp the tab to add the controls to 
     72         * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite) 
     73         */ 
    4574        public void addToControl(Composite comp); 
     75         
     76        /** 
     77         * Initialize the launch configuration with information about this setting. 
     78         *  
     79         * @param config the launch config to initialize. 
     80         * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration) 
     81         */ 
    4682        public void initializeFrom(ILaunchConfiguration config); 
     83         
     84        /** 
     85         * Applies the setting to the given launch configuration. 
     86         *  
     87         * @param config the config to apply the setting to 
     88         * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) 
     89         */ 
    4790        public void performApply(ILaunchConfigurationWorkingCopy config); 
     91         
     92        /** 
     93         * Sets the default values in the configuration. 
     94         *  
     95         * @param config 
     96         * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) 
     97         */ 
    4898        public void setDefaults(ILaunchConfigurationWorkingCopy config); 
     99         
     100        /** 
     101         * Checks whether the setting is valid. If the setting is not valid, this 
     102         * should set the error message on the page. 
     103         */ 
    49104        public void validate(); 
    50105    } 
     
    67122        private Group fGroup; 
    68123         
     124        /** 
     125         * Creates a new group setting with the given parameters 
     126         *  
     127         * @param label       the label to apply to the group 
     128         * @param width       the width (number of columns) the group should 
     129         *                    take up on the top GridLayout. 
     130         * @param numColumns  the number of columns the resulting group should 
     131         *                    have. 
     132         * @param subSettings the settings within the group 
     133         */ 
    69134        public GroupSetting(String label, int width, int numColumns, 
    70135                ISetting[] subSettings) 
     
    110175                    return; 
    111176            } 
     177        } 
     178    } 
     179     
     180    //-------------------------------------------------------------------------- 
     181    // Text setting 
     182     
     183    /** 
     184     * A setting that consists of a text field, optionally with a browse button. 
     185     */ 
     186    protected abstract class TextSetting implements ISetting 
     187    { 
     188        private final String fAttribute; 
     189        private final String fLabelString; 
     190        private final int fNumColumns; 
     191        private final boolean fBrowseButton; 
     192        private final boolean fEditable; 
     193         
     194        protected Label fLabel; 
     195        protected Text fText; 
     196        protected Button fButton; 
     197         
     198        /** 
     199         * Creates a new text setting with the given parameters. 
     200         *  
     201         * @param attribute     the attribute the text setting refers to 
     202         * @param label         the text of the label 
     203         * @param numColumns    the number of columns the three controls should 
     204         *                      take up. Must be >= 2 if no browse button and 
     205         *                      >= 3 if there is a browse button 
     206         * @param browseButton  should there be a browse button? if this is true, 
     207         *                      numColumns must be >= 3 and {@link #browse()} must 
     208         *                      be implemented in the subclass. 
     209         * @param editable      sets whether or not the text field is editable. 
     210         *                      This should only be false if browseButton is true, 
     211         *                      for obvious reasons. 
     212         */ 
     213        protected TextSetting(String attribute, String label, int numColumns, 
     214                boolean browseButton, boolean editable) 
     215        { 
     216            fAttribute = attribute; 
     217            fLabelString = label; 
     218            fNumColumns = numColumns; 
     219            fBrowseButton = browseButton; 
     220            fEditable = editable; 
     221        } 
     222         
     223        public final void addToControl(Composite comp) 
     224        { 
     225            fLabel = new Label(comp, SWT.NONE); 
     226            fLabel.setText(fLabelString); 
     227            GridData gd = new GridData(); 
     228            gd.horizontalSpan = 1; 
     229            fLabel.setLayoutData(gd); 
     230     
     231            fText = new Text(comp, SWT.SINGLE | SWT.BORDER); 
     232            gd = new GridData(GridData.FILL_HORIZONTAL); 
     233            gd.horizontalSpan = fNumColumns - (fBrowseButton ? 2 : 1); 
     234            fText.setLayoutData(gd); 
     235            fText.setEditable(fEditable); 
     236            fText.addModifyListener(new ModifyListener() 
     237            { 
     238                public void modifyText(ModifyEvent evt) 
     239                { 
     240                    validatePage(); 
     241                    updateLaunchConfigurationDialog(); 
     242                } 
     243            }); 
     244             
     245            if(fBrowseButton) 
     246            { 
     247                fButton = new Button(comp, SWT.PUSH); 
     248                fButton.setText("Browse..."); 
     249                gd = new GridData(); 
     250                gd.horizontalSpan = 1; 
     251                fButton.setLayoutData(gd); 
     252                setButtonDimensionHint(fButton); 
     253                fButton.addSelectionListener(new SelectionAdapter() 
     254                { 
     255                    public void widgetSelected(SelectionEvent evt) 
     256                    { 
     257                        String text = browse(); 
     258                        if(null != text) 
     259                            fText.setText(text); 
     260                    } 
     261                }); 
     262            } 
     263        } 
     264         
     265        /** 
     266         * The function to call when the browse button is selected. If 
     267         * browseButton is true, this must be specified. 
     268         *  
     269         * @return the new text to place in the field 
     270         */ 
     271        protected String browse() 
     272        { 
     273            throw new UnsupportedOperationException(); 
     274        } 
     275 
     276        public final void initializeFrom(ILaunchConfiguration config) 
     277        { 
     278            String value = ""; 
     279            try 
     280            { 
     281                value = config.getAttribute(fAttribute, ""); 
     282            } 
     283            catch(CoreException e) { } 
     284             
     285            fText.setText(value); 
     286        } 
     287 
     288        public final void performApply(ILaunchConfigurationWorkingCopy config) 
     289        { 
     290            config.setAttribute(fAttribute, fText.getText().trim()); 
    112291        } 
    113292    } 
     
    343522     * @param numColumns the number of columns it should take up 
    344523     */ 
    345     protected Label createSpacer(Composite parent, int numColumns) 
     524    protected static Label createSpacer(Composite parent, int numColumns) 
    346525    { 
    347526        Label spacer = new Label(parent, SWT.NONE); 
     
    358537    } 
    359538     
     539    protected Button createRadioButton(Composite parent, int numColumns,  
     540            String label, int indent, SelectionListener listener) 
     541    { 
     542        final Button button = new Button(parent, SWT.RADIO); 
     543        button.setText(label); 
     544        GridData gd = new GridData(); 
     545        gd.horizontalSpan = numColumns; 
     546        gd.horizontalIndent = indent; 
     547        button.setLayoutData(gd); 
     548         
     549        if(null == listener) 
     550            listener = new SelectionAdapter() 
     551            { 
     552                public void widgetSelected(SelectionEvent e) 
     553                { 
     554                    if(button.getSelection()) 
     555                        updateLaunchConfigurationDialog(); 
     556                } 
     557            }; 
     558        button.addSelectionListener(listener); 
     559         
     560        return button; 
     561    } 
     562     
    360563    /** 
    361564     * Convenience method to get access to the java model. 
  • trunk/descent.building/src/descent/internal/building/ui/CompilerTab.java

    r1174 r1175  
    1010import org.eclipse.swt.events.ModifyEvent; 
    1111import org.eclipse.swt.events.ModifyListener; 
     12import org.eclipse.swt.events.SelectionAdapter; 
     13import org.eclipse.swt.events.SelectionEvent; 
    1214import org.eclipse.swt.layout.GridData; 
    1315import org.eclipse.swt.layout.GridLayout; 
     
    1719import org.eclipse.swt.widgets.Layout; 
    1820import org.eclipse.swt.widgets.Link; 
     21import org.eclipse.ui.dialogs.PreferencesUtil; 
    1922 
    2023import descent.building.IDescentBuilderConstants; 
     
    2326import descent.launching.JavaRuntime; 
    2427 
    25 public class CompilerTab extends AbstractBuilderTab 
     28/* package */ final class CompilerTab extends AbstractBuilderTab 
    2629{ 
    2730    //-------------------------------------------------------------------------- 
     
    4750            gd.horizontalSpan = 1; 
    4851            fHelpText.setLayoutData(gd); 
     52            fHelpText.addSelectionListener(new SelectionAdapter() 
     53            { 
     54                public void widgetSelected(SelectionEvent e) 
     55                { 
     56                    PreferencesUtil.createPreferenceDialogOn(getShell(), 
     57                            "descent.debug.ui.preferences.VMPreferencePage", 
     58                            null, null).open(); 
     59                     
     60                    // Reset stuff so new changes are reflected in this dialog 
     61                    reinitializeCompilers(); 
     62                    int selectionIndex = fCombo.getSelectionIndex(); 
     63                    resetComboItems(); 
     64                    fCombo.select(fCombo.getSelectionIndex() >= fCompilers.length ? 
     65                            0 : selectionIndex); 
     66                }  
     67            }); 
    4968             
    5069            createSpacer(fGroup, 1); 
     
    6281                            fCompilers[selectedIndex] : null; 
    6382                    compilerOptions.compilerModeChanged(selectedCompiler); 
     83                     
     84                    validatePage(); 
     85                    updateLaunchConfigurationDialog(); 
    6486                } 
    6587            }); 
    6688             
    6789            initializeCompilers(); 
    68             String[] items = new String[fCompilers.length]; 
    69             for(int i = 0; i < items.length; i++) 
    70                 items[i] = getCompilerLabel(fCompilers[i]); 
    71             fCombo.setItems(items); 
    72         } 
    73          
     90            resetComboItems(); 
     91        } 
     92         
     93        /** 
     94         * Initialize compilers if they haven't been initialized (since I'm not 
     95         * sure which order createControl and setDefaults will be set in) 
     96         */ 
    7497        private void initializeCompilers() 
    7598        { 
     
    77100                return; 
    78101             
     102            reinitializeCompilers(); 
     103        } 
     104         
     105        /** 
     106         * Reset the compiler list whether it's already been set or not 
     107         */ 
     108        private void reinitializeCompilers() 
     109        { 
    79110            List<IVMInstall> compilers = new ArrayList<IVMInstall>(); 
    80111            for(IVMInstallType vmInstallType : JavaRuntime.getVMInstallTypes()) 
     
    82113                    compilers.add(vmInstall); 
    83114            fCompilers = compilers.toArray(new IVMInstall[compilers.size()]); 
     115        } 
     116         
     117        private void resetComboItems() 
     118        { 
     119            String[] items = new String[fCompilers.length]; 
     120            for(int i = 0; i < items.length; i++) 
     121                items[i] = getCompilerLabel(fCompilers[i]); 
     122            fCombo.setItems(items); 
    84123        } 
    85124         
     
    106145            try 
    107146            { 
    108                 compilerTypeId = config.getAttribute(IDescentBuilderConstants.ATTR_COMPILER_ID, ""); 
     147                compilerId = config.getAttribute(IDescentBuilderConstants.ATTR_COMPILER_ID, ""); 
    109148            } 
    110149            catch(CoreException e) { } 
  • trunk/descent.building/src/descent/internal/building/ui/DebuildTabGroup.java

    r1174 r1175  
    1212        ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] 
    1313        { 
    14              new BuildTab(), 
     14             new GeneralTab(), 
    1515             new CompilerTab(), 
    1616             new EnvironmentTab(), 
  • trunk/descent.building/src/descent/internal/building/ui/GeneralTab.java

    r1174 r1175  
    99import org.eclipse.core.runtime.IPath; 
    1010import org.eclipse.core.runtime.IStatus; 
     11import org.eclipse.core.runtime.Path; 
    1112import org.eclipse.debug.core.ILaunchConfiguration; 
    1213import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; 
     
    1415import org.eclipse.jface.window.Window; 
    1516import org.eclipse.swt.SWT; 
    16 import org.eclipse.swt.events.ModifyEvent; 
    17 import org.eclipse.swt.events.ModifyListener; 
    1817import org.eclipse.swt.events.SelectionAdapter; 
    1918import org.eclipse.swt.events.SelectionEvent; 
     
    2221import org.eclipse.swt.widgets.Button; 
    2322import org.eclipse.swt.widgets.Composite; 
     23import org.eclipse.swt.widgets.FileDialog; 
     24import org.eclipse.swt.widgets.Group; 
    2425import org.eclipse.swt.widgets.Label; 
    2526import org.eclipse.swt.widgets.Layout; 
    26 import org.eclipse.swt.widgets.Text; 
    2727import org.eclipse.ui.dialogs.ElementListSelectionDialog; 
    2828 
    29 import descent.building.IDescentBuilderConstants; 
    3029import descent.core.IJavaProject; 
    3130import descent.core.JavaCore; 
    3231import descent.core.JavaModelException; 
     32import descent.internal.building.BuilderUtil; 
    3333import descent.internal.building.BuildingPlugin; 
    3434import descent.internal.ui.wizards.dialogfields.DialogField; 
     
    3939import descent.ui.JavaElementSorter; 
    4040 
     41import static descent.building.IDescentBuilderConstants.*; 
     42 
    4143@SuppressWarnings("unchecked") 
    42 public class BuildTab extends AbstractBuilderTab 
    43 {     
     44/* package */ final class GeneralTab extends AbstractBuilderTab 
     45{    
    4446    //-------------------------------------------------------------------------- 
    4547    // Project selection 
    4648     
    47     private final class ProjectSetting implements ISetting 
    48     {  
    49         private Label fLabel; 
    50         private Text fText; 
    51         private Button fButton; 
    52          
    53         public void addToControl(Composite comp) 
    54         { 
    55             fLabel = new Label(comp, SWT.NONE); 
    56             fLabel.setText("Project:"); 
    57             GridData gd = new GridData(); 
    58             fLabel.setLayoutData(gd); 
    59      
    60             fText = new Text(comp, SWT.SINGLE | SWT.BORDER); 
    61             fText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 
    62             fText.addModifyListener(new ModifyListener() 
    63             { 
    64                 public void modifyText(ModifyEvent evt) 
    65                 { 
    66                     validatePage(); 
    67                     updateLaunchConfigurationDialog(); 
    68                 } 
    69             }); 
    70      
    71             fButton = new Button(comp, SWT.PUSH); 
    72             fButton.setText("Browse..."); 
    73             gd = new GridData(); 
    74             fButton.setLayoutData(gd); 
    75             setButtonDimensionHint(fButton); 
    76             fButton.addSelectionListener(new SelectionAdapter() 
    77             { 
    78                 public void widgetSelected(SelectionEvent evt) 
    79                 { 
    80                     handleProjectButtonSelected(); 
    81                 } 
    82             }); 
     49    private final class ProjectSetting extends TextSetting 
     50    { 
     51        ProjectSetting() 
     52        { 
     53            super(ATTR_PROJECT_NAME, "Project:", 3, true, false); 
    8354        } 
    8455         
     
    8758         * context for choosing the container that should be run. 
    8859         */ 
    89         private void handleProjectButtonSelected() 
     60        @Override 
     61        protected String browse() 
    9062        { 
    9163            IJavaProject project = chooseJavaProject(); 
    92             if (project == null) 
    93             { 
    94                 return; 
    95             } 
    96      
    97             String projectName = project.getElementName(); 
    98             fText.setText(projectName); 
     64            if(null != project) 
     65            { 
     66                String name = project.getElementName(); 
     67                if(!name.equals(fText.getText())) 
     68                    outputFileSetting.projectChanged(project); 
     69                return name; 
     70            } 
     71            else 
     72            { 
     73                return null; 
     74            } 
    9975        } 
    10076         
     
    149125        } 
    150126 
    151         public void initializeFrom(ILaunchConfiguration config) 
    152         { 
    153             String projectName = ""; 
    154             try 
    155             { 
    156                 projectName = config.getAttribute(IDescentBuilderConstants.ATTR_PROJECT_NAME, ""); 
    157             } 
    158             catch(CoreException e) { } 
    159              
    160             fText.setText(projectName); 
    161         } 
    162  
    163         public void performApply(ILaunchConfigurationWorkingCopy config) 
    164         { 
    165             config.setAttribute(IDescentBuilderConstants.ATTR_PROJECT_NAME, fText.getText().trim()); 
    166         } 
    167  
    168127        public void setDefaults(ILaunchConfigurationWorkingCopy config) 
    169128        { 
     
    174133                projectName = javaProject.getElementName(); 
    175134             
    176             config.setAttribute(IDescentBuilderConstants.ATTR_PROJECT_NAME, projectName); 
     135            config.setAttribute(ATTR_PROJECT_NAME, projectName); 
    177136             
    178137            // Also, rename the config here (don't do it anywhere else in the 
     
    221180     
    222181    //-------------------------------------------------------------------------- 
     182    // Output type 
     183     
     184    private final class OutputTypeSetting implements ISetting 
     185    { 
     186        private Label fLabel; 
     187        private Button fExecutableRadio; 
     188        private Button fStaticLibRadio; 
     189         
     190        public void addToControl(Composite comp) 
     191        {    
     192            fLabel = new Label(comp, SWT.LEFT); 
     193            fLabel.setText("Target type:"); 
     194            GridData gd = new GridData(); 
     195            gd.horizontalSpan = 3; 
     196            fLabel.setLayoutData(gd); 
     197             
     198            fExecutableRadio = createRadioButton(comp, 3, "Executable", 25,  
     199                    new SelectionAdapter() 
     200                    { 
     201                        public void widgetSelected(SelectionEvent e) 
     202                        { 
     203                            if(fExecutableRadio.getSelection()) 
     204                            { 
     205                                outputFileSetting.outputTypeChanged(); 
     206                                updateLaunchConfigurationDialog(); 
     207                            } 
     208                        } 
     209                    }); 
     210            fStaticLibRadio = createRadioButton(comp, 3, "Static library", 25,  
     211                    new SelectionAdapter() 
     212                    { 
     213                        public void widgetSelected(SelectionEvent e) 
     214                        { 
     215                            if(fStaticLibRadio.getSelection()) 
     216                            { 
     217                                outputFileSetting.outputTypeChanged(); 
     218                                updateLaunchConfigurationDialog(); 
     219                            } 
     220                        } 
     221                    }); 
     222            createSpacer(comp, 3); 
     223        } 
     224 
     225        public void initializeFrom(ILaunchConfiguration config) 
     226        { 
     227            String outputType = OUTPUT_TYPE_EXECUTABLE; 
     228            try 
     229            { 
     230                outputType = config.getAttribute(ATTR_OUTPUT_TYPE, OUTPUT_TYPE_EXECUTABLE); 
     231            } 
     232            catch(CoreException e) { } 
     233             
     234            if(outputType.equals(OUTPUT_TYPE_EXECUTABLE)) 
     235            { 
     236                fExecutableRadio.setSelection(true); 
     237                fStaticLibRadio.setSelection(false); 
     238            } 
     239            else if(outputType.equals(OUTPUT_TYPE_STATIC_LIBRARY)) 
     240            { 
     241                fExecutableRadio.setSelection(false); 
     242                fStaticLibRadio.setSelection(true); 
     243            } 
     244            else 
     245            { 
     246                // Set the defaults 
     247                fExecutableRadio.setSelection(true); 
     248                fStaticLibRadio.setSelection(false); 
     249            } 
     250        } 
     251 
     252        public void performApply(ILaunchConfigurationWorkingCopy config) 
     253        { 
     254            if(fExecutableRadio.getSelection()) 
     255                config.setAttribute(ATTR_OUTPUT_TYPE, OUTPUT_TYPE_EXECUTABLE); 
     256            else 
     257                config.setAttribute(ATTR_OUTPUT_TYPE, OUTPUT_TYPE_STATIC_LIBRARY); 
     258        } 
     259 
     260        public void setDefaults(ILaunchConfigurationWorkingCopy config) 
     261        { 
     262            config.setAttribute(ATTR_OUTPUT_TYPE, OUTPUT_TYPE_EXECUTABLE); 
     263        } 
     264 
     265        public void validate() 
     266        { 
     267            // Nothing to do -- any choice is valid 
     268        } 
     269         
     270        public String getExtension() 
     271        { 
     272            if(fExecutableRadio == null) 
     273                return BuilderUtil.EXTENSION_EXECUTABLE; 
     274             
     275            if(fExecutableRadio.getSelection()) 
     276                return BuilderUtil.EXTENSION_EXECUTABLE; 
     277            else 
     278                return BuilderUtil.EXTENSION_STATIC_LIBRARY; 
     279        } 
     280    } 
     281     
     282    //-------------------------------------------------------------------------- 
     283    // Output file 
     284     
     285    private final class OutputFileSetting extends TextSetting 
     286    {  
     287        OutputFileSetting() 
     288        { 
     289            super(ATTR_OUTPUT_FILE, "Output file:", 3, true, true); 
     290        } 
     291         
     292        @Override 
     293        protected String browse() 
     294        { 
     295            String defaultExtension = getExtension(); 
     296            String defaultLocation = fText.getText(); 
     297            if(0 == defaultLocation.length()) 
     298                defaultLocation = null; 
     299             
     300            FileDialog dialog = new FileDialog(getShell(), SWT.SAVE); 
     301            dialog.setText("Output file location"); 
     302            dialog.setFilterExtensions((defaultExtension.length()) > 0 ? 
     303                    new String[] { "*" + getExtension(), "*.*" } : 
     304                    new String[] { "*.*" }); 
     305            dialog.setFilterPath(toFilterPath(defaultLocation)); 
     306             
     307            return normalizeFilename(dialog.open()); 
     308        } 
     309         
     310        private String toFilterPath(String filename) 
     311        { 
     312            IPath path = new Path(filename); 
     313            if(path.segmentCount() <= 1) 
     314                return null; 
     315            return path.removeLastSegments(1).removeTrailingSeparator().toOSString(); 
     316        } 
     317         
     318        private String normalizeFilename(String filename) 
     319        { 
     320            return new Path(filename).toString(); 
     321        } 
     322         
     323        public void setDefaults(ILaunchConfigurationWorkingCopy config) 
     324        { 
     325            config.setAttribute(ATTR_OUTPUT_FILE,  
     326                    getDefaultLocationForProject(getActiveProject())); 
     327        } 
     328 
     329        public void validate() 
     330        { 
     331            String pathText = fText.getText().trim(); 
     332            if (pathText.length() == 0) 
     333            { 
     334                setErrorMessage("Output path not defined"); 
     335                return; 
     336            } 
     337             
     338            // No way to check if a file is a valid filename since that's 
     339            // file-system (NTFS/FAT/whatever) dependent :-(. I guess some small 
     340            // sanity checks could be added... but whatever, I'll just handle 
     341            // the error in the builder itself 
     342        } 
     343         
     344        public void projectChanged(IJavaProject project) 
     345        { 
     346            if(null != fText) 
     347                fText.setText(getDefaultLocationForProject(project)); 
     348        } 
     349         
     350        public void outputTypeChanged() 
     351        { 
     352            if(null != fText) 
     353                fText.setText(updateExtension(fText.getText())); 
     354        } 
     355         
     356        /** 
     357         * Gets the path for the default output file in the given project. 
     358         *  
     359         * @param project the project whose output folder the result should be in 
     360         * @return        the string representation of the output path 
     361         */ 
     362        private String getDefaultLocationForProject(IJavaProject project) 
     363        { 
     364            if(null == project || !project.exists()) 
     365                return ""; 
     366             
     367            try 
     368            { 
     369                StringBuilder outputFile = new StringBuilder(); 
     370                outputFile.append(BuilderUtil.getAbsolutePath(project. 
     371                        getOutputLocation().makeAbsolute())); 
     372                outputFile.append(IPath.SEPARATOR); 
     373                outputFile.append(project.getElementName()); 
     374                return updateExtension(outputFile.toString()); 
     375            } 
     376            catch(JavaModelException e) 
     377            { 
     378                return ""; 
     379            } 
     380        } 
     381         
     382        /** 
     383         * Updates the extension in the given path to reflect the extension that 
     384         * should be there depending on the file type. For example if the given 
     385         * path is "C:\d\project\out.exe" and the type is changed to 
     386         * dynamic library, this method will return "C:\d\project\out.dll". 
     387         *  
     388         * @param filename 
     389         * @return 
     390         */ 
     391        private String updateExtension(String filename) 
     392        { 
     393            // PERHAPS on unix systems should this actually return libXYZ.a for an 
     394            // input of XYZ if the type is static library...? 
     395             
     396            if(null == filename || 0 == filename.length()) 
     397