Source Code Cross Referenced for DrawEngineLineView.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) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.editor;
0043:
0044:        import java.awt.Graphics;
0045:        import java.awt.Rectangle;
0046:        import java.awt.Shape;
0047:        import java.util.logging.Level;
0048:        import java.util.logging.Logger;
0049:        import javax.swing.event.DocumentEvent;
0050:        import javax.swing.text.BadLocationException;
0051:        import javax.swing.text.Document;
0052:        import javax.swing.text.Element;
0053:        import javax.swing.text.JTextComponent;
0054:        import javax.swing.text.Position;
0055:        import javax.swing.text.View;
0056:        import javax.swing.text.ViewFactory;
0057:        import org.netbeans.editor.view.spi.EstimatedSpanView;
0058:        import org.netbeans.editor.view.spi.LockView;
0059:        import org.netbeans.editor.view.spi.ViewLayoutState;
0060:        import org.netbeans.lib.editor.util.ArrayUtilities;
0061:        import org.netbeans.lib.editor.view.GapDocumentView;
0062:
0063:        /**
0064:         * Line view implementation. It works over LineElement and 
0065:         * delegates drawing to DrawEngine.
0066:         *
0067:         * @author  Martin Roskanin
0068:         */
0069:        /* package */class DrawEngineLineView extends View implements 
0070:                ViewLayoutState, EstimatedSpanView {
0071:
0072:            private static final Logger LOG = Logger
0073:                    .getLogger(DrawEngineLineView.class.getName());
0074:            private static final boolean loggable = LOG
0075:                    .isLoggable(Level.FINEST);
0076:            private static final long PERF_TRESHOLD = Long.getLong(
0077:                    "DrawEngineLineView.PERF_TRESHOLD", -1); //NOI18N, log events lasting longer then PERF_TRASHOLD msec
0078:
0079:            /**
0080:             * Bit that indicates whether x is the major axis.
0081:             */
0082:            private static final int X_MAJOR_AXIS_BIT = 1;
0083:
0084:            /**
0085:             * Bit that indicates that the major axis info is valid.
0086:             */
0087:            private static final int MAJOR_AXIS_PREFERENCE_CHANGED_BIT = 2;
0088:
0089:            /**
0090:             * Bit that indicates that the minor axis info is valid.
0091:             */
0092:            private static final int MINOR_AXIS_PREFERENCE_CHANGED_BIT = 4;
0093:
0094:            /**
0095:             * Bit that indicates that size of the view is valid.
0096:             */
0097:            private static final int VIEW_SIZE_INVALID_BIT = 8;
0098:
0099:            /**
0100:             * Bit value in <code>statusBits</code> determining
0101:             * whether there is a pending layout update scheduled
0102:             * for this layout state.
0103:             */
0104:            private static final int UPDATE_LAYOUT_PENDING_BIT = 16;
0105:
0106:            private static final int ESTIMATED_SPAN_BIT = 32;
0107:
0108:            protected static final int LAST_USED_BIT = ESTIMATED_SPAN_BIT;
0109:
0110:            /**
0111:             * Bit composition being used to test whether 
0112:             * the layout is up-to-date or not.
0113:             */
0114:            private static final int ANY_INVALID = MAJOR_AXIS_PREFERENCE_CHANGED_BIT
0115:                    | MINOR_AXIS_PREFERENCE_CHANGED_BIT | VIEW_SIZE_INVALID_BIT;
0116:
0117:            private int statusBits; // 4 bytes
0118:
0119:            private int viewRawIndex; // 8 bytes
0120:
0121:            private double layoutMajorAxisRawOffset; // double => 16 bytes
0122:
0123:            // major axis
0124:            private float layoutMajorAxisPreferredSpan; // 20 bytes
0125:
0126:            // minor axis
0127:            private float layoutMinorAxisPreferredSpan; // 24 bytes
0128:
0129:            /** Draw graphics for converting position to coords */
0130:            //ModelToViewDG modelToViewDG; // 28 bytes
0131:            /** Draw graphics for converting coords to position */
0132:            private ViewToModelDG viewToModelDG; // 32 bytes
0133:
0134:            public DrawEngineLineView(Element elem) {
0135:                super (elem);
0136:            }
0137:
0138:            private int getBaseX(int orig) {
0139:                return orig + getEditorUI().getTextMargin().left;
0140:            }
0141:
0142:            private JTextComponent getComponent() {
0143:                return (JTextComponent) getContainer();
0144:            }
0145:
0146:            private BaseTextUI getBaseTextUI() {
0147:                return (BaseTextUI) getComponent().getUI();
0148:            }
0149:
0150:            private EditorUI getEditorUI() {
0151:                return getBaseTextUI().getEditorUI();
0152:            }
0153:
0154:            private ModelToViewDG getModelToViewDG() {
0155:                /* fix of issue #55419
0156:                if (modelToViewDG == null) {
0157:                    modelToViewDG = new ModelToViewDG();
0158:                }
0159:                return modelToViewDG;
0160:                 */
0161:                return new ModelToViewDG();
0162:            }
0163:
0164:            private ViewToModelDG getViewToModelDG() {
0165:                if (viewToModelDG == null) {
0166:                    viewToModelDG = new ViewToModelDG();
0167:                }
0168:                return viewToModelDG;
0169:            }
0170:
0171:            public boolean isEstimatedSpan() {
0172:                return isStatusBitsNonZero(ESTIMATED_SPAN_BIT);
0173:            }
0174:
0175:            public void setEstimatedSpan(boolean estimatedSpan) {
0176:                if (isEstimatedSpan() != estimatedSpan) { // really changed
0177:                    if (estimatedSpan) {
0178:                        setStatusBits(ESTIMATED_SPAN_BIT);
0179:                    } else { // changing from true to false
0180:                        clearStatusBits(ESTIMATED_SPAN_BIT);
0181:
0182:                        getParent().preferenceChanged(this , true, true);
0183:                    }
0184:                }
0185:            }
0186:
0187:            protected boolean isFragment() {
0188:                return false;
0189:            }
0190:
0191:            /**
0192:             * Get the offset prior to ending '\n' in the corresponding line element.
0193:             */
0194:            private int getEOLffset() {
0195:                return super .getEndOffset() - 1; // offset prior to ending '\n'
0196:            }
0197:
0198:            /**
0199:             * Get either the EOL offset or the end of the fragment
0200:             * if the fragment is inside the view.
0201:             */
0202:            private int getAdjustedEOLOffset() {
0203:                return Math.min(getEndOffset(), getEOLffset());
0204:            }
0205:
0206:            public @Override
0207:            void insertUpdate(DocumentEvent e, Shape a, ViewFactory f) {
0208:                resetMarkers(e.getOffset());
0209:                preferenceChanged(this , true, false);
0210:            }
0211:
0212:            public @Override
0213:            void removeUpdate(DocumentEvent e, Shape a, ViewFactory f) {
0214:                resetMarkers(e.getOffset());
0215:                preferenceChanged(this , true, false);
0216:            }
0217:
0218:            public @Override
0219:            float getAlignment(int axis) {
0220:                return 0f;
0221:            }
0222:
0223:            public void paint(Graphics g, Shape a) {
0224:                if (!(getDocument() instanceof  BaseDocument))
0225:                    return; //#48134
0226:                // When painting make sure the estimated span is set to false
0227:                setEstimatedSpan(false);
0228:                // No modifications to allocReadOnly variable!
0229:                Rectangle allocReadOnly = (a instanceof  Rectangle) ? (Rectangle) a
0230:                        : a.getBounds();
0231:                int startOffset = getStartOffset();
0232:                int endOffset = getAdjustedEOLOffset();
0233:                try {
0234:                    if (isFragment()) {
0235:                        Rectangle oldClipRect = g.getClipBounds();
0236:                        Rectangle newClip = new Rectangle(oldClipRect);
0237:                        Rectangle startOffsetClip = modelToView(startOffset, a,
0238:                                Position.Bias.Forward).getBounds();
0239:                        Rectangle endOffsetClip = modelToView(endOffset, a,
0240:                                Position.Bias.Forward).getBounds();
0241:                        View parent = getParent();
0242:                        if (parent instanceof  FoldMultiLineView
0243:                                && !equals(parent
0244:                                        .getView(parent.getViewCount() - 1))) {
0245:                            newClip.width = Math.min(oldClipRect.width,
0246:                                    endOffsetClip.x);
0247:
0248:                            if (newClip.width + newClip.x > endOffsetClip.x) {
0249:                                newClip.width = newClip.width
0250:                                        - (newClip.width + newClip.x - endOffsetClip.x);
0251:                            }
0252:
0253:                            g.setClip(newClip);
0254:                        }
0255:
0256:                        int shift = startOffsetClip.x
0257:                                - getEditorUI().getTextMargin().left
0258:                                - allocReadOnly.x;
0259:                        g.translate(-shift, 0);
0260:
0261:                        DrawEngine.getDrawEngine().draw(this ,
0262:                                new DrawGraphics.GraphicsDG(g), getEditorUI(),
0263:                                startOffset, endOffset,
0264:                                getBaseX(allocReadOnly.x), allocReadOnly.y,
0265:                                Integer.MAX_VALUE);
0266:
0267:                        g.translate(shift, 0);
0268:                        g.setClip(oldClipRect);
0269:
0270:                    } else {
0271:                        JTextComponent component = getComponent();
0272:                        if (component != null) {
0273:                            long ts1 = 0, ts2 = 0;
0274:                            if (loggable) {
0275:                                ts1 = System.currentTimeMillis();
0276:                            }
0277:
0278:                            // Translate the graphics clip region to the document offsets
0279:                            // and their view region
0280:                            Rectangle clip = g.getClipBounds();
0281:                            int fromOffset = viewToModel(clip.x, clip.y,
0282:                                    allocReadOnly, null);
0283:                            int toOffset = viewToModel(clip.x + clip.width,
0284:                                    clip.y, allocReadOnly, null);
0285:
0286:                            fromOffset = Math.max(fromOffset - 1,
0287:                                    getStartOffset());
0288:                            toOffset = Math.min(toOffset + 1,
0289:                                    getAdjustedEOLOffset());
0290:
0291:                            Rectangle rr = modelToView(fromOffset,
0292:                                    allocReadOnly, Position.Bias.Forward)
0293:                                    .getBounds();
0294:
0295:                            DrawEngine.getDrawEngine().draw(this ,
0296:                                    new DrawGraphics.GraphicsDG(g),
0297:                                    getEditorUI(), fromOffset, toOffset, rr.x,
0298:                                    rr.y, Integer.MAX_VALUE);
0299:
0300:                            if (loggable) {
0301:                                ts2 = System.currentTimeMillis();
0302:                                if (ts2 - ts1 > PERF_TRESHOLD) {
0303:                                    LOG.finest("paint: " + //NOI18N
0304:                                            "<"
0305:                                            + fromOffset
0306:                                            + ", "
0307:                                            + toOffset
0308:                                            + ">, "
0309:                                            + //NOI18N
0310:                                            "DrawEngine.startX = "
0311:                                            + rr.x
0312:                                            + ", DrawEngine.startY = "
0313:                                            + rr.y
0314:                                            + ", "
0315:                                            + //NOI18N
0316:                                            "shape = [" + allocReadOnly.x
0317:                                            + ", " + allocReadOnly.y + ", "
0318:                                            + allocReadOnly.width + ", "
0319:                                            + allocReadOnly.height
0320:                                            + "], "
0321:                                            + //NOI18N
0322:                                            "clip = [" + clip.x + ", " + clip.y
0323:                                            + ", " + clip.width + ", "
0324:                                            + clip.height + "] " + //NOI18N
0325:                                            "took " + (ts2 - ts1) + " msec"); //NOI18N
0326:                                }
0327:                            }
0328:                        }
0329:                    }
0330:                } catch (BadLocationException ble) {
0331:                    LOG.log(Level.INFO, "Painting the view failed", ble); //NOI18N
0332:                }
0333:            }
0334:
0335:            public float getPreferredSpan(int axis) {
0336:                switch (axis) {
0337:                case Y_AXIS:
0338:                    return getEditorUI().getLineHeight();
0339:                case X_AXIS:
0340:                    //                try {
0341:                    int offset = Math.max(0, getEndOffset() - 1);
0342:                    Shape retShape = modelToView(offset, new Rectangle(),
0343:                            Position.Bias.Forward, false);
0344:                    int ret = retShape.getBounds().x
0345:                            + retShape.getBounds().width;
0346:                    return Math.max(ret, 1f);
0347:                    //                } catch (BadLocationException ble) {
0348:                    //                    LOG.log(Level.INFO, "Can't determine x-axis span", ble); //NOI18N
0349:                    //                }
0350:                }
0351:
0352:                return 1f;
0353:            }
0354:
0355:            // Markers are placed every MARKERS_DIST characters. The first marker
0356:            // at the startOffset and has x-coordinate 0 (in the view's internal coordinate system).
0357:            // Each marker's value is its distance from the beginning of the view in the
0358:            // view's internal coordinate system. Please note that the view's internal
0359:            // coordinate system is different from the JTextComponent's system, which is
0360:            // for example the system of x, y and shape parameters passed to m2v and v2m methods.
0361:            private static final int MARKERS_DIST;
0362:            static {
0363:                int markersDist = 128;
0364:                try {
0365:                    markersDist = (Integer) Class.forName(
0366:                            "org.netbeans.editor.DrawEngineTest").getField(
0367:                            "TEST_MARKERS_DIST").get(null); //NOI18N
0368:                } catch (Exception e) {
0369:                    // ignore
0370:                }
0371:                MARKERS_DIST = markersDist;
0372:                LOG.fine("DrawEngineLineView.MARKERS_DIST = " + MARKERS_DIST); //NOI18N
0373:            }
0374:            private int[] markers = new int[] { 0 };
0375:            private int markersLength = markers.length;
0376:
0377:            public void highlightsChanged(int changeStart, int changeEnd) {
0378:                checkViewAccess();
0379:                resetMarkers(changeStart);
0380:                preferenceChanged(this , true, false);
0381:            }
0382:
0383:            private void resetMarkers(int offset) {
0384:                if (offset < getStartOffset() || offset > getEndOffset()) {
0385:                    // may happen when undo, see #115122
0386:                    markersLength = 1;
0387:                } else {
0388:                    markersLength = Math.min(markersLength,
0389:                            (offset - getStartOffset()) / MARKERS_DIST + 1);
0390:                }
0391:
0392:                if (loggable) {
0393:                    LOG.finest("resetMarkers: "
0394:                            + //NOI18N
0395:                            "<" + getStartOffset() + ", " + getEndOffset()
0396:                            + ">, offset = " + offset + //NOI18N
0397:                            " -> markersLength = " + markersLength); //NOI18N
0398:                }
0399:            }
0400:
0401:            // startX, startY are in the JTextComponent's coordinate space
0402:            private Rectangle getModel2ViewRect(int startOffset, int endOffset,
0403:                    int startX, int startY, int targetOffset) {
0404:                long ts1 = 0, ts2 = 0;
0405:                EditorUI eui = getEditorUI();
0406:                Rectangle ret;
0407:
0408:                View parent;
0409:                if ((((parent = getParent()) instanceof  GapDocumentView) && ((GapDocumentView) parent)
0410:                        .isPendingUpdate())
0411:                        || isEstimatedSpan()) {
0412:                    ret = new Rectangle(getBaseX(startX), startY, 1, eui
0413:                            .getLineHeight());
0414:
0415:                } else {
0416:                    if (loggable) {
0417:                        ts1 = System.currentTimeMillis();
0418:                    }
0419:
0420:                    // XXX: nearly works for monospaced fonts, the only problem is with tabs
0421:                    //            ret = new Rectangle(
0422:                    //                getBaseX((targetOffset - startOffset) * charWidth + startX),
0423:                    //                startY,
0424:                    //                charWidth,
0425:                    //                eui.getLineHeight()
0426:                    //            );
0427:
0428:                    int targetMarkerIdx = (targetOffset - startOffset)
0429:                            / MARKERS_DIST;
0430:                    int markerIdx = Math
0431:                            .min(targetMarkerIdx, markersLength - 1);
0432:                    int markerX = markers[markerIdx];
0433:                    int markerOffset = startOffset + markerIdx * MARKERS_DIST;
0434:
0435:                    ret = new Rectangle(getBaseX(markerX), startY, 1, eui
0436:                            .getLineHeight());
0437:                    try {
0438:                        ModelToViewDG g = getModelToViewDG();
0439:                        g.setRectangle(ret); // set the current rectangle
0440:
0441:                        if (markers.length <= targetMarkerIdx) {
0442:                            int[] arr = new int[targetMarkerIdx + 1];
0443:                            System
0444:                                    .arraycopy(markers, 0, arr, 0,
0445:                                            markers.length);
0446:                            markers = arr;
0447:                        }
0448:
0449:                        for (; markerIdx < targetMarkerIdx; markerIdx++) {
0450:                            DrawEngine.getDrawEngine().draw(this , g, eui,
0451:                                    markerOffset, markerOffset + MARKERS_DIST,
0452:                                    markerX, startY,
0453:                                    markerOffset + MARKERS_DIST);
0454:
0455:                            markerOffset += MARKERS_DIST;
0456:                            markerX = ret.x;
0457:                            markers[markerIdx + 1] = markerX;
0458:                        }
0459:
0460:                        if (targetMarkerIdx >= markersLength) {
0461:                            markersLength = targetMarkerIdx + 1;
0462:                        }
0463:
0464:                        DrawEngine.getDrawEngine().draw(this , g, eui,
0465:                                markerOffset, endOffset,
0466:                                getBaseX(markerX + startX), startY,
0467:                                targetOffset);
0468:
0469:                        g.setRectangle(null);
0470:                    } catch (BadLocationException ble) {
0471:                        // Log and return an estimated view
0472:                        LOG.log(Level.INFO, "Model-to-view translation failed",
0473:                                ble); //NOI18N
0474:                        ret = new Rectangle(getBaseX(startX), startY, 1, eui
0475:                                .getLineHeight());
0476:                    }
0477:
0478:                    if (loggable) {
0479:                        ts2 = System.currentTimeMillis();
0480:                    }
0481:                }
0482:
0483:                if (loggable && ts2 - ts1 > PERF_TRESHOLD) {
0484:                    LOG.finest("m2v: " + //NOI18N
0485:                            "<" + startOffset + ", " + endOffset
0486:                            + ">, targetOffset = " + targetOffset
0487:                            + ", "
0488:                            + //NOI18N
0489:                            "[" + startX + ", " + startY
0490:                            + "] "
0491:                            + //NOI18N
0492:                            "-> [" + ret.getBounds().x + ", "
0493:                            + ret.getBounds().y + ", " + ret.getBounds().width
0494:                            + ", " + ret.getBounds().height + "]" + //NOI18N
0495:                            " took " + (ts2 - ts1) + " msec"); //NOI18N
0496:                }
0497:                return ret;
0498:            }
0499:
0500:            // shape is in the JTextComponent's coordinate space
0501:            public Shape modelToView(int pos, Shape shape, Position.Bias b) {
0502:                return modelToView(pos, shape, b, true); // ensure exact span (not estimated)
0503:            }
0504:
0505:            // shape is in the JTextComponent's coordinate space
0506:            public Shape modelToView(int pos, Shape shape, Position.Bias bias,
0507:                    boolean exactSpan) {
0508:                assert shape != null : "The shape parameter must not be null"; //NOI18N
0509:                checkViewAccess();
0510:
0511:                if (!(getDocument() instanceof  BaseDocument)) {
0512:                    return new Rectangle();
0513:                }
0514:
0515:                if (exactSpan) { // ensure that span will not be estimated
0516:                    setEstimatedSpan(false);
0517:                }
0518:
0519:                if (bias == Position.Bias.Forward
0520:                        && (pos < super .getStartOffset() || pos >= super 
0521:                                .getEndOffset())
0522:                        || bias == Position.Bias.Backward
0523:                        && (pos <= super .getStartOffset() || pos > super 
0524:                                .getEndOffset())) {
0525:                    BadLocationException ble = new BadLocationException(
0526:                            "Invalid offset = "
0527:                                    + pos //NOI18N
0528:                                    + ", bias = "
0529:                                    + bias //NOI18N
0530:                                    + ", outside of the view <"
0531:                                    + super .getStartOffset()
0532:                                    + ", "
0533:                                    + super .getEndOffset()
0534:                                    + ">" //NOI18N
0535:                                    + ", isFragment = "
0536:                                    + isFragment() //NOI18N
0537:                                    + (isFragment() ? ", fragment boundaries <"
0538:                                            + getStartOffset() + ", "
0539:                                            + getEndOffset() + ">" : ""), pos); // NOI18N
0540:                    LOG.log(Level.INFO, null, ble);
0541:                    return new Rectangle(getBaseX(shape.getBounds().x), shape
0542:                            .getBounds().y, 1, getEditorUI().getLineHeight());
0543:                }
0544:
0545:                if (isFragment()
0546:                        && (pos < getStartOffset() || pos > getEndOffset())) {
0547:                    BadLocationException ble = new BadLocationException(
0548:                            "Invalid offset = "
0549:                                    + pos //NOI18N
0550:                                    + ", bias = "
0551:                                    + bias //NOI18N
0552:                                    + ", outside of the fragment view" //NOI18N
0553:                                    + " <" + getStartOffset() + ", "
0554:                                    + getEndOffset() + ">", pos); // NOI18N
0555:                    LOG.log(Level.INFO, null, ble);
0556:                    return new Rectangle(getBaseX(shape.getBounds().x), shape
0557:                            .getBounds().y, 1, getEditorUI().getLineHeight());
0558:                }
0559:
0560:                if (bias == Position.Bias.Backward) {
0561:                    pos--;
0562:                }
0563:
0564:                Rectangle ret = getModel2ViewRect(getStartOffset(),
0565:                        getEndOffset(), shape.getBounds().x,
0566:                        shape.getBounds().y, pos);
0567:
0568:                return ret;
0569:            }
0570:
0571:            // x, y, shape are in the JTextComponent's coordinate space
0572:            public int viewToModel(float x, float y, Shape shape,
0573:                    Position.Bias[] biasReturn) {
0574:                assert shape != null : "The shape parameter must not be null"; //NOI18N
0575:                checkViewAccess();
0576:
0577:                if (!(getDocument() instanceof  BaseDocument)) {
0578:                    return 0;
0579:                }
0580:
0581:                long ts1 = 0, ts2 = 0;
0582:                int pos = getStartOffset();
0583:
0584:                if (biasReturn != null) {
0585:                    biasReturn[0] = Position.Bias.Forward;
0586:                }
0587:
0588:                if (!isEstimatedSpan() && x > shape.getBounds().x) {
0589:                    if (loggable) {
0590:                        ts1 = System.currentTimeMillis();
0591:                    }
0592:
0593:                    EditorUI eui = getEditorUI();
0594:                    int xx = Math.max(0, (int) x - shape.getBounds().x
0595:                            - eui.getTextMargin().left);
0596:
0597:                    // XXX: nearly works for monospaced fonts, the only problem is with tabs
0598:                    //            int chars = xx / charWidth;
0599:                    //            if (chars > getAdjustedEOLOffset() - getStartOffset()) {
0600:                    //                chars = getAdjustedEOLOffset() - getStartOffset();
0601:                    //            }
0602:                    //            pos += chars;
0603:
0604:                    int markerIdx = ArrayUtilities.binarySearch(markers, 0,
0605:                            markersLength - 1, xx);
0606:                    if (markerIdx >= 0) {
0607:                        // hit the marker
0608:                        pos = getStartOffset() + markerIdx * MARKERS_DIST;
0609:                    } else {
0610:                        // get the index of the last marker before xx
0611:                        markerIdx = -markerIdx - 2;
0612:                        int markerX = markers[markerIdx];
0613:                        int markerOffset = getStartOffset() + markerIdx
0614:                                * MARKERS_DIST;
0615:
0616:                        try {
0617:                            ViewToModelDG g = getViewToModelDG();
0618:
0619:                            for (;;) {
0620:                                int nextOffset = Math.min(
0621:                                        getAdjustedEOLOffset(), markerOffset
0622:                                                + MARKERS_DIST - 1);
0623:
0624:                                g.setTargetX(xx);
0625:                                g.setEOLOffset(nextOffset);
0626:
0627:                                DrawEngine.getDrawEngine().draw(this , g, eui,
0628:                                        markerOffset, nextOffset, markerX,
0629:                                        shape.getBounds().y, -1);
0630:
0631:                                if (g.getX() >= xx
0632:                                        || g.getOffset() >= getAdjustedEOLOffset()) {
0633:                                    break;
0634:                                }
0635:
0636:                                markerOffset += MARKERS_DIST;
0637:                                markerX = g.getX();
0638:
0639:                                if (markerIdx + 1 >= markers.length) {
0640:                                    int[] arr = new int[markers.length + 10];
0641:                                    System.arraycopy(markers, 0, arr, 0,
0642:                                            markers.length);
0643:                                    markers = arr;
0644:                                }
0645:                                markers[++markerIdx] = markerX;
0646:                                markersLength = markerIdx + 1;
0647:                            }
0648:
0649:                            pos = Math.min(g.getOffset(),
0650:                                    getAdjustedEOLOffset());
0651:                        } catch (BadLocationException ble) {
0652:                            // Log and return start offset
0653:                            LOG.log(Level.INFO,
0654:                                    "View-to-model translation failed", ble); //NOI18N
0655:                        }
0656:                    }
0657:
0658:                    if (loggable) {
0659:                        ts2 = System.currentTimeMillis();
0660:                    }
0661:                }
0662:
0663:                if (loggable && ts2 - ts1 > PERF_TRESHOLD) {
0664:                    LOG.finest("v2m: "
0665:                            + //NOI18N
0666:                            "[" + x + ", "
0667:                            + y
0668:                            + "], "
0669:                            + //NOI18N
0670:                            "[" + shape.getBounds().x + ", "
0671:                            + shape.getBounds().y + ", "
0672:                            + shape.getBounds().width + ", "
0673:                            + shape.getBounds().height + "] " + //NOI18N
0674:                            "-> " + pos + //NOI18N
0675:                            " took " + (ts2 - ts1) + " msec"); //NOI18N
0676:                }
0677:                return pos;
0678:            }
0679:
0680:            private void checkViewAccess() {
0681:                LockView view = LockView.get(this );
0682:                if (view != null
0683:                        && (view.getLockThread() != Thread.currentThread())) {
0684:                    throw new IllegalStateException(
0685:                            "View access without view lock"); // NOI18N
0686:                }
0687:            }
0688:
0689:            private final class ViewToModelDG extends DrawGraphics.SimpleDG {
0690:
0691:                private int targetX;
0692:                private int offset;
0693:                private int eolOffset;
0694:
0695:                public void setTargetX(int targetX) {
0696:                    this .targetX = targetX;
0697:                }
0698:
0699:                public void setEOLOffset(int eolOffset) {
0700:                    this .eolOffset = eolOffset;
0701:                    this .offset = eolOffset;
0702:                }
0703:
0704:                public int getOffset() {
0705:                    return offset;
0706:                }
0707:
0708:                public @Override
0709:                boolean targetOffsetReached(int offset, char ch, int x,
0710:                        int charWidth, DrawContext ctx) {
0711:                    if (offset <= eolOffset) {
0712:                        if (x + charWidth < targetX) {
0713:                            this .offset = offset;
0714:                            return true;
0715:                        } else { // target position inside the char
0716:                            this .offset = offset;
0717:                            if (targetX > x + charWidth / 2) {
0718:                                Document doc = getDocument();
0719:                                if (ch != '\n' && doc != null
0720:                                        && offset < doc.getLength()) { //NOI18N
0721:                                    this .offset++;
0722:                                }
0723:                            }
0724:                            return false;
0725:                        }
0726:                    } else {
0727:                        return false;
0728:                    }
0729:                }
0730:
0731:            } // End of ViewToModelDG class
0732:
0733:            private final class ModelToViewDG extends DrawGraphics.SimpleDG {
0734:
0735:                private Rectangle r;
0736:
0737:                public Rectangle getRectangle() {
0738:                    return r;
0739:                }
0740:
0741:                public void setRectangle(Rectangle r) {
0742:                    this .r = r;
0743:                }
0744:
0745:                public @Override
0746:                boolean targetOffsetReached(int pos, char ch, int x,
0747:                        int charWidth, DrawContext ctx) {
0748:                    r.x = x;
0749:                    r.y = getY();
0750:                    r.width = charWidth;
0751:                    r.height = getEditorUI().getLineHeight();
0752:                    return false;
0753:                }
0754:            } // End of ModelToViewDG class
0755:
0756:            public @Override
0757:            View createFragment(int p0, int p1) {
0758:                Element elem = getElement();
0759:                return // necessary conditions in accordance with javadoc
0760:                p0 >= 0 && p0 >= elem.getStartOffset()
0761:                        && p0 < elem.getEndOffset()
0762:                        && p1 > 0
0763:                        && p1 <= elem.getEndOffset()
0764:                        && p1 > elem.getStartOffset()
0765:                        &&
0766:                        // create fragment only if one of the element differs from valid start or end offset
0767:                        (p0 != elem.getStartOffset() || p1 != elem
0768:                                .getEndOffset()) ? new FragmentView(
0769:                        getElement(), p0 - elem.getStartOffset(), p1 - p0)
0770:                        : this ;
0771:            }
0772:
0773:            public double getLayoutMajorAxisPreferredSpan() {
0774:                return layoutMajorAxisPreferredSpan;
0775:            }
0776:
0777:            public float getLayoutMajorAxisPreferredSpanFloat() {
0778:                return layoutMajorAxisPreferredSpan;
0779:            }
0780:
0781:            protected void setLayoutMajorAxisPreferredSpan(
0782:                    float layoutMajorAxisPreferredSpan) {
0783:                this .layoutMajorAxisPreferredSpan = layoutMajorAxisPreferredSpan;
0784:            }
0785:
0786:            public double getLayoutMajorAxisRawOffset() {
0787:                return layoutMajorAxisRawOffset;
0788:            }
0789:
0790:            public void setLayoutMajorAxisRawOffset(
0791:                    double layoutMajorAxisRawOffset) {
0792:                this .layoutMajorAxisRawOffset = layoutMajorAxisRawOffset;
0793:            }
0794:
0795:            public float getLayoutMinorAxisAlignment() {
0796:                return getAlignment(getMinorAxis()); // not cached
0797:            }
0798:
0799:            public float getLayoutMinorAxisMaximumSpan() {
0800:                return getLayoutMinorAxisPreferredSpan();
0801:            }
0802:
0803:            public float getLayoutMinorAxisMinimumSpan() {
0804:                return getLayoutMinorAxisPreferredSpan();
0805:            }
0806:
0807:            public float getLayoutMinorAxisPreferredSpan() {
0808:                return layoutMinorAxisPreferredSpan;
0809:            }
0810:
0811:            protected void setLayoutMinorAxisPreferredSpan(
0812:                    float layoutMinorAxisPreferredSpan) {
0813:                this .layoutMinorAxisPreferredSpan = layoutMinorAxisPreferredSpan;
0814:            }
0815:
0816:            public View getView() {
0817:                return this ;
0818:            }
0819:
0820:            public int getViewRawIndex() {
0821:                return viewRawIndex;
0822:            }
0823:
0824:            public void setViewRawIndex(int viewRawIndex) {
0825:                this .viewRawIndex = viewRawIndex;
0826:            }
0827:
0828:            public boolean isFlyweight() {
0829:                return false;
0830:            }
0831:
0832:            public ViewLayoutState selectLayoutMajorAxis(int majorAxis) {
0833:                //        assert ViewUtilities.isAxisValid(majorAxis);
0834:
0835:                if (majorAxis == View.X_AXIS) {
0836:                    setStatusBits(X_MAJOR_AXIS_BIT);
0837:                } else { // y axis
0838:                    clearStatusBits(X_MAJOR_AXIS_BIT);
0839:                }
0840:
0841:                return this ;
0842:            }
0843:
0844:            protected final ViewLayoutState.Parent getLayoutStateParent() {
0845:                View parent = getView().getParent();
0846:                return (parent instanceof  ViewLayoutState.Parent) ? ((ViewLayoutState.Parent) parent)
0847:                        : null;
0848:            }
0849:
0850:            public void updateLayout() {
0851:                // First check whether the layout still need updates
0852:                if (isLayoutValid()) {
0853:                    return; // nothing to do
0854:                }
0855:
0856:                ViewLayoutState.Parent lsParent = getLayoutStateParent();
0857:                if (lsParent == null) {
0858:                    return;
0859:                }
0860:
0861:                // Check whether minor axis has changed
0862:                if (isStatusBitsNonZero(MINOR_AXIS_PREFERENCE_CHANGED_BIT)) { // minor not valid
0863:                    clearStatusBits(MINOR_AXIS_PREFERENCE_CHANGED_BIT);
0864:
0865:                    int minorAxis = getMinorAxis();
0866:                    if (minorAxisUpdateLayout(minorAxis)) {
0867:                        lsParent.minorAxisPreferenceChanged(this );
0868:                    }
0869:                }
0870:
0871:                // Check whether major axis has changed
0872:                if (isStatusBitsNonZero(MAJOR_AXIS_PREFERENCE_CHANGED_BIT)) { // major not valid
0873:                    clearStatusBits(MAJOR_AXIS_PREFERENCE_CHANGED_BIT);
0874:
0875:                    float oldSpan = getLayoutMajorAxisPreferredSpanFloat();
0876:                    float newSpan = getPreferredSpan(getMajorAxis());
0877:                    setLayoutMajorAxisPreferredSpan(newSpan);
0878:                    double majorAxisSpanDelta = newSpan - oldSpan;
0879:                    if (majorAxisSpanDelta != 0) {
0880:                        lsParent.majorAxisPreferenceChanged(this ,
0881:                                majorAxisSpanDelta);
0882:                    }
0883:                }
0884:
0885:                // Check whether size must be set on the view
0886:                if (isStatusBitsNonZero(VIEW_SIZE_INVALID_BIT)) {
0887:                    clearStatusBits(VIEW_SIZE_INVALID_BIT);
0888:
0889:                    float width;
0890:                    float height;
0891:                    float majorAxisSpan = (float) getLayoutMajorAxisPreferredSpan();
0892:                    float minorAxisSpan = lsParent.getMinorAxisSpan(this );
0893:                    if (isXMajorAxis()) { // x is major axis
0894:                        width = majorAxisSpan;
0895:                        height = minorAxisSpan;
0896:                    } else {
0897:                        width = minorAxisSpan;
0898:                        height = majorAxisSpan;
0899:                    }
0900:
0901:                    setSize(width, height);
0902:                }
0903:
0904:                // Possibly update layout again
0905:                updateLayout();
0906:            }
0907:
0908:            protected boolean minorAxisUpdateLayout(int minorAxis) {
0909:                boolean minorAxisPreferenceChanged = false;
0910:                float val;
0911:
0912:                val = getPreferredSpan(minorAxis);
0913:                if (val != getLayoutMinorAxisPreferredSpan()) {
0914:                    setLayoutMinorAxisPreferredSpan(val);
0915:                    minorAxisPreferenceChanged = true;
0916:                }
0917:
0918:                return minorAxisPreferenceChanged;
0919:            }
0920:
0921:            public void viewPreferenceChanged(boolean width, boolean height) {
0922:                if (isXMajorAxis()) { // x is major axis
0923:                    if (width) {
0924:                        setStatusBits(MAJOR_AXIS_PREFERENCE_CHANGED_BIT); // major no longer valid
0925:                    }
0926:                    if (height) {
0927:                        setStatusBits(MINOR_AXIS_PREFERENCE_CHANGED_BIT); // minor no longer valid
0928:                    }
0929:                } else {
0930:                    if (width) {
0931:                        setStatusBits(MINOR_AXIS_PREFERENCE_CHANGED_BIT); // minor no longer valid
0932:                    }
0933:                    if (height) {
0934:                        setStatusBits(MAJOR_AXIS_PREFERENCE_CHANGED_BIT); // major no longer valid
0935:                    }
0936:                }
0937:                setStatusBits(VIEW_SIZE_INVALID_BIT); // child size no longer valid
0938:            }
0939:
0940:            public void markViewSizeInvalid() {
0941:                setStatusBits(VIEW_SIZE_INVALID_BIT);
0942:            }
0943:
0944:            public boolean isLayoutValid() {
0945:                return !isStatusBitsNonZero(ANY_INVALID);
0946:            }
0947:
0948:            protected final boolean isXMajorAxis() {
0949:                return isStatusBitsNonZero(X_MAJOR_AXIS_BIT);
0950:            }
0951:
0952:            protected final int getMajorAxis() {
0953:                return isXMajorAxis() ? View.X_AXIS : View.Y_AXIS;
0954:            }
0955:
0956:            protected final int getMinorAxis() {
0957:                return isXMajorAxis() ? View.Y_AXIS : View.X_AXIS;
0958:            }
0959:
0960:            protected final int getStatusBits(int bits) {
0961:                return (statusBits & bits);
0962:            }
0963:
0964:            protected final boolean isStatusBitsNonZero(int bits) {
0965:                return (getStatusBits(bits) != 0);
0966:            }
0967:
0968:            protected final void setStatusBits(int bits) {
0969:                statusBits |= bits;
0970:            }
0971:
0972:            protected final void clearStatusBits(int bits) {
0973:                statusBits &= ~bits;
0974:            }
0975:
0976:            /** Fragment View of DrawEngineLineView, typicaly created via createFragment method */
0977:            private static final class FragmentView extends DrawEngineLineView {
0978:
0979:                private Position startPos;
0980:                private Position endPos;
0981:
0982:                public FragmentView(Element elem, int offset, int length) {
0983:                    super (elem);
0984:                    try {
0985:                        Document doc = elem.getDocument();
0986:                        this .startPos = doc.createPosition(super 
0987:                                .getStartOffset()
0988:                                + offset);
0989:                        this .endPos = doc.createPosition(startPos.getOffset()
0990:                                + length);
0991:                    } catch (BadLocationException ble) {
0992:                        LOG.log(Level.INFO,
0993:                                "Can't create fragment view, offset = "
0994:                                        + offset + ", length = " + length, ble); //NOI18N
0995:                    }
0996:                }
0997:
0998:                protected @Override
0999:                boolean isFragment() {
1000:                    return true;
1001:                }
1002:
1003:                public @Override
1004:                int getStartOffset() {
1005:                    return startPos.getOffset();
1006:                }
1007:
1008:                public @Override
1009:                int getEndOffset() {
1010:                    return endPos.getOffset();
1011:                }
1012:
1013:            } // End of FragmentView class
1014:
1015:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.