Make PHPeclipse compile correctly under Eclipse Version: 3.2.0 Build id: I20060519...
[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..f8cea73
--- /dev/null
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * 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 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;
+
+import org.eclipse.jface.viewers.IDoubleClickListener;
+
+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 net.sourceforge.phpdt.internal.ui.text.java.hover.AnnotationExpansionControl.AnnotationHoverInput;
+
+
+/**
+ * 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;
+       }
+}