001: /*******************************************************************************
002: * Copyright (c) 2005, 2007 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.ui.internal.dialogs;
011:
012: import java.util.ArrayList;
013: import java.util.Iterator;
014: import java.util.List;
015:
016: import org.eclipse.core.runtime.CoreException;
017: import org.eclipse.core.runtime.IStatus;
018: import org.eclipse.core.runtime.MultiStatus;
019: import org.eclipse.core.runtime.Platform;
020: import org.eclipse.core.runtime.content.IContentType;
021: import org.eclipse.core.runtime.content.IContentTypeManager;
022: import org.eclipse.jface.preference.PreferencePage;
023: import org.eclipse.jface.viewers.ISelectionChangedListener;
024: import org.eclipse.jface.viewers.IStructuredContentProvider;
025: import org.eclipse.jface.viewers.IStructuredSelection;
026: import org.eclipse.jface.viewers.ITreeContentProvider;
027: import org.eclipse.jface.viewers.LabelProvider;
028: import org.eclipse.jface.viewers.ListViewer;
029: import org.eclipse.jface.viewers.SelectionChangedEvent;
030: import org.eclipse.jface.viewers.TreeViewer;
031: import org.eclipse.jface.viewers.Viewer;
032: import org.eclipse.jface.viewers.ViewerComparator;
033: import org.eclipse.jface.window.Window;
034: import org.eclipse.osgi.util.NLS;
035: import org.eclipse.osgi.util.TextProcessor;
036: import org.eclipse.swt.SWT;
037: import org.eclipse.swt.events.KeyAdapter;
038: import org.eclipse.swt.events.KeyEvent;
039: import org.eclipse.swt.events.SelectionAdapter;
040: import org.eclipse.swt.events.SelectionEvent;
041: import org.eclipse.swt.layout.GridData;
042: import org.eclipse.swt.layout.GridLayout;
043: import org.eclipse.swt.widgets.Button;
044: import org.eclipse.swt.widgets.Composite;
045: import org.eclipse.swt.widgets.Control;
046: import org.eclipse.swt.widgets.Label;
047: import org.eclipse.swt.widgets.Shell;
048: import org.eclipse.swt.widgets.Text;
049: import org.eclipse.ui.IWorkbench;
050: import org.eclipse.ui.IWorkbenchPreferencePage;
051: import org.eclipse.ui.PlatformUI;
052: import org.eclipse.ui.dialogs.PreferenceLinkArea;
053: import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
054: import org.eclipse.ui.internal.WorkbenchMessages;
055: import org.eclipse.ui.internal.WorkbenchPlugin;
056: import org.eclipse.ui.internal.misc.StatusUtil;
057: import org.eclipse.ui.internal.util.Util;
058: import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
059: import org.eclipse.ui.statushandlers.StatusManager;
060:
061: /**
062: * Preference page that allows manipulation of core content types. Unlike most
063: * preference pages, it does not work on the preference store itself but rather
064: * the content type manager. As such, there are no apply/default buttons and all
065: * changes made take effect immediately.
066: *
067: * @since 3.1
068: */
069: public class ContentTypesPreferencePage extends PreferencePage
070: implements IWorkbenchPreferencePage {
071:
072: private ListViewer fileAssociationViewer;
073:
074: private Button removeButton;
075:
076: private TreeViewer contentTypesViewer;
077:
078: private Button addButton;
079:
080: private Text charsetField;
081:
082: private Button setButton;
083:
084: private IWorkbench workbench;
085:
086: private class Spec {
087: String name;
088:
089: String ext;
090:
091: boolean isPredefined;
092:
093: int sortValue;
094:
095: /*
096: * (non-Javadoc)
097: *
098: * @see java.lang.Object#toString()
099: */
100: public String toString() {
101: String toString;
102: if (name != null) {
103: toString = name;
104: } else {
105: toString = "*." + ext; //$NON-NLS-1$
106: }
107:
108: if (isPredefined) {
109: toString = NLS.bind(
110: WorkbenchMessages.ContentTypes_lockedFormat,
111: toString);
112: }
113:
114: return toString;
115: }
116: }
117:
118: private class FileSpecComparator extends ViewerComparator {
119: public int category(Object element) {
120: // only Spec objects in here - unchecked cast
121: return ((Spec) element).sortValue;
122: }
123: }
124:
125: private class FileSpecLabelProvider extends LabelProvider {
126: /*
127: * (non-Javadoc)
128: *
129: * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
130: */
131: public String getText(Object element) {
132: String label = super .getText(element);
133: return TextProcessor.process(label, "*."); //$NON-NLS-1$
134: }
135: }
136:
137: private class FileSpecContentProvider implements
138: IStructuredContentProvider {
139:
140: /*
141: * (non-Javadoc)
142: *
143: * @see org.eclipse.jface.viewers.IContentProvider#dispose()
144: */
145: public void dispose() {
146: }
147:
148: /*
149: * (non-Javadoc)
150: *
151: * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
152: * java.lang.Object, java.lang.Object)
153: */
154: public void inputChanged(Viewer viewer, Object oldInput,
155: Object newInput) {
156: }
157:
158: /*
159: * (non-Javadoc)
160: *
161: * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
162: */
163: public Object[] getElements(Object inputElement) {
164: IContentType contentType = (IContentType) inputElement;
165: String[] userextfileSpecs = contentType
166: .getFileSpecs(IContentType.FILE_EXTENSION_SPEC
167: | IContentType.IGNORE_PRE_DEFINED);
168: String[] usernamefileSpecs = contentType
169: .getFileSpecs(IContentType.FILE_NAME_SPEC
170: | IContentType.IGNORE_PRE_DEFINED);
171: String[] preextfileSpecs = contentType
172: .getFileSpecs(IContentType.FILE_EXTENSION_SPEC
173: | IContentType.IGNORE_USER_DEFINED);
174: String[] prenamefileSpecs = contentType
175: .getFileSpecs(IContentType.FILE_NAME_SPEC
176: | IContentType.IGNORE_USER_DEFINED);
177:
178: return createSpecs(userextfileSpecs, usernamefileSpecs,
179: preextfileSpecs, prenamefileSpecs);
180: }
181:
182: private Object[] createSpecs(String[] userextfileSpecs,
183: String[] usernamefileSpecs, String[] preextfileSpecs,
184: String[] prenamefileSpecs) {
185: List returnValues = new ArrayList();
186: for (int i = 0; i < usernamefileSpecs.length; i++) {
187: Spec spec = new Spec();
188: spec.name = usernamefileSpecs[i];
189: spec.isPredefined = false;
190: spec.sortValue = 0;
191: returnValues.add(spec);
192: }
193:
194: for (int i = 0; i < prenamefileSpecs.length; i++) {
195: Spec spec = new Spec();
196: spec.name = prenamefileSpecs[i];
197: spec.isPredefined = true;
198: spec.sortValue = 1;
199: returnValues.add(spec);
200: }
201:
202: for (int i = 0; i < userextfileSpecs.length; i++) {
203: Spec spec = new Spec();
204: spec.ext = userextfileSpecs[i];
205: spec.isPredefined = false;
206: spec.sortValue = 2;
207: returnValues.add(spec);
208: }
209:
210: for (int i = 0; i < preextfileSpecs.length; i++) {
211: Spec spec = new Spec();
212: spec.ext = preextfileSpecs[i];
213: spec.isPredefined = true;
214: spec.sortValue = 3;
215: returnValues.add(spec);
216: }
217:
218: return returnValues.toArray();
219: }
220: }
221:
222: private class ContentTypesLabelProvider extends LabelProvider {
223: /*
224: * (non-Javadoc)
225: *
226: * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
227: */
228: public String getText(Object element) {
229: IContentType contentType = (IContentType) element;
230: return contentType.getName();
231: }
232: }
233:
234: private class ContentTypesContentProvider implements
235: ITreeContentProvider {
236:
237: private IContentTypeManager manager;
238:
239: /*
240: * (non-Javadoc)
241: *
242: * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
243: */
244: public Object[] getChildren(Object parentElement) {
245: List elements = new ArrayList();
246: IContentType baseType = (IContentType) parentElement;
247: IContentType[] contentTypes = manager.getAllContentTypes();
248: for (int i = 0; i < contentTypes.length; i++) {
249: IContentType type = contentTypes[i];
250: if (Util.equals(type.getBaseType(), baseType)) {
251: elements.add(type);
252: }
253: }
254: return elements.toArray();
255: }
256:
257: /*
258: * (non-Javadoc)
259: *
260: * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
261: */
262: public Object getParent(Object element) {
263: IContentType contentType = (IContentType) element;
264: return contentType.getBaseType();
265: }
266:
267: /*
268: * (non-Javadoc)
269: *
270: * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
271: */
272: public boolean hasChildren(Object element) {
273: return getChildren(element).length > 0;
274: }
275:
276: /*
277: * (non-Javadoc)
278: *
279: * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
280: */
281: public Object[] getElements(Object inputElement) {
282: return getChildren(null);
283: }
284:
285: /*
286: * (non-Javadoc)
287: *
288: * @see org.eclipse.jface.viewers.IContentProvider#dispose()
289: */
290: public void dispose() {
291:
292: }
293:
294: /*
295: * (non-Javadoc)
296: *
297: * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
298: * java.lang.Object, java.lang.Object)
299: */
300: public void inputChanged(Viewer viewer, Object oldInput,
301: Object newInput) {
302: manager = (IContentTypeManager) newInput;
303: }
304: }
305:
306: /*
307: * (non-Javadoc)
308: *
309: * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
310: */
311: protected Control createContents(Composite parent) {
312: Composite composite = new Composite(parent, SWT.NONE);
313: GridLayout layout = new GridLayout(2, false);
314: layout.marginHeight = layout.marginWidth = 0;
315: composite.setLayout(layout);
316:
317: PreferenceLinkArea contentTypeArea = new PreferenceLinkArea(
318: composite,
319: SWT.NONE,
320: "org.eclipse.ui.preferencePages.FileEditors", WorkbenchMessages.ContentTypes_FileEditorsRelatedLink,//$NON-NLS-1$
321: (IWorkbenchPreferenceContainer) getContainer(), null);
322:
323: GridData data = new GridData(GridData.FILL_HORIZONTAL
324: | GridData.GRAB_HORIZONTAL);
325: contentTypeArea.getControl().setLayoutData(data);
326:
327: createContentTypesTree(composite);
328: createFileAssociations(composite);
329: createCharset(composite);
330:
331: workbench.getHelpSystem().setHelp(parent,
332: IWorkbenchHelpContextIds.CONTENT_TYPES_PREFERENCE_PAGE);
333:
334: applyDialogFont(composite);
335: return composite;
336: }
337:
338: private void createCharset(final Composite parent) {
339: Composite composite = new Composite(parent, SWT.NONE);
340: GridLayout layout = new GridLayout(3, false);
341: layout.marginHeight = layout.marginWidth = 0;
342: GridData compositeData = new GridData(GridData.FILL_HORIZONTAL);
343: compositeData.horizontalSpan = 2;
344: composite.setLayoutData(compositeData);
345: composite.setLayout(layout);
346:
347: Label label = new Label(composite, SWT.NONE);
348: label.setFont(parent.getFont());
349: label.setText(WorkbenchMessages.ContentTypes_characterSetLabel);
350: charsetField = new Text(composite, SWT.SINGLE | SWT.BORDER);
351: charsetField.setFont(parent.getFont());
352: charsetField.setEnabled(false);
353: GridData data = new GridData(GridData.FILL_HORIZONTAL);
354: charsetField.setLayoutData(data);
355: setButton = new Button(composite, SWT.PUSH);
356: setButton.setFont(parent.getFont());
357: setButton
358: .setText(WorkbenchMessages.ContentTypes_characterSetUpdateLabel);
359: setButton.setEnabled(false);
360: setButtonLayoutData(setButton);
361: setButton.addSelectionListener(new SelectionAdapter() {
362:
363: /*
364: * (non-Javadoc)
365: *
366: * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
367: */
368: public void widgetSelected(SelectionEvent e) {
369: try {
370: String text = charsetField.getText().trim();
371: if (text.length() == 0) {
372: text = null;
373: }
374: getSelectedContentType().setDefaultCharset(text);
375: setButton.setEnabled(false);
376: } catch (CoreException e1) {
377: StatusUtil.handleStatus(e1.getStatus(),
378: StatusManager.SHOW, parent.getShell());
379: }
380: }
381: });
382:
383: charsetField.addKeyListener(new KeyAdapter() {
384: /*
385: * (non-Javadoc)
386: *
387: * @see org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent)
388: */
389: public void keyReleased(KeyEvent e) {
390: IContentType contentType = getSelectedContentType();
391: String charset = contentType.getDefaultCharset();
392: if (charset == null) {
393: charset = ""; //$NON-NLS-1$
394: }
395: setButton.setEnabled(!charset.equals(charsetField
396: .getText()));
397: }
398: });
399:
400: }
401:
402: /**
403: * @param composite
404: */
405: private void createFileAssociations(final Composite composite) {
406: {
407: Label label = new Label(composite, SWT.NONE);
408: label
409: .setText(WorkbenchMessages.ContentTypes_fileAssociationsLabel);
410: GridData data = new GridData();
411: data.horizontalSpan = 2;
412: label.setLayoutData(data);
413: }
414: {
415: fileAssociationViewer = new ListViewer(composite);
416: fileAssociationViewer
417: .setComparator(new FileSpecComparator());
418: fileAssociationViewer.getControl().setFont(
419: composite.getFont());
420: fileAssociationViewer
421: .setContentProvider(new FileSpecContentProvider());
422: fileAssociationViewer
423: .setLabelProvider(new FileSpecLabelProvider());
424: GridData data = new GridData(GridData.FILL_BOTH);
425: data.horizontalSpan = 1;
426: fileAssociationViewer.getControl().setLayoutData(data);
427: fileAssociationViewer
428: .addSelectionChangedListener(new ISelectionChangedListener() {
429:
430: public void selectionChanged(
431: SelectionChangedEvent event) {
432: IStructuredSelection selection = (IStructuredSelection) event
433: .getSelection();
434: if (selection.isEmpty()) {
435: removeButton.setEnabled(false);
436: return;
437: }
438: boolean enabled = true;
439: List elements = selection.toList();
440: for (Iterator i = elements.iterator(); i
441: .hasNext();) {
442: Spec spec = (Spec) i.next();
443: if (spec.isPredefined) {
444: enabled = false;
445: }
446: }
447: removeButton.setEnabled(enabled);
448: }
449: });
450: }
451: {
452: Composite buttonArea = new Composite(composite, SWT.NONE);
453: GridLayout layout = new GridLayout(1, false);
454: layout.marginHeight = layout.marginWidth = 0;
455: buttonArea.setLayout(layout);
456: GridData data = new GridData(
457: GridData.VERTICAL_ALIGN_BEGINNING);
458: buttonArea.setLayoutData(data);
459:
460: addButton = new Button(buttonArea, SWT.PUSH);
461: addButton.setFont(composite.getFont());
462: addButton
463: .setText(WorkbenchMessages.ContentTypes_fileAssociationsAddLabel);
464: addButton.setEnabled(false);
465: setButtonLayoutData(addButton);
466: addButton.addSelectionListener(new SelectionAdapter() {
467: /*
468: * (non-Javadoc)
469: *
470: * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
471: */
472: public void widgetSelected(SelectionEvent e) {
473: Shell shell = composite.getShell();
474: IContentType selectedContentType = getSelectedContentType();
475: FileExtensionDialog dialog = new FileExtensionDialog(
476: shell);
477: if (dialog.open() == Window.OK) {
478: String name = dialog.getName();
479: String extension = dialog.getExtension();
480: try {
481: if (name.equals("*")) { //$NON-NLS-1$
482: selectedContentType
483: .addFileSpec(
484: extension,
485: IContentType.FILE_EXTENSION_SPEC);
486: } else {
487: selectedContentType
488: .addFileSpec(
489: name
490: + (extension
491: .length() > 0 ? ('.' + extension)
492: : ""), //$NON-NLS-1$
493: IContentType.FILE_NAME_SPEC);
494: }
495: } catch (CoreException ex) {
496: StatusUtil.handleStatus(ex.getStatus(),
497: StatusManager.SHOW, shell);
498: WorkbenchPlugin.log(ex);
499: } finally {
500: fileAssociationViewer
501: .setInput(selectedContentType);
502: }
503: }
504: }
505: });
506:
507: removeButton = new Button(buttonArea, SWT.PUSH);
508: removeButton.setEnabled(false);
509: removeButton
510: .setText(WorkbenchMessages.ContentTypes_fileAssociationsRemoveLabel);
511: setButtonLayoutData(removeButton);
512: removeButton.addSelectionListener(new SelectionAdapter() {
513: /*
514: * (non-Javadoc)
515: *
516: * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
517: */
518: public void widgetSelected(SelectionEvent event) {
519: IContentType contentType = getSelectedContentType();
520: Spec[] specs = getSelectedSpecs();
521: MultiStatus result = new MultiStatus(
522: PlatformUI.PLUGIN_ID,
523: 0,
524: new IStatus[0],
525: WorkbenchMessages.ContentTypes_errorDialogMessage,
526: null);
527: for (int i = 0; i < specs.length; i++) {
528: Spec spec = specs[i];
529: try {
530: if (spec.name != null) {
531: contentType.removeFileSpec(spec.name,
532: IContentType.FILE_NAME_SPEC);
533: } else if (spec.ext != null) {
534: contentType
535: .removeFileSpec(
536: spec.ext,
537: IContentType.FILE_EXTENSION_SPEC);
538: }
539: } catch (CoreException e) {
540: result.add(e.getStatus());
541: }
542: }
543: if (!result.isOK()) {
544: StatusUtil.handleStatus(result,
545: StatusManager.SHOW, composite
546: .getShell());
547: }
548: fileAssociationViewer.setInput(contentType);
549: }
550: });
551: }
552: }
553:
554: protected Spec[] getSelectedSpecs() {
555: List list = ((IStructuredSelection) fileAssociationViewer
556: .getSelection()).toList();
557: return (Spec[]) list.toArray(new Spec[list.size()]);
558: }
559:
560: protected IContentType getSelectedContentType() {
561: return (IContentType) ((IStructuredSelection) contentTypesViewer
562: .getSelection()).getFirstElement();
563: }
564:
565: /**
566: * @param composite
567: */
568: private void createContentTypesTree(Composite composite) {
569: {
570: Label label = new Label(composite, SWT.NONE);
571: label.setFont(composite.getFont());
572: label
573: .setText(WorkbenchMessages.ContentTypes_contentTypesLabel);
574: GridData data = new GridData();
575: data.horizontalSpan = 2;
576: label.setLayoutData(data);
577: }
578: {
579: contentTypesViewer = new TreeViewer(composite, SWT.SINGLE
580: | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
581: contentTypesViewer.getControl()
582: .setFont(composite.getFont());
583: contentTypesViewer
584: .setContentProvider(new ContentTypesContentProvider());
585: contentTypesViewer
586: .setLabelProvider(new ContentTypesLabelProvider());
587: contentTypesViewer.setComparator(new ViewerComparator());
588: contentTypesViewer.setInput(Platform
589: .getContentTypeManager());
590: GridData data = new GridData(GridData.FILL_BOTH);
591: data.horizontalSpan = 2;
592: contentTypesViewer.getControl().setLayoutData(data);
593:
594: contentTypesViewer
595: .addSelectionChangedListener(new ISelectionChangedListener() {
596:
597: /*
598: * (non-Javadoc)
599: *
600: * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
601: */
602: public void selectionChanged(
603: SelectionChangedEvent event) {
604: IContentType contentType = (IContentType) ((IStructuredSelection) event
605: .getSelection()).getFirstElement();
606: fileAssociationViewer.setInput(contentType);
607:
608: if (contentType != null) {
609: String charset = contentType
610: .getDefaultCharset();
611: if (charset == null) {
612: charset = ""; //$NON-NLS-1$
613: }
614: charsetField.setText(charset);
615: } else {
616: charsetField.setText(""); //$NON-NLS-1$
617: }
618:
619: charsetField
620: .setEnabled(contentType != null);
621: addButton.setEnabled(contentType != null);
622: setButton.setEnabled(false);
623: }
624: });
625: }
626: }
627:
628: /*
629: * (non-Javadoc)
630: *
631: * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
632: */
633: public void init(IWorkbench workbench) {
634: this.workbench = workbench;
635: noDefaultAndApplyButton();
636: }
637: }
|