/*******************************************************************************
* 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;
}
}