KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > texteditor > AnnotationExpandHover


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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.ui.internal.texteditor;
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.ui.internal.texteditor.AnnotationExpansionControl.AnnotationHoverInput;
51
52 /**
53  * @since 3.0
54  */

55 public class AnnotationExpandHover implements IAnnotationHover, IAnnotationHoverExtension {
56
57     private class InformationControlCreator implements IInformationControlCreator, IInformationControlCreatorExtension {
58
59         /*
60          * @see org.eclipse.jface.text.IInformationControlCreator#createInformationControl(org.eclipse.swt.widgets.Shell)
61          */

62         public IInformationControl createInformationControl(Shell parent) {
63             return new AnnotationExpansionControl(parent, SWT.NONE, fAnnotationAccess);
64         }
65
66         /*
67          * @see org.eclipse.jface.text.IInformationControlCreatorExtension#canReuse(org.eclipse.jface.text.IInformationControl)
68          */

69         public boolean canReuse(IInformationControl control) {
70             return control instanceof AnnotationExpansionControl;
71         }
72
73         /*
74          * @see org.eclipse.jface.text.IInformationControlCreatorExtension#canReplace(org.eclipse.jface.text.IInformationControlCreator)
75          */

76         public boolean canReplace(IInformationControlCreator creator) {
77             return creator == this;
78         }
79     }
80
81     private class VerticalRulerListener implements IVerticalRulerListener {
82
83         /*
84          * @see org.eclipse.jface.text.source.IVerticalRulerListener#annotationSelected(org.eclipse.jface.text.source.VerticalRulerEvent)
85          */

86         public void annotationSelected(VerticalRulerEvent event) {
87             fCompositeRuler.fireAnnotationSelected(event);
88         }
89
90         /*
91          * @see org.eclipse.jface.text.source.IVerticalRulerListener#annotationDefaultSelected(org.eclipse.jface.text.source.VerticalRulerEvent)
92          */

93         public void annotationDefaultSelected(VerticalRulerEvent event) {
94             fCompositeRuler.fireAnnotationDefaultSelected(event);
95         }
96
97         /*
98          * @see org.eclipse.jface.text.source.IVerticalRulerListener#annotationContextMenuAboutToShow(org.eclipse.jface.text.source.VerticalRulerEvent, org.eclipse.swt.widgets.Menu)
99          */

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

119     public AnnotationExpandHover(CompositeRuler ruler, IAnnotationAccess access, IDoubleClickListener doubleClickListener) {
120         fCompositeRuler= ruler;
121         fAnnotationAccess= access;
122         fDblClickListener= doubleClickListener;
123     }
124
125     /*
126      * @see org.eclipse.jface.text.source.IAnnotationHover#getHoverInfo(org.eclipse.jface.text.source.ISourceViewer, int)
127      */

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

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

260     protected int compareRulerLine(Position position, IDocument document, int line) {
261
262         if (position.getOffset() > -1 && position.getLength() > -1) {
263             try {
264                 int firstLine= document.getLineOfOffset(position.getOffset());
265                 if (line == firstLine)
266                     return 1;
267                 if (firstLine <= line && line <= document.getLineOfOffset(position.getOffset() + position.getLength()))
268                     return 2;
269             } catch (BadLocationException x) {
270             }
271         }
272
273         return 0;
274     }
275
276     /*
277      * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#getHoverControlCreator()
278      */

279     public IInformationControlCreator getHoverControlCreator() {
280         return fgCreator;
281     }
282
283     /*
284      * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#getHoverInfo(org.eclipse.jface.text.source.ISourceViewer, org.eclipse.jface.text.source.ILineRange, int)
285      */

286     public Object JavaDoc getHoverInfo(ISourceViewer sourceViewer, ILineRange lineRange, int visibleLines) {
287         return getHoverInfoForLine(sourceViewer, lineRange.getStartLine());
288     }
289
290     /*
291      * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#getHoverLineRange(org.eclipse.jface.text.source.ISourceViewer, int)
292      */

293     public ILineRange getHoverLineRange(ISourceViewer viewer, int lineNumber) {
294         return new LineRange(lineNumber, 1);
295     }
296
297     /*
298      * @see org.eclipse.jface.text.source.IAnnotationHoverExtension#canHandleMouseCursor()
299      */

300     public boolean canHandleMouseCursor() {
301         return true;
302     }
303 }
304
Popular Tags