001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.preferences;
011:
012: import java.io.UnsupportedEncodingException;
013: import java.net.URLDecoder;
014: import java.net.URLEncoder;
015: import java.util.ArrayList;
016: import java.util.NoSuchElementException;
017: import java.util.StringTokenizer;
018:
019: import org.eclipse.core.resources.IProject;
020: import org.eclipse.core.resources.IResource;
021: import org.eclipse.core.resources.IWorkspace;
022: import org.eclipse.core.runtime.IPath;
023: import org.eclipse.core.runtime.IStatus;
024: import org.eclipse.core.runtime.Path;
025: import org.eclipse.core.runtime.Status;
026:
027: import org.eclipse.swt.SWT;
028: import org.eclipse.swt.events.ModifyEvent;
029: import org.eclipse.swt.events.ModifyListener;
030: import org.eclipse.swt.events.SelectionEvent;
031: import org.eclipse.swt.events.SelectionListener;
032: import org.eclipse.swt.layout.GridData;
033: import org.eclipse.swt.layout.GridLayout;
034: import org.eclipse.swt.widgets.Button;
035: import org.eclipse.swt.widgets.Combo;
036: import org.eclipse.swt.widgets.Composite;
037: import org.eclipse.swt.widgets.Control;
038: import org.eclipse.swt.widgets.Group;
039: import org.eclipse.swt.widgets.Label;
040: import org.eclipse.swt.widgets.Text;
041: import org.eclipse.swt.widgets.Widget;
042:
043: import org.eclipse.jface.dialogs.Dialog;
044: import org.eclipse.jface.dialogs.IDialogConstants;
045: import org.eclipse.jface.preference.IPreferenceStore;
046: import org.eclipse.jface.preference.PreferencePage;
047:
048: import org.eclipse.ui.IWorkbench;
049: import org.eclipse.ui.IWorkbenchPreferencePage;
050: import org.eclipse.ui.PlatformUI;
051:
052: import org.eclipse.jdt.core.IClasspathEntry;
053: import org.eclipse.jdt.core.JavaConventions;
054: import org.eclipse.jdt.core.JavaCore;
055:
056: import org.eclipse.jdt.internal.corext.util.Messages;
057:
058: import org.eclipse.jdt.ui.JavaUI;
059: import org.eclipse.jdt.ui.PreferenceConstants;
060:
061: import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
062: import org.eclipse.jdt.internal.ui.JavaPlugin;
063: import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
064: import org.eclipse.jdt.internal.ui.dialogs.StatusUtil;
065:
066: /*
067: * The page for defaults for classpath entries in new java projects.
068: * See PreferenceConstants to access or change these values through public API.
069: */
070: public class NewJavaProjectPreferencePage extends PreferencePage
071: implements IWorkbenchPreferencePage {
072:
073: public static final String ID = "org.eclipse.jdt.ui.preferences.BuildPathPreferencePage"; //$NON-NLS-1$
074:
075: private static final String SRCBIN_FOLDERS_IN_NEWPROJ = PreferenceConstants.SRCBIN_FOLDERS_IN_NEWPROJ;
076: private static final String SRCBIN_SRCNAME = PreferenceConstants.SRCBIN_SRCNAME;
077: private static final String SRCBIN_BINNAME = PreferenceConstants.SRCBIN_BINNAME;
078:
079: private static final String CLASSPATH_JRELIBRARY_INDEX = PreferenceConstants.NEWPROJECT_JRELIBRARY_INDEX;
080: private static final String CLASSPATH_JRELIBRARY_LIST = PreferenceConstants.NEWPROJECT_JRELIBRARY_LIST;
081:
082: private static String fgDefaultEncoding = System
083: .getProperty("file.encoding"); //$NON-NLS-1$
084:
085: public static IClasspathEntry[] getDefaultJRELibrary() {
086: IPreferenceStore store = JavaPlugin.getDefault()
087: .getPreferenceStore();
088:
089: String str = store.getString(CLASSPATH_JRELIBRARY_LIST);
090: int index = store.getInt(CLASSPATH_JRELIBRARY_INDEX);
091:
092: StringTokenizer tok = new StringTokenizer(str, ";"); //$NON-NLS-1$
093: while (tok.hasMoreTokens() && index > 0) {
094: tok.nextToken();
095: index--;
096: }
097:
098: if (tok.hasMoreTokens()) {
099: IClasspathEntry[] res = decodeJRELibraryClasspathEntries(tok
100: .nextToken());
101: if (res.length > 0) {
102: return res;
103: }
104: }
105: return new IClasspathEntry[] { getJREContainerEntry() };
106: }
107:
108: // JRE Entry
109:
110: public static String decodeJRELibraryDescription(String encoded) {
111: int end = encoded.indexOf(' ');
112: if (end != -1) {
113: return decode(encoded.substring(0, end));
114: }
115: return ""; //$NON-NLS-1$
116: }
117:
118: private static String decode(String str) {
119: try {
120: return URLDecoder.decode(str, fgDefaultEncoding);
121: } catch (UnsupportedEncodingException e) {
122: JavaPlugin.log(e);
123: }
124: return ""; //$NON-NLS-1$
125: }
126:
127: private static String encode(String str) {
128: try {
129: return URLEncoder.encode(str, fgDefaultEncoding);
130: } catch (UnsupportedEncodingException e) {
131: JavaPlugin.log(e);
132: }
133: return ""; //$NON-NLS-1$
134: }
135:
136: public static IClasspathEntry[] decodeJRELibraryClasspathEntries(
137: String encoded) {
138: StringTokenizer tok = new StringTokenizer(encoded, " "); //$NON-NLS-1$
139: ArrayList res = new ArrayList();
140: while (tok.hasMoreTokens()) {
141: try {
142: tok.nextToken(); // desc: ignore
143: int kind = Integer.parseInt(tok.nextToken());
144: IPath path = decodePath(tok.nextToken());
145: IPath attachPath = decodePath(tok.nextToken());
146: IPath attachRoot = decodePath(tok.nextToken());
147: boolean isExported = Boolean.valueOf(tok.nextToken())
148: .booleanValue();
149: switch (kind) {
150: case IClasspathEntry.CPE_SOURCE:
151: res.add(JavaCore.newSourceEntry(path));
152: break;
153: case IClasspathEntry.CPE_LIBRARY:
154: res.add(JavaCore.newLibraryEntry(path, attachPath,
155: attachRoot, isExported));
156: break;
157: case IClasspathEntry.CPE_VARIABLE:
158: res.add(JavaCore.newVariableEntry(path, attachPath,
159: attachRoot, isExported));
160: break;
161: case IClasspathEntry.CPE_PROJECT:
162: res.add(JavaCore.newProjectEntry(path, isExported));
163: break;
164: case IClasspathEntry.CPE_CONTAINER:
165: res.add(JavaCore
166: .newContainerEntry(path, isExported));
167: break;
168: }
169: } catch (NumberFormatException e) {
170: String message = PreferencesMessages.NewJavaProjectPreferencePage_error_decode;
171: JavaPlugin.log(new Status(IStatus.ERROR,
172: JavaUI.ID_PLUGIN, IStatus.ERROR, message, e));
173: } catch (NoSuchElementException e) {
174: String message = PreferencesMessages.NewJavaProjectPreferencePage_error_decode;
175: JavaPlugin.log(new Status(IStatus.ERROR,
176: JavaUI.ID_PLUGIN, IStatus.ERROR, message, e));
177: }
178: }
179: return (IClasspathEntry[]) res.toArray(new IClasspathEntry[res
180: .size()]);
181: }
182:
183: public static String encodeJRELibrary(String desc,
184: IClasspathEntry[] cpentries) {
185: StringBuffer buf = new StringBuffer();
186: for (int i = 0; i < cpentries.length; i++) {
187: IClasspathEntry entry = cpentries[i];
188: buf.append(encode(desc));
189: buf.append(' ');
190: buf.append(entry.getEntryKind());
191: buf.append(' ');
192: buf.append(encodePath(entry.getPath()));
193: buf.append(' ');
194: buf.append(encodePath(entry.getSourceAttachmentPath()));
195: buf.append(' ');
196: buf.append(encodePath(entry.getSourceAttachmentRootPath()));
197: buf.append(' ');
198: buf.append(entry.isExported());
199: buf.append(' ');
200: }
201: return buf.toString();
202: }
203:
204: private static String encodePath(IPath path) {
205: if (path == null) {
206: return "#"; //$NON-NLS-1$
207: } else if (path.isEmpty()) {
208: return "&"; //$NON-NLS-1$
209: } else {
210: return encode(path.toPortableString());
211: }
212: }
213:
214: private static IPath decodePath(String str) {
215: if ("#".equals(str)) { //$NON-NLS-1$
216: return null;
217: } else if ("&".equals(str)) { //$NON-NLS-1$
218: return Path.EMPTY;
219: } else {
220: return Path.fromPortableString(decode(str));
221: }
222: }
223:
224: private ArrayList fCheckBoxes;
225: private ArrayList fRadioButtons;
226: private ArrayList fTextControls;
227:
228: private SelectionListener fSelectionListener;
229: private ModifyListener fModifyListener;
230:
231: private Text fBinFolderNameText;
232: private Text fSrcFolderNameText;
233:
234: private Combo fJRECombo;
235:
236: private Button fProjectAsSourceFolder;
237: private Button fFoldersAsSourceFolder;
238:
239: private Label fSrcFolderNameLabel;
240: private Label fBinFolderNameLabel;
241:
242: public NewJavaProjectPreferencePage() {
243: super ();
244: setPreferenceStore(JavaPlugin.getDefault().getPreferenceStore());
245: setDescription(PreferencesMessages.NewJavaProjectPreferencePage_description);
246:
247: // title used when opened programatically
248: setTitle(PreferencesMessages.NewJavaProjectPreferencePage_title);
249:
250: fRadioButtons = new ArrayList();
251: fCheckBoxes = new ArrayList();
252: fTextControls = new ArrayList();
253:
254: fSelectionListener = new SelectionListener() {
255: public void widgetDefaultSelected(SelectionEvent e) {
256: }
257:
258: public void widgetSelected(SelectionEvent e) {
259: controlChanged(e.widget);
260: }
261: };
262:
263: fModifyListener = new ModifyListener() {
264: public void modifyText(ModifyEvent e) {
265: controlModified(e.widget);
266: }
267: };
268:
269: }
270:
271: public static void initDefaults(IPreferenceStore store) {
272: store.setDefault(SRCBIN_FOLDERS_IN_NEWPROJ, true);
273: store.setDefault(SRCBIN_SRCNAME, "src"); //$NON-NLS-1$
274: store.setDefault(SRCBIN_BINNAME, "bin"); //$NON-NLS-1$
275:
276: store.setDefault(CLASSPATH_JRELIBRARY_LIST,
277: getDefaultJRELibraries());
278: store.setDefault(CLASSPATH_JRELIBRARY_INDEX, 0);
279: }
280:
281: private static String getDefaultJRELibraries() {
282: StringBuffer buf = new StringBuffer();
283: IClasspathEntry cntentry = getJREContainerEntry();
284: buf
285: .append(encodeJRELibrary(
286: PreferencesMessages.NewJavaProjectPreferencePage_jre_container_description,
287: new IClasspathEntry[] { cntentry }));
288: buf.append(';');
289: IClasspathEntry varentry = getJREVariableEntry();
290: buf
291: .append(encodeJRELibrary(
292: PreferencesMessages.NewJavaProjectPreferencePage_jre_variable_description,
293: new IClasspathEntry[] { varentry }));
294: buf.append(';');
295: return buf.toString();
296: }
297:
298: private static IClasspathEntry getJREContainerEntry() {
299: return JavaCore.newContainerEntry(new Path(
300: "org.eclipse.jdt.launching.JRE_CONTAINER")); //$NON-NLS-1$
301: }
302:
303: private static IClasspathEntry getJREVariableEntry() {
304: return JavaCore
305: .newVariableEntry(
306: new Path("JRE_LIB"), new Path("JRE_SRC"), new Path("JRE_SRCROOT")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
307: }
308:
309: /*
310: * @see IWorkbenchPreferencePage#init(IWorkbench)
311: */
312: public void init(IWorkbench workbench) {
313: }
314:
315: /**
316: * @see PreferencePage#createControl(Composite)
317: */
318: public void createControl(Composite parent) {
319: super .createControl(parent);
320: PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
321: IJavaHelpContextIds.NEW_JAVA_PROJECT_PREFERENCE_PAGE);
322: }
323:
324: private Button addRadioButton(Composite parent, String label,
325: String key, String value, int indent) {
326: GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
327: gd.horizontalSpan = 2;
328: gd.horizontalIndent = indent;
329:
330: Button button = new Button(parent, SWT.RADIO);
331: button.setText(label);
332: button.setData(new String[] { key, value });
333: button.setLayoutData(gd);
334:
335: button.setSelection(value.equals(getPreferenceStore()
336: .getString(key)));
337:
338: fRadioButtons.add(button);
339: return button;
340: }
341:
342: private Text addTextControl(Composite parent, Label labelControl,
343: String key, int indent) {
344: GridData gd = new GridData();
345: gd.horizontalIndent = indent;
346:
347: labelControl.setLayoutData(gd);
348:
349: gd = new GridData(GridData.FILL_HORIZONTAL);
350: gd.widthHint = convertWidthInCharsToPixels(30);
351:
352: Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
353: text.setText(getPreferenceStore().getString(key));
354: text.setData(key);
355: text.setLayoutData(gd);
356:
357: fTextControls.add(text);
358: return text;
359: }
360:
361: protected Control createContents(Composite parent) {
362: initializeDialogUnits(parent);
363:
364: Composite result = new Composite(parent, SWT.NONE);
365: GridLayout layout = new GridLayout();
366: layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
367: layout.marginWidth = 0;
368: layout.verticalSpacing = convertVerticalDLUsToPixels(10);
369: layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
370: layout.numColumns = 2;
371: result.setLayout(layout);
372:
373: GridData gd = new GridData(GridData.FILL_HORIZONTAL);
374: gd.horizontalSpan = 2;
375:
376: Group sourceFolderGroup = new Group(result, SWT.NONE);
377: layout = new GridLayout();
378: layout.numColumns = 2;
379: sourceFolderGroup.setLayout(layout);
380: sourceFolderGroup.setLayoutData(gd);
381: sourceFolderGroup
382: .setText(PreferencesMessages.NewJavaProjectPreferencePage_sourcefolder_label);
383:
384: int indent = 0;
385:
386: fProjectAsSourceFolder = addRadioButton(
387: sourceFolderGroup,
388: PreferencesMessages.NewJavaProjectPreferencePage_sourcefolder_project,
389: SRCBIN_FOLDERS_IN_NEWPROJ, IPreferenceStore.FALSE,
390: indent);
391: fProjectAsSourceFolder.addSelectionListener(fSelectionListener);
392:
393: fFoldersAsSourceFolder = addRadioButton(
394: sourceFolderGroup,
395: PreferencesMessages.NewJavaProjectPreferencePage_sourcefolder_folder,
396: SRCBIN_FOLDERS_IN_NEWPROJ, IPreferenceStore.TRUE,
397: indent);
398: fFoldersAsSourceFolder.addSelectionListener(fSelectionListener);
399:
400: indent = convertWidthInCharsToPixels(4);
401:
402: fSrcFolderNameLabel = new Label(sourceFolderGroup, SWT.NONE);
403: fSrcFolderNameLabel
404: .setText(PreferencesMessages.NewJavaProjectPreferencePage_folders_src);
405: fSrcFolderNameText = addTextControl(sourceFolderGroup,
406: fSrcFolderNameLabel, SRCBIN_SRCNAME, indent);
407: fSrcFolderNameText.addModifyListener(fModifyListener);
408:
409: fBinFolderNameLabel = new Label(sourceFolderGroup, SWT.NONE);
410: fBinFolderNameLabel
411: .setText(PreferencesMessages.NewJavaProjectPreferencePage_folders_bin);
412: fBinFolderNameText = addTextControl(sourceFolderGroup,
413: fBinFolderNameLabel, SRCBIN_BINNAME, indent);
414: fBinFolderNameText.addModifyListener(fModifyListener);
415:
416: String[] jreNames = getJRENames();
417: if (jreNames.length > 0) {
418: Label jreSelectionLabel = new Label(result, SWT.NONE);
419: jreSelectionLabel
420: .setText(PreferencesMessages.NewJavaProjectPreferencePage_jrelibrary_label);
421: jreSelectionLabel.setLayoutData(new GridData());
422:
423: int index = getPreferenceStore().getInt(
424: CLASSPATH_JRELIBRARY_INDEX);
425: fJRECombo = new Combo(result, SWT.READ_ONLY);
426: fJRECombo.setItems(jreNames);
427: fJRECombo.select(index);
428: fJRECombo.setLayoutData(new GridData(
429: GridData.HORIZONTAL_ALIGN_FILL));
430: }
431:
432: validateFolders();
433:
434: Dialog.applyDialogFont(result);
435: return result;
436: }
437:
438: private void validateFolders() {
439: boolean useFolders = fFoldersAsSourceFolder.getSelection();
440:
441: fSrcFolderNameText.setEnabled(useFolders);
442: fBinFolderNameText.setEnabled(useFolders);
443: fSrcFolderNameLabel.setEnabled(useFolders);
444: fBinFolderNameLabel.setEnabled(useFolders);
445: if (useFolders) {
446: String srcName = fSrcFolderNameText.getText();
447: String binName = fBinFolderNameText.getText();
448: if (srcName.length() + binName.length() == 0) {
449: updateStatus(new StatusInfo(
450: IStatus.ERROR,
451: PreferencesMessages.NewJavaProjectPreferencePage_folders_error_namesempty));
452: return;
453: }
454: IWorkspace workspace = JavaPlugin.getWorkspace();
455: IProject dmy = workspace.getRoot().getProject("project"); //$NON-NLS-1$
456:
457: IStatus status;
458: IPath srcPath = dmy.getFullPath().append(srcName);
459: if (srcName.length() != 0) {
460: status = workspace.validatePath(srcPath.toString(),
461: IResource.FOLDER);
462: if (!status.isOK()) {
463: String message = Messages
464: .format(
465: PreferencesMessages.NewJavaProjectPreferencePage_folders_error_invalidsrcname,
466: status.getMessage());
467: updateStatus(new StatusInfo(IStatus.ERROR, message));
468: return;
469: }
470: }
471: IPath binPath = dmy.getFullPath().append(binName);
472: if (binName.length() != 0) {
473: status = workspace.validatePath(binPath.toString(),
474: IResource.FOLDER);
475: if (!status.isOK()) {
476: String message = Messages
477: .format(
478: PreferencesMessages.NewJavaProjectPreferencePage_folders_error_invalidbinname,
479: status.getMessage());
480: updateStatus(new StatusInfo(IStatus.ERROR, message));
481: return;
482: }
483: }
484: IClasspathEntry entry = JavaCore.newSourceEntry(srcPath);
485: status = JavaConventions.validateClasspath(JavaCore
486: .create(dmy), new IClasspathEntry[] { entry },
487: binPath);
488: if (!status.isOK()) {
489: String message = PreferencesMessages.NewJavaProjectPreferencePage_folders_error_invalidcp;
490: updateStatus(new StatusInfo(IStatus.ERROR, message));
491: return;
492: }
493: }
494: updateStatus(new StatusInfo()); // set to OK
495: }
496:
497: private void updateStatus(IStatus status) {
498: setValid(!status.matches(IStatus.ERROR));
499: StatusUtil.applyToStatusLine(this , status);
500: }
501:
502: private void controlChanged(Widget widget) {
503: if (widget == fFoldersAsSourceFolder
504: || widget == fProjectAsSourceFolder) {
505: validateFolders();
506: }
507: }
508:
509: private void controlModified(Widget widget) {
510: if (widget == fSrcFolderNameText
511: || widget == fBinFolderNameText) {
512: validateFolders();
513: }
514: }
515:
516: /*
517: * @see PreferencePage#performDefaults()
518: */
519: protected void performDefaults() {
520: IPreferenceStore store = getPreferenceStore();
521: for (int i = 0; i < fCheckBoxes.size(); i++) {
522: Button button = (Button) fCheckBoxes.get(i);
523: String key = (String) button.getData();
524: button.setSelection(store.getDefaultBoolean(key));
525: }
526: for (int i = 0; i < fRadioButtons.size(); i++) {
527: Button button = (Button) fRadioButtons.get(i);
528: String[] info = (String[]) button.getData();
529: button.setSelection(info[1].equals(store
530: .getDefaultString(info[0])));
531: }
532: for (int i = 0; i < fTextControls.size(); i++) {
533: Text text = (Text) fTextControls.get(i);
534: String key = (String) text.getData();
535: text.setText(store.getDefaultString(key));
536: }
537: if (fJRECombo != null) {
538: fJRECombo.select(store
539: .getDefaultInt(CLASSPATH_JRELIBRARY_INDEX));
540: }
541:
542: validateFolders();
543: super .performDefaults();
544: }
545:
546: /*
547: * @see IPreferencePage#performOk()
548: */
549: public boolean performOk() {
550: IPreferenceStore store = getPreferenceStore();
551: for (int i = 0; i < fCheckBoxes.size(); i++) {
552: Button button = (Button) fCheckBoxes.get(i);
553: String key = (String) button.getData();
554: store.setValue(key, button.getSelection());
555: }
556: for (int i = 0; i < fRadioButtons.size(); i++) {
557: Button button = (Button) fRadioButtons.get(i);
558: if (button.getSelection()) {
559: String[] info = (String[]) button.getData();
560: store.setValue(info[0], info[1]);
561: }
562: }
563: for (int i = 0; i < fTextControls.size(); i++) {
564: Text text = (Text) fTextControls.get(i);
565: String key = (String) text.getData();
566: store.setValue(key, text.getText());
567: }
568:
569: if (fJRECombo != null) {
570: store.setValue(CLASSPATH_JRELIBRARY_INDEX, fJRECombo
571: .getSelectionIndex());
572: }
573:
574: JavaPlugin.getDefault().savePluginPreferences();
575: return super .performOk();
576: }
577:
578: private String[] getJRENames() {
579: String prefString = getPreferenceStore().getString(
580: CLASSPATH_JRELIBRARY_LIST);
581: ArrayList list = new ArrayList();
582: StringTokenizer tok = new StringTokenizer(prefString, ";"); //$NON-NLS-1$
583: while (tok.hasMoreTokens()) {
584: list.add(decodeJRELibraryDescription(tok.nextToken()));
585: }
586: return (String[]) list.toArray(new String[list.size()]);
587: }
588:
589: }
|