1 19 package org.netbeans.api.retouche.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.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 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 63 public CaretAwareSourceTaskFactory(Phase phase, Priority priority) { 64 super(phase, priority); 65 OpenedEditors.getDefault().addChangeListener(new ChangeListenerImpl()); 67 this.timeout = DEFAULT_RESCHEDULE_TIMEOUT; 68 } 69 70 71 public List <FileObject> getFileObjects() { 72 List <FileObject> files = new ArrayList <FileObject>(OpenedEditors.getDefault().getVisibleEditorsFiles()); 73 74 return files; 75 } 76 77 private Map <JTextComponent , ComponentListener> component2Listener = new HashMap (); 78 private static Map <FileObject, Integer > file2LastPosition = new WeakHashMap (); 79 80 85 public synchronized static int getLastPosition(FileObject file) { 86 if (file == null) { 87 throw new NullPointerException ("Cannot pass null file!"); 88 } 89 90 Integer position = file2LastPosition.get(file); 91 92 if (position == null) { 93 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 { 106 107 public void stateChanged(ChangeEvent e) { 108 List <JTextComponent > added = new ArrayList <JTextComponent >(OpenedEditors.getDefault().getVisibleEditors()); 109 List <JTextComponent > removed = new ArrayList <JTextComponent >(component2Listener.keySet()); 110 111 added.removeAll(component2Listener.keySet()); 112 removed.removeAll(OpenedEditors.getDefault().getVisibleEditors()); 113 114 for (JTextComponent c : removed) { 115 c.removeCaretListener(component2Listener.remove(c)); 116 } 117 118 for (JTextComponent c : added) { 119 ComponentListener l = new ComponentListener(c); 120 121 c.addCaretListener(l); 122 component2Listener.put(c, l); 123 124 setLastPosition(OpenedEditors.getFileObject(c), c.getCaretPosition()); 126 } 127 128 fileObjectsChanged(); 129 } 130 131 } 132 133 private class ComponentListener implements CaretListener { 134 135 private JTextComponent component; 136 private final RequestProcessor.Task rescheduleTask; 137 138 public ComponentListener(JTextComponent component) { 139 this.component = component; 140 rescheduleTask = WORKER.create(new Runnable () { 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 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 |