Source Code Cross Referenced for HighlightingDrawLayer.java in  » IDE-Netbeans » editor » org » netbeans » editor » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » editor » org.netbeans.editor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         *
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * The contents of this file are subject to the terms of either the GNU
007:         * General Public License Version 2 only ("GPL") or the Common
008:         * Development and Distribution License("CDDL") (collectively, the
009:         * "License"). You may not use this file except in compliance with the
010:         * License. You can obtain a copy of the License at
011:         * http://www.netbeans.org/cddl-gplv2.html
012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013:         * specific language governing permissions and limitations under the
014:         * License.  When distributing the software, include this License Header
015:         * Notice in each file and include the License file at
016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
017:         * particular file as subject to the "Classpath" exception as provided
018:         * by Sun in the GPL Version 2 section of the License file that
019:         * accompanied this code. If applicable, add the following below the
020:         * License Header, with the fields enclosed by brackets [] replaced by
021:         * your own identifying information:
022:         * "Portions Copyrighted [year] [name of copyright owner]"
023:         *
024:         * Contributor(s):
025:         *
026:         * The Original Software is NetBeans. The Initial Developer of the Original
027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028:         * Microsystems, Inc. All Rights Reserved.
029:         *
030:         * If you wish your version of this file to be governed by only the CDDL
031:         * or only the GPL Version 2, indicate your decision by adding
032:         * "[Contributor] elects to include this software in this distribution
033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
034:         * single choice of license, a recipient has the option to distribute
035:         * your version of this file under either the CDDL, the GPL Version 2 or
036:         * to extend the choice of license to its licensees as provided above.
037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
038:         * Version 2 license, then the option applies only if the new code is
039:         * made subject to such option by the copyright holder.
040:         */
041:
042:        package org.netbeans.editor;
043:
044:        import java.lang.ref.WeakReference;
045:        import java.util.ArrayList;
046:        import java.util.Collections;
047:        import java.util.List;
048:        import java.util.logging.Level;
049:        import java.util.logging.Logger;
050:        import javax.swing.JEditorPane;
051:        import javax.swing.SwingUtilities;
052:        import javax.swing.text.AbstractDocument;
053:        import javax.swing.text.AttributeSet;
054:        import javax.swing.text.BadLocationException;
055:        import javax.swing.text.Caret;
056:        import javax.swing.text.Document;
057:        import javax.swing.text.Element;
058:        import javax.swing.text.JTextComponent;
059:        import javax.swing.text.Position;
060:        import javax.swing.text.Position.Bias;
061:        import javax.swing.text.SimpleAttributeSet;
062:        import javax.swing.text.View;
063:        import org.netbeans.api.editor.settings.AttributesUtilities;
064:        import org.netbeans.editor.ext.ExtCaret;
065:        import org.netbeans.editor.view.spi.LockView;
066:        import org.netbeans.modules.editor.lib2.highlighting.CaretBasedBlockHighlighting.CaretRowHighlighting;
067:        import org.netbeans.modules.editor.lib2.highlighting.HighlightingManager;
068:        import org.netbeans.modules.editor.lib2.highlighting.HighlightingSpiPackageAccessor;
069:        import org.netbeans.modules.editor.lib2.highlighting.HighlightsLayerAccessor;
070:        import org.netbeans.modules.editor.lib2.highlighting.HighlightsLayerFilter;
071:        import org.netbeans.spi.editor.highlighting.HighlightsChangeEvent;
072:        import org.netbeans.spi.editor.highlighting.HighlightsChangeListener;
073:        import org.netbeans.spi.editor.highlighting.HighlightsContainer;
074:        import org.netbeans.spi.editor.highlighting.HighlightsLayer;
075:        import org.netbeans.spi.editor.highlighting.HighlightsSequence;
076:        import org.openide.util.WeakListeners;
077:
078:        /**
079:         *
080:         * @author vita
081:         */
082:        /* package */final class HighlightingDrawLayer extends
083:                DrawLayer.AbstractLayer implements  HighlightsChangeListener,
084:                AtomicLockListener {
085:            // -J-Dorg.netbeans.editor.HighlightingDrawLayer.level=FINE
086:            private static final Logger LOG = Logger
087:                    .getLogger(HighlightingDrawLayer.class.getName());
088:
089:            private static final String LAYER_A_NAME = "org-netbeans-lib-editor-nview-HighlightingDrawLayer/A"; //NOI18N
090:            // Using the original name for the caret row highlighting, some clients use it to remove the layer.
091:            private static final String LAYER_B_NAME = ExtCaret.HIGHLIGHT_ROW_LAYER_NAME;
092:            private static final String LAYER_C_NAME = "org-netbeans-lib-editor-nview-HighlightingDrawLayer/C"; //NOI18N
093:
094:            private static final HighlightsLayerFilter FILTER_A = new HighlightsLayerFilter() {
095:                public List<? extends HighlightsLayer> filterLayers(
096:                        List<? extends HighlightsLayer> layers) {
097:                    ArrayList<HighlightsLayer> filteredLayers = new ArrayList<HighlightsLayer>();
098:                    boolean add = false;
099:
100:                    for (HighlightsLayer layer : layers) {
101:                        HighlightsLayerAccessor layerAccessor = HighlightingSpiPackageAccessor
102:                                .get().getHighlightsLayerAccessor(layer);
103:
104:                        if (CaretRowHighlighting.LAYER_TYPE_ID
105:                                .equals(layerAccessor.getLayerTypeId())) {
106:                            add = true;
107:                            continue;
108:                        }
109:
110:                        if (add) {
111:                            filteredLayers.add(layer);
112:                        }
113:                    }
114:
115:                    return filteredLayers;
116:                }
117:            }; // End of FILTER_A constant
118:
119:            private static final HighlightsLayerFilter FILTER_B = new HighlightsLayerFilter() {
120:                public List<? extends HighlightsLayer> filterLayers(
121:                        List<? extends HighlightsLayer> layers) {
122:                    ArrayList<HighlightsLayer> filteredLayers = new ArrayList<HighlightsLayer>();
123:
124:                    for (HighlightsLayer layer : layers) {
125:                        HighlightsLayerAccessor layerAccessor = HighlightingSpiPackageAccessor
126:                                .get().getHighlightsLayerAccessor(layer);
127:
128:                        if (CaretRowHighlighting.LAYER_TYPE_ID
129:                                .equals(layerAccessor.getLayerTypeId())) {
130:                            filteredLayers.add(layer);
131:                            break;
132:                        }
133:                    }
134:
135:                    return filteredLayers;
136:                }
137:            }; // End of FILTER_B constant
138:
139:            private static final HighlightsLayerFilter FILTER_C = new HighlightsLayerFilter() {
140:                public List<? extends HighlightsLayer> filterLayers(
141:                        List<? extends HighlightsLayer> layers) {
142:                    ArrayList<HighlightsLayer> filteredLayers = new ArrayList<HighlightsLayer>();
143:
144:                    for (HighlightsLayer layer : layers) {
145:                        HighlightsLayerAccessor layerAccessor = HighlightingSpiPackageAccessor
146:                                .get().getHighlightsLayerAccessor(layer);
147:
148:                        if (CaretRowHighlighting.LAYER_TYPE_ID
149:                                .equals(layerAccessor.getLayerTypeId())) {
150:                            break;
151:                        }
152:
153:                        filteredLayers.add(layer);
154:                    }
155:
156:                    return filteredLayers;
157:                }
158:            }; // End of FILTER_C constant
159:
160:            public static void hookUp(EditorUI eui) {
161:                DrawLayer layerA = eui.findLayer(LAYER_A_NAME);
162:                if (layerA == null) {
163:                    layerA = new HighlightingDrawLayer(LAYER_A_NAME, FILTER_A);
164:                    eui.addLayer(layerA, 10000); // the old caret row draw layer's z-order
165:
166:                    if (LOG.isLoggable(Level.FINE)) {
167:                        LOG.fine("Successfully registered layerA in "
168:                                + simpleToString(eui)); //NOI18N
169:                    }
170:                } else {
171:                    if (LOG.isLoggable(Level.FINE)) {
172:                        LOG.fine("LayerA is already registered in "
173:                                + simpleToString(eui)); //NOI18N
174:                    }
175:                }
176:
177:                DrawLayer layerB = eui.findLayer(LAYER_B_NAME);
178:                if (layerB == null) {
179:                    layerB = new HighlightingDrawLayer(LAYER_B_NAME, FILTER_B);
180:                    eui.addLayer(layerB, 2050); // the old caret row draw layer's z-order
181:
182:                    if (LOG.isLoggable(Level.FINE)) {
183:                        LOG.fine("Successfully registered layerB in "
184:                                + simpleToString(eui)); //NOI18N
185:                    }
186:                } else {
187:                    if (LOG.isLoggable(Level.FINE)) {
188:                        LOG.fine("LayerB is already registered in "
189:                                + simpleToString(eui)); //NOI18N
190:                    }
191:                }
192:
193:                DrawLayer layerC = eui.findLayer(LAYER_C_NAME);
194:                if (layerC == null) {
195:                    layerC = new HighlightingDrawLayer(LAYER_C_NAME, FILTER_C);
196:                    eui.addLayer(layerC, 1000); // the old syntax draw layer's z-order
197:
198:                    if (LOG.isLoggable(Level.FINE)) {
199:                        LOG.fine("Successfully registered layerC in "
200:                                + simpleToString(eui)); //NOI18N
201:                    }
202:                } else {
203:                    if (LOG.isLoggable(Level.FINE)) {
204:                        LOG.fine("LayerC is already registered in "
205:                                + simpleToString(eui)); //NOI18N
206:                    }
207:                }
208:            }
209:
210:            private final HighlightsLayerFilter filter;
211:
212:            private WeakReference<JTextComponent> paneRef = null;
213:            private HighlightsContainer highlights = null;
214:
215:            private AttributeSet lastAttributeSet = null;
216:
217:            // The end-of-line attributes cache
218:            private AttributeSet lastEOLAttribs = null;
219:            private AttributeSet lastELAttribs = null;
220:            private boolean theLittleSpitAtTheBeginningOfAnEmptyLineDrawn = false;
221:
222:            /** Index of the last found line element in processOffset(). */
223:            private int lastLineIndex;
224:
225:            private boolean atomicLockListeningResolved;
226:            private boolean inAtomicLock;
227:
228:            private Position damageStartPos;
229:            private Position damageEndPos;
230:
231:            private HighlightingDrawLayer(String name,
232:                    HighlightsLayerFilter filter) {
233:                super (name);
234:                this .filter = filter;
235:            }
236:
237:            public @Override
238:            void init(DrawContext ctx) {
239:                super .init(ctx);
240:
241:                if (highlights == null) {
242:                    // Initialize
243:                    JTextComponent pane = ctx.getEditorUI().getComponent();
244:
245:                    // HACK: the component can be null when printing, so we will just
246:                    // create a fake JEditorPane
247:                    if (pane == null) {
248:                        Document doc = ctx.getEditorUI().getDocument();
249:
250:                        // Get the document's mime type
251:                        String mimeType = (String) doc.getProperty("mimeType"); //NOI18N
252:                        assert mimeType != null : "Document's mime type can't be null: "
253:                                + doc; //NOI18N
254:
255:                        // HACK: can't set the kit on fakePane, because it needs to run in AWT, which
256:                        // the print actions generally don't. So, the fakePane has EditorKit with
257:                        // the wrong mime type (most likely text/plain). It does not matter much, because
258:                        // the SyntaxHighlighting and NonLexerSyntaxHighlighting layers are registred for
259:                        // all mime types and we do not care about other layers.
260:                        //
261:                        //                // Find the appropriate editor kit
262:                        //                EditorKit kit = MimeLookup.getLookup(MimePath.parse(mimeType)).lookup(EditorKit.class);
263:                        //                assert kit != null : "Can't finde EditorKit for mime type '" + mimeType + "'";
264:
265:                        // Create a fake pane
266:                        JEditorPane fakePane = new JEditorPane();
267:                        //                fakePane.setEditorKit(kit);
268:                        fakePane.setDocument(doc);
269:
270:                        // Filter out all highlights layers, but syntax highlighting
271:                        fakePane.putClientProperty("HighlightsLayerIncludes",
272:                                new String[] {
273:                                        "^.*NonLexerSyntaxHighlighting$",
274:                                        "^.*SyntaxHighlighting$" }); //NOI18N
275:
276:                        pane = fakePane;
277:                    }
278:                    this .paneRef = new WeakReference<JTextComponent>(pane);
279:
280:                    HighlightingManager hm = HighlightingManager.getInstance();
281:                    this .highlights = hm.getHighlights(pane, filter);
282:                    this .highlights.addHighlightsChangeListener(this );
283:
284:                    if (LOG.isLoggable(Level.FINE)) {
285:                        if (filter == FILTER_A) {
286:                            LOG.fine("CHC@"
287:                                    + Integer.toHexString(System
288:                                            .identityHashCode(highlights))
289:                                    + " is for FILTER_A"); //NOI18N
290:                        } else if (filter == FILTER_B) {
291:                            LOG.fine("CHC@"
292:                                    + Integer.toHexString(System
293:                                            .identityHashCode(highlights))
294:                                    + " is for FILTER_B"); //NOI18N
295:                        } else if (filter == FILTER_C) {
296:                            LOG.fine("CHC@"
297:                                    + Integer.toHexString(System
298:                                            .identityHashCode(highlights))
299:                                    + " is for FILTER_C"); //NOI18N
300:                        }
301:                    }
302:                }
303:
304:                lastAttributeSet = null;
305:
306:                // Reset the end-of-line attributes cache
307:                lastEOLAttribs = null;
308:                lastELAttribs = null;
309:                theLittleSpitAtTheBeginningOfAnEmptyLineDrawn = false;
310:
311:                if (!atomicLockListeningResolved) {
312:                    atomicLockListeningResolved = true;
313:                    BaseDocument doc = ctx.getEditorUI().getDocument();
314:                    doc.addAtomicLockListener(WeakListeners.create(
315:                            AtomicLockListener.class, this , doc));
316:                }
317:            }
318:
319:            public boolean isActive(DrawContext ctx, MarkFactory.DrawMark mark) {
320:                if (highlights != null) {
321:                    return processOffset(ctx, false);
322:                } else {
323:                    return false;
324:                }
325:            }
326:
327:            public void updateContext(DrawContext ctx) {
328:                if (highlights != null) {
329:                    if (ctx.isEOL() && ctx.isBOL()) {
330:                        if (extendsEmptyLine()
331:                                && !theLittleSpitAtTheBeginningOfAnEmptyLineDrawn) {
332:                            theLittleSpitAtTheBeginningOfAnEmptyLineDrawn = true;
333:                            Coloring coloring = Coloring
334:                                    .fromAttributeSet(lastELAttribs);
335:                            coloring.apply(ctx);
336:                        } else {
337:                            if (extendsEOL()) {
338:                                Coloring coloring = Coloring
339:                                        .fromAttributeSet(lastEOLAttribs);
340:                                coloring.apply(ctx);
341:                            }
342:                        }
343:                    } else if (ctx.isEOL()) {
344:                        if (extendsEOL()) {
345:                            Coloring coloring = Coloring
346:                                    .fromAttributeSet(lastEOLAttribs);
347:                            coloring.apply(ctx);
348:                        }
349:                    } else {
350:                        processOffset(ctx, true);
351:                    }
352:                }
353:            }
354:
355:            public @Override
356:            boolean extendsEOL() {
357:                if (lastEOLAttribs == null && lastAttributeSet != null) {
358:                    @SuppressWarnings("unchecked")
359:                    List<AttributeSet> allSets = (List<AttributeSet>) lastAttributeSet
360:                            .getAttribute("dismantled-structure"); //NOI18N
361:                    AttributeSet[] arr = filter(allSets != null ? allSets
362:                            : Collections.singletonList(lastAttributeSet));
363:                    lastEOLAttribs = arr[0];
364:                    lastELAttribs = arr[1];
365:                }
366:
367:                boolean b = lastEOLAttribs != null
368:                        && lastEOLAttribs != SimpleAttributeSet.EMPTY;
369:                if (LOG.isLoggable(Level.FINE) && filter == FILTER_A) {
370:                    LOG.fine(simpleToString(this ) + ".extendsEOL = " + b);
371:                }
372:                return b;
373:            }
374:
375:            public @Override
376:            boolean extendsEmptyLine() {
377:                if (lastELAttribs == null && lastAttributeSet != null) {
378:                    @SuppressWarnings("unchecked")
379:                    List<AttributeSet> allSets = (List<AttributeSet>) lastAttributeSet
380:                            .getAttribute("dismantled-structure"); //NOI18N
381:                    AttributeSet[] arr = filter(allSets != null ? allSets
382:                            : Collections.singletonList(lastAttributeSet));
383:                    lastEOLAttribs = arr[0];
384:                    lastELAttribs = arr[1];
385:                }
386:
387:                boolean b = lastELAttribs != null
388:                        && lastELAttribs != SimpleAttributeSet.EMPTY;
389:                if (LOG.isLoggable(Level.FINE) && filter == FILTER_A) {
390:                    LOG.fine(simpleToString(this ) + ".extendsEmptyLine = " + b);
391:                }
392:                return b;
393:            }
394:
395:            // ----------------------------------------------------------------------
396:            //  HighlightsChangeListener implementation
397:            // ----------------------------------------------------------------------
398:
399:            public void highlightChanged(final HighlightsChangeEvent event) {
400:                if (LOG.isLoggable(Level.FINEST)) {
401:                    LOG.finest("BRIDGE-LAYER: changed area ["
402:                            + event.getStartOffset() + ", "
403:                            + event.getEndOffset() + "]"); //NOI18N
404:
405:                    //            LOG.log(Level.FINE, "Dumping highlights: {");
406:                    //            HighlightsSequence seq = highlights.getHighlights(0, Integer.MAX_VALUE);
407:                    //            while(seq.moveNext()) {
408:                    //                StringBuilder sb = new StringBuilder();
409:                    //                sb.append("    <");
410:                    //                sb.append(seq.getStartOffset());
411:                    //                sb.append(", ");
412:                    //                sb.append(seq.getEndOffset());
413:                    //                sb.append(", {");
414:                    //                
415:                    //                Enumeration<?> attrNames = seq.getAttributes().getAttributeNames();
416:                    //                while(attrNames.hasMoreElements()) {
417:                    //                    Object attrName = attrNames.nextElement();
418:                    //                    Object attrValue = seq.getAttributes().getAttribute(attrName);
419:                    //                    
420:                    //                    sb.append(attrName == null ? "null" : attrName.toString());
421:                    //                    sb.append(" = ");
422:                    //                    sb.append(attrValue == null ? "null" : attrValue.toString());
423:                    //                    
424:                    //                    if (attrNames.hasMoreElements()) {
425:                    //                        sb.append(", ");
426:                    //                    }
427:                    //                }
428:                    //                
429:                    //                sb.append("}>");
430:                    //                LOG.log(Level.FINE, sb.toString());
431:                    //            }
432:                    //            LOG.log(Level.FINE, "--- End of Dumping highlights");
433:                }
434:
435:                if (event.getStartOffset() == event.getEndOffset()) {
436:                    return;
437:                }
438:
439:                if (inAtomicLock) {
440:                    JTextComponent pane = paneRef.get();
441:                    if (pane != null) {
442:                        Document doc = pane.getDocument();
443:                        if (doc != null) {
444:                            int startOffset = Math.max(0, Math.min(event
445:                                    .getStartOffset(), doc.getLength()));
446:                            int endOffset = Math.max(startOffset, Math.min(
447:                                    event.getEndOffset(), doc.getLength()));
448:                            try {
449:                                // Only extend the modified area
450:                                if (damageStartPos == null) {
451:                                    damageStartPos = doc
452:                                            .createPosition(startOffset);
453:                                }
454:                                if (damageEndPos == null) {
455:                                    damageEndPos = doc
456:                                            .createPosition(endOffset);
457:                                }
458:
459:                                if (startOffset < damageStartPos.getOffset()) {
460:                                    damageStartPos = doc
461:                                            .createPosition(startOffset);
462:                                }
463:                                if (endOffset > damageEndPos.getOffset()) {
464:                                    damageEndPos = doc
465:                                            .createPosition(endOffset);
466:                                }
467:                            } catch (BadLocationException e) {
468:                                LOG.log(Level.WARNING,
469:                                        "Cannot set damaged range", e);
470:                                damageStartPos = null;
471:                                damageEndPos = null;
472:                            }
473:                        }
474:                    }
475:                    if (LOG.isLoggable(Level.FINE) && damageStartPos != null
476:                            && damageEndPos != null) {
477:                        LOG.fine("highlightsChangeEvent: ["
478:                                + event.getStartOffset() + ", "
479:                                + event.getEndOffset() + "], toDAMAGE: ["
480:                                + damageStartPos.getOffset() + ", "
481:                                + damageEndPos.getOffset() + "]\n");
482:                    }
483:                    return; // Wait for the atomic unlock
484:                }
485:
486:                invokeDamageRange(event.getStartOffset(), event.getEndOffset());
487:            }
488:
489:            private void invokeDamageRange(final int startOffset,
490:                    final int endOffset) {
491:                SwingUtilities.invokeLater(new Runnable() {
492:                    public void run() {
493:                        setNextActivityChangeOffset(0);
494:
495:                        JTextComponent pane = paneRef.get();
496:                        Document d;
497:                        if (pane != null
498:                                && (d = pane.getDocument()) instanceof  AbstractDocument) {
499:                            AbstractDocument doc = (AbstractDocument) d;
500:                            doc.readLock();
501:                            try {
502:                                int rangeEnd = Math.min(endOffset, pane
503:                                        .getDocument().getLength() + 1);
504:                                int rangeStart = startOffset >= rangeEnd ? 0
505:                                        : startOffset;
506:
507:                                if (rangeStart < rangeEnd) {
508:                                    try {
509:                                        if (LOG.isLoggable(Level.FINE)) {
510:                                            LOG.fine("DamageRange: ["
511:                                                    + rangeStart + ", "
512:                                                    + rangeEnd + "]\n");
513:                                        }
514:                                        pane.getUI().damageRange(pane,
515:                                                rangeStart, rangeEnd);
516:                                    } catch (Exception e) {
517:                                        LOG.log(Level.INFO,
518:                                                "Can't update view: range = ["
519:                                                        + rangeStart + ", "
520:                                                        + rangeEnd + "]", e); //NOI18N
521:                                    }
522:
523:                                    try {
524:                                        // XXX: hack, we should use isFixedSize() flag of the layers
525:                                        // this is blindely assuming that caret row highlighting and
526:                                        // higher layers do not change text metrics (eg. font)
527:                                        if (filter == FILTER_C) {
528:                                            notifyViews(pane.getUI()
529:                                                    .getRootView(pane),
530:                                                    rangeStart, rangeEnd);
531:                                        }
532:                                    } catch (Exception e) {
533:                                        LOG.log(Level.INFO,
534:                                                "Can't reset line views: range = ["
535:                                                        + rangeStart + ", "
536:                                                        + rangeEnd + "]", e); //NOI18N
537:                                    }
538:
539:                                    // force caret repaint, see #100384
540:                                    // XXX: not very efficient, should only be done for
541:                                    // containers/events that affect metrics
542:                                    Caret caret = pane.getCaret();
543:                                    if (caret instanceof  BaseCaret) {
544:                                        ((BaseCaret) caret).changedUpdate(null);
545:                                    }
546:                                }
547:                            } finally {
548:                                doc.readUnlock();
549:                            }
550:                        }
551:                    }
552:                });
553:            }
554:
555:            public void atomicLock(AtomicLockEvent evt) {
556:                inAtomicLock = true;
557:            }
558:
559:            public void atomicUnlock(AtomicLockEvent evt) {
560:                inAtomicLock = false;
561:                if (damageStartPos != null && damageEndPos != null) { // Accumulated damage range
562:                    invokeDamageRange(damageStartPos.getOffset(), damageEndPos
563:                            .getOffset());
564:                }
565:                damageStartPos = null;
566:                damageEndPos = null;
567:            }
568:
569:            // ----------------------------------------------------------------------
570:            //  Private implementation
571:            // ----------------------------------------------------------------------
572:
573:            private void notifyViews(View view, int startOffset, int endOffset) {
574:                // Find DrawEngineLineView
575:                while (view != null) {
576:                    int idx = view.getViewIndex(startOffset, Bias.Forward);
577:                    if (idx != -1) {
578:                        View v = view.getView(idx);
579:                        if (v instanceof  DrawEngineLineView) {
580:                            break;
581:                        } else {
582:                            view = v;
583:                        }
584:                    } else {
585:                        view = null;
586:                    }
587:                }
588:
589:                // If DrawEngineLineView found reset all of them between startOffset, endOffset
590:                if (view != null) {
591:                    LockView lockView = LockView.get(view);
592:                    lockView.lock();
593:                    try {
594:                        int firstViewIdx = view.getViewIndex(startOffset,
595:                                Bias.Forward);
596:                        int lastViewIdx = view.getViewIndex(endOffset,
597:                                Bias.Forward);
598:
599:                        for (int i = firstViewIdx; i <= lastViewIdx; i++) {
600:                            View v = view.getView(i);
601:                            if (v instanceof  DrawEngineLineView) {
602:                                ((DrawEngineLineView) v).highlightsChanged(Math
603:                                        .max(startOffset, v.getStartOffset()),
604:                                        Math.min(endOffset, v.getEndOffset()));
605:                            }
606:                        }
607:                    } finally {
608:                        lockView.unlock();
609:                    }
610:                }
611:            }
612:
613:            private int findLineEndOffset(Document doc, int offset) {
614:                Element lineRootElement = doc.getDefaultRootElement();
615:                int lineIndex = lastLineIndex;
616:                if (lineIndex < lineRootElement.getElementCount()) {
617:                    Element lineElement = lineRootElement.getElement(lineIndex);
618:                    if (offset >= lineElement.getStartOffset()
619:                            && offset < lineElement.getEndOffset()) {
620:                        return lineElement.getEndOffset();
621:                    }
622:                }
623:                lineIndex = lineRootElement.getElementIndex(offset);
624:                lastLineIndex = lineIndex;
625:                return lineRootElement.getElement(lineIndex).getEndOffset();
626:            }
627:
628:            private boolean processOffset(DrawContext ctx,
629:                    boolean applyAttributes) {
630:                BaseDocument doc = ctx.getEditorUI().getDocument();
631:                int currentOffset = ctx.getFragmentOffset();
632:                int endOffset = findLineEndOffset(doc, currentOffset);
633:
634:                if (endOffset >= doc.getLength()) {
635:                    endOffset = Integer.MAX_VALUE;
636:                }
637:
638:                HighlightsSequence hs = highlights.getHighlights(currentOffset,
639:                        endOffset);
640:                boolean hasHighlight = hs.moveNext();
641:
642:                if (hasHighlight) {
643:                    if (hs.getStartOffset() <= currentOffset) {
644:                        if (applyAttributes) {
645:                            Coloring coloring = Coloring.fromAttributeSet(hs
646:                                    .getAttributes());
647:                            coloring.apply(ctx);
648:                        }
649:
650:                        lastAttributeSet = hs.getAttributes();
651:                        setNextActivityChangeOffset(hs.getEndOffset());
652:                    } else {
653:                        setNextActivityChangeOffset(hs.getStartOffset());
654:                    }
655:
656:                    return true;
657:                } else {
658:                    return false;
659:                }
660:            }
661:
662:            private AttributeSet[] filter(List<AttributeSet> sets) {
663:                ArrayList<AttributeSet> eolSets = new ArrayList<AttributeSet>();
664:                ArrayList<AttributeSet> elSets = new ArrayList<AttributeSet>();
665:
666:                for (AttributeSet set : sets) {
667:                    Object value = set
668:                            .getAttribute(HighlightsContainer.ATTR_EXTENDS_EOL);
669:
670:                    if ((value instanceof  Boolean)
671:                            && ((Boolean) value).booleanValue()) {
672:                        eolSets.add(set);
673:                    }
674:
675:                    value = set
676:                            .getAttribute(HighlightsContainer.ATTR_EXTENDS_EMPTY_LINE);
677:                    if ((value instanceof  Boolean)
678:                            && ((Boolean) value).booleanValue()) {
679:                        elSets.add(set);
680:                    }
681:                }
682:
683:                AttributeSet eolAttribs;
684:                if (eolSets.size() > 1) {
685:                    eolAttribs = AttributesUtilities.createComposite(eolSets
686:                            .toArray(new AttributeSet[eolSets.size()]));
687:                } else if (eolSets.size() == 1) {
688:                    eolAttribs = eolSets.get(0);
689:                } else {
690:                    eolAttribs = SimpleAttributeSet.EMPTY;
691:                }
692:
693:                AttributeSet elAttribs;
694:                if (elSets.size() > 1) {
695:                    elAttribs = AttributesUtilities.createComposite(elSets
696:                            .toArray(new AttributeSet[elSets.size()]));
697:                } else if (elSets.size() == 1) {
698:                    elAttribs = elSets.get(0);
699:                } else {
700:                    elAttribs = SimpleAttributeSet.EMPTY;
701:                }
702:
703:                return new AttributeSet[] { eolAttribs, elAttribs };
704:            }
705:
706:            private static String simpleToString(Object o) {
707:                return o == null ? "null" : o.getClass() + "@"
708:                        + Integer.toHexString(System.identityHashCode(o)); //NOI18N
709:            }
710:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.