/**
* This file Copyright (c) 2005-2008 Aptana, Inc. This program is
* dual-licensed under both the Aptana Public License and the GNU General
* Public license. You may elect to use one or the other of these licenses.
*
* This program is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. Redistribution, except as permitted by whichever of
* the GPL or APL you select, is prohibited.
*
* 1. For the GPL license (GPL), you can redistribute and/or modify this
* program under the terms of the GNU General Public License,
* Version 3, as published by the Free Software Foundation. You should
* have received a copy of the GNU General Public License, Version 3 along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Aptana provides a special exception to allow redistribution of this file
* with certain other free and open source software ("FOSS") code and certain additional terms
* pursuant to Section 7 of the GPL. You may view the exception and these
* terms on the web at http://www.aptana.com/legal/gpl/.
*
* 2. For the Aptana Public License (APL), this program and the
* accompanying materials are made available under the terms of the APL
* v1.0 which accompanies this distribution, and is available at
* http://www.aptana.com/legal/apl/.
*
* You may view the GPL, Aptana's exception and additional terms, and the
* APL in the file titled license.html at the root of the corresponding
* plugin containing this source file.
*
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.ide.editors.unified.help;
import org.eclipse.help.HelpSystem;
import org.eclipse.help.IContext;
import org.eclipse.help.IContextProvider;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.HelpEvent;
import org.eclipse.swt.events.HelpListener;
import org.eclipse.ui.IWorkbenchPart;
import com.aptana.ide.editors.unified.IFileService;
import com.aptana.ide.editors.unified.IFileLanguageService;
import com.aptana.ide.editors.unified.IUnifiedEditor;
import com.aptana.ide.lexer.Lexeme;
import com.aptana.ide.lexer.LexemeList;
/**
* LexemeUIHelp
*
* @author Ingo Muschenetz
*/
public class LexemeUIHelp
{
/**
* APTANA_DOCS_KEYWORD
*/
public static final String APTANA_DOCS_KEYWORD = "aptana_docs"; //$NON-NLS-1$
/**
* Protected constructor for utility class
*/
protected LexemeUIHelp()
{
}
/**
* setHelp
*
* @param editor
* @param text
* @param fileService
*/
public static void setHelp(IUnifiedEditor editor, StyledText text, IFileService fileService)
{
LexemeHelpListener listener = new LexemeHelpListener(editor, fileService);
text.addHelpListener(listener);
}
/**
* Creates and returns a help context provider for the given part.
*
* @param part
* the part for which to create the help context provider
* @param fileService
* @return the help context provider
*/
public static IContextProvider getHelpContextProvider(IWorkbenchPart part, IFileService fileService)
{
Lexeme lexeme = null;
int offset = 0;
IFileLanguageService fileLanguageService = null;
if (part instanceof IUnifiedEditor)
{
IUnifiedEditor editor = (IUnifiedEditor) part;
lexeme = getLexeme(editor, fileService);
offset = editor.getViewer().getTextWidget().getCaretOffset();
if (lexeme != null)
{
fileLanguageService = fileService.getLanguageService(lexeme.getToken().getLanguage());
}
}
return new LexemeHelpContextProvider(fileLanguageService, lexeme, offset);
}
/**
* Currently, we only provide documentation on identifiers or keywords
*
* @param lexeme
* @return true if lexeme is valid
*/
public static boolean isValidLexeme(Lexeme lexeme)
{
if (lexeme == null)
{
return false;
}
// if (lexeme.getCategoryIndex() == JSTokenCategories.IDENTIFIER
// || lexeme.getCategoryIndex() == JSTokenCategories.KEYWORD)
return true;
// else
// return false;
}
/**
* Returns a valid lexeme (we wish to show in help), or a null object otherwise;
*
* @param editor
* @param fileService
* @return Returns a valid lexeme (we wish to show in help), or a null object otherwise;
*/
public static Lexeme getLexeme(IUnifiedEditor editor, IFileService fileService)
{
int offset = editor.getViewer().getTextWidget().getCaretOffset();
LexemeList lexemes = fileService.getLexemeList();
if (lexemes == null)
{
return null;
}
int floorIndex = lexemes.getLexemeFloorIndex(offset);
Lexeme lexeme = null;
if (floorIndex >= 0)
{
lexeme = lexemes.get(floorIndex);
}
int ceilingIndex = lexemes.getLexemeCeilingIndex(offset);
if (lexeme == null && ceilingIndex >= 0)
{
lexemes.get(lexemes.getLexemeCeilingIndex(offset));
}
if (isValidLexeme(lexeme))
{
return lexeme;
}
else
{
return null;
}
}
/**
* LexemeHelpListener
*
* @author Ingo Muschenetz
*/
private static class LexemeHelpListener implements HelpListener
{
private IUnifiedEditor fEditor;
private IFileService fileService;
/**
* LexemeHelpListener
*
* @param editor
* @param fileService
*/
public LexemeHelpListener(IUnifiedEditor editor, IFileService fileService)
{
fEditor = editor;
this.fileService = fileService;
}
/**
* Invoked when F1 is pressed.
*
* @see org.eclipse.swt.events.HelpListener#helpRequested(org.eclipse.swt.events.HelpEvent)
*/
public void helpRequested(HelpEvent e)
{
Lexeme lexeme = null;
int offset = 0;
if (fEditor != null)
{
lexeme = getLexeme(fEditor, fileService);
offset = fEditor.getViewer().getTextWidget().getCaretOffset();
if (lexeme != null)
{
String language = lexeme.getToken().getLanguage();
LexemeHelpContext.displayHelp("com.aptana.ide.editors.HTMLEditor", fileService //$NON-NLS-1$
.getLanguageService(language), lexeme, offset);
}
}
}
}
/**
* The Help view tracks activation of the workbench parts (views and editors) and checks if they adapt to
* org.eclipse.help.IContextProvider interface. If they do, the view will use the context provider to locate the
* IContext object and get the required information from it.
*
* @author Ingo Muschenetz
*/
private static class LexemeHelpContextProvider implements IContextProvider
{
private String fId = "com.aptana.ide.editors.HTMLEditor"; //$NON-NLS-1$
private IFileLanguageService fileLanguageService;
private Lexeme fLexeme;
private int offset = 0;
/**
* LexemeHelpContextProvider
*
* @param fileLanguageService
* @param lexeme
* @param offset
*/
public LexemeHelpContextProvider(IFileLanguageService fileLanguageService, Lexeme lexeme, int offset)
{
this.fileLanguageService = fileLanguageService;
fLexeme = lexeme;
this.offset = offset;
}
/**
* If context change mask returns NONE, context object will need to be provided when the workbench part is
* activated. If SELECTION is returned, you will need to provide context object that is sensitive to the current
* selection in the part. Each time part selection provider fires a selection change event, the context provider
* will be asked to provide context object. NOTE: The behavior will be different depending on if the editor has
* a selection provider that implements IPostSelectionProvider. See HelpView line 154.
*
* @return ContextChangeMask
*/
public int getContextChangeMask()
{
return SELECTION;
}
/**
* Context object for "About..." part of help. This pulls default content from the contexts.xml file, and adds
* in other content.
*
* @param target
* @return returns the context
*/
public IContext getContext(Object target)
{
IContext context = null;
if (fileLanguageService == null)
{
return context;
}
if (fileLanguageService.getOffsetMapper() == null)
{
return HelpSystem.getContext(fId);
}
Lexeme lexeme = fileLanguageService.getOffsetMapper().getCurrentLexeme();
if (lexeme != null)
{
context = new LexemeHelpContext(context, fileLanguageService, lexeme, offset);
}
else
{
context = HelpSystem.getContext(fId);
}
return context;
}
/**
* Search expression passed to "dynamic help" area. This does a search against an array of federated search
* engines.
*
* @param target
* @return Returns the search expression passed to "dynamic help" area.
*/
public String getSearchExpression(Object target)
{
if (fLexeme != null)
{
String lexemeLanguage = fLexeme.getLanguage();
if(lexemeLanguage != null)
{
lexemeLanguage = lexemeLanguage.replace('/', '_');
}
return lexemeLanguage + " " + fLexeme.getText() + " " + APTANA_DOCS_KEYWORD; //$NON-NLS-1$ //$NON-NLS-2$
}
else
{
return Messages.LexemeUIHelp_Editor;
}
}
}
}