package at.bestsolution.efxclipse.tooling.fxml.editors; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextHover; import org.eclipse.jface.text.ITextHoverExtension; import org.eclipse.jface.text.ITextHoverExtension2; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Region; import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext; import org.eclipse.wst.xml.ui.internal.Logger; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import at.bestsolution.efxclipse.tooling.fxml.editors.FXMLCompletionProposalComputer.JavadocHoverWrapper; import at.bestsolution.efxclipse.tooling.model.FXPlugin; import at.bestsolution.efxclipse.tooling.model.IFXClass; import at.bestsolution.efxclipse.tooling.model.IFXEnumProperty; import at.bestsolution.efxclipse.tooling.model.IFXProperty; @SuppressWarnings("restriction") public class FXMLTextHover implements ITextHover, ITextHoverExtension, ITextHoverExtension2 { private JavadocHoverWrapper javadocWrapper = new JavadocHoverWrapper(); private IJavaElement element; @Override public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) { Object o = getHoverInfo2(textViewer, hoverRegion); return o != null ? o.toString() : null; } @Override public IRegion getHoverRegion(ITextViewer textViewer, int offset) { if ((textViewer == null) || (textViewer.getDocument() == null)) { return null; } IStructuredDocumentRegion flatNode = ((IStructuredDocument) textViewer.getDocument()).getRegionAtCharacterOffset(offset); ITextRegion region = null; if (flatNode != null) { region = flatNode.getRegionAtCharacterOffset(offset); } if (region != null) { // only supply hoverhelp for tag name, attribute name, or // attribute value String regionType = region.getType(); if ((regionType == DOMRegionContext.XML_TAG_NAME) || (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) || (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)) { try { // check if we are at whitespace before or after line IRegion line = textViewer.getDocument().getLineInformationOfOffset(offset); if ((offset > (line.getOffset())) && (offset < (line.getOffset() + line.getLength()))) { // check if we are in region's trailing whitespace // (whitespace after relevant info) if (offset < flatNode.getTextEndOffset(region)) { return new Region(flatNode.getStartOffset(region), region.getTextLength()); } } } catch (BadLocationException e) { Logger.logException(e); } } } return null; } private IJavaElement computeTagNameHelp(IDOMNode xmlnode, IDOMNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region) { if( Character.isLowerCase(xmlnode.getNodeName().charAt(0)) ) { Node parent = xmlnode.getParentNode(); IType ownerType = Util.findType(parent.getNodeName(), parent.getOwnerDocument()); if( ownerType != null ) { IFXClass fxClass = FXPlugin.getClassmodel().findClass(ownerType.getJavaProject(), ownerType); if( fxClass != null ) { IFXProperty p = fxClass.getProperty(xmlnode.getNodeName()); if( p != null ) { return p.getJavaElement(); } } } } else { if( xmlnode.getNodeName().contains(".") ) { String[] parts = xmlnode.getNodeName().split("\\."); IType ownerType = Util.findType(parts[0], xmlnode.getOwnerDocument()); if( ownerType != null ) { IFXClass fxClass = FXPlugin.getClassmodel().findClass(ownerType.getJavaProject(), ownerType); if( fxClass != null ) { IFXProperty p = fxClass.getStaticProperty(parts[1]); if( p != null ) { return p.getJavaElement(); } } } } else { IType ownerType = Util.findType(xmlnode.getNodeName(), xmlnode.getOwnerDocument()); if( ownerType != null ) { IFXClass fxClass = FXPlugin.getClassmodel().findClass(ownerType.getJavaProject(), ownerType); if( fxClass != null ) { try { return Util.findProject(xmlnode.getOwnerDocument()).findType(fxClass.getFQN()); } catch (JavaModelException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } return null; } private IJavaElement computeTagAttNameHelp(IDOMNode xmlnode, IDOMNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region, int offset) { NamedNodeMap m = xmlnode.getAttributes(); IDOMNode attribute = null; if( m != null ) { for( int i = 0; i < m.getLength(); i++ ) { IDOMNode a = (IDOMNode) m.item(i); if( a.contains(offset) ) { attribute = a; } } } if( attribute != null ) { Node parent = xmlnode; if( attribute.getNodeName().contains(".") ) { String[] parts = attribute.getNodeName().split("\\."); IType ownerType = Util.findType(parts[0], parent.getOwnerDocument()); if( ownerType != null ) { IFXClass fxClass = FXPlugin.getClassmodel().findClass(ownerType.getJavaProject(), ownerType); if( fxClass != null ) { IFXProperty p = fxClass.getStaticProperty(parts[1]); if( p != null ) { return p.getJavaElement(); } } } } else { IType ownerType = Util.findType(parent.getNodeName(), parent.getOwnerDocument()); if( ownerType != null ) { IFXClass fxClass = FXPlugin.getClassmodel().findClass(ownerType.getJavaProject(), ownerType); if( fxClass != null ) { IFXProperty p = fxClass.getProperty(attribute.getNodeName()); if( p != null ) { return p.getJavaElement(); } } } } } return null; } private IJavaElement computeTagAttValueHelp(IDOMNode xmlnode, IDOMNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region, int offset) { NamedNodeMap m = xmlnode.getAttributes(); IDOMNode attribute = null; for( int i = 0; i < m.getLength(); i++ ) { IDOMNode a = (IDOMNode) m.item(i); if( a.contains(offset) ) { attribute = a; } } if( attribute != null ) { Node parent = xmlnode; IFXProperty p = null; if( attribute.getNodeName().contains(".") ) { String[] parts = attribute.getNodeName().split("\\."); IType ownerType = Util.findType(parts[0], parent.getOwnerDocument()); if( ownerType != null ) { IFXClass fxClass = FXPlugin.getClassmodel().findClass(ownerType.getJavaProject(), ownerType); if( fxClass != null ) { p = fxClass.getStaticProperty(parts[1]); } } } else { IType ownerType = Util.findType(parent.getNodeName(), parent.getOwnerDocument()); if( ownerType != null ) { IFXClass fxClass = FXPlugin.getClassmodel().findClass(ownerType.getJavaProject(), ownerType); if( fxClass != null ) { p = fxClass.getProperty(attribute.getNodeName()); } } } if( p instanceof IFXEnumProperty ) { IType t = ((IFXEnumProperty) p).getEnumType(); try { for (IField f : t.getFields()) { if (Flags.isEnum(f.getFlags())) { if( f.getElementName().equals(attribute.getNodeValue()) ) { return f; } } } } catch (JavaModelException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return null; } @Override public IInformationControlCreator getHoverControlCreator() { // System.err.println("getHoverControlCreator(): " + element); if( element != null ) { javadocWrapper.setJavaElement(element); return javadocWrapper.getHoverControlCreator(); } return null; } @Override public Object getHoverInfo2(ITextViewer textViewer, IRegion hoverRegion) { System.err.println("getHoverInfo2()"); if ((hoverRegion == null) || (textViewer == null) || (textViewer.getDocument() == null)) { return null; } element = null; int documentOffset = hoverRegion.getOffset(); IndexedRegion treeNode = ContentAssistUtils.getNodeAt(textViewer, documentOffset); if (treeNode == null) { return null; } Node node = (Node) treeNode; while ((node != null) && (node.getNodeType() == Node.TEXT_NODE) && (node.getParentNode() != null)) { node = node.getParentNode(); } IDOMNode parentNode = (IDOMNode) node; IStructuredDocumentRegion flatNode = ((IStructuredDocument) textViewer.getDocument()).getRegionAtCharacterOffset(documentOffset); if (flatNode != null) { ITextRegion region = flatNode.getRegionAtCharacterOffset(documentOffset); if (region != null) { String regionType = region.getType(); if (regionType == DOMRegionContext.XML_TAG_NAME) { element = computeTagNameHelp((IDOMNode) treeNode, parentNode, flatNode, region); } else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) { element = computeTagAttNameHelp((IDOMNode) treeNode, parentNode, flatNode, region, documentOffset); } else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) { element = computeTagAttValueHelp((IDOMNode) treeNode, parentNode, flatNode, region, documentOffset); } } } if( element != null ) { javadocWrapper.setJavaElement(element); return javadocWrapper.getHoverInfo2(textViewer, hoverRegion); } return null; } }