Source Code Cross Referenced for DefaultCaret.java in  » Apache-Harmony-Java-SE » javax-package » javax » swing » text » 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 » Apache Harmony Java SE » javax package » javax.swing.text 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:        /**
0018:         * @author Evgeniya G. Maenkova
0019:         * @version $Revision$
0020:         */package javax.swing.text;
0021:
0022:        import java.awt.Color;
0023:        import java.awt.Component;
0024:        import java.awt.EventQueue;
0025:        import java.awt.Graphics;
0026:        import java.awt.Point;
0027:        import java.awt.Rectangle;
0028:        import java.awt.event.ActionEvent;
0029:        import java.awt.event.ActionListener;
0030:        import java.awt.event.FocusEvent;
0031:        import java.awt.event.FocusListener;
0032:        import java.awt.event.MouseEvent;
0033:        import java.awt.event.MouseListener;
0034:        import java.awt.event.MouseMotionListener;
0035:        import java.beans.PropertyChangeEvent;
0036:        import java.beans.PropertyChangeListener;
0037:        import java.io.IOException;
0038:        import java.io.ObjectInputStream;
0039:        import java.io.ObjectOutputStream;
0040:        import java.util.EventListener;
0041:
0042:        import javax.swing.AbstractAction;
0043:        import javax.swing.SwingConstants;
0044:        import javax.swing.SwingUtilities;
0045:        import javax.swing.Timer;
0046:        import javax.swing.event.ChangeEvent;
0047:        import javax.swing.event.ChangeListener;
0048:        import javax.swing.event.DocumentEvent;
0049:        import javax.swing.event.DocumentListener;
0050:        import javax.swing.event.EventListenerList;
0051:        import javax.swing.text.Position.Bias;
0052:
0053:        import org.apache.harmony.awt.text.AWTTextAction;
0054:        import org.apache.harmony.awt.text.ActionNames;
0055:        import org.apache.harmony.awt.text.ActionSet;
0056:        import org.apache.harmony.awt.text.TextKit;
0057:        import org.apache.harmony.awt.text.TextUtils;
0058:        import org.apache.harmony.x.swing.StringConstants;
0059:
0060:        import org.apache.harmony.x.swing.internal.nls.Messages;
0061:
0062:        public class DefaultCaret extends Rectangle implements  Caret,
0063:                FocusListener, MouseListener, MouseMotionListener {
0064:
0065:            public static final int ALWAYS_UPDATE = 2;
0066:
0067:            public static final int NEVER_UPDATE = 1;
0068:
0069:            public static final int UPDATE_WHEN_ON_EDT = 0;
0070:
0071:            protected EventListenerList listenerList = new EventListenerList();
0072:
0073:            protected transient ChangeEvent changeEvent = new ChangeEvent(this );
0074:
0075:            private int mark;
0076:
0077:            private int dot;
0078:
0079:            private transient Position.Bias dotBias = Position.Bias.Forward;
0080:
0081:            private transient Position.Bias markBias = Position.Bias.Forward;
0082:
0083:            private boolean async;
0084:
0085:            //Position in document to follow the adjucent caret position
0086:            //on document updates. Help to get new bias (dot) after
0087:            //document updates.
0088:            private int dotTrack;
0089:
0090:            //current policy (for 1.5.0 sets by setUpdatePolicy)
0091:            private int selectedPolicy = UPDATE_WHEN_ON_EDT;
0092:
0093:            private int blinkRate;
0094:
0095:            //installed text component
0096:            private Component component;
0097:
0098:            TextKit textKit;
0099:
0100:            //current selection color
0101:            private Color selectionColor;
0102:
0103:            //current caret color
0104:            private Color caretColor;
0105:
0106:            //value selectionColor in case of JTextComponent.getSelectionColor()
0107:            //equals null
0108:            private static final Color DEF_SEL_COLOR = new Color(192, 224, 255);
0109:
0110:            //value selectionColor in case of JTextComponent.getCaretColor()
0111:            //equals null
0112:            private static final Color DEF_CARET_COLOR = new Color(0, 0, 0);
0113:
0114:            //delay for magicTimer
0115:            static final int DEFAULT_MAGIC_DELAY = 600;
0116:
0117:            private static final int APEX_NUMBER = 3;
0118:
0119:            private static final int TRIANGLE_HEIGHT = 4;
0120:
0121:            private static final int RIGHT_TRIANGLE_WIDTH = 5;
0122:
0123:            private static final int LEFT_TRIANGLE_WIDTH = 4;
0124:
0125:            //current painter for selection
0126:            private transient DefaultHighlighter.DefaultHighlightPainter painter;
0127:
0128:            //reference to current selection, if any
0129:            private transient Object selectionTag;
0130:
0131:            //DocumentListener for document of current JTextComponent
0132:            private transient DocumentListener dh = new DocumentHandler();
0133:
0134:            //PropertyChangeListener for current JTextComponent
0135:            private transient PropertyHandler pch;
0136:
0137:            //used by mouseClicked method
0138:            private static final transient AWTTextAction SELECT_WORD_ACTION = ActionSet.actionMap
0139:                    .get(ActionNames.selectWordAction);
0140:
0141:            //used by mouseClicked method
0142:            private static final transient AWTTextAction SELECT_LINE_ACTION = ActionSet.actionMap
0143:                    .get(ActionNames.selectLineAction);
0144:
0145:            Point magicCaretPosition;
0146:
0147:            private transient boolean isVisible;
0148:
0149:            private boolean isSelectionVisible;
0150:
0151:            //Timer to repaint caret according to current blinkRate
0152:            transient Object blinkTimer;
0153:
0154:            //Timer to set magicCaretPosition to current caret position
0155:            transient Object magicTimer;
0156:
0157:            //defines whether caret be painting or blinking, if blink on
0158:            transient boolean shouldDraw = true;
0159:
0160:            //defines x coordinates of flag, in case of bidirectional text
0161:            private transient int[] triangleX = new int[APEX_NUMBER];
0162:
0163:            //defines y coordinates of flag, in case of bidirectional text
0164:            private transient int[] triangleY = new int[APEX_NUMBER];
0165:
0166:            //used for modelToView calls
0167:            private transient Position.Bias[] bias = new Position.Bias[1];
0168:
0169:            //for DnD support, selection doesn't change when drag
0170:            private boolean handleMouseDrag = true;
0171:
0172:            //flag to restore selection
0173:            private boolean restoreSelection;
0174:
0175:            //used when JTextComponent has NavigationFilter
0176:            private transient FilterBypass filterBypass = new FilterBypass(this );
0177:
0178:            private transient NavigationFilter navigationFilter;
0179:
0180:            private Highlighter highlighter;
0181:
0182:            private Document document;
0183:
0184:            private boolean isBidiDocument;
0185:
0186:            //This variable remembers last coordinates, where mouse button
0187:            //was pressed. Handling MouseEvent in MouseClicked method depends
0188:            //on this.
0189:            private int[] lastPressPoint = new int[2];
0190:
0191:            //action for blinkTimer
0192:            Object blinkAction;
0193:
0194:            //Action for magic timer. If MagicCaretPosition still null,
0195:            //MagicCaretPosition set to current caret position, else do nothing.
0196:            Object magicAction;
0197:
0198:            private class PropertyHandler implements  PropertyChangeListener {
0199:                public void propertyChange(final PropertyChangeEvent evt) {
0200:                    String proptertyName = evt.getPropertyName();
0201:                    Object newValue = evt.getNewValue();
0202:                    if (StringConstants.TEXT_COMPONENT_DOCUMENT_PROPERTY
0203:                            .equals(proptertyName)) {
0204:                        Document oldDoc = (Document) evt.getOldValue();
0205:                        document = textKit.getDocument();
0206:                        if (oldDoc != null) {
0207:                            oldDoc.removeDocumentListener(dh);
0208:                        }
0209:                        if (document != null) {
0210:                            updateBidiInfo();
0211:                            document.addDocumentListener(dh);
0212:                            setDot(0);
0213:                        }
0214:                    } else if (StringConstants.TEXT_COMPONENT_CARET_COLOR_PROPERTY
0215:                            .equals(proptertyName)) {
0216:                        caretColor = (Color) newValue;
0217:                    } else if (StringConstants.TEXT_COMPONENT_SELECTION_COLOR_PROPERTY
0218:                            .equals(proptertyName)) {
0219:                        selectionColor = (Color) newValue;
0220:                        painter = new DefaultHighlighter.DefaultHighlightPainter(
0221:                                selectionColor);
0222:                    } else if (StringConstants.TEXT_COMPONENT_HIGHLIGHTER_PROPERTY
0223:                            .equals(proptertyName)) {
0224:                        highlighter = (Highlighter) newValue;
0225:                    } else if (StringConstants.TEXT_COMPONENT_NAV_FILTER_NAME
0226:                            .equals(proptertyName)) {
0227:                        navigationFilter = (NavigationFilter) newValue;
0228:                    }
0229:                }
0230:            }
0231:
0232:            //DocumentListener, to change dot, dotBias, mark, current selection on
0233:            // document updates
0234:            //according to AsynchronousMovement property.
0235:            //Don't repaint caret, JText component do painting on document updates.
0236:            private class DocumentHandler implements  DocumentListener {
0237:
0238:                /*
0239:                 * Returns position after string removing (length - length of string,
0240:                 * offset position where string is removed). Pos - position, which
0241:                 * should new position be defined for
0242:                 */
0243:                private int newPosOnRemove(final int pos, final int length,
0244:                        final int offset) {
0245:                    int endUpdate = offset + length;
0246:                    if ((pos > offset) && (endUpdate <= pos)) {
0247:                        return pos - length;
0248:                    }
0249:                    if ((pos > offset) && (endUpdate > pos)) {
0250:                        return offset;
0251:                    }
0252:                    return pos;
0253:                }
0254:
0255:                /*
0256:                 * Returns position after string inserting (length - length of string,
0257:                 * offset position where string is added). Pos - position, which
0258:                 * should new position be defined for
0259:                 */
0260:                private int newPosOnInsert(final int pos, final int length,
0261:                        final int offset) {
0262:                    if (offset <= pos) {
0263:                        return pos + length;
0264:                    }
0265:                    return pos;
0266:                }
0267:
0268:                /**
0269:                 * Caret position don't change on changeUpdate of Document
0270:                 */
0271:                public void changedUpdate(final DocumentEvent e) {
0272:
0273:                }
0274:
0275:                public synchronized void removeUpdate(final DocumentEvent e) {
0276:                    final int docLength = document.getLength();
0277:                    final boolean condOnNeverUpdate = (docLength <= Math.max(
0278:                            dot, mark));
0279:                    final boolean isNeverUpdate = (selectedPolicy == NEVER_UPDATE);
0280:                    final boolean isUpdateWhenOnEdt = (selectedPolicy == UPDATE_WHEN_ON_EDT);
0281:                    final boolean isUpdateWhenOnEdtAndAsync = (isUpdateWhenOnEdt && !EventQueue
0282:                            .isDispatchThread());
0283:                    if ((isNeverUpdate || isUpdateWhenOnEdtAndAsync)
0284:                            && !condOnNeverUpdate) {
0285:                        return;
0286:                    }
0287:
0288:                    removeUpdate(e, isNeverUpdate || isUpdateWhenOnEdtAndAsync,
0289:                            docLength);
0290:                }
0291:
0292:                private void removeUpdate(final DocumentEvent e,
0293:                        final boolean trivialUpdate, final int docLength) {
0294:                    int length = e.getLength();
0295:                    int offset = e.getOffset();
0296:                    int newMark;
0297:                    int newDot;
0298:                    Position.Bias newBias;
0299:
0300:                    if (trivialUpdate) {
0301:                        newMark = Math.min(mark, docLength);
0302:                        newDot = Math.min(dot, docLength);
0303:                        newBias = dotBias;
0304:                    } else {
0305:                        newMark = newPosOnRemove(mark, length, offset);
0306:                        dotTrack = newPosOnRemove(dotTrack, length, offset);
0307:                        newDot = newPosOnRemove(dot, length, offset);
0308:                        newBias = getNewBias(dotTrack, newDot);
0309:                    }
0310:
0311:                    mark = newMark;
0312:                    moveDot(newDot, newBias);
0313:                    if (dot == mark) {
0314:                        markBias = dotBias;
0315:                    }
0316:                }
0317:
0318:                public synchronized void insertUpdate(final DocumentEvent e) {
0319:                    if ((selectedPolicy == NEVER_UPDATE)
0320:                            || ((selectedPolicy == UPDATE_WHEN_ON_EDT) && !EventQueue
0321:                                    .isDispatchThread())) {
0322:                        return;
0323:                    }
0324:
0325:                    int length = e.getLength();
0326:                    int offset = e.getOffset();
0327:                    String s = null;
0328:                    try {
0329:                        s = document.getText(offset, 1);
0330:                    } catch (final BadLocationException ex) {
0331:                    }
0332:
0333:                    if (offset == dot
0334:                            && (length + offset) != document.getLength()) {
0335:                        dotBias = Position.Bias.Backward;
0336:                    }
0337:
0338:                    if (s.equals("\n")) {
0339:                        dotBias = Position.Bias.Forward;
0340:                    }
0341:
0342:                    mark = newPosOnInsert(mark, length, offset);
0343:                    moveDot(newPosOnInsert(dot, length, offset), dotBias);
0344:                    if (dot == mark) {
0345:                        markBias = dotBias;
0346:                    }
0347:                    updateBidiInfo();
0348:                }
0349:
0350:            }
0351:
0352:            /**
0353:             * Default Implementation if NavigationFilter.FilterBypass. Used in setDot()
0354:             * and moveDot(), when component.getNavigationFilter doesn't equal null.
0355:             */
0356:            private class FilterBypass extends NavigationFilter.FilterBypass {
0357:                DefaultCaret caret;
0358:
0359:                FilterBypass(final DefaultCaret dc) {
0360:                    caret = dc;
0361:                }
0362:
0363:                @Override
0364:                public Caret getCaret() {
0365:                    return caret;
0366:                }
0367:
0368:                @Override
0369:                public void setDot(final int i, final Bias b) {
0370:                    caret.internalSetDot(i, b);
0371:                }
0372:
0373:                @Override
0374:                public void moveDot(final int i, final Bias b) {
0375:                    caret.internalMoveDot(i, b);
0376:                }
0377:
0378:            }
0379:
0380:            /**
0381:             * Sets all fiels to default values
0382:             */
0383:            public DefaultCaret() {
0384:                blinkTimer = createTimer(false, 0);
0385:                magicTimer = createTimer(true, 0);
0386:                painter = new DefaultHighlighter.DefaultHighlightPainter(
0387:                        selectionColor);
0388:            }
0389:
0390:            public void addChangeListener(final ChangeListener changeListener) {
0391:                if (changeListener != null) {
0392:                    listenerList.add(ChangeListener.class, changeListener);
0393:                }
0394:            }
0395:
0396:            /**
0397:             * Adds selection according to current dot and mark, if isSelectionVisible
0398:             * equals true.
0399:             *
0400:             */
0401:            private void addHighlight() {
0402:                if (mark == dot) {
0403:                    return;
0404:                }
0405:                if (!isSelectionVisible) {
0406:                    restoreSelection = true;
0407:                    removeHighlight();
0408:                    return;
0409:                }
0410:
0411:                if (selectionTag == null) {
0412:                    selectionTag = addHighlight(Math.min(dot, mark), Math.max(
0413:                            dot, mark));
0414:                }
0415:            }
0416:
0417:            protected void adjustVisibility(final Rectangle r) {
0418:                if (r != null) {
0419:                    textKit.scrollRectToVisible(new Rectangle(r.x, r.y,
0420:                            r.width + 1, r.height));
0421:                }
0422:            }
0423:
0424:            /**
0425:             * Repaint caret according to current dot and dotBias.
0426:             *
0427:             */
0428:            private void calcNewPos() {
0429:                Rectangle p = null;
0430:                try {
0431:                    p = textKit.modelToView(dot, dotBias);
0432:                } catch (final BadLocationException e) {
0433:                }
0434:                if (p == null) {
0435:                    return;
0436:                }
0437:                damage(p);
0438:            }
0439:
0440:            /**
0441:             * Sets dot to new position i, repaint caret, sets magic caret position to
0442:             * null. Calls fireStateChanged.
0443:             *
0444:             * @param i new dot
0445:             */
0446:            private void changeDot(final int i) {
0447:                dot = i;
0448:                magicCaretPosition = null;
0449:                shouldDraw = true;
0450:                dotTrack = changePosTrack(dot, dotBias);
0451:                calcNewPos();
0452:                fireStateChanged();
0453:            }
0454:
0455:            /**
0456:             * Changes current selection, if any. Removes current selection, if dot
0457:             * equals mark.
0458:             */
0459:            private void changeHighlight() {
0460:                if (dot == mark) {
0461:                    if (selectionTag != null) {
0462:                        removeHighlight();
0463:                    }
0464:                } else {
0465:                    if (selectionTag == null) {
0466:                        addHighlight();
0467:                    } else {
0468:                        changeHighlight(selectionTag, Math.min(dot, mark), Math
0469:                                .max(dot, mark));
0470:                    }
0471:                }
0472:            }
0473:
0474:            /*
0475:             * Calculate new adjacent position value according to pos and bias.
0476:             *
0477:             * @param newPos offset, which should new adjucent position be defined for
0478:             * @param newBias bias of pos
0479:             * @return new adjucent position
0480:             */
0481:            private int changePosTrack(final int newPos,
0482:                    final Position.Bias newBias) {
0483:                if (newBias == Position.Bias.Forward) {
0484:                    return newPos + 1;
0485:                } else {
0486:                    return newPos;
0487:                }
0488:            }
0489:
0490:            protected synchronized void damage(final Rectangle r) {
0491:                repaint();
0492:                if (r == null) {
0493:                    return;
0494:                }
0495:                x = r.x;
0496:                y = r.y;
0497:                width = 0;
0498:                height = r.height - 2;
0499:                adjustVisibility(r);
0500:                repaint();
0501:            }
0502:
0503:            /**
0504:             * Stops timer for blinking.
0505:             *
0506:             */
0507:            public void deinstall(final JTextComponent comp) {
0508:                if (component == null || comp != component) {
0509:                    return;
0510:                }
0511:                if (document != null) {
0512:                    document.removeDocumentListener(dh);
0513:                }
0514:                component.removePropertyChangeListener(pch);
0515:                component.removeMouseListener(this );
0516:                component.removeMouseMotionListener(this );
0517:                component.removeFocusListener(this );
0518:                stopTimer(blinkTimer);
0519:                stopTimer(magicTimer);
0520:                highlighter = null;
0521:                component = null;
0522:                textKit = null;
0523:            }
0524:
0525:            @Override
0526:            public boolean equals(final Object obj) {
0527:                return this  == obj;
0528:            }
0529:
0530:            protected void fireStateChanged() {
0531:                if (isVisible) {
0532:                    TextUtils.setNativeCaretPosition(this , component);
0533:                }
0534:                Object[] listeners = listenerList.getListenerList();
0535:                for (int i = listeners.length - 2; i >= 0; i -= 2) {
0536:                    if (listeners[i] == ChangeListener.class) {
0537:                        if (changeEvent == null) {
0538:                            changeEvent = new ChangeEvent(this );
0539:                        }
0540:                        ((ChangeListener) listeners[i + 1])
0541:                                .stateChanged(changeEvent);
0542:                    }
0543:                }
0544:            }
0545:
0546:            /**
0547:             * Sets isSelectionVisible to true
0548:             *
0549:             */
0550:            public void focusGained(final FocusEvent fe) {
0551:                isSelectionVisible = true;
0552:                if (restoreSelection) {
0553:                    addHighlight();
0554:                    restoreSelection = false;
0555:                }
0556:                if (isComponentEditable()) {
0557:                    setVisible(true);
0558:                    repaint();
0559:                } else {
0560:                    setVisible(false);
0561:                }
0562:            }
0563:
0564:            /**
0565:             * Sets isSelectionVisible to true
0566:             *
0567:             */
0568:            public void focusLost(final FocusEvent fe) {
0569:                setVisible(false);
0570:                isSelectionVisible = true;
0571:                Component c = fe.getOppositeComponent();
0572:                if (c != null && !fe.isTemporary()
0573:                        && isRestoreSelectionCondition(c)) {
0574:                    restoreSelection = true;
0575:                    removeHighlight();
0576:                }
0577:                repaint();
0578:            }
0579:
0580:            private boolean getAsynchronousMovement() {
0581:                return async;
0582:            }
0583:
0584:            public int getBlinkRate() {
0585:                return blinkRate;
0586:            }
0587:
0588:            public ChangeListener[] getChangeListeners() {
0589:                return listenerList.getListeners(ChangeListener.class);
0590:
0591:            }
0592:
0593:            protected final JTextComponent getComponent() {
0594:                return component instanceof  JTextComponent ? (JTextComponent) component
0595:                        : null;
0596:            }
0597:
0598:            /*
0599:             * Defines flag direction, to paint caret in case of bidirectional text
0600:             *
0601:             * @return true - if flag in the left direction, false - if flag in the
0602:             *         right direction
0603:             */
0604:            private boolean getDirection() {
0605:                AbstractDocument ad = ((AbstractDocument) document);
0606:                int length = ad.getLength();
0607:
0608:                boolean currentDirection = (dot >= 1) ? ad
0609:                        .isLeftToRight(dot - 1) : false;
0610:                boolean nextDirection = (dot <= length) ? ad.isLeftToRight(dot)
0611:                        : true;
0612:
0613:                if (currentDirection == nextDirection) {
0614:                    return (currentDirection) ? false : true;
0615:                }
0616:                if (currentDirection) {
0617:                    return (dotBias == Position.Bias.Backward) ? false : true;
0618:                } else {
0619:                    return (dotBias == Position.Bias.Backward) ? true : false;
0620:                }
0621:            }
0622:
0623:            public int getDot() {
0624:                return dot;
0625:            }
0626:
0627:            /**
0628:             * Returns current dot bias
0629:             *
0630:             * @return dotBias dot bias
0631:             */
0632:            Position.Bias getDotBias() {
0633:                return dotBias;
0634:            }
0635:
0636:            public <T extends EventListener> T[] getListeners(final Class<T> c) {
0637:                T[] evL = null;
0638:                try {
0639:                    evL = listenerList.getListeners(c);
0640:                } catch (final ClassCastException e) {
0641:                    throw e;
0642:                }
0643:                return evL;
0644:            }
0645:
0646:            public Point getMagicCaretPosition() {
0647:                return magicCaretPosition;
0648:                //return stubMagicCaretPosition;
0649:            }
0650:
0651:            public int getMark() {
0652:                return mark;
0653:            }
0654:
0655:            /**
0656:             * Get new bias for current position and its adjucent position
0657:             *
0658:             * @param posTrack adjucent position
0659:             * @param pos current position
0660:             * @return bias
0661:             */
0662:            private Position.Bias getNewBias(final int posTrack, final int pos) {
0663:                return (posTrack == pos) ? Position.Bias.Backward
0664:                        : Position.Bias.Forward;
0665:            }
0666:
0667:            protected Highlighter.HighlightPainter getSelectionPainter() {
0668:                return painter;
0669:            }
0670:
0671:            public int getUpdatePolicy() {
0672:                return selectedPolicy;
0673:            }
0674:
0675:            /**
0676:             * Adds listeners to c, if c doesn't equal null.
0677:             * Adds DocumentListener to
0678:             * c, if c doesn't equals null. Sets textUI, caretColor, selectionColor to
0679:             * value from c, if they don't equal null. Sets new painter according to
0680:             * selectionColor.
0681:             */
0682:            public void install(final JTextComponent c) {
0683:                setComponent(c);
0684:
0685:                component.addMouseListener(this );
0686:                component.addMouseMotionListener(this );
0687:                component.addFocusListener(this );
0688:                component.addPropertyChangeListener(getPropertyHandler());
0689:                highlighter = c.getHighlighter();
0690:                navigationFilter = c.getNavigationFilter();
0691:                painter = new DefaultHighlighter.DefaultHighlightPainter(
0692:                        selectionColor);
0693:            }
0694:
0695:            void setComponent(final Component c) {
0696:                component = c;
0697:                textKit = TextUtils.getTextKit(component);
0698:                document = textKit.getDocument();
0699:                updateBidiInfo();
0700:                if (document != null) {
0701:                    document.addDocumentListener(dh);
0702:                }
0703:                selectionColor = getSelectionColor();
0704:                caretColor = getCaretColor();
0705:            }
0706:
0707:            public boolean isActive() {
0708:                //return shouldDraw;
0709:                return isVisible;
0710:            }
0711:
0712:            public boolean isSelectionVisible() {
0713:                return isSelectionVisible;
0714:            }
0715:
0716:            public boolean isVisible() {
0717:                return isVisible;
0718:            }
0719:
0720:            //MouseClicked is called if mouse button was released farther
0721:            //than 5 pixels (from place, where mouse button was pressed).
0722:            //Sometimes, it is not enough. For example, when width of
0723:            //a letter is smaller than 5 pixels.
0724:            //So it's necessarily to filter these mouse events.
0725:
0726:            private boolean needClick(final MouseEvent e) {
0727:                return selectionTag == null
0728:                        || (Math.abs(e.getX() - lastPressPoint[0]) > 1 && Math
0729:                                .abs(e.getY() - lastPressPoint[1]) > 1);
0730:
0731:            }
0732:
0733:            public void mouseClicked(final MouseEvent me) {
0734:                if (!needClick(me)) {
0735:                    return;
0736:                }
0737:                int clickCount = me.getClickCount();
0738:                if (me.getButton() == MouseEvent.BUTTON1) {
0739:                    if (clickCount == 1) {
0740:                        positionCaret(me);
0741:                    }
0742:                    if (clickCount == 2) {
0743:                        SELECT_WORD_ACTION.performAction(textKit);
0744:                    }
0745:                    if (clickCount == 3) {
0746:                        SELECT_LINE_ACTION.performAction(textKit);
0747:                    }
0748:                }
0749:            }
0750:
0751:            /**
0752:             * Calculates offset, which correspond MouseEvent. If DragAndDropCondition
0753:             * return false, moveDot is called.
0754:             */
0755:            public void mouseDragged(final MouseEvent me) {
0756:
0757:                int offset = textKit.viewToModel(
0758:                        new Point(me.getX(), me.getY()), bias);
0759:                if (offset < 0) {
0760:                    return;
0761:                }
0762:                int mask = MouseEvent.BUTTON1_DOWN_MASK;
0763:                if ((me.getModifiersEx() & mask) != mask) {
0764:                    return;
0765:                }
0766:                if (handleMouseDrag) { //(! DragAndDropCondition(offset))
0767:                    moveDot(offset, bias[0]);
0768:                }
0769:            }
0770:
0771:            /**
0772:             * If component.getDragEnabled() returns true and offset in selection,
0773:             * return true. Otherwise, returns false.
0774:             */
0775:            private boolean isDragAndDropCondition(final int offset) {
0776:                return isDragEnabled() ? (offset >= Math.min(dot, mark) && offset <= Math
0777:                        .max(dot, mark))
0778:                        : false;
0779:            }
0780:
0781:            public void mouseEntered(final MouseEvent me) {
0782:            }
0783:
0784:            public void mouseExited(final MouseEvent me) {
0785:            }
0786:
0787:            public void mouseMoved(final MouseEvent me) {
0788:            }
0789:
0790:            /**
0791:             * Calculates offset, which corresponds to MouseEvent. If shift-button isn't
0792:             * pressed, DragAndDropCondition return false, then setDot is called.
0793:             */
0794:            public void mousePressed(final MouseEvent me) {
0795:                int offset;
0796:                int mask = MouseEvent.SHIFT_DOWN_MASK;
0797:                if (me.getButton() != MouseEvent.BUTTON1
0798:                        || !component.isEnabled()) {
0799:                    return;
0800:                }
0801:                component.requestFocusInWindow();
0802:                offset = textKit.viewToModel(new Point(me.getX(), me.getY()),
0803:                        bias);
0804:                if (offset < 0) {
0805:                    return;
0806:                }
0807:                rememberPressPoint(me);
0808:                if ((me.getModifiersEx() & mask) == mask) {
0809:                    moveDot(offset, bias[0]);
0810:                } else {
0811:                    boolean condition = isDragAndDropCondition(offset);
0812:                    if (!condition) {
0813:                        setDot(offset, bias[0]);
0814:                    }
0815:                    handleMouseDrag = !(condition && dot != mark);
0816:                }
0817:
0818:            }
0819:
0820:            private void rememberPressPoint(final MouseEvent e) {
0821:                lastPressPoint[0] = e.getX();
0822:                lastPressPoint[1] = e.getY();
0823:            }
0824:
0825:            public void mouseReleased(final MouseEvent me) {
0826:
0827:            }
0828:
0829:            protected void moveCaret(final MouseEvent me) {
0830:                int offset = textKit.viewToModel(
0831:                        new Point(me.getX(), me.getY()), bias);
0832:                if (offset >= 0) {
0833:                    moveDot(offset);
0834:                }
0835:            }
0836:
0837:            /**
0838:             * Calls changeDot, don't change mark. Adds or changes highlight, it depends
0839:             * on current dot and mark
0840:             *
0841:             */
0842:            public void moveDot(final int i) {
0843:                moveDot(i, Position.Bias.Forward);
0844:            }
0845:
0846:            /**
0847:             * If current JTextComponent has NavigationFilter then call
0848:             * getComponent.getNavigationFilter.moveDot. Otherwise, calls changeDot,
0849:             * don't change mark. Sets new dot, new dotBias. Adds or changes highlight,
0850:             * it dependes on current dot and mark
0851:             *
0852:             * @param i new dot
0853:             * @param b new dot bias
0854:             */
0855:
0856:            void moveDot(final int i, final Position.Bias b) {
0857:                if (navigationFilter == null) {
0858:                    internalMoveDot(i, b);
0859:                } else {
0860:                    navigationFilter.moveDot(filterBypass, i, b);
0861:                }
0862:            }
0863:
0864:            private void internalMoveDot(final int i, final Position.Bias b) {
0865:                dotBias = b;
0866:                changeDot(i);
0867:                changeHighlight();
0868:            }
0869:
0870:            public void paint(final Graphics g) {
0871:                try {
0872:                    if (!isVisible || !shouldDraw) {
0873:                        return;
0874:                    }
0875:                    Rectangle p = textKit.modelToView(dot, dotBias);
0876:                    if (p == null) {
0877:                        return;
0878:                    }
0879:                    this .setBounds(p.x, p.y, 0, p.height - 2);
0880:                    g.setColor(caretColor);
0881:                    g.drawRect(x, y, width, height);
0882:
0883:                    if (isBidiDocument) {
0884:                        triangleX[0] = x;
0885:                        triangleX[1] = x;
0886:                        triangleX[2] = getDirection() ? (x - LEFT_TRIANGLE_WIDTH)
0887:                                : (x + RIGHT_TRIANGLE_WIDTH);
0888:                        triangleY[0] = y;
0889:                        triangleY[1] = y + TRIANGLE_HEIGHT;
0890:                        triangleY[2] = y;
0891:                        g.fillPolygon(triangleX, triangleY, APEX_NUMBER);
0892:                    }
0893:                } catch (BadLocationException e) {
0894:
0895:                }
0896:            }
0897:
0898:            protected void positionCaret(final MouseEvent me) {
0899:                int offset = textKit.viewToModel(
0900:                        new Point(me.getX(), me.getY()), bias);
0901:                if (offset >= 0) {
0902:                    setDot(offset, bias[0]);
0903:                }
0904:            }
0905:
0906:            /**
0907:             * Reads object by default, reads string representation dotBias, markBias,
0908:             * sets dotBias, markBias. Sets blinkTimer, magicTimer, textUI, dh, pch,
0909:             * selectWord, selectLine, triangleX, triangleY, bias.
0910:             *
0911:             * @param s
0912:             * @throws IOException
0913:             * @throws ClassNotFoundException
0914:             */
0915:            private void readObject(final ObjectInputStream s)
0916:                    throws IOException, ClassNotFoundException {
0917:
0918:                s.defaultReadObject();
0919:                String forwardString = Position.Bias.Forward.toString();
0920:                dotBias = (forwardString.equals(s.readUTF())) ? Position.Bias.Forward
0921:                        : Position.Bias.Backward;
0922:
0923:                markBias = (forwardString.equals(s.readUTF())) ? Position.Bias.Forward
0924:                        : Position.Bias.Backward;
0925:                painter = new DefaultHighlighter.DefaultHighlightPainter(
0926:                        selectionColor);
0927:
0928:                dh = new DocumentHandler();
0929:                pch = new PropertyHandler();
0930:
0931:                if (component != null) {
0932:                    component.addPropertyChangeListener(pch);
0933:                    if (textKit.getDocument() != null) {
0934:                        textKit.getDocument().addDocumentListener(dh);
0935:                    }
0936:                }
0937:
0938:                blinkTimer = createTimer(false, 0);
0939:                magicTimer = createTimer(true, 0);
0940:
0941:                triangleX = new int[APEX_NUMBER];
0942:                triangleY = new int[APEX_NUMBER];
0943:
0944:                bias = new Position.Bias[1];
0945:            }
0946:
0947:            public void removeChangeListener(final ChangeListener chL) {
0948:                listenerList.remove(ChangeListener.class, chL);
0949:            }
0950:
0951:            /**
0952:             * Removes current selection, selectionTag doesn't equal null. Sets
0953:             * selectionTag to null.
0954:             */
0955:            private void removeHighlight() {
0956:                if (selectionTag == null) {
0957:                    return;
0958:                }
0959:                removeHighlight(selectionTag);
0960:                selectionTag = null;
0961:            }
0962:
0963:            protected final synchronized void repaint() {
0964:                if (component != null) {
0965:                    if (!isBidiDocument) {
0966:                        //Commented since current 2d implementation cannot properly repaint region
0967:                        // of 1 pixel width.
0968:                        //component.repaint(0, x, y, width + 1, height + 1);
0969:                        component.repaint(0, x - 2, y, width + 4, height + 1);
0970:                    } else {
0971:                        component.repaint(0, x - 5, y, width + 10, height + 1);
0972:                    }
0973:                }
0974:            }
0975:
0976:            final void setAsynchronousMovement(final boolean b) {
0977:                async = b;
0978:                int i = (b) ? DefaultCaret.ALWAYS_UPDATE
0979:                        : DefaultCaret.UPDATE_WHEN_ON_EDT;
0980:                setUpdatePolicy(i);
0981:            }
0982:
0983:            /**
0984:             * Restarts timer for blinking, if blink on
0985:             *
0986:             */
0987:            public void setBlinkRate(final int i) {
0988:                if (i < 0) {
0989:                    throw new IllegalArgumentException(Messages.getString(
0990:                            "swing.64", i)); //$NON-NLS-1$
0991:                }
0992:                blinkRate = i;
0993:                stopTimer(blinkTimer);
0994:                if (blinkRate > 0) {
0995:                    setTimerDelay(blinkTimer, blinkRate);
0996:                    if (isVisible) {
0997:                        startTimer(blinkTimer);
0998:                    }
0999:                }
1000:            }
1001:
1002:            public void setDot(final int i) {
1003:                setDot(i, Position.Bias.Forward);
1004:                return;
1005:            }
1006:
1007:            /**
1008:             * If current JTextComponent has NavigationFilter then call
1009:             * getComponent.getNavigationFilter.setDot. Otherwise, sets dot and mark to
1010:             * i, sets dotBias and markBias to b. Removes highlight, if any.
1011:             *
1012:             * @param i new dot
1013:             * @param b new dotBias
1014:             */
1015:
1016:            void setDot(final int i, final Position.Bias b) {
1017:                if (navigationFilter == null) {
1018:                    internalSetDot(i, b);
1019:                } else {
1020:                    navigationFilter.setDot(filterBypass, i, b);
1021:                }
1022:            }
1023:
1024:            private void internalSetDot(final int i, final Position.Bias b) {
1025:                dotBias = b;
1026:                markBias = b;
1027:                mark = i;
1028:                changeDot(i);
1029:                removeHighlight();
1030:            }
1031:
1032:            public void setMagicCaretPosition(final Point p) {
1033:                magicCaretPosition = p;
1034:                //stubMagicCaretPosition = p;
1035:            }
1036:
1037:            public void setSelectionVisible(final boolean b) {
1038:                isSelectionVisible = b;
1039:                if (b) {
1040:                    addHighlight();
1041:                    restoreSelection = false;
1042:                } else {
1043:                    restoreSelection = true;
1044:                    removeHighlight();
1045:                }
1046:            }
1047:
1048:            public void setUpdatePolicy(final int policy) {
1049:                if (policy >= 0 && policy <= 2) {
1050:                    selectedPolicy = policy;
1051:                } else {
1052:                    throw new IllegalArgumentException();
1053:                }
1054:            }
1055:
1056:            public void setVisible(final boolean b) {
1057:                isVisible = b;
1058:                if (b) {
1059:                    startTimer(magicTimer);
1060:                    if (blinkRate > 0) {
1061:                        startTimer(blinkTimer);
1062:                    }
1063:                } else {
1064:                    stopTimer(blinkTimer);
1065:                    stopTimer(magicTimer);
1066:                }
1067:            }
1068:
1069:            /*
1070:             * The format of the string is based on 1.5 release behavior
1071:             * of BasicTextUI.BasicCaret class which can be revealed
1072:             * using the following code:
1073:             *
1074:             *     JTextArea textArea = new JTextArea();
1075:             *     System.out.println(textArea.getCaret());
1076:             *     System.out.println(textArea.getCaret().getClass().getName());
1077:             */
1078:            @Override
1079:            public String toString() {
1080:                return "Dot=(" + dot + ", " + dotBias.toString() + ") "
1081:                        + "Mark=(" + mark + ", " + markBias.toString() + ")";
1082:            }
1083:
1084:            private void updateBidiInfo() {
1085:                isBidiDocument = TextUtils.isBidirectional(document);
1086:            }
1087:
1088:            /**
1089:             * Writes object bu default, writes string representation dotBias, markBias
1090:             *
1091:             * @param s
1092:             * @throws IOException
1093:             */
1094:            private void writeObject(final ObjectOutputStream s)
1095:                    throws IOException {
1096:                s.defaultWriteObject();
1097:                s.writeUTF(dotBias.toString());
1098:                s.writeUTF(markBias.toString());
1099:            }
1100:
1101:            private PropertyChangeListener getPropertyHandler() {
1102:                if (pch == null) {
1103:                    pch = new PropertyHandler();
1104:                }
1105:                return pch;
1106:            }
1107:
1108:            Object createTimer(final boolean isMagicTimer, final int delay) {
1109:                return isMagicTimer ? new javax.swing.Timer(
1110:                        DEFAULT_MAGIC_DELAY, (ActionListener) getMagicAction())
1111:                        : new javax.swing.Timer(delay,
1112:                                (ActionListener) getBlinkAction());
1113:            }
1114:
1115:            void startTimer(final Object timer) {
1116:                ((Timer) timer).start();
1117:            }
1118:
1119:            void setTimerDelay(final Object timer, final int delay) {
1120:                ((Timer) timer).setDelay(delay);
1121:            }
1122:
1123:            void stopTimer(final Object timer) {
1124:                ((javax.swing.Timer) timer).stop();
1125:            }
1126:
1127:            Object getMagicAction() {
1128:                if (magicAction == null) {
1129:                    magicAction = new AbstractAction() {
1130:                        public void actionPerformed(final ActionEvent e) {
1131:                            if (magicCaretPosition == null) {
1132:                                magicCaretPosition = new Point(x, y);
1133:                            }
1134:                        }
1135:                    };
1136:                }
1137:                return magicAction;
1138:            }
1139:
1140:            Object getBlinkAction() {
1141:                if (blinkAction == null) {
1142:                    blinkAction = new AbstractAction() {
1143:                        public void actionPerformed(final ActionEvent e) {
1144:                            shouldDraw = !shouldDraw;
1145:                            EventQueue.invokeLater(new Runnable() {
1146:                                public void run() {
1147:                                    repaint();
1148:                                }
1149:                            });
1150:                        }
1151:                    };
1152:                }
1153:                return blinkAction;
1154:            }
1155:
1156:            boolean isRestoreSelectionCondition(final Component c) {
1157:                return SwingUtilities.windowForComponent(c) == SwingUtilities
1158:                        .windowForComponent(component);
1159:            }
1160:
1161:            Color getCaretColor() {
1162:                JTextComponent textComponent = getComponent();
1163:                Color componentsColor = textComponent.getCaretColor();
1164:                return componentsColor != null ? componentsColor
1165:                        : DEF_CARET_COLOR;
1166:            }
1167:
1168:            Color getSelectionColor() {
1169:                JTextComponent textComponent = getComponent();
1170:                Color componentsColor = textComponent.getSelectionColor();
1171:                return componentsColor != null ? componentsColor
1172:                        : DEF_SEL_COLOR;
1173:            }
1174:
1175:            boolean isComponentEditable() {
1176:                return ((JTextComponent) component).isEditable()
1177:                        && component.isEnabled();
1178:            }
1179:
1180:            boolean isDragEnabled() {
1181:                return ((JTextComponent) component).getDragEnabled();
1182:            }
1183:
1184:            Object addHighlight(final int p0, final int p1) {
1185:                if (highlighter != null && component.isEnabled()) {
1186:                    Object result = null;
1187:                    try {
1188:                        result = highlighter.addHighlight(p0, p1, painter);
1189:                    } catch (BadLocationException e) {
1190:                    }
1191:                    return result;
1192:                } else {
1193:                    return null;
1194:                }
1195:            }
1196:
1197:            void changeHighlight(final Object tag, final int p0, final int p1) {
1198:                if (highlighter != null) {
1199:                    try {
1200:                        highlighter.changeHighlight(tag, p0, p1);
1201:                    } catch (final BadLocationException e) {
1202:                    }
1203:                }
1204:            }
1205:
1206:            void removeHighlight(final Object tag) {
1207:                if (highlighter != null) {
1208:                    highlighter.removeHighlight(tag);
1209:                }
1210:            }
1211:
1212:            void setMagicCaretPosition(final int pos, final int direction,
1213:                    final Point oldPoint) {
1214:                try {
1215:                    Point newPoint = null;
1216:                    if (direction == SwingConstants.SOUTH
1217:                            || direction == SwingConstants.NORTH) {
1218:                        if (oldPoint == null) {
1219:                            Rectangle r = textKit.modelToView(pos,
1220:                                    Position.Bias.Forward).getBounds();
1221:                            newPoint = new Point(r.x, r.y);
1222:                        } else {
1223:                            newPoint = oldPoint;
1224:                        }
1225:                    }
1226:
1227:                    setMagicCaretPosition(newPoint);
1228:                } catch (BadLocationException e) {
1229:                    e.printStackTrace();
1230:                }
1231:            }
1232:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.