Lines 49-61
Link Here
|
49 |
import java.beans.PropertyChangeListener; |
49 |
import java.beans.PropertyChangeListener; |
50 |
import java.text.MessageFormat; |
50 |
import java.text.MessageFormat; |
51 |
import java.util.ArrayList; |
51 |
import java.util.ArrayList; |
|
|
52 |
import java.util.Arrays; |
53 |
import java.util.Collection; |
54 |
import java.util.Collections; |
55 |
import java.util.Comparator; |
56 |
import java.util.HashMap; |
57 |
import java.util.HashSet; |
52 |
import java.util.List; |
58 |
import java.util.List; |
|
|
59 |
import java.util.Map; |
53 |
import java.util.Set; |
60 |
import java.util.Set; |
54 |
import java.util.TreeSet; |
61 |
import java.util.TreeSet; |
55 |
import java.util.logging.Logger; |
62 |
import java.util.logging.Logger; |
56 |
import javax.swing.*; |
63 |
import javax.swing.*; |
57 |
import javax.swing.event.ListDataEvent; |
64 |
import javax.swing.event.ListDataEvent; |
58 |
import javax.swing.event.ListDataListener; |
65 |
import javax.swing.event.ListDataListener; |
|
|
66 |
import org.netbeans.api.annotations.common.CheckForNull; |
59 |
import org.netbeans.api.annotations.common.NonNull; |
67 |
import org.netbeans.api.annotations.common.NonNull; |
60 |
import org.netbeans.api.annotations.common.NullAllowed; |
68 |
import org.netbeans.api.annotations.common.NullAllowed; |
61 |
import org.netbeans.api.java.platform.JavaPlatform; |
69 |
import org.netbeans.api.java.platform.JavaPlatform; |
Lines 81-87
Link Here
|
81 |
*/ |
89 |
*/ |
82 |
public final class PlatformUiSupport { |
90 |
public final class PlatformUiSupport { |
83 |
|
91 |
|
84 |
private static final SpecificationVersion JDK_1_5 = new SpecificationVersion("1.5"); //NOI18N |
92 |
private static final SpecificationVersion JDK_1_5 = new SpecificationVersion("1.5"); //NOI18N |
|
|
93 |
private static final SpecificationVersion JDK_8 = new SpecificationVersion("1.8"); //NOI18N |
85 |
private static final Logger LOGGER = Logger.getLogger(PlatformUiSupport.class.getName()); |
94 |
private static final Logger LOGGER = Logger.getLogger(PlatformUiSupport.class.getName()); |
86 |
|
95 |
|
87 |
private PlatformUiSupport() { |
96 |
private PlatformUiSupport() { |
Lines 148-154
Link Here
|
148 |
@NonNull final String projectConfigurationNamespace, |
157 |
@NonNull final String projectConfigurationNamespace, |
149 |
@NonNull final Object platformKey, |
158 |
@NonNull final Object platformKey, |
150 |
@NullAllowed final Object sourceLevelKey) { |
159 |
@NullAllowed final Object sourceLevelKey) { |
151 |
storePlatform(props, helper, projectConfigurationNamespace, platformKey, sourceLevelKey, true); |
160 |
storePlatform( |
|
|
161 |
props, |
162 |
helper, |
163 |
projectConfigurationNamespace, |
164 |
platformKey, |
165 |
sourceLevelKey, |
166 |
null, |
167 |
true); |
152 |
} |
168 |
} |
153 |
|
169 |
|
154 |
/** |
170 |
/** |
Lines 168-183
Link Here
|
168 |
@NonNull final Object platformKey, |
184 |
@NonNull final Object platformKey, |
169 |
@NullAllowed final Object sourceLevelKey, |
185 |
@NullAllowed final Object sourceLevelKey, |
170 |
final boolean updatePreferredPlatform) { |
186 |
final boolean updatePreferredPlatform) { |
|
|
187 |
storePlatform( |
188 |
props, |
189 |
helper, |
190 |
projectConfigurationNamespace, |
191 |
platformKey, |
192 |
sourceLevelKey, |
193 |
null, |
194 |
updatePreferredPlatform); |
195 |
} |
196 |
|
197 |
/** |
198 |
* Stores active platform, <i>javac.source</i>,<i>javac.target</i> and <i>javac.profile</i> into the project's metadata. |
199 |
* @param props project's shared properties |
200 |
* @param helper {@link UpdateHelper} that is capable to upgrade project metadata if needed. |
201 |
* @param projectConfigurationNamespace project configuration namespace. |
202 |
* @param platformKey the {@link PlatformKey} got from the platform model. |
203 |
* @param sourceLevelKey {@link SourceLevelKey} representing source level; can be <code>null</code>. |
204 |
* @param profileKey {@link Profile} representing required profile; can be <code>null</code> for full JRE. |
205 |
* @param updatePreferredPlatform if true the {@link PreferredProjectPlatform} will be updated |
206 |
* @since 1.45 |
207 |
*/ |
208 |
public static void storePlatform( |
209 |
@NonNull final EditableProperties props, |
210 |
@NonNull final UpdateHelper helper, |
211 |
@NonNull final String projectConfigurationNamespace, |
212 |
@NonNull final Object platformKey, |
213 |
@NullAllowed final Object sourceLevelKey, |
214 |
@NullAllowed final Object profileKey, |
215 |
final boolean updatePreferredPlatform) { |
171 |
Parameters.notNull("props", props); //NOI18N |
216 |
Parameters.notNull("props", props); //NOI18N |
172 |
Parameters.notNull("helper", helper); //NOI18N |
217 |
Parameters.notNull("helper", helper); //NOI18N |
173 |
Parameters.notNull("projectConfigurationNamespace", projectConfigurationNamespace); //NOI18N |
218 |
Parameters.notNull("projectConfigurationNamespace", projectConfigurationNamespace); //NOI18N |
174 |
Parameters.notNull("platformKey", platformKey); //NOI18N |
219 |
Parameters.notNull("platformKey", platformKey); //NOI18N |
175 |
|
220 |
if (!(platformKey instanceof PlatformKey)) { |
176 |
assert platformKey instanceof PlatformKey; |
221 |
throw new IllegalArgumentException(String.format( |
|
|
222 |
"Unsupported platform key: %s of type: %s", //NOI18N |
223 |
platformKey, |
224 |
platformKey.getClass())); |
225 |
} |
226 |
if (sourceLevelKey != null && !(sourceLevelKey instanceof SourceLevelKey)) { |
227 |
throw new IllegalArgumentException(String.format( |
228 |
"Unsupported source level key: %s of type: %s", //NOI18N |
229 |
sourceLevelKey, |
230 |
sourceLevelKey.getClass())); |
231 |
} |
232 |
if (profileKey != null && !(profileKey instanceof Profile)) { |
233 |
throw new IllegalArgumentException(String.format( |
234 |
"Unsupported profile key: %s of type: %s", //NOI18N |
235 |
profileKey, |
236 |
profileKey.getClass())); |
237 |
} |
177 |
|
238 |
|
178 |
final String javaPlatformKey = "platform.active"; //NOI18N |
239 |
final String javaPlatformKey = "platform.active"; //NOI18N |
179 |
final String javacSourceKey = "javac.source"; //NOI18N |
240 |
final String javacSourceKey = "javac.source"; //NOI18N |
180 |
final String javacTargetKey = "javac.target"; //NOI18N |
241 |
final String javacTargetKey = "javac.target"; //NOI18N |
|
|
242 |
final String javacProfileKey = "javac.profile"; //NOI18N |
181 |
|
243 |
|
182 |
PlatformKey pk = (PlatformKey) platformKey; |
244 |
PlatformKey pk = (PlatformKey) platformKey; |
183 |
JavaPlatform platform = getPlatform(pk); |
245 |
JavaPlatform platform = getPlatform(pk); |
Lines 251-257
Link Here
|
251 |
if (sourceLevelKey == null) { |
313 |
if (sourceLevelKey == null) { |
252 |
sourceLevel = platform.getSpecification().getVersion(); |
314 |
sourceLevel = platform.getSpecification().getVersion(); |
253 |
} else { |
315 |
} else { |
254 |
assert sourceLevelKey instanceof SourceLevelKey; |
|
|
255 |
sourceLevel = ((SourceLevelKey) sourceLevelKey).getSourceLevel(); |
316 |
sourceLevel = ((SourceLevelKey) sourceLevelKey).getSourceLevel(); |
256 |
} |
317 |
} |
257 |
String javacSource = sourceLevel.toString(); |
318 |
String javacSource = sourceLevel.toString(); |
Lines 275-286
Link Here
|
275 |
if (!javacTarget.equals(props.getProperty(javacTargetKey))) { |
336 |
if (!javacTarget.equals(props.getProperty(javacTargetKey))) { |
276 |
props.setProperty(javacTargetKey, javacTarget); |
337 |
props.setProperty(javacTargetKey, javacTarget); |
277 |
} |
338 |
} |
|
|
339 |
|
340 |
final String javacProfile; |
341 |
if (profileKey != null) { |
342 |
javacProfile = ((Profile)profileKey).getName(); |
343 |
} else { |
344 |
javacProfile = null; |
345 |
} |
346 |
if (javacProfile != null) { |
347 |
if(!javacProfile.equals(props.getProperty(javacProfileKey))) { |
348 |
props.setProperty(javacProfileKey, javacProfile); |
349 |
} |
350 |
} else if (props.containsKey(javacProfileKey)) { |
351 |
props.remove(javacProfileKey); |
352 |
} |
278 |
|
353 |
|
279 |
if (changed) { |
354 |
if (changed) { |
280 |
helper.putPrimaryConfigurationData(root, true); |
355 |
helper.putPrimaryConfigurationData(root, true); |
281 |
} |
356 |
} |
282 |
} |
357 |
} |
283 |
|
358 |
|
|
|
359 |
/** |
360 |
* Returns a {@link SpecificationVersion} for an item obtained from the {@link ComboBoxModel} created by |
361 |
* the {@link PlatformUiSupport#createSourceLevelComboBoxModel} method. This method |
362 |
* can return <code>null</code> if the source level is broken. |
363 |
* @param sourceLevelKey an item obtained from {@link ComboBoxModel} created by |
364 |
* {@link PlatformUiSupport#createSourceLevelComboBoxModel}. |
365 |
* @return {@link SpecificationVersion} or <code>null</code> in case when source level is broken. |
366 |
* @throws IllegalArgumentException if the input parameter is not an object created by source level combobox model. |
367 |
* @since 1.45 |
368 |
*/ |
369 |
public static SpecificationVersion getSourceLevel(@NonNull final Object sourceLevelKey) { |
370 |
Parameters.notNull("sourceLevelKey", sourceLevelKey); //NOI18N |
371 |
if (!(sourceLevelKey instanceof SourceLevelKey)) { |
372 |
throw new IllegalArgumentException(String.format( |
373 |
"Unsupported source level key: %s of type: %s", //NOI18N |
374 |
sourceLevelKey, |
375 |
sourceLevelKey.getClass())); |
376 |
} |
377 |
return ((SourceLevelKey)sourceLevelKey).getSourceLevel(); |
378 |
} |
379 |
|
284 |
|
380 |
|
285 |
/** |
381 |
/** |
286 |
* Return a {@link JavaPlatform} for an item obtained from the ComboBoxModel created by |
382 |
* Return a {@link JavaPlatform} for an item obtained from the ComboBoxModel created by |
Lines 345-350
Link Here
|
345 |
} |
441 |
} |
346 |
|
442 |
|
347 |
/** |
443 |
/** |
|
|
444 |
* Create {@link ComboBoxModel} of JRE profiles for active source level. |
445 |
* The model listens on the source level {@link ComboBoxModel} and update its |
446 |
* state according to the changes. It is possible to define minimal required |
447 |
* JRE profile. |
448 |
* @param sourceLevelModel the source level model used for listening. |
449 |
* @param initialProfile initial profile, null if unknown. |
450 |
* @param minimalProfile minimal JRE profile to be displayed. |
451 |
* It can be <code>null</code> if all the JRE profiles should be displayed. |
452 |
* @return {@link ComboBoxModel}. |
453 |
* @since 1.45 |
454 |
*/ |
455 |
public static ComboBoxModel createProfileComboBoxModel( |
456 |
@NonNull final ComboBoxModel sourceLevelModel, |
457 |
@NullAllowed final String initialProfile, |
458 |
@NullAllowed final String minimalProfile) { |
459 |
return new ProfileComboBoxModel(sourceLevelModel, initialProfile, minimalProfile); |
460 |
} |
461 |
|
462 |
/** |
463 |
* Create {@link ListCellRenderer} for JRE profiles. |
464 |
* This renderer highlights incorrect profile names. |
465 |
* @return {@link ListCellRenderer} for JRE profiles. |
466 |
* @since 1.45 |
467 |
*/ |
468 |
public static ListCellRenderer createProfileListCellRenderer() { |
469 |
return new ProfileListCellRenderer(); |
470 |
} |
471 |
|
472 |
/** |
348 |
* This class represents a JavaPlatform in the {@link ListModel} |
473 |
* This class represents a JavaPlatform in the {@link ListModel} |
349 |
* created by the {@link PlatformUiSupport#createPlatformComboBoxModel(String)} method. |
474 |
* created by the {@link PlatformUiSupport#createPlatformComboBoxModel(String)} method. |
350 |
*/ |
475 |
*/ |
Lines 814-819
Link Here
|
814 |
} |
939 |
} |
815 |
} |
940 |
} |
816 |
|
941 |
|
|
|
942 |
private interface Profile { |
943 |
@NonNull |
944 |
String getName(); |
945 |
|
946 |
@NonNull |
947 |
String getDisplayName(); |
948 |
|
949 |
int getRank(); |
950 |
|
951 |
boolean isSupportedIn(@NonNull final SpecificationVersion sourceLevel); |
952 |
} |
953 |
|
954 |
private enum StandardProfile implements Profile { |
955 |
COMPACT1( |
956 |
"compact1", //NOI18N |
957 |
NbBundle.getMessage(PlatformUiSupport.class, "TXT_Profile_Compact1"), |
958 |
0, |
959 |
Arrays.asList(JDK_8)), |
960 |
COMPACT2( |
961 |
"compact2", //NOI18N |
962 |
NbBundle.getMessage(PlatformUiSupport.class, "TXT_Profile_Compact2"), |
963 |
1, |
964 |
Arrays.asList(JDK_8)), |
965 |
COMPACT3( |
966 |
"compact3", //NOI18N |
967 |
NbBundle.getMessage(PlatformUiSupport.class, "TXT_Profile_Compact3"), |
968 |
2, |
969 |
Arrays.asList(JDK_8)), |
970 |
DEFAULT( |
971 |
"default", //NOI18N |
972 |
NbBundle.getMessage(PlatformUiSupport.class, "TXT_Profile_Default"), |
973 |
Integer.MAX_VALUE-1, |
974 |
Arrays.asList(JDK_8)); |
975 |
|
976 |
private static final Map<String,Profile> profilesByName = |
977 |
new HashMap<String, Profile>(); |
978 |
static { |
979 |
for (Profile p : values()) { |
980 |
profilesByName.put(p.getName(), p); |
981 |
} |
982 |
} |
983 |
|
984 |
private final String name; |
985 |
private final String displayName; |
986 |
private final int rank; |
987 |
private final Set<? extends SpecificationVersion> supportedIn; |
988 |
|
989 |
StandardProfile( |
990 |
@NonNull final String name, |
991 |
@NonNull final String displayName, |
992 |
@NonNull final int rank, |
993 |
@NonNull final Collection<? extends SpecificationVersion> supportedIn) { |
994 |
Parameters.notNull("name", name); //NOI18N |
995 |
Parameters.notNull("displayName", displayName); //NOI18N |
996 |
this.name = name; |
997 |
this.displayName = displayName; |
998 |
this.rank = rank; |
999 |
this.supportedIn = Collections.unmodifiableSet( |
1000 |
new HashSet<SpecificationVersion>(supportedIn)); |
1001 |
} |
1002 |
|
1003 |
@Override |
1004 |
public String getName() { |
1005 |
return name; |
1006 |
} |
1007 |
|
1008 |
@Override |
1009 |
public String getDisplayName() { |
1010 |
return displayName; |
1011 |
} |
1012 |
|
1013 |
@Override |
1014 |
public int getRank() { |
1015 |
return rank; |
1016 |
} |
1017 |
|
1018 |
@Override |
1019 |
public boolean isSupportedIn(SpecificationVersion sourceLevel) { |
1020 |
return supportedIn.contains(sourceLevel); |
1021 |
} |
1022 |
|
1023 |
@Override |
1024 |
public String toString() { |
1025 |
return String.format( |
1026 |
"%s (%s)", //NOI18N |
1027 |
displayName, |
1028 |
name); |
1029 |
} |
1030 |
|
1031 |
@CheckForNull |
1032 |
static Profile forName(@NonNull final String id) { |
1033 |
return profilesByName.get(id); |
1034 |
} |
1035 |
|
1036 |
} |
1037 |
|
1038 |
private static final class ProfileComboBoxModel extends AbstractListModel implements ComboBoxModel, ListDataListener { |
1039 |
|
1040 |
private final ComboBoxModel sourceLevelModel; |
1041 |
private final String initialProfileName; |
1042 |
private final String minimalProfileName; |
1043 |
|
1044 |
private Profile[] profiles; |
1045 |
private Profile selectedItem; |
1046 |
|
1047 |
ProfileComboBoxModel( |
1048 |
@NonNull final ComboBoxModel sourceLevelModel, |
1049 |
@NullAllowed final String initialProfileName, |
1050 |
@NullAllowed final String minimalProfileName) { |
1051 |
this.sourceLevelModel = sourceLevelModel; |
1052 |
this.initialProfileName = initialProfileName; |
1053 |
this.minimalProfileName = minimalProfileName; |
1054 |
this.sourceLevelModel.addListDataListener(this); |
1055 |
} |
1056 |
|
1057 |
@Override |
1058 |
public int getSize() { |
1059 |
final Profile[] p = init(); |
1060 |
return p.length; |
1061 |
} |
1062 |
|
1063 |
@Override |
1064 |
@CheckForNull |
1065 |
public Object getElementAt(final int index) { |
1066 |
final Profile[] p = init(); |
1067 |
if (index < 0 || index >= p.length) { |
1068 |
throw new IndexOutOfBoundsException(String.format( |
1069 |
"Index: %d, Profiles count: %d", //NOI18N |
1070 |
index, |
1071 |
p.length)); |
1072 |
} |
1073 |
return p[index]; |
1074 |
} |
1075 |
|
1076 |
@Override |
1077 |
public void setSelectedItem(@NullAllowed final Object anItem) { |
1078 |
assert anItem == null || anItem instanceof Profile; |
1079 |
selectedItem = (Profile) anItem; |
1080 |
} |
1081 |
|
1082 |
@Override |
1083 |
@CheckForNull |
1084 |
public Object getSelectedItem() { |
1085 |
return selectedItem; |
1086 |
} |
1087 |
|
1088 |
@Override |
1089 |
public void intervalAdded(ListDataEvent e) { |
1090 |
} |
1091 |
|
1092 |
@Override |
1093 |
public void intervalRemoved(ListDataEvent e) { |
1094 |
} |
1095 |
|
1096 |
@Override |
1097 |
public void contentsChanged(ListDataEvent e) { |
1098 |
final int oldSize = getSize(); |
1099 |
profiles = null; |
1100 |
fireContentsChanged(this, 0, oldSize); |
1101 |
} |
1102 |
|
1103 |
private Profile[] init() { |
1104 |
if (profiles == null) { |
1105 |
final Comparator<Profile> c = new Comparator<Profile>() { |
1106 |
@Override |
1107 |
public int compare( |
1108 |
@NonNull final Profile p1, |
1109 |
@NonNull final Profile p2) { |
1110 |
final int r1 = p1.getRank(); |
1111 |
final int r2 = p2.getRank(); |
1112 |
return r1 < r2 ? |
1113 |
-1 : |
1114 |
r1 == r2 ? |
1115 |
0 : |
1116 |
1; |
1117 |
} |
1118 |
}; |
1119 |
Profile minimalProfile = null; |
1120 |
if (minimalProfileName != null) { |
1121 |
minimalProfile = StandardProfile.forName(minimalProfileName); |
1122 |
} |
1123 |
final Collection<Profile> pc = new TreeSet<Profile>(c); |
1124 |
final Object slk = sourceLevelModel.getSelectedItem(); |
1125 |
final SpecificationVersion sl; |
1126 |
if (slk instanceof SourceLevelKey) { |
1127 |
sl = ((SourceLevelKey)slk).getSourceLevel(); |
1128 |
} else { |
1129 |
sl = null; |
1130 |
} |
1131 |
for (StandardProfile p : StandardProfile.values()) { |
1132 |
if (minimalProfile != null && |
1133 |
c.compare(minimalProfile, selectedItem) > 0) { |
1134 |
continue; |
1135 |
} |
1136 |
if (sl != null && !p.isSupportedIn(sl)) { |
1137 |
continue; |
1138 |
} |
1139 |
pc.add(p); |
1140 |
} |
1141 |
if (selectedItem == null) { |
1142 |
if (initialProfileName != null && !initialProfileName.isEmpty()) { |
1143 |
selectedItem = StandardProfile.forName(initialProfileName); |
1144 |
if (selectedItem == null) { |
1145 |
selectedItem = new Profile() { |
1146 |
@Override |
1147 |
public String getName() { |
1148 |
return initialProfileName; |
1149 |
} |
1150 |
@Override |
1151 |
public String getDisplayName() { |
1152 |
return getName(); |
1153 |
} |
1154 |
@Override |
1155 |
public int getRank() { |
1156 |
return Integer.MAX_VALUE; |
1157 |
} |
1158 |
@Override |
1159 |
public boolean isSupportedIn(SpecificationVersion sourceLevel) { |
1160 |
return true; |
1161 |
} |
1162 |
}; |
1163 |
pc.add(selectedItem); |
1164 |
} |
1165 |
} else { |
1166 |
selectedItem = StandardProfile.DEFAULT; |
1167 |
} |
1168 |
} |
1169 |
this.profiles = pc.toArray(new Profile[pc.size()]); |
1170 |
} |
1171 |
return profiles; |
1172 |
} |
1173 |
} |
1174 |
|
1175 |
private static final class ProfileListCellRenderer implements ListCellRenderer { |
1176 |
|
1177 |
private final ListCellRenderer delegate; |
1178 |
|
1179 |
ProfileListCellRenderer() { |
1180 |
delegate = HtmlRenderer.createRenderer(); |
1181 |
} |
1182 |
|
1183 |
@Override |
1184 |
public Component getListCellRendererComponent( |
1185 |
@NonNull final JList list, |
1186 |
@NullAllowed Object value, |
1187 |
final int index, |
1188 |
final boolean isSelected, |
1189 |
final boolean cellHasFocus) { |
1190 |
if (value instanceof Profile) { |
1191 |
final Profile p = (Profile) value; |
1192 |
if (StandardProfile.forName(p.getName()) == null) { |
1193 |
value = "<html><font color=\"#A40000\">" + //NOI18N |
1194 |
p.getDisplayName(); |
1195 |
} else { |
1196 |
value = p.getDisplayName(); |
1197 |
} |
1198 |
} |
1199 |
return delegate.getListCellRendererComponent( |
1200 |
list, value, index, isSelected, cellHasFocus); |
1201 |
} |
1202 |
|
1203 |
} |
1204 |
|
817 |
/** |
1205 |
/** |
818 |
* Retturns a {@link JavaPlatform} for given {@link PlatformKey} |
1206 |
* Retturns a {@link JavaPlatform} for given {@link PlatformKey} |
819 |
* or null when the platformKey is either null or not bound to a platform. |
1207 |
* or null when the platformKey is either null or not bound to a platform. |