KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > api > retouche > source > support > CaretAwareSourceTaskFactory


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.retouche.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.retouche.source.Phase;
32 import org.netbeans.api.retouche.source.Source.Priority;
33 import org.netbeans.api.retouche.source.SourceTaskFactory;
34 import org.openide.filesystems.FileObject;
35 import org.openide.util.RequestProcessor;
36
37 /**
38  * This file is originally from Retouche, the Java Support
39  * infrastructure in NetBeans. I have modified the file as little
40  * as possible to make merging Retouche fixes back as simple as
41  * possible.
42  *
43  * A {@link SourceTaskFactorySupport} that registers tasks to all files that are
44  * opened in the editor and are visible. This factory also listens on the caret on
45  * opened and visible JTextComponents and reschedules the tasks as necessary.
46  *
47  * The tasks may access current caret position using {@link #getLastPosition} method.
48  *
49  * @author Jan Lahoda
50  */

51 public abstract class CaretAwareSourceTaskFactory extends SourceTaskFactory {
52     
53     private static final int DEFAULT_RESCHEDULE_TIMEOUT = 300;
54     private static final RequestProcessor WORKER = new RequestProcessor("CaretAwareSourceTaskFactory worker");
55     
56     private int timeout;
57     
58     /**Construct the CaretAwareSourceTaskFactory with given {@link Phase} and {@link Priority}.
59      *
60      * @param phase phase to use for tasks created by {@link #createTask}
61      * @param priority priority to use for tasks created by {@link #createTask}
62      */

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

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