| /******************************************************************************* |
| * Copyright (c) 2010 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.ui.propertiesfileeditor; |
| |
| import java.nio.charset.Charset; |
| import java.nio.charset.CharsetEncoder; |
| |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.custom.VerifyKeyListener; |
| import org.eclipse.swt.events.VerifyEvent; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| |
| import org.eclipse.core.resources.IFile; |
| |
| import org.eclipse.jface.text.DocumentCommand; |
| import org.eclipse.jface.text.DocumentEvent; |
| import org.eclipse.jface.text.IAutoEditStrategy; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IDocumentListener; |
| import org.eclipse.jface.text.contentassist.ICompletionProposal; |
| import org.eclipse.jface.text.quickassist.IQuickAssistAssistant; |
| import org.eclipse.jface.text.quickassist.IQuickAssistProcessor; |
| import org.eclipse.jface.text.source.ISourceViewer; |
| import org.eclipse.jface.text.source.ISourceViewerExtension3; |
| |
| import org.eclipse.ui.progress.WorkbenchJob; |
| |
| /** |
| * Auto edit strategy that escapes a character if it cannot be encoded in the .properties file's |
| * encoding. |
| * |
| * <p> |
| * A quick assist to escape backslashes is offered iff the pasted text is not perfectly correct for |
| * the .properties file, i.e. if the text contains |
| * <ul> |
| * <li>an invalid escape sequence as defined by |
| * {@link PropertiesFileEscapes#containsInvalidEscapeSequence(String)}</li> |
| * <li>a character which requires Unicode escapes</li> |
| * </ul> |
| * </p> |
| * |
| * @since 3.7 |
| */ |
| public class PropertiesFileAutoEditStrategy implements IAutoEditStrategy { |
| |
| private final IFile fFile; |
| |
| private String fCharsetName; |
| |
| private CharsetEncoder fCharsetEncoder; |
| |
| private final ISourceViewer fSourceViewer; |
| |
| public PropertiesFileAutoEditStrategy(IFile file, ISourceViewer sourceViewer) { |
| fFile= file; |
| fSourceViewer= sourceViewer; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.jface.text.IAutoEditStrategy#customizeDocumentCommand(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.DocumentCommand) |
| */ |
| public void customizeDocumentCommand(IDocument document, DocumentCommand command) { |
| showProposal(escape(command), document); |
| } |
| |
| private ICompletionProposal escape(DocumentCommand command) { |
| try { |
| String charsetName= fFile.getCharset(); |
| if (!charsetName.equals(fCharsetName)) { |
| fCharsetName= charsetName; |
| fCharsetEncoder= Charset.forName(fCharsetName).newEncoder(); |
| } |
| } catch (CoreException e) { |
| return null; |
| } |
| |
| String text= command.text; |
| boolean escapeUnicodeChars= !fCharsetEncoder.canEncode(text); |
| boolean escapeBackslash= (text.length() > 1) && ((escapeUnicodeChars && PropertiesFileEscapes.containsUnescapedBackslash(text)) || PropertiesFileEscapes.containsInvalidEscapeSequence(text)); |
| |
| if (!escapeUnicodeChars && !escapeBackslash) |
| return null; |
| |
| command.text= PropertiesFileEscapes.escape(text, false, false, escapeUnicodeChars); |
| if (escapeBackslash) { |
| String proposalText= PropertiesFileEscapes.escape(text, false, true, escapeUnicodeChars); |
| return new EscapeBackslashCompletionProposal(proposalText, command.offset, command.text.length(), true); |
| } |
| return null; |
| } |
| |
| private void showProposal(final ICompletionProposal proposal, final IDocument document) { |
| if (proposal != null && fSourceViewer instanceof ISourceViewerExtension3) { |
| final WorkbenchJob job= new WorkbenchJob(PropertiesFileEditorMessages.PropertiesFileAutoEditStrategy_showQuickAssist) { |
| @Override |
| public IStatus runInUIThread(IProgressMonitor monitor) { |
| IQuickAssistAssistant assistant= ((ISourceViewerExtension3)fSourceViewer).getQuickAssistAssistant(); |
| IQuickAssistProcessor processor= assistant.getQuickAssistProcessor(); |
| if (processor instanceof PropertiesCorrectionProcessor) { |
| ((PropertiesCorrectionProcessor)processor).setProposals(new ICompletionProposal[] { proposal }); |
| assistant.showPossibleQuickAssists(); |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| job.setSystem(true); |
| job.schedule(500); |
| final StyledText textWidget= fSourceViewer.getTextWidget(); |
| textWidget.addVerifyKeyListener(new VerifyKeyListener() { |
| public void verifyKey(VerifyEvent event) { |
| job.cancel(); |
| textWidget.removeVerifyKeyListener(this); |
| } |
| }); |
| |
| final IDocumentListener documentListener= new IDocumentListener() { |
| private boolean pasteComplete= false; |
| public void documentAboutToBeChanged(DocumentEvent event) { |
| } |
| public void documentChanged(DocumentEvent event) { |
| if (pasteComplete) { |
| job.cancel(); |
| document.removeDocumentListener(this); |
| } |
| pasteComplete= true; |
| } |
| }; |
| document.addDocumentListener(documentListener); |
| } |
| } |
| } |