Added
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2008 IBM Corporation and others. |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
6 |
* http://www.eclipse.org/legal/epl-v10.html |
7 |
* |
8 |
* Contributors: |
9 |
* IBM Corporation - initial API and implementation |
10 |
*******************************************************************************/ |
11 |
package org.eclipse.pde.internal.ui.preferences; |
12 |
|
13 |
import com.ibm.icu.text.MessageFormat; |
14 |
import java.util.*; |
15 |
import java.util.List; |
16 |
import org.eclipse.core.resources.*; |
17 |
import org.eclipse.core.runtime.*; |
18 |
import org.eclipse.core.runtime.jobs.Job; |
19 |
import org.eclipse.core.runtime.preferences.*; |
20 |
import org.eclipse.jface.dialogs.IDialogSettings; |
21 |
import org.eclipse.jface.dialogs.MessageDialog; |
22 |
import org.eclipse.jface.resource.JFaceResources; |
23 |
import org.eclipse.pde.internal.core.builders.CompilerFlags; |
24 |
import org.eclipse.pde.internal.core.natures.PDE; |
25 |
import org.eclipse.pde.internal.ui.*; |
26 |
import org.eclipse.swt.SWT; |
27 |
import org.eclipse.swt.custom.ScrolledComposite; |
28 |
import org.eclipse.swt.events.*; |
29 |
import org.eclipse.swt.graphics.Point; |
30 |
import org.eclipse.swt.layout.GridData; |
31 |
import org.eclipse.swt.layout.GridLayout; |
32 |
import org.eclipse.swt.widgets.*; |
33 |
import org.eclipse.ui.forms.events.ExpansionAdapter; |
34 |
import org.eclipse.ui.forms.events.ExpansionEvent; |
35 |
import org.eclipse.ui.forms.widgets.ExpandableComposite; |
36 |
import org.eclipse.ui.preferences.*; |
37 |
import org.osgi.service.prefs.BackingStoreException; |
38 |
|
39 |
/** |
40 |
* A configuration block for setting PDE compiler preferences |
41 |
* |
42 |
* @since 3.4 |
43 |
*/ |
44 |
public class PDECompilersConfigurationBlock { |
45 |
|
46 |
/** |
47 |
* Provides data information for created controls |
48 |
*/ |
49 |
protected static class ControlData { |
50 |
private Key key; |
51 |
private String[] values; |
52 |
|
53 |
/** |
54 |
* Constructor |
55 |
* @param key |
56 |
* @param values |
57 |
*/ |
58 |
public ControlData(Key key, String[] values) { |
59 |
this.key = key; |
60 |
this.values = values; |
61 |
} |
62 |
|
63 |
public Key getKey() { |
64 |
return key; |
65 |
} |
66 |
|
67 |
public String getValue(boolean selection) { |
68 |
int index = selection ? 0 : 1; |
69 |
return values[index]; |
70 |
} |
71 |
|
72 |
public String getValue(int index) { |
73 |
return values[index]; |
74 |
} |
75 |
|
76 |
public int getSelection(String value) { |
77 |
if (value != null) { |
78 |
for (int i = 0; i < values.length; i++) { |
79 |
if (value.equals(values[i])) { |
80 |
return i; |
81 |
} |
82 |
} |
83 |
} |
84 |
return values.length - 1; // assume the last option is the least severe |
85 |
} |
86 |
} |
87 |
|
88 |
/** |
89 |
* Provides management for changed/stored values for a given preference key |
90 |
*/ |
91 |
protected static class Key { |
92 |
|
93 |
private String qualifier; |
94 |
private String key; |
95 |
|
96 |
/** |
97 |
* Constructor |
98 |
* @param qualifier |
99 |
* @param key |
100 |
*/ |
101 |
public Key(String qualifier, String key) { |
102 |
this.qualifier = qualifier; |
103 |
this.key = key; |
104 |
} |
105 |
|
106 |
/** |
107 |
* Returns the {@link IEclipsePreferences} node for the given context and {@link IWorkingCopyManager} |
108 |
* @param context |
109 |
* @param manager |
110 |
* @return the {@link IEclipsePreferences} node or <code>null</code> |
111 |
*/ |
112 |
private IEclipsePreferences getNode(IScopeContext context, IWorkingCopyManager manager) { |
113 |
IEclipsePreferences node = context.getNode(qualifier); |
114 |
if (manager != null) { |
115 |
return manager.getWorkingCopy(node); |
116 |
} |
117 |
return node; |
118 |
} |
119 |
|
120 |
/** |
121 |
* Returns the value stored in the {@link IEclipsePreferences} node from the given context and working copy manager |
122 |
* @param context |
123 |
* @param manager |
124 |
* @return the value from the {@link IEclipsePreferences} node or <code>null</code> |
125 |
*/ |
126 |
public String getStoredValue(IScopeContext context, IWorkingCopyManager manager) { |
127 |
IEclipsePreferences node = getNode(context, manager); |
128 |
if (node != null) { |
129 |
return node.get(key, null); |
130 |
} |
131 |
return null; |
132 |
} |
133 |
|
134 |
/** |
135 |
* Returns the stored value of this {@link IEclipsePreferences} node using a given lookup order, and allowing the |
136 |
* top scope to be ignored |
137 |
* @param lookupOrder |
138 |
* @param ignoreTopScope |
139 |
* @param manager |
140 |
* @return the value from the {@link IEclipsePreferences} node or <code>null</code> |
141 |
*/ |
142 |
public String getStoredValue(IScopeContext[] lookupOrder, boolean ignoreTopScope, IWorkingCopyManager manager) { |
143 |
for (int i = ignoreTopScope ? 1 : 0; i < lookupOrder.length; i++) { |
144 |
String value = getStoredValue(lookupOrder[i], manager); |
145 |
if (value != null) { |
146 |
return value; |
147 |
} |
148 |
} |
149 |
return null; |
150 |
} |
151 |
|
152 |
/** |
153 |
* Sets the value of this key |
154 |
* @param context |
155 |
* @param value |
156 |
* @param manager |
157 |
*/ |
158 |
public void setStoredValue(IScopeContext context, String value, IWorkingCopyManager manager) { |
159 |
IEclipsePreferences node = getNode(context, manager); |
160 |
if (value != null) { |
161 |
node.put(key, value); |
162 |
} else { |
163 |
node.remove(key); |
164 |
} |
165 |
} |
166 |
|
167 |
/* (non-Javadoc) |
168 |
* @see java.lang.Object#toString() |
169 |
*/ |
170 |
public String toString() { |
171 |
return qualifier + '/' + key; |
172 |
} |
173 |
} |
174 |
|
175 |
/** |
176 |
* Returns a new {@link Key} for the {@link PDEPlugin} preference store |
177 |
* @param key |
178 |
* @return the new {@link Key} for the {@link PDEPlugin} preference store |
179 |
*/ |
180 |
protected final static Key getPDEPrefKey(String key) { |
181 |
return new Key(PDE.PLUGIN_ID, key); |
182 |
} |
183 |
|
184 |
//unresolved |
185 |
private static final Key KEY_P_UNRESOLVED_IMPORTS = getPDEPrefKey(CompilerFlags.P_UNRESOLVED_IMPORTS); |
186 |
private static final Key KEY_P_UNRESOLVED_EX_POINTS = getPDEPrefKey(CompilerFlags.P_UNRESOLVED_EX_POINTS); |
187 |
private static final Key KEY_F_UNRESOLVED_PLUGINS = getPDEPrefKey(CompilerFlags.F_UNRESOLVED_PLUGINS); |
188 |
private static final Key KEY_F_UNRESOLVED_FEATURES = getPDEPrefKey(CompilerFlags.F_UNRESOLVED_FEATURES); |
189 |
|
190 |
//unknown elements |
191 |
private static final Key KEY_P_UNKNOWN_ELEMENT = getPDEPrefKey(CompilerFlags.P_UNKNOWN_ELEMENT); |
192 |
private static final Key KEY_P_UNKNOWN_ATTRIBUTE = getPDEPrefKey(CompilerFlags.P_UNKNOWN_ATTRIBUTE); |
193 |
private static final Key KEY_P_UNKNOWN_CLASS = getPDEPrefKey(CompilerFlags.P_UNKNOWN_CLASS); |
194 |
private static final Key KEY_P_UNKNOWN_RESOURCE = getPDEPrefKey(CompilerFlags.P_UNKNOWN_RESOURCE); |
195 |
private static final Key KEY_P_UNKNOWN_IDENTIFIER = getPDEPrefKey(CompilerFlags.P_UNKNOWN_IDENTIFIER); |
196 |
|
197 |
//general |
198 |
private static final Key KEY_P_DISCOURAGED_CLASS = getPDEPrefKey(CompilerFlags.P_DISCOURAGED_CLASS); |
199 |
private static final Key KEY_P_NO_REQUIRED_ATT = getPDEPrefKey(CompilerFlags.P_NO_REQUIRED_ATT); |
200 |
private static final Key KEY_P_BUILD = getPDEPrefKey(CompilerFlags.P_BUILD); |
201 |
private static final Key KEY_P_NOT_EXTERNALIZED = getPDEPrefKey(CompilerFlags.P_NOT_EXTERNALIZED); |
202 |
private static final Key KEY_P_INCOMPATIBLE_ENV = getPDEPrefKey(CompilerFlags.P_INCOMPATIBLE_ENV); |
203 |
private static final Key KEY_P_MISSING_EXPORT_PKGS = getPDEPrefKey(CompilerFlags.P_MISSING_EXPORT_PKGS); |
204 |
private static final Key KEY_P_DEPRECATED = getPDEPrefKey(CompilerFlags.P_DEPRECATED); |
205 |
private static final Key KEY_P_MISSING_BUNDLE_CLASSPATH_ENTRIES = getPDEPrefKey(CompilerFlags.P_MISSING_BUNDLE_CLASSPATH_ENTRIES); |
206 |
private static final Key KEY_S_CREATE_DOCS = getPDEPrefKey(CompilerFlags.S_CREATE_DOCS); |
207 |
private static final Key KEY_S_DOC_FOLDER = getPDEPrefKey(CompilerFlags.S_DOC_FOLDER); |
208 |
private static final Key KEY_S_OPEN_TAGS = getPDEPrefKey(CompilerFlags.S_OPEN_TAGS); |
209 |
|
210 |
private static String[] SEVERITIES = {IPreferenceConstants.VALUE_ERROR, IPreferenceConstants.VALUE_WARNING, IPreferenceConstants.VALUE_IGNORE}; |
211 |
|
212 |
private static Key[] fgAllKeys = {KEY_F_UNRESOLVED_FEATURES, KEY_F_UNRESOLVED_PLUGINS, KEY_P_BUILD, KEY_P_DEPRECATED, KEY_P_DISCOURAGED_CLASS, KEY_P_INCOMPATIBLE_ENV, KEY_P_MISSING_BUNDLE_CLASSPATH_ENTRIES, KEY_P_MISSING_EXPORT_PKGS, KEY_P_NO_REQUIRED_ATT, KEY_P_NOT_EXTERNALIZED, KEY_P_UNKNOWN_ATTRIBUTE, KEY_P_UNKNOWN_CLASS, KEY_P_UNKNOWN_ELEMENT, KEY_P_UNKNOWN_IDENTIFIER, KEY_P_UNKNOWN_RESOURCE, KEY_P_UNRESOLVED_EX_POINTS, KEY_P_UNRESOLVED_IMPORTS, KEY_S_CREATE_DOCS, KEY_S_DOC_FOLDER, KEY_S_OPEN_TAGS}; |
213 |
|
214 |
/** |
215 |
* Constant representing the {@link IDialogSettings} section for this block |
216 |
*/ |
217 |
private static final String SETTINGS = "pde_compiler_errorwarnings_block"; //$NON-NLS-1$ |
218 |
|
219 |
/** |
220 |
* The context of settings locations to search for values in |
221 |
*/ |
222 |
private IScopeContext[] fLookupOrder = null; |
223 |
|
224 |
/** |
225 |
* The project this block is working on settings for. Only applies in the |
226 |
* case of project specific settings |
227 |
*/ |
228 |
private IProject fProject = null; |
229 |
|
230 |
/** |
231 |
* the working copy manager to work with settings |
232 |
*/ |
233 |
private IWorkingCopyManager fManager = null; |
234 |
|
235 |
/** |
236 |
* The main composite for the configuration block, used for enabling/disabling the block |
237 |
*/ |
238 |
private Composite fMainComp = null; |
239 |
|
240 |
/** |
241 |
* Stored old fProject specific settings. |
242 |
*/ |
243 |
private IdentityHashMap fOldProjectSettings = null; |
244 |
|
245 |
/** |
246 |
* Map of controls to the tab they appear on. Allows for optimizing which builders |
247 |
* are used if changes are made |
248 |
*/ |
249 |
private HashMap fControlMap = new HashMap(3); |
250 |
|
251 |
/** |
252 |
* Listing of all of the {@link ExpandableComposite}s in the block |
253 |
*/ |
254 |
private ArrayList fExpComps = new ArrayList(); |
255 |
|
256 |
/** |
257 |
* Flag used to know if the page needs saving or not |
258 |
*/ |
259 |
private boolean fDirty = false; |
260 |
|
261 |
/** |
262 |
* counter to know how many times we have prompted users' to rebuild |
263 |
*/ |
264 |
private int fRebuildcount = 0; |
265 |
|
266 |
/** |
267 |
* Set of builders to use when building if there are changes |
268 |
*/ |
269 |
private HashSet fBuilders = new HashSet(4); |
270 |
|
271 |
/** |
272 |
* The parent this block has been added to |
273 |
*/ |
274 |
private Composite fParent = null; |
275 |
|
276 |
/** |
277 |
* Default selection listener for combo and check controls |
278 |
*/ |
279 |
private SelectionListener selectionlistener = new SelectionAdapter() { |
280 |
public void widgetSelected(SelectionEvent e) { |
281 |
if (e.widget instanceof Combo) { |
282 |
Combo combo = (Combo) e.widget; |
283 |
ControlData data = (ControlData) combo.getData(); |
284 |
data.key.setStoredValue(fLookupOrder[0], Integer.toString(combo.getSelectionIndex()), fManager); |
285 |
fDirty = true; |
286 |
fRebuildcount = 0; |
287 |
} else if (e.widget instanceof Button) { |
288 |
Button button = (Button) e.widget; |
289 |
ControlData data = (ControlData) button.getData(); |
290 |
data.key.setStoredValue(fLookupOrder[0], Boolean.toString(button.getSelection()), fManager); |
291 |
fDirty = true; |
292 |
fRebuildcount = 0; |
293 |
} |
294 |
addBuilder((Control) e.widget); |
295 |
} |
296 |
}; |
297 |
|
298 |
/** |
299 |
* Default modify listener for text controls |
300 |
*/ |
301 |
private ModifyListener modifylistener = new ModifyListener() { |
302 |
public void modifyText(ModifyEvent e) { |
303 |
if (e.widget instanceof Text) { |
304 |
Text text = (Text) e.widget; |
305 |
ControlData data = (ControlData) text.getData(); |
306 |
data.key.setStoredValue(fLookupOrder[0], text.getText().trim(), fManager); |
307 |
fDirty = true; |
308 |
fRebuildcount = 0; |
309 |
} |
310 |
} |
311 |
}; |
312 |
|
313 |
/** |
314 |
* Constructor |
315 |
* @param project |
316 |
* @param container |
317 |
*/ |
318 |
public PDECompilersConfigurationBlock(IProject project, IWorkbenchPreferenceContainer container) { |
319 |
fProject = project; |
320 |
if (fProject != null) { |
321 |
fLookupOrder = new IScopeContext[] {new ProjectScope(fProject), new InstanceScope(), new DefaultScope()}; |
322 |
} else { |
323 |
fLookupOrder = new IScopeContext[] {new InstanceScope(), new DefaultScope()}; |
324 |
} |
325 |
if (container == null) { |
326 |
fManager = new WorkingCopyManager(); |
327 |
} else { |
328 |
fManager = container.getWorkingCopyManager(); |
329 |
} |
330 |
if (fProject == null || hasProjectSpecificSettings(fProject)) { |
331 |
fOldProjectSettings = null; |
332 |
} else { |
333 |
fOldProjectSettings = new IdentityHashMap(); |
334 |
for (int i = 0; i < fgAllKeys.length; i++) { |
335 |
fOldProjectSettings.put(fgAllKeys[i], fgAllKeys[i].getStoredValue(fLookupOrder, false, fManager)); |
336 |
} |
337 |
} |
338 |
} |
339 |
|
340 |
/** |
341 |
* returns if this block has fProject specific settings |
342 |
* @param fProject |
343 |
* @return true if there are fProject specific settings, false otherwise |
344 |
*/ |
345 |
public boolean hasProjectSpecificSettings(IProject project) { |
346 |
if (project != null) { |
347 |
IScopeContext projectContext = new ProjectScope(project); |
348 |
for (int i = 0; i < fgAllKeys.length; i++) { |
349 |
if (fgAllKeys[i].getStoredValue(projectContext, fManager) != null) { |
350 |
return true; |
351 |
} |
352 |
} |
353 |
} |
354 |
return false; |
355 |
} |
356 |
|
357 |
/** |
358 |
* Sets using project specific settings |
359 |
* @param enable |
360 |
*/ |
361 |
public void useProjectSpecificSettings(boolean enable) { |
362 |
boolean disabled = fOldProjectSettings == null; |
363 |
if (enable != disabled && fProject != null) { |
364 |
if (enable) { |
365 |
for (int i = 0; i < fgAllKeys.length; i++) { |
366 |
fgAllKeys[i].setStoredValue(fLookupOrder[0], (String) fOldProjectSettings.get(fgAllKeys[i]), fManager); |
367 |
} |
368 |
fOldProjectSettings = null; |
369 |
updateControls(); |
370 |
} else { |
371 |
fOldProjectSettings = new IdentityHashMap(); |
372 |
String old = null; |
373 |
for (int i = 0; i < fgAllKeys.length; i++) { |
374 |
old = fgAllKeys[i].getStoredValue(fLookupOrder, false, fManager); |
375 |
fOldProjectSettings.put(fgAllKeys[i], old); |
376 |
fgAllKeys[i].setStoredValue(fLookupOrder[0], null, fManager); |
377 |
} |
378 |
} |
379 |
} |
380 |
fDirty = true; |
381 |
enableControl(fMainComp, enable); |
382 |
} |
383 |
|
384 |
/** |
385 |
* Updates all of the registered {@link Control}s on the page. |
386 |
* Registration implies that the {@link Control} was added to the map |
387 |
* fControlMap |
388 |
*/ |
389 |
private void updateControls() { |
390 |
HashSet controls = null; |
391 |
Control control = null; |
392 |
for (Iterator iter = fControlMap.keySet().iterator(); iter.hasNext();) { |
393 |
controls = (HashSet) fControlMap.get(iter.next()); |
394 |
if (controls == null) { |
395 |
continue; |
396 |
} |
397 |
for (Iterator iter2 = controls.iterator(); iter2.hasNext();) { |
398 |
control = (Control) iter2.next(); |
399 |
if (control instanceof Combo) { |
400 |
Combo combo = (Combo) control; |
401 |
ControlData data = (ControlData) combo.getData(); |
402 |
int index = 0; |
403 |
try { |
404 |
index = Integer.parseInt(data.key.getStoredValue(fLookupOrder, false, fManager)); |
405 |
} catch (Exception e) { |
406 |
//set the default if something goes wrong |
407 |
index = Integer.parseInt(data.key.getStoredValue(fLookupOrder, true, fManager)); |
408 |
} |
409 |
combo.select(data.getSelection(SEVERITIES[index])); |
410 |
} else if (control instanceof Button) { |
411 |
Button button = (Button) control; |
412 |
ControlData data = (ControlData) button.getData(); |
413 |
button.setSelection(Boolean.valueOf(data.key.getStoredValue(fLookupOrder, false, fManager)).booleanValue()); |
414 |
} else if (control instanceof Text) { |
415 |
Text text = (Text) control; |
416 |
ControlData data = (ControlData) text.getData(); |
417 |
text.setText(data.key.getStoredValue(fLookupOrder, false, fManager)); |
418 |
} |
419 |
} |
420 |
} |
421 |
} |
422 |
|
423 |
/** |
424 |
* recursive method to enable/disable all of the controls on the main page |
425 |
* @param ctrl |
426 |
* @param enabled |
427 |
*/ |
428 |
private void enableControl(Control ctrl, boolean enabled) { |
429 |
ctrl.setEnabled(enabled); |
430 |
if (ctrl instanceof Composite) { |
431 |
Composite comp = (Composite) ctrl; |
432 |
Control[] children = comp.getChildren(); |
433 |
for (int i = 0; i < children.length; i++) { |
434 |
enableControl(children[i], enabled); |
435 |
} |
436 |
} |
437 |
} |
438 |
|
439 |
/** |
440 |
* Creates the control in the parent control |
441 |
* |
442 |
* @param parent the parent control |
443 |
*/ |
444 |
public Control createControl(Composite parent) { |
445 |
fParent = parent; |
446 |
fMainComp = SWTFactory.createComposite(parent, 1, 1, GridData.FILL_BOTH, 0, 0); |
447 |
TabFolder folder = null; |
448 |
if (fProject == null) { |
449 |
SWTFactory.createVerticalSpacer(parent, 1); |
450 |
folder = new TabFolder(fMainComp, SWT.NONE); |
451 |
GridData gd = new GridData(GridData.FILL_BOTH); |
452 |
gd.heightHint = 375; |
453 |
gd.widthHint = 400; |
454 |
folder.setLayoutData(gd); |
455 |
} |
456 |
|
457 |
Composite main = (folder == null ? fMainComp : folder); |
458 |
//plugins page |
459 |
createPage(CompilerFlags.PLUGIN_FLAGS, main, PDEUIMessages.CompilersConfigurationBlock_plugins, PDEUIMessages.CompilersConfigurationBlock_label); |
460 |
|
461 |
if (fProject == null) { |
462 |
//the sharing property page does not use these two tabs |
463 |
//schema page |
464 |
createPage(CompilerFlags.SCHEMA_FLAGS, main, PDEUIMessages.CompilersConfigurationBlock_schemas, PDEUIMessages.CompilersConfigurationBlock_altlabel); |
465 |
|
466 |
//features / sites page |
467 |
createPage(CompilerFlags.FEATURE_FLAGS, main, PDEUIMessages.CompilersConfigurationBlock_features, PDEUIMessages.CompilersConfigurationBlock_label); |
468 |
} |
469 |
restoreExpansionState(); |
470 |
return fMainComp; |
471 |
} |
472 |
|
473 |
/** |
474 |
* Creates a tab page parented in the folder |
475 |
* @param kind |
476 |
* @param folder |
477 |
* @param name |
478 |
* @param description |
479 |
* @return a new composite to act as the page for a tab |
480 |
*/ |
481 |
private Composite createPage(int kind, Composite folder, String name, String description) { |
482 |
Composite page = SWTFactory.createComposite(folder, 1, 1, GridData.FILL_BOTH); |
483 |
Composite parent = page; |
484 |
if (fProject == null) { |
485 |
TabItem tab = new TabItem((TabFolder) folder, SWT.NONE); |
486 |
tab.setText(name); |
487 |
tab.setControl(page); |
488 |
parent = SWTFactory.createComposite(page, 2, 1, GridData.FILL_BOTH); |
489 |
} |
490 |
SWTFactory.createWrapLabel(parent, description, 2); |
491 |
SWTFactory.createVerticalSpacer(parent, 1); |
492 |
switch (kind) { |
493 |
case CompilerFlags.PLUGIN_FLAGS : { |
494 |
ScrolledComposite scomp = createScrolledComposite(parent, 1); |
495 |
Composite sbody = SWTFactory.createComposite(scomp, 1, 1, GridData.FILL_BOTH); |
496 |
scomp.setContent(sbody); |
497 |
//General |
498 |
Composite client = createExpansibleComposite(sbody, PDEUIMessages.PDECompilersConfigurationBlock_general); |
499 |
initializeComboControls(client, new String[] {PDEUIMessages.compilers_p_no_required_att, PDEUIMessages.CompilersConfigurationTab_buildPropertiesErrors, PDEUIMessages.CompilersConfigurationTab_incompatEnv, PDEUIMessages.compilers_p_exported_pkgs, PDEUIMessages.CompilersConfigurationTab_missingBundleClasspathEntries}, new Key[] {KEY_P_NO_REQUIRED_ATT, KEY_P_BUILD, KEY_P_INCOMPATIBLE_ENV, KEY_P_MISSING_EXPORT_PKGS, KEY_P_MISSING_BUNDLE_CLASSPATH_ENTRIES}, CompilerFlags.PLUGIN_FLAGS); |
500 |
//Usage |
501 |
client = createExpansibleComposite(sbody, PDEUIMessages.PDECompilersConfigurationBlock_usage); |
502 |
initializeComboControls(client, new String[] {PDEUIMessages.compilers_p_unresolved_import, PDEUIMessages.compilers_p_unresolved_ex_points, PDEUIMessages.compilers_p_deprecated, PDEUIMessages.compilers_p_not_externalized_att}, new Key[] {KEY_P_UNRESOLVED_IMPORTS, KEY_P_UNRESOLVED_EX_POINTS, KEY_P_DEPRECATED, KEY_P_NOT_EXTERNALIZED}, CompilerFlags.PLUGIN_FLAGS); |
503 |
//References |
504 |
client = createExpansibleComposite(sbody, PDEUIMessages.PDECompilersConfigurationBlock_references); |
505 |
initializeComboControls(client, new String[] {PDEUIMessages.compilers_p_unknown_element, PDEUIMessages.compilers_p_unknown_attribute, PDEUIMessages.compilers_p_unknown_class, PDEUIMessages.compilers_p_discouraged_class, PDEUIMessages.compilers_p_unknown_resource, PDEUIMessages.compilers_p_unknown_identifier}, new Key[] {KEY_P_UNKNOWN_ELEMENT, KEY_P_UNKNOWN_ATTRIBUTE, KEY_P_UNKNOWN_CLASS, KEY_P_DISCOURAGED_CLASS, KEY_P_UNKNOWN_RESOURCE, KEY_P_UNKNOWN_IDENTIFIER,}, CompilerFlags.PLUGIN_FLAGS); |
506 |
|
507 |
break; |
508 |
} |
509 |
case CompilerFlags.SCHEMA_FLAGS : { |
510 |
createCheckControl(parent, PDEUIMessages.compilers_s_create_docs, KEY_S_CREATE_DOCS, CompilerFlags.SCHEMA_FLAGS); |
511 |
Composite comp = SWTFactory.createComposite(parent, 2, 2, GridData.FILL_HORIZONTAL, 0, 0); |
512 |
createTextControl(comp, PDEUIMessages.compilers_s_doc_folder, KEY_S_DOC_FOLDER, CompilerFlags.SCHEMA_FLAGS); |
513 |
SWTFactory.createVerticalSpacer(parent, 1); |
514 |
initializeComboControls(parent, new String[] {PDEUIMessages.compilers_s_open_tags}, new Key[] {KEY_S_OPEN_TAGS}, CompilerFlags.SCHEMA_FLAGS); |
515 |
break; |
516 |
} |
517 |
case CompilerFlags.FEATURE_FLAGS : { |
518 |
initializeComboControls(parent, new String[] {PDEUIMessages.compilers_f_unresolved_features, PDEUIMessages.compilers_f_unresolved_plugins}, new Key[] {KEY_F_UNRESOLVED_FEATURES, KEY_F_UNRESOLVED_PLUGINS}, CompilerFlags.FEATURE_FLAGS); |
519 |
break; |
520 |
} |
521 |
} |
522 |
return page; |
523 |
} |
524 |
|
525 |
/** |
526 |
* Creates a set of combo boxes for the given string/ key pairs |
527 |
* @param composite |
528 |
* @param labels |
529 |
* @param keys |
530 |
* @param tabkind |
531 |
*/ |
532 |
private void initializeComboControls(Composite composite, String[] labels, Key[] keys, int tabkind) { |
533 |
for (int i = 0, max = labels.length; i < max; i++) { |
534 |
createComboControl(composite, labels[i], keys[i], tabkind); |
535 |
} |
536 |
} |
537 |
|
538 |
/** |
539 |
* Creates a checkbox button control in the parent |
540 |
* @param parent |
541 |
* @param label |
542 |
* @param key |
543 |
* @param tabkind |
544 |
*/ |
545 |
private void createCheckControl(Composite parent, String label, Key key, int tabkind) { |
546 |
Button button = SWTFactory.createCheckButton(parent, label, null, false, 2); |
547 |
ControlData data = new ControlData(key, new String[] {Boolean.toString(false)}); |
548 |
button.setData(data); |
549 |
button.setSelection(Boolean.valueOf(data.key.getStoredValue(fLookupOrder, false, fManager)).booleanValue()); |
550 |
button.addSelectionListener(selectionlistener); |
551 |
Integer mapkey = new Integer(tabkind); |
552 |
HashSet controls = (HashSet) fControlMap.get(mapkey); |
553 |
if (controls == null) { |
554 |
controls = new HashSet(8); |
555 |
fControlMap.put(mapkey, controls); |
556 |
} |
557 |
controls.add(button); |
558 |
} |
559 |
|
560 |
/** |
561 |
* Disposes the controls from this page |
562 |
*/ |
563 |
public void dispose() { |
564 |
fMainComp.getParent().dispose(); |
565 |
fExpComps.clear(); |
566 |
fControlMap.clear(); |
567 |
} |
568 |
|
569 |
/** |
570 |
* Creates a {@link Label} | {@link Combo} control. The combo is initialized from the given {@link Key} |
571 |
* @param parent |
572 |
* @param label |
573 |
* @param key |
574 |
* @param tabkind |
575 |
*/ |
576 |
protected void createComboControl(Composite parent, String label, Key key, int tabkind) { |
577 |
Label lbl = new Label(parent, SWT.NONE); |
578 |
GridData gd = new GridData(GridData.BEGINNING, GridData.CENTER, true, false); |
579 |
lbl.setLayoutData(gd); |
580 |
lbl.setText(label); |
581 |
Combo combo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY); |
582 |
gd = new GridData(GridData.END, GridData.CENTER, false, false); |
583 |
ControlData data = new ControlData(key, SEVERITIES); |
584 |
combo.setData(data); |
585 |
combo.setItems(SEVERITIES); |
586 |
combo.addSelectionListener(selectionlistener); |
587 |
int index = 0; |
588 |
try { |
589 |
index = Integer.parseInt(key.getStoredValue(fLookupOrder, false, fManager)); |
590 |
} catch (Exception e) { |
591 |
//set the default if something goes wrong |
592 |
index = Integer.parseInt(key.getStoredValue(fLookupOrder, true, fManager)); |
593 |
} |
594 |
combo.select(data.getSelection(SEVERITIES[index])); |
595 |
Integer mapkey = new Integer(tabkind); |
596 |
HashSet controls = (HashSet) fControlMap.get(mapkey); |
597 |
if (controls == null) { |
598 |
controls = new HashSet(8); |
599 |
fControlMap.put(mapkey, controls); |
600 |
} |
601 |
controls.add(combo); |
602 |
} |
603 |
|
604 |
/** |
605 |
* Creates a new text control on the parent for the given pref key |
606 |
* @param parent |
607 |
* @param label |
608 |
* @param key |
609 |
* @param tabkind |
610 |
*/ |
611 |
private void createTextControl(Composite parent, String label, Key key, int tabkind) { |
612 |
SWTFactory.createLabel(parent, label, 1); |
613 |
Text text = SWTFactory.createSingleText(parent, 1); |
614 |
ControlData data = new ControlData(key, new String[0]); |
615 |
text.setData(data); |
616 |
text.setText(data.key.getStoredValue(fLookupOrder, false, fManager)); |
617 |
text.addModifyListener(modifylistener); |
618 |
Integer mapkey = new Integer(tabkind); |
619 |
HashSet controls = (HashSet) fControlMap.get(mapkey); |
620 |
if (controls == null) { |
621 |
controls = new HashSet(8); |
622 |
fControlMap.put(mapkey, controls); |
623 |
} |
624 |
controls.add(text); |
625 |
} |
626 |
|
627 |
/** |
628 |
* Creates a scrolled composite |
629 |
* @param parent |
630 |
* @param columns |
631 |
* @return a new scrolled composite |
632 |
*/ |
633 |
protected ScrolledComposite createScrolledComposite(Composite parent, int columns) { |
634 |
ScrolledComposite scomp = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL); |
635 |
scomp.setExpandHorizontal(true); |
636 |
scomp.setExpandVertical(true); |
637 |
scomp.setLayout(new GridLayout(1, false)); |
638 |
scomp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
639 |
scomp.addListener(SWT.Resize, new Listener() { |
640 |
public void handleEvent(Event event) { |
641 |
handleExpand(getScrollingParent(event.widget)); |
642 |
} |
643 |
}); |
644 |
return scomp; |
645 |
} |
646 |
|
647 |
/** |
648 |
* Creates an {@link ExpandableComposite} with a client composite and a default grid layout |
649 |
* @param parent |
650 |
* @param title |
651 |
* @return a new expandable composite |
652 |
*/ |
653 |
private Composite createExpansibleComposite(Composite parent, String title) { |
654 |
ExpandableComposite ecomp = SWTFactory.createExpandibleComposite(parent, title, 1, GridData.FILL_HORIZONTAL); |
655 |
ecomp.addExpansionListener(new ExpansionAdapter() { |
656 |
public void expansionStateChanged(ExpansionEvent e) { |
657 |
Object obj = e.getSource(); |
658 |
handleExpand(getScrollingParent(obj)); |
659 |
} |
660 |
}); |
661 |
ecomp.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT)); |
662 |
fExpComps.add(ecomp); |
663 |
Composite client = SWTFactory.createComposite(ecomp, 2, 1, GridData.FILL_BOTH); |
664 |
ecomp.setClient(client); |
665 |
return client; |
666 |
} |
667 |
|
668 |
/** |
669 |
* Returns the scrolling parent for the given ExpandibleComposite object |
670 |
* @param obj |
671 |
* @return the scrolling parent of the given object or <code>null</code> if there isn't one |
672 |
*/ |
673 |
private ScrolledComposite getScrollingParent(Object obj) { |
674 |
if (obj instanceof ExpandableComposite) { |
675 |
ExpandableComposite ecomp = (ExpandableComposite) obj; |
676 |
Composite parent = ecomp.getParent(); |
677 |
while (parent != null && !(parent instanceof ScrolledComposite)) { |
678 |
parent = parent.getParent(); |
679 |
} |
680 |
if (parent != null) { |
681 |
return (ScrolledComposite) parent; |
682 |
} |
683 |
} |
684 |
if (obj instanceof ScrolledComposite) { |
685 |
return (ScrolledComposite) obj; |
686 |
} |
687 |
return null; |
688 |
} |
689 |
|
690 |
/** |
691 |
* Handles one of the expandable composites being expanded |
692 |
*/ |
693 |
private void handleExpand(ScrolledComposite composite) { |
694 |
if (composite == null) { |
695 |
return; |
696 |
} |
697 |
try { |
698 |
composite.setRedraw(false); |
699 |
Composite c = (Composite) composite.getContent(); |
700 |
if (c == null) { |
701 |
return; |
702 |
} |
703 |
Point newSize = c.computeSize(SWT.DEFAULT, SWT.DEFAULT); |
704 |
composite.setMinSize(newSize); |
705 |
c.layout(true); |
706 |
} finally { |
707 |
composite.setRedraw(true); |
708 |
} |
709 |
} |
710 |
|
711 |
/** |
712 |
* Saves all of the changes on the page |
713 |
*/ |
714 |
public void performOK() { |
715 |
save(); |
716 |
persistExpansionState(); |
717 |
} |
718 |
|
719 |
/** |
720 |
* Directly applies all of the changes on the page |
721 |
*/ |
722 |
public void performApply() { |
723 |
save(); |
724 |
} |
725 |
|
726 |
/** |
727 |
* Performs the save operation on the working cop manager |
728 |
*/ |
729 |
private void save() { |
730 |
if (fDirty) { |
731 |
try { |
732 |
ArrayList changes = new ArrayList(); |
733 |
collectChanges(fLookupOrder[0], changes); |
734 |
if (changes.size() > 0) { |
735 |
if (fRebuildcount < 1) { |
736 |
fRebuildcount++; |
737 |
fManager.applyChanges(); |
738 |
String message = PDEUIMessages.PDECompilersConfigurationBlock_settings_changed_all; |
739 |
if (fProject != null) { |
740 |
message = MessageFormat.format(PDEUIMessages.PDECompilersConfigurationBlock_setting_changed_project, new String[] {fProject.getName()}); |
741 |
} |
742 |
if (MessageDialog.openQuestion(fParent.getShell(), PDEUIMessages.PDECompilersConfigurationBlock_settings_changed, message)) { |
743 |
doFullBuild(); |
744 |
} |
745 |
} |
746 |
} |
747 |
fDirty = false; |
748 |
} catch (BackingStoreException bse) { |
749 |
PDEPlugin.log(bse); |
750 |
} |
751 |
} |
752 |
} |
753 |
|
754 |
/** |
755 |
* Collects the keys that have changed on the page into the specified list |
756 |
* @param changes the {@link List} to collect changed keys into |
757 |
*/ |
758 |
private void collectChanges(IScopeContext context, List changes) { |
759 |
Key key = null; |
760 |
String origval = null, newval = null; |
761 |
boolean complete = fOldProjectSettings == null && fProject != null; |
762 |
for (int i = 0; i < fgAllKeys.length; i++) { |
763 |
key = fgAllKeys[i]; |
764 |
origval = key.getStoredValue(context, null); |
765 |
newval = key.getStoredValue(context, fManager); |
766 |
if (newval == null) { |
767 |
if (origval != null) { |
768 |
changes.add(key); |
769 |
} else if (complete) { |
770 |
key.setStoredValue(context, key.getStoredValue(fLookupOrder, true, fManager), fManager); |
771 |
changes.add(key); |
772 |
} |
773 |
} else if (!newval.equals(origval)) { |
774 |
changes.add(key); |
775 |
} |
776 |
} |
777 |
} |
778 |
|
779 |
/** |
780 |
* Cancels all of the changes on the page |
781 |
*/ |
782 |
public void performCancel() { |
783 |
persistExpansionState(); |
784 |
} |
785 |
|
786 |
/** |
787 |
* Reverts all of the settings back to their defaults |
788 |
*/ |
789 |
public void performDefaults() { |
790 |
String defval = null; |
791 |
for (int i = 0; i < fgAllKeys.length; i++) { |
792 |
defval = fgAllKeys[i].getStoredValue(fLookupOrder, true, fManager); |
793 |
fgAllKeys[i].setStoredValue(fLookupOrder[0], defval, fManager); |
794 |
} |
795 |
updateControls(); |
796 |
fDirty = true; |
797 |
fRebuildcount = 0; |
798 |
} |
799 |
|
800 |
/** |
801 |
* Stores the expansion state of the composites |
802 |
*/ |
803 |
private void persistExpansionState() { |
804 |
IDialogSettings settings = PDEPlugin.getDefault().getDialogSettings().addNewSection(SETTINGS); |
805 |
for (int i = 0; i < fExpComps.size(); i++) { |
806 |
settings.put(Integer.toString(i), ((ExpandableComposite) fExpComps.get(i)).isExpanded()); |
807 |
} |
808 |
} |
809 |
|
810 |
/** |
811 |
* Restores the expansion state of the composites in this block. |
812 |
* If there are no settings, than the first composite is expanded by default |
813 |
*/ |
814 |
private void restoreExpansionState() { |
815 |
IDialogSettings settings = PDEPlugin.getDefault().getDialogSettings().getSection(SETTINGS); |
816 |
if (settings != null) { |
817 |
for (int i = 0; i < fExpComps.size(); i++) { |
818 |
((ExpandableComposite) fExpComps.get(i)).setExpanded(settings.getBoolean(Integer.toString(i))); |
819 |
} |
820 |
} else { |
821 |
((ExpandableComposite) fExpComps.get(0)).setExpanded(true); |
822 |
} |
823 |
} |
824 |
|
825 |
/** |
826 |
* Adds the associated builder for the tab this control lives on. Lookups are done using |
827 |
* hash codes for constant time containment checks |
828 |
* @param control |
829 |
*/ |
830 |
private void addBuilder(Control control) { |
831 |
HashSet controls = null; |
832 |
Integer key = null; |
833 |
for (Iterator iter = fControlMap.keySet().iterator(); iter.hasNext();) { |
834 |
key = (Integer) iter.next(); |
835 |
controls = (HashSet) fControlMap.get(key); |
836 |
if (controls == null) { |
837 |
continue; |
838 |
} |
839 |
if (controls.contains(control)) { |
840 |
switch (key.intValue()) { |
841 |
case CompilerFlags.PLUGIN_FLAGS : { |
842 |
fBuilders.add(PDE.MANIFEST_BUILDER_ID); |
843 |
break; |
844 |
} |
845 |
case CompilerFlags.SCHEMA_FLAGS : { |
846 |
fBuilders.add(PDE.SCHEMA_BUILDER_ID); |
847 |
break; |
848 |
} |
849 |
case CompilerFlags.FEATURE_FLAGS : |
850 |
case CompilerFlags.SITE_FLAGS : { |
851 |
fBuilders.add(PDE.FEATURE_BUILDER_ID); |
852 |
break; |
853 |
} |
854 |
} |
855 |
return; |
856 |
} |
857 |
} |
858 |
} |
859 |
|
860 |
/** |
861 |
* Performs a full build of the workspace |
862 |
*/ |
863 |
private void doFullBuild() { |
864 |
Job buildJob = new Job(PDEUIMessages.CompilersConfigurationBlock_building) { |
865 |
public boolean belongsTo(Object family) { |
866 |
return ResourcesPlugin.FAMILY_MANUAL_BUILD == family; |
867 |
} |
868 |
|
869 |
protected IStatus run(IProgressMonitor monitor) { |
870 |
try { |
871 |
IProject[] projects = null; |
872 |
if (fProject == null) { |
873 |
projects = PDEPlugin.getWorkspace().getRoot().getProjects(); |
874 |
} else { |
875 |
projects = new IProject[] {fProject}; |
876 |
} |
877 |
monitor.beginTask("", projects.length * 2); //$NON-NLS-1$ |
878 |
for (int i = 0; i < projects.length; i++) { |
879 |
IProject projectToBuild = projects[i]; |
880 |
if (!projectToBuild.isOpen()) |
881 |
continue; |
882 |
if (projectToBuild.hasNature(PDE.PLUGIN_NATURE)) { |
883 |
if (fBuilders.contains(PDE.MANIFEST_BUILDER_ID)) |
884 |
projectToBuild.build(IncrementalProjectBuilder.FULL_BUILD, PDE.MANIFEST_BUILDER_ID, null, new SubProgressMonitor(monitor, 1)); |
885 |
else |
886 |
monitor.worked(1); |
887 |
if (fBuilders.contains(PDE.SCHEMA_BUILDER_ID)) |
888 |
projectToBuild.build(IncrementalProjectBuilder.FULL_BUILD, PDE.SCHEMA_BUILDER_ID, null, new SubProgressMonitor(monitor, 1)); |
889 |
else |
890 |
monitor.worked(1); |
891 |
} else if (projectToBuild.hasNature(PDE.FEATURE_NATURE)) { |
892 |
if (fBuilders.contains(PDE.FEATURE_BUILDER_ID)) |
893 |
projectToBuild.build(IncrementalProjectBuilder.FULL_BUILD, PDE.FEATURE_BUILDER_ID, null, new SubProgressMonitor(monitor, 2)); |
894 |
} else { |
895 |
monitor.worked(2); |
896 |
} |
897 |
} |
898 |
} catch (CoreException e) { |
899 |
return e.getStatus(); |
900 |
} catch (OperationCanceledException e) { |
901 |
return Status.CANCEL_STATUS; |
902 |
} finally { |
903 |
monitor.done(); |
904 |
} |
905 |
return Status.OK_STATUS; |
906 |
} |
907 |
}; |
908 |
buildJob.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule()); |
909 |
buildJob.setUser(true); |
910 |
buildJob.schedule(); |
911 |
} |
912 |
} |