~ubuntu-branches/ubuntu/quantal/netbeans/quantal

« back to all changes in this revision

Viewing changes to java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/PlatformUiSupport.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
6
 * The contents of this file are subject to the terms of either the GNU
 
7
 * General Public License Version 2 only ("GPL") or the Common
 
8
 * Development and Distribution License("CDDL") (collectively, the
 
9
 * "License"). You may not use this file except in compliance with the
 
10
 * License. You can obtain a copy of the License at
 
11
 * http://www.netbeans.org/cddl-gplv2.html
 
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 
13
 * specific language governing permissions and limitations under the
 
14
 * License.  When distributing the software, include this License Header
 
15
 * Notice in each file and include the License file at
 
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 
17
 * particular file as subject to the "Classpath" exception as provided
 
18
 * by Sun in the GPL Version 2 section of the License file that
 
19
 * accompanied this code. If applicable, add the following below the
 
20
 * License Header, with the fields enclosed by brackets [] replaced by
 
21
 * your own identifying information:
 
22
 * "Portions Copyrighted [year] [name of copyright owner]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
26
 * The Original Software is NetBeans. The Initial Developer of the Original
 
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 
28
 * Microsystems, Inc. All Rights Reserved.
 
29
 *
 
30
 * If you wish your version of this file to be governed by only the CDDL
 
31
 * or only the GPL Version 2, indicate your decision by adding
 
32
 * "[Contributor] elects to include this software in this distribution
 
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 
34
 * single choice of license, a recipient has the option to distribute
 
35
 * your version of this file under either the CDDL, the GPL Version 2 or
 
36
 * to extend the choice of license to its licensees as provided above.
 
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 
38
 * Version 2 license, then the option applies only if the new code is
 
39
 * made subject to such option by the copyright holder.
 
40
 */
 
41
 
 
42
package org.netbeans.modules.java.j2seproject.ui.customizer;
 
43
 
 
44
import java.awt.Component;
 
45
import java.beans.PropertyChangeEvent;
 
46
import java.beans.PropertyChangeListener;
 
47
import java.text.MessageFormat;
 
48
import java.util.ArrayList;
 
49
import java.util.List;
 
50
import java.util.Set;
 
51
import java.util.TreeSet;
 
52
import java.util.logging.Logger;
 
53
import javax.swing.AbstractListModel;
 
54
import javax.swing.ComboBoxModel;
 
55
import javax.swing.JButton;
 
56
import javax.swing.JList;
 
57
import javax.swing.ListCellRenderer;
 
58
import javax.swing.event.ListDataEvent;
 
59
import javax.swing.event.ListDataListener;
 
60
import org.netbeans.api.java.platform.JavaPlatform;
 
61
import org.netbeans.api.java.platform.JavaPlatformManager;
 
62
import org.netbeans.api.java.platform.Specification;
 
63
import org.netbeans.modules.java.j2seproject.J2SEProjectType;
 
64
import org.netbeans.modules.java.j2seproject.UpdateHelper;
 
65
import org.netbeans.spi.project.support.ant.EditableProperties;
 
66
import org.openide.DialogDisplayer;
 
67
import org.openide.NotifyDescriptor;
 
68
import org.openide.awt.HtmlRenderer;
 
69
import org.openide.modules.SpecificationVersion;
 
70
import org.openide.util.NbBundle;
 
71
import org.openide.util.WeakListeners;
 
72
import org.w3c.dom.Element;
 
73
import org.w3c.dom.NodeList;
 
74
 
 
75
/**
 
76
 * Support class for {@link JavaPlatform} manipulation in j2seproject customizer.
 
77
 * @author tzezula
 
78
 */
 
79
public class PlatformUiSupport {    
 
80
    
 
81
    private static final SpecificationVersion JDK_5 = new SpecificationVersion ("1.5");  //NOI18N
 
82
    private static final SpecificationVersion JDK_6 = new SpecificationVersion ("1.6");  //NOI18N
 
83
    private static final Logger LOGGER = Logger.getLogger(PlatformUiSupport.class.getName());
 
84
    
 
85
    private PlatformUiSupport() {
 
86
    }
 
87
    
 
88
    /**
 
89
     * Creates {@link ComboBoxModel} of J2SE platforms.
 
90
     * The model listens on the {@link JavaPlatformManager} and update its
 
91
     * state according to changes
 
92
     * @param activePlatform the active project's platform 
 
93
     * @return {@link ComboBoxModel}
 
94
     */
 
95
    public static ComboBoxModel createPlatformComboBoxModel (String activePlatform) {
 
96
        return new PlatformComboBoxModel (activePlatform);
 
97
    }
 
98
    
 
99
    
 
100
    /**
 
101
     * Creates a {@link ListCellRenderer} for rendering items of the {@link ComboBoxModel}
 
102
     * created by the {@link PlatformUiSupport#createPlatformComboBoxModel} method.
 
103
     * @return {@link ListCellRenderer}
 
104
     */
 
105
    public static ListCellRenderer createPlatformListCellRenderer () {
 
106
        return new PlatformListCellRenderer ();
 
107
    }
 
108
       
 
109
    /**
 
110
     * Stores active platform, javac.source and javac.target into the project's metadata
 
111
     * @param props project's shared properties
 
112
     * @param helper to read/update project.xml
 
113
     * @param platformKey the PatformKey got from the platform model
 
114
     * @param sourceLevel source level
 
115
     */
 
116
    public static void storePlatform (EditableProperties props, UpdateHelper helper, Object platformKey, Object sourceLevelKey) {
 
117
        assert platformKey instanceof PlatformKey;        
 
118
        PlatformKey pk = (PlatformKey) platformKey;
 
119
        JavaPlatform platform = getPlatform(pk);                
 
120
        //null means active broken (unresolved) platform, no need to do anything
 
121
        if (platform != null) {
 
122
            SpecificationVersion jdk13 = new SpecificationVersion ("1.3");  //NOI18N
 
123
            String platformAntName = (String) platform.getProperties().get("platform.ant.name");    //NOI18N        
 
124
            assert platformAntName != null;
 
125
            props.put(J2SEProjectProperties.JAVA_PLATFORM, platformAntName);
 
126
            Element root = helper.getPrimaryConfigurationData(true);
 
127
            boolean defaultPlatform = pk.isDefaultPlatform();
 
128
            boolean changed = false;
 
129
            NodeList explicitPlatformNodes = root.getElementsByTagNameNS (J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE,"explicit-platform");   //NOI18N
 
130
            if (defaultPlatform) {                
 
131
                if (explicitPlatformNodes.getLength()==1) {
 
132
                    root.removeChild(explicitPlatformNodes.item(0));
 
133
                    changed = true;
 
134
                }                
 
135
            }
 
136
            else {
 
137
                Element explicitPlatform;
 
138
                switch (explicitPlatformNodes.getLength()) {
 
139
                    case 0:
 
140
                        explicitPlatform = root.getOwnerDocument().createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "explicit-platform"); //NOI18N                    
 
141
                        NodeList sourceRootNodes = root.getElementsByTagNameNS (J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE,"source-roots");   //NOI18N
 
142
                        assert sourceRootNodes.getLength() == 1 : "Broken project.xml file"; //NOI18N
 
143
                        root.insertBefore(explicitPlatform, sourceRootNodes.item(0));
 
144
                        changed = true;
 
145
                        break;
 
146
                    case 1:
 
147
                        explicitPlatform = (Element)explicitPlatformNodes.item(0);
 
148
                        break;
 
149
                    default:
 
150
                        throw new AssertionError("Broken project.xml file");   //NOI18N
 
151
                }                
 
152
                String explicitSourceAttrValue = explicitPlatform.getAttribute("explicit-source-supported");    //NOI18N
 
153
                if (jdk13.compareTo(platform.getSpecification().getVersion())>=0 &&
 
154
                    !"false".equals(explicitSourceAttrValue)) {   //NOI18N
 
155
                    explicitPlatform.setAttribute("explicit-source-supported","false"); //NOI18N
 
156
                    changed = true;
 
157
                }
 
158
                else if (jdk13.compareTo(platform.getSpecification().getVersion())<0 &&
 
159
                    !"true".equals(explicitSourceAttrValue)) {  //NOI18N
 
160
                    explicitPlatform.setAttribute("explicit-source-supported","true"); //NOI18N
 
161
                    changed = true;
 
162
                }                                
 
163
            }
 
164
            
 
165
            SpecificationVersion sourceLevel;
 
166
            if (sourceLevelKey == null) {
 
167
                sourceLevel = platform.getSpecification().getVersion();
 
168
            }
 
169
            else {
 
170
                assert sourceLevelKey instanceof SourceLevelKey;
 
171
                sourceLevel = ((SourceLevelKey)sourceLevelKey).getSourceLevel();
 
172
            }
 
173
            String javacSource = sourceLevel.toString();
 
174
            String javacTarget = javacSource;
 
175
            
 
176
            //Issue #116490
 
177
            // Customizer value | -source | -targer
 
178
            // JDK 1.2            1.2        1.1
 
179
            // JDK 1.3            1.3        1.1
 
180
            // JDK 1.4            1.4        1.4
 
181
            // JDK 5              1.5        1.5
 
182
            // JDK 6              1.5        1.6
 
183
            // JDK 7              1.7        1.7  - should bring a new language features
 
184
            if (jdk13.compareTo(sourceLevel)>=0) {
 
185
                javacTarget = "1.1";        //NOI18N
 
186
            }
 
187
            else if (JDK_6.equals(sourceLevel)) {
 
188
                javacSource = JDK_5.toString();
 
189
            }            
 
190
                        
 
191
            if (!javacSource.equals(props.getProperty(J2SEProjectProperties.JAVAC_SOURCE))) {
 
192
                props.setProperty (J2SEProjectProperties.JAVAC_SOURCE, javacSource);
 
193
            }
 
194
            if (!javacTarget.equals(props.getProperty(J2SEProjectProperties.JAVAC_TARGET))) {
 
195
                props.setProperty (J2SEProjectProperties.JAVAC_TARGET, javacTarget);
 
196
            }
 
197
                        
 
198
            if (changed) {
 
199
                helper.putPrimaryConfigurationData(root, true);
 
200
            }
 
201
        }
 
202
    }
 
203
    
 
204
    
 
205
    /** 
 
206
     * Returns a {@link JavaPlatform} for an item obtained from the ComboBoxModel created by
 
207
     * the {@link PlatformUiSupport#createComboBoxModel} method
 
208
     * @param platformKey an item obtained from ComboBoxModel created by {@link PlatformUiSupport#createComboBoxModel}
 
209
     * @return JavaPlatform or null in case when platform is broken
 
210
     * @exception {@link IllegalArgumentException} is thrown in case when parameter in not an object created by
 
211
     * platform combobox model.
 
212
     */
 
213
    public static JavaPlatform getPlatform (Object platformKey) {
 
214
       if (platformKey instanceof PlatformKey) {
 
215
           return getPlatform ((PlatformKey)platformKey);
 
216
       }
 
217
       else {
 
218
           throw new IllegalArgumentException ();
 
219
       }
 
220
    }
 
221
    
 
222
    /**
 
223
     * Creates {@link ComboBoxModel} of source levels for active platform.
 
224
     * The model listens on the platform's {@link ComboBoxModel} and update its
 
225
     * state according to changes
 
226
     * @param platformComboBoxModel the platform's model used for listenning
 
227
     * @param initialValue initial source level value
 
228
     * @return {@link ComboBoxModel} of {@link SpecificationVersion}
 
229
     */
 
230
    public static ComboBoxModel createSourceLevelComboBoxModel (ComboBoxModel platformComboBoxModel, String initialSourceLevel, String initinalTargetLevel) {
 
231
        return new SourceLevelComboBoxModel (platformComboBoxModel, initialSourceLevel, initinalTargetLevel);
 
232
    }
 
233
    
 
234
    
 
235
    public static ListCellRenderer createSourceLevelListCellRenderer () {
 
236
        return new SourceLevelListCellRenderer ();
 
237
    }
 
238
    
 
239
    
 
240
    private static JavaPlatform getPlatform (PlatformKey platformKey) {
 
241
        return platformKey.platform;
 
242
    }    
 
243
    
 
244
    
 
245
    /**
 
246
     * This class represents a  JavaPlatform in the {@link ListModel}
 
247
     * created by the {@link PlatformUiSupport#createPlatformComboBoxModel}
 
248
     * method.
 
249
     */
 
250
    private static class PlatformKey implements Comparable {
 
251
        
 
252
        private String name;
 
253
        private JavaPlatform platform;
 
254
        
 
255
        /**
 
256
         * Creates a PlatformKey for a broken platform
 
257
         * @param name the ant name of the broken platform
 
258
         */
 
259
        public PlatformKey (String name) {
 
260
            assert name != null;
 
261
            this.name = name;
 
262
        }
 
263
        
 
264
        /**
 
265
         * Creates a PlatformKey for a platform
 
266
         * @param platform the {@link JavaPlatform}
 
267
         */
 
268
        public PlatformKey (JavaPlatform platform) {
 
269
            assert platform != null;
 
270
            this.platform = platform;
 
271
        }
 
272
 
 
273
        public int compareTo(Object o) {
 
274
            return this.getDisplayName().compareTo(((PlatformKey)o).getDisplayName());
 
275
        }
 
276
        
 
277
        public boolean equals (Object other) {
 
278
            if (other instanceof PlatformKey) {
 
279
                PlatformKey otherKey = (PlatformKey)other;
 
280
                return (this.platform == null ? otherKey.platform == null : this.platform.equals(otherKey.platform)) &&
 
281
                       otherKey.getDisplayName().equals (this.getDisplayName());
 
282
            }
 
283
            else {
 
284
                return false;
 
285
            }
 
286
        }
 
287
        
 
288
        public int hashCode () {
 
289
            return getDisplayName ().hashCode ();
 
290
        }
 
291
        
 
292
        public String toString () {
 
293
            return getDisplayName ();
 
294
        }
 
295
        
 
296
        public synchronized String getDisplayName () {
 
297
            if (this.name == null) {                
 
298
                this.name = this.platform.getDisplayName();
 
299
            }
 
300
            return this.name;
 
301
        }
 
302
        
 
303
        public boolean isDefaultPlatform () {
 
304
            if (this.platform == null) {
 
305
                return false;
 
306
            }
 
307
            return this.platform.equals(JavaPlatformManager.getDefault().getDefaultPlatform());
 
308
        }
 
309
        
 
310
        public boolean isBroken () {
 
311
            return this.platform == null;
 
312
        }
 
313
        
 
314
    }    
 
315
    
 
316
    private static final class SourceLevelKey implements Comparable {
 
317
        
 
318
        final SpecificationVersion sourceLevel;
 
319
        final boolean broken;
 
320
        
 
321
        public SourceLevelKey (final SpecificationVersion sourceLevel) {
 
322
            this (sourceLevel, false);
 
323
        }
 
324
        
 
325
        public SourceLevelKey (final SpecificationVersion sourceLevel, final boolean broken) {
 
326
            assert sourceLevel != null : "Source level cannot be null";     //NOI18N
 
327
            this.sourceLevel = sourceLevel;
 
328
            this.broken = broken;
 
329
        }
 
330
        
 
331
        public SpecificationVersion getSourceLevel () {
 
332
            return this.sourceLevel;
 
333
        }
 
334
        
 
335
        public boolean isBroken () {
 
336
            return this.broken;
 
337
        }
 
338
        
 
339
        public int compareTo (final Object other) {
 
340
            assert other instanceof SourceLevelKey : "Illegal argument of SourceLevelKey.compareTo()";  //NOI18N
 
341
            SourceLevelKey otherKey = (SourceLevelKey) other;
 
342
            return this.sourceLevel.compareTo(otherKey.sourceLevel);
 
343
        }
 
344
        
 
345
        public @Override boolean equals (final Object other) {
 
346
            return (other instanceof SourceLevelKey) &&
 
347
                   ((SourceLevelKey)other).sourceLevel.equals(this.sourceLevel);
 
348
        }
 
349
        
 
350
        public @Override int hashCode () {
 
351
            return this.sourceLevel.hashCode();
 
352
        }
 
353
        
 
354
        public @Override String toString () {
 
355
            StringBuffer buffer = new StringBuffer ();
 
356
            if (this.broken) {
 
357
                buffer.append("Broken: ");      //NOI18N
 
358
            }
 
359
            buffer.append(this.sourceLevel.toString());
 
360
            return buffer.toString();
 
361
        }
 
362
        
 
363
        public String getDisplayName () {
 
364
            String _tmp = sourceLevel.toString();
 
365
            if (JDK_5.compareTo(sourceLevel)<=0) {                
 
366
                _tmp = _tmp.replaceFirst("^1\\.([5-9]|\\d\\d+)$", "$1");        //NOI18N
 
367
            }            
 
368
            return NbBundle.getMessage(PlatformUiSupport.class, "LBL_JDK",_tmp);
 
369
        }
 
370
        
 
371
    }
 
372
    
 
373
    private static class PlatformComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener {
 
374
        
 
375
        private JavaPlatformManager pm;
 
376
        private PlatformKey[] platformNamesCache;
 
377
        private String initialPlatform;
 
378
        private PlatformKey selectedPlatform;
 
379
        
 
380
        public PlatformComboBoxModel (String initialPlatform) {
 
381
            this.pm = JavaPlatformManager.getDefault();
 
382
            this.pm.addPropertyChangeListener(WeakListeners.propertyChange(this, this.pm));
 
383
            this.initialPlatform = initialPlatform;
 
384
        }
 
385
        
 
386
        public int getSize () {
 
387
            PlatformKey[] platformNames = getPlatformNames ();
 
388
            return platformNames.length;
 
389
        }
 
390
        
 
391
        public Object getElementAt (int index) {
 
392
            PlatformKey[] platformNames = getPlatformNames ();
 
393
            assert index >=0 && index< platformNames.length;
 
394
            return platformNames[index];
 
395
        }
 
396
        
 
397
        public Object getSelectedItem () {
 
398
            this.getPlatformNames(); //Force setting of selectedPlatform if it is not alredy done
 
399
            return this.selectedPlatform;
 
400
        }
 
401
        
 
402
        public void setSelectedItem (Object obj) {
 
403
            this.selectedPlatform = (PlatformKey) obj;
 
404
            this.fireContentsChanged(this, -1, -1);
 
405
        }
 
406
        
 
407
        public void propertyChange (PropertyChangeEvent event) {
 
408
            if (JavaPlatformManager.PROP_INSTALLED_PLATFORMS.equals(event.getPropertyName())) {
 
409
                synchronized (this) {
 
410
                    this.platformNamesCache = null;
 
411
                }
 
412
                this.fireContentsChanged(this, -1, -1);
 
413
            }
 
414
        }
 
415
        
 
416
        private synchronized PlatformKey[] getPlatformNames () {
 
417
            if (this.platformNamesCache == null) {
 
418
                JavaPlatform[] platforms = pm.getPlatforms (null, new Specification("j2se",null));    //NOI18N
 
419
                JavaPlatform defaultPlatform = pm.getDefaultPlatform ();
 
420
                Set/*<PlatformKey>*/ orderedNames = new TreeSet ();
 
421
                boolean activeFound = false;
 
422
                for (int i=0; i< platforms.length; i++) {
 
423
                    if (platforms[i].getInstallFolders().size()>0) {
 
424
                        PlatformKey pk = new PlatformKey(platforms[i]);
 
425
                        orderedNames.add (pk);
 
426
                        if (!activeFound && initialPlatform != null) {
 
427
                            String antName = (String) platforms[i].getProperties().get("platform.ant.name");    //NOI18N
 
428
                            if (initialPlatform.equals(antName)) {
 
429
                                if (this.selectedPlatform == null) {
 
430
                                    this.selectedPlatform = pk;
 
431
                                    initialPlatform = null;
 
432
                                }
 
433
                                activeFound = true;
 
434
                            }
 
435
                        }
 
436
                    }                    
 
437
                }
 
438
                if (!activeFound) {
 
439
                    if (initialPlatform == null) {
 
440
                        if (this.selectedPlatform == null || !orderedNames.contains(this.selectedPlatform)) {
 
441
                            this.selectedPlatform = new PlatformKey (JavaPlatformManager.getDefault().getDefaultPlatform());
 
442
                        }
 
443
                    }
 
444
                    else {
 
445
                        PlatformKey pk = new PlatformKey (this.initialPlatform);
 
446
                        orderedNames.add (pk);
 
447
                        if (this.selectedPlatform == null) {
 
448
                            this.selectedPlatform = pk;
 
449
                        }
 
450
                    }
 
451
                }
 
452
                this.platformNamesCache = (PlatformKey[]) orderedNames.toArray(new PlatformKey[orderedNames.size()]);
 
453
            }
 
454
            return this.platformNamesCache;                    
 
455
        }
 
456
        
 
457
    }
 
458
    
 
459
    private static class PlatformListCellRenderer implements ListCellRenderer {
 
460
        
 
461
        private ListCellRenderer delegate;
 
462
        
 
463
        public PlatformListCellRenderer () {
 
464
            this.delegate = HtmlRenderer.createRenderer ();
 
465
        }
 
466
 
 
467
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
 
468
            String name;
 
469
            if (value == null) {
 
470
                name = "";  //NOI18N
 
471
            }
 
472
            else {
 
473
                assert value instanceof PlatformKey : "Wrong model";  //NOI18N
 
474
                PlatformKey key = (PlatformKey) value;           
 
475
                if (key.isBroken()) {
 
476
                    name = "<html><font color=\"#A40000\">" +    //NOI18N
 
477
                        NbBundle.getMessage (PlatformUiSupport.class,"TXT_BrokenPlatformFmt", key.getDisplayName());
 
478
                }
 
479
                else {
 
480
                    name = key.getDisplayName();
 
481
                }
 
482
            }
 
483
            return this.delegate.getListCellRendererComponent(list, name, index, isSelected, cellHasFocus);
 
484
        }        
 
485
    }
 
486
    
 
487
    private static class SourceLevelComboBoxModel extends AbstractListModel implements ComboBoxModel, ListDataListener {
 
488
        
 
489
        private static final String VERSION_PREFIX = "1.";      //The version prefix
 
490
        private static final int INITIAL_VERSION_MINOR = 2;     //1.2
 
491
        
 
492
        private SpecificationVersion selectedSourceLevel;
 
493
        private SpecificationVersion originalSourceLevel;
 
494
        private SourceLevelKey[] sourceLevelCache;
 
495
        private final ComboBoxModel platformComboBoxModel;
 
496
        private PlatformKey activePlatform;
 
497
        
 
498
        public SourceLevelComboBoxModel (ComboBoxModel platformComboBoxModel, String initialSourceLevel, String initialTargetLevel) {            
 
499
            this.platformComboBoxModel = platformComboBoxModel;
 
500
            this.activePlatform = (PlatformKey) this.platformComboBoxModel.getSelectedItem();
 
501
            this.platformComboBoxModel.addListDataListener (this);
 
502
            if (initialSourceLevel != null && initialSourceLevel.length() > 0) {
 
503
                try {
 
504
                    this.originalSourceLevel = new SpecificationVersion (initialSourceLevel);
 
505
                } catch (NumberFormatException nfe) {
 
506
                    //If the javac.source has invalid value, do not preselect and log it
 
507
                    LOGGER.warning("Invalid javac.source: "+initialSourceLevel);        //NO18N
 
508
                }
 
509
            }
 
510
            if (initialTargetLevel != null && initialTargetLevel.length() > 0) {
 
511
                try {
 
512
                    SpecificationVersion originalTargetLevel = new SpecificationVersion (initialTargetLevel);
 
513
                    if (this.originalSourceLevel == null || this.originalSourceLevel.compareTo(originalTargetLevel)<0) {
 
514
                        this.originalSourceLevel = originalTargetLevel;
 
515
                    }
 
516
                } catch (NumberFormatException nfe) {
 
517
                    //If the javac.target has invalid value, do not preselect and log it
 
518
                    LOGGER.warning("Invalid javac.target: "+initialTargetLevel);        //NOI18N
 
519
                }
 
520
            }
 
521
            this.selectedSourceLevel = this.originalSourceLevel;
 
522
        }
 
523
                
 
524
        public int getSize () {
 
525
            SourceLevelKey[] sLevels = getSourceLevels ();
 
526
            return sLevels.length;
 
527
        }
 
528
        
 
529
        public Object getElementAt (int index) {
 
530
            SourceLevelKey[] sLevels = getSourceLevels ();
 
531
            assert index >=0 && index< sLevels.length;
 
532
            return sLevels[index];
 
533
        }
 
534
        
 
535
        public Object getSelectedItem () {
 
536
            SourceLevelKey[] keys = getSourceLevels ();
 
537
            for (int i=0; i<keys.length; i++) {
 
538
                if (keys[i].getSourceLevel().equals(this.selectedSourceLevel)) {
 
539
                    return keys[i];
 
540
                }
 
541
            }
 
542
            return null;
 
543
        }
 
544
        
 
545
        public void setSelectedItem (Object obj) {
 
546
            this.selectedSourceLevel = (obj == null ? null : ((SourceLevelKey)obj).getSourceLevel());
 
547
            this.fireContentsChanged(this, -1, -1);
 
548
        }
 
549
        
 
550
        public void intervalAdded(ListDataEvent e) {
 
551
        }
 
552
 
 
553
        public void intervalRemoved(ListDataEvent e) {
 
554
        }
 
555
 
 
556
        public void contentsChanged(ListDataEvent e) {
 
557
            PlatformKey selectedPlatform = (PlatformKey) this.platformComboBoxModel.getSelectedItem();
 
558
            JavaPlatform platform = getPlatform(selectedPlatform);
 
559
            if (platform != null) {
 
560
                SpecificationVersion version = platform.getSpecification().getVersion();
 
561
                if (this.selectedSourceLevel != null && this.selectedSourceLevel.compareTo(version)>0 &&
 
562
                    !shouldChangePlatform (selectedSourceLevel, version)) {
 
563
                    //Restore original
 
564
                   this.platformComboBoxModel.setSelectedItem(this.activePlatform);                            
 
565
                   return;
 
566
                }
 
567
                else {
 
568
                    this.originalSourceLevel = null;
 
569
                }
 
570
            }
 
571
            this.activePlatform = selectedPlatform;
 
572
            resetCache ();
 
573
        }
 
574
        
 
575
        private void resetCache () {            
 
576
            synchronized (this) {
 
577
                this.sourceLevelCache = null;                
 
578
            }
 
579
            this.fireContentsChanged(this, -1, -1);
 
580
        }
 
581
        
 
582
        private SourceLevelKey[] getSourceLevels () {
 
583
            if (this.sourceLevelCache == null) {
 
584
                PlatformKey selectedPlatform = (PlatformKey) this.platformComboBoxModel.getSelectedItem();
 
585
                JavaPlatform platform = getPlatform(selectedPlatform);                
 
586
                List/*<SpecificationVersion>*/ sLevels = new ArrayList ();
 
587
                //If platform == null broken platform, the source level range is unknown
 
588
                //The source level combo box should be empty and disabled
 
589
                boolean selSourceLevelValid = false;
 
590
                if (platform != null) {                    
 
591
                    SpecificationVersion version = platform.getSpecification().getVersion();                                        
 
592
                    int index = INITIAL_VERSION_MINOR;
 
593
                    SpecificationVersion template = new SpecificationVersion (VERSION_PREFIX + Integer.toString (index++));
 
594
                    boolean origSourceLevelValid = false;
 
595
                    
 
596
                    while (template.compareTo(version)<=0) {
 
597
                        if (template.equals(this.originalSourceLevel)) {
 
598
                            origSourceLevelValid = true;
 
599
                        }
 
600
                        if (template.equals(this.selectedSourceLevel)) {
 
601
                            selSourceLevelValid = true;
 
602
                        }
 
603
                        sLevels.add (new SourceLevelKey (template));
 
604
                        template = new SpecificationVersion (VERSION_PREFIX + Integer.toString (index++));
 
605
                    }
 
606
                    if (this.originalSourceLevel != null && !origSourceLevelValid) {
 
607
                        if (originalSourceLevel.equals(this.selectedSourceLevel)) {                            
 
608
                            selSourceLevelValid = true;
 
609
                        }
 
610
                        sLevels.add (new SourceLevelKey(this.originalSourceLevel,true));
 
611
                    }                                        
 
612
                }
 
613
                this.sourceLevelCache = (SourceLevelKey[]) sLevels.toArray(new SourceLevelKey[sLevels.size()]);
 
614
                if (!selSourceLevelValid) {
 
615
                    this.selectedSourceLevel = this.sourceLevelCache.length == 0 ? 
 
616
                        null : this.sourceLevelCache[this.sourceLevelCache.length-1].getSourceLevel();
 
617
                }
 
618
            }
 
619
            return this.sourceLevelCache;
 
620
        }
 
621
        
 
622
        private static boolean shouldChangePlatform (SpecificationVersion selectedSourceLevel, SpecificationVersion platformSourceLevel) {
 
623
            JButton changeOption = new JButton (NbBundle.getMessage(PlatformUiSupport.class, "CTL_ChangePlatform"));
 
624
            changeOption.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(PlatformUiSupport.class, "AD_ChangePlatform"));
 
625
            String message = MessageFormat.format (NbBundle.getMessage(PlatformUiSupport.class,"TXT_ChangePlatform"),new Object[] {
 
626
                selectedSourceLevel.toString(),
 
627
                platformSourceLevel.toString(),
 
628
            });
 
629
            return DialogDisplayer.getDefault().notify(
 
630
                new NotifyDescriptor (message,
 
631
                        NbBundle.getMessage(PlatformUiSupport.class,"TXT_ChangePlatformTitle"),
 
632
                        NotifyDescriptor.DEFAULT_OPTION,
 
633
                        NotifyDescriptor.WARNING_MESSAGE,
 
634
                        new Object[] {
 
635
                            changeOption,
 
636
                            NotifyDescriptor.CANCEL_OPTION
 
637
                        },
 
638
                        changeOption)) == changeOption;
 
639
        }
 
640
    }
 
641
    
 
642
    private static class SourceLevelListCellRenderer implements ListCellRenderer {
 
643
        
 
644
        ListCellRenderer delegate;
 
645
        
 
646
        public SourceLevelListCellRenderer () {
 
647
            this.delegate = HtmlRenderer.createRenderer();
 
648
        }
 
649
        
 
650
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
 
651
            String message;
 
652
            if (value == null) {
 
653
                message = "";   //NOI18N
 
654
            }
 
655
            else {
 
656
                assert value instanceof SourceLevelKey;
 
657
                SourceLevelKey key = (SourceLevelKey) value;            
 
658
                if (key.isBroken()) {                
 
659
                    message = "<html><font color=\"#A40000\">" +    //NOI18N
 
660
                        NbBundle.getMessage(PlatformUiSupport.class,"TXT_InvalidSourceLevel",key.getDisplayName());
 
661
                }
 
662
                else {
 
663
                    message = key.getDisplayName();
 
664
                }
 
665
            }
 
666
            return this.delegate.getListCellRendererComponent(list, message, index, isSelected, cellHasFocus);
 
667
        }
 
668
    }
 
669
    
 
670
}