/** * Copyright (c) 2013-2016 Angelo ZERR. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation */ package org.eclipse.wst.json.ui.internal.text.hover; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextHoverExtension2; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.information.IInformationProviderExtension2; import org.eclipse.wst.json.core.document.IJSONNode; import org.eclipse.wst.json.core.document.IJSONPair; import org.eclipse.wst.json.core.document.IJSONValue; import org.eclipse.wst.json.core.regions.JSONRegionContexts; import org.eclipse.wst.json.core.util.JSONUtil; import org.eclipse.wst.json.ui.internal.Logger; import org.eclipse.wst.json.ui.internal.text.JSONBrowserInformationControlInput; import org.eclipse.wst.json.ui.internal.text.JSONHoverControlCreator; import org.eclipse.wst.json.ui.internal.text.JSONPresenterControlCreator; 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.sse.ui.internal.taginfo.AbstractHoverProcessor; /** * Text hover processor for JSON. * */ public class JSONHoverProcessor extends AbstractHoverProcessor implements ITextHoverExtension2, IInformationProviderExtension2 { private IInformationControlCreator hoverControlCreator; private IInformationControlCreator presenterControlCreator; @Override public String getHoverInfo(ITextViewer viewer, IRegion hoverRegion) { JSONBrowserInformationControlInput info = (JSONBrowserInformationControlInput) getHoverInfo2( viewer, hoverRegion); return info != null ? info.getHtml() : null; } @Override public Object getHoverInfo2(ITextViewer viewer, IRegion hoverRegion) { if ((hoverRegion == null) || (viewer == null) || (viewer.getDocument() == null)) { return null; } int documentOffset = hoverRegion.getOffset(); String html = computeHoverHelp(viewer, documentOffset); if (html != null) { return new JSONBrowserInformationControlInput(null, html, 20); } return 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 object key, or simple JSON value String regionType = region.getType(); if ((regionType == JSONRegionContexts.JSON_OBJECT_KEY) || JSONUtil.isJSONSimpleValue(regionType)) { 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; } /** * Retrieves documentation to display in the hover help popup. * * @return String any documentation information to display <code>null</code> * if there is nothing to display. * */ protected String computeHoverHelp(ITextViewer textViewer, int documentPosition) { String result = null; IndexedRegion treeNode = ContentAssistUtils.getNodeAt(textViewer, documentPosition); if (treeNode == null) { return null; } IJSONNode node = (IJSONNode) treeNode; IJSONNode parentNode = node.getParentNode(); IStructuredDocumentRegion flatNode = ((IStructuredDocument) textViewer .getDocument()).getRegionAtCharacterOffset(documentPosition); if (flatNode != null) { ITextRegion region = flatNode .getRegionAtCharacterOffset(documentPosition); if (region != null) { result = computeRegionHelp(treeNode, parentNode, flatNode, region); } } return result; } /** * Computes the hoverhelp based on region * * @return String hoverhelp */ protected String computeRegionHelp(IndexedRegion treeNode, IJSONNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region) { if (region == null) { return null; } String regionType = region.getType(); if (treeNode instanceof IJSONPair && regionType == JSONRegionContexts.JSON_OBJECT_KEY) { return computeObjectKeyHelp((IJSONPair) treeNode, parentNode, flatNode, region); } if (treeNode instanceof IJSONValue && JSONUtil.isJSONSimpleValue(regionType)) { return computeValueHelp((IJSONValue) treeNode, parentNode, flatNode, region); } return null; } protected String computeObjectKeyHelp(IJSONPair treeNode, IJSONNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region) { return HTMLJSONPrinter.getAdditionalProposalInfo(treeNode); } protected String computeValueHelp(IJSONValue treeNode, IJSONNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region) { return HTMLJSONPrinter.getAdditionalProposalInfo(treeNode); } @Override public IInformationControlCreator getHoverControlCreator() { if (hoverControlCreator == null) hoverControlCreator = new JSONHoverControlCreator( getInformationPresenterControlCreator()); return hoverControlCreator; } @Override public IInformationControlCreator getInformationPresenterControlCreator() { if (presenterControlCreator == null) presenterControlCreator = new JSONPresenterControlCreator(); return presenterControlCreator; } }