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