1 19 package org.netbeans.api.java.source.support; 20 21 import java.util.ArrayList ; 22 import java.util.HashMap ; 23 import java.util.List ; 24 import java.util.Map ; 25 import java.util.WeakHashMap ; 26 import javax.swing.event.CaretEvent ; 27 import javax.swing.event.CaretListener ; 28 import javax.swing.event.ChangeEvent ; 29 import javax.swing.event.ChangeListener ; 30 import javax.swing.text.JTextComponent ; 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 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 57 public CaretAwareJavaSourceTaskFactory(Phase phase, Priority priority) { 58 super(phase, priority); 59 OpenedEditors.getDefault().addChangeListener(new ChangeListenerImpl()); 61 this.timeout = DEFAULT_RESCHEDULE_TIMEOUT; 62 } 63 64 65 public List <FileObject> getFileObjects() { 66 List <FileObject> files = new ArrayList <FileObject>(OpenedEditors.getDefault().getVisibleEditorsFiles()); 67 68 return files; 69 } 70 71 private Map <JTextComponent , ComponentListener> component2Listener = new HashMap (); 72 private static Map <FileObject, Integer > file2LastPosition = new WeakHashMap (); 73 74 79 public synchronized static int getLastPosition(FileObject file) { 80 if (file == null) { 81 throw new NullPointerException ("Cannot pass null file!"); 82 } 83 84 Integer position = file2LastPosition.get(file); 85 86 if (position == null) { 87 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 { 99 100 public void stateChanged(ChangeEvent e) { 101 List <JTextComponent > added = new ArrayList <JTextComponent >(OpenedEditors.getDefault().getVisibleEditors()); 102 List <JTextComponent > removed = new ArrayList <JTextComponent >(component2Listener.keySet()); 103 104 added.removeAll(component2Listener.keySet()); 105 removed.removeAll(OpenedEditors.getDefault().getVisibleEditors()); 106 107 for (JTextComponent c : removed) { 108 c.removeCaretListener(component2Listener.remove(c)); 109 } 110 111 for (JTextComponent c : added) { 112 ComponentListener l = new ComponentListener(c); 113 114 c.addCaretListener(l); 115 component2Listener.put(c, l); 116 117 setLastPosition(OpenedEditors.getFileObject(c), c.getCaretPosition()); 119 } 120 121 fileObjectsChanged(); 122 } 123 124 } 125 126 private class ComponentListener implements CaretListener { 127 128 private JTextComponent component; 129 private final RequestProcessor.Task rescheduleTask; 130 131 public ComponentListener(JTextComponent component) { 132 this.component = component; 133 rescheduleTask = WORKER.create(new Runnable () { 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 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 |