KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > NbToolTip


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.editor;
21
22 import javax.swing.event.DocumentEvent JavaDoc;
23 import javax.swing.event.DocumentListener JavaDoc;
24 import javax.swing.text.AbstractDocument JavaDoc;
25 import javax.swing.text.JTextComponent JavaDoc;
26 import javax.swing.text.StyledDocument JavaDoc;
27 import javax.swing.text.BadLocationException JavaDoc;
28 import org.openide.filesystems.FileChangeAdapter;
29 import org.openide.filesystems.FileObject;
30 import org.openide.text.Annotation;
31 import org.openide.text.Line;
32 import java.io.IOException JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import org.netbeans.editor.ext.ToolTipSupport;
35 import org.openide.loaders.DataObjectNotFoundException;
36 import org.netbeans.editor.BaseDocument;
37 import org.netbeans.editor.Utilities;
38 import org.netbeans.editor.AnnotationDesc;
39 import org.netbeans.editor.ext.ExtEditorUI;
40 import org.netbeans.editor.ext.ExtUtilities;
41 import java.beans.PropertyChangeListener JavaDoc;
42 import org.openide.cookies.EditorCookie;
43 import org.openide.loaders.DataObject;
44 import org.openide.cookies.InstanceCookie;
45 import java.util.Enumeration JavaDoc;
46 import java.util.ArrayList JavaDoc;
47 import java.beans.PropertyChangeEvent JavaDoc;
48 import javax.swing.plaf.TextUI JavaDoc;
49 import org.netbeans.editor.BaseTextUI;
50 import org.openide.filesystems.Repository;
51 import org.openide.util.RequestProcessor;
52
53 /**
54 * ToolTip annotations reading and refreshing
55 *
56 * @author Miloslav Metelka
57 * @version 1.00
58 */

59
60 public class NbToolTip extends FileChangeAdapter {
61     
62     private static final boolean debug = Boolean.getBoolean("netbeans.debug.editor.tooltip");
63     
64     private static final HashMap JavaDoc mime2tip = new HashMap JavaDoc();
65     
66     private static int lastRequestId;
67     
68     private String JavaDoc mimeType;
69     
70     private Annotation[] tipAnnotations;
71     
72     private RequestProcessor toolTipRP = new RequestProcessor("ToolTip-Evaluator", 1); // NOI18N
73

74     static synchronized void buildToolTip(JTextComponent JavaDoc target) {
75         String JavaDoc mimeType = NbEditorUtilities.getMimeType(target.getDocument());
76         NbToolTip tip = getTip(mimeType);
77         tip.buildTip(target);
78     }
79     
80     private static int newRequestId() {
81         return ++lastRequestId;
82     }
83     
84     private static int getLastRequestId() {
85         return lastRequestId;
86     }
87     
88     
89     private NbToolTip(String JavaDoc mimeType) {
90         this.mimeType = mimeType;
91     }
92     
93     private static NbToolTip getTip(String JavaDoc mimeType) {
94         NbToolTip tip = (NbToolTip)mime2tip.get(mimeType);
95         if (tip == null) {
96             tip = new NbToolTip(mimeType);
97             mime2tip.put(mimeType, tip);
98         }
99         
100         return tip;
101     }
102
103     private Annotation[] getTipAnnotations() {
104         Annotation[] annos;
105         synchronized (NbToolTip.class) {
106             annos = tipAnnotations;
107         }
108         
109         if (annos == null) {
110
111             if (debug) {
112                 System.err.println("Searching for tooltip annotations for mimeType=" + mimeType);
113             }
114
115             FileObject annoFolder = Repository.getDefault().getDefaultFileSystem().
116             findResource("Editors/" + mimeType + "/ToolTips"); //NOI18N
117

118             if (debug) {
119                 System.err.println("tooltip annotation folder=" + annoFolder);
120             }
121
122             if (annoFolder != null) {
123                 ArrayList JavaDoc al = new ArrayList JavaDoc();
124                 Enumeration JavaDoc en = annoFolder.getChildren(false);
125                 while (en.hasMoreElements()) {
126                     FileObject fo = (FileObject)en.nextElement();
127                     
128                     if (debug) {
129                         System.err.println("tooltip annotation fileobject=" + fo);
130                     }
131
132                     try {
133                         DataObject dob = DataObject.find(fo);
134                         InstanceCookie ic = (InstanceCookie)dob.getCookie(InstanceCookie.class);
135
136                         if (debug) {
137                             System.err.println("tooltip annotation instanceCookie=" + ic);
138                         }
139
140                         if (ic != null) {
141                             Object JavaDoc a = ic.instanceCreate();
142
143                             if (debug) {
144                                 System.err.println("tooltip annotation instance=" + a);
145                             }
146
147                             if (a instanceof Annotation) {
148
149                                 if (debug) {
150                                     System.err.println("Found tooltip annotation=" + a
151                                         + ", class " + a.getClass() // NOI18N
152
+ " for mimeType=" + mimeType // NOI18N
153
);
154                                 }
155                                 
156                                 al.add(a);
157                             }
158                         }
159                     } catch (DataObjectNotFoundException e) {
160                     } catch (IOException JavaDoc e) {
161                     } catch (ClassNotFoundException JavaDoc e) {
162                     }
163                 }
164                 
165                 annos = (Annotation[])al.toArray(new Annotation[al.size()]);
166                 synchronized (NbToolTip.class) {
167                     tipAnnotations = annos;
168                 }
169                 
170                 annoFolder.addFileChangeListener(this);
171             }
172         }
173         
174         return annos;
175     }
176      
177     private void buildTip(JTextComponent JavaDoc target) {
178
179         TextUI JavaDoc textUI = target.getUI();
180         if (textUI!=null && textUI instanceof BaseTextUI){
181             BaseTextUI btui = (BaseTextUI)textUI;
182             ExtEditorUI editorUI = (ExtEditorUI)btui.getEditorUI();
183             ToolTipSupport tts = editorUI.getToolTipSupport();
184             String JavaDoc toolTipText = btui.getToolTipText(target, tts.getLastMouseEvent().getPoint());
185             if (toolTipText!=null){
186                 return;
187             }
188         }
189         
190         Annotation[] annos = getTipAnnotations();
191         if (annos != null) {
192             ExtEditorUI ui = ExtUtilities.getExtEditorUI(target);
193             if (ui != null) {
194                 ToolTipSupport tts = ui.getToolTipSupport();
195                 if (tts != null) {
196                     BaseDocument doc = Utilities.getDocument(target);
197                     if (doc != null) {
198                         DataObject dob = NbEditorUtilities.getDataObject(doc);
199                         if (dob != null && dob.isValid()) {
200                             EditorCookie ec = (EditorCookie)dob.getCookie(EditorCookie.class);
201                             if (ec != null) {
202                                 StyledDocument JavaDoc openedDoc;
203                                 try {
204                                     openedDoc = ec.openDocument();
205                                 } catch (IOException JavaDoc e) {
206                                     openedDoc = null; // should return in next if stmt
207
}
208
209                                 if (openedDoc != doc) { // doc has changed in meantime
210
return;
211                                 }
212
213                                 // partial fix of #33165 - read-locking of the document added
214
doc.readLock();
215                                 try {
216                                     int offset = target.viewToModel(tts.getLastMouseEvent().getPoint());
217                                     if (offset >= 0) {
218                                         try {
219                                             int line = Utilities.getLineOffset(doc, offset);
220                                             int col = offset - Utilities.getRowStart(target, offset);
221                                             Line.Set ls = ec.getLineSet();
222                                             if (ls != null) {
223                                                 Line l = ls.getCurrent(line);
224                                                 if (l != null) {
225                                                     Line.Part lp = l.createPart(col, 0);
226                                                     if (lp != null) {
227                                                         AnnotationDesc annoDesc = doc.getAnnotations().getActiveAnnotation(line);
228                                                         if (annoDesc != null && ((offset < annoDesc.getOffset() || offset >= annoDesc.getOffset() + annoDesc.getLength()))) {
229                                                             annoDesc = null;
230                                                         }
231                                                         org.netbeans.editor.BaseKit kit = org.netbeans.editor.Utilities.getKit(target);
232                                                         if (kit instanceof NbEditorKit) {
233                                                             int requestId = newRequestId();
234                                                             toolTipRP.post(new Request(annoDesc, annos, lp, tts, doc, (NbEditorKit)kit, requestId));
235                                                         }
236                                                     }
237                                                 }
238                                             }
239                                         } catch (BadLocationException JavaDoc e) {
240                                         }
241                                     }
242                                 } finally {
243                                     doc.readUnlock();
244                                 }
245                             }
246                         }
247                     }
248                 }
249             }
250         }
251     }
252         
253     private static class Request implements Runnable JavaDoc, PropertyChangeListener JavaDoc, DocumentListener JavaDoc {
254         
255         private ToolTipSupport tts;
256         
257         private Annotation[] annos;
258         
259         private AnnotationDesc annoDesc;
260         
261         private Line.Part linePart;
262         
263         private AbstractDocument JavaDoc doc;
264         
265         private NbEditorKit kit;
266         
267         private int requestId;
268         
269         private boolean documentModified;
270         
271         Request(AnnotationDesc annoDesc, Annotation[] annos, Line.Part lp,
272         ToolTipSupport tts, AbstractDocument JavaDoc doc, NbEditorKit kit, int requestId) {
273             this.annoDesc = annoDesc;
274             this.annos = annos;
275             this.linePart = lp;
276             this.tts = tts;
277             this.doc = doc;
278             this.kit = kit;
279             this.requestId = requestId;
280         }
281         
282         public void run() {
283             if (tts == null) return;
284             
285             if (tts == null || tts.getStatus() == ToolTipSupport.STATUS_HIDDEN) {
286                 return; // do nothing
287
}
288             if (!isRequestValid()) {
289                 return;
290             }
291
292             if (tts!=null) tts.addPropertyChangeListener(this);
293             
294             kit.toolTipAnnotationsLock(doc);
295             try {
296                 doc.readLock();
297                 try {
298
299                     if (!isRequestValid()) {
300                         return;
301                     }
302
303                     // Attach tooltip annotations
304
for (int i = 0; i < annos.length; i++) {
305                         annos[i].attach(linePart);
306                     }
307
308                     if (annoDesc != null && tts != null) {
309                         tts.setToolTipText(annoDesc.getShortDescription());
310                         annoDesc.addPropertyChangeListener(this);
311                     } else {
312                         for (int i = 0; i < annos.length; i++) {
313                             String JavaDoc desc = annos[i].getShortDescription();
314                             if (desc != null && tts != null) {
315                                 tts.setToolTipText(desc);
316                             }
317                             annos[i].addPropertyChangeListener(this);
318                         }
319                     }
320                 } finally {
321                     doc.readUnlock();
322                 }
323             } finally {
324                 kit.toolTipAnnotationsUnlock(doc);
325             }
326         }
327           
328         private boolean isRequestValid() {
329             return (getLastRequestId() == this.requestId)
330                 && !documentModified
331                 && isDocumentValid();
332         }
333
334         private boolean isDocumentValid() {
335             DataObject dob = NbEditorUtilities.getDataObject(doc);
336             if (dob != null) {
337                 EditorCookie ec = (EditorCookie)dob.getCookie(EditorCookie.class);
338                 if (ec != null) {
339                     StyledDocument JavaDoc openedDoc;
340                     try {
341                         openedDoc = ec.openDocument();
342                     } catch (IOException JavaDoc e) {
343                         openedDoc = null; // should return in next if stmt
344
}
345                     
346                     return (openedDoc == doc);
347                 }
348             }
349             return false;
350         }
351
352         private void dismiss() {
353             if (tts !=null) tts.removePropertyChangeListener(this);
354             tts = null; // signal that support no longer valid
355

356             if (annoDesc != null) {
357                 annoDesc.removePropertyChangeListener(this);
358             } else {
359                 for (int i = 0; i < annos.length; i++) {
360                     annos[i].removePropertyChangeListener(this);
361                     annos[i].detach();
362                 }
363             }
364         }
365
366         public void propertyChange(PropertyChangeEvent JavaDoc evt) {
367             String JavaDoc propName = evt.getPropertyName();
368             if (Annotation.PROP_SHORT_DESCRIPTION.equals(propName) || AnnotationDesc.PROP_SHORT_DESCRIPTION.equals(propName)) {
369                 if (evt.getNewValue() != null) {
370                     final String JavaDoc tipText = (String JavaDoc)evt.getNewValue();
371                     Utilities.runInEventDispatchThread( // ensure to run in AWT thread
372
new Runnable JavaDoc() {
373                             public void run() {
374                                 if (tts != null) {
375                                     tts.setToolTipText(tipText);
376                                 }
377                             }
378                         }
379                     );
380                 }
381                 
382             } else if (ToolTipSupport.PROP_STATUS.equals(propName)) {
383                 if (((Integer JavaDoc)evt.getNewValue()).intValue() == ToolTipSupport.STATUS_HIDDEN) {
384                     dismiss();
385                 }
386             }
387         }
388         
389         public void insertUpdate(DocumentEvent JavaDoc evt) {
390             documentModified = true;
391         }
392         
393         public void removeUpdate(DocumentEvent JavaDoc evt) {
394             documentModified = true;
395         }
396         
397         public void changedUpdate(DocumentEvent JavaDoc evt) {
398         }
399
400     }
401
402 }
403
Popular Tags