KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > api > java > source > support > CaretAwareJavaSourceTaskFactory


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 package org.netbeans.api.java.source.support;
20
21 import java.util.ArrayList JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.WeakHashMap JavaDoc;
26 import javax.swing.event.CaretEvent JavaDoc;
27 import javax.swing.event.CaretListener JavaDoc;
28 import javax.swing.event.ChangeEvent JavaDoc;
29 import javax.swing.event.ChangeListener JavaDoc;
30 import javax.swing.text.JTextComponent JavaDoc;
31 import org.netbeans.api.java.source.JavaSource.Phase;
32 import org.netbeans.api.java.source.JavaSource.Priority;
33 import org.netbeans.api.java.source.JavaSourceTaskFactory;
34 import org.openide.filesystems.FileObject;
35 import org.openide.util.RequestProcessor;
36
37 /**A {@link JavaSourceTaskFactorySupport} that registers tasks to all files that are
38  * opened in the editor and are visible. This factory also listens on the caret on
39  * opened and visible JTextComponents and reschedules the tasks as necessary.
40  *
41  * The tasks may access current caret position using {@link #getLastPosition} method.
42  *
43  * @author Jan Lahoda
44  */

45 public abstract class CaretAwareJavaSourceTaskFactory extends JavaSourceTaskFactory {
46     
47     private static final int DEFAULT_RESCHEDULE_TIMEOUT = 300;
48     private static final RequestProcessor WORKER = new RequestProcessor("CaretAwareJavaSourceTaskFactory worker");
49     
50     private int timeout;
51     
52     /**Construct the CaretAwareJavaSourceTaskFactory with given {@link Phase} and {@link Priority}.
53      *
54      * @param phase phase to use for tasks created by {@link #createTask}
55      * @param priority priority to use for tasks created by {@link #createTask}
56      */

57     public CaretAwareJavaSourceTaskFactory(Phase phase, Priority priority) {
58         super(phase, priority);
59         //XXX: weak, or something like this:
60
OpenedEditors.getDefault().addChangeListener(new ChangeListenerImpl());
61         this.timeout = DEFAULT_RESCHEDULE_TIMEOUT;
62     }
63     
64     /**@inheritDoc*/
65     public List JavaDoc<FileObject> getFileObjects() {
66         List JavaDoc<FileObject> files = new ArrayList JavaDoc<FileObject>(OpenedEditors.getDefault().getVisibleEditorsFiles());
67
68         return files;
69     }
70
71     private Map JavaDoc<JTextComponent JavaDoc, ComponentListener> component2Listener = new HashMap JavaDoc();
72     private static Map JavaDoc<FileObject, Integer JavaDoc> file2LastPosition = new WeakHashMap JavaDoc();
73     
74     /**Returns current caret position in current {@link JTextComponent} for a given file.
75      *
76      * @param file file from which the position should be found
77      * @return caret position in the current {@link JTextComponent} for a given file.
78      */

79     public synchronized static int getLastPosition(FileObject file) {
80         if (file == null) {
81             throw new NullPointerException JavaDoc("Cannot pass null file!");
82         }
83         
84         Integer JavaDoc position = file2LastPosition.get(file);
85         
86         if (position == null) {
87             //no position set yet:
88
return 0;
89         }
90         
91         return position;
92     }
93     
94     synchronized static void setLastPosition(FileObject file, int position) {
95        file2LastPosition.put(file, position);
96     }
97     
98     private class ChangeListenerImpl implements ChangeListener JavaDoc {
99         
100         public void stateChanged(ChangeEvent JavaDoc e) {
101             List JavaDoc<JTextComponent JavaDoc> added = new ArrayList JavaDoc<JTextComponent JavaDoc>(OpenedEditors.getDefault().getVisibleEditors());
102             List JavaDoc<JTextComponent JavaDoc> removed = new ArrayList JavaDoc<JTextComponent JavaDoc>(component2Listener.keySet());
103             
104             added.removeAll(component2Listener.keySet());
105             removed.removeAll(OpenedEditors.getDefault().getVisibleEditors());
106             
107             for (JTextComponent JavaDoc c : removed) {
108                 c.removeCaretListener(component2Listener.remove(c));
109             }
110             
111             for (JTextComponent JavaDoc c : added) {
112                 ComponentListener l = new ComponentListener(c);
113                 
114                 c.addCaretListener(l);
115                 component2Listener.put(c, l);
116                 
117                 //TODO: are we in AWT Thread?:
118
setLastPosition(OpenedEditors.getFileObject(c), c.getCaretPosition());
119             }
120             
121             fileObjectsChanged();
122         }
123         
124     }
125     
126     private class ComponentListener implements CaretListener JavaDoc {
127         
128         private JTextComponent JavaDoc component;
129         private final RequestProcessor.Task rescheduleTask;
130         
131         public ComponentListener(JTextComponent JavaDoc component) {
132             this.component = component;
133             rescheduleTask = WORKER.create(new Runnable JavaDoc() {
134                 public void run() {
135                     FileObject file = OpenedEditors.getFileObject(ComponentListener.this.component);
136                     
137                     if (file != null) {
138                         setLastPosition(file, ComponentListener.this.component.getCaretPosition());
139                         reschedule(file);
140                     }
141                 }
142             });
143         }
144         
145         public void caretUpdate(CaretEvent JavaDoc e) {
146             FileObject file = OpenedEditors.getFileObject(component);
147             
148             if (file != null) {
149                 setLastPosition(file, component.getCaretPosition());
150                 rescheduleTask.schedule(timeout);
151             }
152         }
153         
154     }
155 }
156
Popular Tags