blob: 0d9ac5060d3363d6f7d5835a825aaf8728c892f5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2010 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jface.text.hyperlink;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.Geometry;
import org.eclipse.jface.util.Util;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.text.AbstractInformationControl;
import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IInformationControlExtension2;
import org.eclipse.jface.text.IInformationControlExtension3;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.ITextHoverExtension;
import org.eclipse.jface.text.ITextHoverExtension2;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.IWidgetTokenKeeper;
import org.eclipse.jface.text.IWidgetTokenKeeperExtension;
import org.eclipse.jface.text.IWidgetTokenOwner;
import org.eclipse.jface.text.IWidgetTokenOwnerExtension;
import org.eclipse.jface.text.JFaceTextUtil;
import org.eclipse.jface.text.Region;
/**
* A hyperlink presenter capable of showing multiple hyperlinks in a hover.
*
* @since 3.4
*/
public class MultipleHyperlinkPresenter extends DefaultHyperlinkPresenter implements IHyperlinkPresenterExtension2 {
private static final boolean IS_OLD_WINDOWS;
static {
int majorVersion= Integer.MAX_VALUE;
if (Util.isWin32()) {
String osVersion= System.getProperty("os.version"); //$NON-NLS-1$
if (osVersion != null) {
int majorIndex = osVersion.indexOf('.');
if (majorIndex != -1) {
osVersion = osVersion.substring(0, majorIndex);
try {
majorVersion= Integer.parseInt(osVersion);
} catch (NumberFormatException exception) {
// use default
}
}
}
}
IS_OLD_WINDOWS= majorVersion < 6; // before Vista (6.0)
}
private static final boolean IS_MAC= Util.isMac();
private static final boolean IS_GTK= Util.isGtk();
/**
* An information control capable of showing a list of hyperlinks. The hyperlinks can be opened.
*/
private static class LinkListInformationControl extends AbstractInformationControl implements IInformationControlExtension2 {
private static final class LinkContentProvider implements IStructuredContentProvider {
/*
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
*/
public Object[] getElements(Object inputElement) {
return (Object[]) inputElement;
}
/*
* @see org.eclipse.jface.viewers.IContentProvider#dispose()
*/
public void dispose() {
}
/*
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
*/
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
private static final class LinkLabelProvider extends ColumnLabelProvider {
/*
* @see org.eclipse.jface.viewers.ColumnLabelProvider#getText(java.lang.Object)
*/
public String getText(Object element) {
IHyperlink link= (IHyperlink)element;
String text= link.getHyperlinkText();
if (text != null)
return text;
return HyperlinkMessages.getString("LinkListInformationControl.unknownLink"); //$NON-NLS-1$
}
}
private final MultipleHyperlinkHoverManager fManager;
private IHyperlink[] fInput;
private Composite fParent;
private Table fTable;
private final Color fForegroundColor;
private final Color fBackgroundColor;
/**
* Creates a link list information control with the given shell as parent.
*
* @param parentShell the parent shell
* @param manager the hover manager
* @param foregroundColor the foreground color, must not be disposed
* @param backgroundColor the background color, must not be disposed
*/
public LinkListInformationControl(Shell parentShell, MultipleHyperlinkHoverManager manager, Color foregroundColor, Color backgroundColor) {
super(parentShell, false);
fManager= manager;
fForegroundColor= foregroundColor;
fBackgroundColor= backgroundColor;
create();
}
/*
* @see org.eclipse.jface.text.IInformationControl#setInformation(java.lang.String)
*/
public void setInformation(String information) {
//replaced by IInformationControlExtension2#setInput(java.lang.Object)
}
/*
* @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object)
*/
public void setInput(Object input) {
fInput= (IHyperlink[]) input;
deferredCreateContent(fParent);
}
/*
* @see org.eclipse.jface.text.AbstractInformationControl#createContent(org.eclipse.swt.widgets.Composite)
*/
protected void createContent(Composite parent) {
fParent= parent;
GridLayout layout= new GridLayout();
if (IS_OLD_WINDOWS) {
layout.marginWidth= 0;
layout.marginHeight= 4;
layout.marginRight= 4;
} else if (IS_MAC) {
layout.marginWidth= 4;
layout.marginHeight= 0;
layout.marginTop= 4;
layout.marginBottom= 4 - 1;
} else if (IS_GTK) {
layout.marginWidth= 4;
layout.marginHeight= 0;
layout.marginTop= 4;
layout.marginBottom= 4 - 2;
} else {
layout.marginWidth= 4;
layout.marginHeight= 4;
}
fParent.setLayout(layout);
fParent.setForeground(fForegroundColor);
fParent.setBackground(fBackgroundColor);
}
/*
* @see org.eclipse.jface.text.AbstractInformationControl#computeSizeHint()
*/
public Point computeSizeHint() {
Point preferedSize= getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
Point constraints= getSizeConstraints();
if (constraints == null)
return preferedSize;
if (fTable.getVerticalBar() == null || fTable.getHorizontalBar() == null)
return Geometry.min(constraints, preferedSize);
int scrollBarWidth= fTable.getVerticalBar().getSize().x;
int scrollBarHeight= fTable.getHorizontalBar().getSize().y;
int width;
if (preferedSize.y - scrollBarHeight <= constraints.y) {
width= preferedSize.x - scrollBarWidth;
fTable.getVerticalBar().setVisible(false);
} else {
width= Math.min(preferedSize.x, constraints.x);
}
int height;
if (preferedSize.x - scrollBarWidth <= constraints.x) {
height= preferedSize.y - scrollBarHeight;
fTable.getHorizontalBar().setVisible(false);
} else {
height= Math.min(preferedSize.y, constraints.y);
}
return new Point(width, height);
}
private void deferredCreateContent(Composite parent) {
fTable= new Table(parent, SWT.SINGLE | SWT.FULL_SELECTION);
fTable.setLinesVisible(false);
fTable.setHeaderVisible(false);
fTable.setForeground(fForegroundColor);
fTable.setBackground(fBackgroundColor);
fTable.setFont(JFaceResources.getDialogFont());
GridData data= new GridData(SWT.BEGINNING, SWT.BEGINNING, true, true);
fTable.setLayoutData(data);
final TableViewer viewer= new TableViewer(fTable);
viewer.setContentProvider(new LinkContentProvider());
viewer.setLabelProvider(new LinkLabelProvider());
viewer.setInput(fInput);
fTable.setSelection(0);
registerTableListeners();
getShell().addShellListener(new ShellAdapter() {
/*
* @see org.eclipse.swt.events.ShellAdapter#shellActivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellActivated(ShellEvent e) {
if (viewer.getTable().getSelectionCount() == 0) {
viewer.getTable().setSelection(0);
}
viewer.getTable().setFocus();
}
});
}
private void registerTableListeners() {
fTable.addMouseMoveListener(new MouseMoveListener() {
TableItem fLastItem= null;
public void mouseMove(MouseEvent e) {
if (fTable.equals(e.getSource())) {
Object o= fTable.getItem(new Point(e.x, e.y));
if (fLastItem == null ^ o == null) {
fTable.setCursor(o == null ? null : fTable.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
}
if (o instanceof TableItem) {
TableItem item= (TableItem) o;
if (!o.equals(fLastItem)) {
fLastItem= (TableItem) o;
fTable.setSelection(new TableItem[] { fLastItem });
} else if (e.y < fTable.getItemHeight() / 4) {
// Scroll up
int index= fTable.indexOf(item);
if (index > 0) {
fLastItem= fTable.getItem(index - 1);
fTable.setSelection(new TableItem[] { fLastItem });
}
} else if (e.y > fTable.getBounds().height - fTable.getItemHeight() / 4) {
// Scroll down
int index= fTable.indexOf(item);
if (index < fTable.getItemCount() - 1) {
fLastItem= fTable.getItem(index + 1);
fTable.setSelection(new TableItem[] { fLastItem });
}
}
} else if (o == null) {
fLastItem= null;
}
}
}
});
fTable.addSelectionListener(new SelectionAdapter() {
public void widgetDefaultSelected(SelectionEvent e) {
openSelectedLink();
}
});
fTable.addMouseListener(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
if (IS_MAC && (e.stateMask & SWT.COMMAND) != 0) {
// workaround for https://bugs.eclipse.org/325223
TableItem item= fTable.getItem(new Point(e.x, e.y));
if (item != null) {
fTable.setSelection(item);
}
}
}
public void mouseUp(MouseEvent e) {
if (fTable.getSelectionCount() < 1)
return;
if (e.button != 1)
return;
if (fTable.equals(e.getSource())) {
Object o= fTable.getItem(new Point(e.x, e.y));
TableItem selection= fTable.getSelection()[0];
if (selection.equals(o))
openSelectedLink();
}
}
});
fTable.addTraverseListener(new TraverseListener() {
public void keyTraversed(TraverseEvent e) {
if (e.keyCode == SWT.ESC) {
fManager.hideInformationControl();
}
}
});
}
/*
* @see org.eclipse.jface.text.IInformationControlExtension#hasContents()
*/
public boolean hasContents() {
return true;
}
/**
* Opens the currently selected link.
*/
private void openSelectedLink() {
if (fTable.getSelectionCount() < 1)
return;
TableItem selection= fTable.getSelection()[0];
IHyperlink link= (IHyperlink)selection.getData();
fManager.hideInformationControl();
fManager.setCaret();
link.open();
}
}
private class MultipleHyperlinkHover implements ITextHover, ITextHoverExtension, ITextHoverExtension2 {
/**
* @see org.eclipse.jface.text.ITextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
* @deprecated As of 3.4, replaced by
* {@link ITextHoverExtension2#getHoverInfo2(ITextViewer, IRegion)}
*/
public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
return null;
}
/*
* @see org.eclipse.jface.text.ITextHover#getHoverRegion(org.eclipse.jface.text.ITextViewer, int)
*/
public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
return fSubjectRegion;
}
/*
* @see org.eclipse.jface.text.ITextHoverExtension2#getHoverInfo2(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
*/
public Object getHoverInfo2(ITextViewer textViewer, IRegion hoverRegion) {
return fHyperlinks;
}
/*
* @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
*/
public IInformationControlCreator getHoverControlCreator() {
return new IInformationControlCreator() {
public IInformationControl createInformationControl(Shell parent) {
Color foregroundColor= fTextViewer.getTextWidget().getForeground();
Color backgroundColor= fTextViewer.getTextWidget().getBackground();
return new LinkListInformationControl(parent, fManager, foregroundColor, backgroundColor);
}
};
}
}
private static class MultipleHyperlinkHoverManager extends AbstractInformationControlManager implements IWidgetTokenKeeper, IWidgetTokenKeeperExtension {
private class Closer implements IInformationControlCloser, Listener, KeyListener, MouseListener {
private Control fSubjectControl;
private Display fDisplay;
private IInformationControl fControl;
private Rectangle fSubjectArea;
/*
* @see org.eclipse.jface.text.AbstractInformationControlManager.IInformationControlCloser#setInformationControl(org.eclipse.jface.text.IInformationControl)
*/
public void setInformationControl(IInformationControl control) {
fControl= control;
}
/*
* @see org.eclipse.jface.text.AbstractInformationControlManager.IInformationControlCloser#setSubjectControl(org.eclipse.swt.widgets.Control)
*/
public void setSubjectControl(Control subject) {
fSubjectControl= subject;
}
/*
* @see org.eclipse.jface.text.AbstractInformationControlManager.IInformationControlCloser#start(org.eclipse.swt.graphics.Rectangle)
*/
public void start(Rectangle subjectArea) {
fSubjectArea= subjectArea;
fDisplay= fSubjectControl.getDisplay();
if (!fDisplay.isDisposed()) {
fDisplay.addFilter(SWT.FocusOut, this);
fDisplay.addFilter(SWT.MouseMove, this);
fTextViewer.getTextWidget().addKeyListener(this);
fTextViewer.getTextWidget().addMouseListener(this);
}
}
/*
* @see org.eclipse.jface.text.AbstractInformationControlManager.IInformationControlCloser#stop()
*/
public void stop() {
if (fDisplay != null && !fDisplay.isDisposed()) {
fDisplay.removeFilter(SWT.FocusOut, this);
fDisplay.removeFilter(SWT.MouseMove, this);
fTextViewer.getTextWidget().removeKeyListener(this);
fTextViewer.getTextWidget().removeMouseListener(this);
}
fSubjectArea= null;
}
/*
* @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
*/
public void handleEvent(Event event) {
switch (event.type) {
case SWT.FocusOut:
if (!fControl.isFocusControl())
disposeInformationControl();
break;
case SWT.MouseMove:
handleMouseMove(event);
break;
}
}
/**
* Handle mouse movement events.
*
* @param event the event
*/
private void handleMouseMove(Event event) {
if (!(event.widget instanceof Control))
return;
if (fControl.isFocusControl())
return;
Control eventControl= (Control) event.widget;
//transform coordinates to subject control:
Point mouseLoc= event.display.map(eventControl, fSubjectControl, event.x, event.y);
if (fSubjectArea.contains(mouseLoc))
return;
if (inKeepUpZone(mouseLoc.x, mouseLoc.y, ((IInformationControlExtension3) fControl).getBounds()))
return;
if (!isTakingFocusWhenVisible())
hideInformationControl();
}
/**
* Tests whether a given mouse location is within the keep-up zone.
* The hover should not be hidden as long as the mouse stays inside this zone.
*
* @param x the x coordinate, relative to the <em>subject control</em>
* @param y the y coordinate, relative to the <em>subject control</em>
* @param controlBounds the bounds of the current control
*
* @return <code>true</code> iff the mouse event occurred in the keep-up zone
*/
private boolean inKeepUpZone(int x, int y, Rectangle controlBounds) {
// +-----------+
// |subjectArea|
// +-----------+
// |also keepUp|
// ++-----------+-------+
// | totalBounds |
// +--------------------+
if (fSubjectArea.contains(x, y))
return true;
Rectangle iControlBounds= fSubjectControl.getDisplay().map(null, fSubjectControl, controlBounds);
Rectangle totalBounds= Geometry.copy(iControlBounds);
if (totalBounds.contains(x, y))
return true;
int keepUpY= fSubjectArea.y + fSubjectArea.height;
Rectangle alsoKeepUp= new Rectangle(fSubjectArea.x, keepUpY, fSubjectArea.width, totalBounds.y - keepUpY);
return alsoKeepUp.contains(x, y);
}
/*
* @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
*/
public void keyPressed(KeyEvent e) {
}
/*
* @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
*/
public void keyReleased(KeyEvent e) {
if (!isTakingFocusWhenVisible())
hideInformationControl();
}
/*
* @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
* @since 3.5
*/
public void mouseDoubleClick(MouseEvent e) {
}
/*
* @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
* @since 3.5
*/
public void mouseDown(MouseEvent e) {
}
/*
* @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
* @since 3.5
*/
public void mouseUp(MouseEvent e) {
hideInformationControl();
}
}
/**
* Priority of the hover managed by this manager.
* Default value: One higher then for the hovers
* managed by TextViewerHoverManager.
*/
private static final int WIDGET_TOKEN_PRIORITY= 1;
private final MultipleHyperlinkHover fHover;
private final ITextViewer fTextViewer;
private final MultipleHyperlinkPresenter fHyperlinkPresenter;
private final Closer fCloser;
private boolean fIsControlVisible;
/**
* Create a new MultipleHyperlinkHoverManager. The MHHM can show and hide
* the given MultipleHyperlinkHover inside the given ITextViewer.
*
* @param hover the hover to manage
* @param viewer the viewer to show the hover in
* @param hyperlinkPresenter the hyperlink presenter using this manager to present hyperlinks
*/
public MultipleHyperlinkHoverManager(MultipleHyperlinkHover hover, ITextViewer viewer, MultipleHyperlinkPresenter hyperlinkPresenter) {
super(hover.getHoverControlCreator());
fHover= hover;
fTextViewer= viewer;
fHyperlinkPresenter= hyperlinkPresenter;
fCloser= new Closer();
setCloser(fCloser);
fIsControlVisible= false;
}
/*
* @see org.eclipse.jface.text.AbstractInformationControlManager#computeInformation()
*/
protected void computeInformation() {
IRegion region= fHover.getHoverRegion(fTextViewer, -1);
if (region == null) {
setInformation(null, null);
return;
}
Rectangle area= JFaceTextUtil.computeArea(region, fTextViewer);
if (area == null || area.isEmpty()) {
setInformation(null, null);
return;
}
Object information= fHover.getHoverInfo2(fTextViewer, region);
setCustomInformationControlCreator(fHover.getHoverControlCreator());
setInformation(information, area);
}
/*
* @see org.eclipse.jface.text.AbstractInformationControlManager#computeInformationControlLocation(org.eclipse.swt.graphics.Rectangle, org.eclipse.swt.graphics.Point)
*/
protected Point computeInformationControlLocation(Rectangle subjectArea, Point controlSize) {
Point result= super.computeInformationControlLocation(subjectArea, controlSize);
Point cursorLocation= fTextViewer.getTextWidget().getDisplay().getCursorLocation();
if (isTakingFocusWhenVisible() || cursorLocation.x <= result.x + controlSize.x)
return result;
result.x= cursorLocation.x + 20 - controlSize.x;
return result;
}
/*
* @see org.eclipse.jface.text.AbstractInformationControlManager#showInformationControl(org.eclipse.swt.graphics.Rectangle)
*/
protected void showInformationControl(Rectangle subjectArea) {
if (fTextViewer instanceof IWidgetTokenOwnerExtension) {
if (((IWidgetTokenOwnerExtension) fTextViewer).requestWidgetToken(this, WIDGET_TOKEN_PRIORITY))
super.showInformationControl(subjectArea);
} else if (fTextViewer instanceof IWidgetTokenOwner) {
if (((IWidgetTokenOwner) fTextViewer).requestWidgetToken(this))
super.showInformationControl(subjectArea);
} else {
super.showInformationControl(subjectArea);
}
fIsControlVisible= true;
}
/**
* Sets the caret where hyperlinking got initiated.
*
* @since 3.5
*/
private void setCaret() {
fHyperlinkPresenter.setCaret();
}
/*
* @see org.eclipse.jface.text.AbstractInformationControlManager#hideInformationControl()
*/
protected void hideInformationControl() {
super.hideInformationControl();
if (fTextViewer instanceof IWidgetTokenOwner) {
((IWidgetTokenOwner) fTextViewer).releaseWidgetToken(this);
}
fIsControlVisible= false;
fHyperlinkPresenter.hideHyperlinks();
}
/*
* @see org.eclipse.jface.text.AbstractInformationControlManager#disposeInformationControl()
*/
public void disposeInformationControl() {
super.disposeInformationControl();
if (fTextViewer instanceof IWidgetTokenOwner) {
((IWidgetTokenOwner) fTextViewer).releaseWidgetToken(this);
}
fIsControlVisible= false;
fHyperlinkPresenter.hideHyperlinks();
}
/*
* @see org.eclipse.jface.text.IWidgetTokenKeeper#requestWidgetToken(org.eclipse.jface.text.IWidgetTokenOwner)
*/
public boolean requestWidgetToken(IWidgetTokenOwner owner) {
hideInformationControl();
return true;
}
/*
* @see org.eclipse.jface.text.IWidgetTokenKeeperExtension#requestWidgetToken(org.eclipse.jface.text.IWidgetTokenOwner, int)
*/
public boolean requestWidgetToken(IWidgetTokenOwner owner, int priority) {
if (priority < WIDGET_TOKEN_PRIORITY)
return false;
hideInformationControl();
return true;
}
/*
* @see org.eclipse.jface.text.IWidgetTokenKeeperExtension#setFocus(org.eclipse.jface.text.IWidgetTokenOwner)
*/
public boolean setFocus(IWidgetTokenOwner owner) {
return isTakingFocusWhenVisible();
}
/**
* Returns <code>true</code> if the information control managed by
* this manager is visible, <code>false</code> otherwise.
*
* @return <code>true</code> if information control is visible
*/
public boolean isInformationControlVisible() {
return fIsControlVisible;
}
}
private ITextViewer fTextViewer;
private IHyperlink[] fHyperlinks;
private Region fSubjectRegion;
private MultipleHyperlinkHoverManager fManager;
/**
* The offset in the text viewer where hyperlinking got initiated.
* @since 3.5
*/
private int fCursorOffset;
/**
* Creates a new multiple hyperlink presenter which uses {@link #HYPERLINK_COLOR} to read the
* color from the given preference store.
*
* @param store the preference store
*/
public MultipleHyperlinkPresenter(IPreferenceStore store) {
super(store);
}
/**
* Creates a new multiple hyperlink presenter.
*
* @param color the hyperlink color, to be disposed by the caller
*/
public MultipleHyperlinkPresenter(RGB color) {
super(color);
}
/*
* @see org.eclipse.jface.text.hyperlink.DefaultHyperlinkPresenter#install(org.eclipse.jface.text.ITextViewer)
*/
public void install(ITextViewer viewer) {
super.install(viewer);
fTextViewer= viewer;
fManager= new MultipleHyperlinkHoverManager(new MultipleHyperlinkHover(), fTextViewer, this);
fManager.install(viewer.getTextWidget());
fManager.setSizeConstraints(100, 12, false, true);
}
/*
* @see org.eclipse.jface.text.hyperlink.DefaultHyperlinkPresenter#uninstall()
*/
public void uninstall() {
super.uninstall();
if (fTextViewer != null) {
fManager.dispose();
fTextViewer= null;
}
}
/*
* @see org.eclipse.jface.text.hyperlink.DefaultHyperlinkPresenter#canShowMultipleHyperlinks()
*/
public boolean canShowMultipleHyperlinks() {
return true;
}
/*
* @see org.eclipse.jface.text.hyperlink.DefaultHyperlinkPresenter#canHideHyperlinks()
*/
public boolean canHideHyperlinks() {
return !fManager.isInformationControlVisible();
}
/*
* @see org.eclipse.jface.text.hyperlink.DefaultHyperlinkPresenter#hideHyperlinks()
*/
public void hideHyperlinks() {
super.hideHyperlinks();
fHyperlinks= null;
}
/*
* @see org.eclipse.jface.text.hyperlink.DefaultHyperlinkPresenter#showHyperlinks(org.eclipse.jface.text.hyperlink.IHyperlink[])
*/
public void showHyperlinks(IHyperlink[] hyperlinks) {
showHyperlinks(hyperlinks, false);
}
/**
* {@inheritDoc}
*
* @since 3.7
*/
public void showHyperlinks(IHyperlink[] activeHyperlinks, boolean takesFocusWhenVisible) {
fManager.takesFocusWhenVisible(takesFocusWhenVisible);
super.showHyperlinks(new IHyperlink[] { activeHyperlinks[0] });
fSubjectRegion= null;
fHyperlinks= activeHyperlinks;
if (activeHyperlinks.length == 1)
return;
int start= activeHyperlinks[0].getHyperlinkRegion().getOffset();
int end= start + activeHyperlinks[0].getHyperlinkRegion().getLength();
for (int i= 1; i < activeHyperlinks.length; i++) {
int hstart= activeHyperlinks[i].getHyperlinkRegion().getOffset();
int hend= hstart + activeHyperlinks[i].getHyperlinkRegion().getLength();
start= Math.min(start, hstart);
end= Math.max(end, hend);
}
fSubjectRegion= new Region(start, end - start);
fCursorOffset= JFaceTextUtil.getOffsetForCursorLocation(fTextViewer);
fManager.showInformation();
}
/**
* Sets the caret where hyperlinking got initiated.
*
* @since 3.5
*/
private void setCaret() {
Point selectedRange= fTextViewer.getSelectedRange();
if (fCursorOffset != -1 && !(fSubjectRegion.getOffset() <= selectedRange.x && selectedRange.x + selectedRange.y <= fSubjectRegion.getOffset() + fSubjectRegion.getLength()))
fTextViewer.setSelectedRange(fCursorOffset, 0);
}
}