org.jboss.tools.jst.jsp.jspeditor.info.JavaStringELInfoHover.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.jst.jsp.jspeditor.info.JavaStringELInfoHover.java

Source

/******************************************************************************* 
 * Copyright (c) 2010-2011 Red Hat, Inc. 
 * Distributed under license by Red Hat, Inc. All rights reserved. 
 * This program is 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: 
 * Red Hat, Inc. - initial API and implementation 
 ******************************************************************************/
package org.jboss.tools.jst.jsp.jspeditor.info;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.net.URL;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IOpenable;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.corext.javadoc.JavaDocLocations;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.text.FastJavaPartitionScanner;
import org.eclipse.jdt.internal.ui.text.JavaWordFinder;
import org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover;
import org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks;
import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.text.IJavaPartitions;
import org.eclipse.jface.internal.text.html.BrowserInformationControlInput;
import org.eclipse.jface.internal.text.html.HTMLPrinter;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.swt.graphics.FontData;
import org.jboss.tools.common.el.core.model.ELInvocationExpression;
import org.jboss.tools.common.el.core.model.ELModel;
import org.jboss.tools.common.el.core.model.ELUtil;
import org.jboss.tools.common.el.core.parser.ELParser;
import org.jboss.tools.common.el.core.parser.ELParserUtil;
import org.jboss.tools.common.el.core.resolver.ELContext;
import org.jboss.tools.common.el.core.resolver.ELResolution;
import org.jboss.tools.common.el.core.resolver.ELResolver;
import org.jboss.tools.common.el.core.resolver.ELSegment;
import org.jboss.tools.common.el.core.resolver.JavaMemberELSegmentImpl;
import org.jboss.tools.common.el.ui.ca.ELProposalProcessor;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.text.TextProposal;
import org.jboss.tools.common.util.StringUtil;
import org.jboss.tools.jst.jsp.JspEditorPlugin;
import org.jboss.tools.jst.jsp.contentassist.Utils;
import org.jboss.tools.jst.web.kb.KbQuery;
import org.jboss.tools.jst.web.kb.PageContextFactory;
import org.jboss.tools.jst.web.kb.PageProcessor;
import org.jboss.tools.jst.web.kb.KbQuery.Type;
import org.jboss.tools.jst.web.kb.el.MessagePropertyELSegmentImpl;
import org.osgi.framework.Bundle;

/**
 * 
 * @author Victor Rubezhny
 *
 */
@SuppressWarnings("restriction")
public class JavaStringELInfoHover extends JavadocHover {
    //   private IInformationControlCreator fPresenterControlCreator;

    /*
     * @see ITextHover#getHoverRegion(ITextViewer, int)
     */
    public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
        return JavaWordFinder.findWord(textViewer.getDocument(), offset);
    }

    /*
     * @see JavaElementHover
     */
    public String getHoverInfoDepracated(ITextViewer textViewer, IRegion region) {
        // find a region of __java_string, if we're in it - use it
        IDocument document = textViewer == null ? null : textViewer.getDocument();
        if (document == null)
            return null;

        int rangeStart = -1;
        int rangeLength = 0;
        IToken rangeToken = null;
        FastJavaPartitionScanner scanner = new FastJavaPartitionScanner();
        scanner.setRange(document, 0, document.getLength());
        while (true) {
            IToken token = scanner.nextToken();
            if (token == null || token.isEOF())
                break;
            int start = scanner.getTokenOffset();
            int length = scanner.getTokenLength();
            int end = start + length;
            if (start <= region.getOffset() && end >= region.getOffset()) {
                rangeStart = start;
                rangeLength = length;
                rangeToken = token;
                break;
            }
            if (start > region.getOffset())
                break;
        }

        if (rangeToken == null || rangeStart == -1 || rangeLength <= 0
                || !IJavaPartitions.JAVA_STRING.equals(rangeToken.getData()))
            return null;

        // OK. We've found JAVA_STRING token  
        // Check that the position is in the EL 
        if (!checkStartPosition(document, region.getOffset()))
            return null;

        // Calculate and prepare KB-query parameters
        String text = null;
        try {
            text = document.get(rangeStart, rangeLength);
        } catch (BadLocationException e) {
            JspEditorPlugin.getPluginLog().logError(e);
        }
        int inValueOffset = region.getOffset() - rangeStart;

        ELParser p = ELParserUtil.getJbossFactory().createParser();
        ELModel model = p.parse(text);

        ELInvocationExpression ie = ELUtil.findExpression(model, inValueOffset);// ELExpression
        if (ie == null)
            return null;

        String query = "#{" + ie.getText(); //$NON-NLS-1$

        KbQuery kbQuery = Utils.createKbQuery(Type.ATTRIBUTE_VALUE, region.getOffset() + region.getLength(), query,
                query, "", "", null, null, false); //$NON-NLS-1$ //$NON-NLS-2$

        ITypeRoot input = getEditorInputJavaElement();
        if (input == null)
            return null;

        IFile file = null;

        try {
            IResource resource = input.getCorrespondingResource();
            if (resource instanceof IFile)
                file = (IFile) resource;
        } catch (JavaModelException e) {
            // Ignore. It is probably because of Java element's resource is not found 
        }

        if (file == null) {
            return null;
        }

        ELContext context = PageContextFactory.createPageContext(file, JavaCore.JAVA_SOURCE_CONTENT_TYPE);

        TextProposal[] proposals = PageProcessor.getInstance().getProposals(kbQuery, context);
        if (proposals == null)
            return null;

        for (TextProposal proposal : proposals) {
            String label = proposal == null ? null : proposal.getLabel();
            label = (label == null || label.indexOf(':') == -1) ? label
                    : label.substring(0, label.indexOf(':')).trim();
            if (label != null && query.endsWith(label) && proposal != null && proposal.getContextInfo() != null
                    && proposal.getContextInfo().trim().length() > 0) {
                return proposal.getContextInfo();
            }
        }

        return null;
    }

    /*
    * @see org.eclipse.jface.text.ITextHoverExtension2#getHoverInfo2(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
    * @since 3.4
    */
    public Object getHoverInfo2(ITextViewer textViewer, IRegion region) {
        // find a region of __java_string, if we're in it - use it
        IDocument document = textViewer == null ? null : textViewer.getDocument();
        if (document == null)
            return null;

        int rangeStart = -1;
        int rangeLength = 0;
        IToken rangeToken = null;
        FastJavaPartitionScanner scanner = new FastJavaPartitionScanner();
        scanner.setRange(document, 0, document.getLength());
        while (true) {
            IToken token = scanner.nextToken();
            if (token == null || token.isEOF())
                break;
            int start = scanner.getTokenOffset();
            int length = scanner.getTokenLength();
            int end = start + length;
            if (start <= region.getOffset() && end >= region.getOffset()) {
                rangeStart = start;
                rangeLength = length;
                rangeToken = token;
                break;
            }
            if (start > region.getOffset())
                break;
        }

        if (rangeToken == null || rangeStart == -1 || rangeLength <= 0
                || !IJavaPartitions.JAVA_STRING.equals(rangeToken.getData()))
            return null;

        // OK. We've found JAVA_STRING token  
        // Check that the position is in the EL 
        if (!checkStartPosition(document, region.getOffset()))
            return null;

        // Calculate and prepare KB-query parameters
        String text = null;
        try {
            text = document.get(rangeStart, rangeLength);
        } catch (BadLocationException e) {
            JspEditorPlugin.getPluginLog().logError(e);
        }
        int inValueOffset = region.getOffset() - rangeStart;

        ELParser p = ELParserUtil.getJbossFactory().createParser();
        ELModel model = p.parse(text);

        ELInvocationExpression ie = ELUtil.findExpression(model, inValueOffset);// ELExpression
        if (ie == null)
            return null;

        ITypeRoot input = getEditorInputJavaElement();
        if (input == null)
            return null;

        IResource r = input.getResource();
        if (!(r instanceof IFile) || !r.exists() || r.getName().endsWith(".jar")) { //$NON-NLS-1$
            return null;
        }
        IFile file = (IFile) r;

        ELContext context = PageContextFactory.createPageContext(file, JavaCore.JAVA_SOURCE_CONTENT_TYPE);

        ELResolver[] resolvers = context.getElResolvers();

        for (int i = 0; resolvers != null && i < resolvers.length; i++) {
            ELResolution resolution = resolvers[i] == null ? null
                    : resolvers[i].resolve(context, ie, region.getOffset() + region.getLength());
            if (resolution == null)
                continue;

            ELSegment segment = resolution.getLastSegment();
            if (segment == null || !segment.isResolved())
                continue;

            if (segment instanceof JavaMemberELSegmentImpl) {
                JavaMemberELSegmentImpl jmSegment = (JavaMemberELSegmentImpl) segment;

                IJavaElement[] javaElements = jmSegment.getAllJavaElements();
                if (javaElements == null || javaElements.length == 0) {
                    if (jmSegment.getJavaElement() == null)
                        continue;

                    javaElements = new IJavaElement[] { jmSegment.getJavaElement() };
                }
                if (javaElements == null || javaElements.length == 0)
                    continue;

                return JavaStringELInfoHover.getHoverInfo2Internal(javaElements, true);
            } else if (segment instanceof MessagePropertyELSegmentImpl) {
                MessagePropertyELSegmentImpl mpSegment = (MessagePropertyELSegmentImpl) segment;
                String baseName = mpSegment.getBaseName();
                String propertyName = mpSegment.isBundle() ? null
                        : StringUtil.trimQuotes(segment.getToken().getText());
                String hoverText = ELProposalProcessor.getELMessagesHoverInternal(baseName, propertyName,
                        (List<XModelObject>) mpSegment.getObjects());
                StringBuffer buffer = new StringBuffer(hoverText);

                HTMLPrinter.insertPageProlog(buffer, 0, getStyleSheet());
                HTMLPrinter.addPageEpilog(buffer);

                return new ELInfoHoverBrowserInformationControlInput(null, new IJavaElement[0], buffer.toString(),
                        0);
            }
        }

        return null;
    }

    /*
     * Checks if the EL start starting characters are present
     * @param viewer
     * @param offset
     * @return
     * @throws BadLocationException
     */
    private boolean checkStartPosition(IDocument document, int offset) {
        try {
            while (--offset >= 0) {
                if ('}' == document.getChar(offset))
                    return false;

                if ('"' == document.getChar(offset) && (offset - 1) >= 0 && '\\' != document.getChar(offset - 1)) {
                    return false;
                }

                if ('{' == document.getChar(offset) && (offset - 1) >= 0
                        && ('#' == document.getChar(offset - 1) || '$' == document.getChar(offset - 1))) {
                    return true;
                }
            }
        } catch (BadLocationException e) {
            JspEditorPlugin.getPluginLog().logError(e);
        }
        return false;
    }

    public static ELInfoHoverBrowserInformationControlInput getHoverInfo2Internal(IJavaElement[] elements,
            boolean useFullHTML) {
        int nResults = elements.length;
        StringBuffer buffer = new StringBuffer();
        boolean hasContents = false;
        String base = null;
        IJavaElement element = null;

        int leadingImageWidth = 0;

        if (nResults > 1) {
            for (int i = 0; i < elements.length; i++) {
                if (useFullHTML) {
                    HTMLPrinter.startBulletList(buffer);
                }
                if (elements[i] == null)
                    continue;
                if (elements[i] instanceof IMember || elements[i].getElementType() == IJavaElement.LOCAL_VARIABLE
                        || elements[i].getElementType() == IJavaElement.TYPE_PARAMETER) {
                    if (useFullHTML) {
                        HTMLPrinter.addBullet(buffer, getInfoText(elements[i], false, useFullHTML));
                    } else {
                        buffer.append('\u002d').append(' ').append(getInfoText(elements[i], false, useFullHTML));
                    }
                    hasContents = true;
                }
                if (useFullHTML) {
                    HTMLPrinter.endBulletList(buffer);
                } else {
                    buffer.append("<br/>"); //$NON-NLS-1$
                }
            }

            for (int i = 0; i < elements.length; i++) {
                if (elements[i] == null)
                    continue;
                if (elements[i] instanceof IMember || elements[i].getElementType() == IJavaElement.LOCAL_VARIABLE
                        || elements[i].getElementType() == IJavaElement.TYPE_PARAMETER) {
                    if (!useFullHTML) {
                        buffer.append("<br/>"); //$NON-NLS-1$
                    }
                    base = addFullInfo(buffer, elements[i], useFullHTML);
                    hasContents = true;
                }
            }
        } else {
            element = elements[0];
            if (element instanceof IMember || element.getElementType() == IJavaElement.LOCAL_VARIABLE
                    || element.getElementType() == IJavaElement.TYPE_PARAMETER) {
                base = addFullInfo(buffer, element, useFullHTML);
                hasContents = true;
            }
            leadingImageWidth = 20;
        }

        if (!hasContents)
            return null;

        if (buffer.length() > 0) {
            HTMLPrinter.insertPageProlog(buffer, 0, useFullHTML ? getStyleSheet() : null);
            if (base != null) {
                int endHeadIdx = buffer.indexOf("</head>"); //$NON-NLS-1$
                if (endHeadIdx != -1) {
                    buffer.insert(endHeadIdx, "\n<base href='" + base + "'>\n"); //$NON-NLS-1$ //$NON-NLS-2$
                }
            }
            HTMLPrinter.addPageEpilog(buffer);

            return new ELInfoHoverBrowserInformationControlInput(null, elements, buffer.toString(),
                    leadingImageWidth);
        }

        return null;
    }

    /**
     * Adds full information to the hover
     * Returns base URL if exists
     * 
     * @param buffer
     * @param element
     * @return
     */
    private static String addFullInfo(StringBuffer buffer, IJavaElement element, boolean useFullHTML) {
        String base = null;

        if (element instanceof IMember) {
            IMember member = (IMember) element;
            HTMLPrinter.addSmallHeader(buffer, getInfoText(member, true, useFullHTML));
            Reader reader;
            try {
                String content = JavadocContentAccess2.getHTMLContent(member, true);
                reader = content == null ? null : new StringReader(content);

                // Provide hint why there's no Javadoc
                if (reader == null && member.isBinary()) {
                    boolean hasAttachedJavadoc = JavaDocLocations.getJavadocBaseLocation(member) != null;
                    IPackageFragmentRoot root = (IPackageFragmentRoot) member
                            .getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
                    boolean hasAttachedSource = root != null && root.getSourceAttachmentPath() != null;
                    IOpenable openable = member.getOpenable();
                    boolean hasSource = openable.getBuffer() != null;

                    if (!hasAttachedSource && !hasAttachedJavadoc)
                        reader = new StringReader(ELInfoHoverMessages.ELInfoHover_noAttachments);
                    else if (!hasAttachedJavadoc && !hasSource)
                        reader = new StringReader(ELInfoHoverMessages.ELInfoHover_noAttachedJavadoc);
                    else if (!hasAttachedSource)
                        reader = new StringReader(ELInfoHoverMessages.ELInfoHover_noAttachedJavaSource);
                    else if (!hasSource)
                        reader = new StringReader(ELInfoHoverMessages.ELInfoHover_noInformation);

                } else {
                    base = JavaDocLocations.getBaseURL(member);
                }

            } catch (JavaModelException ex) {
                reader = new StringReader(ELInfoHoverMessages.ELInfoHover_error_gettingJavadoc);
                JavaPlugin.log(ex);
            }

            if (reader != null) {
                HTMLPrinter.addParagraph(buffer, reader);
            }

        } else if (element.getElementType() == IJavaElement.LOCAL_VARIABLE
                || element.getElementType() == IJavaElement.TYPE_PARAMETER) {
            HTMLPrinter.addSmallHeader(buffer, getInfoText(element, true, useFullHTML));
        }
        return base;
    }

    private static final long LABEL_FLAGS = JavaElementLabels.ALL_FULLY_QUALIFIED
            | JavaElementLabels.M_PRE_RETURNTYPE | JavaElementLabels.M_PARAMETER_TYPES
            | JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_EXCEPTIONS
            | JavaElementLabels.F_PRE_TYPE_SIGNATURE | JavaElementLabels.M_PRE_TYPE_PARAMETERS
            | JavaElementLabels.T_TYPE_PARAMETERS | JavaElementLabels.USE_RESOLVED;
    private static final long LOCAL_VARIABLE_FLAGS = LABEL_FLAGS & ~JavaElementLabels.F_FULLY_QUALIFIED
            | JavaElementLabels.F_POST_QUALIFIED;
    private static final long TYPE_PARAMETER_FLAGS = LABEL_FLAGS | JavaElementLabels.TP_POST_QUALIFIED;

    private static String getInfoText(IJavaElement element, boolean allowImage, boolean useFullHTML) {
        long flags;
        switch (element.getElementType()) {
        case IJavaElement.LOCAL_VARIABLE:
            flags = LOCAL_VARIABLE_FLAGS;
            break;
        case IJavaElement.TYPE_PARAMETER:
            flags = TYPE_PARAMETER_FLAGS;
            break;
        default:
            flags = LABEL_FLAGS;
            break;
        }
        StringBuffer label = new StringBuffer(JavaElementLinks.getElementLabel(element, flags));

        String imageName = null;
        if (allowImage) {
            URL imageUrl = JavaPlugin.getDefault().getImagesOnFSRegistry().getImageURL(element);
            if (imageUrl != null) {
                imageName = imageUrl.toExternalForm();
            }
        }

        StringBuffer buf = new StringBuffer();
        addImageAndLabel(buf, imageName, 16, 16, 2, 2, label.toString(), 2, 2, useFullHTML);
        return buf.toString();
    }

    /**
     * The style sheet (css).
     * @since 3.4
     */
    private static String fgStyleSheet;

    /**
     * Returns the Javadoc hover style sheet with the current Javadoc font from the preferences.
     * @return the updated style sheet
     * @since 3.4
     */
    private static String getStyleSheet() {
        if (fgStyleSheet == null)
            fgStyleSheet = loadStyleSheet();
        String css = fgStyleSheet;
        if (css != null) {
            FontData fontData = JFaceResources.getFontRegistry()
                    .getFontData(PreferenceConstants.APPEARANCE_JAVADOC_FONT)[0];
            css = HTMLPrinter.convertTopLevelFont(css, fontData);
        }

        return css;
    }

    /**
     * Loads and returns the Javadoc hover style sheet.
     * @return the style sheet, or <code>null</code> if unable to load
     * @since 3.4
     */
    private static String loadStyleSheet() {
        Bundle bundle = Platform.getBundle(JavaPlugin.getPluginId());
        URL styleSheetURL = bundle.getEntry("/JavadocHoverStyleSheet.css"); //$NON-NLS-1$
        if (styleSheetURL != null) {
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new InputStreamReader(styleSheetURL.openStream()));
                StringBuffer buffer = new StringBuffer(1500);
                String line = reader.readLine();
                while (line != null) {
                    buffer.append(line);
                    buffer.append('\n');
                    line = reader.readLine();
                }
                return buffer.toString();
            } catch (IOException ex) {
                JavaPlugin.log(ex);
                return ""; //$NON-NLS-1$
            } finally {
                try {
                    if (reader != null)
                        reader.close();
                } catch (IOException e) {
                }
            }
        }
        return null;
    }

    public static void addImageAndLabel(StringBuffer buf, String imageName, int imageWidth, int imageHeight,
            int imageLeft, int imageTop, String label, int labelLeft, int labelTop, boolean useFullHTML) {

        if (imageName != null) {
            StringBuffer imageStyle = new StringBuffer("position: relative; "); //$NON-NLS-1$
            imageStyle.append("width: ").append(imageWidth).append("px; "); //$NON-NLS-1$ //$NON-NLS-2$
            imageStyle.append("height: ").append(imageHeight).append("px; "); //$NON-NLS-1$ //$NON-NLS-2$
            if (imageTop != -1)
                imageStyle.append("top: ").append(imageTop).append("px; "); //$NON-NLS-1$ //$NON-NLS-2$
            if (imageLeft != -1)
                imageStyle.append("left: ").append(imageLeft).append("px; "); //$NON-NLS-1$ //$NON-NLS-2$

            if (useFullHTML) {
                buf.append("<!--[if lte IE 6]><![if gte IE 5.5]>\n"); //$NON-NLS-1$
                buf.append("<span style=\"").append(imageStyle) //$NON-NLS-1$
                        .append("filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='").append(imageName) //$NON-NLS-1$
                        .append("')\">\n"); //$NON-NLS-1$
                buf.append("<![endif]><![endif]-->\n"); //$NON-NLS-1$

                buf.append("<!--[if !IE]>-->\n"); //$NON-NLS-1$
                buf.append("<img style='").append(imageStyle).append("' src='").append(imageName).append("'>\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                buf.append("<!--<![endif]-->\n"); //$NON-NLS-1$
                buf.append("<!--[if gte IE 7]>\n"); //$NON-NLS-1$
                buf.append("<img style='").append(imageStyle).append("' src='").append(imageName).append("'>\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                buf.append("<![endif]-->\n"); //$NON-NLS-1$
            } else {
                buf.append("<img style='").append(imageStyle).append("' src='").append(imageName).append("'>\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            }
        }

        buf.append("<span style='word-wrap:break-word;"); //$NON-NLS-1$
        if (imageName != null) {
            buf.append("margin-left: ").append(labelLeft).append("px; "); //$NON-NLS-1$ //$NON-NLS-2$
            buf.append("margin-top: ").append(labelTop).append("px; "); //$NON-NLS-1$ //$NON-NLS-2$
        }
        buf.append("'>"); //$NON-NLS-1$
        buf.append(label);
        buf.append("</span>"); //$NON-NLS-1$
        if (imageName != null) {
            buf.append("</span>"); //$NON-NLS-1$
        }
    }

}

@SuppressWarnings("restriction")
class ELInfoHoverBrowserInformationControlInput extends BrowserInformationControlInput {
    private final IJavaElement[] fElements;
    private final String fHtml;
    private final int fLeadingImageWidth;

    /**
     * Creates a new browser information control input.
     *
     * @param previous previous input, or <code>null</code> if none available
     * @param element the element, or <code>null</code> if none available
     * @param html HTML contents, must not be null
     * @param leadingImageWidth the indent required for the element image
     */
    public ELInfoHoverBrowserInformationControlInput(BrowserInformationControlInput previous,
            IJavaElement[] elements, String html, int leadingImageWidth) {
        super(previous);
        Assert.isNotNull(html);
        fElements = elements;
        fHtml = html;
        fLeadingImageWidth = leadingImageWidth;
    }

    /*
     * @see org.eclipse.jface.internal.text.html.BrowserInformationControlInput#getLeadingImageWidth()
     * @since 3.4
     */
    public int getLeadingImageWidth() {
        return fLeadingImageWidth;
    }

    /**
     * Returns the Java element.
     *
     * @return the element or <code>null</code> if none available
     */
    public IJavaElement[] getElements() {
        return fElements;
    }

    /*
     * @see org.eclipse.jface.internal.text.html.BrowserInput#getHtml()
     */
    public String getHtml() {
        return fHtml;
    }

    @Override
    public Object getInputElement() {
        return fElements == null ? (Object) fHtml : fElements;
    }

    private String fInputName = null;

    @Override
    public String getInputName() {
        if (fInputName != null)
            return fInputName;

        String inputName = ""; //$NON-NLS-1$
        for (int i = 0; fElements != null && i < fElements.length; i++) {
            if (i > 0 && inputName.trim().length() > 0)
                inputName += " & "; //$NON-NLS-1$
            inputName += fElements[i].getElementName();
        }
        fInputName = inputName;

        return fInputName;
    }

}