Source Code Cross Referenced for EditorUI.java in  » Swing-Library » abeille-forms-designer » 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 » Swing Library » abeille forms designer » org.netbeans.editor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *                 Sun Public License Notice
0003:         * 
0004:         * The contents of this file are subject to the Sun Public License
0005:         * Version 1.0 (the "License"). You may not use this file except in
0006:         * compliance with the License. A copy of the License is available at
0007:         * http://www.sun.com/
0008:         * 
0009:         * The Original Code is NetBeans. The Initial Developer of the Original
0010:         * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
0011:         * Microsystems, Inc. All Rights Reserved.
0012:         */
0013:
0014:        package org.netbeans.editor;
0015:
0016:        import java.awt.BorderLayout;
0017:        import java.awt.Color;
0018:        import java.awt.Component;
0019:        import java.awt.Dimension;
0020:        import java.awt.Font;
0021:        import java.awt.FontMetrics;
0022:        import java.awt.Frame;
0023:        import java.awt.Graphics;
0024:        import java.awt.Graphics2D;
0025:        import java.awt.Insets;
0026:        import java.awt.Point;
0027:        import java.awt.Rectangle;
0028:        import java.awt.event.FocusAdapter;
0029:        import java.awt.event.FocusEvent;
0030:        import java.beans.PropertyChangeEvent;
0031:        import java.beans.PropertyChangeListener;
0032:        import java.beans.PropertyChangeSupport;
0033:        import java.util.HashMap;
0034:        import java.util.Hashtable;
0035:        import java.util.Iterator;
0036:        import java.util.Map;
0037:
0038:        import javax.swing.Action;
0039:        import javax.swing.JComponent;
0040:        import javax.swing.JPanel;
0041:        import javax.swing.JScrollPane;
0042:        import javax.swing.JViewport;
0043:        import javax.swing.SwingUtilities;
0044:        import javax.swing.event.ChangeEvent;
0045:        import javax.swing.event.ChangeListener;
0046:        import javax.swing.plaf.TextUI;
0047:        import javax.swing.text.BadLocationException;
0048:        import javax.swing.text.Caret;
0049:        import javax.swing.text.JTextComponent;
0050:        import javax.swing.text.View;
0051:
0052:        /**
0053:         * Editor UI for the component. All the additional UI features like advanced
0054:         * scrolling, info about fonts, abbreviations, keyword matching are based on
0055:         * this class.
0056:         * 
0057:         * @author Miloslav Metelka
0058:         * @version 1.00
0059:         */
0060:        public class EditorUI implements  ChangeListener,
0061:                PropertyChangeListener, SettingsChangeListener {
0062:
0063:            public static final String OVERWRITE_MODE_PROPERTY = "overwriteMode"; // NOI18N
0064:
0065:            public static final String COMPONENT_PROPERTY = "component"; // NOI18N
0066:
0067:            /**
0068:             * Default scrolling type is used for the standard setDot() call. If the
0069:             * area is on the screen, it jumps to it, otherwise it centers the requested
0070:             * area vertically in the middle of the window and it uses smallest covering
0071:             * on the right side.
0072:             */
0073:            public static final int SCROLL_DEFAULT = 0;
0074:
0075:            /**
0076:             * Scrolling type used for regular caret moves. The scrollJump is used when
0077:             * the caret requests area outside the screen.
0078:             */
0079:            public static final int SCROLL_MOVE = 1;
0080:
0081:            /**
0082:             * Scrolling type where the smallest covering for the requested rectangle is
0083:             * used. It's useful for going to the end of the line for example.
0084:             */
0085:            public static final int SCROLL_SMALLEST = 2;
0086:
0087:            /**
0088:             * Scrolling type for find operations, that can request additional
0089:             * configurable area in each direction, so the context around is visible
0090:             * too.
0091:             */
0092:            public static final int SCROLL_FIND = 3;
0093:
0094:            private static final Insets NULL_INSETS = new Insets(0, 0, 0, 0);
0095:
0096:            private static final Dimension NULL_DIMENSION = new Dimension(0, 0);
0097:
0098:            private static final int STYLE_CNT = 4;
0099:
0100:            private static final boolean debugUpdateLineHeight = Boolean
0101:                    .getBoolean("netbeans.debug.editor.updateLineHeight");
0102:
0103:            /**
0104:             * Map holding the coloring maps for the different languages. It helps to
0105:             * minimize the amount of the coloring maps and also save the time necessary
0106:             * for their creation.
0107:             */
0108:            private static final HashMap sharedColoringMaps = new HashMap(57);
0109:            private static final SettingsChangeListener clearingListener = new SettingsChangeListener() {
0110:                public void settingsChange(SettingsChangeEvent evt) {
0111:                    // Fired when the Settings are locked
0112:                    sharedColoringMaps.clear();
0113:                }
0114:            };
0115:
0116:            static {
0117:                Settings.addSettingsChangeListener(clearingListener);
0118:            }
0119:
0120:            /** Component this extended UI is related to. */
0121:            private JTextComponent component;
0122:
0123:            private JComponent extComponent;
0124:
0125:            /** Property change support for firing property changes */
0126:            PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
0127:                    this );
0128:
0129:            /** Document for the case ext ui is constructed without the component */
0130:            private BaseDocument printDoc;
0131:
0132:            /** Draw layer chain */
0133:            private DrawLayerList drawLayerList = new DrawLayerList();
0134:
0135:            /** Map holding the [name, coloring] pairs */
0136:            private Map coloringMap;
0137:
0138:            /**
0139:             * Character (or better line) height. Particular view can use a different
0140:             * character height however most views will probably use this one.
0141:             */
0142:            private int lineHeight = 1; // prevent possible division by zero
0143:
0144:            private float lineHeightCorrection = 1.0f;
0145:
0146:            /** Ascent of the line which is maximum ascent of all the fonts used. */
0147:            private int lineAscent;
0148:
0149:            /** Width of the space in the default coloring's font */
0150:            int defaultSpaceWidth = 1;
0151:
0152:            /** Flag to initialize fonts */
0153:            private boolean fontsInited;
0154:
0155:            /** Should the search words be colored? */
0156:            boolean highlightSearch;
0157:
0158:            /**
0159:             * Enable displaying line numbers. Both this flag and
0160:             * <tt>lineNumberVisibleSetting</tt> must be true to have the line numbers
0161:             * visible in the window. This flag is false by default. It's turned on
0162:             * automatically if the getExtComponent is called.
0163:             */
0164:            boolean lineNumberEnabled;
0165:
0166:            /** This flag corresponds to the LINE_NUMBER_VISIBLE setting. */
0167:            boolean lineNumberVisibleSetting;
0168:
0169:            /**
0170:             * Whether to show line numbers or not. This flag is obtained using bitwise
0171:             * AND operation on lineNumberEnabled flag and lineNumberVisibleSetting
0172:             * flag.
0173:             */
0174:            boolean lineNumberVisible;
0175:
0176:            /**
0177:             * Line number total width with indentation. It includes left and right
0178:             * line-number margins and lineNumberDigitWidth * lineNumberMaxDigitCount.
0179:             */
0180:            int lineNumberWidth;
0181:
0182:            /**
0183:             * Width of one digit used for line numbering. It's based on the information
0184:             * from the line coloring.
0185:             */
0186:            int lineNumberDigitWidth;
0187:
0188:            /** Current maximum count of digits in line number */
0189:            int lineNumberMaxDigitCount;
0190:
0191:            /** Margin on the left and right side of the line number */
0192:            Insets lineNumberMargin;
0193:
0194:            /**
0195:             * This is the size of the editor as component while the real size of the
0196:             * lines edited can be lower. The reason why to use this virtual size is
0197:             * that each resizing of the component means revalidating and therefore
0198:             * repainting of the whole component.
0199:             */
0200:            Rectangle virtualSize = new Rectangle();
0201:
0202:            // /** This is the increment by which the size of the component
0203:            // * is increased.
0204:            // */
0205:            // Rectangle virtualSizeIncrement = new Rectangle(); !!!
0206:
0207:            /** Margin between the line-number bar and the text. */
0208:            int textLeftMarginWidth;
0209:
0210:            /**
0211:             * This is the full margin around the text. The left margin is an addition
0212:             * of component's margin and lineNumberWidth and textLeftMarginWidth.
0213:             */
0214:            Insets textMargin = NULL_INSETS;
0215:
0216:            /**
0217:             * How much columns/lines to add when the scroll is performed so that the
0218:             * component is not scrolled so often. Negative number means portion of the
0219:             * extent width/height
0220:             */
0221:            Insets scrollJumpInsets;
0222:
0223:            /**
0224:             * How much columns/lines to add when the scroll is performed so that the
0225:             * component is not scrolled so often. Negative number means portion of the
0226:             * extent width/height
0227:             */
0228:            Insets scrollFindInsets;
0229:
0230:            /**
0231:             * Flag saying whether either the width or height in virtualSize were
0232:             * updated.
0233:             */
0234:            boolean virtualSizeUpdated;
0235:
0236:            /** Listener to changes in settings */
0237:            private PropertyChangeListener settingsListener;
0238:
0239:            /** EditorUI properties */
0240:            Hashtable props = new Hashtable(11);
0241:
0242:            boolean textLimitLineVisible;
0243:
0244:            Color textLimitLineColor;
0245:
0246:            int textLimitWidth;
0247:
0248:            private Rectangle lastExtentBounds = new Rectangle();
0249:
0250:            private Dimension componentSizeIncrement = new Dimension();
0251:
0252:            private Abbrev abbrev;
0253:
0254:            private WordMatch wordMatch;
0255:
0256:            private Object componentLock;
0257:
0258:            /** Status bar */
0259:            StatusBar statusBar;
0260:
0261:            private FocusAdapter focusL;
0262:
0263:            Map renderingHints;
0264:
0265:            /** Glyph gutter used for drawing of annotation glyph icons. */
0266:            private GlyphGutter glyphGutter = null;
0267:
0268:            /**
0269:             * The line numbers can be shown in glyph gutter and therefore it is
0270:             * necessary to disable drawing of lines here. During the printing on the
0271:             * the other hand, line numbers must be visible.
0272:             */
0273:            private boolean disableLineNumbers = true;
0274:
0275:            /** Left right corner of the JScrollPane */
0276:            private JPanel glyphCorner;
0277:
0278:            /** Construct extended UI for the use with a text component */
0279:            public EditorUI() {
0280:                Settings.addSettingsChangeListener(this );
0281:
0282:                focusL = new FocusAdapter() {
0283:                    public void focusGained(FocusEvent evt) {
0284:                        Registry.activate(getComponent());
0285:                    }
0286:                };
0287:
0288:            }
0289:
0290:            /** Construct extended UI for printing the given document */
0291:            public EditorUI(BaseDocument printDoc) {
0292:                this .printDoc = printDoc;
0293:
0294:                settingsChange(null);
0295:
0296:                setLineNumberEnabled(true);
0297:
0298:                updateLineNumberWidth(0);
0299:
0300:                drawLayerList.add(printDoc.getDrawLayerList());
0301:            }
0302:
0303:            /**
0304:             * Gets the coloring map that can be shared by the components with the same
0305:             * kit. Only the component coloring map is provided.
0306:             */
0307:            protected static Map getSharedColoringMap(Class kitClass) {
0308:                synchronized (Settings.class) { // must sync like this against dedloks
0309:                    Map cm = (Map) sharedColoringMaps.get(kitClass);
0310:                    if (cm == null) {
0311:                        cm = SettingsUtil.getColoringMap(kitClass, false, true);
0312:                        // Test if there's a default coloring
0313:                        if (cm.get(SettingsNames.DEFAULT_COLORING) == null) {
0314:                            cm.put(SettingsNames.DEFAULT_COLORING,
0315:                                    SettingsDefaults.defaultColoring);
0316:                        }
0317:
0318:                        sharedColoringMaps.put(kitClass, cm);
0319:                    }
0320:
0321:                    return cm;
0322:                }
0323:            }
0324:
0325:            /**
0326:             * Called when the <tt>BaseTextUI</tt> is being installed into the
0327:             * component.
0328:             */
0329:            protected void installUI(JTextComponent c) {
0330:                synchronized (getComponentLock()) {
0331:                    this .component = c;
0332:                    putProperty(COMPONENT_PROPERTY, c);
0333:
0334:                    // listen on component
0335:                    component.addPropertyChangeListener(this );
0336:                    component.addFocusListener(focusL);
0337:
0338:                    // listen on caret
0339:                    Caret caret = component.getCaret();
0340:                    if (caret != null) {
0341:                        caret.addChangeListener(this );
0342:                    }
0343:
0344:                    BaseDocument doc = getDocument();
0345:                    if (doc != null) {
0346:                        modelChanged(null, doc);
0347:                    }
0348:                }
0349:
0350:                // Make sure all the things depending on non-null component will be
0351:                // updated
0352:                settingsChange(null);
0353:
0354:                // fix for issue #16352
0355:                getDefaultColoring().apply(component);
0356:            }
0357:
0358:            /**
0359:             * Called when the <tt>BaseTextUI</tt> is being uninstalled from the
0360:             * component.
0361:             */
0362:            protected void uninstallUI(JTextComponent c) {
0363:                synchronized (getComponentLock()) {
0364:
0365:                    // fix for issue 12996
0366:                    if (component != null) {
0367:
0368:                        // stop listening on caret
0369:                        Caret caret = component.getCaret();
0370:                        if (caret != null) {
0371:                            caret.removeChangeListener(this );
0372:                        }
0373:
0374:                        // stop listening on component
0375:                        component.removePropertyChangeListener(this );
0376:                        component.removeFocusListener(focusL);
0377:
0378:                    }
0379:
0380:                    BaseDocument doc = getDocument();
0381:                    if (doc != null) {
0382:                        modelChanged(doc, null);
0383:                    }
0384:
0385:                    component = null;
0386:                    putProperty(COMPONENT_PROPERTY, null);
0387:
0388:                    // Clear the font-metrics cache
0389:                    FontMetricsCache.clear();
0390:                }
0391:            }
0392:
0393:            /**
0394:             * Get the lock assuring the component will not be changed by
0395:             * <tt>installUI()</tt> or <tt>uninstallUI()</tt>. It's useful for the
0396:             * classes that want to listen for the component change in <tt>EditorUI</tt>.
0397:             */
0398:            public Object getComponentLock() {
0399:                if (componentLock == null) {
0400:                    componentLock = new ComponentLock();
0401:                }
0402:                return componentLock;
0403:            }
0404:
0405:            static class ComponentLock {
0406:            };
0407:
0408:            public void addPropertyChangeListener(PropertyChangeListener l) {
0409:                propertyChangeSupport.addPropertyChangeListener(l);
0410:            }
0411:
0412:            public void addPropertyChangeListener(String propertyName,
0413:                    PropertyChangeListener l) {
0414:                propertyChangeSupport
0415:                        .addPropertyChangeListener(propertyName, l);
0416:            }
0417:
0418:            public void removePropertyChangeListener(PropertyChangeListener l) {
0419:                propertyChangeSupport.removePropertyChangeListener(l);
0420:            }
0421:
0422:            public void removePropertyChangeListener(String propertyName,
0423:                    PropertyChangeListener l) {
0424:                propertyChangeSupport.removePropertyChangeListener(
0425:                        propertyName, l);
0426:            }
0427:
0428:            protected final void firePropertyChange(String propertyName,
0429:                    Object oldValue, Object newValue) {
0430:                propertyChangeSupport.firePropertyChange(propertyName,
0431:                        oldValue, newValue);
0432:            }
0433:
0434:            public void settingsChange(SettingsChangeEvent evt) {
0435:                if (component != null) {
0436:                    if (Utilities.getKit(component) == null) {
0437:                        return; // prevent problems if not garbage collected and
0438:                        // settings changed
0439:                    }
0440:                }
0441:
0442:                Class kitClass = getKitClass();
0443:                String settingName = (evt != null) ? evt.getSettingName()
0444:                        : null;
0445:
0446:                if (settingName == null
0447:                        || SettingsNames.LINE_NUMBER_VISIBLE
0448:                                .equals(settingName)
0449:                        || SettingsNames.PRINT_LINE_NUMBER_VISIBLE
0450:                                .equals(settingName)) {
0451:                    lineNumberVisibleSetting = SettingsUtil
0452:                            .getBoolean(
0453:                                    kitClass,
0454:                                    (component != null) ? SettingsNames.LINE_NUMBER_VISIBLE
0455:                                            : SettingsNames.PRINT_LINE_NUMBER_VISIBLE,
0456:                                    (component != null) ? SettingsDefaults.defaultLineNumberVisible
0457:                                            : SettingsDefaults.defaultPrintLineNumberVisible);
0458:                    lineNumberVisible = lineNumberEnabled
0459:                            && lineNumberVisibleSetting;
0460:
0461:                    // if this is printing, the drawing of original line numbers must be
0462:                    // enabled
0463:                    if (component == null)
0464:                        disableLineNumbers = false;
0465:
0466:                    if (disableLineNumbers)
0467:                        lineNumberVisible = false;
0468:                }
0469:
0470:                BaseDocument doc = getDocument();
0471:                if (doc != null) {
0472:
0473:                    if (settingName == null
0474:                            || SettingsNames.LINE_NUMBER_MARGIN
0475:                                    .equals(settingName)) {
0476:                        Object value = Settings.getValue(kitClass,
0477:                                SettingsNames.LINE_NUMBER_MARGIN);
0478:                        lineNumberMargin = (value instanceof  Insets) ? (Insets) value
0479:                                : NULL_INSETS;
0480:                    }
0481:
0482:                    if (settingName == null
0483:                            || SettingsNames.TEXT_LEFT_MARGIN_WIDTH
0484:                                    .equals(settingName)) {
0485:                        textLeftMarginWidth = SettingsUtil.getInteger(kitClass,
0486:                                SettingsNames.TEXT_LEFT_MARGIN_WIDTH,
0487:                                SettingsDefaults.defaultTextLeftMarginWidth);
0488:                    }
0489:
0490:                    if (settingName == null
0491:                            || SettingsNames.LINE_HEIGHT_CORRECTION
0492:                                    .equals(settingName)) {
0493:                        Object value = Settings.getValue(kitClass,
0494:                                SettingsNames.LINE_HEIGHT_CORRECTION);
0495:                        if (!(value instanceof  Float)
0496:                                || ((Float) value).floatValue() < 0) {
0497:                            value = SettingsDefaults.defaultLineHeightCorrection;
0498:                        }
0499:                        lineHeightCorrection = ((Float) value).floatValue();
0500:                    }
0501:
0502:                    if (settingName == null
0503:                            || SettingsNames.TEXT_LIMIT_LINE_VISIBLE
0504:                                    .equals(settingName)) {
0505:                        textLimitLineVisible = SettingsUtil.getBoolean(
0506:                                kitClass,
0507:                                SettingsNames.TEXT_LIMIT_LINE_VISIBLE,
0508:                                SettingsDefaults.defaultTextLimitLineVisible);
0509:                    }
0510:
0511:                    if (settingName == null
0512:                            || SettingsNames.TEXT_LIMIT_LINE_COLOR
0513:                                    .equals(settingName)) {
0514:                        Object value = Settings.getValue(kitClass,
0515:                                SettingsNames.TEXT_LIMIT_LINE_COLOR);
0516:                        textLimitLineColor = (value instanceof  Color) ? (Color) value
0517:                                : SettingsDefaults.defaultTextLimitLineColor;
0518:                    }
0519:
0520:                    if (settingName == null
0521:                            || SettingsNames.TEXT_LIMIT_WIDTH
0522:                                    .equals(settingName)) {
0523:                        textLimitWidth = SettingsUtil.getPositiveInteger(
0524:                                kitClass, SettingsNames.TEXT_LIMIT_WIDTH,
0525:                                SettingsDefaults.defaultTextLimitWidth);
0526:                    }
0527:
0528:                    // component only properties
0529:                    if (component != null) {
0530:                        if (settingName == null
0531:                                || SettingsNames.SCROLL_JUMP_INSETS
0532:                                        .equals(settingName)) {
0533:                            Object value = Settings.getValue(kitClass,
0534:                                    SettingsNames.SCROLL_JUMP_INSETS);
0535:                            scrollJumpInsets = (value instanceof  Insets) ? (Insets) value
0536:                                    : NULL_INSETS;
0537:                        }
0538:
0539:                        if (settingName == null
0540:                                || SettingsNames.SCROLL_FIND_INSETS
0541:                                        .equals(settingName)) {
0542:                            Object value = Settings.getValue(kitClass,
0543:                                    SettingsNames.SCROLL_FIND_INSETS);
0544:                            scrollFindInsets = (value instanceof  Insets) ? (Insets) value
0545:                                    : NULL_INSETS;
0546:                        }
0547:
0548:                        if (settingName == null
0549:                                || SettingsNames.COMPONENT_SIZE_INCREMENT
0550:                                        .equals(settingName)) {
0551:                            Object value = Settings.getValue(kitClass,
0552:                                    SettingsNames.COMPONENT_SIZE_INCREMENT);
0553:                            componentSizeIncrement = (value instanceof  Dimension) ? (Dimension) value
0554:                                    : NULL_DIMENSION;
0555:                        }
0556:
0557:                        if (settingName == null
0558:                                || SettingsNames.RENDERING_HINTS
0559:                                        .equals(settingName)) {
0560:                            Object value = Settings.getValue(kitClass,
0561:                                    SettingsNames.RENDERING_HINTS);
0562:                            renderingHints = (value instanceof  Map) ? (Map) value
0563:                                    : null;
0564:                        }
0565:
0566:                        if (settingName == null
0567:                                || SettingsNames.CARET_COLOR_INSERT_MODE
0568:                                        .equals(settingName)
0569:                                || SettingsNames.CARET_COLOR_OVERWRITE_MODE
0570:                                        .equals(settingName)) {
0571:                            Boolean b = (Boolean) getProperty(OVERWRITE_MODE_PROPERTY);
0572:                            Color caretColor;
0573:                            if (b == null || !b.booleanValue()) {
0574:                                Object value = Settings.getValue(kitClass,
0575:                                        SettingsNames.CARET_COLOR_INSERT_MODE);
0576:                                caretColor = (value instanceof  Color) ? (Color) value
0577:                                        : SettingsDefaults.defaultCaretColorInsertMode;
0578:
0579:                            } else {
0580:                                Object value = Settings
0581:                                        .getValue(
0582:                                                kitClass,
0583:                                                SettingsNames.CARET_COLOR_OVERWRITE_MODE);
0584:                                caretColor = (value instanceof  Color) ? (Color) value
0585:                                        : SettingsDefaults.defaultCaretColorOvwerwriteMode;
0586:                            }
0587:
0588:                            if (caretColor != null) {
0589:                                component.setCaretColor(caretColor);
0590:                            }
0591:                        }
0592:
0593:                        component.setKeymap(Utilities.getKit(component)
0594:                                .getKeymap());
0595:
0596:                        // fix for issues 13842, 14003
0597:                        if (SwingUtilities.isEventDispatchThread()) {
0598:                            BaseTextUI ui = (BaseTextUI) component.getUI();
0599:                            ui.updateHeight();
0600:                            component.repaint();
0601:                        } else {
0602:                            SwingUtilities.invokeLater(new Runnable() {
0603:                                public void run() {
0604:                                    if (component != null) {
0605:                                        BaseTextUI ui = (BaseTextUI) component
0606:                                                .getUI();
0607:                                        ui.updateHeight();
0608:                                        component.repaint();
0609:                                    }
0610:                                }
0611:                            });
0612:                        }
0613:                    }
0614:                }
0615:
0616:                coloringMap = null; // reset coloring map so it's lazily rebuilt
0617:                fontsInited = false;
0618:
0619:            }
0620:
0621:            public void stateChanged(final ChangeEvent evt) {
0622:                SwingUtilities.invokeLater(new Runnable() {
0623:                    public void run() {
0624:                        if (component != null) {
0625:                            BaseKit kit = Utilities.getKit(component);
0626:                            if (kit != null) {
0627:                                boolean selectionVisible = ((Caret) evt
0628:                                        .getSource()).isSelectionVisible();
0629:                                Action a = kit
0630:                                        .getActionByName(BaseKit.cutAction);
0631:                                if (a != null) {
0632:                                    a.setEnabled(selectionVisible);
0633:                                }
0634:
0635:                                a = kit.getActionByName(BaseKit.copyAction);
0636:                                if (a != null) {
0637:                                    a.setEnabled(selectionVisible);
0638:                                }
0639:
0640:                                a = kit
0641:                                        .getActionByName(BaseKit.removeSelectionAction);
0642:                                if (a != null) {
0643:                                    a.setEnabled(selectionVisible);
0644:                                }
0645:                            }
0646:                        }
0647:                    }
0648:                });
0649:            }
0650:
0651:            protected void modelChanged(BaseDocument oldDoc, BaseDocument newDoc) {
0652:                if (oldDoc != null) {
0653:                    // remove all document layers
0654:                    drawLayerList.remove(oldDoc.getDrawLayerList());
0655:                }
0656:
0657:                if (newDoc != null) {
0658:                    settingsChange(null);
0659:
0660:                    // add all document layers
0661:                    drawLayerList.add(newDoc.getDrawLayerList());
0662:                }
0663:
0664:                if (oldDoc != null)
0665:                    oldDoc.getBookmarks().removeAll();
0666:            }
0667:
0668:            public void propertyChange(PropertyChangeEvent evt) {
0669:                String propName = evt.getPropertyName();
0670:
0671:                if ("document".equals(propName)) {
0672:                    BaseDocument oldDoc = (evt.getOldValue() instanceof  BaseDocument) ? (BaseDocument) evt
0673:                            .getOldValue()
0674:                            : null;
0675:                    BaseDocument newDoc = (evt.getNewValue() instanceof  BaseDocument) ? (BaseDocument) evt
0676:                            .getNewValue()
0677:                            : null;
0678:                    modelChanged(oldDoc, newDoc);
0679:
0680:                } else if ("margin".equals(propName)) { // NOI18N
0681:                    updateTextMargin();
0682:
0683:                } else if ("caret".equals(propName)) { // NOI18N
0684:                    if (evt.getOldValue() instanceof  Caret) {
0685:                        ((Caret) evt.getOldValue()).removeChangeListener(this );
0686:                    }
0687:                    if (evt.getNewValue() instanceof  Caret) {
0688:                        ((Caret) evt.getNewValue()).addChangeListener(this );
0689:                    }
0690:
0691:                } else if ("enabled".equals(propName)) { // NOI18N
0692:                    if (!component.isEnabled()) {
0693:                        component.getCaret().setVisible(false);
0694:                    }
0695:                }
0696:            }
0697:
0698:            protected Map createColoringMap() {
0699:                Map cm;
0700:
0701:                if (component != null) {
0702:                    // Use the shared coloring-map to save space and time
0703:                    cm = getSharedColoringMap(getKitClass());
0704:
0705:                } else { // print coloring-map must be created
0706:                    cm = SettingsUtil.getColoringMap(getKitClass(),
0707:                            (component == null), true);
0708:                    // Test if there's a default coloring
0709:                    if (cm.get(SettingsNames.DEFAULT_COLORING) == null) {
0710:                        cm.put(SettingsNames.DEFAULT_COLORING,
0711:                                SettingsDefaults.defaultColoring);
0712:                    }
0713:                }
0714:
0715:                return cm;
0716:            }
0717:
0718:            public int getLineHeight() {
0719:                return lineHeight;
0720:            }
0721:
0722:            public int getLineAscent() {
0723:                return lineAscent;
0724:            }
0725:
0726:            public Map getColoringMap() {
0727:                if (coloringMap == null) {
0728:                    coloringMap = createColoringMap();
0729:                }
0730:                return coloringMap;
0731:            }
0732:
0733:            public Coloring getDefaultColoring() {
0734:                return (Coloring) getColoringMap().get(
0735:                        SettingsNames.DEFAULT_COLORING);
0736:            }
0737:
0738:            public Coloring getColoring(String coloringName) {
0739:                return (Coloring) getColoringMap().get(coloringName);
0740:            }
0741:
0742:            private void updateLineHeight(Graphics g) {
0743:                if (debugUpdateLineHeight) {
0744:                    System.err
0745:                            .println("EditorUI.updateLineHeight(): Computing lineHeight ...");
0746:                }
0747:
0748:                Map cm = getColoringMap();
0749:                Iterator i = cm.entrySet().iterator();
0750:                int maxHeight = 1;
0751:                int maxAscent = 0;
0752:                while (i.hasNext()) {
0753:                    Map.Entry me = (Map.Entry) i.next();
0754:                    String coloringName = (String) me.getKey();
0755:                    Coloring c = (Coloring) me.getValue();
0756:                    if (c != null) {
0757:                        Font font = c.getFont();
0758:                        if (font != null
0759:                                && (c.getFontMode() & Coloring.FONT_MODE_APPLY_SIZE) != 0) {
0760:                            FontMetrics fm = g.getFontMetrics(font);
0761:                            if (fm != null) {
0762:                                if (debugUpdateLineHeight) {
0763:                                    if (maxHeight < fm.getHeight()) {
0764:                                        System.err
0765:                                                .println("Updating maxHeight from "
0766:                                                        + maxHeight
0767:                                                        + " to "
0768:                                                        + fm.getHeight()
0769:                                                        + ", coloringName="
0770:                                                        + coloringName
0771:                                                        + ", font=" + font);
0772:                                    }
0773:
0774:                                    if (maxHeight < fm.getHeight()) {
0775:                                        System.err
0776:                                                .println("Updating maxAscent from "
0777:                                                        + maxAscent
0778:                                                        + " to "
0779:                                                        + fm.getAscent()
0780:                                                        + ", coloringName="
0781:                                                        + coloringName
0782:                                                        + ", font=" + font);
0783:                                    }
0784:                                }
0785:
0786:                                maxHeight = Math.max(maxHeight, fm.getHeight());
0787:                                maxAscent = Math.max(maxAscent, fm.getAscent());
0788:                            }
0789:                        }
0790:                    }
0791:                }
0792:
0793:                // Apply lineHeightCorrection
0794:                lineHeight = (int) (maxHeight * lineHeightCorrection);
0795:                lineAscent = (int) (maxAscent * lineHeightCorrection);
0796:
0797:            }
0798:
0799:            /**
0800:             * Return whether the fonts are already initialized or not.
0801:             */
0802:            boolean isFontsInited() {
0803:                return fontsInited;
0804:            }
0805:
0806:            protected void update(Graphics g) {
0807:                Class kitClass = Utilities.getKitClass(component);
0808:
0809:                // Set the margin
0810:                if (kitClass != null) {
0811:                    Object value = Settings.getValue(kitClass,
0812:                            SettingsNames.MARGIN);
0813:                    Insets margin = (value instanceof  Insets) ? (Insets) value
0814:                            : null;
0815:                    component.setMargin(margin);
0816:                }
0817:
0818:                // Apply the default coloring to the component
0819:                getDefaultColoring().apply(component);
0820:
0821:                // Possibly apply the rendering hints
0822:                if (renderingHints != null) {
0823:                    ((Graphics2D) g).setRenderingHints(renderingHints);
0824:                }
0825:
0826:                Coloring dc = getDefaultColoring();
0827:
0828:                // Handle line number fonts and widths
0829:                Coloring lnc = (Coloring) getColoringMap().get(
0830:                        SettingsNames.LINE_NUMBER_COLORING);
0831:                if (lnc != null) {
0832:                    Font lnFont = lnc.getFont();
0833:                    if (lnFont == null) {
0834:                        lnFont = dc.getFont();
0835:                    }
0836:                    FontMetrics lnFM = g.getFontMetrics(lnFont);
0837:                    int maxWidth = 1;
0838:                    char[] digit = new char[1]; // will be used for '0' - '9'
0839:                    for (int i = 0; i <= 9; i++) {
0840:                        digit[0] = (char) ('0' + i);
0841:                        maxWidth = Math.max(maxWidth, lnFM.charsWidth(digit, 0,
0842:                                1));
0843:                    }
0844:                    lineNumberDigitWidth = maxWidth;
0845:                }
0846:
0847:                // Update line height
0848:                updateLineHeight(g);
0849:
0850:                // Update space width of the default coloring's font
0851:                FontMetricsCache.Info fmcInfo = FontMetricsCache
0852:                        .getInfo(getDefaultColoring().getFont());
0853:                defaultSpaceWidth = fmcInfo.getSpaceWidth(g);
0854:
0855:                // Update total height
0856:                if (component != null) {
0857:                    ((BaseTextUI) component.getUI()).updateHeight();
0858:                    updateLineNumberWidth(0);
0859:                    checkLineLimit();
0860:                }
0861:
0862:                /*
0863:                 * JDK1.3 patch for the behavior that occurs when the line is wider than
0864:                 * the screen and the user first clicks End key to go to the end and
0865:                 * then goes back by (Ctrl+)Left. As the non-simple scrolling mode is
0866:                 * used in JViewport in 1.3 the line number block appears shifted to the
0867:                 * right and gets repainted after 300ms which looks ugly. The patch is
0868:                 * to set the simple scrolling mode into JViewport.
0869:                 * 
0870:                 * getParentViewport().setScrollMode(0); // 2 stands for
0871:                 * SIMPLE_SCROLL_MODE
0872:                 * 
0873:                 */
0874:                try {
0875:                    JViewport vp = getParentViewport();
0876:                    if (vp != null) {
0877:                        java.lang.reflect.Method setScrollModeMethod = JViewport.class
0878:                                .getDeclaredMethod("setScrollMode",
0879:                                        new Class[] { Integer.TYPE }); // NOI18N
0880:                        setScrollModeMethod.invoke(vp,
0881:                                new Object[] { new Integer(0) });
0882:                    }
0883:                } catch (Throwable t) {
0884:                }
0885:
0886:                // Update various sizes
0887:                fontsInited = true;
0888:
0889:                // update glyph gutter colors and fonts
0890:                if (isGlyphGutterVisible()) {
0891:                    glyphGutter.update();
0892:                    updateScrollPaneCornerColor();
0893:                }
0894:
0895:                // FIx of #14295
0896:                updateVirtualHeight(0);
0897:            }
0898:
0899:            public final JTextComponent getComponent() {
0900:                return component;
0901:            }
0902:
0903:            /**
0904:             * Get the document to work on. Either component's document or printed
0905:             * document is returned. It can return null in case the component's document
0906:             * is not instance of BaseDocument.
0907:             */
0908:            public final BaseDocument getDocument() {
0909:                return (component != null) ? Utilities.getDocument(component)
0910:                        : printDoc;
0911:            }
0912:
0913:            private Class getKitClass() {
0914:                return (component != null) ? Utilities.getKitClass(component)
0915:                        : ((printDoc != null) ? printDoc.getKitClass() : null);
0916:            }
0917:
0918:            public Object getProperty(Object key) {
0919:                return props.get(key);
0920:            }
0921:
0922:            public void putProperty(Object key, Object value) {
0923:                Object oldValue;
0924:                if (value != null) {
0925:                    oldValue = props.put(key, value);
0926:                } else {
0927:                    oldValue = props.remove(key);
0928:                }
0929:                firePropertyChange(key.toString(), oldValue, value);
0930:            }
0931:
0932:            /**
0933:             * Create or get extended editor component. The extended component should
0934:             * normally be used for editing files instead of just the JEditorPane
0935:             * because it offers status bar and possibly other useful components. The
0936:             * getExtComponent() should not be used when the JEditorPane is included in
0937:             * dialog.
0938:             * 
0939:             * @see #hasExtComponent()
0940:             */
0941:            public JComponent getExtComponent() {
0942:                if (extComponent == null) {
0943:                    if (component != null) {
0944:                        setLineNumberEnabled(true); // enable line numbering
0945:
0946:                        // extComponent will be a panel
0947:                        extComponent = new JPanel(new BorderLayout());
0948:
0949:                        // Add the scroll-pane with the component to the center
0950:                        JScrollPane scroller = new JScrollPane(component);
0951:                        scroller.getViewport().setMinimumSize(
0952:                                new Dimension(4, 4));
0953:
0954:                        // glyph gutter must be created here
0955:                        glyphGutter = new GlyphGutter(this );
0956:                        scroller.setRowHeaderView(glyphGutter);
0957:
0958:                        glyphCorner = new JPanel();
0959:                        updateScrollPaneCornerColor();
0960:                        scroller.setCorner(JScrollPane.LOWER_LEFT_CORNER,
0961:                                glyphCorner);
0962:
0963:                        extComponent.add(scroller);
0964:
0965:                        // Install the status-bar panel to the bottom
0966:                        extComponent.add(getStatusBar().getPanel(),
0967:                                BorderLayout.SOUTH);
0968:                    }
0969:                }
0970:                return extComponent;
0971:            }
0972:
0973:            /**
0974:             * Whether this ui uses extComponent or not.
0975:             * 
0976:             * @see #getExtComponent()
0977:             */
0978:            public boolean hasExtComponent() {
0979:                return (extComponent != null);
0980:            }
0981:
0982:            public Abbrev getAbbrev() {
0983:                if (abbrev == null) {
0984:                    abbrev = new Abbrev(this , true, true);
0985:                }
0986:                return abbrev;
0987:            }
0988:
0989:            public WordMatch getWordMatch() {
0990:                if (wordMatch == null) {
0991:                    wordMatch = new WordMatch(this );
0992:                }
0993:                return wordMatch;
0994:            }
0995:
0996:            public StatusBar getStatusBar() {
0997:                if (statusBar == null) {
0998:                    statusBar = new StatusBar(this );
0999:                }
1000:                return statusBar;
1001:            }
1002:
1003:            final DrawLayerList getDrawLayerList() {
1004:                return drawLayerList;
1005:            }
1006:
1007:            /** Find the layer with some layer name in the layer hierarchy */
1008:            public DrawLayer findLayer(String layerName) {
1009:                return drawLayerList.findLayer(layerName);
1010:            }
1011:
1012:            /**
1013:             * Add new layer and use its priority to position it in the chain. If
1014:             * there's the layer with same visibility then the inserted layer will be
1015:             * placed after it.
1016:             * 
1017:             * @param layer
1018:             *            layer to insert into the chain
1019:             */
1020:            public boolean addLayer(DrawLayer layer, int visibility) {
1021:                return drawLayerList.add(layer, visibility);
1022:            }
1023:
1024:            public DrawLayer removeLayer(String layerName) {
1025:                return drawLayerList.remove(layerName);
1026:            }
1027:
1028:            public void repaint(int startY) {
1029:                repaint(startY, component.getHeight());
1030:            }
1031:
1032:            public void repaint(int startY, int height) {
1033:                if (height <= 0) {
1034:                    return;
1035:                }
1036:                int width = Math.max(component.getWidth(), 0);
1037:                startY = Math.max(startY, 0);
1038:                component.repaint(0, startY, width, height);
1039:            }
1040:
1041:            public void repaintOffset(int pos) throws BadLocationException {
1042:                repaintBlock(pos, pos);
1043:            }
1044:
1045:            /** Repaint the block between the given positions. */
1046:            public void repaintBlock(int startPos, int endPos)
1047:                    throws BadLocationException {
1048:                BaseTextUI ui = (BaseTextUI) component.getUI();
1049:                if (startPos > endPos) { // swap
1050:                    int tmpPos = startPos;
1051:                    startPos = endPos;
1052:                    endPos = tmpPos;
1053:                }
1054:                try {
1055:                    int yFrom = ui.getYFromPos(startPos);
1056:                    int yTo = ui.getYFromPos(endPos);
1057:                    repaint(yFrom, (yTo - yFrom) + lineHeight);
1058:                } catch (BadLocationException e) {
1059:                    if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
1060:                        e.printStackTrace();
1061:                    }
1062:                }
1063:            }
1064:
1065:            /** Is the parent of some editor component a viewport */
1066:            private JViewport getParentViewport() {
1067:                Component pc = component.getParent();
1068:                return (pc instanceof  JViewport) ? (JViewport) pc : null;
1069:            }
1070:
1071:            /** Finds the frame - parent of editor component */
1072:            public static Frame getParentFrame(Component c) {
1073:                do {
1074:                    c = c.getParent();
1075:                    if (c instanceof  Frame) {
1076:                        return (Frame) c;
1077:                    }
1078:                } while (c != null);
1079:                return null;
1080:            }
1081:
1082:            /**
1083:             * Possibly update virtual width. If the width is really updated, the method
1084:             * returns true.
1085:             */
1086:            public boolean updateVirtualWidth(int width) {
1087:                boolean updated = false;
1088:                if (width > virtualSize.width) {
1089:                    int widthInc = componentSizeIncrement.width;
1090:                    widthInc = (widthInc < 0) ? (lastExtentBounds.width
1091:                            * (-widthInc) / 100) : widthInc * defaultSpaceWidth;
1092:
1093:                    virtualSize.width = width + widthInc;
1094:                    virtualSizeUpdated = true;
1095:                    updated = true;
1096:                }
1097:
1098:                return updated;
1099:            }
1100:
1101:            /**
1102:             * Possibly update virtual height. If the height is really updated, the
1103:             * method returns true. There is a slight difference against virtual width
1104:             * in that if the height is shrinked too much the virtual height is shrinked
1105:             * too. 0 can be used to update to the real height.
1106:             */
1107:            public boolean updateVirtualHeight(int height) {
1108:                boolean updated = false;
1109:                updateLineNumberWidth(0);
1110:
1111:                if (height > 0) {
1112:                    if (height > virtualSize.height) {
1113:                        int heightInc = componentSizeIncrement.height;
1114:                        heightInc = (heightInc < 0) ? (lastExtentBounds.height
1115:                                * (-heightInc) / 100) : heightInc * lineHeight;
1116:
1117:                        virtualSize.height = height + heightInc;
1118:                        virtualSizeUpdated = true;
1119:                        updated = true;
1120:                    }
1121:
1122:                    if (height < virtualSize.height - lastExtentBounds.height) {
1123:                        virtualSize.height = height;
1124:                        virtualSizeUpdated = true;
1125:                        updated = true;
1126:                    }
1127:
1128:                } else { // compute real height - fix of #14295
1129:                    height = (int) ((TextUI) component.getUI()).getRootView(
1130:                            component).getPreferredSpan(View.Y_AXIS);
1131:                    if (height != virtualSize.height) {
1132:                        virtualSize.height = height;
1133:                        virtualSizeUpdated = true;
1134:                        updated = true;
1135:                    }
1136:                }
1137:
1138:                return updated;
1139:            }
1140:
1141:            public boolean isLineNumberEnabled() {
1142:                return lineNumberEnabled;
1143:            }
1144:
1145:            public void setLineNumberEnabled(boolean lineNumberEnabled) {
1146:                this .lineNumberEnabled = lineNumberEnabled;
1147:                lineNumberVisible = lineNumberEnabled
1148:                        && lineNumberVisibleSetting;
1149:                if (disableLineNumbers)
1150:                    lineNumberVisible = false;
1151:            }
1152:
1153:            /**
1154:             * Update the width that will be occupied by the line number.
1155:             * 
1156:             * @param maxDigitCount
1157:             *            maximum digit count that can the line number have. if it's
1158:             *            lower or equal to zero it will be computed automatically.
1159:             */
1160:            public void updateLineNumberWidth(int maxDigitCount) {
1161:                int oldWidth = lineNumberWidth;
1162:
1163:                if (lineNumberVisible) {
1164:                    try {
1165:                        if (maxDigitCount <= 0) {
1166:                            BaseDocument doc = getDocument();
1167:                            int lineCnt = Utilities.getLineOffset(doc, doc
1168:                                    .getLength()) + 1;
1169:                            maxDigitCount = Integer.toString(lineCnt).length();
1170:                        }
1171:
1172:                        if (maxDigitCount > lineNumberMaxDigitCount) {
1173:                            lineNumberMaxDigitCount = maxDigitCount;
1174:                        }
1175:
1176:                    } catch (BadLocationException e) {
1177:                        lineNumberMaxDigitCount = 1;
1178:                    }
1179:                    lineNumberWidth = lineNumberMaxDigitCount
1180:                            * lineNumberDigitWidth;
1181:                    if (lineNumberMargin != null) {
1182:                        lineNumberWidth += lineNumberMargin.left
1183:                                + lineNumberMargin.right;
1184:                    }
1185:
1186:                } else {
1187:                    lineNumberWidth = 0;
1188:                }
1189:
1190:                updateTextMargin();
1191:                if (oldWidth != lineNumberWidth) { // changed
1192:                    if (component != null) {
1193:                        component.repaint();
1194:                    }
1195:                }
1196:            }
1197:
1198:            void checkLineLimit() {
1199:                BaseDocument doc = getDocument();
1200:                if (doc != null) {
1201:                    Integer lineLimit = (Integer) doc
1202:                            .getProperty(BaseDocument.LINE_LIMIT_PROP);
1203:                    if (lineLimit != null) {
1204:                        if (component != null) {
1205:                            // Not using FM cache - could be called too early
1206:                            FontMetrics fm = component
1207:                                    .getFontMetrics(getDefaultColoring()
1208:                                            .getFont());
1209:                            if (fm != null) {
1210:                                int charWidth = fm.stringWidth("A");
1211:                                updateVirtualWidth(charWidth
1212:                                        * lineLimit.intValue()
1213:                                        + lineNumberWidth);
1214:                            }
1215:                        }
1216:                    }
1217:                }
1218:            }
1219:
1220:            public void updateTextMargin() {
1221:                if (!SwingUtilities.isEventDispatchThread()) {
1222:                    SwingUtilities.invokeLater(new Runnable() {
1223:                        public void run() {
1224:                            updateTextMargin();
1225:                        }
1226:                    });
1227:                }
1228:
1229:                Insets orig = textMargin;
1230:                Insets cm = (component != null) ? component.getMargin() : null;
1231:                int leftWidth = lineNumberWidth + textLeftMarginWidth;
1232:                if (cm != null) {
1233:                    textMargin = new Insets(cm.top, cm.left + leftWidth,
1234:                            cm.bottom, cm.right);
1235:                } else {
1236:                    textMargin = new Insets(0, leftWidth, 0, 0);
1237:                }
1238:                if (orig.top != textMargin.top
1239:                        || orig.bottom != textMargin.bottom) {
1240:                    ((BaseTextUI) component.getUI()).invalidateStartY();
1241:                }
1242:            }
1243:
1244:            public Rectangle getExtentBounds() {
1245:                return getExtentBounds(null);
1246:            }
1247:
1248:            /**
1249:             * Get position of the component extent. The (x, y) are set to (0, 0) if
1250:             * there's no viewport or (-x, -y) if there's one.
1251:             */
1252:            public Rectangle getExtentBounds(Rectangle r) {
1253:                if (r == null) {
1254:                    r = new Rectangle();
1255:                }
1256:                if (component != null) {
1257:                    JViewport port = getParentViewport();
1258:                    if (port != null) {
1259:                        Point p = port.getViewPosition();
1260:                        r.width = port.getWidth();
1261:                        r.height = port.getHeight();
1262:                        r.x = p.x;
1263:                        r.y = p.y;
1264:                    } else { // no viewport
1265:                        r.setBounds(component.getVisibleRect());
1266:                    }
1267:                }
1268:                return r;
1269:            }
1270:
1271:            /** Get the begining of the area covered by text */
1272:            public Insets getTextMargin() {
1273:                return textMargin;
1274:            }
1275:
1276:            public void scrollRectToVisible(final Rectangle r,
1277:                    final int scrollPolicy) {
1278:                Utilities.runInEventDispatchThread(new Runnable() {
1279:                    public void run() {
1280:                        scrollRectToVisibleFragile(r, scrollPolicy);
1281:                    }
1282:                });
1283:            }
1284:
1285:            /** Must be called with EventDispatchThread */
1286:            boolean scrollRectToVisibleFragile(Rectangle r, int scrollPolicy) {
1287:                Insets margin = getTextMargin();
1288:                Rectangle bounds = getExtentBounds();
1289:                r = new Rectangle(r); // make copy of orig rect
1290:                r.x -= margin.left;
1291:                r.y -= margin.top;
1292:                bounds.width -= margin.left + margin.right;
1293:                bounds.height -= margin.top + margin.bottom;
1294:                return scrollRectToVisibleImpl(r, scrollPolicy, bounds);
1295:            }
1296:
1297:            /**
1298:             * Scroll the view so that requested rectangle is best visible. There are
1299:             * different scroll policies available.
1300:             * 
1301:             * @return whether the extent has to be scrolled in any direction.
1302:             */
1303:            private boolean scrollRectToVisibleImpl(Rectangle r,
1304:                    int scrollPolicy, Rectangle bounds) {
1305:                if (bounds.width <= 0 || bounds.height <= 0) {
1306:                    return false;
1307:                }
1308:
1309:                // handle find scrolling specifically
1310:                if (scrollPolicy == SCROLL_FIND) {
1311:                    // converted inset
1312:                    int cnvFI = (scrollFindInsets.left < 0) ? (-bounds.width
1313:                            * scrollFindInsets.left / 100)
1314:                            : scrollFindInsets.left * defaultSpaceWidth;
1315:
1316:                    int nx = Math.max(r.x - cnvFI, 0);
1317:
1318:                    cnvFI = (scrollFindInsets.right < 0) ? (-bounds.width
1319:                            * scrollFindInsets.right / 100)
1320:                            : scrollFindInsets.right * defaultSpaceWidth;
1321:
1322:                    r.width += (r.x - nx) + cnvFI;
1323:                    r.x = nx;
1324:
1325:                    cnvFI = (scrollFindInsets.top < 0) ? (-bounds.height
1326:                            * scrollFindInsets.top / 100)
1327:                            : scrollFindInsets.top * lineHeight;
1328:
1329:                    int ny = Math.max(r.y - cnvFI, 0);
1330:
1331:                    cnvFI = (scrollFindInsets.bottom < 0) ? (-bounds.height
1332:                            * scrollFindInsets.bottom / 100)
1333:                            : scrollFindInsets.bottom * lineHeight;
1334:
1335:                    r.height += (r.y - ny) + cnvFI;
1336:                    r.y = ny;
1337:
1338:                    return scrollRectToVisibleImpl(r, SCROLL_SMALLEST, bounds); // recall
1339:                }
1340:                // r must be within virtualSize's width
1341:                if (r.x + r.width > virtualSize.width) {
1342:                    r.x = virtualSize.width - r.width;
1343:                    if (r.x < 0) {
1344:                        r.x = 0;
1345:                        r.width = virtualSize.width;
1346:                    }
1347:                    return scrollRectToVisibleImpl(r, scrollPolicy, bounds); // recall
1348:                }
1349:                // r must be within virtualSize's height
1350:                if (r.y + r.height > virtualSize.height) {
1351:                    r.y = virtualSize.height - r.height;
1352:                    if (r.y < 0) {
1353:                        r.y = 0;
1354:                        r.height = virtualSize.height;
1355:                    }
1356:                    return scrollRectToVisibleImpl(r, scrollPolicy, bounds);
1357:                }
1358:
1359:                // if r extends bounds dimension it must be corrected now
1360:                if (r.width > bounds.width || r.height > bounds.height) {
1361:                    Rectangle caretRect = new Rectangle((Rectangle) component
1362:                            .getCaret());
1363:                    if (caretRect.x >= r.x
1364:                            && caretRect.x + caretRect.width <= r.x + r.width
1365:                            && caretRect.y >= r.y
1366:                            && caretRect.y + caretRect.height <= r.y + r.height) { // caret
1367:                        // inside
1368:                        // requested
1369:                        // rect
1370:                        // move scroll rect for best caret visibility
1371:                        int overX = r.width - bounds.width;
1372:                        int overY = r.height - bounds.height;
1373:                        if (overX > 0) {
1374:                            r.x -= overX * (caretRect.x - r.x) / r.width;
1375:                        }
1376:                        if (overY > 0) {
1377:                            r.y -= overY * (caretRect.y - r.y) / r.height;
1378:                        }
1379:                    }
1380:                    r.height = bounds.height;
1381:                    r.width = bounds.width; // could be different algorithm
1382:                    return scrollRectToVisibleImpl(r, scrollPolicy, bounds);
1383:                }
1384:
1385:                int newX = bounds.x;
1386:                int newY = bounds.y;
1387:                boolean move = false;
1388:                // now the scroll rect is within bounds of the component
1389:                // and can have size of the extent at maximum
1390:                if (r.x < bounds.x) {
1391:                    move = true;
1392:                    switch (scrollPolicy) {
1393:                    case SCROLL_MOVE:
1394:                        newX = (scrollJumpInsets.left < 0) ? (bounds.width
1395:                                * (-scrollJumpInsets.left) / 100)
1396:                                : scrollJumpInsets.left * defaultSpaceWidth;
1397:                        newX = Math.min(newX, bounds.x + bounds.width
1398:                                - (r.x + r.width));
1399:                        newX = Math.max(r.x - newX, 0); // new bounds.x
1400:                        break;
1401:                    case SCROLL_DEFAULT:
1402:                    case SCROLL_SMALLEST:
1403:                    default:
1404:                        newX = r.x;
1405:                        break;
1406:                    }
1407:                    updateVirtualWidth(newX + bounds.width);
1408:                } else if (r.x + r.width > bounds.x + bounds.width) {
1409:                    move = true;
1410:                    switch (scrollPolicy) {
1411:                    case SCROLL_SMALLEST:
1412:                        newX = r.x + r.width - bounds.width;
1413:                        break;
1414:                    default:
1415:                        newX = (scrollJumpInsets.right < 0) ? (bounds.width
1416:                                * (-scrollJumpInsets.right) / 100)
1417:                                : scrollJumpInsets.right * defaultSpaceWidth;
1418:                        newX = Math.min(newX, bounds.width - r.width);
1419:                        newX = (r.x + r.width) + newX - bounds.width;
1420:                        break;
1421:                    }
1422:                    updateVirtualWidth(newX + bounds.width);
1423:                }
1424:
1425:                if (r.y < bounds.y) {
1426:                    move = true;
1427:                    switch (scrollPolicy) {
1428:                    case SCROLL_MOVE:
1429:                        newY = r.y;
1430:                        newY -= (scrollJumpInsets.top < 0) ? (bounds.height
1431:                                * (-scrollJumpInsets.top) / 100)
1432:                                : scrollJumpInsets.top * lineHeight;
1433:                        break;
1434:                    case SCROLL_SMALLEST:
1435:                        newY = r.y;
1436:                        break;
1437:                    case SCROLL_DEFAULT:
1438:                    default:
1439:                        newY = r.y - (bounds.height - r.height) / 2; // center
1440:                        break;
1441:                    }
1442:                    newY = Math.max(newY, 0);
1443:                } else if (r.y + r.height > bounds.y + bounds.height) {
1444:                    move = true;
1445:                    switch (scrollPolicy) {
1446:                    case SCROLL_MOVE:
1447:                        newY = (r.y + r.height) - bounds.height;
1448:                        newY += (scrollJumpInsets.bottom < 0) ? (bounds.height
1449:                                * (-scrollJumpInsets.bottom) / 100)
1450:                                : scrollJumpInsets.bottom * lineHeight;
1451:                        break;
1452:                    case SCROLL_SMALLEST:
1453:                        newY = (r.y + r.height) - bounds.height;
1454:                        break;
1455:                    case SCROLL_DEFAULT:
1456:                    default:
1457:                        newY = r.y - (bounds.height - r.height) / 2; // center
1458:                        break;
1459:                    }
1460:                    newY = Math.max(newY, 0);
1461:                }
1462:
1463:                if (move) {
1464:                    setExtentPosition(newX, newY);
1465:                }
1466:                return move;
1467:            }
1468:
1469:            void setExtentPosition(int x, int y) {
1470:                JViewport port = getParentViewport();
1471:                if (port != null) {
1472:                    Point p = new Point(Math.max(x, 0), Math.max(y, 0));
1473:                    port.setViewPosition(p);
1474:                }
1475:            }
1476:
1477:            public void adjustWindow(int caretPercentFromWindowTop) {
1478:                final Rectangle bounds = getExtentBounds();
1479:                if (component != null
1480:                        && (component.getCaret() instanceof  Rectangle)) {
1481:                    Rectangle caretRect = (Rectangle) component.getCaret();
1482:                    bounds.y = caretRect.y
1483:                            - (caretPercentFromWindowTop * bounds.height) / 100
1484:                            + (caretPercentFromWindowTop * lineHeight) / 100;
1485:                    Utilities.runInEventDispatchThread(new Runnable() {
1486:                        public void run() {
1487:                            scrollRectToVisible(bounds, SCROLL_SMALLEST);
1488:                        }
1489:                    });
1490:                }
1491:            }
1492:
1493:            /**
1494:             * Set the dot according to the currently visible screen window. #param
1495:             * percentFromWindowTop percentage giving the distance of the caret from the
1496:             * top of the currently visible window.
1497:             */
1498:            public void adjustCaret(int percentFromWindowTop) {
1499:                JTextComponent c = component;
1500:                if (c != null) {
1501:                    Rectangle bounds = getExtentBounds();
1502:                    bounds.y += (percentFromWindowTop * bounds.height) / 100
1503:                            - (percentFromWindowTop * lineHeight) / 100;
1504:                    try {
1505:                        int offset = ((BaseTextUI) c.getUI())
1506:                                .getPosFromY(bounds.y);
1507:                        if (offset >= 0) {
1508:                            caretSetDot(offset, null, SCROLL_SMALLEST);
1509:                        }
1510:                    } catch (BadLocationException e) {
1511:                    }
1512:                }
1513:            }
1514:
1515:            /**
1516:             * Set the position of the caret and scroll the extent if necessary.
1517:             * 
1518:             * @param offset
1519:             *            position where the caret should be placed
1520:             * @param scrollRect
1521:             *            rectangle that should become visible. It can be null when no
1522:             *            scrolling should be done.
1523:             * @param scrollPolicy
1524:             *            policy to be used when scrolling.
1525:             * @deprecated
1526:             */
1527:            public void caretSetDot(int offset, Rectangle scrollRect,
1528:                    int scrollPolicy) {
1529:                if (component != null) {
1530:                    Caret caret = component.getCaret();
1531:                    if (caret instanceof  BaseCaret) {
1532:                        ((BaseCaret) caret).setDot(offset, scrollRect,
1533:                                scrollPolicy);
1534:                    } else {
1535:                        caret.setDot(offset);
1536:                    }
1537:                }
1538:            }
1539:
1540:            /**
1541:             * Set the position of the caret and scroll the extent if necessary.
1542:             * 
1543:             * @param offset
1544:             *            position where the caret should be placed
1545:             * @param scrollRect
1546:             *            rectangle that should become visible. It can be null when no
1547:             *            scrolling should be done.
1548:             * @param scrollPolicy
1549:             *            policy to be used when scrolling.
1550:             * @deprecated
1551:             */
1552:            public void caretMoveDot(int offset, Rectangle scrollRect,
1553:                    int scrollPolicy) {
1554:                if (component != null) {
1555:                    Caret caret = component.getCaret();
1556:                    if (caret instanceof  BaseCaret) {
1557:                        ((BaseCaret) caret).moveDot(offset, scrollRect,
1558:                                scrollPolicy);
1559:                    } else {
1560:                        caret.moveDot(offset);
1561:                    }
1562:                }
1563:            }
1564:
1565:            /**
1566:             * This method is called by textui to do the paint. It is forwarded either
1567:             * to paint through the image and then copy the image area to the screen or
1568:             * to paint directly to this graphics. The real work occurs in draw-engine.
1569:             */
1570:            protected void paint(Graphics g) {
1571:                if (component != null) { // component must be installed
1572:                    if (!fontsInited && g != null) {
1573:                        update(g);
1574:                        getExtentBounds(lastExtentBounds);
1575:                    }
1576:                    ((BaseTextUI) component.getUI()).paintRegion(g);
1577:                }
1578:            }
1579:
1580:            /** Returns the line number margin */
1581:            public Insets getLineNumberMargin() {
1582:                return lineNumberMargin;
1583:            }
1584:
1585:            /** Returns width of the one digit */
1586:            public int getLineNumberDigitWidth() {
1587:                return lineNumberDigitWidth;
1588:            }
1589:
1590:            /** Is glyph gutter created and visible for the document or not */
1591:            public boolean isGlyphGutterVisible() {
1592:                return glyphGutter != null;
1593:            }
1594:
1595:            protected void updateScrollPaneCornerColor() {
1596:                Coloring lineColoring = (Coloring) getColoringMap().get(
1597:                        SettingsNames.LINE_NUMBER_COLORING);
1598:                Coloring defaultColoring = (Coloring) getDefaultColoring();
1599:
1600:                Color backgroundColor;
1601:                if (lineColoring.getBackColor() != null)
1602:                    backgroundColor = lineColoring.getBackColor();
1603:                else
1604:                    backgroundColor = defaultColoring.getBackColor();
1605:
1606:                glyphCorner.setBackground(backgroundColor);
1607:            }
1608:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.