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.ui.editors.text;
011:
012: import java.io.CharConversionException;
013: import java.io.UnsupportedEncodingException;
014:
015: import org.eclipse.swt.SWT;
016: import org.eclipse.swt.custom.BusyIndicator;
017: import org.eclipse.swt.events.SelectionAdapter;
018: import org.eclipse.swt.events.SelectionEvent;
019: import org.eclipse.swt.graphics.Color;
020: import org.eclipse.swt.layout.GridData;
021: import org.eclipse.swt.widgets.Button;
022: import org.eclipse.swt.widgets.Composite;
023: import org.eclipse.swt.widgets.Display;
024: import org.eclipse.swt.widgets.Label;
025: import org.eclipse.swt.widgets.Shell;
026:
027: import org.eclipse.core.runtime.IStatus;
028: import org.eclipse.core.runtime.Preferences;
029:
030: import org.eclipse.core.resources.ResourcesPlugin;
031:
032: import org.eclipse.jface.action.IAction;
033:
034: import org.eclipse.ui.IEditorInput;
035: import org.eclipse.ui.IWorkbenchWindow;
036: import org.eclipse.ui.PlatformUI;
037: import org.eclipse.ui.internal.editors.text.NLSUtility;
038: import org.eclipse.ui.texteditor.IDocumentProvider;
039: import org.eclipse.ui.texteditor.ITextEditorActionConstants;
040: import org.eclipse.ui.texteditor.StatusTextEditor;
041: import org.eclipse.ui.texteditor.TextEditorAction;
042:
043: /**
044: * The standard implementation of <code>IEncodingSupport</code>.
045: * @since 2.0
046: */
047: public class DefaultEncodingSupport implements IEncodingSupport {
048:
049: /** Internal property change listener. */
050: private Preferences.IPropertyChangeListener fPropertyChangeListener;
051: /** The editor this support is associated with. */
052: private StatusTextEditor fTextEditor;
053:
054: /**
055: * Creates a new encoding support.
056: */
057: public DefaultEncodingSupport() {
058: super ();
059: }
060:
061: /**
062: * Associates this encoding support to the given text editor and initializes this encoding.
063: *
064: * @param textEditor the editor
065: */
066: public void initialize(StatusTextEditor textEditor) {
067:
068: fTextEditor = textEditor;
069:
070: fPropertyChangeListener = new Preferences.IPropertyChangeListener() {
071: public void propertyChange(Preferences.PropertyChangeEvent e) {
072: if (ResourcesPlugin.PREF_ENCODING.equals(e
073: .getProperty())) {
074: Runnable runnable = new Runnable() {
075: public void run() {
076: setEncoding(null, false); // null means: use default
077: }
078: };
079: if (Display.getCurrent() != null)
080: runnable.run();
081: else {
082: // Post runnable into UI thread
083: Shell shell;
084: if (fTextEditor != null)
085: shell = fTextEditor.getSite().getShell();
086: else
087: shell = getActiveWorkbenchShell();
088: Display display;
089: if (shell != null)
090: display = shell.getDisplay();
091: else
092: display = Display.getDefault();
093: display.asyncExec(runnable);
094: }
095: }
096: }
097: };
098:
099: Preferences p = ResourcesPlugin.getPlugin()
100: .getPluginPreferences();
101: p.addPropertyChangeListener(fPropertyChangeListener);
102: }
103:
104: /**
105: * Disposes this encoding support.
106: */
107: public void dispose() {
108: Preferences p = ResourcesPlugin.getPlugin()
109: .getPluginPreferences();
110: p.removePropertyChangeListener(fPropertyChangeListener);
111:
112: fTextEditor = null;
113: }
114:
115: /**
116: * Resets this encoding support. Should be called if, e.g., the input element of the
117: * associated editor changed.
118: */
119: public void reset() {
120: }
121:
122: /**
123: * Sets the encoding of the editor's input to the given value. If <code>overwrite</code> is
124: * <code>true</code> the value is set even if the encoding is already set.
125: *
126: * @param encoding the new encoding
127: * @param overwrite <code>true</code> if current encoding should be overwritten
128: */
129: protected void setEncoding(String encoding, boolean overwrite) {
130: IDocumentProvider p = fTextEditor.getDocumentProvider();
131: if (p instanceof IStorageDocumentProvider) {
132: final IEditorInput input = fTextEditor.getEditorInput();
133: IStorageDocumentProvider provider = (IStorageDocumentProvider) p;
134: String current = provider.getEncoding(input);
135: if (!fTextEditor.isDirty()) {
136: String internal = encoding == null ? "" : encoding; //$NON-NLS-1$
137: boolean apply = (overwrite || current == null)
138: && !internal.equals(current);
139: if (apply) {
140: provider.setEncoding(input, encoding);
141: Runnable encodingSetter = new Runnable() {
142: public void run() {
143: fTextEditor.doRevertToSaved();
144: }
145: };
146: Display display = fTextEditor.getSite().getShell()
147: .getDisplay();
148: if (display != null && !display.isDisposed())
149: BusyIndicator
150: .showWhile(display, encodingSetter);
151: else
152: encodingSetter.run();
153: }
154: }
155: }
156: }
157:
158: /*
159: * @see IEncodingSupport#setEncoding(String)
160: */
161: public void setEncoding(String encoding) {
162: setEncoding(encoding, true);
163: }
164:
165: /*
166: * @see IEncodingSupport#getEncoding()
167: */
168: public String getEncoding() {
169: IDocumentProvider p = fTextEditor.getDocumentProvider();
170: if (p instanceof IStorageDocumentProvider) {
171: IStorageDocumentProvider provider = (IStorageDocumentProvider) p;
172: return provider.getEncoding(fTextEditor.getEditorInput());
173: }
174: return null;
175: }
176:
177: /*
178: * @see IEncodingSupport#getDefaultEncoding()
179: */
180: public String getDefaultEncoding() {
181: IDocumentProvider p = fTextEditor.getDocumentProvider();
182: if (p instanceof IStorageDocumentProvider) {
183: IStorageDocumentProvider provider = (IStorageDocumentProvider) p;
184: return provider.getDefaultEncoding();
185: }
186: return null;
187: }
188:
189: /**
190: * Returns a status header for the given status.
191: *
192: * @param status the status
193: * @return a status header for the given status.
194: */
195: public String getStatusHeader(IStatus status) {
196: Throwable t = status.getException();
197:
198: if (t instanceof CharConversionException)
199: return TextEditorMessages.Editor_error_unreadable_encoding_header;
200:
201: if (t instanceof UnsupportedEncodingException)
202: return TextEditorMessages.Editor_error_unsupported_encoding_header;
203:
204: return null;
205: }
206:
207: /**
208: * Returns a banner for the given status.
209: *
210: * @param status the status
211: * @return a banner for the given status.
212: */
213: public String getStatusBanner(IStatus status) {
214: Throwable t = status.getException();
215:
216: if (t instanceof CharConversionException)
217: return TextEditorMessages.Editor_error_unreadable_encoding_banner;
218:
219: if (t instanceof UnsupportedEncodingException)
220: return TextEditorMessages.Editor_error_unsupported_encoding_banner;
221:
222: return null;
223:
224: }
225:
226: /**
227: * Returns a status message if any.
228: *
229: * @param status the status
230: * @return a status message indicating encoding problems or <code>null</code> otherwise
231: */
232: public String getStatusMessage(IStatus status) {
233: Throwable t = status.getException();
234: if (t instanceof CharConversionException
235: || t instanceof UnsupportedEncodingException) {
236:
237: String encoding = getEncoding();
238: if (encoding == null)
239: encoding = getDefaultEncoding();
240:
241: if (t instanceof CharConversionException) {
242: if (encoding != null)
243: return NLSUtility
244: .format(
245: TextEditorMessages.Editor_error_unreadable_encoding_message_arg,
246: encoding);
247: return TextEditorMessages.Editor_error_unreadable_encoding_message;
248: }
249:
250: if (t instanceof UnsupportedEncodingException) {
251: if (encoding != null)
252: return NLSUtility
253: .format(
254: TextEditorMessages.Editor_error_unsupported_encoding_message_arg,
255: encoding);
256: return TextEditorMessages.Editor_error_unsupported_encoding_message;
257: }
258: }
259:
260: return null;
261: }
262:
263: /**
264: * Returns <code>true</code> if the given status is an
265: * encoding error.
266: *
267: * @param status the status to check
268: * @return <code>true</code> if the given status is an encoding error
269: * @since 3.1
270: */
271: public boolean isEncodingError(IStatus status) {
272: if (status == null || status.getSeverity() != IStatus.ERROR)
273: return false;
274:
275: Throwable t = status.getException();
276: return t instanceof CharConversionException
277: || t instanceof UnsupportedEncodingException;
278: }
279:
280: /**
281: * Creates the control which allows to change the encoding.
282: * In case of encoding errors this control will be placed below
283: * the status of the status editor.
284: *
285: * @param parent the parent control
286: * @param status the status
287: * @since 3.1
288: */
289: public void createStatusEncodingChangeControl(Composite parent,
290: final IStatus status) {
291: final IAction action = fTextEditor
292: .getAction(ITextEditorActionConstants.CHANGE_ENCODING);
293: if (action instanceof TextEditorAction)
294: ((TextEditorAction) action).update();
295:
296: if (action == null || !action.isEnabled())
297: return;
298:
299: Shell shell = parent.getShell();
300: Display display = shell.getDisplay();
301: Color bgColor = display
302: .getSystemColor(SWT.COLOR_LIST_BACKGROUND);
303:
304: Button button = new Button(parent, SWT.PUSH | SWT.FLAT);
305: button.setText(action.getText());
306: button.addSelectionListener(new SelectionAdapter() {
307: /*
308: * @see org.eclipse.swt.events.SelectionAdapter#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
309: */
310: public void widgetSelected(SelectionEvent e) {
311: action.run();
312: }
313: });
314:
315: Label filler = new Label(parent, SWT.NONE);
316: filler.setLayoutData(new GridData(GridData.FILL_BOTH));
317: filler.setBackground(bgColor);
318: }
319:
320: /**
321: * Returns the shell of the active workbench window.
322: *
323: * @return the shell of the active workbench window or <code>null</code> if none
324: * @since 3.2
325: */
326: private static Shell getActiveWorkbenchShell() {
327: IWorkbenchWindow window = PlatformUI.getWorkbench()
328: .getActiveWorkbenchWindow();
329: if (window != null)
330: return window.getShell();
331:
332: return null;
333: }
334:
335: }
|