/**
* Aptana Studio
* Copyright (c) 2005-2012 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.editor.php.internal.ui.editor.hyperlink;
import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import com.aptana.core.util.ArrayUtil;
import com.aptana.core.util.StringUtil;
import com.aptana.editor.common.contentassist.ILexemeProvider;
import com.aptana.editor.php.internal.contentAssist.PHPTokenType;
import com.aptana.editor.php.internal.contentAssist.ParsingUtils;
import com.aptana.editor.php.internal.contentAssist.mapping.ICodeLocation;
import com.aptana.editor.php.internal.contentAssist.mapping.PHPOffsetMapper;
import com.aptana.editor.php.internal.ui.editor.PHPSourceEditor;
import com.aptana.editor.php.util.EditorUtils;
import com.aptana.parsing.lexer.Lexeme;
public class PHPHyperlinkDetector extends AbstractHyperlinkDetector
{
private static final String LINK_TEXT_FORMAT = "{0} [{1}]"; //$NON-NLS-1$
/*
* (non-Javadoc)
* @see org.eclipse.jface.text.hyperlink.IHyperlinkDetector#detectHyperlinks(org.eclipse.jface.text.ITextViewer,
* org.eclipse.jface.text.IRegion, boolean)
*/
public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks)
{
if (region == null || textViewer == null)
{
return null;
}
IEditorPart part = (IEditorPart) getAdapter(IEditorPart.class);
if (!(part instanceof PHPSourceEditor))
{
return null;
}
PHPSourceEditor editor = (PHPSourceEditor) part;
return detectHyperlinks(editor, region, canShowMultipleHyperlinks);
}
/**
* Detect hyperlinks given a {@link PHPSourceEditor} and an {@link IRegion}.
*
* @param editor
* @param region
* @param canShowMultipleHyperlinks
* @return An array of detected {@link IHyperlink}s.
*/
public IHyperlink[] detectHyperlinks(PHPSourceEditor editor, IRegion region, boolean canShowMultipleHyperlinks)
{
ILexemeProvider<PHPTokenType> lexemeProvider = ParsingUtils.createLexemeProvider(editor.getDocumentProvider()
.getDocument(editor.getEditorInput()), region.getOffset());
Lexeme<PHPTokenType> lexeme = lexemeProvider.getLexemeFromOffset(region.getOffset());
if (lexeme == null)
{
return null;
}
List<IHyperlink> result = new ArrayList<IHyperlink>();
PHPOffsetMapper offsetMapper = editor.getOffsetMapper();
ICodeLocation[] codeLocations = offsetMapper.findTargets(lexeme, lexemeProvider);
if (!ArrayUtil.isEmpty(codeLocations))
{
IRegion linkRegion = new Region(lexeme.getStartingOffset(), lexeme.getLength());
for (ICodeLocation codeLocation : codeLocations)
{
String hyperLinkText = lexeme.getText();
if (!StringUtil.isEmpty(codeLocation.getFullPath()))
{
hyperLinkText = MessageFormat.format(LINK_TEXT_FORMAT, hyperLinkText,
Path.fromOSString(codeLocation.getFullPath()).lastSegment());
}
else if (codeLocation.getRemoteFileStore() != null)
{
hyperLinkText = MessageFormat.format(LINK_TEXT_FORMAT, hyperLinkText, codeLocation
.getRemoteFileStore().getName());
}
IHyperlink link = new PHPHyperLink(codeLocation, linkRegion, hyperLinkText, StringUtil.EMPTY);
result.add(link);
}
}
if (!result.isEmpty())
{
return result.toArray(new IHyperlink[result.size()]);
}
return null;
}
/**
* PHP Hyperlink implementation for PHP elements that we have their declaration identified.
*
* @author Shalom Gibly <sgibly@aptana.com>
*/
static class PHPHyperLink implements IHyperlink
{
private IRegion region;
private String hyperlinkText;
private String typeLabel;
private final ICodeLocation codeLocation;
protected PHPHyperLink(ICodeLocation codeLocation, IRegion region, String hyperlinkText, String typeLabel)
{
this.codeLocation = codeLocation;
this.region = region;
this.hyperlinkText = hyperlinkText;
this.typeLabel = typeLabel;
}
public IRegion getHyperlinkRegion()
{
return region;
}
public String getHyperlinkText()
{
return hyperlinkText;
}
public String getTypeLabel()
{
return typeLabel;
}
/**
* @see org.eclipse.jface.text.hyperlink.IHyperlink#open()
*/
public void open()
{
if (codeLocation == null)
{
return;
}
IFileStore remoteFileStore = codeLocation.getRemoteFileStore();
Lexeme<PHPTokenType> startLexeme = codeLocation.getStartLexeme();
if (remoteFileStore != null)
{
com.aptana.ide.ui.io.navigator.actions.EditorUtils.openFileInEditor(remoteFileStore, null,
new TextSelection(startLexeme.getStartingOffset(), startLexeme.getLength()));
}
else
{
openInEditor(codeLocation.getFullPath(), startLexeme);
}
}
private void openInEditor(String fileName, Lexeme<PHPTokenType> lexeme)
{
File file = new File(fileName);
IEditorPart part = null;
if (file.exists())
{
part = EditorUtils.openInEditor(file);
}
else
{
IResource findMember = ResourcesPlugin.getWorkspace().getRoot().findMember(fileName);
if (findMember != null && findMember.exists() && findMember instanceof IFile)
{
part = EditorUtils.openInEditor(new File(((IFile) findMember).getLocationURI()));
}
}
if (part instanceof AbstractTextEditor)
{
AbstractTextEditor editor = (AbstractTextEditor) part;
editor.selectAndReveal(lexeme.getStartingOffset(), lexeme.getLength());
}
}
}
}