KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > text > java > hover > AnnotationExpandHover


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.ui.text.java.hover;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Collections JavaDoc;
15 import java.util.Comparator JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Map JavaDoc;
20
21 import org.eclipse.swt.SWT;
22 import org.eclipse.swt.custom.StyledText;
23 import org.eclipse.swt.graphics.Point;
24 import org.eclipse.swt.widgets.Menu;
25 import org.eclipse.swt.widgets.Shell;
26
27 import org.eclipse.jface.viewers.IDoubleClickListener;
28
29 import org.eclipse.jface.text.BadLocationException;
30 import org.eclipse.jface.text.IDocument;
31 import org.eclipse.jface.text.IInformationControl;
32 import org.eclipse.jface.text.IInformationControlCreator;
33 import org.eclipse.jface.text.IInformationControlCreatorExtension;
34 import org.eclipse.jface.text.ITextViewerExtension5;
35 import org.eclipse.jface.text.Position;
36 import org.eclipse.jface.text.TextViewer;
37 import org.eclipse.jface.text.source.Annotation;
38 import org.eclipse.jface.text.source.CompositeRuler;
39 import org.eclipse.jface.text.source.IAnnotationAccess;
40 import org.eclipse.jface.text.source.IAnnotationAccessExtension;
41 import org.eclipse.jface.text.source.IAnnotationHover;
42 import org.eclipse.jface.text.source.IAnnotationHoverExtension;
43 import org.eclipse.jface.text.source.IAnnotationModel;
44 import org.eclipse.jface.text.source.ILineRange;
45 import org.eclipse.jface.text.source.ISourceViewer;
46 import org.eclipse.jface.text.source.IVerticalRulerListener;
47 import org.eclipse.jface.text.source.LineRange;
48 import org.eclipse.jface.text.source.VerticalRulerEvent;
49
50 import org.eclipse.jdt.internal.ui.text.java.hover.AnnotationExpansionControl.AnnotationHoverInput;
51
52
53 /**
54  * This class got moved here form Platform Text since it was not used there
55  * and caused discouraged access warnings. It will be moved down again once
56  * annotation roll-over support is provided by Platform Text.
57  *
58  * @since 3.2
59  */

60 public class AnnotationExpandHover implements IAnnotationHover, IAnnotationHoverExtension {
61
62     private class InformationControlCreator implements IInformationControlCreator, IInformationControlCreatorExtension {
63
64         /*
65          * @see org.eclipse.jface.text.IInformationControlCreator#createInformationControl(org.eclipse.swt.widgets.Shell)
66          */

67         public IInformationControl createInformationControl(Shell parent) {
68             return new AnnotationExpansionControl(parent, SWT.NONE, fAnnotationAccess);
69         }
70
71         /*
72          * @see org.eclipse.jface.text.IInformationControlCreatorExtension#canReuse(org.eclipse.jface.text.IInformationControl)
73          */

74         public boolean canReuse(IInformationControl control) {
75             return control instanceof AnnotationExpansionControl;
76         }
77
78         /*
79          * @see org.eclipse.jface.text.IInformationControlCreatorExtension#canReplace(org.eclipse.jface.text.IInformationControlCreator)
80          */

81         public boolean canReplace(IInformationControlCreator creator) {
82             return creator == this;
83         }
84     }
85
86     private class VerticalRulerListener implements IVerticalRulerListener {
87
88         /*
89          * @see org.eclipse.jface.text.source.IVerticalRulerListener#annotationSelected(org.eclipse.jface.text.source.VerticalRulerEvent)
90          */

91         public void annotationSelected(VerticalRulerEvent event) {
92             fCompositeRuler.fireAnnotationSelected(event);
93         }
94
95         /*
96          * @see org.eclipse.jface.text.source.IVerticalRulerListener#annotationDefaultSelected(org.eclipse.jface.text.source.VerticalRulerEvent)
97          */

98         public void annotationDefaultSelected(VerticalRulerEvent event) {
99             fCompositeRuler.fireAnnotationDefaultSelected(event);
100         }
101
102         /*
103          * @see org.eclipse.jface.text.source.IVerticalRulerListener#annotationContextMenuAboutToShow(org.eclipse.jface.text.source.VerticalRulerEvent, org.eclipse.swt.widgets.Menu)
104          */

105         public void annotationContextMenuAboutToShow(VerticalRulerEvent event, Menu menu) {
106             fCompositeRuler.fireAnnotationContextMenuAboutToShow(event, menu);
107         }
108     }
109
110
111     private final IInformationControlCreator fgCreator= new InformationControlCreator();
112     protected final IVerticalRulerListener fgListener= new VerticalRulerListener();
113     protected CompositeRuler fCompositeRuler;
114     protected IDoubleClickListener fDblClickListener;
115     protected IAnnotationAccess fAnnotationAccess;
116
117     /**
118      * Creates a new hover instance.
119      *
120      * @param ruler
121      * @param access
122      * @param doubleClickListener
123      */

124     public AnnotationExpandHover(CompositeRuler ruler, IAnnotationAccess access, IDoubleClickListener doubleClickListener) {
125         fCompositeRuler= ruler;
126         fAnnotationAccess= access;
127         fDblClickListener= doubleClickListener;
128     }
129
130     /*
131      * @see org.eclipse.jface.text.source.IAnnotationHover#getHoverInfo(org.eclipse.jface.text.source.ISourceViewer, int)
132      */

133     public String JavaDoc getHoverInfo(ISourceViewer sourceViewer, int line) {
134         // we don't have any sensible return value as text
135
return null;
136     }
137
138     protected Object JavaDoc getHoverInfoForLine(ISourceViewer viewer, int line) {
139         IAnnotationModel model= viewer.getAnnotationModel();
140         IDocument document= viewer.getDocument();
141
142         if (model == null)
143             return null;
144
145         List JavaDoc exact= new ArrayList JavaDoc();
146         HashMap JavaDoc messagesAtPosition= new HashMap JavaDoc();
147
148         Iterator JavaDoc e= model.getAnnotationIterator();
149         while (e.hasNext()) {
150             Annotation annotation= (Annotation) e.next();
151             Position position= model.getPosition(annotation);
152             if (position == null)
153                 continue;
154
155             if (compareRulerLine(position, document, line) == 1) {
156                 if (isDuplicateMessage(messagesAtPosition, position, annotation.getText()))
157                     continue;
158
159                 exact.add(annotation);
160             }
161         }
162
163         if (exact.size() < 1)
164             return null;
165
166         sort(exact, model);
167
168         if (exact.size() > 0)
169             setLastRulerMouseLocation(viewer, line);
170
171         AnnotationHoverInput input= new AnnotationHoverInput();
172         input.fAnnotations= (Annotation[]) exact.toArray(new Annotation[0]);
173         input.fViewer= viewer;
174         input.fRulerInfo= fCompositeRuler;
175         input.fAnnotationListener= fgListener;
176         input.fDoubleClickListener= fDblClickListener;
177         input.model= model;
178
179         return input;
180     }
181
182     protected void sort(List JavaDoc exact, final IAnnotationModel model) {
183         class AnnotationComparator implements Comparator JavaDoc {
184
185             /*
186              * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
187              */

188             public int compare(Object JavaDoc o1, Object JavaDoc o2) {
189                 Annotation a1= (Annotation) o1;
190                 Annotation a2= (Annotation) o2;
191
192                 Position p1= model.getPosition(a1);
193                 Position p2= model.getPosition(a2);
194
195                 // annotation order:
196
// primary order: by position in line
197
// secondary: annotation importance
198
if (p1.offset == p2.offset)
199                     return getOrder(a2) - getOrder(a1);
200                 return p1.offset - p2.offset;
201             }
202         }
203
204         Collections.sort(exact, new AnnotationComparator());
205
206     }
207
208     protected int getOrder(Annotation annotation) {
209         if (fAnnotationAccess instanceof IAnnotationAccessExtension) {
210             IAnnotationAccessExtension extension= (IAnnotationAccessExtension) fAnnotationAccess;
211             return extension.getLayer(annotation);
212         }
213         return IAnnotationAccessExtension.DEFAULT_LAYER;
214     }
215
216     protected boolean isDuplicateMessage(Map JavaDoc messagesAtPosition, Position position, String JavaDoc message) {
217         if (message == null)
218             return false;
219         
220         if (messagesAtPosition.containsKey(position)) {
221             Object JavaDoc value= messagesAtPosition.get(position);
222             if (message == null || message.equals(value))
223                 return true;
224
225             if (value instanceof List JavaDoc) {
226                 List JavaDoc messages= (List JavaDoc)value;
227                 if (messages.contains(message))
228                     return true;
229                 messages.add(message);
230             } else {
231                 ArrayList JavaDoc messages= new ArrayList JavaDoc();
232                 messages.add(value);
233                 messages.add(message);
234                 messagesAtPosition.put(position, messages);
235             }
236         } else
237             messagesAtPosition.put(position, message);
238         return false;
239     }
240
241     protected void setLastRulerMouseLocation(ISourceViewer viewer, int line) {
242         // set last mouse activity in order to get the correct context menu
243
if (fCompositeRuler != null) {
244             StyledText st= viewer.getTextWidget();
245             if (st != null && !st.isDisposed()) {
246                 if (viewer instanceof ITextViewerExtension5) {
247                     int widgetLine= ((ITextViewerExtension5)viewer).modelLine2WidgetLine(line);
248                     Point loc= st.getLocationAtOffset(st.getOffsetAtLine(widgetLine));
249                     fCompositeRuler.setLocationOfLastMouseButtonActivity(0, loc.y);
250                 } else if (viewer instanceof TextViewer) {
251                     // TODO remove once TextViewer implements the extension
252
int widgetLine= ((TextViewer)viewer).modelLine2WidgetLine(line);
253                     Point loc= st.getLocationAtOffset(st.getOffsetAtLine(widgetLine));
254                     fCompositeRuler.setLocationOfLastMouseButtonActivity(0, loc.y);
255                 }
256             }
257         }
258     }
259
260     /**
261      * Returns the distance to the ruler line.
262      *
263      * @param position the position
264      * @param document the document
265      * @param line the line number
266      * @return the distance to the ruler line
267      */

268     protected int compareRulerLine(Position position, IDocument document, int line) {
269
270         if (position.getOffset() > -1 && position.getLength() > -1) {
271             try {
272                 int firstLine= document.getLineOfOffset(position.getOffset());
273                 if (line == firstLine)
274                     return 1;
275                 if (firstLine <= line && line <= document.getLineOfOffset(position.getOffset() + position.getLength()))
276                     return 2;
277             } catch (BadLocationException x) {
278             }
279         }
280
281         return 0;
282     }
283
284     /*
285      * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#getHoverControlCreator()
286      */

287     public IInformationControlCreator getHoverControlCreator() {
288         return fgCreator;
289     }
290
291     /*
292      * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#getHoverInfo(org.eclipse.jface.text.source.ISourceViewer, org.eclipse.jface.text.source.ILineRange, int)
293      */

294     public Object JavaDoc getHoverInfo(ISourceViewer sourceViewer, ILineRange lineRange, int visibleLines) {
295         return getHoverInfoForLine(sourceViewer, lineRange.getStartLine());
296     }
297
298     /*
299      * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#getHoverLineRange(org.eclipse.jface.text.source.ISourceViewer, int)
300      */

301     public ILineRange getHoverLineRange(ISourceViewer viewer, int lineNumber) {
302         return new LineRange(lineNumber, 1);
303     }
304
305     /*
306      * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#canHandleMouseCursor()
307      */

308     public boolean canHandleMouseCursor() {
309         return true;
310     }
311 }
312
Popular Tags