fixed bug #1115300, #1115292
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / JavaAnnotationHover.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.text;
12
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Map;
18
19 import net.sourceforge.phpdt.internal.corext.Assert;
20 import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
21 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
22
23 import org.eclipse.jface.preference.IPreferenceStore;
24 import org.eclipse.jface.text.BadLocationException;
25 import org.eclipse.jface.text.IDocument;
26 import org.eclipse.jface.text.Position;
27 import org.eclipse.jface.text.source.Annotation;
28 import org.eclipse.jface.text.source.IAnnotationHover;
29 import org.eclipse.jface.text.source.IAnnotationModel;
30 import org.eclipse.jface.text.source.ISourceViewer;
31 import org.eclipse.ui.editors.text.EditorsUI;
32 import org.eclipse.ui.texteditor.AnnotationPreference;
33
34 // TODO: delete this class ? we use PHPAnnotationHover instead !
35 /**
36  * Determines all markers for the given line and collects, concatenates, and formates
37  * their messages.
38  */
39 public class JavaAnnotationHover implements IAnnotationHover {
40         private static class JavaAnnotationHoverType {
41         }
42         
43         public static final JavaAnnotationHoverType OVERVIEW_RULER_HOVER= new JavaAnnotationHoverType();
44         public static final JavaAnnotationHoverType TEXT_RULER_HOVER= new JavaAnnotationHoverType();
45         public static final JavaAnnotationHoverType VERTICAL_RULER_HOVER= new JavaAnnotationHoverType();
46         
47         private IPreferenceStore fStore= PHPeclipsePlugin.getDefault().getPreferenceStore();
48         
49         private JavaAnnotationHoverType fType;
50         
51         public JavaAnnotationHover(JavaAnnotationHoverType type) {
52                 Assert.isTrue(OVERVIEW_RULER_HOVER.equals(type) || TEXT_RULER_HOVER.equals(type) || VERTICAL_RULER_HOVER.equals(type));
53                 fType= type;
54         }
55         
56         /**
57          * Returns the distance to the ruler line. 
58          */
59         protected int compareRulerLine(Position position, IDocument document, int line) {
60                 
61                 if (position.getOffset() > -1 && position.getLength() > -1) {
62                         try {
63                                 int javaAnnotationLine= document.getLineOfOffset(position.getOffset());
64                                 if (line == javaAnnotationLine)
65                                         return 1;
66                                 if (javaAnnotationLine <= line && line <= document.getLineOfOffset(position.getOffset() + position.getLength()))
67                                         return 2;
68                         } catch (BadLocationException x) {
69                         }
70                 }
71                 
72                 return 0;
73         }
74         
75         /**
76          * Selects a set of markers from the two lists. By default, it just returns
77          * the set of exact matches.
78          */
79         protected List select(List exactMatch, List including) {
80                 return exactMatch;
81         }
82         /**
83          * Returns one marker which includes the ruler's line of activity.
84          */
85         protected List getJavaAnnotationsForLine(ISourceViewer viewer, int line) {
86                 
87                 IDocument document= viewer.getDocument();
88                 IAnnotationModel model= viewer.getAnnotationModel();
89                 
90                 if (model == null)
91                         return null;
92                         
93                 List exact= new ArrayList();
94                 List including= new ArrayList();
95                 
96                 Iterator e= model.getAnnotationIterator();
97                 HashMap messagesAtPosition= new HashMap();
98                 while (e.hasNext()) {
99                         Annotation annotation= (Annotation) e.next();
100
101                         if (annotation.getText() == null)
102                                 continue;
103                         
104                         Position position= model.getPosition(annotation);
105                         if (position == null)
106                                 continue;
107                         
108                         AnnotationPreference preference= getAnnotationPreference(annotation);
109                         if (preference == null)
110                                 continue;
111                         
112                         if (OVERVIEW_RULER_HOVER.equals(fType)) {                               
113                                 String key= preference.getOverviewRulerPreferenceKey();
114                                 if (key == null || !fStore.getBoolean(key))
115                                         continue;
116                         } else if (TEXT_RULER_HOVER.equals(fType)) {
117                                 String key= preference.getTextPreferenceKey();
118                                 if (key != null) {
119                                         if (!fStore.getBoolean(key))
120                                                 continue;
121                                 } else {
122                                         key= preference.getHighlightPreferenceKey();
123                                         if (key == null || !fStore.getBoolean(key))
124                                                 continue;
125                                 }
126                         } else if (VERTICAL_RULER_HOVER.equals(fType)) {
127                                 String key= preference.getVerticalRulerPreferenceKey();
128                                 // backward compatibility
129                                 if (key != null && !fStore.getBoolean(key))
130                                         continue;
131                         }
132                         
133                         if (isDuplicateJavaAnnotation(messagesAtPosition, position, annotation.getText()))
134                                 continue;
135                         
136                         switch (compareRulerLine(position, document, line)) {
137                         case 1:
138                                 exact.add(annotation);
139                                 break;
140                         case 2:
141                                 including.add(annotation);
142                                 break;
143                         }
144                 }
145                 
146                 return select(exact, including);
147         }
148 //      /**
149 //       * Returns one marker which includes the ruler's line of activity.
150 //       */
151 //      protected List getJavaAnnotationsForLine(ISourceViewer viewer, int line) {
152 //              
153 //              IDocument document= viewer.getDocument();
154 //              IAnnotationModel model= viewer.getAnnotationModel();
155 //              
156 //              if (model == null)
157 //                      return null;
158 //                      
159 //              List exact= new ArrayList();
160 //              List including= new ArrayList();
161 //              
162 //              Iterator e= model.getAnnotationIterator();
163 //              HashMap messagesAtPosition= new HashMap();
164 //              while (e.hasNext()) {
165 //                      Object o= e.next();
166 //                      if (o instanceof IJavaAnnotation) {
167 //                              IJavaAnnotation a= (IJavaAnnotation)o;
168 //                              if (!a.hasOverlay()) {
169 //                                      Position position= model.getPosition((Annotation)a);
170 //                                      if (position == null)
171 //                                              continue;
172 //
173 //                                      if (isDuplicateJavaAnnotation(messagesAtPosition, position, a.getMessage()))
174 //                                              continue;
175 //      
176 //                                      switch (compareRulerLine(position, document, line)) {
177 //                                              case 1:
178 //                                                      exact.add(a);
179 //                                                      break;
180 //                                              case 2:
181 //                                                      including.add(a);
182 //                                                      break;
183 //                                      }
184 //                              }
185 //                      }
186 //              }
187 //              
188 //              return select(exact, including);
189 //      }
190
191         private boolean isDuplicateJavaAnnotation(Map messagesAtPosition, Position position, String message) {
192                 if (messagesAtPosition.containsKey(position)) {
193                         Object value= messagesAtPosition.get(position);
194                         if (message.equals(value))
195                                 return true;
196
197                         if (value instanceof List) {
198                                 List messages= (List)value;
199                                 if  (messages.contains(message))
200                                         return true;
201                                 else
202                                         messages.add(message);
203                         } else {
204                                 ArrayList messages= new ArrayList();
205                                 messages.add(value);
206                                 messages.add(message);
207                                 messagesAtPosition.put(position, messages);
208                         }
209                 } else
210                         messagesAtPosition.put(position, message);
211                 return false;
212         }
213         
214         /*
215          * @see IVerticalRulerHover#getHoverInfo(ISourceViewer, int)
216          */
217         public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) {
218                 List javaAnnotations= getJavaAnnotationsForLine(sourceViewer, lineNumber);
219                 if (javaAnnotations != null) {
220                         
221                         if (javaAnnotations.size() == 1) {
222                                 
223                                 // optimization
224                                 Annotation annotation= (Annotation) javaAnnotations.get(0);
225                                 String message= annotation.getText();
226                                 if (message != null && message.trim().length() > 0)
227                                         return formatSingleMessage(message);
228                                         
229                         } else {
230                                         
231                                 List messages= new ArrayList();
232                                 
233                                 Iterator e= javaAnnotations.iterator();
234                                 while (e.hasNext()) {
235                                         Annotation annotation= (Annotation) e.next();
236                                         String message= annotation.getText();
237                                         if (message != null && message.trim().length() > 0)
238                                                 messages.add(message.trim());
239                                 }
240                                 
241                                 if (messages.size() == 1)
242                                         return formatSingleMessage((String) messages.get(0));
243                                         
244                                 if (messages.size() > 1)
245                                         return formatMultipleMessages(messages);
246                         }
247                 }
248                 
249                 return null;
250         }
251         /*
252          * @see IVerticalRulerHover#getHoverInfo(ISourceViewer, int)
253          */
254 //      public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) {
255 //              List javaAnnotations= getJavaAnnotationsForLine(sourceViewer, lineNumber);
256 //              if (javaAnnotations != null) {
257 //                      
258 //                      if (javaAnnotations.size() == 1) {
259 //                              
260 //                              // optimization
261 //                              IJavaAnnotation javaAnnotation= (IJavaAnnotation) javaAnnotations.get(0);
262 //                              String message= javaAnnotation.getMessage();
263 //                              if (message != null && message.trim().length() > 0)
264 //                                      return formatSingleMessage(message);
265 //                                      
266 //                      } else {
267 //                                      
268 //                              List messages= new ArrayList();
269 //                              
270 //                              Iterator e= javaAnnotations.iterator();
271 //                              while (e.hasNext()) {
272 //                                      IJavaAnnotation javaAnnotation= (IJavaAnnotation) e.next();
273 //                                      String message= javaAnnotation.getMessage();
274 //                                      if (message != null && message.trim().length() > 0)
275 //                                              messages.add(message.trim());
276 //                              }
277 //                              
278 //                              if (messages.size() == 1)
279 //                                      return formatSingleMessage((String) messages.get(0));
280 //                                      
281 //                              if (messages.size() > 1)
282 //                                      return formatMultipleMessages(messages);
283 //                      }
284 //              }
285 //              
286 //              return null;
287 //      }
288         
289         /*
290          * Formats a message as HTML text.
291          */
292         private String formatSingleMessage(String message) {
293                 StringBuffer buffer= new StringBuffer();
294                 HTMLPrinter.addPageProlog(buffer);
295                 HTMLPrinter.addParagraph(buffer, HTMLPrinter.convertToHTMLContent(message));
296                 HTMLPrinter.addPageEpilog(buffer);
297                 return buffer.toString();
298         }
299         
300         /*
301          * Formats several message as HTML text.
302          */
303         private String formatMultipleMessages(List messages) {
304                 StringBuffer buffer= new StringBuffer();
305                 HTMLPrinter.addPageProlog(buffer);
306                 HTMLPrinter.addParagraph(buffer, HTMLPrinter.convertToHTMLContent(PHPUIMessages.getString("JavaAnnotationHover.multipleMarkersAtThisLine"))); //$NON-NLS-1$
307                 
308                 HTMLPrinter.startBulletList(buffer);
309                 Iterator e= messages.iterator();
310                 while (e.hasNext())
311                         HTMLPrinter.addBullet(buffer, HTMLPrinter.convertToHTMLContent((String) e.next()));
312                 HTMLPrinter.endBulletList(buffer);      
313                 
314                 HTMLPrinter.addPageEpilog(buffer);
315                 return buffer.toString();
316         }
317         
318         /**
319          * Returns the annotation preference for the given annotation.
320          * 
321          * @param annotation the annotation
322          * @return the annotation preference or <code>null</code> if none
323          */     
324         private AnnotationPreference getAnnotationPreference(Annotation annotation) {
325                 return EditorsUI.getAnnotationPreferenceLookup().getAnnotationPreference(annotation);
326         }
327 }