/******************************************************************************* * Copyright (c) 2007, 2015 David Green and others. * 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: * David Green - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.wikitext.ui.util; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.text.AbstractInformationControlManager; import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.DefaultInformationControl.IInformationPresenter; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.information.IInformationProvider; import org.eclipse.jface.text.information.IInformationProviderExtension; import org.eclipse.jface.text.information.IInformationProviderExtension2; import org.eclipse.jface.text.information.InformationPresenter; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.mylyn.internal.wikitext.ui.editor.syntax.FastMarkupPartitioner; import org.eclipse.mylyn.wikitext.ui.viewer.HtmlTextPresenter; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; /** * @author David Green */ public class InformationPresenterUtil { /** * @see InformationPresenter#setSizeConstraints(int, int, boolean, boolean) */ public static class SizeConstraint { int horizontalWidthInChars; int verticalWidthInChars; boolean enforceAsMinimumSize; boolean enforceAsMaximumSize; /** * @see InformationPresenter#setSizeConstraints(int, int, boolean, boolean) */ public SizeConstraint(int horizontalWidthInChars, int verticalWidthInChars, boolean enforceAsMinimumSize, boolean enforceAsMaximumSize) { super(); this.horizontalWidthInChars = horizontalWidthInChars; this.verticalWidthInChars = verticalWidthInChars; this.enforceAsMinimumSize = enforceAsMinimumSize; this.enforceAsMaximumSize = enforceAsMaximumSize; } } @SuppressWarnings("deprecation") private static final class InformationProvider implements IInformationProvider, IInformationProviderExtension, IInformationProviderExtension2 { private final IRegion hoverRegion; private final Object hoverInfo; private final IInformationControlCreator controlCreator; InformationProvider(IRegion hoverRegion, Object info, IInformationControlCreator controlCreator) { this.hoverRegion = hoverRegion; this.hoverInfo = info; this.controlCreator = controlCreator; } public IRegion getSubject(ITextViewer textViewer, int invocationOffset) { return hoverRegion; } public String getInformation(ITextViewer textViewer, IRegion subject) { return hoverInfo.toString(); } public Object getInformation2(ITextViewer textViewer, IRegion subject) { return hoverInfo; } public IInformationControlCreator getInformationPresenterControlCreator() { return controlCreator; } } private static final String DATA_INFORMATION_PRESENTER = InformationPresenterUtil.class.getName() + "#informationPresenter"; //$NON-NLS-1$ private static final String DATA_INFORMATION_CONTROL_CREATOR = InformationPresenterUtil.class.getName() + "#informationControlCreator"; //$NON-NLS-1$ /** * Get an information presenter to present the provided HTML content. The returned presenter is ready for displaying * the information, all that is left to do is call {@link InformationPresenter#showInformation()}. * * @param viewer * the viewer for which the information control should be created * @param constraint * the size constraint * @param toolBarManager * the tool bar manager, or null if there should be none * @param htmlContent * the HTML content to be displayed by the information presenter. * @return the presenter */ public static InformationPresenter getHtmlInformationPresenter(ISourceViewer viewer, SizeConstraint constraint, final ToolBarManager toolBarManager, String htmlContent) { Control control = viewer.getTextWidget(); InformationPresenter presenter = (InformationPresenter) control.getData(DATA_INFORMATION_PRESENTER); // bug 270059: ensure that the size/positioning math works by specifying the offet of the // current selection. int offset = viewer.getSelectedRange().x; IInformationControlCreator informationControlCreator; if (presenter == null) { informationControlCreator = new IInformationControlCreator() { @SuppressWarnings("deprecation") public IInformationControl createInformationControl(Shell shell) { try { // try reflection to access 3.4 APIs // DefaultInformationControl(Shell parent, ToolBarManager toolBarManager, IInformationPresenter presenter); return DefaultInformationControl.class.getConstructor(Shell.class, ToolBarManager.class, IInformationPresenter.class) .newInstance(shell, toolBarManager, new HtmlTextPresenter()); } catch (NoSuchMethodException e) { // no way with 3.3 to get V_SCROLL and a ToolBarManager return new DefaultInformationControl(shell, SWT.RESIZE, SWT.V_SCROLL | SWT.H_SCROLL, new HtmlTextPresenter()); } catch (Exception e) { throw new IllegalStateException(e); } } }; presenter = new InformationPresenter(informationControlCreator) { @Override public IInformationProvider getInformationProvider(String contentType) { IInformationProvider informationProvider = super.getInformationProvider(contentType); if (informationProvider == null) { informationProvider = super.getInformationProvider(IDocument.DEFAULT_CONTENT_TYPE); } return informationProvider; } }; presenter.install(viewer); presenter.setAnchor(AbstractInformationControlManager.ANCHOR_BOTTOM); presenter.setMargins(6, 6); // default values from AbstractInformationControlManager presenter.setOffset(offset); presenter.install(viewer); final InformationPresenter informationPresenter = presenter; viewer.getTextWidget().addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { try { informationPresenter.uninstall(); } catch (Exception e2) { } informationPresenter.dispose(); } }); control.setData(DATA_INFORMATION_PRESENTER, presenter); control.setData(DATA_INFORMATION_CONTROL_CREATOR, informationControlCreator); } else { informationControlCreator = (IInformationControlCreator) control.getData(DATA_INFORMATION_CONTROL_CREATOR); presenter.disposeInformationControl(); } presenter.setSizeConstraints(constraint.horizontalWidthInChars, constraint.verticalWidthInChars, constraint.enforceAsMinimumSize, constraint.enforceAsMaximumSize); InformationProvider informationProvider = new InformationProvider(new org.eclipse.jface.text.Region(offset, 0), htmlContent, informationControlCreator); for (String contentType : FastMarkupPartitioner.ALL_CONTENT_TYPES) { presenter.setInformationProvider(informationProvider, contentType); } presenter.setInformationProvider(informationProvider, IDocument.DEFAULT_CONTENT_TYPE); return presenter; } }