package gr.uom.java.ast.visualization; import java.util.List; import org.eclipse.jface.text.AbstractInformationControlManager; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.ITextViewer; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; /** * Information control manager. * Refactored from {@link org.eclipse.jface.text.information.InformationPresenter} * for general usage instead of {@link ITextViewer}. */ public class InformationControlManager extends AbstractInformationControlManager { /** * Internal information control closer. Listens to several events issued by its subject control * and closes the information control when necessary. */ class InformationControlCloser implements IInformationControlCloser, ControlListener, MouseListener, FocusListener, KeyListener { /** The subject control. */ private Control subjectControl; /** The information control. */ private IInformationControl informationControlToClose; /** Indicates whether this closer is active. */ private boolean isActive = false; public void setSubjectControl(Control control) { subjectControl = control; } public void setInformationControl(IInformationControl control) { informationControlToClose = control; } public void start(Rectangle informationArea) { if (isActive) { return; } isActive = true; if (subjectControl != null && !subjectControl.isDisposed()) { subjectControl.addControlListener(this); subjectControl.addMouseListener(this); subjectControl.addFocusListener(this); subjectControl.addKeyListener(this); } if (informationControlToClose != null) { informationControlToClose.addFocusListener(this); } } public void stop() { if (!isActive) { return; } isActive = false; if (informationControlToClose != null) { informationControlToClose.removeFocusListener(this); } if (subjectControl != null && !subjectControl.isDisposed()) { subjectControl.removeControlListener(this); subjectControl.removeMouseListener(this); subjectControl.removeFocusListener(this); subjectControl.removeKeyListener(this); } } public void controlResized(ControlEvent e) { hideInformationControl(); } public void controlMoved(ControlEvent e) { hideInformationControl(); } public void mouseDown(MouseEvent e) { hideInformationControl(); } public void mouseUp(MouseEvent e) { // nothing to do } public void mouseDoubleClick(MouseEvent e) { hideInformationControl(); } public void focusGained(FocusEvent e) { // nothing to do } public void focusLost(FocusEvent e) { Display d = subjectControl.getDisplay(); d.asyncExec(new Runnable() { // Without the asyncExec, mouse clicks to the workbench window are swallowed. public void run() { if (informationControlToClose == null || !informationControlToClose.isFocusControl()) { hideInformationControl(); } } }); } public void keyPressed(KeyEvent e) { hideInformationControl(); } public void keyReleased(KeyEvent e) { // nothing to do } public void mouseDragged(org.eclipse.draw2d.MouseEvent me) { // TODO Auto-generated method stub } } private static final IInformationControlCreator DEFAULT_INFORMATION_CONTROL_CREATOR = new FeatureEnviedMethodInformationControlCreator(); private final IInformationProvider informationProvider; private final List<ICustomInformationControlCreator> customControlCreators; /** * Creates a new information control manager that uses the given information provider and control creators. * The manager is not installed on any control yet. By default, an information * control closer is set that closes the information control in the event of key strokes, * resizing, moves, focus changes, mouse clicks, and disposal - all of those applied to * the information control's parent control. Optionally, the setup ensures that the information * control when made visible will request the focus. * * @param informationProvider the information provider to be used * @param customControlCreators the control creators to be used * @param takeFocusWhenVisible set to <code>true</code> if the information control should take focus when made visible */ public InformationControlManager(IInformationProvider informationProvider, List<ICustomInformationControlCreator> customControlCreators, boolean takeFocusWhenVisible) { super(DEFAULT_INFORMATION_CONTROL_CREATOR); this.informationProvider = informationProvider; this.customControlCreators = customControlCreators; setCloser(new InformationControlCloser()); takesFocusWhenVisible(takeFocusWhenVisible); } @Override protected void computeInformation() { Display display = getSubjectControl().getDisplay(); Point mouseLocation = display.getCursorLocation(); mouseLocation = getSubjectControl().toControl(mouseLocation); // Compute information input Object info = informationProvider.getInformation(mouseLocation); // Find an information control creator for the computed information input IInformationControlCreator customControlCreator = null; for (ICustomInformationControlCreator controlCreator : customControlCreators) { if (controlCreator.isSupported(info)) { customControlCreator = controlCreator; break; } } setCustomInformationControlCreator(customControlCreator); // Convert to String for default TextLabelInformationControl // (Fallback, if no custom control creator has been found) //if (info != null && customControlCreator == null) { // info = info.toString(); //} // Trigger the presentation of the computed information if(customControlCreator != null){ Rectangle area = informationProvider.getArea(mouseLocation); setInformation(info, area); } } @Override protected Point computeLocation(Rectangle subjectArea, Point controlSize, Anchor anchor) { Point location = super.computeLocation(subjectArea, controlSize, anchor); location.x += 20; return location; } }