KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > lib2 > DocumentsJumpList


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.lib2;
21
22 import java.beans.PropertyChangeEvent JavaDoc;
23 import java.beans.PropertyChangeListener JavaDoc;
24 import java.beans.PropertyChangeSupport JavaDoc;
25 import javax.swing.text.Document JavaDoc;
26 import javax.swing.text.JTextComponent JavaDoc;
27 import javax.swing.text.BadLocationException JavaDoc;
28 import javax.swing.text.Caret JavaDoc;
29 import javax.swing.text.Position JavaDoc;
30
31 /**
32 * The last several jumps in either the current file
33 * or across several files is stored here in the list.
34 * It's possible to track this list.
35 *
36 * @author Miloslav Metelka
37 * @version 1.00
38 */

39 public class DocumentsJumpList {
40
41     /** Maximum size to which the list will be shrinked
42     * if it exceeds the THRESHOLD_SIZE.
43     */

44     private static final int MAX_SIZE = 50;
45
46     /** Reaching this count means that the size should be checked
47     * and possibly shrinked to the MAX_SIZE.
48     */

49     private static final int CHECK_COUNT = 10;
50
51     /** Current jump list entry */
52     private static Entry currentEntry;
53
54     private static int checkCnt;
55     private static final PropertyChangeSupport JavaDoc support = new PropertyChangeSupport JavaDoc(DocumentsJumpList.class);;
56     private static boolean dotAtCurrentEntry = false;
57     
58     private static PropertyChangeListener JavaDoc registryListener = new PropertyChangeListener JavaDoc() {
59         public void propertyChange(PropertyChangeEvent JavaDoc e) {
60             support.firePropertyChange(null, null, null);
61         }
62     };
63     
64     static {
65         DocumentsRegistry.addPropertyChangeListener(registryListener);
66     }
67     
68     public static void addPropertyChangeListener(PropertyChangeListener JavaDoc listener) {
69         support.addPropertyChangeListener(listener);
70     }
71
72     public static void removePropertyChangeListener(PropertyChangeListener JavaDoc listener) {
73         support.removePropertyChangeListener(listener);
74     }
75     
76     public static void dotMoved(JTextComponent JavaDoc c, int offset) {
77         if (dotAtCurrentEntry && currentEntry != null && (currentEntry.getComponent() != c || currentEntry.getPosition() != offset)) {
78             support.firePropertyChange(null, null, null);
79             dotAtCurrentEntry = false;
80         } else {
81             dotAtCurrentEntry = currentEntry != null && currentEntry.getComponent() == c && currentEntry.getPosition() == offset;
82         }
83     }
84     
85     public static void checkAddEntry() {
86         JTextComponent JavaDoc c = DocumentsRegistry.getMostActiveComponent();
87         if (c != null) {
88             checkAddEntry(c, c.getCaret().getDot());
89         }
90     }
91
92     public static void checkAddEntry(JTextComponent JavaDoc c) {
93         checkAddEntry(c, c.getCaret().getDot());
94     }
95
96     public static void checkAddEntry(JTextComponent JavaDoc c, int pos) {
97         if (currentEntry == null
98                 || currentEntry.getComponent() != c
99                 || currentEntry.getPosition() != pos
100            ) {
101             addEntry(c, pos);
102         }
103     }
104
105     public static void addEntry(JTextComponent JavaDoc c, int pos) {
106         try {
107             Entry e = new Entry(c, pos, currentEntry);
108             currentEntry = e;
109             if (++checkCnt >= CHECK_COUNT) { // perform size check
110
sizeCheck();
111             }
112             dotAtCurrentEntry = true;
113         } catch (BadLocationException JavaDoc e) {
114             // entry not added
115
}
116     }
117
118     /**
119     * @param c current component. It's used to compare the current
120     * component and position with those stored in the entries.
121     */

122     public static void jumpPrev(JTextComponent JavaDoc c) {
123         int dotPos = c.getCaret().getDot();
124         if (currentEntry != null) {
125             while (true) {
126                 int entryPos = currentEntry.getPosition();
127                 JTextComponent JavaDoc entryComp = currentEntry.getComponent();
128                 if (entryComp != null && (entryComp != c || (entryPos >= 0 && entryPos != dotPos))) {
129                     if (currentEntry.setDot()) {
130                         support.firePropertyChange(null, null, null);
131                         break;
132                     }
133                 }
134                 if (currentEntry.prev != null) { // must check not to end up with null
135
currentEntry = currentEntry.prev;
136                 } else {
137                     break; // break when on the last entry
138
}
139             }
140         }
141     }
142
143     public static boolean hasPrev() {
144         JTextComponent JavaDoc c = DocumentsRegistry.getMostActiveComponent();
145         Caret JavaDoc caret = c != null ? c.getCaret() : null;
146         if (caret != null) {
147             Entry e = currentEntry;
148             if (e != null) {
149                 while (true) {
150                     int entryPos = e.getPosition();
151                     JTextComponent JavaDoc entryComp = e.getComponent();
152                     int dotPos = caret.getDot();
153                     if (entryComp != null && (entryComp != c || (entryPos >= 0 && entryPos != dotPos))) {
154                         if (entryPos >= 0 && entryPos <= entryComp.getDocument().getLength()) {
155                             return true;
156                         }
157                     }
158                     if (e.prev != null) { // must check not to end up with null
159
e = e.prev;
160                     } else {
161                         break; // break when on the last entry
162
}
163                 }
164             }
165         }
166         return false;
167     }
168
169     /**
170     * @param c current component. It's used to compare the current
171     * component and position with those stored in the entries.
172     */

173     public static void jumpNext(JTextComponent JavaDoc c) {
174         int dotPos = c.getCaret().getDot();
175         if (currentEntry != null)
176             currentEntry = currentEntry.next;
177         if (currentEntry != null) {
178             while (true) {
179                 int entryPos = currentEntry.getPosition();
180                 JTextComponent JavaDoc entryComp = currentEntry.getComponent();
181                 if (entryComp != null && (entryComp != c || (entryPos >= 0 && entryPos != dotPos))) {
182                     if (currentEntry.setDot()) {
183                         support.firePropertyChange(null, null, null);
184                         break;
185                     }
186                 }
187                 if (currentEntry.next != null) { // must check not to end up with null
188
currentEntry = currentEntry.next;
189                 } else {
190                     break; // break when on the last entry
191
}
192             }
193         }
194     }
195
196     public static boolean hasNext() {
197         JTextComponent JavaDoc c = DocumentsRegistry.getMostActiveComponent();
198         if (c != null) {
199             int dotPos = c.getCaret().getDot();
200             Entry e = currentEntry != null ? currentEntry.next : currentEntry;
201             if (e != null) {
202                 while (true) {
203                     int entryPos = e.getPosition();
204                     JTextComponent JavaDoc entryComp = e.getComponent();
205                     if (entryComp != null && (entryComp != c || (entryPos >= 0 && entryPos != dotPos))) {
206                         if (entryPos >= 0 && entryPos <= entryComp.getDocument().getLength()) {
207                             return true;
208                         }
209                     }
210                     if (e.next!= null) { // must check not to end up with null
211
e = e.next;
212                     } else {
213                         break; // break when on the last entry
214
}
215                 }
216             }
217         }
218         return false;
219     }
220
221     /**
222     * @param c current component. It's used to compare the current
223     * component to those stored in the jump list entries.
224     */

225     public static void jumpPrevComponent(JTextComponent JavaDoc c) {
226         if (currentEntry != null) {
227             while (true) {
228                 JTextComponent JavaDoc entryComp = currentEntry.getComponent();
229                 if (entryComp != null && entryComp != c) {
230                     if (currentEntry.setDot()) {
231                         break;
232                     }
233                 }
234                 if (currentEntry.prev != null) { // must check not to end up with null
235
currentEntry = currentEntry.prev;
236                 } else {
237                     break; // break when on the last entry
238
}
239             }
240         }
241     }
242
243     /**
244     * @param c current component. It's used to compare the current
245     * component to those stored in the jump list entries.
246     */

247     public static void jumpNextComponent(JTextComponent JavaDoc c) {
248         if (currentEntry != null) {
249             while (true) {
250                 JTextComponent JavaDoc entryComp = currentEntry.getComponent();
251                 if (entryComp != null && entryComp != c) {
252                     if (currentEntry.setDot()) {
253                         break;
254                     }
255                 }
256                 if (currentEntry.next != null) { // must check not to end up with null
257
currentEntry = currentEntry.next;
258                 } else {
259                     break; // break when on the last entry
260
}
261             }
262         }
263     }
264
265     public static String JavaDoc dump() {
266         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
267         int i = 0;
268         Entry e = currentEntry;
269         if (e != null) {
270             while (true) {
271                 if (e.prev != null) {
272                     e = e.prev;
273                     i--;
274                 } else {
275                     break;
276                 }
277             }
278
279             while (e != null) {
280                 JTextComponent JavaDoc comp = e.getComponent();
281                 String JavaDoc docStr = (comp != null) ?
282                                 (String JavaDoc)comp.getDocument().getProperty(Document.TitleProperty)
283                                 : "<Invalid document>"; // NOI18N
284
if (docStr == null) { // no title property
285
docStr = "Untitled"; // NOI18N
286
}
287                 sb.append("[" + i++ + "]=" + docStr + ", " + e.getPosition() + "\n"); // NOI18N
288
e = e.next;
289             }
290         } else { // null current entry
291
sb.append("Empty list"); // NOI18N
292
}
293         return sb.toString();
294     }
295
296     private static void sizeCheck() {
297         int cnt = MAX_SIZE;
298         Entry e = currentEntry;
299         while (e != null && cnt > 0) {
300             e = e.prev;
301             cnt--; // #19429
302
}
303         if (e != null) { // reached the one that should be the first
304
e.makeFirst();
305         }
306     }
307
308     public static class Entry {
309
310         /** ID of the stored position component */
311         private int componentID;
312
313         /** The position stored in the document */
314         private Position JavaDoc pos;
315
316         /** Previous entry in the linked list */
317         private Entry prev;
318
319         /** Next entry in the linked list */
320         private Entry next;
321
322         private Entry(JTextComponent JavaDoc component, int offset, Entry last) throws BadLocationException JavaDoc {
323             componentID = DocumentsRegistry.getID(component);
324 // TODO: remove
325
// posID = ((BaseDocument)component.getDocument()).storePosition(offset);
326
pos = component.getDocument().createPosition(offset);
327             if (last != null) { // apend after the last entry
328
last.next = this;
329                 this.prev = last;
330             }
331         }
332
333         public int getPosition() {
334             return pos.getOffset();
335         }
336
337         public JTextComponent JavaDoc getComponent() {
338             return DocumentsRegistry.getComponent(componentID);
339         }
340
341         /** Set the dot to the component and position
342         * stored in the mark.
343         * @return true if the caret was successfully moved
344         */

345         public boolean setDot() {
346             JTextComponent JavaDoc c = getComponent();
347             if (c != null) {
348                 if (DocumentsRegistry.getMostActiveComponent() != c) {
349                 
350                     ComponentUtils.requestFocus(c); // possibly request for the component
351
DocumentsRegistry.activate(c);
352                 }
353
354                 int pos = getPosition();
355                 if (pos >= 0 && pos <= c.getDocument().getLength()) {
356                     c.getCaret().setDot(pos); // set the dot
357
return true;
358                 }
359             }
360             return false;
361         }
362
363         void makeLast() {
364             if (next != null) {
365                 next.prev = null;
366                 next = null;
367             }
368         }
369
370         void makeFirst() {
371             if (prev != null) {
372                 prev.next = null;
373                 prev = null;
374             }
375         }
376
377 // TODO: remove
378
// protected void finalize() throws Throwable {
379
// JTextComponent c = DocumentsRegistry.getComponent(componentID);
380
// if (c != null) {
381
// ((BaseDocument)c.getDocument()).removeStoredPosition(posID);
382
// }
383
// super.finalize();
384
// }
385
}
386 }
387
Popular Tags