package com.framsticks.framclipse.editors.hover; import java.util.List; import org.eclipse.jface.internal.text.html.BrowserInformationControl; import org.eclipse.jface.internal.text.html.HTMLTextPresenter; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.AbstractReusableInformationControlCreator; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.IInformationControlExtension4; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextHover; import org.eclipse.jface.text.ITextHoverExtension; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.information.IInformationProviderExtension2; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.editors.text.EditorsUI; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.xpath.XPath; import com.framsticks.framclipse.Framclipse; import com.framsticks.framclipse.editors.codeCompletion.SyntaxUtils; public class FramscriptTextHover implements ITextHover, ITextHoverExtension, IInformationProviderExtension2 { private static final class PresenterControlCreator extends AbstractReusableInformationControlCreator { public IInformationControl doCreateInformationControl(Shell parent) { // int shellStyle= SWT.RESIZE | SWT.TOOL; // int style= SWT.V_SCROLL | SWT.H_SCROLL; // if (BrowserInformationControl.isAvailable(parent)) { // return new BrowserInformationControl(parent, JFaceResources.DIALOG_FONT, true); // return new BrowserInformationControl(parent, shellStyle, style); // } else // return new DefaultInformationControl(parent, shellStyle, style, new HTMLTextPresenter(false)); return new DefaultInformationControl(parent, true); } } private static final class HoverControlCreator extends AbstractReusableInformationControlCreator { public IInformationControl doCreateInformationControl(Shell parent) { // if (BrowserInformationControl.isAvailable(parent)) { // return new BrowserInformationControl(parent, JFaceResources.DIALOG_FONT, true); // return new BrowserInformationControl(parent, SWT.TOOL | SWT.NO_TRIM, SWT.NONE, EditorsUI.getTooltipAffordanceString()); // } else { // return new DefaultInformationControl(parent, SWT.NONE, new HTMLTextPresenter(true), EditorsUI.getTooltipAffordanceString()); return new DefaultInformationControl(parent, true); // } } /* * @see org.eclipse.jdt.internal.ui.text.java.hover.AbstractReusableInformationControlCreator#canReuse(org.eclipse.jface.text.IInformationControl) */ public boolean canReuse(IInformationControl control) { if (!super.canReuse(control)) return false; if (control instanceof IInformationControlExtension4) ((IInformationControlExtension4)control).setStatusText(EditorsUI.getTooltipAffordanceString()); return true; } } private static final int DESCRIPTION_LENGTH = 60; private IInformationControlCreator fHoverControlCreator; private IInformationControlCreator fPresenterControlCreator; public IInformationControlCreator getInformationPresenterControlCreator() { if (fPresenterControlCreator == null) fPresenterControlCreator= new PresenterControlCreator(); return fPresenterControlCreator; } public IInformationControlCreator getHoverControlCreator() { if (fHoverControlCreator == null) fHoverControlCreator= new HoverControlCreator(); return fHoverControlCreator; } public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) { int offset = hoverRegion.getOffset() + hoverRegion.getLength(); IDocument document = textViewer.getDocument(); List elements = SyntaxUtils.getElementsAt(document, offset); if (elements.size() == 0) { return null; } String name = elements.remove(elements.size() - 1); String elementFormat = "%s[@" + SyntaxUtils.NAME_ATTRIBUTE + "='%s']/"; String query = SyntaxUtils.ROOT + "/"; if (elements.size() == 0) { query += String.format(elementFormat, SyntaxUtils.TYPE_ELEMENT, name); } else { // elements.size() > 1 String parent; try { parent = SyntaxUtils.getLastElementType(elements); } catch (JDOMException e) { e.printStackTrace(); return null; } query += String.format(elementFormat, SyntaxUtils.TYPE_ELEMENT, parent) + String.format(elementFormat, SyntaxUtils.ELEMENT_ELEMENT, name); } query += SyntaxUtils.DESCRIPTION_ELEMENT; Document syntax = Framclipse.getDefault().getFramscriptSyntax(); try { XPath xpath = XPath.newInstance(query); Element element = (Element) xpath.selectSingleNode(syntax); if (element == null) { return null; } return formatDescription(element.getValue()); } catch (Exception e) { e.printStackTrace(); } return null; } public IRegion getHoverRegion(ITextViewer textViewer, int offset) { IDocument document = textViewer.getDocument(); String after = SyntaxUtils.getElementAfter(document, offset); int line = 0; try { line = document.getLineOfOffset(offset); } catch (BadLocationException e) { e.printStackTrace(); } int lineStart = offset; try { lineStart = document.getLineInformation(line).getOffset(); } catch (BadLocationException e) { e.printStackTrace(); } IRegion region = new Region(lineStart, offset + after.length() - lineStart); return region; } private static String formatDescription(String description) { String result = ""; int offset = 0; while (offset < description.length()) { int length = DESCRIPTION_LENGTH; if (offset + length > description.length()) { result += description.substring(offset); return result; } for (int i = length; i > 0; i--) { if (Character.isWhitespace(description.charAt(offset + i))) { length = i; i = 0; } } result += description.substring(offset, offset + length) + "\n"; offset += length + 1; } return result; } }