package com.liferay.ide.velocity.editor; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import org.apache.velocity.runtime.directive.VelocimacroProxy; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Path; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentListener; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextInputListener; import org.eclipse.jface.text.ITextViewerExtension2; import org.eclipse.jface.text.ITextViewerExtension5; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.IVerticalRuler; import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.jface.text.source.projection.ProjectionAnnotation; import org.eclipse.jface.text.source.projection.ProjectionSupport; import org.eclipse.jface.text.source.projection.ProjectionViewer; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.MouseMoveListener; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorActionBarContributor; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.browser.IWebBrowser; import org.eclipse.ui.editors.text.TextEditor; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.internal.browser.WorkbenchBrowserSupport; import org.eclipse.ui.part.EditorActionBarContributor; import org.eclipse.ui.texteditor.BasicTextEditorActionContributor; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; import org.eclipse.ui.texteditor.MarkerAnnotation; import org.eclipse.ui.texteditor.TextOperationAction; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import com.liferay.ide.velocity.scanner.XMLElementGuesser; import com.liferay.ide.velocity.ui.editor.outline.VelocityOutlinePage; import com.liferay.ide.velocity.ui.editor.xml.VelocityAutoIndentStrategy; import com.liferay.ide.velocity.vaulttec.ui.IPreferencesConstants; import com.liferay.ide.velocity.vaulttec.ui.VelocityColorProvider; import com.liferay.ide.velocity.vaulttec.ui.VelocityPlugin; import com.liferay.ide.velocity.vaulttec.ui.editor.VelocityConfiguration; import com.liferay.ide.velocity.vaulttec.ui.editor.VelocityDocumentProvider; import com.liferay.ide.velocity.vaulttec.ui.editor.VelocityEditorEnvironment; import com.liferay.ide.velocity.vaulttec.ui.editor.VelocityReconcilingStrategy; import com.liferay.ide.velocity.vaulttec.ui.editor.actions.FormatAction; import com.liferay.ide.velocity.vaulttec.ui.editor.actions.GotoDefinitionAction; import com.liferay.ide.velocity.vaulttec.ui.editor.actions.IVelocityActionConstants; import com.liferay.ide.velocity.vaulttec.ui.editor.actions.IVelocityActionDefinitionIds; import com.liferay.ide.velocity.vaulttec.ui.editor.actions.JTidyAction; import com.liferay.ide.velocity.vaulttec.ui.editor.actions.ToggleCommentAction; import com.liferay.ide.velocity.vaulttec.ui.editor.text.VelocityTextGuesser; import com.liferay.ide.velocity.vaulttec.ui.model.ITreeNode; import com.liferay.ide.velocity.vaulttec.ui.model.ModelTools; import com.wutka.dtd.DTD; import com.wutka.dtd.DTDElement; import com.wutka.dtd.DTDParser; /** * DOCUMENT ME! * * @version $Revision: 37 $ * @author <a href="mailto:akmal.sarhan@gmail.com">Akmal Sarhan </a> */ public class VelocityEditor extends TextEditor implements IPropertyChangeListener { /* * (non-Javadoc) * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createAnnotationAccess() */ private static final String TEMPLATE_PROPOSALS = "template_proposals_action"; //$NON-NLS-1$ public static Browser definitionBrowser; private static final String PREFIX = "VelocityEditor."; private static DTD dtd = null; public static final Map<String, String> map = new HashMap<String, String>(100); static { map.put("A", getDocLocation() + "wdghtml40/special/a.html"); map.put("ABBR", getDocLocation() + "wdghtml40/phrase/abbr.html"); map.put("ACRONYM", getDocLocation() + "wdghtml40/phrase/acronym.html"); map.put("ADDRESS", getDocLocation() + "wdghtml40/block/address.html"); map.put("APPLET", getDocLocation() + "wdghtml40/special/applet.html"); map.put("AREA", getDocLocation() + "wdghtml40/special/area.html"); map.put("B", getDocLocation() + "wdghtml40/fontstyle/b.html"); map.put("BASE", getDocLocation() + "wdghtml40/head/base.html"); map.put("BASEFONT", getDocLocation() + "wdghtml40/special/basefont.html"); map.put("BDO", getDocLocation() + "wdghtml40/special/bdo.html"); map.put("BIG", getDocLocation() + "wdghtml40/fontstyle/big.html"); map.put("BLOCKQUOTE", getDocLocation() + "wdghtml40/block/blockquote.html"); map.put("BODY", getDocLocation() + "wdghtml40/html/body.html"); map.put("BR", getDocLocation() + "wdghtml40/special/br.html"); map.put("BUTTON", getDocLocation() + "wdghtml40/forms/button.html"); map.put("CAPTION", getDocLocation() + "wdghtml40/tables/caption.html"); map.put("CENTER", getDocLocation() + "wdghtml40/block/center.html"); map.put("CITE", getDocLocation() + "wdghtml40/phrase/cite.html"); map.put("CODE", getDocLocation() + "wdghtml40/phrase/code.html"); map.put("COL", getDocLocation() + "wdghtml40/tables/col.html"); map.put("COLGROUP", getDocLocation() + "wdghtml40/tables/colgroup.html"); map.put("DD", getDocLocation() + "wdghtml40/lists/dd.html"); map.put("DEL", getDocLocation() + "wdghtml40/phrase/del.html"); map.put("DFN", getDocLocation() + "wdghtml40/phrase/dfn.html"); map.put("DIR", getDocLocation() + "wdghtml40/lists/dir.html"); map.put("DIV", getDocLocation() + "wdghtml40/block/div.html"); map.put("DL", getDocLocation() + "wdghtml40/lists/dl.html"); map.put("DT", getDocLocation() + "wdghtml40/lists/dt.html"); map.put("EM", getDocLocation() + "wdghtml40/phrase/em.html"); map.put("FIELDSET", getDocLocation() + "wdghtml40/forms/fieldset.html"); map.put("FONT", getDocLocation() + "wdghtml40/special/font.html"); map.put("FORM", getDocLocation() + "wdghtml40/forms/form.html"); map.put("FRAME", getDocLocation() + "wdghtml40/frames/frame.html"); map.put("FRAMESET", getDocLocation() + "wdghtml40/frames/frameset.html"); map.put("H1", getDocLocation() + "wdghtml40/block/h1.html"); map.put("H2", getDocLocation() + "wdghtml40/block/h2.html"); map.put("H3", getDocLocation() + "wdghtml40/block/h3.html"); map.put("H4", getDocLocation() + "wdghtml40/block/h4.html"); map.put("H5", getDocLocation() + "wdghtml40/block/h5.html"); map.put("H6", getDocLocation() + "wdghtml40/block/h6.html"); map.put("HEAD", getDocLocation() + "wdghtml40/head/head.html"); map.put("HR", getDocLocation() + "wdghtml40/block/hr.html"); map.put("HTML", getDocLocation() + "wdghtml40/html/html.html"); map.put("I", getDocLocation() + "wdghtml40/fontstyle/i.html"); map.put("IFRAME", getDocLocation() + "wdghtml40/special/iframe.html"); map.put("IMG", getDocLocation() + "wdghtml40/special/img.html"); map.put("INPUT", getDocLocation() + "wdghtml40/forms/input.html"); map.put("INS", getDocLocation() + "wdghtml40/phrase/ins.html"); map.put("ISINDEX", getDocLocation() + "wdghtml40/block/isindex.html"); map.put("KBD", getDocLocation() + "wdghtml40/phrase/kbd.html"); map.put("LABEL", getDocLocation() + "wdghtml40/forms/label.html"); map.put("LEGEND", getDocLocation() + "wdghtml40/forms/legend.html"); map.put("LI", getDocLocation() + "wdghtml40/lists/li.html"); map.put("LINK", getDocLocation() + "wdghtml40/head/link.html"); map.put("MAP", getDocLocation() + "wdghtml40/special/map.html"); map.put("MENU", getDocLocation() + "wdghtml40/lists/menu.html"); map.put("META", getDocLocation() + "wdghtml40/head/meta.html"); map.put("NOFRAMES", getDocLocation() + "wdghtml40/frames/noframes.html"); map.put("NOSCRIPT", getDocLocation() + "wdghtml40/block/noscript.html"); map.put("OBJECT", getDocLocation() + "wdghtml40/special/object.html"); map.put("OL", getDocLocation() + "wdghtml40/lists/ol.html"); map.put("OPTGROUP", getDocLocation() + "wdghtml40/forms/optgroup.html"); map.put("OPTION", getDocLocation() + "wdghtml40/forms/option.html"); map.put("P", getDocLocation() + "wdghtml40/block/p.html"); map.put("PARAM", getDocLocation() + "wdghtml40/special/param.html"); map.put("PRE", getDocLocation() + "wdghtml40/block/pre.html"); map.put("Q", getDocLocation() + "wdghtml40/special/q.html"); map.put("S", getDocLocation() + "wdghtml40/fontstyle/s.html"); map.put("SAMP", getDocLocation() + "wdghtml40/phrase/samp.html"); map.put("SCRIPT", getDocLocation() + "wdghtml40/special/script.html"); map.put("SELECT", getDocLocation() + "wdghtml40/forms/select.html"); map.put("SMALL", getDocLocation() + "wdghtml40/fontstyle/small.html"); map.put("SPAN", getDocLocation() + "wdghtml40/special/span.html"); map.put("STRIKE", getDocLocation() + "wdghtml40/fontstyle/strike.html"); map.put("STRONG", getDocLocation() + "wdghtml40/phrase/strong.html"); map.put("STYLE", getDocLocation() + "wdghtml40/head/style.html"); map.put("SUB", getDocLocation() + "wdghtml40/special/sub.html"); map.put("SUP", getDocLocation() + "wdghtml40/special/sup.html"); map.put("TABLE", getDocLocation() + "wdghtml40/tables/table.html"); map.put("TBODY", getDocLocation() + "wdghtml40/tables/tbody.html"); map.put("TD", getDocLocation() + "wdghtml40/tables/td.html"); map.put("TEXTAREA", getDocLocation() + "wdghtml40/forms/textarea.html"); map.put("TFOOT", getDocLocation() + "wdghtml40/tables/tfoot.html"); map.put("TH", getDocLocation() + "wdghtml40/tables/th.html"); map.put("THEAD", getDocLocation() + "wdghtml40/tables/thead.html"); map.put("TITLE", getDocLocation() + "wdghtml40/head/title.html"); map.put("TR", getDocLocation() + "wdghtml40/tables/tr.html"); map.put("TT", getDocLocation() + "wdghtml40/fontstyle/tt.html"); map.put("U", getDocLocation() + "wdghtml40/fontstyle/u.html"); map.put("UL", getDocLocation() + "wdghtml40/lists/ul.html"); map.put("VAR", getDocLocation() + "wdghtml40/phrase/var.html"); map.put("BACKGROUND", getDocLocation() + "wdghtml40/css.html#background"); map.put("BACKGROUND-ATTACHMENT", getDocLocation() + "wdghtml40/css.html#background-attachment"); map.put("BACKGROUND-COLOR", getDocLocation() + "wdghtml40/css.html#background-color"); map.put("BACKGROUND-IMAGE", getDocLocation() + "wdghtml40/css.html#background-image"); map.put("BACKGROUND-POSITION", getDocLocation() + "wdghtml40/css.html#background-position"); map.put("BACKGROUND-REPEAT", getDocLocation() + "wdghtml40/css.html#background-repeat"); map.put("BORDER", getDocLocation() + "wdghtml40/css.html#border"); map.put("BORDER-BOTTOM", getDocLocation() + "wdghtml40/css.html#border-bottom"); map.put("BORDER-BOTTOM-WIDTH", getDocLocation() + "wdghtml40/css.html#border-bottom-width"); map.put("BORDER-COLOR", getDocLocation() + "wdghtml40/css.html#border-color"); map.put("BORDER-LEFT", getDocLocation() + "wdghtml40/css.html#border-left"); map.put("BORDER-LEFT-WIDTH", getDocLocation() + "wdghtml40/css.html#border-left-width"); map.put("BORDER-RIGHT", getDocLocation() + "wdghtml40/css.html#border-right"); map.put("BORDER-RIGHT-WIDTH", getDocLocation() + "wdghtml40/css.html#border-right-width"); map.put("BORDER-STYLE", getDocLocation() + "wdghtml40/css.html#border-style"); map.put("BORDER-TOP", getDocLocation() + "wdghtml40/css.html#border-top"); map.put("BORDER-TOP-WIDTH", getDocLocation() + "wdghtml40/css.html#border-top-width"); map.put("BORDER-WIDTH", getDocLocation() + "wdghtml40/css.html#border-width"); map.put("BOX", getDocLocation() + "wdghtml40/css.html#box"); map.put("CLASSIFICATION", getDocLocation() + "wdghtml40/css.html#classification"); map.put("CLEAR", getDocLocation() + "wdghtml40/css.html#clear"); map.put("COLOR", getDocLocation() + "wdghtml40/css.html#color"); map.put("COLOR-BACKGROUND", getDocLocation() + "wdghtml40/css.html#color-background"); map.put("COLOR-UNITS", getDocLocation() + "wdghtml40/css.html#color-units"); map.put("DISPLAY", getDocLocation() + "wdghtml40/css.html#display"); map.put("FLOAT", getDocLocation() + "wdghtml40/css.html#float"); map.put("FONT", getDocLocation() + "wdghtml40/css.html#font"); map.put("FONT-FAMILY", getDocLocation() + "wdghtml40/css.html#font-family"); map.put("FONT-PROPERTIES", getDocLocation() + "wdghtml40/css.html#font-properties"); map.put("FONT-SIZE", getDocLocation() + "wdghtml40/css.html#font-size"); map.put("FONT-STYLE", getDocLocation() + "wdghtml40/css.html#font-style"); map.put("FONT-VARIANT", getDocLocation() + "wdghtml40/css.html#font-variant"); map.put("FONT-WEIGHT", getDocLocation() + "wdghtml40/css.html#font-weight"); map.put("HEIGHT", getDocLocation() + "wdghtml40/css.html#height"); map.put("LENGTH", getDocLocation() + "wdghtml40/css.html#length"); map.put("LETTER-SPACING", getDocLocation() + "wdghtml40/css.html#letter-spacing"); map.put("LINE-HEIGHT", getDocLocation() + "wdghtml40/css.html#line-height"); map.put("LIST-STYLE", getDocLocation() + "wdghtml40/css.html#list-style"); map.put("LIST-STYLE-IMAGE", getDocLocation() + "wdghtml40/css.html#list-style-image"); map.put("LIST-STYLE-POSITION", getDocLocation() + "wdghtml40/css.html#list-style-position"); map.put("LIST-STYLE-TYPE", getDocLocation() + "wdghtml40/css.html#list-style-type"); map.put("MARGIN", getDocLocation() + "wdghtml40/css.html#margin"); map.put("MARGIN-BOTTOM", getDocLocation() + "wdghtml40/css.html#margin-bottom"); map.put("MARGIN-LEFT", getDocLocation() + "wdghtml40/css.html#margin-left"); map.put("MARGIN-RIGHT", getDocLocation() + "wdghtml40/css.html#margin-right"); map.put("MARGIN-TOP", getDocLocation() + "wdghtml40/css.html#margin-top"); map.put("PADDING", getDocLocation() + "wdghtml40/css.html#padding"); map.put("PADDING-BOTTOM", getDocLocation() + "wdghtml40/css.html#padding-bottom"); map.put("PADDING-LEFT", getDocLocation() + "wdghtml40/css.html#padding-left"); map.put("PADDING-RIGHT", getDocLocation() + "wdghtml40/css.html#padding-right"); map.put("PADDING-TOP", getDocLocation() + "wdghtml40/css.html#padding-top"); map.put("PERCENTAGE", getDocLocation() + "wdghtml40/css.html#percentage"); map.put("TEXT", getDocLocation() + "wdghtml40/css.html#text"); map.put("TEXT-ALIGN", getDocLocation() + "wdghtml40/css.html#text-align"); map.put("TEXT-DECORATION", getDocLocation() + "wdghtml40/css.html#text-decoration"); map.put("TEXT-INDENT", getDocLocation() + "wdghtml40/css.html#text-indent"); map.put("TEXT-TRANSFORM", getDocLocation() + "wdghtml40/css.html#text-transform"); map.put("UNITS", getDocLocation() + "wdghtml40/css.html#units"); map.put("URLS", getDocLocation() + "wdghtml40/css.html#urls"); map.put("VERTICAL-ALIGN", getDocLocation() + "wdghtml40/css.html#vertical-align"); map.put("WHITE-SPACE", getDocLocation() + "wdghtml40/css.html#white-space"); map.put("WIDTH", getDocLocation() + "wdghtml40/css.html#width"); map.put("WORD-SPACING", getDocLocation() + "wdghtml40/css.html#word-spacing"); } private VelocityColorProvider cp; // private AnnotationModel fAnnotationModel; private ModelTools fModelTools; private VelocityReconcilingStrategy fReconcilingStrategy; private VelocityOutlinePage fOutlinePage; /** * Last cursor position (line) handled in * <code>handleCursorPositionChanged()</code> */ private int fLastCursorLine; VelocityConfiguration vc = null; public MouseClickListener fMouseListener; private ProjectionSupport projectionSupport; private Set set; public VelocityEditor() { fModelTools = new ModelTools(this); fReconcilingStrategy = new VelocityReconcilingStrategy(this); cp = VelocityEditorEnvironment.getColorProvider(); VelocityPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this); } private void openBrowser(String url) { try { IWebBrowser browser = WorkbenchBrowserSupport.getInstance() .createBrowser(0, "MyBrowserID", "MyBrowserName", "MyBrowser Tooltip"); browser.openURL(new URL(url)); } catch (Exception e) { System.out.println(e); } } private static String getDocLocation() { String loc = ""; URL url = VelocityPlugin.getDefault().getBundle().getEntry("/"); try { loc = FileLocator.resolve(url).toString(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return loc; } /** * Currently we only validate against the xhtml strict dtd, this is used by * completion to test what elements are valid in the given context. */ public static DTDElement getHTMLElement(String name) { if (dtd == null) { String path = VelocityPlugin.getInstallPath() + "xhtml1-strict.dtd"; URL url = null; try { url = new URL(path); } catch (MalformedURLException e2) { e2.printStackTrace(); return null; } try { DTDParser parser = new DTDParser(url, false); dtd = parser.parse(false); } catch (IOException e1) { e1.printStackTrace(); return null; } } return (DTDElement) dtd.elements.get(name); } /* * (non-Javadoc) * * @see org.eclipse.ui.editors.text.TextEditor#initializeEditor() */ protected void initializeEditor() { super.initializeEditor(); VelocityEditorEnvironment.connect(); setDocumentProvider(new VelocityDocumentProvider()); VelocityConfiguration vc = new VelocityConfiguration(this); setSourceViewerConfiguration(vc); } // /* // * (non-Javadoc) // * // * @see // org.eclipse.ui.editors.text.TextEditor#initializeKeyBindingScopes() // */ // protected void initializeKeyBindingScopes() // { // setKeyBindingScopes(new String[] { // "com.googlecode.veloeclipse.vaulttec.ui.velocityEditorScope" }); // } private void enableBrowserLikeLinks() { if (fMouseListener == null) { fMouseListener = new MouseClickListener(); fMouseListener.install(); } } /* * (non-Javadoc) * * @see org.eclipse.ui.texteditor.AbstractTextEditor#createActions() */ protected void createActions() { super.createActions(); // Add goto definition action IAction action = new GotoDefinitionAction(VelocityPlugin.getDefault().getResourceBundle(), PREFIX + "GotoDefinition.", this); action.setActionDefinitionId(IVelocityActionDefinitionIds.GOTO_DEFINITION); setAction(IVelocityActionConstants.GOTO_DEFINITION, action); action = new TextOperationAction(VelocityPlugin.getDefault().getResourceBundle(), "ContentAssistProposal.", this, ISourceViewer.CONTENTASSIST_PROPOSALS); //$NON-NLS-1$ action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); // setAction("ContentAssistProposal", action); //$NON-NLS-1$ setAction(IVelocityActionConstants.CONTENT_ASSIST, action); // jtidy action = new JTidyAction(VelocityPlugin.getDefault().getResourceBundle(), PREFIX + "JTidy.", this); action.setActionDefinitionId(IVelocityActionDefinitionIds.JTIDY); setAction(IVelocityActionConstants.JTIDY, action); // TOGGLE_COMMENT action = new ToggleCommentAction(VelocityPlugin.getDefault().getResourceBundle(), PREFIX + "ToggleComment.", this); action.setActionDefinitionId(IVelocityActionDefinitionIds.TOGGLE_COMMENT); setAction(IVelocityActionConstants.TOGGLE_COMMENT, action); // FormatEditor action = new FormatAction(VelocityPlugin.getDefault().getResourceBundle(), PREFIX + "FormatEditor.", this); action.setActionDefinitionId(IVelocityActionDefinitionIds.FORMAT); setAction(IVelocityActionConstants.FORMAT, action); // template proposal action = new TextOperationAction(TemplateMessages.getResourceBundle(), "Editor." + TEMPLATE_PROPOSALS + ".", //$NON-NLS-1$ //$NON-NLS-2$ this, ISourceViewer.CONTENTASSIST_PROPOSALS); action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); setAction(TEMPLATE_PROPOSALS, action); markAsStateDependentAction(TEMPLATE_PROPOSALS, true); enableBrowserLikeLinks(); configureToggleCommentAction(); } /** * Get the outline page if requested. * * @see org.eclipse.core.runtime.IAdaptable.getAdapter(Class) */ public Object getAdapter(Class aClass) { // Object adapter; // if (aClass.equals(IContentOutlinePage.class)) // { // if ((fOutlinePage == null) || fOutlinePage.isDisposed()) // { // fOutlinePage = new VelocityOutlinePage(this); // if (getEditorInput() != null) // { // fOutlinePage.setInput(getEditorInput()); // } // } // adapter = fOutlinePage; // } else // { // adapter = super.getAdapter(aClass); // } // return adapter; // folding if (IContentOutlinePage.class.equals(aClass)) { if (fOutlinePage == null || fOutlinePage.isDisposed()) { fOutlinePage = new VelocityOutlinePage(this); if (getEditorInput() != null) { fOutlinePage.setInput(getEditorInput()); } } return fOutlinePage; } if (projectionSupport != null) { Object adapter = projectionSupport.getAdapter(getSourceViewer(), aClass); if (adapter != null) return adapter; } return super.getAdapter(aClass); } /** * Disconnect from editor environment and dispose outline page. * * @see org.eclipse.ui.IWorkbenchPart#dispose() */ public void dispose() { if ((fOutlinePage != null) && !fOutlinePage.isDisposed()) { fOutlinePage.dispose(); fOutlinePage = null; } VelocityEditorEnvironment.disconnect(); super.dispose(); } /* * (non-Javadoc) * * @see org.eclipse.ui.texteditor.AbstractTextEditor#editorContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager) */ protected void editorContextMenuAboutToShow(IMenuManager aMenu) { super.editorContextMenuAboutToShow(aMenu); addAction(aMenu, IWorkbenchActionConstants.MB_ADDITIONS, IVelocityActionConstants.GOTO_DEFINITION); addAction(aMenu, IWorkbenchActionConstants.MB_ADDITIONS, IVelocityActionConstants.CONTENT_ASSIST); addAction(aMenu, IWorkbenchActionConstants.MB_ADDITIONS, IVelocityActionConstants.TOGGLE_COMMENT); addAction(aMenu, IWorkbenchActionConstants.MB_ADDITIONS, IVelocityActionConstants.FORMAT); addAction(aMenu, IWorkbenchActionConstants.MB_ADDITIONS, IVelocityActionConstants.JTIDY); } /* * (non-Javadoc) * * @see org.eclipse.ui.texteditor.AbstractTextEditor#handleCursorPositionChanged() */ protected void handleCursorPositionChanged() { super.handleCursorPositionChanged(); int line = getCursorLine(); if ((line > 0) && (line != fLastCursorLine)) { fLastCursorLine = line; if ((fOutlinePage != null) && !fOutlinePage.isDisposed()) { fOutlinePage.selectNode(line, false); } } } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public IDocument getDocument() { ISourceViewer viewer = getSourceViewer(); if (viewer != null) { return viewer.getDocument(); } return null; } /** * DOCUMENT ME! * * @param anOffset * DOCUMENT ME! * @return DOCUMENT ME! */ public int getLine(int anOffset) { int line; try { line = getDocument().getLineOfOffset(anOffset) + 1; } catch (BadLocationException e) { line = -1; } return line; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public int getCursorLine() { int line = -1; ISourceViewer sourceViewer = getSourceViewer(); if (sourceViewer != null) { StyledText styledText = sourceViewer.getTextWidget(); int caret = widgetOffset2ModelOffset(sourceViewer, styledText.getCaretOffset()); IDocument document = sourceViewer.getDocument(); if (document != null) { try { line = document.getLineOfOffset(caret) + 1; } catch (BadLocationException e) { VelocityPlugin.log(e); } } } return line; } /** * DOCUMENT ME! * * @param aNode * DOCUMENT ME! * @param aMoveCursor * DOCUMENT ME! */ public void highlightNode(ITreeNode aNode, boolean aMoveCursor) { resetHighlightRange(); IDocument doc = getDocument(); try { int offset = doc.getLineOffset(aNode.getStartLine() - 1); IRegion endLine = doc.getLineInformation(aNode.getEndLine() - 1); int length = (endLine.getOffset() + endLine.getLength()) - offset; setHighlightRange(offset, length + 1, aMoveCursor); } catch (BadLocationException e) { resetHighlightRange(); } } /** * DOCUMENT ME! * * @param offset * DOCUMENT ME! * @param aMoveCursor * DOCUMENT ME! */ public void highlightOpenTag(int offset, boolean aMoveCursor) { resetHighlightRange(); IDocument doc = getDocument(); int linenr = -1; try { markInNavigationHistory(); linenr = doc.getLineOfOffset(offset); IRegion endLine = doc.getLineInformation(linenr); int length = (endLine.getOffset() + endLine.getLength()) - offset; setHighlightRange(offset, length + 1, aMoveCursor); markInNavigationHistory(); } catch (BadLocationException e) { resetHighlightRange(); } } /** * DOCUMENT ME! * * @param aNode * DOCUMENT ME! */ public void revealNode(ITreeNode aNode) { ISourceViewer viewer = getSourceViewer(); if (viewer != null) { IDocument doc = getDocument(); try { int offset = doc.getLineOffset(aNode.getStartLine() - 1); IRegion endLine = doc.getLineInformation(aNode.getEndLine() - 1); int length = (endLine.getOffset() + endLine.getLength()) - offset; // Reveal segment's text area in document StyledText widget = getSourceViewer().getTextWidget(); widget.setRedraw(false); viewer.revealRange(offset, length); widget.setRedraw(true); } catch (BadLocationException e) { resetHighlightRange(); } } } /** * DOCUMENT ME! * * @param aLine * DOCUMENT ME! * @return DOCUMENT ME! */ public ITreeNode getNodeByLine(int aLine) { return fModelTools.getNodeByLine(aLine); } /** * DOCUMENT ME! * * @param aRegion * DOCUMENT ME! * @return DOCUMENT ME! */ public String getDefinitionLine(IRegion aRegion) { int tagOffset = -1; String guessed = null; if (aRegion != null) { XMLElementGuesser xmlguess = new XMLElementGuesser(getDocument(), aRegion.getOffset(), true); guessed = xmlguess.getText(); int xmltype = xmlguess.getType(); tagOffset = xmlguess.getTagOffset(); if ((guessed != null) && map.containsKey(guessed.toUpperCase())) { switch (xmltype) { case VelocityTextGuesser.TAG_DIRECTIVE: guessed = "Ctrl+Alt+Mouseclick to show definition of " + guessed; break; case VelocityTextGuesser.TAG_CLOSE: int i = VelocityAutoIndentStrategy.findMatchingOpenTagBefore(tagOffset, getDocument()); if (i > -1) { int lnr = -1; try { lnr = getDocument().getLineOfOffset(i); } catch (BadLocationException e) { // TODO Auto-generated catch block e.printStackTrace(); } guessed = "Ctrl+Alt+Mouseclick to go to matching tag of " + guessed + ((lnr > -1) ? (" -> " + (lnr + 1) + "") : ""); } else { guessed = "this tag is incorrectly closed"; } break; default: guessed = null; break; } } else { guessed = null; VelocityTextGuesser guess = new VelocityTextGuesser(getDocument(), aRegion.getOffset(), true); // Check if guessed text references an externally defined macro if (guess.getType() == VelocityTextGuesser.TYPE_DIRECTIVE) { VelocimacroProxy vp = VelocityEditorEnvironment.getParser().getLibraryMacro(guess.getText()); if (vp != null) { String template = ((IFileEditorInput) getEditorInput()).getFile().getName(); if (!vp.getTemplateName().equals(template)) { StringBuffer buf = new StringBuffer(); buf.append("#macro ("); buf.append(vp.getName()); buf.append(") - "); buf.append(vp.getTemplateName()); return buf.toString(); } } } else if (guess.getType() == VelocityTextGuesser.TYPE_END) { int i = VelocityAutoIndentStrategy.findStartVeloBefore(guess.getTagOffset(), getDocument()); int lnr = -1; if (i > -1) { try { lnr = getDocument().getLineOfOffset(i); } catch (BadLocationException e) { // TODO Auto-generated catch block e.printStackTrace(); } } guessed = "Ctrl+Alt+Mouseclick to go to directive start " + ((lnr > -1) ? (" -> " + (lnr + 1) + "") : ""); } // Look through model tree for guessed text ITreeNode node = fModelTools.getNodeByGuess(guess); if (node != null) { IDocument doc = getDocument(); try { aRegion = doc.getLineInformation(node.getStartLine() - 1); StringBuffer buf = new StringBuffer(); buf.append(node.getStartLine()); buf.append(": "); buf.append(doc.get(aRegion.getOffset(), aRegion.getLength()).trim()); return buf.toString(); } catch (BadLocationException e) { } } } } return guessed; } /** * DOCUMENT ME! * * @param aRegion * DOCUMENT ME! */ public void gotoDefinition(IRegion aRegion) { int tagOffset = -1; if (aRegion != null) { XMLElementGuesser xmlguess = new XMLElementGuesser(getDocument(), aRegion.getOffset(), true); String guessed = xmlguess.getText(); int xmltype = xmlguess.getType(); tagOffset = xmlguess.getTagOffset(); if ((guessed != null) && map.containsKey(guessed.toUpperCase())) { switch (xmltype) { case VelocityTextGuesser.TAG_DIRECTIVE: guessed = (String) map.get(guessed.toUpperCase()); openBrowser(guessed); return; case VelocityTextGuesser.TAG_CLOSE: int i = VelocityAutoIndentStrategy.findMatchingOpenTagBefore(tagOffset, getDocument()); if (i > -1) { highlightOpenTag(i, true); } break; default: guessed = (String) map.get(guessed.toUpperCase()); openBrowser(guessed); return; } } else { VelocityTextGuesser guess = new VelocityTextGuesser(getDocument(), aRegion.getOffset(), true); // Check if guessed text references an externally defined macro if ((guess.getType() == VelocityTextGuesser.TYPE_DIRECTIVE) || (guess.getType() == VelocityTextGuesser.TYPE_VARIABLE)) { VelocimacroProxy vp = VelocityEditorEnvironment.getParser().getLibraryMacro(guess.getText()); if (vp != null) { String template = ((IFileEditorInput) getEditorInput()).getFile().getName(); if (!vp.getTemplateName().equals(template)) { try { // Goto the macro definition IPreferenceStore store = VelocityPlugin.getDefault().getPreferenceStore(); String filestr = store.getString(IPreferencesConstants.LIBRARY_PATH) + "/" + vp.getTemplateName(); IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(filestr)); IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); ITextEditor teditor = (ITextEditor)IDE.openEditor(page, file); IDocumentProvider provider = teditor.getDocumentProvider(); IDocument document = provider.getDocument(teditor.getEditorInput()); int start = document.getLineOffset(vp.getLine()-2); teditor.selectAndReveal(start + vp.getColumn()-1, 0); } catch(Exception e) { e.printStackTrace(); } return; } } // Look through model tree for guessed text ITreeNode node = fModelTools.getNodeByGuess(guess); if (node != null) { markInNavigationHistory(); highlightNode(node, true); markInNavigationHistory(); } } else if (guess.getType() == VelocityTextGuesser.TYPE_END) { int i = VelocityAutoIndentStrategy.findStartVeloBefore(guess.getTagOffset(), getDocument()); if (i > -1) { highlightOpenTag(i, true); } } } getSourceViewer().invalidateTextPresentation(); } } /** * Returns true if specified line belongs to a <code>#foreach</code> * block. */ public boolean isLineWithinLoop(int aLine) { return fModelTools.isLineWithinLoop(aLine); } /** * DOCUMENT ME! * * @param aLine * DOCUMENT ME! * @return DOCUMENT ME! */ public List getVariables(int aLine) { return fModelTools.getVariables(aLine); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public VelocityReconcilingStrategy getReconcilingStrategy() { return fReconcilingStrategy; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public Object[] getRootElements() { return fReconcilingStrategy.getRootElements(); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public ITreeNode getRootNode() { return fReconcilingStrategy.getRootNode(); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public ITreeNode getLastRootNode() { return fReconcilingStrategy.getLastRootNode(); } /** * DOCUMENT ME! */ public void updateOutlinePage() { if (fOutlinePage != null) { fOutlinePage.update(); } } /** * DOCUMENT ME! * * @param aLine * DOCUMENT ME! */ public void moveCursor(int aLine) { ISourceViewer sourceViewer = getSourceViewer(); try { int offset = getDocument().getLineOffset(aLine - 1); sourceViewer.setSelectedRange(offset, 0); sourceViewer.revealRange(offset, 0); } catch (BadLocationException e) { } } /** * Determines if the specified character may be part of a Velocity * reference. A character may be part of a Velocity directive if and only if * it is one of the following: * <ul> * <li>a letter (a..z, A..Z) * <li>a digit (0..9) * <li>a hyphen ("-") * <li>a connecting punctuation character ("_") * </ul> * * @param aChar * the character to be tested. * @return true if the character may be part of a Velocity reference; false * otherwise. * @see java.lang.Character#isLetterOrDigit(char) */ public static boolean isReferencePart(char aChar) { return Character.isLetterOrDigit(aChar) || (aChar == '-') || (aChar == '_'); } /** * Displays an error message in editor's status line. */ public void displayErrorMessage(String aMessage) { IStatusLineManager manager = getStatusLineManager(); if (manager != null) { manager.setErrorMessage(aMessage); } } /** * DOCUMENT ME! * * @param aMessage * DOCUMENT ME! * @param aLine * DOCUMENT ME! */ public void addProblemMarker(String aMessage, int aLine, int severity) { IFile file = ((IFileEditorInput) getEditorInput()).getFile(); try { IMarker marker = file.createMarker(IMarker.PROBLEM); marker.setAttribute(IMarker.SEVERITY, severity); marker.setAttribute(IMarker.MESSAGE, aMessage); marker.setAttribute(IMarker.LINE_NUMBER, aLine); Position pos = new Position(getDocument().getLineOffset(aLine - 1)); getSourceViewer().getAnnotationModel().addAnnotation(new MarkerAnnotation(marker), pos); } catch (Exception e) { VelocityPlugin.log(e); } } /* * (non-Javadoc) * * @see org.eclipse.ui.editors.text.TextEditor#handlePreferenceStoreChanged(org.eclipse.jface.util.PropertyChangeEvent) */ protected void handlePreferenceStoreChanged(PropertyChangeEvent event) { cp.handlePreferenceStoreChanged(event); super.handlePreferenceStoreChanged(event); } // /* // * @see AbstractTextEditor#doSetInput(IEditorInput) // */ // protected void doSetInput(IEditorInput input) throws CoreException // { // super.doSetInput(input); // // configureToggleCommentAction(); // } private void configureToggleCommentAction() { IAction action = getAction(IVelocityActionConstants.TOGGLE_COMMENT); //$NON-NLS-1$ if (action instanceof ToggleCommentAction) { ISourceViewer sourceViewer = getSourceViewer(); SourceViewerConfiguration configuration = getSourceViewerConfiguration(); ((ToggleCommentAction) action).configure(sourceViewer, configuration); } } /** * @return */ public VelocityConfiguration getVelocityConfiguration() { return vc; } /* * (non-Javadoc) * * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent event) { cp.handlePreferenceStoreChanged(event); ISourceViewer viewer = getSourceViewer(); if (viewer != null) { viewer.invalidateTextPresentation(); } } /** * DOCUMENT ME! * * @param token * DOCUMENT ME! * @return DOCUMENT ME! */ public static int findLocalizedModifier(String token) { if (token == null) { return 0; } if (token.equalsIgnoreCase(Action.findModifierString(SWT.CTRL))) { return SWT.CTRL; } if (token.equalsIgnoreCase(Action.findModifierString(SWT.SHIFT))) { return SWT.SHIFT; } if (token.equalsIgnoreCase(Action.findModifierString(SWT.ALT))) { return SWT.ALT; } if (token.equalsIgnoreCase(Action.findModifierString(SWT.COMMAND))) { return SWT.COMMAND; } return 0; } public class MouseClickListener implements KeyListener, MouseListener, MouseMoveListener, FocusListener, PaintListener, IPropertyChangeListener, IDocumentListener, ITextInputListener { /** The session is active. */ public boolean fActive; /** The currently active style range. */ public IRegion fActiveRegion; /** The currently active style range as position. */ private Position fRememberedPosition; /** The hand cursor. */ private Cursor fCursor; /** The link color. */ private Color fColor; /** The key modifier mask. */ private int fKeyModifierMask; public void deactivate() { deactivate(false); } public void deactivate(boolean redrawAll) { if (!fActive) { return; } repairRepresentation(redrawAll); fActive = false; } public void install() { ISourceViewer sourceViewer = getSourceViewer(); if (sourceViewer == null) { return; } StyledText text = sourceViewer.getTextWidget(); if ((text == null) || text.isDisposed()) { return; } updateColor(sourceViewer); sourceViewer.addTextInputListener(this); IDocument document = sourceViewer.getDocument(); if (document != null) { document.addDocumentListener(this); } text.addKeyListener(this); text.addMouseListener(this); text.addMouseMoveListener(this); text.addFocusListener(this); text.addPaintListener(this); updateKeyModifierMask(); IPreferenceStore preferenceStore = getPreferenceStore(); preferenceStore.addPropertyChangeListener(this); } private void updateKeyModifierMask() { fKeyModifierMask = computeStateMask("Ctrl+Alt"); if (fKeyModifierMask == -1) { } } private int computeStateMask(String modifiers) { if (modifiers == null) { return -1; } if (modifiers.length() == 0) { return SWT.NONE; } int stateMask = 0; StringTokenizer modifierTokenizer = new StringTokenizer(modifiers, ",;.:+-* "); //$NON-NLS-1$ while (modifierTokenizer.hasMoreTokens()) { int modifier = findLocalizedModifier(modifierTokenizer.nextToken()); if ((modifier == 0) || ((stateMask & modifier) == modifier)) { return -1; } stateMask = stateMask | modifier; } return stateMask; } public void uninstall() { if (fColor != null) { fColor.dispose(); fColor = null; } if (fCursor != null) { fCursor.dispose(); fCursor = null; } ISourceViewer sourceViewer = getSourceViewer(); if (sourceViewer == null) { return; } sourceViewer.removeTextInputListener(this); IDocument document = sourceViewer.getDocument(); if (document != null) { document.removeDocumentListener(this); } IPreferenceStore preferenceStore = getPreferenceStore(); if (preferenceStore != null) { preferenceStore.removePropertyChangeListener(this); } StyledText text = sourceViewer.getTextWidget(); if ((text == null) || text.isDisposed()) { return; } text.removeKeyListener(this); text.removeMouseListener(this); text.removeMouseMoveListener(this); text.removeFocusListener(this); text.removePaintListener(this); } private void updateColor(ISourceViewer viewer) { if (fColor != null) { fColor.dispose(); } StyledText text = viewer.getTextWidget(); if ((text == null) || text.isDisposed()) { return; } fColor = new Color(Display.getCurrent(), 0, 0, 255); } private void repairRepresentation() { repairRepresentation(false); } private void repairRepresentation(boolean redrawAll) { if (fActiveRegion == null) { return; } ISourceViewer viewer = getSourceViewer(); if (viewer != null) { resetCursor(viewer); int offset = fActiveRegion.getOffset(); int length = fActiveRegion.getLength(); // remove style if (!redrawAll && viewer instanceof ITextViewerExtension2) { ((ITextViewerExtension2) viewer).invalidateTextPresentation(offset, length); } else { viewer.invalidateTextPresentation(); } // remove underline if (viewer instanceof ITextViewerExtension5) { ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; offset = extension.modelOffset2WidgetOffset(offset); } else { offset -= viewer.getVisibleRegion().getOffset(); } StyledText text = viewer.getTextWidget(); try { text.redrawRange(offset, length, true); } catch (IllegalArgumentException x) { } } fActiveRegion = null; } private IRegion selectWord(IDocument document, int anchor) { try { int offset = anchor; char c; while (offset >= 0) { c = document.getChar(offset); if (!Character.isJavaIdentifierPart(c)) // || (c == '$')) { break; } --offset; } int start = offset; offset = anchor; int length = document.getLength(); while (offset < length) { c = document.getChar(offset); if (!Character.isJavaIdentifierPart(c)) // || (c == '$')) { break; } ++offset; } int end = offset; if (start == end) { return new Region(start, 0); } else { return new Region(start + 1, end - start - 1); } } catch (BadLocationException x) { return null; } } IRegion getCurrentTextRegion(ISourceViewer viewer) { int offset = getCurrentTextOffset(viewer); if (offset == -1) { return null; } try { return selectWord(viewer.getDocument(), offset); } catch (Exception e) { return null; } } private int getCurrentTextOffset(ISourceViewer viewer) { try { StyledText text = viewer.getTextWidget(); if ((text == null) || text.isDisposed()) { return -1; } Display display = text.getDisplay(); Point absolutePosition = display.getCursorLocation(); Point relativePosition = text.toControl(absolutePosition); int widgetOffset = text.getOffsetAtLocation(relativePosition); if (viewer instanceof ITextViewerExtension5) { ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; return extension.widgetOffset2ModelOffset(widgetOffset); } else { return widgetOffset + viewer.getVisibleRegion().getOffset(); } } catch (IllegalArgumentException e) { return -1; } } private void highlightRegion(ISourceViewer viewer, IRegion region) { if (region.equals(fActiveRegion)) { return; } repairRepresentation(); StyledText text = viewer.getTextWidget(); if ((text == null) || text.isDisposed()) { return; } // highlight region int offset = 0; int length = 0; if (viewer instanceof ITextViewerExtension5) { ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; IRegion widgetRange = extension.modelRange2WidgetRange(region); if (widgetRange == null) { return; } offset = widgetRange.getOffset(); length = widgetRange.getLength(); } else { offset = region.getOffset() - viewer.getVisibleRegion().getOffset(); length = region.getLength(); } StyleRange oldStyleRange = text.getStyleRangeAtOffset(offset); Color foregroundColor = fColor; Color backgroundColor = (oldStyleRange == null) ? text.getBackground() : oldStyleRange.background; StyleRange styleRange = new StyleRange(offset, length, foregroundColor, backgroundColor); text.setStyleRange(styleRange); // underline text.redrawRange(offset, length, true); fActiveRegion = region; } private void activateCursor(ISourceViewer viewer) { StyledText text = viewer.getTextWidget(); if ((text == null) || text.isDisposed()) { return; } Display display = text.getDisplay(); if (fCursor == null) { fCursor = new Cursor(display, SWT.CURSOR_HAND); } text.setCursor(fCursor); } private void resetCursor(ISourceViewer viewer) { StyledText text = viewer.getTextWidget(); if ((text != null) && !text.isDisposed()) { text.setCursor(null); } if (fCursor != null) { fCursor.dispose(); fCursor = null; } } /* * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent) */ public void keyPressed(KeyEvent event) { if (fActive) { deactivate(); return; } if (event.keyCode != fKeyModifierMask) { deactivate(); return; } fActive = true; // removed for #25871 // // ISourceViewer viewer= getSourceViewer(); // if (viewer == null) // return; // // IRegion region= getCurrentTextRegion(viewer); // if (region == null) // return; // // highlightRegion(viewer, region); // activateCursor(viewer); } /* * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent) */ public void keyReleased(KeyEvent event) { if (!fActive) { return; } deactivate(); } /* * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent) */ public void mouseDoubleClick(MouseEvent e) { } /* * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent) */ public void mouseDown(MouseEvent event) { if (!fActive) { return; } if (event.stateMask != fKeyModifierMask) { deactivate(); return; } if (event.button != 1) { deactivate(); return; } } /* * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent) */ public void mouseUp(MouseEvent e) { if (!fActive) { return; } if (e.button != 1) { deactivate(); return; } boolean wasActive = fCursor != null; if (wasActive) { IAction action = getAction("GotoDefinition"); //$NON-NLS-1$ if (action != null) { action.run(); // repairRepresentation(true); // getSourceViewer().invalidateTextPresentation(); } } deactivate(); } /* * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent) */ public void mouseMove(MouseEvent event) { if (event.widget instanceof Control && !((Control) event.widget).isFocusControl()) { deactivate(); return; } if (!fActive) { if (event.stateMask != fKeyModifierMask) { return; } // modifier was already pressed fActive = true; } ISourceViewer viewer = getSourceViewer(); if (viewer == null) { deactivate(); return; } StyledText text = viewer.getTextWidget(); if ((text == null) || text.isDisposed()) { deactivate(); return; } if (((event.stateMask & SWT.BUTTON1) != 0) && (text.getSelectionCount() != 0)) { deactivate(); return; } IRegion region = getCurrentTextRegion(viewer); if ((region == null) || (region.getLength() == 0)) { repairRepresentation(); getSourceViewer().invalidateTextPresentation(); return; } highlightRegion(viewer, region); activateCursor(viewer); } /* * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent) */ public void focusGained(FocusEvent e) { IFile file = ((IFileEditorInput) getEditorInput()).getFile(); try { // Automatically update the file in the editor if it has changed in the // filesystem file.refreshLocal(IResource.DEPTH_ZERO, null); } catch (CoreException e1) { // Just skip it. } } /* * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent) */ public void focusLost(FocusEvent event) { deactivate(); } /* * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent) */ public void documentAboutToBeChanged(DocumentEvent event) { if (fActive && (fActiveRegion != null)) { fRememberedPosition = new Position(fActiveRegion.getOffset(), fActiveRegion.getLength()); try { event.getDocument().addPosition(fRememberedPosition); } catch (BadLocationException x) { fRememberedPosition = null; } } } /* * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent) */ public void documentChanged(DocumentEvent event) { if ((fRememberedPosition != null) && !fRememberedPosition.isDeleted()) { event.getDocument().removePosition(fRememberedPosition); fActiveRegion = new Region(fRememberedPosition.getOffset(), fRememberedPosition.getLength()); } fRememberedPosition = null; ISourceViewer viewer = getSourceViewer(); if (viewer != null) { StyledText widget = viewer.getTextWidget(); if ((widget != null) && !widget.isDisposed()) { widget.getDisplay().asyncExec(new Runnable() { public void run() { deactivate(); } }); } } } /* * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, * org.eclipse.jface.text.IDocument) */ public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { if (oldInput == null) { return; } deactivate(); oldInput.removeDocumentListener(this); } /* * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, * org.eclipse.jface.text.IDocument) */ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { if (newInput == null) { return; } newInput.addDocumentListener(this); } /* * @see PaintListener#paintControl(PaintEvent) */ public void paintControl(PaintEvent event) { if (fActiveRegion == null) { return; } ISourceViewer viewer = getSourceViewer(); if (viewer == null) { return; } StyledText text = viewer.getTextWidget(); if ((text == null) || text.isDisposed()) { return; } int offset = 0; int length = 0; if (viewer instanceof ITextViewerExtension5) { ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; IRegion widgetRange = extension.modelRange2WidgetRange(new Region(offset, length)); if (widgetRange == null) { return; } offset = widgetRange.getOffset(); length = widgetRange.getLength(); } else { IRegion region = viewer.getVisibleRegion(); if (!includes(region, fActiveRegion)) { return; } offset = fActiveRegion.getOffset() - region.getOffset(); length = fActiveRegion.getLength(); } // support for bidi Point minLocation = getMinimumLocation(text, offset, length); Point maxLocation = getMaximumLocation(text, offset, length); int x1 = minLocation.x; int x2 = (minLocation.x + maxLocation.x) - minLocation.x - 1; int y = (minLocation.y + text.getLineHeight()) - 1; GC gc = event.gc; if ((fColor != null) && !fColor.isDisposed()) { gc.setForeground(fColor); } gc.drawLine(x1, y, x2, y); } private boolean includes(IRegion region, IRegion position) { return (position.getOffset() >= region.getOffset()) && ((position.getOffset() + position.getLength()) <= (region.getOffset() + region.getLength())); } private Point getMinimumLocation(StyledText text, int offset, int length) { Point minLocation = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); for (int i = 0; i <= length; i++) { Point location = text.getLocationAtOffset(offset + i); if (location.x < minLocation.x) { minLocation.x = location.x; } if (location.y < minLocation.y) { minLocation.y = location.y; } } return minLocation; } private Point getMaximumLocation(StyledText text, int offset, int length) { Point maxLocation = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE); for (int i = 0; i <= length; i++) { Point location = text.getLocationAtOffset(offset + i); if (location.x > maxLocation.x) { maxLocation.x = location.x; } if (location.y > maxLocation.y) { maxLocation.y = location.y; } } return maxLocation; } /* * (non-Javadoc) * * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent event) { // TODO Auto-generated method stub } } // folding // private RecipeOccurrencesUpdater fOccurrencesUpdater; /* * (non-Javadoc) * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createPartControl(org.eclipse.swt.widgets.Composite) */ public void createPartControl(Composite parent) { super.createPartControl(parent); ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer(); projectionSupport = new ProjectionSupport(projectionViewer, getAnnotationAccess(), getSharedColors()); projectionSupport.install(); projectionViewer.doOperation(ProjectionViewer.TOGGLE); // fOccurrencesUpdater= new RecipeOccurrencesUpdater(this); } protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { fAnnotationAccess = createAnnotationAccess(); fOverviewRuler = createOverviewRuler(getSharedColors()); ISourceViewer viewer = new ProjectionViewer(parent, ruler, fOverviewRuler, true, styles); // ensure decoration support has been created and configured: getSourceViewerDecorationSupport(viewer); return viewer; } public void fold(int foldingStart, int foldingEnd) { Position foldingPosition = new Position(foldingStart, foldingEnd - foldingStart); if (getSourceViewer().getAnnotationModel() != null) { getSourceViewer().getAnnotationModel().addAnnotation(new ProjectionAnnotation(), foldingPosition); } } public static IEditorPart openInEditor(IFile file) { if (file != null) { IWorkbenchPage p = VelocityPlugin.getActiveWorkbenchWindow().getActivePage(); if (p != null) { IEditorPart editorPart = null; try { editorPart = IDE.openEditor(p, file, true); } catch (PartInitException e) { // TODO Auto-generated catch block e.printStackTrace(); } // initializeHighlightRange(editorPart); return editorPart; } } return null; } }