KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > lib2 > highlighting > CaretBasedBlockHighlighting


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.highlighting;
21
22 import java.beans.PropertyChangeEvent JavaDoc;
23 import java.beans.PropertyChangeListener JavaDoc;
24 import java.util.logging.Level JavaDoc;
25 import java.util.logging.Logger JavaDoc;
26 import javax.swing.event.ChangeEvent JavaDoc;
27 import javax.swing.event.ChangeListener JavaDoc;
28 import javax.swing.text.AttributeSet JavaDoc;
29 import javax.swing.text.BadLocationException JavaDoc;
30 import javax.swing.text.Caret JavaDoc;
31 import javax.swing.text.Document JavaDoc;
32 import javax.swing.text.EditorKit JavaDoc;
33 import javax.swing.text.JTextComponent JavaDoc;
34 import javax.swing.text.Position JavaDoc;
35 import javax.swing.text.SimpleAttributeSet JavaDoc;
36 import org.netbeans.api.editor.mimelookup.MimeLookup;
37 import org.netbeans.api.editor.mimelookup.MimePath;
38 import org.netbeans.api.editor.settings.AttributesUtilities;
39 import org.netbeans.api.editor.settings.FontColorNames;
40 import org.netbeans.api.editor.settings.FontColorSettings;
41 import org.netbeans.modules.editor.lib2.DocUtils;
42 import org.netbeans.spi.editor.highlighting.HighlightsSequence;
43 import org.netbeans.spi.editor.highlighting.support.AbstractHighlightsContainer;
44 import org.openide.util.WeakListeners;
45
46 /**
47  * The layer for highlighting a caret row.
48  *
49  * @author Vita Stejskal
50  */

51 public abstract class CaretBasedBlockHighlighting extends AbstractHighlightsContainer implements ChangeListener JavaDoc, PropertyChangeListener JavaDoc {
52
53     private static final Logger JavaDoc LOG = Logger.getLogger(CaretBasedBlockHighlighting.class.getName());
54     
55     private final MimePath mimePath;
56     private final JTextComponent JavaDoc component;
57     private Caret JavaDoc caret;
58     private ChangeListener JavaDoc caretListener;
59     
60     private final String JavaDoc coloringName;
61     private final boolean extendsEOL;
62     private final boolean extendsEmptyLine;
63     
64     private Position JavaDoc currentLineStart;
65     private Position JavaDoc currentLineEnd;
66     
67     /** Creates a new instance of CaretSelectionLayer */
68     protected CaretBasedBlockHighlighting(JTextComponent JavaDoc component, String JavaDoc coloringName, boolean extendsEOL, boolean extendsEmptyLine) {
69         // Determine the mime type
70
EditorKit JavaDoc kit = component.getUI().getEditorKit(component);
71         String JavaDoc mimeType = kit == null ? null : kit.getContentType();
72         this.mimePath = mimeType == null ? MimePath.EMPTY : MimePath.parse(mimeType);
73
74         this.coloringName = coloringName;
75         this.extendsEOL = extendsEOL;
76         this.extendsEmptyLine = extendsEmptyLine;
77         
78         // Hook up the component
79
this.component = component;
80         this.component.addPropertyChangeListener(WeakListeners.propertyChange(this, this.component));
81
82         // Hook up the caret
83
this.caret = component.getCaret();
84         if (this.caret != null) {
85             this.caretListener = WeakListeners.change(this, this.caret);
86             this.caret.addChangeListener(caretListener);
87         }
88
89         // Calculate the current line position
90
updateLineInfo(false);
91     }
92
93     // ------------------------------------------------
94
// AbstractHighlightsContainer implementation
95
// ------------------------------------------------
96

97     public final HighlightsSequence getHighlights(int startOffset, int endOffset) {
98         if (currentLineStart != null && currentLineEnd != null &&
99             endOffset >= currentLineStart.getOffset() && startOffset <= currentLineEnd.getOffset())
100         {
101             return new SimpleHighlightsSequence(
102                 Math.max(currentLineStart.getOffset(), startOffset),
103                 Math.min(currentLineEnd.getOffset(), endOffset),
104                 getAttribs()
105             );
106         } else {
107             return HighlightsSequence.EMPTY;
108         }
109     }
110
111     // ------------------------------------------------
112
// PropertyChangeListener implementation
113
// ------------------------------------------------
114

115     public final void propertyChange(PropertyChangeEvent JavaDoc evt) {
116         if (evt.getPropertyName() == null || "caret".equals(evt.getPropertyName())) { //NOI18N
117
if (caret != null) {
118                 caret.removeChangeListener(caretListener);
119                 caretListener = null;
120             }
121             
122             caret = component.getCaret();
123             
124             if (caret != null) {
125                 caretListener = WeakListeners.change(this, caret);
126                 caret.addChangeListener(caretListener);
127             }
128             
129             updateLineInfo(true);
130         }
131     }
132     
133     // ------------------------------------------------
134
// ChangeListener implementation
135
// ------------------------------------------------
136

137     public final void stateChanged(ChangeEvent JavaDoc e) {
138         updateLineInfo(true);
139     }
140
141     protected abstract Position JavaDoc [] getCurrentBlockPositions(Document JavaDoc document, Caret JavaDoc caret);
142     
143     // ------------------------------------------------
144
// private implementation
145
// ------------------------------------------------
146

147     private final void updateLineInfo(boolean fire) {
148         Position JavaDoc [] currentLine = getCurrentBlockPositions(component.getDocument(), caret);
149         
150         if (!comparePositions(currentLine[0], currentLineStart) ||
151             !comparePositions(currentLine[1], currentLineEnd))
152         {
153             Position JavaDoc changeStart = getLowerPosition(currentLine[0], currentLineStart);
154             Position JavaDoc changeEnd = getHigherPosition(currentLine[1], currentLineEnd);
155
156             if (LOG.isLoggable(Level.FINE)) {
157                 LOG.fine("Current row changed from [" //NOI18N
158
+ positionToString(currentLineStart) + ", " + positionToString(currentLineEnd) + "] to [" //NOI18N
159
+ positionToString(currentLine[0]) + ", " + positionToString(currentLine[1]) + "]"); //NOI18N
160
}
161             
162             currentLineStart = currentLine[0];
163             currentLineEnd = currentLine[1];
164
165             if (fire) {
166                 fireHighlightsChange(
167                     changeStart == null ? 0 : changeStart.getOffset(),
168                     changeEnd == null ? Integer.MAX_VALUE : changeEnd.getOffset()
169                 );
170             }
171         }
172     }
173     
174     private AttributeSet JavaDoc getAttribs() {
175         FontColorSettings fcs = MimeLookup.getLookup(mimePath).lookup(FontColorSettings.class);
176         AttributeSet JavaDoc attribs = fcs.getFontColors(coloringName);
177         
178         if (attribs == null) {
179             attribs = SimpleAttributeSet.EMPTY;
180         } else if (extendsEOL || extendsEmptyLine) {
181             attribs = AttributesUtilities.createImmutable(
182                 attribs,
183                 AttributesUtilities.createImmutable(
184                     ATTR_EXTENDS_EOL, Boolean.valueOf(extendsEOL),
185                     ATTR_EXTENDS_EMPTY_LINE, Boolean.valueOf(extendsEmptyLine))
186             );
187         }
188         
189         return attribs;
190     }
191     
192     private static boolean comparePositions(Position JavaDoc p1, Position JavaDoc p2) {
193         return (p1 == null && p2 == null) ||
194                (p1 != null && p2 != null && p1.getOffset() == p2.getOffset());
195     }
196     
197     private static Position JavaDoc getLowerPosition(Position JavaDoc p1, Position JavaDoc p2) {
198         if (p1 != null && p2 != null) {
199             return p1.getOffset() < p2.getOffset() ? p1 : p2;
200         } else if (p1 != null) {
201             return p1;
202         } else if (p2 != null) {
203             return p2;
204         } else {
205             return null;
206         }
207     }
208     
209     private static Position JavaDoc getHigherPosition(Position JavaDoc p1, Position JavaDoc p2) {
210         if (p1 != null && p2 != null) {
211             return p1.getOffset() > p2.getOffset() ? p1 : p2;
212         } else if (p1 != null) {
213             return p1;
214         } else if (p2 != null) {
215             return p2;
216         } else {
217             return null;
218         }
219     }
220     
221     private static String JavaDoc positionToString(Position JavaDoc p) {
222         return p == null ? "null" : Integer.toString(p.getOffset()); //NOI18N
223
}
224     
225     private static final class SimpleHighlightsSequence implements HighlightsSequence {
226         
227         private int startOffset;
228         private int endOffset;
229         private AttributeSet JavaDoc attribs;
230         
231         private boolean end = false;
232         
233         public SimpleHighlightsSequence(int startOffset, int endOffset, AttributeSet JavaDoc attribs) {
234             this.startOffset = startOffset;
235             this.endOffset = endOffset;
236             this.attribs = attribs;
237         }
238
239         public boolean moveNext() {
240             if (!end) {
241                 end = true;
242                 return true;
243             } else {
244                 return false;
245             }
246         }
247
248         public int getStartOffset() {
249             return startOffset;
250         }
251
252         public int getEndOffset() {
253             return endOffset;
254         }
255
256         public AttributeSet JavaDoc getAttributes() {
257             return attribs;
258         }
259     } // End of SimpleHighlightsSequence
260

261     public static final class CaretRowHighlighting extends CaretBasedBlockHighlighting {
262         
263         public static final String JavaDoc LAYER_TYPE_ID = "org.netbeans.modules.editor.lib2.highlighting.CaretRowHighlighting"; //NOI18N
264

265         public CaretRowHighlighting(JTextComponent JavaDoc component) {
266             super(component, FontColorNames.CARET_ROW_COLORING, true, false);
267         }
268         
269         protected Position JavaDoc[] getCurrentBlockPositions(Document JavaDoc document, Caret JavaDoc caret) {
270             if (document != null && caret != null) {
271                 int caretOffset = caret.getDot();
272                 try {
273                     int startOffset = DocUtils.getRowStart(document, caretOffset, 0);
274                     int endOffset = DocUtils.getRowEnd(document, caretOffset);
275
276                     if (endOffset < document.getLength()) {
277                         endOffset++; // include the new-line character
278
}
279
280                     return new Position JavaDoc [] {
281                         document.createPosition(startOffset),
282                         document.createPosition(endOffset),
283                     };
284                 } catch (BadLocationException JavaDoc e) {
285                     LOG.log(Level.WARNING, e.getMessage(), e);
286                 }
287             }
288
289             return new Position JavaDoc [] { null, null };
290         }
291     } // End of CaretRowHighlighting class
292

293     public static final class TextSelectionHighlighting extends CaretBasedBlockHighlighting {
294         
295         public static final String JavaDoc LAYER_TYPE_ID = "org.netbeans.modules.editor.lib2.highlighting.TextSelectionHighlighting"; //NOI18N
296

297         public TextSelectionHighlighting(JTextComponent JavaDoc component) {
298             super(component, FontColorNames.SELECTION_COLORING, false, true);
299         }
300     
301         protected Position JavaDoc[] getCurrentBlockPositions(Document JavaDoc document, Caret JavaDoc caret) {
302             if (document != null && caret != null) {
303                 int caretOffset = caret.getDot();
304                 int markOffset = caret.getMark();
305
306                 if (caretOffset != markOffset) {
307                     try {
308                         return new Position JavaDoc [] {
309                             document.createPosition(Math.min(caretOffset, markOffset)),
310                             document.createPosition(Math.max(caretOffset, markOffset)),
311                         };
312                     } catch (BadLocationException JavaDoc e) {
313                         LOG.log(Level.WARNING, e.getMessage(), e);
314                     }
315                 }
316             }
317             
318             return new Position JavaDoc [] { null, null };
319         }
320     } // End of TextSelectionHighlighting class
321
}
322
Popular Tags