blob: 64f099ab3d9698bea130f454bc6881b2552b0e27 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 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
* Florian Albrecht <florian.albrecht@clintworld.de> - make NLSKeyHyperlink work with non-text editors - https://bugs.eclipse.org/bugs/show_bug.cgi?id=97228
*******************************************************************************/
package org.eclipse.jdt.internal.ui.javaeditor;
import org.eclipse.swt.widgets.Display;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPartitioningException;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.texteditor.IEditorStatusLine;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.internal.corext.refactoring.nls.AccessorClassReference;
import org.eclipse.jdt.internal.corext.refactoring.nls.NLSHintHelper;
import org.eclipse.jdt.internal.corext.refactoring.nls.NLSRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.nls.PropertyFileDocumentModel;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.propertiesfileeditor.IPropertiesFilePartitions;
import org.eclipse.jdt.internal.ui.propertiesfileeditor.PropertyKeyHyperlinkDetector;
import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
/**
* NLS key hyperlink.
*
* @since 3.1
*/
public class NLSKeyHyperlink implements IHyperlink {
private IRegion fRegion;
private AccessorClassReference fAccessorClassReference;
private IEditorPart fEditor;
private final String fKeyName;
/**
* Creates a new NLS key hyperlink.
*
* @param region the region of the link
* @param keyName the name of the key
* @param ref the accessor class reference
* @param editor the editor which contains the hyperlink
*/
public NLSKeyHyperlink(IRegion region, String keyName, AccessorClassReference ref, IEditorPart editor) {
Assert.isNotNull(region);
Assert.isNotNull(keyName);
Assert.isNotNull(ref);
Assert.isNotNull(editor);
fRegion= region;
fKeyName= keyName;
fAccessorClassReference= ref;
fEditor= editor;
}
/*
* @see org.eclipse.jdt.internal.ui.javaeditor.IHyperlink#getHyperlinkRegion()
*/
public IRegion getHyperlinkRegion() {
return fRegion;
}
/*
* @see org.eclipse.jdt.internal.ui.javaeditor.IHyperlink#open()
*/
public void open() {
IStorage propertiesFile= null;
try {
ITypeBinding typeBinding= fAccessorClassReference.getBinding();
propertiesFile= NLSHintHelper.getResourceBundle(typeBinding.getJavaElement().getJavaProject(), fAccessorClassReference);
} catch (JavaModelException e) {
// Don't open the file
}
openKeyInPropertiesFile(fKeyName, propertiesFile, fEditor);
}
/**
* Calculates the region of the NLS key in the properties file and reveals it in editor.
*
* @param keyName the NLS key
* @param propertiesFile the properties file, or <code>null</code>
* @param activeEditor the active editor part
*/
public static void openKeyInPropertiesFile(String keyName, IStorage propertiesFile, IEditorPart activeEditor) {
if (propertiesFile == null) {
showErrorInStatusLine(activeEditor, JavaEditorMessages.Editor_OpenPropertiesFile_error_fileNotFound_dialogMessage);
return;
}
IEditorPart editor;
try {
editor= EditorUtility.openInEditor(propertiesFile, true);
} catch (PartInitException e) {
handleOpenPropertiesFileFailed(propertiesFile, activeEditor);
return;
}
// Reveal the key in the editor
IEditorInput editorInput = editor.getEditorInput();
IDocument document= null;
if (editor instanceof ITextEditor)
document= ((ITextEditor)editor).getDocumentProvider().getDocument(editorInput);
else {
IFile file= (IFile)editorInput.getAdapter(IFile.class);
if (file != null) {
IPath path= file.getFullPath();
ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
try {
manager.connect(path, LocationKind.IFILE, null);
try {
ITextFileBuffer buffer= manager.getTextFileBuffer(path, LocationKind.IFILE);
if (buffer != null)
document= buffer.getDocument();
} finally {
manager.disconnect(path, LocationKind.IFILE, null);
}
} catch (CoreException ex) {
JavaPlugin.log(ex);
}
}
}
// Find key in document
boolean found= false;
IRegion region= null;
if (document != null) {
FindReplaceDocumentAdapter finder= new FindReplaceDocumentAdapter(document);
PropertyKeyHyperlinkDetector detector= new PropertyKeyHyperlinkDetector();
detector.setContext(editor);
String key= PropertyFileDocumentModel.escape(keyName, false);
int offset= document.getLength() - 1;
try {
while (!found && offset >= 0) {
region= finder.find(offset, key, false, true, false, false);
if (region == null)
offset= -1;
else {
// test whether it's the key
IHyperlink[] hyperlinks= detector.detectHyperlinks(null, region, false);
if (hyperlinks != null) {
for (int i= 0; i < hyperlinks.length; i++) {
IRegion hyperlinkRegion= hyperlinks[i].getHyperlinkRegion();
found= key.equals(document.get(hyperlinkRegion.getOffset(), hyperlinkRegion.getLength()));
}
} else if (document instanceof IDocumentExtension3) {
// Fall back: test using properties file partitioning
ITypedRegion partition= null;
partition= ((IDocumentExtension3)document).getPartition(IPropertiesFilePartitions.PROPERTIES_FILE_PARTITIONING, region.getOffset(), false);
found= IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())
&& key.equals(document.get(partition.getOffset(), partition.getLength()).trim());
}
// Prevent endless loop (panic code, shouldn't be needed)
if (offset == region.getOffset())
offset= -1;
else
offset= region.getOffset();
}
}
} catch (BadLocationException ex) {
found= false;
} catch (BadPartitioningException e1) {
found= false;
}
}
if (found)
EditorUtility.revealInEditor(editor, region);
else {
EditorUtility.revealInEditor(editor, 0, 0);
showErrorInStatusLine(editor, Messages.format(JavaEditorMessages.Editor_OpenPropertiesFile_error_keyNotFound, keyName));
}
}
/**
* Shows the given message as error on the status line.
*
* @param editor the editor part
* @param message message to be displayed
*/
private static void showErrorInStatusLine(IEditorPart editor, final String message) {
final Display display= editor.getSite().getShell().getDisplay();
display.beep();
final IEditorStatusLine statusLine= (IEditorStatusLine)editor.getAdapter(IEditorStatusLine.class);
if (statusLine != null) {
display.asyncExec(new Runnable() {
/*
* @see java.lang.Runnable#run()
*/
public void run() {
statusLine.setMessage(true, message, null);
}
});
}
}
/**
* Shows error message in status line if opening the properties file in editor fails.
*
* @param propertiesFile the propertiesFile
* @param editor the editor part
*/
private static void handleOpenPropertiesFileFailed(IStorage propertiesFile, IEditorPart editor) {
showErrorInStatusLine(editor, Messages.format(JavaEditorMessages.Editor_OpenPropertiesFile_error_openEditor_dialogMessage, BasicElementLabels.getPathLabel(propertiesFile.getFullPath(), true)));
}
/*
* @see org.eclipse.jdt.internal.ui.javaeditor.IHyperlink#getTypeLabel()
*/
public String getTypeLabel() {
return null;
}
/*
* @see org.eclipse.jdt.internal.ui.javaeditor.IHyperlink#getHyperlinkText()
*/
public String getHyperlinkText() {
String bundleName= fAccessorClassReference.getResourceBundleName();
String propertyFileName= BasicElementLabels.getResourceName((bundleName.substring(bundleName.lastIndexOf('.') + 1, bundleName.length()) + NLSRefactoring.PROPERTY_FILE_EXT));
return Messages.format(JavaEditorMessages.Editor_OpenPropertiesFile_hyperlinkText, new Object[] { propertyFileName });
}
}