1) Moved net.sourceforge.phpeclipse.ui\src\net\sourceforge\phpdt back to net.sourcefo...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / java / hover / AnnotationExpandHover.java
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AnnotationExpandHover.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AnnotationExpandHover.java
new file mode 100644 (file)
index 0000000..581517a
--- /dev/null
@@ -0,0 +1,337 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.ui.text.java.hover.AnnotationExpansionControl.AnnotationHoverInput;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IInformationControlCreatorExtension;
+import org.eclipse.jface.text.ITextViewerExtension5;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.CompositeRuler;
+import org.eclipse.jface.text.source.IAnnotationAccess;
+import org.eclipse.jface.text.source.IAnnotationAccessExtension;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.IAnnotationHoverExtension;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.ILineRange;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRulerListener;
+import org.eclipse.jface.text.source.LineRange;
+import org.eclipse.jface.text.source.VerticalRulerEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * This class got moved here form Platform Text since it was not used there and
+ * caused discouraged access warnings. It will be moved down again once
+ * annotation roll-over support is provided by Platform Text.
+ * 
+ * @since 3.2
+ */
+public class AnnotationExpandHover implements IAnnotationHover,
+               IAnnotationHoverExtension {
+
+       private class InformationControlCreator implements
+                       IInformationControlCreator, IInformationControlCreatorExtension {
+
+               /*
+                * @see org.eclipse.jface.text.IInformationControlCreator#createInformationControl(org.eclipse.swt.widgets.Shell)
+                */
+               public IInformationControl createInformationControl(Shell parent) {
+                       return new AnnotationExpansionControl(parent, SWT.NONE,
+                                       fAnnotationAccess);
+               }
+
+               /*
+                * @see org.eclipse.jface.text.IInformationControlCreatorExtension#canReuse(org.eclipse.jface.text.IInformationControl)
+                */
+               public boolean canReuse(IInformationControl control) {
+                       return control instanceof AnnotationExpansionControl;
+               }
+
+               /*
+                * @see org.eclipse.jface.text.IInformationControlCreatorExtension#canReplace(org.eclipse.jface.text.IInformationControlCreator)
+                */
+               public boolean canReplace(IInformationControlCreator creator) {
+                       return creator == this;
+               }
+       }
+
+       private class VerticalRulerListener implements IVerticalRulerListener {
+
+               /*
+                * @see org.eclipse.jface.text.source.IVerticalRulerListener#annotationSelected(org.eclipse.jface.text.source.VerticalRulerEvent)
+                */
+               public void annotationSelected(VerticalRulerEvent event) {
+                       fCompositeRuler.fireAnnotationSelected(event);
+               }
+
+               /*
+                * @see org.eclipse.jface.text.source.IVerticalRulerListener#annotationDefaultSelected(org.eclipse.jface.text.source.VerticalRulerEvent)
+                */
+               public void annotationDefaultSelected(VerticalRulerEvent event) {
+                       fCompositeRuler.fireAnnotationDefaultSelected(event);
+               }
+
+               /*
+                * @see org.eclipse.jface.text.source.IVerticalRulerListener#annotationContextMenuAboutToShow(org.eclipse.jface.text.source.VerticalRulerEvent,
+                *      org.eclipse.swt.widgets.Menu)
+                */
+               public void annotationContextMenuAboutToShow(VerticalRulerEvent event,
+                               Menu menu) {
+                       fCompositeRuler.fireAnnotationContextMenuAboutToShow(event, menu);
+               }
+       }
+
+       private final IInformationControlCreator fgCreator = new InformationControlCreator();
+
+       protected final IVerticalRulerListener fgListener = new VerticalRulerListener();
+
+       protected CompositeRuler fCompositeRuler;
+
+       protected IDoubleClickListener fDblClickListener;
+
+       protected IAnnotationAccess fAnnotationAccess;
+
+       /**
+        * Creates a new hover instance.
+        * 
+        * @param ruler
+        * @param access
+        * @param doubleClickListener
+        */
+       public AnnotationExpandHover(CompositeRuler ruler,
+                       IAnnotationAccess access, IDoubleClickListener doubleClickListener) {
+               fCompositeRuler = ruler;
+               fAnnotationAccess = access;
+               fDblClickListener = doubleClickListener;
+       }
+
+       /*
+        * @see org.eclipse.jface.text.source.IAnnotationHover#getHoverInfo(org.eclipse.jface.text.source.ISourceViewer,
+        *      int)
+        */
+       public String getHoverInfo(ISourceViewer sourceViewer, int line) {
+               // we don't have any sensible return value as text
+               return null;
+       }
+
+       protected Object getHoverInfoForLine(ISourceViewer viewer, int line) {
+               IAnnotationModel model = viewer.getAnnotationModel();
+               IDocument document = viewer.getDocument();
+
+               if (model == null)
+                       return null;
+
+               List exact = new ArrayList();
+               HashMap messagesAtPosition = new HashMap();
+
+               Iterator e = model.getAnnotationIterator();
+               while (e.hasNext()) {
+                       Annotation annotation = (Annotation) e.next();
+                       Position position = model.getPosition(annotation);
+                       if (position == null)
+                               continue;
+
+                       if (compareRulerLine(position, document, line) == 1) {
+                               if (isDuplicateMessage(messagesAtPosition, position, annotation
+                                               .getText()))
+                                       continue;
+
+                               exact.add(annotation);
+                       }
+               }
+
+               if (exact.size() < 1)
+                       return null;
+
+               sort(exact, model);
+
+               if (exact.size() > 0)
+                       setLastRulerMouseLocation(viewer, line);
+
+               AnnotationHoverInput input = new AnnotationHoverInput();
+               input.fAnnotations = (Annotation[]) exact.toArray(new Annotation[0]);
+               input.fViewer = viewer;
+               input.fRulerInfo = fCompositeRuler;
+               input.fAnnotationListener = fgListener;
+               input.fDoubleClickListener = fDblClickListener;
+               input.model = model;
+
+               return input;
+       }
+
+       protected void sort(List exact, final IAnnotationModel model) {
+               class AnnotationComparator implements Comparator {
+
+                       /*
+                        * @see java.util.Comparator#compare(java.lang.Object,
+                        *      java.lang.Object)
+                        */
+                       public int compare(Object o1, Object o2) {
+                               Annotation a1 = (Annotation) o1;
+                               Annotation a2 = (Annotation) o2;
+
+                               Position p1 = model.getPosition(a1);
+                               Position p2 = model.getPosition(a2);
+
+                               // annotation order:
+                               // primary order: by position in line
+                               // secondary: annotation importance
+                               if (p1.offset == p2.offset)
+                                       return getOrder(a2) - getOrder(a1);
+                               return p1.offset - p2.offset;
+                       }
+               }
+
+               Collections.sort(exact, new AnnotationComparator());
+
+       }
+
+       protected int getOrder(Annotation annotation) {
+               if (fAnnotationAccess instanceof IAnnotationAccessExtension) {
+                       IAnnotationAccessExtension extension = (IAnnotationAccessExtension) fAnnotationAccess;
+                       return extension.getLayer(annotation);
+               }
+               return IAnnotationAccessExtension.DEFAULT_LAYER;
+       }
+
+       protected boolean isDuplicateMessage(Map messagesAtPosition,
+                       Position position, String message) {
+               if (message == null)
+                       return false;
+
+               if (messagesAtPosition.containsKey(position)) {
+                       Object value = messagesAtPosition.get(position);
+                       if (message == null || message.equals(value))
+                               return true;
+
+                       if (value instanceof List) {
+                               List messages = (List) value;
+                               if (messages.contains(message))
+                                       return true;
+                               messages.add(message);
+                       } else {
+                               ArrayList messages = new ArrayList();
+                               messages.add(value);
+                               messages.add(message);
+                               messagesAtPosition.put(position, messages);
+                       }
+               } else
+                       messagesAtPosition.put(position, message);
+               return false;
+       }
+
+       protected void setLastRulerMouseLocation(ISourceViewer viewer, int line) {
+               // set last mouse activity in order to get the correct context menu
+               if (fCompositeRuler != null) {
+                       StyledText st = viewer.getTextWidget();
+                       if (st != null && !st.isDisposed()) {
+                               if (viewer instanceof ITextViewerExtension5) {
+                                       int widgetLine = ((ITextViewerExtension5) viewer)
+                                                       .modelLine2WidgetLine(line);
+                                       Point loc = st.getLocationAtOffset(st
+                                                       .getOffsetAtLine(widgetLine));
+                                       fCompositeRuler.setLocationOfLastMouseButtonActivity(0,
+                                                       loc.y);
+                               } else if (viewer instanceof TextViewer) {
+                                       // TODO remove once TextViewer implements the extension
+                                       int widgetLine = ((TextViewer) viewer)
+                                                       .modelLine2WidgetLine(line);
+                                       Point loc = st.getLocationAtOffset(st
+                                                       .getOffsetAtLine(widgetLine));
+                                       fCompositeRuler.setLocationOfLastMouseButtonActivity(0,
+                                                       loc.y);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Returns the distance to the ruler line.
+        * 
+        * @param position
+        *            the position
+        * @param document
+        *            the document
+        * @param line
+        *            the line number
+        * @return the distance to the ruler line
+        */
+       protected int compareRulerLine(Position position, IDocument document,
+                       int line) {
+
+               if (position.getOffset() > -1 && position.getLength() > -1) {
+                       try {
+                               int firstLine = document.getLineOfOffset(position.getOffset());
+                               if (line == firstLine)
+                                       return 1;
+                               if (firstLine <= line
+                                               && line <= document.getLineOfOffset(position
+                                                               .getOffset()
+                                                               + position.getLength()))
+                                       return 2;
+                       } catch (BadLocationException x) {
+                       }
+               }
+
+               return 0;
+       }
+
+       /*
+        * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#getHoverControlCreator()
+        */
+       public IInformationControlCreator getHoverControlCreator() {
+               return fgCreator;
+       }
+
+       /*
+        * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#getHoverInfo(org.eclipse.jface.text.source.ISourceViewer,
+        *      org.eclipse.jface.text.source.ILineRange, int)
+        */
+       public Object getHoverInfo(ISourceViewer sourceViewer,
+                       ILineRange lineRange, int visibleLines) {
+               return getHoverInfoForLine(sourceViewer, lineRange.getStartLine());
+       }
+
+       /*
+        * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#getHoverLineRange(org.eclipse.jface.text.source.ISourceViewer,
+        *      int)
+        */
+       public ILineRange getHoverLineRange(ISourceViewer viewer, int lineNumber) {
+               return new LineRange(lineNumber, 1);
+       }
+
+       /*
+        * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#canHandleMouseCursor()
+        */
+       public boolean canHandleMouseCursor() {
+               return true;
+       }
+}