Source Code Cross Referenced for DesignerCaret.java in  » IDE-Netbeans » visualweb.api.designer » org » netbeans » modules » visualweb » 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 » IDE Netbeans » visualweb.api.designer » org.netbeans.modules.visualweb.text 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.modules.visualweb.text;
0043:
0044:        import java.awt.Graphics;
0045:        import java.awt.HeadlessException;
0046:        import java.awt.Point;
0047:        import java.awt.Rectangle;
0048:        import java.awt.Toolkit;
0049:        import java.awt.datatransfer.Clipboard;
0050:        import java.awt.datatransfer.ClipboardOwner;
0051:        import java.awt.datatransfer.StringSelection;
0052:        import java.awt.datatransfer.Transferable;
0053:        import java.awt.event.ActionEvent;
0054:        import java.awt.event.ActionListener;
0055:        import java.awt.event.FocusEvent;
0056:        import java.awt.event.FocusListener;
0057:        import java.awt.event.MouseEvent;
0058:        import java.awt.event.MouseListener;
0059:        import java.awt.event.MouseMotionListener;
0060:        import javax.swing.Action;
0061:        import javax.swing.ActionMap;
0062:        import javax.swing.SwingUtilities;
0063:        import javax.swing.Timer;
0064:        import javax.swing.TransferHandler;
0065:        import javax.swing.UIManager;
0066:
0067:        import org.netbeans.modules.visualweb.api.designer.DomProvider.DomDocument;
0068:        import org.netbeans.modules.visualweb.api.designer.DomProvider.DomDocumentEvent;
0069:        import org.netbeans.modules.visualweb.api.designer.DomProvider.DomDocumentListener;
0070:        import org.netbeans.modules.visualweb.api.designer.DomProvider.DomPosition;
0071:        import org.netbeans.modules.visualweb.api.designer.DomProvider.DomRange;
0072:        import org.netbeans.modules.visualweb.api.designer.markup.MarkupService;
0073:        import org.netbeans.modules.visualweb.css2.ModelViewMapper;
0074:        import org.netbeans.modules.visualweb.designer.WebForm;
0075:        import org.netbeans.modules.visualweb.text.actions.SelectLineAction;
0076:        import org.netbeans.modules.visualweb.text.actions.SelectWordAction;
0077:
0078:        import org.openide.ErrorManager;
0079:
0080:        import org.openide.util.WeakListeners;
0081:        import org.w3c.dom.Node;
0082:
0083:        /**
0084:         * Caret to use in flow mode editing in the designer.
0085:         * Derived from Swing's DesignerCaret code but changed integer dot/mark
0086:         * based code to use DOM Range objects, changed document update semantics,
0087:         * and mouse operations since we can't blindly listen for mouse clicks
0088:         * we have to take directions from the SelectionManager.
0089:         *
0090:         * @todo Stop using Position objects in calls to modelToView etc;
0091:         *   instead pass node and offset.
0092:         *
0093:         * @author  Timothy Prinzing
0094:         * @author  Tor Norbye
0095:         */
0096:        /*public*/class DesignerCaret extends Rectangle implements 
0097:                FocusListener, MouseListener, MouseMotionListener {
0098:            private static transient Action selectWord = null;
0099:            private static transient Action selectLine = null;
0100:            private transient boolean installed;
0101:
0102:            // ---- member variables ------------------------------------------
0103:            // package-private to avoid inner classes private member
0104:            // access bug
0105:            DesignerPaneBase component;
0106:
0107:            /**
0108:             * flag to indicate if async updates should move the caret.
0109:             */
0110:            boolean async;
0111:            boolean visible;
0112:            boolean flashOn;
0113:
0114:            //Position dot = Position.NONE;
0115:            //Position mark = Position.NONE;
0116:            //    Range range = null;
0117:            DomRange range = null;
0118:
0119:            Object selectionTag;
0120:            boolean selectionVisible;
0121:            Timer flasher;
0122:            Point magicCaretPosition;
0123:            private final Handler handler = new Handler();
0124:
0125:            /**
0126:             * This is used to indicate if the caret currently owns the selection. This is always false if
0127:             * the system does not support the system clipboard.
0128:             */
0129:            private boolean ownsSelection;
0130:
0131:            /**
0132:             * If this is true, the location of the dot is updated regardless of the current location. This
0133:             * is set in the DocumentListener such that even if the model location of dot hasn't changed
0134:             * (perhaps do to a forward delete) the visual location is updated.
0135:             */
0136:            private boolean forceCaretPositionChange;
0137:
0138:            /**
0139:             * Whether or not mouseReleased should adjust the caret and focus. This flag is set by
0140:             * mousePressed if it wanted to adjust the caret and focus but couldn't because of a possible
0141:             * DnD operation.
0142:             */
0143:            private transient boolean shouldHandleRelease;
0144:
0145:            /**
0146:             * Constructs a default caret.
0147:             */
0148:            public DesignerCaret() {
0149:                async = false;
0150:            }
0151:
0152:            public DomRange getRange() {
0153:                return range;
0154:            }
0155:
0156:            /**
0157:             * Get the flag that determines whether or not asynchronous updates will move the caret.
0158:             * Normally the caret is moved by events from the event thread such as mouse or keyboard events.
0159:             * Changes from another thread might be used to load a file, or show changes from another user.
0160:             * This flag determines whether those changes will move the caret.
0161:             */
0162:            boolean getAsynchronousMovement() {
0163:                return async;
0164:            }
0165:
0166:            /**
0167:             * Set the flag that determines whether or not asynchronous updates will move the caret.
0168:             * Normally the caret is moved by events from the event thread such as mouse or keyboard events.
0169:             * Changes from another thread might be used to load a file, or show changes from another user.
0170:             * This flag determines whether those changes will move the caret.
0171:             *
0172:             * @param m
0173:             *            move the caret on asynchronous updates if true.
0174:             */
0175:            void setAsynchronousMovement(boolean m) {
0176:                async = m;
0177:            }
0178:
0179:            /**
0180:             * Gets the text editor component that this caret is is bound to.
0181:             *
0182:             * @return the component
0183:             */
0184:            protected final DesignerPaneBase getComponent() {
0185:                return component;
0186:            }
0187:
0188:            /**
0189:             * Cause the caret to be painted. The repaint area is the bounding box of the caret (i.e. the
0190:             * caret rectangle or <em>this</em>).
0191:             * <p>
0192:             * This method is thread safe, although most Swing methods are not. Please see <A
0193:             * HREF="http://java.sun.com/products/jfc/swingdoc-archive/threads.html"> Threads and Swing </A>
0194:             * for more information.
0195:             */
0196:            protected final synchronized void repaint() {
0197:                if (component != null) {
0198:                    component.repaint(x, y, width, height);
0199:                }
0200:            }
0201:
0202:            /**
0203:             * Cause the selection region to be painted.
0204:             */
0205:            protected final synchronized void repaintSelection() {
0206:                if (component != null) {
0207:                    component.repaint();
0208:                }
0209:            }
0210:
0211:            /**
0212:             * Damages the area surrounding the caret to cause it to be repainted in a new location. If
0213:             * paint() is reimplemented, this method should also be reimplemented. This method should update
0214:             * the caret bounds (x, y, width, and height).
0215:             *
0216:             * @param r
0217:             *            the current location of the caret
0218:             * @see #paint
0219:             */
0220:            protected synchronized void damage(Rectangle r) {
0221:                if (r != null) {
0222:                    x = r.x - 4;
0223:                    y = r.y;
0224:                    width = 10;
0225:                    height = r.height;
0226:                    repaint();
0227:                }
0228:            }
0229:
0230:            /**
0231:             * Scrolls the associated view (if necessary) to make the caret visible. Since how this should
0232:             * be done is somewhat of a policy, this method can be reimplemented to change the behavior. By
0233:             * default the scrollRectToVisible method is called on the associated component.
0234:             *
0235:             * @param nloc
0236:             *            the new position to scroll to
0237:             */
0238:            protected void adjustVisibility(Rectangle nloc) {
0239:                if (component == null) {
0240:                    return;
0241:                }
0242:
0243:                if (SwingUtilities.isEventDispatchThread()) {
0244:                    component.scrollRectToVisible(nloc);
0245:                } else {
0246:                    SwingUtilities.invokeLater(new SafeScroller(nloc));
0247:                }
0248:            }
0249:
0250:            /**
0251:             * Tries to set the position of the caret from the coordinates of a mouse event, using
0252:             * viewToModel().
0253:             *
0254:             * @param e
0255:             *            the mouse event
0256:             */
0257:            private/*protected*/void positionCaret(MouseEvent e) { // XXX When is this used?
0258:
0259:                Point pt = new Point(e.getX(), e.getY());
0260:                //        Position pos = component.getUI().viewToModel(component, pt);
0261:                //        WebForm webform = component.getDocument().getWebForm();
0262:                WebForm webform = component.getWebForm();
0263:
0264:                //        Position pos = webform.viewToModel(pt);
0265:                DomPosition pos = webform.viewToModel(pt);
0266:
0267:                if ((webform.getManager().getInlineEditor() == null)
0268:                        || !webform.getManager().getInlineEditor()
0269:                                .isDocumentEditor()) {
0270:                    //            pos = DesignerUtils.checkPosition(pos, true, /*webform*/webform.getManager().getInlineEditor());
0271:                    //            pos = ModelViewMapper.findValidPosition(pos, true, /*webform*/webform.getManager().getInlineEditor());
0272:                    pos = ModelViewMapper.findValidPosition(webform, pos, true, /*webform*/
0273:                            webform.getManager().getInlineEditor());
0274:                }
0275:
0276:                //        if (pos != Position.NONE) {
0277:                if (pos != DomPosition.NONE) {
0278:                    setDot(pos);
0279:                }
0280:            }
0281:
0282:            /**
0283:             * Tries to move the position of the caret from the coordinates of a mouse event, using
0284:             * viewToModel(). This will cause a selection if the dot and mark are different.
0285:             *
0286:             * @param e
0287:             *            the mouse event
0288:             */
0289:            private/*protected*/void moveCaret(MouseEvent e) {
0290:                Point pt = new Point(e.getX(), e.getY());
0291:                //        Position pos = component.getUI().viewToModel(component, pt);
0292:                //        WebForm webform = component.getDocument().getWebForm();
0293:                WebForm webform = component.getWebForm();
0294:
0295:                //        Position pos = webform.viewToModel(pt);
0296:                DomPosition pos = webform.viewToModel(pt);
0297:
0298:                if ((webform.getManager().getInlineEditor() == null)
0299:                        || !webform.getManager().getInlineEditor()
0300:                                .isDocumentEditor()) {
0301:                    //            pos = DesignerUtils.checkPosition(pos, true, /*webform*/webform.getManager().getInlineEditor());
0302:                    //            pos = ModelViewMapper.findValidPosition(pos, true, /*webform*/webform.getManager().getInlineEditor());
0303:                    pos = ModelViewMapper.findValidPosition(webform, pos, true, /*webform*/
0304:                            webform.getManager().getInlineEditor());
0305:                }
0306:
0307:                //        if (pos != Position.NONE) {
0308:                if (pos != DomPosition.NONE) {
0309:                    moveDot(pos);
0310:                }
0311:            }
0312:
0313:            // --- FocusListener methods --------------------------
0314:
0315:            /**
0316:             * Called when the component containing the caret gains focus. This is implemented to set the
0317:             * caret to visible if the component is editable.
0318:             *
0319:             * @param e
0320:             *            the focus event
0321:             * @see FocusListener#focusGained
0322:             */
0323:            public void focusGained(FocusEvent e) {
0324:                if (component.isEnabled()) {
0325:                    setVisible(true);
0326:                    setSelectionVisible(true);
0327:                }
0328:            }
0329:
0330:            /**
0331:             * Called when the component containing the caret loses focus. This is implemented to set the
0332:             * caret to visibility to false.
0333:             *
0334:             * @param e
0335:             *            the focus event
0336:             * @see FocusListener#focusLost
0337:             */
0338:            public void focusLost(FocusEvent e) {
0339:                setVisible(false);
0340:                setSelectionVisible(ownsSelection || e.isTemporary());
0341:            }
0342:
0343:            // --- MouseListener methods -----------------------------------
0344:
0345:            /**
0346:             * Called when the mouse is clicked. If the click was generated from button1, a double click
0347:             * selects a word, and a triple click the current line.
0348:             *
0349:             * @param e
0350:             *            the mouse event
0351:             * @see MouseListener#mouseClicked
0352:             */
0353:            public void mouseClicked(MouseEvent e) {
0354:                if (!e.isConsumed()) {
0355:                    int nclicks = e.getClickCount();
0356:
0357:                    if (SwingUtilities.isLeftMouseButton(e)) {
0358:                        // mouse 1 behavior
0359:                        if (e.getClickCount() == 2) {
0360:                            Action a = null;
0361:                            ActionMap map = getComponent().getActionMap();
0362:
0363:                            if (map != null) {
0364:                                a = map.get(DesignerPaneBase.selectWordAction);
0365:                            }
0366:
0367:                            if (a == null) {
0368:                                if (selectWord == null) {
0369:                                    selectWord = new SelectWordAction();
0370:                                }
0371:
0372:                                a = selectWord;
0373:                            }
0374:
0375:                            a.actionPerformed(new ActionEvent(getComponent(),
0376:                                    ActionEvent.ACTION_PERFORMED, null, e
0377:                                            .getWhen(), e.getModifiers()));
0378:                        } else if (e.getClickCount() == 3) {
0379:                            Action a = null;
0380:                            ActionMap map = getComponent().getActionMap();
0381:
0382:                            if (map != null) {
0383:                                a = map.get(DesignerPaneBase.selectLineAction);
0384:                            }
0385:
0386:                            if (a == null) {
0387:                                if (selectLine == null) {
0388:                                    selectLine = new SelectLineAction();
0389:                                }
0390:
0391:                                a = selectLine;
0392:                            }
0393:
0394:                            a.actionPerformed(new ActionEvent(getComponent(),
0395:                                    ActionEvent.ACTION_PERFORMED, null, e
0396:                                            .getWhen(), e.getModifiers()));
0397:                        }
0398:                    } else if (SwingUtilities.isMiddleMouseButton(e)) {
0399:                        // mouse 2 behavior
0400:                        if (nclicks == 1) {
0401:                            // paste system selection, if it exists
0402:                            DesignerPaneBase c = (DesignerPaneBase) e
0403:                                    .getSource();
0404:
0405:                            if (c != null) {
0406:                                try {
0407:                                    Toolkit tk = c.getToolkit();
0408:                                    Clipboard buffer = tk.getSystemSelection();
0409:
0410:                                    if (buffer != null) {
0411:                                        // platform supports system selections, update it.
0412:                                        adjustCaret(e);
0413:
0414:                                        TransferHandler th = c
0415:                                                .getTransferHandler();
0416:
0417:                                        if (th != null) {
0418:                                            Transferable trans = buffer
0419:                                                    .getContents(null);
0420:
0421:                                            if (trans != null) {
0422:                                                th.importData(c, trans);
0423:                                            }
0424:                                        }
0425:
0426:                                        adjustFocus(true);
0427:                                    }
0428:                                } catch (HeadlessException he) {
0429:                                    ErrorManager.getDefault().notify(
0430:                                            ErrorManager.INFORMATIONAL, he);
0431:
0432:                                    // do nothing... there is no system clipboard
0433:                                }
0434:                            }
0435:                        }
0436:                    }
0437:                }
0438:            }
0439:
0440:            /**
0441:             * If button 1 is pressed, this is implemented to request focus on the associated text
0442:             * component, and to set the caret position. If the shift key is held down, the caret will be
0443:             * moved, potentially resulting in a selection, otherwise the caret position will be set to the
0444:             * new location. If the component is not enabled, there will be no request for focus.
0445:             *
0446:             * @param e
0447:             *            the mouse event
0448:             * @see MouseListener#mousePressed
0449:             */
0450:            public void mousePressed(MouseEvent e) {
0451:                if (SwingUtilities.isLeftMouseButton(e)) {
0452:                    if (e.isConsumed()) {
0453:                        shouldHandleRelease = true;
0454:                    } else {
0455:                        shouldHandleRelease = false;
0456:                        adjustCaretAndFocus(e);
0457:                    }
0458:                }
0459:            }
0460:
0461:            private void adjustCaretAndFocus(MouseEvent e) {
0462:                adjustCaret(e);
0463:                adjustFocus(false);
0464:            }
0465:
0466:            /**
0467:             * Adjusts the caret location based on the MouseEvent.
0468:             */
0469:            private void adjustCaret(MouseEvent e) {
0470:                //        if (((e.getModifiers() & ActionEvent.SHIFT_MASK) != 0) && (getDot() != Position.NONE)) {
0471:                if (((e.getModifiers() & ActionEvent.SHIFT_MASK) != 0)
0472:                        && (getDot() != DomPosition.NONE)) {
0473:                    moveCaret(e);
0474:                } else {
0475:                    positionCaret(e);
0476:                }
0477:            }
0478:
0479:            /**
0480:             * Adjusts the focus, if necessary.
0481:             *
0482:             * @param inWindow
0483:             *            if true indicates requestFocusInWindow should be used
0484:             */
0485:            private void adjustFocus(boolean inWindow) {
0486:                if ((component != null) && component.isEnabled()
0487:                        && component.isRequestFocusEnabled()) {
0488:                    if (inWindow) {
0489:                        component.requestFocusInWindow();
0490:                    } else {
0491:                        component.requestFocus();
0492:                    }
0493:                }
0494:            }
0495:
0496:            /**
0497:             * Called when the mouse is released.
0498:             *
0499:             * @param e
0500:             *            the mouse event
0501:             * @see MouseListener#mouseReleased
0502:             */
0503:            public void mouseReleased(MouseEvent e) {
0504:                if (shouldHandleRelease && SwingUtilities.isLeftMouseButton(e)) {
0505:                    adjustCaretAndFocus(e);
0506:                }
0507:            }
0508:
0509:            /**
0510:             * Called when the mouse enters a region.
0511:             *
0512:             * @param e
0513:             *            the mouse event
0514:             * @see MouseListener#mouseEntered
0515:             */
0516:            public void mouseEntered(MouseEvent e) {
0517:            }
0518:
0519:            /**
0520:             * Called when the mouse exits a region.
0521:             *
0522:             * @param e
0523:             *            the mouse event
0524:             * @see MouseListener#mouseExited
0525:             */
0526:            public void mouseExited(MouseEvent e) {
0527:            }
0528:
0529:            // --- MouseMotionListener methods -------------------------
0530:
0531:            /**
0532:             * Moves the caret position according to the mouse pointer's current location. This effectively
0533:             * extends the selection. By default, this is only done for mouse button 1.
0534:             *
0535:             * @param e
0536:             *            the mouse event
0537:             * @see MouseMotionListener#mouseDragged
0538:             */
0539:            public void mouseDragged(MouseEvent e) {
0540:                if ((!e.isConsumed()) && SwingUtilities.isLeftMouseButton(e)) {
0541:                    moveCaret(e);
0542:                }
0543:            }
0544:
0545:            /**
0546:             * Called when the mouse is moved.
0547:             *
0548:             * @param e
0549:             *            the mouse event
0550:             * @see MouseMotionListener#mouseMoved
0551:             */
0552:            public void mouseMoved(MouseEvent e) {
0553:            }
0554:
0555:            // ---- Caret methods ---------------------------------
0556:
0557:            /**
0558:             * Renders the caret as a vertical line. If this is reimplemented the damage method should also
0559:             * be reimplemented as it assumes the shape of the caret is a vertical line. Sets the caret
0560:             * color to the value returned by getCaretColor().
0561:             * <p>
0562:             *
0563:             * @param g
0564:             *            the graphics context
0565:             * @see #damage
0566:             */
0567:            public void paint(Graphics g) {
0568:                if (isVisible() && flashOn) {
0569:                    DesignerPaneBaseUI mapper = component.getUI();
0570:
0571:                    if (range == null) {
0572:                        return;
0573:                    }
0574:
0575:                    //            Position dot = range.getDot();
0576:                    DomPosition dot = range.getDot();
0577:                    //            Rectangle r = mapper.modelToView(/*component,*/ dot);
0578:                    //            WebForm webForm = component.getDocument().getWebForm();
0579:                    WebForm webForm = component.getWebForm();
0580:
0581:                    Rectangle r = webForm.modelToView(dot);
0582:
0583:                    if ((r == null) || ((r.width == 0) && (r.height == 0))) {
0584:                        return;
0585:                    }
0586:
0587:                    if ((width > 0) && (height > 0)
0588:                            && !this ._contains(r.x, r.y, r.width, r.height)) {
0589:                        // We seem to have gotten out of sync and no longer
0590:                        // contain the right location, adjust accordingly.
0591:                        Rectangle clip = g.getClipBounds();
0592:
0593:                        if ((clip != null) && !clip.contains(this )) {
0594:                            // Clip doesn't contain the old location, force it
0595:                            // to be repainted lest we leave a caret around.
0596:                            repaint();
0597:                        }
0598:
0599:                        // This will potentially cause a repaint of something
0600:                        // we're already repainting, but without changing the
0601:                        // semantics of damage we can't really get around this.
0602:                        damage(r);
0603:                    }
0604:
0605:                    g.setColor(component.getCaretColor());
0606:
0607:                    //g.setColor(java.awt.Color.RED);
0608:                    g.drawLine(r.x, r.y, r.x, (r.y + r.height) - 1);
0609:                    g.drawLine(r.x + 1, r.y, r.x + 1, (r.y + r.height) - 1);
0610:
0611:                    // see if we should paint a flag to indicate the bias
0612:                    // of the caret.
0613:                    // PENDING(prinz) this should be done through
0614:                    // protected methods so that alternative LAF
0615:                    // will show bidi information.
0616:                }
0617:            }
0618:
0619:            /**
0620:             * Called when the UI is being installed into the interface of a JTextComponent. This can be
0621:             * used to gain access to the model that is being navigated by the implementation of this
0622:             * interface. Sets the dot and mark to 0, and establishes document, property change, focus,
0623:             * mouse, and mouse motion listeners.
0624:             *
0625:             * @param c
0626:             *            the component
0627:             */
0628:            public void install(DesignerPaneBase c) {
0629:                //        assert !installed;
0630:                if (installed) {
0631:                    ErrorManager
0632:                            .getDefault()
0633:                            .notify(
0634:                                    ErrorManager.INFORMATIONAL,
0635:                                    new IllegalStateException(
0636:                                            "The designer caret is installed already!")); // NOI18N
0637:                    return;
0638:                }
0639:
0640:                installed = true;
0641:                component = c;
0642:
0643:                // NO caret until you click to set one (switching to flow mode
0644:                // should also do that
0645:                //dot = mark = Position.NONE;
0646:                c.addFocusListener(this );
0647:
0648:                //        c.getDocument().addDomDocumentListener(handler);
0649:                //        c.getWebForm().getDocument().addDomDocumentListener(handler);
0650:                // XXX #123003 Another memory leak via the listener (missing call to deinstall), using weak listener instead.
0651:                //        c.getWebForm().getDomDocument().addDomDocumentListener(handler);
0652:                DomDocument domDocument = c.getWebForm().getDomDocument();
0653:                DomDocumentListener weakListener = WeakListeners.create(
0654:                        DomDocumentListener.class, handler, domDocument);
0655:                domDocument.addDomDocumentListener(weakListener);
0656:
0657:                // if the component already has focus, it won't
0658:                // be notified.
0659:                if (component.hasFocus()) {
0660:                    focusGained(null);
0661:                }
0662:            }
0663:
0664:            /**
0665:             * Called when the UI is being removed from the interface of a JTextComponent. This is used to
0666:             * unregister any listeners that were attached.
0667:             *
0668:             * @param c
0669:             *            the component
0670:             */
0671:            public void deinstall(DesignerPaneBase c) {
0672:                //        assert installed;
0673:                if (!installed) {
0674:                    ErrorManager
0675:                            .getDefault()
0676:                            .notify(
0677:                                    ErrorManager.INFORMATIONAL,
0678:                                    new IllegalStateException(
0679:                                            "The designer caret was not installed before!")); // NOI18N
0680:                    return;
0681:                }
0682:
0683:                installed = false;
0684:                c.removeFocusListener(this );
0685:
0686:                //        c.getDocument().removeDomDocumentListener(handler);
0687:                //        c.getWebForm().getDocument().removeDomDocumentListener(handler);
0688:                //        c.getWebForm().getDomDocument().removeDomDocumentListener(handler);
0689:
0690:                synchronized (this ) {
0691:                    component = null;
0692:                }
0693:
0694:                if (flasher != null) {
0695:                    flasher.stop();
0696:                    flasher = null;
0697:                }
0698:
0699:                if (range != null) {
0700:                    range.detach();
0701:                    range = null;
0702:                }
0703:            }
0704:
0705:            /**
0706:             * Changes the selection visibility.
0707:             *
0708:             * @param vis
0709:             *            the new visibility
0710:             */
0711:            public void setSelectionVisible(boolean vis) {
0712:                if (vis != selectionVisible) {
0713:                    selectionVisible = vis;
0714:
0715:                    if (!selectionVisible || hasSelection()) {
0716:                        // XXX this causes a global repaint... notagood!
0717:                        repaintSelection();
0718:                    }
0719:                }
0720:            }
0721:
0722:            /**
0723:             * Checks whether the current selection is visible.
0724:             *
0725:             * @return true if the selection is visible
0726:             */
0727:            public boolean isSelectionVisible() {
0728:                return selectionVisible;
0729:            }
0730:
0731:            /**
0732:             * Determines if the caret is currently visible.
0733:             *
0734:             * @return true if visible else false
0735:             */
0736:            public boolean isVisible() {
0737:                return visible;
0738:            }
0739:
0740:            /**
0741:             * Sets the caret visibility, and repaints the caret.
0742:             *
0743:             * @param e
0744:             *            the visibility specifier
0745:             */
0746:            public void setVisible(boolean e) {
0747:                // focus lost notification can come in later after the
0748:                // caret has been deinstalled, in which case the component
0749:                // will be null.
0750:                if (component != null) {
0751:                    DesignerPaneBaseUI mapper = component.getUI();
0752:
0753:                    if (visible != e) {
0754:                        visible = e;
0755:
0756:                        // repaint the caret
0757:                        if (range != null) {
0758:                            //                    Position dot = range.getDot();
0759:                            DomPosition dot = range.getDot();
0760:                            //                    Rectangle loc = mapper.modelToView(/*component,*/ dot);
0761:                            //                    WebForm webForm = component.getDocument().getWebForm();
0762:                            WebForm webForm = component.getWebForm();
0763:
0764:                            Rectangle loc = webForm.modelToView(dot);
0765:                            damage(loc);
0766:                        }
0767:                    }
0768:                }
0769:
0770:                if (flasher != null) {
0771:                    if (visible) {
0772:                        flashOn = true;
0773:                        flasher.start();
0774:                    } else {
0775:                        flasher.stop();
0776:                    }
0777:                }
0778:            }
0779:
0780:            /**
0781:             * Sets the caret blink rate.
0782:             *
0783:             * @param rate
0784:             *            the rate in milliseconds, 0 to stop blinking
0785:             */
0786:            public void setBlinkRate(int rate) {
0787:                if (rate != 0) {
0788:                    if (flasher == null) {
0789:                        flasher = new Timer(rate, handler);
0790:                    }
0791:
0792:                    flasher.setDelay(rate);
0793:                } else {
0794:                    if (flasher != null) {
0795:                        flasher.stop();
0796:                        flasher.removeActionListener(handler);
0797:                        flasher = null;
0798:                        flashOn = true;
0799:                    }
0800:                }
0801:            }
0802:
0803:            /**
0804:             * Gets the caret blink rate.
0805:             *
0806:             * @return the delay in milliseconds. If this is zero the caret will not blink.
0807:             */
0808:            public int getBlinkRate() {
0809:                return (flasher == null) ? 0 : flasher.getDelay();
0810:            }
0811:
0812:            /**
0813:             * Fetches the current position of the caret.
0814:             * The caret dot position is always a source position.
0815:             *
0816:             * @return the position >= 0
0817:             */
0818:            //    public Position getDot() {
0819:            public DomPosition getDot() {
0820:                if (range == null) {
0821:                    //            return Position.NONE;
0822:                    return DomPosition.NONE;
0823:                }
0824:
0825:                return range.getDot();
0826:            }
0827:
0828:            /**
0829:             * Fetches the current position of the mark. If there is a selection, the dot and mark will not
0830:             * be the same.
0831:             * The caret mark position is always a source position.
0832:             *
0833:             * @return the position >= 0
0834:             */
0835:            //    public Position getMark() {
0836:            public DomPosition getMark() {
0837:                if (range == null) {
0838:                    //            return Position.NONE;
0839:                    return DomPosition.NONE;
0840:                }
0841:
0842:                return range.getMark();
0843:            }
0844:
0845:            /**
0846:             * Return the first endpoint of the range in the document.
0847:             * This is always a source position.
0848:             */
0849:            //    public Position getFirstPosition() {
0850:            public DomPosition getFirstPosition() {
0851:                if (range == null) {
0852:                    //            return Position.NONE;
0853:                    return DomPosition.NONE;
0854:                }
0855:
0856:                return range.getFirstPosition();
0857:            }
0858:
0859:            /**
0860:             * Return the second/last endpoint of the range in the document.
0861:             * This is always a source position.
0862:             */
0863:            //    public Position getLastPosition() {
0864:            public DomPosition getLastPosition() {
0865:                if (range == null) {
0866:                    //            return Position.NONE;
0867:                    return DomPosition.NONE;
0868:                }
0869:
0870:                return range.getLastPosition();
0871:            }
0872:
0873:            /**
0874:             * Sets the caret position and mark to some position. This implicitly sets the selection range
0875:             * to zero.
0876:             *
0877:             * @param dot
0878:             *            the position >= 0
0879:             */
0880:            //    public void setDot(Position dot) {
0881:            public void setDot(DomPosition dot) {
0882:                handleSetDot(dot);
0883:            }
0884:
0885:            /**
0886:             * Moves the caret position to some other position.
0887:             *
0888:             * @param dot
0889:             *            the position >= 0
0890:             */
0891:            //    public void moveDot(Position dot) {
0892:            public void moveDot(DomPosition dot) {
0893:                /*
0894:                 * We don't have disabled designer panes... if (! component.isEnabled()) { // don't allow
0895:                 * selection on disabled components. setDot(dot, dotBias); return; }
0896:                 */
0897:                //        if ((dot == Position.NONE) && (range == null)) {
0898:                if ((dot == DomPosition.NONE) && (range == null)) {
0899:                    return;
0900:                } else if ((range != null) && range.isDot(dot)) {
0901:                    return;
0902:                }
0903:
0904:                handleMoveDot(dot);
0905:            }
0906:
0907:            //    void handleMoveDot(Position dot) {
0908:            void handleMoveDot(DomPosition dot) {
0909:                //        assert !dot.isRendered();
0910:                //        if (MarkupService.isRenderedNode(dot.getNode())) {
0911:                if (component.getWebForm().isRenderedNode(dot.getNode())) {
0912:                    ErrorManager.getDefault().notify(
0913:                            ErrorManager.INFORMATIONAL,
0914:                            new IllegalArgumentException(
0915:                                    "The node is expected not rendered"
0916:                                            + dot.getNode())); // NOI18N
0917:                }
0918:
0919:                // XXX Very suspicious assertion.
0920:                //        assert component.getDocument().getWebForm().getPane().getPageBox().getElement().getOwnerDocument() == component.getDocument().getWebForm().getJspDom();
0921:                //        if (component.getDocument().getWebForm().getPane().getPageBox().getElement().getOwnerDocument() != component.getDocument().getWebForm().getHtmlDom()) {
0922:                //            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
0923:                //                    new IllegalStateException("Owner document is expected to be html dom=" + component.getDocument().getWebForm().getHtmlDom() // NOI18N
0924:                //                    + ", but it is dom=" + component.getDocument().getWebForm().getPane().getPageBox().getElement().getOwnerDocument())); // NOI18N
0925:                //        }
0926:                if (component.getWebForm().getPane().getPageBox().getElement()
0927:                        .getOwnerDocument() != component.getWebForm()
0928:                        .getHtmlDom()) {
0929:                    ErrorManager.getDefault().notify(
0930:                            ErrorManager.INFORMATIONAL,
0931:                            new IllegalStateException(
0932:                                    "Owner document is expected to be html dom="
0933:                                            + component.getWebForm()
0934:                                                    .getHtmlDom() // NOI18N
0935:                                            + ", but it is dom="
0936:                                            + component.getWebForm().getPane()
0937:                                                    .getPageBox().getElement()
0938:                                                    .getOwnerDocument())); // NOI18N
0939:                }
0940:
0941:                changeCaretPosition(dot);
0942:
0943:                setSelectionVisible(hasSelection());
0944:
0945:                if (hasSelection()) {
0946:                    repaintSelection();
0947:                }
0948:            }
0949:
0950:            //    void handleSetDot(Position dot) {
0951:            void handleSetDot(DomPosition dot) {
0952:                // move dot, if it changed
0953:
0954:                /*
0955:                 * Document doc = component.getDocument(); if (doc != null) { dot = Position.first(dot,
0956:                 * doc.getEndPosition()); } dot = Position.last(dot, doc.getStartPosition());
0957:                 */
0958:                // XXX #124732 Possible NPE.
0959:                //        if (dot == Position.NONE) {
0960:                if (component == null || dot == null || dot == DomPosition.NONE) {
0961:                    if (range != null) {
0962:                        range.detach();
0963:                        range = null;
0964:                    }
0965:
0966:                    // TODO: Gotta clear selection highlights here!
0967:                    return;
0968:                }
0969:
0970:                //        assert !dot.isRendered() ||
0971:                //        component.getDocument().getWebForm().getManager().isInlineEditing() : dot;
0972:                //        if (MarkupService.isRenderedNode(dot.getNode())
0973:                if (component.getWebForm().isRenderedNode(dot.getNode())
0974:                //        && !component.getDocument().getWebForm().getManager().isInlineEditing()) {
0975:                        && !component.getWebForm().getManager()
0976:                                .isInlineEditing()) {
0977:                    ErrorManager.getDefault().notify(
0978:                            ErrorManager.INFORMATIONAL,
0979:                            new IllegalStateException(
0980:                                    "It is not in inline editing, and node is rendered node="
0981:                                            + dot.getNode())); // NOI18N
0982:                }
0983:
0984:                // XXX Very suspicious assertion.
0985:                //        assert component.getDocument().getWebForm().getPane().getPageBox().getElement().getOwnerDocument() == component.getDocument().getWebForm().getJspDom();
0986:                //        if (component.getDocument().getWebForm().getPane().getPageBox().getElement().getOwnerDocument() != component.getDocument().getWebForm().getHtmlDom()) {
0987:                //            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
0988:                //                    new IllegalStateException("Owner document is expected to be html dom=" + component.getDocument().getWebForm().getHtmlDom() // NOI18N
0989:                //                    + ", but it is dom=" + component.getDocument().getWebForm().getPane().getPageBox().getElement().getOwnerDocument())); // NOI18N
0990:                //        }
0991:                if (component.getWebForm().getPane().getPageBox().getElement()
0992:                        .getOwnerDocument() != component.getWebForm()
0993:                        .getHtmlDom()) {
0994:                    ErrorManager.getDefault().notify(
0995:                            ErrorManager.INFORMATIONAL,
0996:                            new IllegalStateException(
0997:                                    "Owner document is expected to be html dom="
0998:                                            + component.getWebForm()
0999:                                                    .getHtmlDom() // NOI18N
1000:                                            + ", but it is dom="
1001:                                            + component.getWebForm().getPane()
1002:                                                    .getPageBox().getElement()
1003:                                                    .getOwnerDocument())); // NOI18N
1004:                }
1005:
1006:                Node node = dot.getNode();
1007:                int offset = dot.getOffset();
1008:
1009:                // Set the mark to the new dot position
1010:                boolean dotChanged;
1011:
1012:                if (range == null) {
1013:                    //            range = new Range(component.getDocument().getWebForm(), node, offset, node, offset);
1014:                    //            range = Range.create(component.getDocument().getWebForm(), node, offset, node, offset);
1015:                    //            range = Range.create(component.getWebForm(), node, offset, node, offset);
1016:                    range = component.getWebForm().createDomRange(node, offset,
1017:                            node, offset);
1018:
1019:                    dotChanged = true;
1020:                } else {
1021:                    range.setMark(node, offset, dot.getBias());
1022:
1023:                    //            dotChanged = range.isDot(dot);
1024:                    // When we're using dom ranges they offset will always
1025:                    // have been preadjusted so we don't 
1026:                    dotChanged = true;
1027:                }
1028:
1029:                if (dotChanged || (selectionTag != null)
1030:                        || forceCaretPositionChange) {
1031:                    changeCaretPosition(dot);
1032:                }
1033:
1034:                setSelectionVisible(hasSelection());
1035:
1036:                //        if (System.getProperty("rave.debugLayout") != null) {
1037:                //            org.openide.awt.StatusDisplayer.getDefault().setStatusText("Caret=" + getDot());
1038:                //        }
1039:            }
1040:
1041:            // ---- local methods --------------------------------------------
1042:
1043:            /**
1044:             * Sets the caret position (dot) to a new location. This causes the old and new location to be
1045:             * repainted. It also makes sure that the caret is within the visible region of the view, if the
1046:             * view is scrollable.
1047:             */
1048:            //    void changeCaretPosition(Position dot) {
1049:            void changeCaretPosition(DomPosition dot) {
1050:                // repaint the old position and set the new value of
1051:                // the dot.
1052:                repaint();
1053:
1054:                // Make sure the caret is visible if this window has the focus.
1055:                if ((flasher != null) && flasher.isRunning()) {
1056:                    flashOn = true;
1057:                    flasher.restart();
1058:                }
1059:
1060:                // notify listeners at the caret moved
1061:                //this.dot = dot;
1062:                //NPE: Why can range be null sometimes
1063:                // XXX #94270 I would like that know too. For now just hacking the issue.
1064:                //        range.setDot(dot.getNode(), dot.getOffset(), dot.getBias());
1065:                if (range == null) {
1066:                    // XXX Log the problem?
1067:                    //            range = new Range(component.getDocument().getWebForm(), dot.getNode(), dot.getOffset(), dot.getNode(), dot.getOffset());
1068:                    //            range = Range.create(component.getDocument().getWebForm(), dot.getNode(), dot.getOffset(), dot.getNode(), dot.getOffset());
1069:                    //            range = Range.create(component.getWebForm(), dot.getNode(), dot.getOffset(), dot.getNode(), dot.getOffset());
1070:                    range = component.getWebForm().createDomRange(
1071:                            dot.getNode(), dot.getOffset(), dot.getNode(),
1072:                            dot.getOffset());
1073:                } else {
1074:                    range.setDot(dot.getNode(), dot.getOffset(), dot.getBias());
1075:                }
1076:
1077:                updateSystemSelection();
1078:
1079:                setMagicCaretPosition(null);
1080:
1081:                // We try to repaint the caret later, since things
1082:                // may be unstable at the time this is called
1083:                // (i.e. we don't want to depend upon notification
1084:                // order or the fact that this might happen on
1085:                // an unsafe thread).
1086:                Runnable callRepaintNewCaret = new Runnable() {
1087:                    public void run() {
1088:                        repaintNewCaret();
1089:                    }
1090:                };
1091:
1092:                SwingUtilities.invokeLater(callRepaintNewCaret);
1093:            }
1094:
1095:            /**
1096:             * Repaints the new caret position, with the assumption that this is happening on the event
1097:             * thread so that calling <code>modelToView</code> is safe.
1098:             */
1099:            void repaintNewCaret() {
1100:                if (component != null) {
1101:                    DesignerPaneBaseUI mapper = component.getUI();
1102:                    //            Document doc = component.getDocument();
1103:
1104:                    if ((mapper != null) /*&& (doc != null)*/
1105:                            && (range != null)) {
1106:                        // determine the new location and scroll if
1107:                        // not visible.
1108:                        //                Position dot = range.getDot();
1109:                        DomPosition dot = range.getDot();
1110:                        //                Rectangle newLoc = mapper.modelToView(/*component,*/ dot);
1111:                        //                WebForm webForm = component.getDocument().getWebForm();
1112:                        WebForm webForm = component.getWebForm();
1113:
1114:                        Rectangle newLoc = webForm.modelToView(dot);
1115:
1116:                        if (newLoc != null) {
1117:                            adjustVisibility(newLoc);
1118:
1119:                            // If there is no magic caret position, make one
1120:                            if (getMagicCaretPosition() == null) {
1121:                                setMagicCaretPosition(new Point(newLoc.x,
1122:                                        newLoc.y));
1123:                            }
1124:                        }
1125:
1126:                        // repaint the new position
1127:                        damage(newLoc);
1128:                    }
1129:                }
1130:            }
1131:
1132:            private void updateSystemSelection() {
1133:                if (!range.isEmpty() && (component != null)) {
1134:                    Clipboard clip = getSystemSelection();
1135:
1136:                    if (clip != null) {
1137:                        String rangeText = component.getWebForm()
1138:                                .getDomDocument().getRangeText(range);
1139:
1140:                        clip.setContents(new StringSelection(rangeText),
1141:                                getClipboardOwner());
1142:                        ownsSelection = true;
1143:                    }
1144:                }
1145:            }
1146:
1147:            private Clipboard getSystemSelection() {
1148:                try {
1149:                    return component.getToolkit().getSystemSelection();
1150:                } catch (HeadlessException he) {
1151:                    ErrorManager.getDefault().notify(
1152:                            ErrorManager.INFORMATIONAL, he);
1153:
1154:                    // do nothing... there is no system clipboard
1155:                }
1156:
1157:                return null;
1158:            }
1159:
1160:            private ClipboardOwner getClipboardOwner() {
1161:                return handler;
1162:            }
1163:
1164:            /**
1165:             * Saves the current caret position. This is used when caret up/down actions occur, moving
1166:             * between lines that have uneven end positions.
1167:             *
1168:             * @param p
1169:             *            the position
1170:             * @see #getMagicCaretPosition
1171:             */
1172:            public void setMagicCaretPosition(Point p) {
1173:                magicCaretPosition = p;
1174:            }
1175:
1176:            /**
1177:             * Gets the saved caret position.
1178:             *
1179:             * @return the position see #setMagicCaretPosition
1180:             */
1181:            public Point getMagicCaretPosition() {
1182:                return magicCaretPosition;
1183:            }
1184:
1185:            /** Notify caret that the range it is attached to is no longer valid */
1186:            public void detachDom() {
1187:                if (range != null) {
1188:                    range.detach();
1189:                    range = null;
1190:                }
1191:            }
1192:
1193:            /**
1194:             * Compares this object to the specified object. The superclass behavior of comparing rectangles
1195:             * is not desired, so this is changed to the Object behavior.
1196:             *
1197:             * @param obj
1198:             *            the object to compare this font with
1199:             * @return <code>true</code> if the objects are equal; <code>false</code> otherwise
1200:             */
1201:            public boolean equals(Object obj) {
1202:                return (this  == obj);
1203:            }
1204:
1205:            // XXX This class should override hashCode too! I recently alerted the Swing group to this too.
1206:            public String toString() {
1207:                if (range != null) {
1208:                    return range.toString();
1209:                } else {
1210:                    return "Caret-range is nul";
1211:                }
1212:            }
1213:
1214:            // Rectangle.contains returns false if passed a rect with a w or h == 0,
1215:            // this won't (assuming X,Y are contained with this rectangle).
1216:            private boolean _contains(int X, int Y, int W, int H) {
1217:                int w = this .width;
1218:                int h = this .height;
1219:
1220:                if ((w | h | W | H) < 0) {
1221:                    // At least one of the dimensions is negative...
1222:                    return false;
1223:                }
1224:
1225:                // Note: if any dimension is zero, tests below must return false...
1226:                int x = this .x;
1227:                int y = this .y;
1228:
1229:                if ((X < x) || (Y < y)) {
1230:                    return false;
1231:                }
1232:
1233:                if (W > 0) {
1234:                    w += x;
1235:                    W += X;
1236:
1237:                    if (W <= X) {
1238:                        // X+W overflowed or W was zero, return false if...
1239:                        // either original w or W was zero or
1240:                        // x+w did not overflow or
1241:                        // the overflowed x+w is smaller than the overflowed X+W
1242:                        if ((w >= x) || (W > w)) {
1243:                            return false;
1244:                        }
1245:                    } else {
1246:                        // X+W did not overflow and W was not zero, return false if...
1247:                        // original w was zero or
1248:                        // x+w did not overflow and x+w is smaller than X+W
1249:                        if ((w >= x) && (W > w)) {
1250:                            return false;
1251:                        }
1252:                    }
1253:                } else if ((x + w) < X) {
1254:                    return false;
1255:                }
1256:
1257:                if (H > 0) {
1258:                    h += y;
1259:                    H += Y;
1260:
1261:                    if (H <= Y) {
1262:                        if ((h >= y) || (H > h)) {
1263:                            return false;
1264:                        }
1265:                    } else {
1266:                        if ((h >= y) && (H > h)) {
1267:                            return false;
1268:                        }
1269:                    }
1270:                } else if ((y + h) < Y) {
1271:                    return false;
1272:                }
1273:
1274:                return true;
1275:            }
1276:
1277:            /*private*/void removeSelection() {
1278:                //        assert range != null;
1279:                if (range == null) {
1280:                    ErrorManager.getDefault().notify(
1281:                            ErrorManager.INFORMATIONAL,
1282:                            new IllegalStateException("Range is null.")); // NOI18N
1283:                    return;
1284:                }
1285:                //        range.deleteContents();
1286:                boolean success = component.getWebForm().getDomDocument()
1287:                        .deleteRangeContents(range);
1288:                if (!success) {
1289:                    // Read-only - can't edit!!
1290:                    //            UIManager.getLookAndFeel().provideErrorFeedback(webform.getPane());
1291:                    UIManager.getLookAndFeel().provideErrorFeedback(component);
1292:                }
1293:            }
1294:
1295:            String getSelectedText() {
1296:                if (range == null) {
1297:                    ErrorManager.getDefault().notify(
1298:                            ErrorManager.INFORMATIONAL,
1299:                            new IllegalStateException("Range is null.")); // NOI18N
1300:                    return ""; // NOI18N
1301:                }
1302:                //        return range.getText();
1303:                if (component == null) {
1304:                    ErrorManager.getDefault().notify(
1305:                            ErrorManager.INFORMATIONAL,
1306:                            new IllegalStateException("Component is null.")); // NOI18N
1307:                    return ""; // NOI18N
1308:                }
1309:                return component.getWebForm().getDomDocument().getRangeText(
1310:                        range);
1311:            }
1312:
1313:            /**
1314:             * Return true iff we have a selection - or put differently, if the dot is at a different
1315:             * location than the mark.
1316:             */
1317:            public boolean hasSelection() {
1318:                return (range != null) && !range.isEmpty();
1319:            }
1320:
1321:            // XXX Moved to DesignerPaneBase.
1322:            //    /** Return the text in the selection, if any (if not returns null).
1323:            //     * If the cut parameter is true, then the selection is deleted too.
1324:            //     */
1325:            //    public Transferable copySelection(boolean cut) {
1326:            //        if (hasSelection()) {
1327:            //            String text = range.getText();
1328:            //            assert text.length() > 0;
1329:            //
1330:            //            Transferable transferable = new StringSelection(text);
1331:            //
1332:            //            if (cut) {
1333:            //                removeSelection();
1334:            //            }
1335:            //
1336:            //            return transferable;
1337:            //        } else {
1338:            //            return new StringSelection("");
1339:            //        }
1340:            //    }
1341:
1342:            // XXX Moved to DesignerPaneBase.
1343:            //    /**
1344:            //     * Replace the selection. Beep if within a read-only region.
1345:            //     */
1346:            //    public void replaceSelection(String content) {
1347:            ////        WebForm webform = component.getDocument().getWebForm();
1348:            //        WebForm webform = component.getWebForm();
1349:            //        
1350:            //        InlineEditor editor = webform.getManager().getInlineEditor();
1351:            //
1352:            //        if ((content.equals("\n") || content.equals("\r\n")) && // NOI18N
1353:            //                (editor != null) && !editor.isMultiLine()) {
1354:            //            // Commit
1355:            //            // Should I look to see if the Shift key is pressed, and if so let
1356:            //            // you insert a newline?
1357:            //            webform.getManager().finishInlineEditing(false);
1358:            //
1359:            //            return;
1360:            //        }
1361:            //
1362:            //        /*
1363:            //        if (range.isReadOnlyRegion()) {
1364:            //            UIManager.getLookAndFeel().provideErrorFeedback(component);
1365:            //            return;
1366:            //        }
1367:            //         */
1368:            //        if (hasSelection()) {
1369:            //            removeSelection();
1370:            //        }
1371:            //
1372:            ////        Position pos = getDot();
1373:            //        DomPosition pos = getDot();
1374:            //
1375:            //        if (editor == null) {
1376:            ////            assert (pos == Position.NONE) || !pos.isRendered();
1377:            ////            if (pos != Position.NONE && MarkupService.isRenderedNode(pos.getNode())) {
1378:            //            if (pos != DomPosition.NONE && MarkupService.isRenderedNode(pos.getNode())) {
1379:            //                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
1380:            //                        new IllegalStateException("Node is expected to be not rendered, node=" + pos.getNode())); // NOI18N
1381:            //            }
1382:            //        } // else: Stay in the DocumentFragment; don't jump to the source DOM (there is none)
1383:            //
1384:            ////        if (pos == Position.NONE) {
1385:            //        if (pos == DomPosition.NONE) {
1386:            //            UIManager.getLookAndFeel().provideErrorFeedback(component);
1387:            //
1388:            //            return;
1389:            //        }
1390:            //
1391:            ////        component.getDocument().insertString(this, pos, content);
1392:            ////        component.getDocument().insertString(pos, content);
1393:            //        component.getWebForm().getDomDocument().insertString(pos, content);
1394:            //    }
1395:
1396:            // XXX Moved to designer/jsf/../DomDocumentIpmpl.
1397:            /**
1398:             * @todo Check deletion back to first char in <body> !
1399:             * @todo Refactor document mutation into the document class
1400:             * @todo Check read-only state etc
1401:             */
1402:            public boolean removeNextChar() {
1403:                // TODO - compute previous visual position, decide if it's
1404:                //        //    isWithinEditableRegion(Position pos) 
1405:                //        // and if so, set the range to it and delete the range.
1406:                //        if (hasSelection()) {
1407:                //            removeSelection();
1408:                //
1409:                //            return true;
1410:                //        }
1411:                //
1412:                ////        Document doc = component.getDocument();
1413:                ////        Position mark = range.getMark();
1414:                //        DomPosition mark = range.getMark();
1415:                ////        Position dot = ModelViewMapper.computeArrowRight(doc.getWebForm(), mark);
1416:                ////        Position dot = ModelViewMapper.computeArrowRight(component.getWebForm(), mark);
1417:                //        DomPosition dot = ModelViewMapper.computeArrowRight(component.getWebForm(), mark);
1418:                //
1419:                ////        if ((dot == Position.NONE) || !isWithinEditableRegion(dot)) {
1420:                //        if ((dot == DomPosition.NONE) || !isWithinEditableRegion(dot)) {
1421:                //            UIManager.getLookAndFeel().provideErrorFeedback(component); // beep
1422:                //
1423:                //            return false;
1424:                //        }
1425:                //
1426:                //        range.setRange(dot.getNode(), dot.getOffset(), mark.getNode(), mark.getOffset());
1427:                ////        range.deleteContents();
1428:                //        removeSelection();
1429:                //
1430:                //        return true;
1431:                WebForm webForm = component.getWebForm();
1432:                return webForm.getDomDocument().deleteNextChar(webForm, range);
1433:            }
1434:
1435:            /**
1436:             * @todo Check deletion back to first char in <body> !
1437:             * @todo Refactor document mutation into the document class
1438:             * @todo Check read-only state etc
1439:             */
1440:            public boolean removePreviousChar() {
1441:                // TODO - compute previous visual position, decide if it's
1442:                //        //    isWithinEditableRegion(Position pos) 
1443:                //        // and if so, set the range to it and delete the range.
1444:                //        if (hasSelection()) {
1445:                //            removeSelection();
1446:                //
1447:                //            return true;
1448:                //        }
1449:                //
1450:                ////        Document doc = component.getDocument();
1451:                ////        Position mark = range.getMark();
1452:                //        DomPosition mark = range.getMark();
1453:                ////        Position dot = ModelViewMapper.computeArrowLeft(doc.getWebForm(), mark);
1454:                ////        Position dot = ModelViewMapper.computeArrowLeft(component.getWebForm(), mark);
1455:                //        DomPosition dot = ModelViewMapper.computeArrowLeft(component.getWebForm(), mark);
1456:                //
1457:                ////        if ((dot == Position.NONE) || !isWithinEditableRegion(dot)) {
1458:                //        if ((dot == DomPosition.NONE) || !isWithinEditableRegion(dot)) {
1459:                //            UIManager.getLookAndFeel().provideErrorFeedback(component); // beep
1460:                //
1461:                //            return false;
1462:                //        }
1463:                //
1464:                //        range.setRange(dot.getNode(), dot.getOffset(), mark.getNode(), mark.getOffset());
1465:                //
1466:                //        // XXX DEBUGGING ONLY
1467:                //        /*
1468:                //        Element element = doc.getBody();
1469:                //        if (element != null) {
1470:                //            System.out.println("BEFORE DELETION: " + org.netbeans.modules.visualweb.css2.FacesSupport.getHtmlStream(element));
1471:                //        }
1472:                //        */
1473:                ////        range.deleteContents();
1474:                //        removeSelection();
1475:                //
1476:                //        // XXX DEBUGGING ONLY
1477:                //
1478:                //        /*
1479:                //        if (element != null) {
1480:                //            System.out.println("BEFORE DELETION: " + org.netbeans.modules.visualweb.css2.FacesSupport.getHtmlStream(element));
1481:                //        }
1482:                //        */
1483:                //        return true;
1484:                WebForm webForm = component.getWebForm();
1485:                return webForm.getDomDocument().deletePreviousChar(webForm,
1486:                        range);
1487:            }
1488:
1489:            boolean replaceSelection(String content) {
1490:                // XXX Moved to DomDocumentImpl.
1491:                /*
1492:                if (range.isReadOnlyRegion()) {
1493:                    UIManager.getLookAndFeel().provideErrorFeedback(component);
1494:                    return;
1495:                }
1496:                 */
1497:                //        if (hasSelection()) {
1498:                //            removeSelection();
1499:                //        }
1500:                //
1501:                ////        Position pos = getDot();
1502:                //        DomPosition pos = getDot();
1503:                //
1504:                ////        if (editor == null) {
1505:                //        if (!component.getWebForm().isInlineEditing()) {
1506:                ////            assert (pos == Position.NONE) || !pos.isRendered();
1507:                ////            if (pos != Position.NONE && MarkupService.isRenderedNode(pos.getNode())) {
1508:                //            if (pos != DomPosition.NONE && MarkupService.isRenderedNode(pos.getNode())) {
1509:                //                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
1510:                //                        new IllegalStateException("Node is expected to be not rendered, node=" + pos.getNode())); // NOI18N
1511:                //                return false;
1512:                //            }
1513:                //        } // else: Stay in the DocumentFragment; don't jump to the source DOM (there is none)
1514:                //
1515:                ////        if (pos == Position.NONE) {
1516:                //        if (pos == DomPosition.NONE) {
1517:                ////            UIManager.getLookAndFeel().provideErrorFeedback(this);
1518:                //            return false;
1519:                //        }
1520:                //
1521:                ////        component.getDocument().insertString(this, pos, content);
1522:                ////        component.getDocument().insertString(pos, content);
1523:                //        return component.getWebForm().getDomDocument().insertString(pos, content);
1524:                return component.getWebForm().getDomDocument().insertString(
1525:                        component.getWebForm(), range, content);
1526:            }
1527:
1528:            // XXX Moved to WebForm.
1529:            //    /** Return true iff the position is within the editable portion of the document. */
1530:            ////    public boolean isWithinEditableRegion(Position pos) {
1531:            //    public boolean isWithinEditableRegion(DomPosition pos) {
1532:            ////        WebForm webform = component.getDocument().getWebForm();
1533:            //        WebForm webform = component.getWebForm();
1534:            //
1535:            //        InlineEditor editor = webform.getManager().getInlineEditor();
1536:            //
1537:            //        if (editor != null) {
1538:            ////            Position editableRegionStart = editor.getBegin();
1539:            ////            Position editableRegionEnd = editor.getEnd();
1540:            //            DomPosition editableRegionStart = editor.getBegin();
1541:            //            DomPosition editableRegionEnd = editor.getEnd();
1542:            //
1543:            ////            assert editableRegionStart != Position.NONE;
1544:            ////            assert editableRegionEnd != Position.NONE;
1545:            //
1546:            //            return pos.isLaterThan(editableRegionStart) && pos.isEarlierThan(editableRegionEnd);
1547:            //        }
1548:            //
1549:            ////        assert !pos.isRendered() : pos;
1550:            //        if (MarkupService.isRenderedNode(pos.getNode())) {
1551:            //            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
1552:            //                    new IllegalStateException("Node is expected to be not rendered, node=" + pos.getNode()));
1553:            //        }
1554:            //        
1555:            //
1556:            //        if (!webform.isGridMode()) {
1557:            //            // In page flow mode, all regions are editable. Note - this
1558:            //            // may not be true when I start allowing sub-grids
1559:            //            return true;
1560:            //        }
1561:            //
1562:            //        CssBox box = webform.getManager().getInsertModeBox();
1563:            //
1564:            //        if (box == null) {
1565:            //            return false;
1566:            //        }
1567:            //
1568:            //        //Position editableRegionStart = Position.create(box.getSourceElement());
1569:            //        //Position editableRegionEnd = new Position(null, editableRegionStart.getNode(),
1570:            //        //                                               editableRegionStart.getOffset()+1);
1571:            //        Element componentRootElement = CssBox.getElementForComponentRootCssBox(box);
1572:            ////        Position editableRegionStart =
1573:            ////            new Position(box.getDesignBean().getElement(), 0, Bias.FORWARD);
1574:            //                // XXX Possible NPE?
1575:            ////                new Position(CssBox.getMarkupDesignBeanForCssBox(box).getElement(), 0, Bias.FORWARD);
1576:            ////                new Position(WebForm.getDomProviderService().getSourceElement(componentRootElement), 0, Bias.FORWARD);
1577:            ////        DomPosition editableRegionStart = DesignerPaneBase.createDomPosition(WebForm.getDomProviderService().getSourceElement(componentRootElement), 0, Bias.FORWARD);
1578:            //        DomPosition editableRegionStart = component.getWebForm().createDomPosition(WebForm.getDomProviderService().getSourceElement(componentRootElement), 0, Bias.FORWARD);
1579:            //        
1580:            ////        Position editableRegionEnd =
1581:            ////            new Position(editableRegionStart.getNode(),
1582:            ////                editableRegionStart.getNode().getChildNodes().getLength(), Bias.BACKWARD);
1583:            ////        DomPosition editableRegionEnd = DesignerPaneBase.createDomPosition(editableRegionStart.getNode(), editableRegionStart.getNode().getChildNodes().getLength(), Bias.BACKWARD);
1584:            //        DomPosition editableRegionEnd = component.getWebForm().createDomPosition(editableRegionStart.getNode(), editableRegionStart.getNode().getChildNodes().getLength(), Bias.BACKWARD);
1585:            //
1586:            //        return pos.isLaterThan(editableRegionStart) && pos.isEarlierThan(editableRegionEnd);
1587:            //    }
1588:
1589:            /** Return true iff the caret is within a read only region */
1590:            public boolean isReadOnlyRegion() {
1591:                return (range != null) ? range.isReadOnlyRegion() : false;
1592:            }
1593:
1594:            class SafeScroller implements  Runnable {
1595:                Rectangle r;
1596:
1597:                SafeScroller(Rectangle r) {
1598:                    this .r = r;
1599:                }
1600:
1601:                public void run() {
1602:                    if (component != null) {
1603:                        component.scrollRectToVisible(r);
1604:                    }
1605:                }
1606:            }
1607:
1608:            class Handler implements  ActionListener, ClipboardOwner,
1609:                    DomDocumentListener {
1610:                // --- ActionListener methods ----------------------------------
1611:
1612:                /**
1613:                 * Invoked when the blink timer fires. This is called asynchronously. The simply changes the
1614:                 * visibility and repaints the rectangle that last bounded the caret.
1615:                 *
1616:                 * @param e
1617:                 *            the action event
1618:                 */
1619:                public void actionPerformed(ActionEvent e) {
1620:                    if (((width == 0) || (height == 0)) && isVisible()) {
1621:                        // setVisible(true) will cause a scroll, only do this if the
1622:                        // new location is really valid.
1623:                        if (component != null) {
1624:                            DesignerPaneBaseUI mapper = component.getUI();
1625:
1626:                            if (range != null) {
1627:                                //                        Position dot = range.getDot();
1628:                                DomPosition dot = range.getDot();
1629:                                //                        Rectangle r = mapper.modelToView(/*component,*/ dot);
1630:                                //                        WebForm webForm = component.getDocument().getWebForm();
1631:                                WebForm webForm = component.getWebForm();
1632:
1633:                                Rectangle r = webForm.modelToView(dot);
1634:
1635:                                if ((r != null) && (r.width != 0)
1636:                                        && (r.height != 0)) {
1637:                                    damage(r);
1638:                                }
1639:                            }
1640:                        }
1641:                    }
1642:
1643:                    flashOn = !flashOn;
1644:                    repaint();
1645:                }
1646:
1647:                //
1648:                // ClipboardOwner
1649:                //
1650:
1651:                /**
1652:                 * Toggles the visibility of the selection when ownership is lost.
1653:                 */
1654:                public void lostOwnership(Clipboard clipboard,
1655:                        Transferable contents) {
1656:                    if (ownsSelection) {
1657:                        ownsSelection = false;
1658:
1659:                        if ((component != null) && !component.hasFocus()) {
1660:                            setSelectionVisible(false);
1661:                        }
1662:                    }
1663:                }
1664:
1665:                //////////////////////////
1666:                // DomDocumentListener >>>
1667:
1668:                public void insertUpdate(DomDocumentEvent evt) {
1669:                    DesignerCaret.this .setDot(evt.getDomPosition());
1670:                }
1671:
1672:                public void componentMoved(DomDocumentEvent evt) {
1673:                    // XXX 126234 Possible NPE.
1674:                    if (component == null) {
1675:                        return;
1676:                    }
1677:
1678:                    if (component.hasCaret()) {
1679:                        DomPosition pos = ModelViewMapper
1680:                                .getFirstDocumentPosition(component
1681:                                        .getWebForm(), false);
1682:                        //                webform.getPane().getCaret().setDot(pos);
1683:                        //                webForm.getPane().setCaretDot(pos);
1684:                        setDot(pos);
1685:                    }
1686:                }
1687:
1688:                public void componentsMoved(DomDocumentEvent evt) {
1689:                    // XXX #91531 User didn't want to have this kind of autoscroll behavior.
1690:                    //            final Rectangle rect = boundingBox;
1691:                    //            // #6331237 NPE.
1692:                    //            if(rect != null) {
1693:                    //                SwingUtilities.invokeLater(new Runnable() {
1694:                    //                    public void run() {
1695:                    //                        editor.scrollRectToVisible(rect);
1696:                    //                    }
1697:                    //                });
1698:                    //            }
1699:                }
1700:
1701:                public void componentMovedTo(DomDocumentEvent evt) {
1702:                    // XXX For not nothing here.
1703:                }
1704:                // DomDocumentListener <<<
1705:                //////////////////////////
1706:            }
1707:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.