/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.ui.editors.sql.util;
import org.jkiss.dbeaver.Log;
import org.eclipse.jface.text.*;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationHover;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.ITextEditor;
import org.jkiss.dbeaver.ui.editors.sql.SQLEditorBase;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* SQLAnnotationHover
*/
public class SQLAnnotationHover extends AbstractSQLEditorTextHover
implements ITextHover, IAnnotationHover, ITextHoverExtension, ITextHoverExtension2
{
private static final Log log = Log.getLog(SQLAnnotationHover.class);
private List<Annotation> annotations = new ArrayList<>();
private SQLEditorBase editor;
private IHyperlinkDetector[] hyperlinkDetectors;
public SQLAnnotationHover(SQLEditorBase editor)
{
setEditor(editor);
}
/**
* Returns the information which should be presented when a hover popup is shown for the specified hover region. The
* hover region has the same semantics as the region returned by <code>getHoverRegion</code>. If the returned
* information is <code>null</code> or empty no hover popup will be shown.
*
* @deprecated
* @param textViewer the viewer on which the hover popup should be shown
* @param hoverRegion the text range in the viewer which is used to determine the hover display information
* @return the hover popup display information
*/
@Override
public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion)
{
Object hoverInfo2 = getHoverInfo2(textViewer, hoverRegion);
return hoverInfo2 == null ? null : hoverInfo2.toString();
}
@Override
public Object getHoverInfo2(ITextViewer textViewer, IRegion hoverRegion)
{
if (hyperlinkDetectors == null) {
hyperlinkDetectors = editor.getViewerConfiguration().getHyperlinkDetectors(editor.getViewer());
}
/*
IAnnotationModel model = textViewer instanceof ISourceViewer ? ((ISourceViewer) textViewer).getAnnotationModel() : null;
//avoids finding annotations again
if (annotations.size() == 0) {
findAnnotations(hoverRegion.getOffset(), model, null, 0);
}
*/
/*
for (IHyperlinkDetector hyperlinkDetector : hyperlinkDetectors) {
IHyperlink[] hyperlinks = hyperlinkDetector.detectHyperlinks(textViewer, hoverRegion, false);
if (!CommonUtils.isEmpty(hyperlinks)) {
return hyperlinks[0];
}
}
*/
return null;
}
/**
* Returns the text region which should serve as the source of information to compute the hover popup display
* information. The popup has been requested for the given offset.
* <p/>
* For example, if hover information can be provided on a per method basis in a source viewer, the offset should be
* used to find the enclosing method and the source range of the method should be returned.
*
* @param textViewer the viewer on which the hover popup should be shown
* @param offset the offset for which the hover request has been issued
* @return the hover region used to compute the hover display information
*/
@Override
public IRegion getHoverRegion(ITextViewer textViewer, int offset)
{
return SQLWordFinder.findWord(textViewer.getDocument(), offset);
}
/**
* Returns the text which should be presented in the a hover popup window. This information is requested based on
* the specified line number.
*
* @param sourceViewer the source viewer this hover is registered with
* @param lineNumber the line number for which information is requested
* @return the requested information or <code>null</code> if no such information exists
*/
@Override
public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber)
{
if (annotations.size() == 0) {
findAnnotations(-1, sourceViewer.getAnnotationModel(), sourceViewer.getDocument(), lineNumber);
}
return null;//getHoverInfo();
}
/**
* Finds annotations either by offset or by lineNumber
*/
private void findAnnotations(int offset, IAnnotationModel model, IDocument document, int lineNumber)
{
annotations.clear();
if (model == null) {
if (editor != null) {
ITextEditor editor = this.editor;
model = editor.getDocumentProvider().getAnnotationModel(editor.getEditorInput());
}
}
if (model == null) {
return;
}
for (Iterator<?> it = model.getAnnotationIterator(); it.hasNext();) {
Annotation annotation = (Annotation) it.next();
Position position = model.getPosition(annotation);
//if position is null, just return.
if (position == null) {
return;
}
try {
if (position.overlapsWith(offset, 1) || document != null
&& document.getLineOfOffset(position.offset) == lineNumber) {
annotations.add(annotation);
}
}
catch (BadLocationException e) {
log.error(e);
}
}
}
/*
private String getHoverInfo()
{
String text = null;
IPreferenceStore store = DBeaverCore.getInstance().getGlobalPreferenceStore();
for (Annotation annotation : annotations) {
if (annotation instanceof MarkerAnnotation) {
try {
IMarker marker = ((MarkerAnnotation) annotation).getMarker();
if (marker.getType().equals(SQLConstants.SYNTAX_MARKER_TYPE)
|| marker.getType().equals(SQLConstants.PORTABILITY_MARKER_TYPE)) {
if (store.getBoolean(SQLPreferenceConstants.SHOW_SYNTAX_ERROR_DETAIL)) {
text = (String) marker.getBinding(IMarker.MESSAGE);
} else {
text = (String) marker.getBinding(SQLConstants.SHORT_MESSAGE);
}
//TODO: consider combine multiple annotations
break;
}
}
catch (CoreException e) {
log.error(e);
}
}
}
annotations.clear();
return text;
}
*/
@Override
public void setEditor(IEditorPart editor)
{
this.editor = (SQLEditorBase) editor;
}
public IInformationControlCreator getHoverControlCreator()
{
return new IInformationControlCreator() {
@Override
public IInformationControl createInformationControl(Shell parent)
{
DefaultInformationControl control = new DefaultInformationControl(parent, true);
control.setSizeConstraints(60, 10);
return control;
}
};
}
}