Source Code Cross Referenced for SelectionManager.java in  » IDE-Netbeans » visualweb.api.designer » org » netbeans » modules » visualweb » designer » 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.designer 
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.designer;
0043:
0044:        import java.awt.BasicStroke;
0045:        import java.awt.Cursor;
0046:        import java.awt.Dimension;
0047:        import java.awt.FontMetrics;
0048:        import java.awt.Graphics2D;
0049:        import java.awt.Image;
0050:        import java.awt.Point;
0051:        import java.awt.Rectangle;
0052:        import java.awt.Stroke;
0053:        import java.awt.event.ActionEvent;
0054:        import java.awt.event.ActionListener;
0055:        import java.awt.geom.AffineTransform;
0056:        import java.util.ArrayList;
0057:        import java.util.HashSet;
0058:        import java.util.Iterator;
0059:        import java.util.List;
0060:        import java.util.Set;
0061:        import javax.swing.JViewport;
0062:        import javax.swing.SwingUtilities;
0063:        import javax.swing.Timer;
0064:        import org.netbeans.modules.visualweb.api.designer.Designer;
0065:        import org.netbeans.modules.visualweb.api.designer.Designer.Box;
0066:        import org.netbeans.modules.visualweb.api.designer.Designer.DesignerEvent;
0067:
0068:        import org.netbeans.modules.visualweb.api.designer.DomProviderService.ResizeConstraint;
0069:        import org.netbeans.modules.visualweb.api.designer.DomProvider.DomPosition;
0070:        import org.netbeans.modules.visualweb.api.designer.DomProvider.DomPosition.Bias;
0071:        import org.netbeans.modules.visualweb.css2.BoxType;
0072:        import org.netbeans.modules.visualweb.css2.CssBox;
0073:        import org.netbeans.modules.visualweb.css2.ExternalDocumentBox;
0074:        import org.netbeans.modules.visualweb.css2.ModelViewMapper;
0075:        import org.netbeans.modules.visualweb.css2.PageBox;
0076:        import org.netbeans.modules.visualweb.designer.html.HtmlTag;
0077:
0078:        import org.openide.ErrorManager;
0079:        import org.openide.nodes.Node;
0080:
0081:        import org.w3c.dom.Element;
0082:
0083:        /**
0084:         * This class is the central point for handling selections, mouse interactions,
0085:         * keyboard interactions, etc., with the page editor / the WYSIWYG designer.
0086:         * It for example listens to mouse events and decides whether this translates
0087:         * into a change in selected components, or a drag of a component, etc.
0088:         *
0089:         * <p>
0090:         * This class manages selections in the page designer.
0091:         *
0092:         * <p>
0093:         * @todo Rename this class to "InteractionManager", formalize the remaining interactions
0094:         *  that aren't using the Interaction interface yet (like InlineEditors, selection cycling),
0095:         *  pull the selection-set specific code into a separate SelectionHandler (set & painter),
0096:         *  pull the utility methods into the Utilities class.
0097:         * @todo Handle getComponentBounds replacement to getComponentRectangles
0098:         *   later! And speed up caching of component rectangle list!
0099:         * @todo Get rid of all traces of "View" in the selection handling!
0100:         * @todo Remove the inlineEditor (finish it) if the user deletes a component! Even via the
0101:         *    app outline! (perhaps only if it's the component we're inline editing or some child of it)
0102:         * <p>
0103:         *
0104:         * @author  Tor Norbye
0105:         */
0106:        public class SelectionManager {
0107:            // The source file is organized into groups of related functionality:
0108:            // mouse handling, painting, selection manipulation, etc.
0109:            // Please keep this in mind when editing the file - don't just add
0110:            // methods at the end of the file for example.
0111:            private static final int NODE_REFRESH_DELAY = 300; // ms
0112:
0113:            // Dreamweaver-like hierarchy bar
0114:            static final boolean PAINT_SELECTION_HIERARCHY = System
0115:                    .getProperty("designer.paintSelHierarchy") != null; // NOI18N
0116:
0117:            /** Width/height of the selection handles - these are drawn at
0118:             * all four corners and the middle of all four edges */
0119:            private static final int BARSIZE = 5;
0120:            private static final int SELECTIONVIEW_LEFT = 1;
0121:            private BasicStroke selStroke;
0122:            private final WebForm webform;
0123:            //    private DocumentComp documentComponent = null;
0124:
0125:            //    /** Set of selected objects. Contains FormObjects only. */
0126:            //    private Set<FormObject> selected = new HashSet<FormObject>();
0127:
0128:            //    private final Set<SelectedComponent> selectedComponents = new HashSet<SelectedComponent>();
0129:            private final List<SelectedComponent> selectedComponents = new ArrayList<SelectedComponent>();
0130:
0131:            //    /** The "primary" selected object - e.g. you may have selected
0132:            //        10 components, but the most recently clicked one is the
0133:            //        primary item. Right clicking on an item makes it the primary. */
0134:            //    private MarkupDesignBean primary = null;
0135:            //    /** Previous selection, in case new selected item is an ancestor
0136:            //     * of the previously selected item
0137:            //     */
0138:            //    private MarkupDesignBean leaf = null;
0139:            /** The "primary" selected object - e.g. you may have selected
0140:                10 components, but the most recently clicked one is the
0141:                primary item. Right clicking on an item makes it the primary. */
0142:            private Element primary = null;
0143:            /** Previous selection, in case new selected item is an ancestor
0144:             * of the previously selected item
0145:             */
0146:            private Element leaf = null;
0147:
0148:            private AffineTransform transform = new AffineTransform();
0149:            private boolean paintBeanIcon = false;
0150:            int selectionViewPos = Integer.MAX_VALUE;
0151:            private Timer refreshTimer;
0152:
0153:            //    private Node[] prevNodes = null;
0154:
0155:            //    /** When set, ignore selection requests */
0156:            //    private boolean ignoreSelection;
0157:
0158:            SelectionManager(WebForm webform) {
0159:                this .webform = webform;
0160:
0161:                webform.getPane();
0162:            }
0163:
0164:            /** Clear out the selection - after this has run,
0165:             * no components are selected
0166:             * @param update If true, update property sheets etc. to reflect
0167:             *  the new selection.
0168:             */
0169:            public void clearSelection(boolean update) {
0170:                selectionViewPos = Integer.MAX_VALUE;
0171:                leaf = null;
0172:
0173:                //        if ((selected == null) || (selected.size() == 0)) {
0174:                if (selectedComponents.isEmpty()) {
0175:                    if (update) { // XXX why are we doing this? It should already be correct
0176:                    //                updateSelection();
0177:                        updateNodes();
0178:
0179:                        // is a repaint needed?
0180:                    }
0181:
0182:                    return;
0183:                }
0184:
0185:                //        selected = new HashSet<FormObject>();
0186:                selectedComponents.clear();
0187:
0188:                primary = null;
0189:
0190:                if (update) {
0191:                    //            updateSelection();
0192:                    updateNodes();
0193:                    //            webform.getTopComponent().disableCutCopyDelete(); // not true for paste
0194:                    //            webform.tcDisableCutCopyDelete();
0195:                    webform.getPane().repaint();
0196:                }
0197:            }
0198:
0199:            /** XXX Altered copy of clear selection, to immediatelly update the nodes.
0200:             * FIXME Get rid of the delayed node updates. */
0201:            public void clearSelectionImmediate() {
0202:                selectionViewPos = Integer.MAX_VALUE;
0203:                leaf = null;
0204:
0205:                //        if ((selected == null) || (selected.size() == 0)) {
0206:                if (selectedComponents.isEmpty()) {
0207:                    // XXX why are we doing this? It should already be correct
0208:                    updateSelectionImmediate();
0209:
0210:                    // is a repaint needed?
0211:                    return;
0212:                }
0213:
0214:                //        selected = new HashSet<FormObject>();
0215:                selectedComponents.clear();
0216:                primary = null;
0217:
0218:                updateSelectionImmediate();
0219:                //        webform.getTopComponent().disableCutCopyDelete(); // not true for paste
0220:                //        webform.tcDisableCutCopyDelete();
0221:                webform.getPane().repaint();
0222:            }
0223:
0224:            //    /** Update IDE to visually reflect the current selection */
0225:            //    public void updateSelection() {
0226:            //        updateNodes();
0227:            //        
0228:            ////        updateSelectionInOldOutline();
0229:            //    }
0230:
0231:            public void updateSelectionImmediate() {
0232:                updateNodesImmediate();
0233:
0234:                //        updateSelectionInOldOutline();
0235:            }
0236:
0237:            //    // XXX Get rid of this method after getting rid of old outline.
0238:            //    private void updateSelectionInOldOutline() {
0239:            //        // Sync document outline view
0240:            //        if ((selected == null) || (selected.size() == 0)) {
0241:            ////            OutlineTopComp.getInstance().selectBeans(null);
0242:            //        } else {
0243:            //            DesignBean[] lbs = new DesignBean[selected.size()];
0244:            //            Iterator it = selected.iterator();
0245:            //            int index = 0;
0246:            //
0247:            //            while (it.hasNext()) {
0248:            //                FormObject fob = (FormObject)it.next();
0249:            //                lbs[index++] = fob.component;
0250:            //            }
0251:            //
0252:            //            try {
0253:            //                ignoreSelection = true;
0254:            ////                OutlineTopComp.getInstance().selectBeans(lbs);
0255:            //            } finally {
0256:            //                ignoreSelection = false;
0257:            //            }
0258:            //        }
0259:            //
0260:            //        // TODO: Move enable/disable cut,copy,delete into this method!
0261:            //    }
0262:
0263:            /** Synchronize the selection with the model. This should be called
0264:             * when DesignBeans may have changed underneath us, for example because
0265:             * the user modified the backing file, and it's reparsed by insync.
0266:             * At this point the DesignBeans we're pointing to in our selection set
0267:             * may be stale, so for each selected bean check if it's still live
0268:             * and if not, find its new representative if any.
0269:             * @param update If true, update property sheets etc. to reflect
0270:             *  the new selection.
0271:             */
0272:            public void syncSelection(boolean update) {
0273:                //        if ((selected == null) || (selected.size() == 0)) {
0274:                if (selectedComponents.isEmpty()) {
0275:                    return;
0276:                }
0277:
0278:                leaf = null;
0279:                selectionViewPos = Integer.MAX_VALUE;
0280:                primary = null;
0281:
0282:                //        LiveUnit unit = webform.getModel().getLiveUnit();
0283:
0284:                //        Iterator it = selected.iterator();
0285:                //        List<FormObject> remove = new ArrayList<FormObject>();
0286:
0287:                //        while (it.hasNext()) {
0288:                //            FormObject fo = (FormObject)it.next();
0289:                //        for (FormObject fo : selected) {
0290:                //
0291:                //            if (fo.component != null) {
0292:                //                // Gotta find the new DesignBean for bean fo.component
0293:                //                MarkupDesignBean oldBean = fo.component;
0294:                //                // XXX Big architectural flaw, the model itself is not consistent (doesn't fire changes about itself),
0295:                //                // one needs to get 'newer' beans from the 'old' ones.
0296:                //                // TODO find out better solution.
0297:                ////                fo.component = (MarkupDesignBean)unit.getBeanEquivalentTo(oldBean);
0298:                //                fo.component = webform.getMarkupDesignBeanEquivalentTo(oldBean);
0299:                //
0300:                //                if (fo.component == null) {
0301:                //                    remove.add(fo);
0302:                //                }
0303:                //            }
0304:                //        }
0305:
0306:                List<SelectedComponent> remove = new ArrayList<SelectedComponent>();
0307:                for (SelectedComponent sc : selectedComponents) {
0308:                    if (sc.componentRootElement != null) {
0309:                        // Gotta find the new DesignBean for bean fo.component
0310:                        Element oldComponentRootElement = sc.componentRootElement;
0311:                        // XXX Big architectural flaw, the model itself is not consistent (doesn't fire changes about itself),
0312:                        // one needs to get 'newer' beans from the 'old' ones.
0313:                        // TODO find out better solution.
0314:                        //                fo.component = (MarkupDesignBean)unit.getBeanEquivalentTo(oldBean);
0315:                        sc.componentRootElement = webform
0316:                                .getComponentRootElementEquivalentTo(oldComponentRootElement);
0317:
0318:                        if (sc.componentRootElement == null) {
0319:                            remove.add(sc);
0320:                        }
0321:                    }
0322:                }
0323:
0324:                // Remove the items in the selection hashmap that we couldn't find
0325:                // a new DesignBean for. Not done during the iteration since it confuses
0326:                // the iterator.
0327:                //        it = remove.iterator();
0328:                //
0329:                //        while (it.hasNext()) {
0330:                //        for (FormObject fo : remove) {
0331:                ////            FormObject fo = (FormObject)it.next();
0332:                //            selected.remove(fo);
0333:                //        }
0334:                for (SelectedComponent sc : remove) {
0335:                    selectedComponents.remove(sc);
0336:                }
0337:
0338:                webform.getPane().repaint(); // XXX should this only be done for update=true?
0339:
0340:                if (update) {
0341:                    //            updateSelection();
0342:                    updateNodes();
0343:
0344:                    // XXX why are we disabling cut copy paste? That depends on the
0345:                    // selection, doesn't it?
0346:                    //            webform.getTopComponent().disableCutCopyDelete(); // not true for paste
0347:                    //            webform.tcDisableCutCopyDelete();
0348:                }
0349:            }
0350:
0351:            //    /** After a sync, try to position the caret close to where it was,
0352:            //     * and if not, hide the caret
0353:            //     * Hmmmmmm shouldn't hide the caret in flow mode!
0354:            //     */
0355:            //    public void syncCaret() {
0356:            //        // Fix the caret
0357:            //        DesignerCaret dc = webform.getPane().getCaret();
0358:            //
0359:            //        if ((dc != null) && (dc.getDot() != Position.NONE)) {
0360:            //            /*
0361:            //            LiveUnit unit = webform.getModel().getLiveUnit();
0362:            //            org.w3c.dom.Node n = dc.getDot().getNode();
0363:            //            Element newElement = null;
0364:            //            while (n != null) {
0365:            //                if (n instanceof XhtmlElement) {
0366:            //                    XhtmlElement e = (XhtmlElement)n;
0367:            //                    if (e.getDesignBean() != null) {
0368:            //                        DesignBean newBean = unit.getBeanByName(e.getDesignBean().getInstanceName());
0369:            //                        if (newBean != null) {
0370:            //                            newElement = FacesSupport.getElement(newBean);
0371:            //                            break;
0372:            //                        }
0373:            //                    }
0374:            //                }
0375:            //                n = n.getParentNode();
0376:            //            }
0377:            //            if (newElement != null) {
0378:            //                Position newPos = webform.getMapper().
0379:            //                // Can't do this because this will update the range
0380:            //                // in two steps, and as soon as one of the end points
0381:            //                // is in a different
0382:            //                //getPane().setCaretPosition(newPos);
0383:            //
0384:            //                dc = getPane().getPaneUI().createCaret();
0385:            //                getPane().setCaret(dc);
0386:            //                getPane().setCaretPosition(newPos);
0387:            //            } else if (!webform.getDocument().isGridMode()) {
0388:            //                getPane().showCaretAtBeginning();
0389:            //            } else {
0390:            //                getPane().setCaret(null);
0391:            //            }
0392:            //             */
0393:            //
0394:            //            // DONE IN PAGEBOX.layout!
0395:            //            //            dc.setDot(Position.NONE); // Ensure range gets detached since we could be in a new DOM
0396:            //            //            getPane().showCaretAtBeginning();
0397:            //        }
0398:            //    }
0399:
0400:            /** Add the given view/component to the selection.
0401:             * @param update If true, update property sheets etc. to reflect
0402:             *  the new selection.
0403:             */
0404:            public void addSelected(
0405:                    /*MarkupDesignBean component*/Element componentRootElement,
0406:                    boolean update) {
0407:                //        boolean wasEmpty = ((selected == null) || (selected.size() == 0));
0408:                boolean wasEmpty = selectedComponents.isEmpty();
0409:                //        FormObject fo = new FormObject();
0410:                //        fo.component = component;
0411:                SelectedComponent sc = new SelectedComponent();
0412:                sc.componentRootElement = componentRootElement;
0413:
0414:                //        primary = component;
0415:                primary = sc.componentRootElement;
0416:
0417:                //        if (fo.component == null) {
0418:                //            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
0419:                //                    new NullPointerException("MarkupDesignBean is null!")); // NOI18N
0420:                //        }
0421:                if (sc.componentRootElement == null) {
0422:                    ErrorManager.getDefault().notify(
0423:                            ErrorManager.INFORMATIONAL,
0424:                            new NullPointerException(
0425:                                    "ComponentRootElement is null!")); // NOI18N
0426:                }
0427:
0428:                //        fo.resizeConstraints = Resizer.getResizeConstraints(webform, component);
0429:                sc.resizeConstraints = Resizer.getResizeConstraints(webform,
0430:                        componentRootElement);
0431:
0432:                //        selected.add(fo);
0433:                //        leaf = fo.component;
0434:                if (!selectedComponents.contains(sc)) {
0435:                    selectedComponents.add(sc);
0436:                }
0437:                //        leaf = component;
0438:                leaf = sc.componentRootElement;
0439:
0440:                if (update) {
0441:                    //            updateSelection();
0442:                    updateNodes();
0443:                }
0444:
0445:                if (wasEmpty) {
0446:                    // Enable Cut, Copy, Delete
0447:                    //            webform.getTopComponent().enableCutCopyDelete();
0448:                    //            webform.tcEnableCutCopyDelete();
0449:                }
0450:            }
0451:
0452:            /** Set the selection to the given component.
0453:             * Attempt to preserve the current component as a leaf, provided
0454:             * the new component to be selected is an ancestor of the current leaf.
0455:             */
0456:            public void setSelected(
0457:                    /*MarkupDesignBean component*/Element componentRootElement,
0458:                    boolean update) {
0459:                //        MarkupDesignBean oldLeaf = leaf;
0460:                //        primary = component;
0461:                Element oldLeaf = leaf;
0462:                primary = componentRootElement;
0463:
0464:                clearSelection(false);
0465:                //        addSelected(component, update);
0466:                addSelected(componentRootElement, update);
0467:
0468:                // Is the new component an ancestor of the old leaf?
0469:                //        MarkupDesignBean component = WebForm.getDomProviderService().getMarkupDesignBeanForElement(componentRootElement);
0470:                if (PAINT_SELECTION_HIERARCHY) {
0471:                    //            DesignBean curr = oldLeaf;
0472:                    //            DesignBean curr = WebForm.getDomProviderService().getMarkupDesignBeanForElement(oldLeaf);
0473:                    Element curr = oldLeaf;
0474:
0475:                    while (curr != null) {
0476:                        //                if (component == curr) {
0477:                        if (componentRootElement == curr) {
0478:                            // Yes!
0479:                            leaf = oldLeaf;
0480:
0481:                            return;
0482:                        }
0483:
0484:                        //                curr = curr.getBeanParent();
0485:                        curr = webform.getDomProviderService()
0486:                                .getParentComponent(curr);
0487:                    }
0488:
0489:                    // No. This is the new leaf.
0490:                    //            assert leaf == component;
0491:                    //            if (leaf != WebForm.getDomProviderService().getComponentRootElementForMarkupDesignBean(component)) {
0492:                    if (leaf != componentRootElement) {
0493:                        ErrorManager.getDefault().notify(
0494:                                ErrorManager.INFORMATIONAL,
0495:                                new IllegalStateException(
0496:                                        "Leaf is different from expected, leaf="
0497:                                                + leaf + ", expected="
0498:                                                + componentRootElement)); // NOI18N
0499:                    }
0500:                }
0501:            }
0502:
0503:            /** Remove the given view/component from the selection.
0504:             * @param update If true, update property sheets etc. to reflect
0505:             *  the new selection.
0506:             */
0507:            public void removeSelected(
0508:                    /*MarkupDesignBean component*/Element componentRootElement,
0509:                    boolean update) {
0510:                //        boolean wasEmpty = ((selected == null) || (selected.size() == 0));
0511:                boolean wasEmpty = selectedComponents.isEmpty();
0512:
0513:                if (!wasEmpty) {
0514:                    //            Iterator it = selected.iterator();
0515:                    //
0516:                    //            while (it.hasNext()) {
0517:                    //                FormObject fo = (FormObject)it.next();
0518:                    //            for (FormObject fo : selected) {
0519:                    //
0520:                    //                if (fo.component == component) {
0521:                    //                    selected.remove(fo);
0522:                    //
0523:                    //                    break;
0524:                    //                }
0525:                    //            }
0526:                    for (SelectedComponent sc : selectedComponents) {
0527:                        if (sc.componentRootElement == componentRootElement) {
0528:                            selectedComponents.remove(sc);
0529:                            break;
0530:                        }
0531:                    }
0532:                }
0533:
0534:                //        if (component == primary) {
0535:                if (componentRootElement == primary) {
0536:                    primary = null;
0537:
0538:                    //            if (selected.size() > 1) {
0539:                    if (selectedComponents.size() > 1) {
0540:                        pickPrimary();
0541:                    }
0542:                }
0543:
0544:                if (update) {
0545:                    //            updateSelection();
0546:                    updateNodes();
0547:                }
0548:
0549:                //        if (wasEmpty && (selected.size() == 0)) { // removed last component
0550:                if (wasEmpty && selectedComponents.isEmpty()) { // removed last component
0551:                //            webform.getTopComponent().disableCutCopyDelete(); // not true for paste
0552:                //            webform.tcDisableCutCopyDelete();
0553:                }
0554:            }
0555:
0556:            /** Return true iff the given view is in the set of selected views.
0557:                @param component The view to check. May not be null.
0558:                @return true iff the component is currently selected.
0559:             */
0560:            public boolean isSelected(
0561:                    /*DesignBean component*/Element componentRootElement) {
0562:                //        if ((selected == null) || (selected.size() == 0)) {
0563:                if (componentRootElement == null
0564:                        || selectedComponents.isEmpty()) {
0565:                    return false;
0566:                }
0567:
0568:                //        Iterator it = selected.iterator();
0569:                //
0570:                //        while (it.hasNext()) {
0571:                //            FormObject fo = (FormObject)it.next();
0572:                //        for (FormObject fo : selected) {
0573:                //            if (fo.component == component) {
0574:                //                return true;
0575:                //            }
0576:                //        }
0577:                for (SelectedComponent sc : selectedComponents) {
0578:                    if (sc.componentRootElement == componentRootElement) {
0579:                        return true;
0580:                    }
0581:                }
0582:
0583:                return false;
0584:            }
0585:
0586:            /** Return true iff the given view is in the set of selected views
0587:             * or is a child of a selected view.
0588:             * @param box The box to check. May not be null.
0589:             * @return true iff the box or one of its ancestors is currently selected.
0590:             */
0591:            public boolean isBelowSelected(CssBox box) {
0592:                if (box.getBoxType() == BoxType.TEXT) {
0593:                    box = box.getParent();
0594:                }
0595:
0596:                //        if ((box.getDesignBean() != null) && isSelected(box.getDesignBean())) {
0597:                //        MarkupDesignBean markupDesignBean = CssBox.getMarkupDesignBeanForCssBox(box);
0598:                //        if ((markupDesignBean != null) && isSelected(markupDesignBean)) {
0599:                Element componentRootElement = CssBox
0600:                        .getElementForComponentRootCssBox(box);
0601:                if (isSelected(componentRootElement)) {
0602:                    return true;
0603:                }
0604:
0605:                return getSelectedAncestor(box) != null;
0606:            }
0607:
0608:            /** Check to see if any ancestors of the given view (or the view
0609:             * itself) is in the selection set, and if so, return it. This will
0610:             * return the closest (e.g. furthest down the element tree) match.
0611:             *
0612:             *   @param box The box to check. May not be null.
0613:             *   @return The selected view or ancestor of the box
0614:             */
0615:            public CssBox getSelectedAncestor(CssBox box) {
0616:                if (box != null) {
0617:                    // Skip the immediate box
0618:                    box = box.getParent();
0619:                }
0620:
0621:                while (box != null) {
0622:                    //            if ((box.getDesignBean() != null) && isSelected(box.getDesignBean())) {
0623:                    //            MarkupDesignBean markupDesignBean = CssBox.getMarkupDesignBeanForCssBox(box);
0624:                    //            if ((markupDesignBean != null) && isSelected(markupDesignBean)) {
0625:                    Element componentRootElement = CssBox
0626:                            .getElementForComponentRootCssBox(box);
0627:                    if (isSelected(componentRootElement)) {
0628:                        return box;
0629:                    }
0630:
0631:                    box = box.getParent();
0632:                }
0633:
0634:                return null;
0635:            }
0636:
0637:            /** Return the first container component found in the selection.
0638:             * If no direct selected component is a container, return the first
0639:             * container ancestor for the first selected item.
0640:             */
0641:            public/*DesignBean*/Element getSelectedContainer() {
0642:                //        Iterator it = selected.iterator();
0643:                //
0644:                //        while (it.hasNext()) {
0645:                //            FormObject fo = (FormObject)it.next();
0646:                //        for (FormObject fo : selected) {
0647:                //            DesignBean lb = fo.component;
0648:                //
0649:                //            if (lb.isContainer()) {
0650:                //                return lb;
0651:                //            }
0652:                //        }
0653:                for (SelectedComponent sc : selectedComponents) {
0654:                    //            DesignBean lb = WebForm.getDomProviderService().getMarkupDesignBeanForElement(sc.componentRootElement);
0655:                    //            if (lb.isContainer()) {
0656:                    if (webform.getDomProviderService()
0657:                            .isContainerTypeComponent(sc.componentRootElement)) {
0658:                        //                return lb;
0659:                        return sc.componentRootElement;
0660:                    }
0661:                }
0662:
0663:                //        it = selected.iterator();
0664:                //
0665:                //        while (it.hasNext()) {
0666:                //            FormObject fo = (FormObject)it.next();
0667:                //        for (FormObject fo : selected) {
0668:                //            DesignBean lb = fo.component;
0669:                //
0670:                //            if (lb.getBeanParent() != null) {
0671:                //                return lb.getBeanParent();
0672:                //            }
0673:                //        }
0674:                for (SelectedComponent sc : selectedComponents) {
0675:                    //            DesignBean lb = WebForm.getDomProviderService().getMarkupDesignBeanForElement(sc.componentRootElement);
0676:                    //            if (lb.getBeanParent() != null) {
0677:                    Element parentComponentRootElement = webform
0678:                            .getDomProviderService().getParentComponent(
0679:                                    sc.componentRootElement);
0680:                    if (parentComponentRootElement != null) {
0681:                        //                return lb.getBeanParent();
0682:                        return parentComponentRootElement;
0683:                    }
0684:                }
0685:
0686:                return null;
0687:            }
0688:
0689:            /** Returned the first positioned element in the selection. Gets the component root element (rendered element). */
0690:            Element getPositionElement() {
0691:                //        Iterator it = selected.iterator();
0692:                //
0693:                //        while (it.hasNext()) {
0694:                //            FormObject fo = (FormObject)it.next();
0695:                //        for (FormObject fo : selected) {
0696:                ////            CssBox box = webform.getMapper().findBox(fo.component);
0697:                //            CssBox box = ModelViewMapper.findBox(webform.getPane().getPageBox(), fo.component);
0698:                //
0699:                //            if ((box != null) && box.getBoxType().isPositioned()) {
0700:                ////                return box.getDesignBean().getElement();
0701:                //                // XXX Shouldn't be here the fo.component? See above.
0702:                //                return CssBox.getMarkupDesignBeanForCssBox(box).getElement();
0703:                //            }
0704:                //        }
0705:                for (SelectedComponent sc : selectedComponents) {
0706:                    //            CssBox box = webform.getMapper().findBox(fo.component);
0707:                    CssBox box = ModelViewMapper
0708:                            .findBoxForComponentRootElement(webform.getPane()
0709:                                    .getPageBox(), sc.componentRootElement);
0710:
0711:                    if ((box != null) && box.getBoxType().isPositioned()) {
0712:                        //                return box.getDesignBean().getElement();
0713:                        // XXX Shouldn't be here the fo.component? See above.
0714:                        //                return CssBox.getMarkupDesignBeanForCssBox(box).getElement();
0715:                        return CssBox.getElementForComponentRootCssBox(box);
0716:                    }
0717:                }
0718:
0719:                return null;
0720:            }
0721:
0722:            /** Select all components on the designer surface (except components
0723:             * that are children of other components, and except components that
0724:             * are "special", such as Form/Body/Head/Html, etc.
0725:             */
0726:            public void selectAll() {
0727:                //DesignBean root = webform.getModel().getRootBean();
0728:                //        RaveElement element = webform.getBody();
0729:                Element element = webform.getHtmlBody();
0730:                //        DesignBean root = element.getDesignBean();
0731:                //        DesignBean root = InSyncService.getProvider().getMarkupDesignBeanForElement(element);
0732:                //        DesignBean root = WebForm.getDomProviderService().getMarkupDesignBeanForElement(element);
0733:                //        
0734:                //        if (root == null) {
0735:                //            return;
0736:                //        }
0737:                if (element == null) {
0738:                    return;
0739:                }
0740:
0741:                // XXX #109439 The same components appeared more times in the selection.
0742:                clearSelection(false);
0743:
0744:                Element[] children = webform.getDomProviderService()
0745:                        .getChildComponents(element);
0746:                //        for (int i = 0, n = root.getChildBeanCount(); i < n; i++) {
0747:                //            DesignBean child = root.getChildBean(i);
0748:                for (Element child : children) {
0749:
0750:                    //            if (child instanceof MarkupDesignBean) {
0751:                    //                selectAll((MarkupDesignBean)child);
0752:                    //                selectAll(WebForm.getDomProviderService().getComponentRootElementForMarkupDesignBean((MarkupDesignBean)child));
0753:                    //            }
0754:                    selectAll(child);
0755:                }
0756:
0757:                //        // We should not select the two special <br> components that are added
0758:                //        // to flow-positioned documents: the last break in the form component,
0759:                //        // and the first br in the body component. These are there to ensure that
0760:                //        // there are caret-viable lines in the document.
0761:                //        if (!webform.isGridMode()) {
0762:                ////            if ((root.getChildBeanCount() > 0) &&
0763:                ////                    ((MarkupDesignBean)root.getChildBean(0)).getElement().getTagName().equals(HtmlTag.BR.name)) {
0764:                //            if (children.length > 0 && HtmlTag.BR.name.equals(children[0].getTagName())) {
0765:                ////                removeSelected((MarkupDesignBean)root.getChildBean(0), false);
0766:                ////                removeSelected(WebForm.getDomProviderService().getComponentRootElementForMarkupDesignBean((MarkupDesignBean)root.getChildBean(0)), false);
0767:                //                removeSelected(children[0], false);
0768:                //            }
0769:                //
0770:                //            // Look for last bean in the default parent
0771:                ////            MarkupDesignBean defaultBean =
0772:                ////                FacesSupport.getDesignBean(webform.getModel().getFacesUnit().getDefaultParent()
0773:                ////                                                  .getElement());
0774:                ////            MarkupDesignBean defaultBean =
0775:                //////                    WebForm.getDomProviderService().getMarkupDesignBeanForElement(webform.getModel().getFacesUnit().getDefaultParent()
0776:                //////                                                  .getElement());
0777:                ////                    WebForm.getDomProviderService().getMarkupDesignBeanForElement(
0778:                ////                        webform.getDefaultParentMarkupBeanElement());
0779:                //            
0780:                ////            Element defaultElement = webform.getDefaultParentMarkupBeanElement();
0781:                //            Element defaultElement = webform.getDefaultParentComponent();
0782:                //            
0783:                ////            if (defaultBean != null) {
0784:                ////                int n = defaultBean.getChildBeanCount();
0785:                ////
0786:                ////                if ((n > 0) &&
0787:                ////                        ((MarkupDesignBean)defaultBean.getChildBean(n - 1)).getElement().getTagName()
0788:                ////                             .equals(HtmlTag.BR.name)) {
0789:                //////                    removeSelected((MarkupDesignBean)defaultBean.getChildBean(n - 1), false);
0790:                ////                    removeSelected(WebForm.getDomProviderService().getComponentRootElementForMarkupDesignBean((MarkupDesignBean)defaultBean.getChildBean(n - 1)), false);
0791:                ////                }
0792:                ////            }
0793:                //            if (defaultElement != null) {
0794:                //                Element[] defaultElementChildren = WebForm.getDomProviderService().getChildComponents(defaultElement);
0795:                //                int n = defaultElementChildren.length;
0796:                //                if ((n > 0) && HtmlTag.BR.name.equals(defaultElementChildren[n-1].getTagName())) {
0797:                //                    removeSelected(defaultElementChildren[n - 1], false);
0798:                //                }
0799:                //            }
0800:                //        }
0801:                if (!webform.isGridMode()) {
0802:                    // XXX Just the same what did the original code, but without JSF specific API.
0803:                    if (!selectedComponents.isEmpty()) {
0804:                        Element firstSelectedComponent = selectedComponents
0805:                                .get(0).componentRootElement;
0806:                        Element lastSelectedComponent = selectedComponents
0807:                                .get(selectedComponents.size() - 1).componentRootElement;
0808:                        if (firstSelectedComponent != null
0809:                                && HtmlTag.BR.name
0810:                                        .equals(firstSelectedComponent
0811:                                                .getTagName())) {
0812:                            removeSelected(firstSelectedComponent, false);
0813:                        }
0814:                        if (lastSelectedComponent != null
0815:                                && HtmlTag.BR.name.equals(lastSelectedComponent
0816:                                        .getTagName())) {
0817:                            removeSelected(lastSelectedComponent, false);
0818:                        }
0819:                    }
0820:                }
0821:
0822:                //        updateSelection();
0823:                updateNodes();
0824:
0825:                //        if (selected.size() > 0) {
0826:                if (!selectedComponents.isEmpty()) {
0827:                    //            webform.getTopComponent().enableCutCopyDelete();
0828:                    //            webform.tcEnableCutCopyDelete();
0829:                }
0830:
0831:                webform.getPane().repaint();
0832:            }
0833:
0834:            private void selectAll(
0835:                    /*MarkupDesignBean bean*/Element componentRootElement) {
0836:                //        if (!FacesSupport.isSpecialBean(/*webform, */bean)) {
0837:                //        if (!Util.isSpecialBean(bean)) {
0838:                //        MarkupDesignBean bean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(componentRootElement);
0839:                if (!webform.getDomProviderService().isSpecialComponent(
0840:                        componentRootElement)) {
0841:                    //            addSelected(bean, false);
0842:                    addSelected(componentRootElement, false);
0843:                }
0844:
0845:                //        for (int i = 0, n = bean.getChildBeanCount(); i < n; i++) {
0846:                //            DesignBean child = bean.getChildBean(i);
0847:                //
0848:                //            if (child instanceof MarkupDesignBean) {
0849:                ////                selectAll((MarkupDesignBean)child);
0850:                //                selectAll(WebForm.getDomProviderService().getComponentRootElementForMarkupDesignBean((MarkupDesignBean)child));
0851:                //            }
0852:                //        }
0853:                Element[] children = webform.getDomProviderService()
0854:                        .getChildComponents(componentRootElement);
0855:                for (Element child : children) {
0856:                    selectAll(child);
0857:                }
0858:            }
0859:
0860:            /** Select all views that intersect the given bound rectangle.
0861:             * @todo Decide if views should be entirely within the bounds, or
0862:             * merely intersect the rectangle
0863:             * @param pane Pane to look for selection in
0864:             * @param bounds Bounds to scan within
0865:             * @param exclusive If true, only include components that are fully
0866:             *             contained within the bounds. If false, include any
0867:             *             component that touches the bounds.
0868:             * @todo Get rid of the pane parameter - it is redundant; should be webform.getPane()
0869:             */
0870:            public void selectComponentRectangle(Rectangle bounds,
0871:                    boolean contained) {
0872:                List<Element> list = new ArrayList<Element>();
0873:                DesignerPane pane = webform.getPane();
0874:                selectViews(pane.getPageBox(), list, bounds, contained, 0);
0875:
0876:                //        Iterator it = list.iterator();
0877:                clearSelection(false);
0878:
0879:                //        while (it.hasNext()) {
0880:                //            MarkupDesignBean component = (MarkupDesignBean)it.next();
0881:                for (Element componentRootElement : list) {
0882:                    //            addSelected(component, false);
0883:                    addSelected(componentRootElement, false);
0884:
0885:                    // The Marquee will call repaint
0886:                }
0887:
0888:                //        updateSelection();
0889:                updateNodes();
0890:
0891:                // XXX do I need to go and set copy selection here?
0892:                pane.repaint();
0893:            }
0894:
0895:            private static void selectViews(CssBox box, List<Element> matches,
0896:                    Rectangle bounds, boolean contained, int depth) {
0897:                if (DesignerUtils.intersects(bounds, box.getAbsoluteX(), box
0898:                        .getAbsoluteY(), box.getWidth(), box.getHeight())) {
0899:                    // TODO - use DesignerCaret's _contains instead!
0900:                    if ((contained && bounds.contains(box.getAbsoluteX(), box
0901:                            .getAbsoluteY(), box.getWidth(), box.getHeight()))
0902:                            || (!contained && DesignerUtils.intersects(bounds,
0903:                                    box.getAbsoluteX(), box.getAbsoluteY(), box
0904:                                            .getWidth(), box.getHeight()))) {
0905:                        //                if (box.getDesignBean() != null) {
0906:                        //                    matches.add(box.getDesignBean());
0907:                        //                MarkupDesignBean markupDesignBean = CssBox.getMarkupDesignBeanForCssBox(box);
0908:                        //                if (markupDesignBean != null) {
0909:                        //                    matches.add(markupDesignBean);
0910:                        //                }
0911:                        Element componentRootElement = CssBox
0912:                                .getElementForComponentRootCssBox(box);
0913:                        if (componentRootElement != null) {
0914:                            matches.add(componentRootElement);
0915:                        }
0916:                    }
0917:                }
0918:
0919:                // XXX Should only have to do this for intersecting boxes!!!
0920:                // (plus those intersecting with the -extents- of the box, e.g.
0921:                // including absolutely positioned boxes!)
0922:                for (int i = 0, n = box.getBoxCount(); i < n; i++) {
0923:                    CssBox child = box.getBox(i);
0924:
0925:                    if (child instanceof  ExternalDocumentBox) {
0926:                        continue;
0927:                    }
0928:
0929:                    selectViews(child, matches, bounds, contained, depth + 1);
0930:                }
0931:            }
0932:
0933:            /**
0934:             * Focus the default property. Return false if no default property was
0935:             * found, or if the property is read only, if no component is selected,
0936:             * etc.
0937:             * @todo check for readonly prop, and immediately sync prop sheet
0938:             * to avoid delay problem!
0939:             */
0940:            public boolean focusDefaultProperty(ActionEvent event) {
0941:                //        if ((selected != null) && (selected.size() > 0)) {
0942:                if (!selectedComponents.isEmpty()) {
0943:                    DesignerPane pane = webform.getPane();
0944:                    //            ModelViewMapper mapper = webform.getMapper();
0945:
0946:                    // Find the first selected component that has a default
0947:                    // property or is inline editing capable
0948:                    //            Iterator it = selected.iterator();
0949:                    //
0950:                    //            while (it.hasNext()) {
0951:                    //                FormObject fo = (FormObject)it.next();
0952:                    //            for (FormObject fo : selected) {
0953:                    //                DesignBean lb = fo.component;
0954:                    for (SelectedComponent sc : selectedComponents) {
0955:                        //                if (lb instanceof MarkupDesignBean) {
0956:                        //                    MarkupDesignBean bean = (MarkupDesignBean)lb;
0957:                        //                    CssBox box = mapper.findBox(bean);
0958:                        CssBox box = ModelViewMapper
0959:                                .findBoxForComponentRootElement(webform
0960:                                        .getPane().getPageBox(),
0961:                                        sc.componentRootElement);
0962:                        // TODO - pass in keystroke too
0963:                        boolean inlineEdited =
0964:                        //                    webform.getManager().startInlineEditing(bean, null, box, true, false,
0965:                        webform.getManager().startInlineEditing(
0966:                                sc.componentRootElement, null, box, true,
0967:                                false, event.getActionCommand(), false);
0968:                        if (inlineEdited) {
0969:                            return true;
0970:                        }
0971:                        //                }
0972:
0973:                        //                DesignBean lb = WebForm.getDomProviderService().getMarkupDesignBeanForElement(sc.componentRootElement);
0974:                        //                BeanInfo bi = lb.getBeanInfo();
0975:                        //                if (bi != null) {
0976:                        //                    int defaultProp = bi.getDefaultPropertyIndex();
0977:                        //
0978:                        //                    if (defaultProp != -1) {
0979:                        if (webform.getDomProviderService().hasDefaultProperty(
0980:                                sc.componentRootElement)) {
0981:                            //                        FeatureDescriptor defProp = bi.getPropertyDescriptors()[defaultProp];
0982:                            //
0983:                            //                        // How do we launch the property sheet editing a
0984:                            //                        // particular property?
0985:                            //                        final JTable jt =
0986:                            ////                            org.netbeans.modules.visualweb.designer.DesignerUtils.findPropSheetTable(true, true);
0987:                            //                                findPropSheetTable(true, true);
0988:                            //
0989:                            //                        if (jt == null) {
0990:                            //                            return false;
0991:                            //                        }
0992:                            //
0993:                            //                        TableModel model = jt.getModel();
0994:                            //
0995:                            //                        // Set focus of jt?
0996:                            //                        for (int row = 0, n = model.getRowCount(); row < n; row++) {
0997:                            //                            Object o = model.getValueAt(row, 0);
0998:                            //
0999:                            //                            if (!(o instanceof FeatureDescriptor)) {
1000:                            //                                continue;
1001:                            //                            }
1002:                            //
1003:                            //                            FeatureDescriptor desc = (FeatureDescriptor)o;
1004:                            //
1005:                            //                            if (defProp.getName().equals(desc.getName())) {
1006:                            //                                // Edit the cell XXX only if readonly!
1007:                            //                                if (desc instanceof Node.Property) {
1008:                            //                                    Node.Property prop = (Node.Property)desc;
1009:                            //
1010:                            //                                    if (!prop.canWrite()) {
1011:                            //                                        return false;
1012:                            //                                    }
1013:                            //                                }
1014:                            //
1015:                            //                                final int r = row;
1016:                            //                                final String content = event.getActionCommand();
1017:                            //                                SwingUtilities.invokeLater(new Runnable() {
1018:                            //                                        public void run() {
1019:                            //                                            jt.editCellAt(r, 1, null);
1020:                            //                                            jt.requestFocus();
1021:                            //
1022:                            //                                            Object ce = jt.getCellEditor(r, 1);
1023:                            //
1024:                            //                                            // Hack Alert: try to transfer the
1025:                            //                                            // original keypress into the text field
1026:                            //                                            Component comp =
1027:                            //                                                getInplaceEditorComponentForSheetCellEditor(ce);
1028:                            //
1029:                            //                                            if (comp instanceof javax.swing.text.JTextComponent) {
1030:                            //                                                javax.swing.text.JTextComponent jtc =
1031:                            //                                                    (javax.swing.text.JTextComponent)comp;
1032:                            //                                                jtc.replaceSelection(content);
1033:                            //                                            }
1034:                            //                                        }
1035:                            //                                    });
1036:                            //
1037:                            //                                return true;
1038:                            //                            }
1039:                            //                        }
1040:                            return webform.getDomProviderService()
1041:                                    .focusDefaultProperty(
1042:                                            sc.componentRootElement,
1043:                                            event.getActionCommand());
1044:                        } else {
1045:                            // Is it a MarkupBean that has a TextNode child?
1046:                            // (for example a <div> or a <table>. If so,
1047:                            // try to set the caret to the given position
1048:                            // and repeat the insert.)
1049:                            //                        Element element = FacesSupport.getElement(lb);
1050:                            //                        Element element = Util.getElement(lb);
1051:                            //                        Element element = WebForm.getDomProviderService().getElement(lb);
1052:                            Element element = webform.getDomProviderService()
1053:                                    .getSourceElement(sc.componentRootElement);
1054:
1055:                            if (element != null) {
1056:                                //                            org.w3c.dom.Node text = DesignerUtils.findFirstTextChild(element);
1057:                                org.w3c.dom.Node text = findFirstTextChild(element);
1058:
1059:                                if (text != null) {
1060:                                    //                                DesignerCaret dc = pane.getPaneUI().createCaret();
1061:                                    //                                pane.setCaret(dc);
1062:                                    pane.createCaret();
1063:
1064:                                    //                                Position newPos = new Position(text, 0, Bias.FORWARD);
1065:                                    //                                Position newPos = Position.create(text, 0, Bias.FORWARD);
1066:                                    DomPosition newPos = webform
1067:                                            .createDomPosition(text, 0,
1068:                                                    Bias.FORWARD);
1069:
1070:                                    //                                pane.setCaretPosition(newPos);
1071:                                    pane.setCaretDot(newPos);
1072:
1073:                                    //                                Document doc = webform.getDocument();
1074:
1075:                                    ////                                UndoEvent undoEvent = webform.getModel().writeLock(NbBundle.getMessage(DefaultKeyTypedAction.class,
1076:                                    ////                                        "InsertChar"));
1077:                                    //                                DomProvider.WriteLock writeLock = webform.writeLock(NbBundle.getMessage(DefaultKeyTypedAction.class,
1078:                                    //                                        "InsertChar"));
1079:                                    //                                try {
1080:                                    //                                    doc.writeLock(NbBundle.getMessage(DefaultKeyTypedAction.class,
1081:                                    //                                            "InsertChar"));
1082:
1083:                                    final String content = event
1084:                                            .getActionCommand();
1085:                                    //                                    pane.getCaret().replaceSelection(content);
1086:                                    pane.replaceSelection(content);
1087:                                    //                                } finally {
1088:                                    ////                                    doc.writeUnlock();
1089:                                    ////                                    webform.getModel().writeUnlock(undoEvent);
1090:                                    //                                    webform.writeUnlock(writeLock);
1091:                                    //                                }
1092:
1093:                                    return true;
1094:                                }
1095:                            }
1096:                        }
1097:                        //                }
1098:                    }
1099:                }
1100:
1101:                return false;
1102:            }
1103:
1104:            // XXX Moved from DesignerUtils.
1105:            /** Find the first TextNode child under this element, or null
1106:             * if no such node is found.
1107:             * @todo How do we avoid returning for example the blank
1108:             * textnode between <table> and <tr> in a table? I want
1109:             * the <td> !
1110:             */
1111:            private static org.w3c.dom.Node findFirstTextChild(
1112:                    org.w3c.dom.Node node) {
1113:                //        if(DEBUG) {
1114:                //            debugLog(DesignerUtils.class.getName() + ".findFirstTextChild(Node)");
1115:                //        }
1116:                if (node == null) {
1117:                    return (null);
1118:                }
1119:                if ((node.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
1120:                        || (node.getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE)) {
1121:                    return node;
1122:                }
1123:
1124:                org.w3c.dom.NodeList nl = node.getChildNodes();
1125:
1126:                for (int i = 0, n = nl.getLength(); i < n; i++) {
1127:                    org.w3c.dom.Node result = findFirstTextChild(nl.item(i));
1128:
1129:                    if (result != null) {
1130:                        return result;
1131:                    }
1132:                }
1133:
1134:                return null;
1135:            }
1136:
1137:            //    // XXX Moved from DesignerUtils.
1138:            //    /** Locate the JTable within the property sheet in the IDE.
1139:            //     * WARNING: Implementation hacks!
1140:            //     * @param focus If set, focus the top component
1141:            //     * @param visible If set, ensure the top component is fronted
1142:            //     */
1143:            //    private static JTable findPropSheetTable(boolean focus, boolean visible) {
1144:            //        WindowManager mgr = WindowManager.getDefault();
1145:            //        TopComponent properties = mgr.findTopComponent("properties"); // NOI18N
1146:            //        
1147:            //        if ((properties != null) && (visible || properties.isShowing())) {
1148:            //            if (focus) {
1149:            //                properties.requestActive();
1150:            //            }
1151:            //            
1152:            //            if (visible) {
1153:            //                properties.requestVisible();
1154:            //            }
1155:            //            
1156:            //            return findTable(properties);
1157:            //        }
1158:            //        
1159:            //        return null;
1160:            //    }
1161:            //    
1162:            //    /** Fish the given Container hierarchy for a JTable */
1163:            //    private static JTable findTable(Container c) {
1164:            ////        if(DEBUG) {
1165:            ////            debugLog(DesignerUtils.class.getName() + ".findTable(Container)");
1166:            ////        }
1167:            //        if(c == null) {
1168:            //            return(null);
1169:            //        }
1170:            //        if (c instanceof JTable) {
1171:            //            return (JTable)c;
1172:            //        }
1173:            //        
1174:            //        int n = c.getComponentCount();
1175:            //        
1176:            //        for (int i = 0; i < n; i++) {
1177:            //            Component comp = c.getComponent(i);
1178:            //            
1179:            //            if (comp instanceof JTable) {
1180:            //                return (JTable)comp;
1181:            //            }
1182:            //            
1183:            //            if (comp instanceof Container) {
1184:            //                JTable table = findTable((Container)comp);
1185:            //                
1186:            //                if (table != null) {
1187:            //                    return table;
1188:            //                }
1189:            //            }
1190:            //        }
1191:            //        
1192:            //        return null;
1193:            //    }
1194:            //
1195:            //    // XXX Using reflection, But it is still better than changing NB code
1196:            //    // The task from UI point of view looks very strange... why the text isn't inserted into the component, as user expect,
1197:            //    // but surprisinlgy the focus is moved into property sheet? That kind of solutions cause problems like this.
1198:            //    private static Component getInplaceEditorComponentForSheetCellEditor(Object ce) {
1199:            //        if (ce == null) {
1200:            //            return null;
1201:            //        }
1202:            //
1203:            //        Object inplaceEditor;
1204:            //
1205:            //        try {
1206:            //            ClassLoader cl =
1207:            //                org.openide.explorer.propertysheet.PropertySheet.class.getClassLoader();
1208:            //            Class sheetCellEditorClass =
1209:            //                Class.forName("org.openide.explorer.propertysheet.SheetCellEditor", true, cl); // NOI18N
1210:            //            java.lang.reflect.Method getInplaceEditorMethod =
1211:            //                sheetCellEditorClass.getDeclaredMethod("getInplaceEditor", new Class[0]); // NOI18N
1212:            //            getInplaceEditorMethod.setAccessible(true);
1213:            //            inplaceEditor = getInplaceEditorMethod.invoke(ce, new Object[0]);
1214:            //        } catch (ClassNotFoundException cnfe) {
1215:            //            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, cnfe);
1216:            //            inplaceEditor = null;
1217:            //        } catch (NoSuchMethodException nsme) {
1218:            //            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, nsme);
1219:            //            inplaceEditor = null;
1220:            //        } catch (IllegalAccessException iae) {
1221:            //            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, iae);
1222:            //            inplaceEditor = null;
1223:            //        } catch (java.lang.reflect.InvocationTargetException ite) {
1224:            //            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ite);
1225:            //            inplaceEditor = null;
1226:            //        }
1227:            //
1228:            //        if (inplaceEditor instanceof org.openide.explorer.propertysheet.InplaceEditor) {
1229:            //            return ((org.openide.explorer.propertysheet.InplaceEditor)inplaceEditor).getComponent();
1230:            //        } else {
1231:            //            return null;
1232:            //        }
1233:            //    }
1234:
1235:            /**
1236:             * Determine if the given point overlaps a selection handle.
1237:             * @param editor The editor whose selection we're checking
1238:             * @param x The x coordinate of the position we want to check
1239:             * @param y The y coordinate of the position we want to check
1240:             * @return Cursor.DEFAULT_CURSOR if the given point (x,y) is not
1241:             * over any of the selection handles drawn for the current selection.
1242:             * If it is, return the right edge direction for the overlap.
1243:             * If there are multiple overlapping selection handles, it's arbitrary
1244:             * which one is chosen.
1245:             * @see overSelection
1246:             */
1247:            public int getSelectionHandleDir(int x, int y, int maxWidth,
1248:                    int maxHeight) {
1249:                //        if ((selected != null) && (selected.size() > 0)) {
1250:                //            Iterator it = selected.iterator();
1251:                ////            ModelViewMapper mapper = webform.getMapper();
1252:                //
1253:                //            while (it.hasNext()) {
1254:                //                FormObject fo = (FormObject)it.next();
1255:                //
1256:                //                // XXX I should cache these!!!
1257:                ////                ArrayList rectangles = mapper.getComponentRectangles(fo.component);
1258:                //                List rectangles = ModelViewMapper.getComponentRectangles(webform.getPane().getPageBox(), fo.component);
1259:                //
1260:                //                for (int i = 0; i < rectangles.size(); i++) {
1261:                //                    int over =
1262:                //                        overSelection(x, y, (Rectangle)rectangles.get(i), fo.resizeConstraints,
1263:                //                            maxWidth, maxHeight);
1264:                //
1265:                //                    if (over != Cursor.DEFAULT_CURSOR) {
1266:                //                        return over;
1267:                //                    }
1268:                //                }
1269:                //            }
1270:                //        }
1271:                for (SelectedComponent sc : selectedComponents) {
1272:                    // XXX I should cache these!!!
1273:                    //                ArrayList rectangles = mapper.getComponentRectangles(fo.component);
1274:                    List rectangles = ModelViewMapper.getComponentRectangles(
1275:                            webform.getPane().getPageBox(),
1276:                            sc.componentRootElement);
1277:                    for (int i = 0; i < rectangles.size(); i++) {
1278:                        int over = overSelection(x, y, (Rectangle) rectangles
1279:                                .get(i), sc.resizeConstraints, maxWidth,
1280:                                maxHeight);
1281:                        if (over != Cursor.DEFAULT_CURSOR) {
1282:                            return over;
1283:                        }
1284:                    }
1285:                }
1286:
1287:                return Cursor.DEFAULT_CURSOR;
1288:            }
1289:
1290:            /**
1291:             * Similar to getSelectionHandleDir, but returns the selected
1292:             * object whose selection handles are pointed at, rather than the
1293:             * selection handle direction.
1294:             */
1295:            public/*MarkupDesignBean*/Element getSelectionHandleView(int x,
1296:                    int y, int maxWidth, int maxHeight) {
1297:                //        if ((selected != null) && (selected.size() > 0)) {
1298:                ////            ModelViewMapper mapper = webform.getMapper();
1299:                //
1300:                //            Iterator it = selected.iterator();
1301:                //
1302:                //            while (it.hasNext()) {
1303:                //                FormObject fo = (FormObject)it.next();
1304:                ////                ArrayList rectangles = mapper.getComponentRectangles(fo.component);
1305:                //                List rectangles = ModelViewMapper.getComponentRectangles(webform.getPane().getPageBox(), fo.component);
1306:                //
1307:                //                for (int i = 0; i < rectangles.size(); i++) {
1308:                //                    int dir =
1309:                //                        overSelection(x, y, (Rectangle)rectangles.get(i), fo.resizeConstraints,
1310:                //                            maxWidth, maxHeight);
1311:                //
1312:                //                    if (dir != Cursor.DEFAULT_CURSOR) {
1313:                //                        return fo.component;
1314:                //                    }
1315:                //                }
1316:                //            }
1317:                //        }
1318:                for (SelectedComponent sc : selectedComponents) {
1319:                    //                ArrayList rectangles = mapper.getComponentRectangles(fo.component);
1320:                    List<Rectangle> rectangles = ModelViewMapper
1321:                            .getComponentRectangles(webform.getPane()
1322:                                    .getPageBox(), sc.componentRootElement);
1323:
1324:                    for (Rectangle rectangle : rectangles) {
1325:                        int dir = overSelection(x, y, rectangle,
1326:                                sc.resizeConstraints, maxWidth, maxHeight);
1327:                        if (dir != Cursor.DEFAULT_CURSOR) {
1328:                            return sc.componentRootElement;
1329:                        }
1330:                    }
1331:                }
1332:
1333:                return null;
1334:            }
1335:
1336:            /**
1337:             * Return true iff no components are selected
1338:             */
1339:            public boolean isSelectionEmpty() {
1340:                //        return (selected == null) || (selected.size() == 0);
1341:                return selectedComponents.isEmpty();
1342:            }
1343:
1344:            /**
1345:             * Report the number of selected items.
1346:             * @return the number of selected items in the designer
1347:             */
1348:            public int getNumSelected() {
1349:                //        return (selected == null) ? 0 : selected.size();
1350:                return selectedComponents.size();
1351:            }
1352:
1353:            /** Make a particular element selected
1354:             */
1355:            public void selectComponents(
1356:                    final/*DesignBean[] components*/Element[] componentRootElements,
1357:                    final boolean update) {
1358:                //        if (ignoreSelection) {
1359:                //            return;
1360:                //        }
1361:
1362:                // Make sure the component is selected
1363:                // Unfortunately we have to do this in a delay;
1364:                // see Document.handleEvent for details (look near
1365:                // DOM_NODE_INSERTED - and note that we're called
1366:                // from DndHandler when components
1367:                // are inserted)
1368:                SwingUtilities.invokeLater(new Runnable() {
1369:                    public void run() {
1370:                        //                    assert components != null;
1371:                        //
1372:                        //                    clearSelection(false);
1373:                        //
1374:                        //                    for (int i = 0; i < components.length; i++) {
1375:                        //                        if (components[i] instanceof MarkupDesignBean) {
1376:                        ////                            addSelected((MarkupDesignBean)components[i], false);
1377:                        //                            addSelected(getComponentRootElementForMarkupDesignBean((MarkupDesignBean)components[i]), false);
1378:                        //                        }
1379:                        //                    }
1380:
1381:                        clearSelection(false);
1382:
1383:                        if (componentRootElements != null) {
1384:                            for (Element componentRootElement : componentRootElements) {
1385:                                if (componentRootElement != null) {
1386:                                    addSelected(componentRootElement, false);
1387:                                }
1388:                            }
1389:                        }
1390:
1391:                        if (update) {
1392:                            //                        updateSelection();
1393:                            updateNodes();
1394:                        }
1395:
1396:                        DesignerPane dp = webform.getPane();
1397:
1398:                        // #6258586 NPE fix.
1399:                        if (dp != null) {
1400:                            dp.repaint(); // tray wants a repaint but no node update!!! update means node update!
1401:                        }
1402:                    }
1403:                });
1404:            }
1405:
1406:            /** Increase the size of the given rectangle to accomodate
1407:             * the selection handles. Typically used when computing dirty/repaint
1408:             * rectangles
1409:             * @todo Should probably be a static method
1410:             */
1411:            public void enlarge(Rectangle r) {
1412:                r.x -= (BARSIZE + 1);
1413:                r.y -= (BARSIZE + 1);
1414:                r.width += ((2 * BARSIZE) + 2);
1415:                r.height += ((2 * BARSIZE) + 2);
1416:            }
1417:
1418:            private BasicStroke getSelectionStroke() {
1419:                if (selStroke == null) {
1420:                    int width = 1;
1421:                    selStroke = new BasicStroke((float) width,
1422:                            BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER,
1423:                            10.0f,
1424:                            new float[] { 6 * width, (6 * width) + width },
1425:                            0.0f);
1426:                }
1427:
1428:                return selStroke;
1429:            }
1430:
1431:            /** Draw selection rectangles around the currently selected views */
1432:            public void paintSelection(Graphics2D g2d) {
1433:                if (webform.getManager().isInlineEditing()) {
1434:                    return;
1435:                }
1436:
1437:                //        if ((selected != null) && (selected.size() > 0)) {
1438:                //            boolean selectedMany = selected.size() > 1;
1439:                if (!selectedComponents.isEmpty()) {
1440:                    //            boolean selectedMany = selected.size() > 1;
1441:                    boolean selectedMany = selectedComponents.size() > 1;
1442:                    //            ModelViewMapper mapper = webform.getMapper();
1443:                    ColorManager colors = webform.getColors();
1444:
1445:                    //            Iterator it = selected.iterator();
1446:                    PageBox pageBox = webform.getPane().getPageBox();
1447:                    int maxWidth = pageBox.getWidth();
1448:                    int maxHeight = pageBox.getHeight();
1449:
1450:                    //            while (it.hasNext()) {
1451:                    //                FormObject fo = (FormObject)it.next();
1452:                    //            for (FormObject fo : selected) {
1453:                    //
1454:                    //                // XXX I should cache these!!!
1455:                    ////                ArrayList rectangles = mapper.getComponentRectangles(fo.component);
1456:                    //                List rectangles = ModelViewMapper.getComponentRectangles(pageBox, fo.component);
1457:                    ////                Rectangle bounds = mapper.getComponentBounds(fo.component);
1458:                    //                Rectangle bounds = ModelViewMapper.getComponentBounds(pageBox, fo.component);
1459:
1460:                    // XXX #95626 Hack (model might be changing underneath without proper notifications).
1461:                    // The elements might have been changed while the beans remain same.
1462:                    if (primary != null) {
1463:                        Element equivalentElement = webform
1464:                                .getComponentRootElementEquivalentTo(primary);
1465:                        if (equivalentElement != null
1466:                                && equivalentElement != primary) {
1467:                            primary = equivalentElement;
1468:                        }
1469:                    }
1470:
1471:                    for (SelectedComponent sc : selectedComponents) {
1472:                        // XXX #95626 Hack (model might be changing underneath without proper notifications).
1473:                        // The elements might have been changed while the beans remain same.
1474:                        Element equivalentElement = webform
1475:                                .getComponentRootElementEquivalentTo(sc.componentRootElement);
1476:                        if (equivalentElement != null
1477:                                && equivalentElement != sc.componentRootElement) {
1478:                            sc.componentRootElement = equivalentElement;
1479:                        }
1480:
1481:                        // XXX I should cache these!!!
1482:                        //                ArrayList rectangles = mapper.getComponentRectangles(fo.component);
1483:                        List rectangles = ModelViewMapper
1484:                                .getComponentRectangles(pageBox,
1485:                                        sc.componentRootElement);
1486:                        //                Rectangle bounds = mapper.getComponentBounds(fo.component);
1487:                        Rectangle bounds = ModelViewMapper.getComponentBounds(
1488:                                pageBox, sc.componentRootElement);
1489:
1490:                        int n = rectangles.size();
1491:
1492:                        // Draw bounds rectangle if we have multiple rectangles?
1493:                        if (n > 0) {
1494:                            Rectangle r1 = (Rectangle) rectangles.get(0);
1495:
1496:                            if ((r1.x != bounds.x) || (r1.y != bounds.y)
1497:                                    || (r1.width != bounds.width)
1498:                                    || (r1.height != bounds.height)) {
1499:                                g2d.setColor(colors.selectionBoundsColor);
1500:
1501:                                Stroke oldStroke = g2d.getStroke();
1502:                                BasicStroke selStroke = getSelectionStroke();
1503:                                g2d.setStroke(selStroke);
1504:                                g2d.drawRect(bounds.x, bounds.y, bounds.width,
1505:                                        bounds.height);
1506:                                g2d.setStroke(oldStroke);
1507:                            }
1508:                        }
1509:
1510:                        for (int i = 0; i < n; i++) {
1511:                            //                    paintSelected(g2d, selectedMany && (fo.component == primary),
1512:                            //                        (Rectangle)rectangles.get(i), fo.resizeConstraints, maxWidth, maxHeight);
1513:                            paintSelected(g2d, selectedMany
1514:                                    && (sc.componentRootElement == primary),
1515:                                    (Rectangle) rectangles.get(i),
1516:                                    sc.resizeConstraints, maxWidth, maxHeight);
1517:                        }
1518:                    }
1519:                }
1520:            }
1521:
1522:            /**
1523:             * Draw selection for the given view.
1524:             * @param g The graphics to draw with
1525:             * @param insertMode If true, draw a thick insert-mode rectangle
1526:             *        around the selection
1527:             * @param rect The selection rectangle
1528:             * @param constraints Which sides are resizable
1529:             */
1530:            private void paintSelected(Graphics2D g2d, boolean isPrimary,
1531:                    Rectangle rect, /*int constraints,*/
1532:                    ResizeConstraint[] resizeConstraints, int maxWidth,
1533:                    int maxHeight) {
1534:                int x = rect.x;
1535:                int y = rect.y;
1536:                int w = rect.width;
1537:                int h = rect.height;
1538:
1539:                if (x < (BARSIZE + 1)) {
1540:                    w -= ((BARSIZE + 1) - x);
1541:                    x = BARSIZE + 1;
1542:                }
1543:
1544:                if (y < (BARSIZE + 1)) {
1545:                    h -= ((BARSIZE + 1) - y);
1546:                    y = BARSIZE + 1;
1547:                }
1548:
1549:                if ((x + w + BARSIZE) > maxWidth) {
1550:                    w = maxWidth - BARSIZE - x;
1551:                }
1552:
1553:                if ((y + h + BARSIZE) > maxHeight) {
1554:                    h = maxHeight - BARSIZE - y;
1555:                }
1556:
1557:                int w2 = (w / 2) - (BARSIZE / 2);
1558:                int h2 = (h / 2) - (BARSIZE / 2);
1559:
1560:                //g2d.setColor(Marquee.marqueeColor); // TODO - make selectable
1561:                //g2d.setXORMode(view.getContainer().getBackground());
1562:                //g2d.setPaintMode(); // Just in case...
1563:                // I've gotta clip! I'm drawing outside of the canvas on OSX!
1564:                ColorManager colors = webform.getColors();
1565:                g2d.setColor(colors.selectionColor); // TODO - make selectable
1566:
1567:                g2d
1568:                        .drawRect(x - BARSIZE - 1, y - BARSIZE - 1, BARSIZE,
1569:                                BARSIZE);
1570:                g2d.drawRect(x + w, y - BARSIZE - 1, BARSIZE, BARSIZE);
1571:                g2d.drawRect(x + w, y + h, BARSIZE, BARSIZE);
1572:                g2d.drawRect(x - BARSIZE - 1, y + h, BARSIZE, BARSIZE);
1573:
1574:                // Middles
1575:                //        if ((constraints & Constants.ResizeConstraints.TOP) != 0) {
1576:                if (Resizer.hasTopResizeConstraint(resizeConstraints)) {
1577:                    g2d.drawRect(x + w2, y - BARSIZE - 1, BARSIZE, BARSIZE); // top
1578:                }
1579:
1580:                //        if ((constraints & Constants.ResizeConstraints.LEFT) != 0) {
1581:                if (Resizer.hasLeftResizeConstraint(resizeConstraints)) {
1582:                    g2d.drawRect(x - BARSIZE - 1, y + h2, BARSIZE, BARSIZE); // left
1583:                }
1584:
1585:                //        if ((constraints & Constants.ResizeConstraints.BOTTOM) != 0) {
1586:                if (Resizer.hasBottomResizeConstraint(resizeConstraints)) {
1587:                    g2d.drawRect(x + w2, y + h, BARSIZE, BARSIZE); // bottom
1588:                }
1589:
1590:                //        if ((constraints & Constants.ResizeConstraints.RIGHT) != 0) {
1591:                if (Resizer.hasRightResizeConstraint(resizeConstraints)) {
1592:                    g2d.drawRect(x + w, y + h2, BARSIZE, BARSIZE); // right
1593:                }
1594:
1595:                // Reverse video within the outer rectangle to increase visibility
1596:                // over areas different from the dominant background color
1597:                g2d.setColor(colors.selectionColorReverse);
1598:                g2d.drawRect(x - BARSIZE - 1 + 1, y - BARSIZE - 1 + 1,
1599:                        BARSIZE - 2, BARSIZE - 2);
1600:                g2d.drawRect(x + w + 1, y - BARSIZE - 1 + 1, BARSIZE - 2,
1601:                        BARSIZE - 2);
1602:                g2d.drawRect(x + w + 1, y + h + 1, BARSIZE - 2, BARSIZE - 2);
1603:                g2d.drawRect(x - BARSIZE - 1 + 1, y + h + 1, BARSIZE - 2,
1604:                        BARSIZE - 2);
1605:
1606:                //        if ((constraints & Constants.ResizeConstraints.TOP) != 0) {
1607:                if (Resizer.hasTopResizeConstraint(resizeConstraints)) {
1608:                    g2d.drawRect(x + w2 + 1, y - BARSIZE - 1 + 1, BARSIZE - 2,
1609:                            BARSIZE - 2); // top
1610:                }
1611:
1612:                //        if ((constraints & Constants.ResizeConstraints.LEFT) != 0) {
1613:                if (Resizer.hasLeftResizeConstraint(resizeConstraints)) {
1614:                    g2d.drawRect(x - BARSIZE - 1 + 1, y + h2 + 1, BARSIZE - 2,
1615:                            BARSIZE - 2); // left
1616:                }
1617:
1618:                //        if ((constraints & Constants.ResizeConstraints.BOTTOM) != 0) {
1619:                if (Resizer.hasBottomResizeConstraint(resizeConstraints)) {
1620:                    g2d.drawRect(x + w2 + 1, y + h + 1, BARSIZE - 2,
1621:                            BARSIZE - 2); // bottom
1622:                }
1623:
1624:                //        if ((constraints & Constants.ResizeConstraints.RIGHT) != 0) {
1625:                if (Resizer.hasRightResizeConstraint(resizeConstraints)) {
1626:                    g2d.drawRect(x + w + 1, y + h2 + 1, BARSIZE - 2,
1627:                            BARSIZE - 2); // right
1628:                }
1629:
1630:                if (isPrimary) {
1631:                    // Fill in the selection squares to indicate the primary
1632:                    // item. We only fill in the corners to make it stand out a
1633:                    // bit more.
1634:                    g2d.setColor(colors.primaryColor);
1635:                    g2d.fillRect(x - BARSIZE - 1 + 1, y - BARSIZE - 1 + 1,
1636:                            (BARSIZE + 1) - 2, (BARSIZE + 1) - 2);
1637:                    g2d.fillRect(x + w + 1, y - BARSIZE - 1 + 1,
1638:                            (BARSIZE + 1) - 2, (BARSIZE + 1) - 2);
1639:                    g2d.fillRect(x + w + 1, y + h + 1, (BARSIZE + 1) - 2,
1640:                            (BARSIZE + 1) - 2);
1641:                    g2d.fillRect(x - BARSIZE - 1 + 1, y + h + 1,
1642:                            (BARSIZE + 1) - 2, (BARSIZE + 1) - 2);
1643:
1644:                    //            if ((constraints & Constants.ResizeConstraints.TOP) != 0) {
1645:                    if (Resizer.hasTopResizeConstraint(resizeConstraints)) {
1646:                        g2d.drawRect(x + w2 + 1, y - BARSIZE - 1 + 1,
1647:                                BARSIZE - 2, BARSIZE - 2); // top
1648:                    }
1649:
1650:                    //            if ((constraints & Constants.ResizeConstraints.LEFT) != 0) {
1651:                    if (Resizer.hasLeftResizeConstraint(resizeConstraints)) {
1652:                        g2d.drawRect(x - BARSIZE - 1 + 1, y + h2 + 1,
1653:                                BARSIZE - 2, BARSIZE - 2); // left
1654:                    }
1655:
1656:                    //            if ((constraints & Constants.ResizeConstraints.BOTTOM) != 0) {
1657:                    if (Resizer.hasBottomResizeConstraint(resizeConstraints)) {
1658:                        g2d.drawRect(x + w2 + 1, y + h + 1, BARSIZE - 2,
1659:                                BARSIZE - 2); // bottom
1660:                    }
1661:
1662:                    //            if ((constraints & Constants.ResizeConstraints.RIGHT) != 0) {
1663:                    if (Resizer.hasRightResizeConstraint(resizeConstraints)) {
1664:                        g2d.drawRect(x + w + 1, y + h2 + 1, BARSIZE - 2,
1665:                                BARSIZE - 2); // right
1666:                    }
1667:                }
1668:
1669:                //g2d.setPaintMode();
1670:            }
1671:
1672:            /**
1673:             * Draw selection for the given view.
1674:             * @param g The graphics to draw with
1675:             * @param insertMode If true, draw a thick insert-mode rectangle
1676:             *        around the selection
1677:             * @param rect The selection rectangle
1678:             * @param constraints Which sides are resizable
1679:             */
1680:            void paintInlineEditorBox(Graphics2D g2d, Rectangle rect) {
1681:                int x = rect.x;
1682:                int y = rect.y;
1683:                int w = rect.width;
1684:                int h = rect.height;
1685:
1686:                if (x < (BARSIZE + 1)) {
1687:                    w -= ((BARSIZE + 1) - x);
1688:                    x = BARSIZE + 1;
1689:                }
1690:
1691:                if (y < (BARSIZE + 1)) {
1692:                    h -= ((BARSIZE + 1) - y);
1693:                    y = BARSIZE + 1;
1694:                }
1695:
1696:                PageBox pageBox = webform.getPane().getPageBox();
1697:                int maxWidth = pageBox.getWidth();
1698:                int maxHeight = pageBox.getHeight();
1699:
1700:                if ((x + w + BARSIZE) > maxWidth) {
1701:                    w = maxWidth - BARSIZE - x;
1702:                }
1703:
1704:                if ((y + h + BARSIZE) > maxHeight) {
1705:                    h = maxHeight - BARSIZE - y;
1706:                }
1707:
1708:                //g2d.setColor(Marquee.marqueeColor); // TODO - make selectable
1709:                //g2d.setXORMode(view.getContainer().getBackground());
1710:                //g2d.setPaintMode(); // Just in case...
1711:                // I've gotta clip! I'm drawing outside of the canvas on OSX!
1712:                ColorManager colors = webform.getColors();
1713:                g2d.setColor(colors.selectionColor); // TODO - make selectable
1714:
1715:                g2d
1716:                        .drawRect(x - BARSIZE - 1, y - BARSIZE - 1, BARSIZE,
1717:                                BARSIZE);
1718:                g2d.drawRect(x + w, y - BARSIZE - 1, BARSIZE, BARSIZE);
1719:                g2d.drawRect(x + w, y + h, BARSIZE, BARSIZE);
1720:                g2d.drawRect(x - BARSIZE - 1, y + h, BARSIZE, BARSIZE);
1721:
1722:                // Reverse video within the outer rectangle to increase visibility
1723:                // over areas different from the dominant background color
1724:                g2d.setColor(colors.selectionColorReverse);
1725:                g2d.drawRect(x - BARSIZE - 1 + 1, y - BARSIZE - 1 + 1,
1726:                        BARSIZE - 2, BARSIZE - 2);
1727:                g2d.drawRect(x + w + 1, y - BARSIZE - 1 + 1, BARSIZE - 2,
1728:                        BARSIZE - 2);
1729:                g2d.drawRect(x + w + 1, y + h + 1, BARSIZE - 2, BARSIZE - 2);
1730:                g2d.drawRect(x - BARSIZE - 1 + 1, y + h + 1, BARSIZE - 2,
1731:                        BARSIZE - 2);
1732:
1733:                // Solid text bars
1734:                g2d.setColor(colors.insertColor); // TODO - make selectable
1735:                g2d.fillRect(x + 1, y - BARSIZE - 1, w - 2, (BARSIZE + 1) - 1);
1736:                g2d.fillRect(x + 1, y + h + 1, w - 2, (BARSIZE + 1) - 1);
1737:                g2d.fillRect(x - BARSIZE - 1, y + 1, (BARSIZE + 1) - 1, h - 2);
1738:                g2d.fillRect(x + w + 1, y + 1, (BARSIZE + 1) - 1, h - 2);
1739:
1740:                //g2d.setPaintMode();
1741:            }
1742:
1743:            /** Check to see if the cursor position is over a selection rectangle.
1744:             * This method is here next to the drawing routine since it's closely
1745:             * tied to how the selection is rendered - it should be pixel accurate
1746:             * about whether the given position is on top of a selection
1747:             * handle bar.
1748:             * @param px The x coordinate of the position we want to check
1749:             * @param py The y coordinate of the position we want to check
1750:             * @param rect The rectangle for a selected view/component
1751:             * @param constraints Resizability constraints
1752:             * @return An integer equal to either Cursor.DEFAULT_CURSOR if there
1753:             *  is no overlap, or Cursor.N_RESIZE_CURSOR, Cursor.NE_RESIZE_CURSOR,
1754:             *  (etc. etc. for all the directions) to indicate that there is a match,
1755:             *  an in particular on which edge/corner.  Thus, there is overlap
1756:             *  if return value is not equal to Cursor.DEFAULT_CURSOR, and the
1757:             *  specific return value can be used to for example pick an appropriate
1758:             *  Cursor to draw.
1759:             */
1760:            private int overSelection(int px, int py, Rectangle rect, /*int constraints,*/
1761:            ResizeConstraint[] resizeConstraints, int maxWidth, int maxHeight) {
1762:                if (py >= selectionViewPos) {
1763:                    return Cursor.DEFAULT_CURSOR;
1764:                }
1765:
1766:                int x = rect.x;
1767:                int y = rect.y;
1768:                int w = rect.width;
1769:                int h = rect.height;
1770:
1771:                if (x < (BARSIZE + 1)) {
1772:                    w -= ((BARSIZE + 1) - x);
1773:                    x = BARSIZE + 1;
1774:                }
1775:
1776:                if (y < (BARSIZE + 1)) {
1777:                    h -= ((BARSIZE + 1) - y);
1778:                    y = BARSIZE + 1;
1779:                }
1780:
1781:                // Quick elimination - not within the rectangle that surrounds the
1782:                // view of width BARSIZE. This is true for most points in the canvas
1783:                // so is a quick way to speed up the search
1784:                if (px < (x - BARSIZE - 1)) {
1785:                    return Cursor.DEFAULT_CURSOR;
1786:                }
1787:
1788:                if (py < (y - BARSIZE - 1)) {
1789:                    return Cursor.DEFAULT_CURSOR;
1790:                }
1791:
1792:                if ((x + w + BARSIZE) > maxWidth) {
1793:                    w = maxWidth - BARSIZE - x;
1794:                }
1795:
1796:                if ((y + h + BARSIZE) > maxHeight) {
1797:                    h = maxHeight - BARSIZE - y;
1798:                }
1799:
1800:                if (px > (x + w + BARSIZE)) {
1801:                    return Cursor.DEFAULT_CURSOR;
1802:                }
1803:
1804:                if (py > (y + h + BARSIZE)) {
1805:                    return Cursor.DEFAULT_CURSOR;
1806:                }
1807:
1808:                // Okay, do some more fine tuned checking
1809:                if (DesignerUtils.inside(px, py, x - BARSIZE - 1, y - BARSIZE
1810:                        - 1, BARSIZE, BARSIZE)) {
1811:                    //            if ((constraints &
1812:                    //                    (Constants.ResizeConstraints.TOP | Constants.ResizeConstraints.LEFT)) == (Constants.ResizeConstraints.TOP |
1813:                    //                    Constants.ResizeConstraints.LEFT)) {
1814:                    if (Resizer.hasTopResizeConstraint(resizeConstraints)
1815:                            && Resizer
1816:                                    .hasLeftResizeConstraint(resizeConstraints)) {
1817:                        return Cursor.NW_RESIZE_CURSOR;
1818:                        //            } else if ((constraints & Constants.ResizeConstraints.TOP) != 0) {
1819:                    } else if (Resizer
1820:                            .hasTopResizeConstraint(resizeConstraints)) {
1821:                        return Cursor.N_RESIZE_CURSOR;
1822:                        //            } else if ((constraints & Constants.ResizeConstraints.LEFT) != 0) {
1823:                    } else if (Resizer
1824:                            .hasLeftResizeConstraint(resizeConstraints)) {
1825:                        return Cursor.W_RESIZE_CURSOR;
1826:                    }
1827:                }
1828:
1829:                if (DesignerUtils.inside(px, py, x + w, y - BARSIZE - 1,
1830:                        BARSIZE, BARSIZE)) {
1831:                    //            if ((constraints &
1832:                    //                    (Constants.ResizeConstraints.TOP | Constants.ResizeConstraints.RIGHT)) == (Constants.ResizeConstraints.TOP |
1833:                    //                    Constants.ResizeConstraints.RIGHT)) {
1834:                    if (Resizer.hasTopResizeConstraint(resizeConstraints)
1835:                            && Resizer
1836:                                    .hasRightResizeConstraint(resizeConstraints)) {
1837:                        return Cursor.NE_RESIZE_CURSOR;
1838:                        //            } else if ((constraints & Constants.ResizeConstraints.TOP) != 0) {
1839:                    } else if (Resizer
1840:                            .hasTopResizeConstraint(resizeConstraints)) {
1841:                        return Cursor.N_RESIZE_CURSOR;
1842:                        //            } else if ((constraints & Constants.ResizeConstraints.RIGHT) != 0) {
1843:                    } else if (Resizer
1844:                            .hasRightResizeConstraint(resizeConstraints)) {
1845:                        return Cursor.E_RESIZE_CURSOR;
1846:                    }
1847:                }
1848:
1849:                if (DesignerUtils
1850:                        .inside(px, py, x + w, y + h, BARSIZE, BARSIZE)) {
1851:                    //            if ((constraints &
1852:                    //                    (Constants.ResizeConstraints.BOTTOM | Constants.ResizeConstraints.RIGHT)) == (Constants.ResizeConstraints.BOTTOM |
1853:                    //                    Constants.ResizeConstraints.RIGHT)) {
1854:                    if (Resizer.hasBottomResizeConstraint(resizeConstraints)
1855:                            && Resizer
1856:                                    .hasRightResizeConstraint(resizeConstraints)) {
1857:                        return Cursor.SE_RESIZE_CURSOR;
1858:                        //            } else if ((constraints & Constants.ResizeConstraints.BOTTOM) != 0) {
1859:                    } else if (Resizer
1860:                            .hasBottomResizeConstraint(resizeConstraints)) {
1861:                        return Cursor.S_RESIZE_CURSOR;
1862:                        //            } else if ((constraints & Constants.ResizeConstraints.RIGHT) != 0) {
1863:                    } else if (Resizer
1864:                            .hasRightResizeConstraint(resizeConstraints)) {
1865:                        return Cursor.E_RESIZE_CURSOR;
1866:                    }
1867:                }
1868:
1869:                if (DesignerUtils.inside(px, py, x - BARSIZE - 1, y + h,
1870:                        BARSIZE, BARSIZE)) {
1871:                    //            if ((constraints &
1872:                    //                    (Constants.ResizeConstraints.BOTTOM | Constants.ResizeConstraints.LEFT)) == (Constants.ResizeConstraints.BOTTOM |
1873:                    //                    Constants.ResizeConstraints.LEFT)) {
1874:                    if (Resizer.hasBottomResizeConstraint(resizeConstraints)
1875:                            && Resizer
1876:                                    .hasLeftResizeConstraint(resizeConstraints)) {
1877:                        return Cursor.SW_RESIZE_CURSOR;
1878:                        //            } else if ((constraints & Constants.ResizeConstraints.BOTTOM) != 0) {
1879:                    } else if (Resizer
1880:                            .hasBottomResizeConstraint(resizeConstraints)) {
1881:                        return Cursor.S_RESIZE_CURSOR;
1882:                        //            } else if ((constraints & Constants.ResizeConstraints.LEFT) != 0) {
1883:                    } else if (Resizer
1884:                            .hasLeftResizeConstraint(resizeConstraints)) {
1885:                        return Cursor.W_RESIZE_CURSOR;
1886:                    }
1887:                }
1888:
1889:                // In inline editing mode we can drag the border to start moving the component
1890:                // PENDING: Look for a movable parent first to decide?
1891:                // Or only do this for positioned components?
1892:                if (webform.getManager().isInlineEditing()
1893:                        && DesignerUtils.inside(px, py, x - BARSIZE - 1, y
1894:                                - BARSIZE - 1, w + (2 * BARSIZE), h
1895:                                + (2 * BARSIZE))
1896:                        && !DesignerUtils.inside(px, py, x, y, w, h)) {
1897:                    return Cursor.MOVE_CURSOR;
1898:                }
1899:
1900:                int w2 = (w / 2) - (BARSIZE / 2);
1901:                int h2 = (h / 2) - (BARSIZE / 2);
1902:
1903:                //        if ((constraints & Constants.ResizeConstraints.TOP) != 0) {
1904:                if (Resizer.hasTopResizeConstraint(resizeConstraints)) {
1905:                    if (DesignerUtils.inside(px, py, (x + w2) - (BARSIZE / 2),
1906:                            y - BARSIZE - 1, BARSIZE, BARSIZE)) {
1907:                        return Cursor.N_RESIZE_CURSOR;
1908:                    }
1909:                }
1910:
1911:                //        if ((constraints & Constants.ResizeConstraints.LEFT) != 0) {
1912:                if (Resizer.hasLeftResizeConstraint(resizeConstraints)) {
1913:                    if (DesignerUtils.inside(px, py, x - BARSIZE - 1, (y + h2)
1914:                            - (BARSIZE / 2), BARSIZE, BARSIZE)) {
1915:                        return Cursor.W_RESIZE_CURSOR;
1916:                    }
1917:                }
1918:
1919:                //        if ((constraints & Constants.ResizeConstraints.BOTTOM) != 0) {
1920:                if (Resizer.hasBottomResizeConstraint(resizeConstraints)) {
1921:                    if (DesignerUtils.inside(px, py, (x + w2) - (BARSIZE / 2),
1922:                            y + h, BARSIZE, BARSIZE)) {
1923:                        return Cursor.S_RESIZE_CURSOR;
1924:                    }
1925:                }
1926:
1927:                //        if ((constraints & Constants.ResizeConstraints.RIGHT) != 0) {
1928:                if (Resizer.hasRightResizeConstraint(resizeConstraints)) {
1929:                    if (DesignerUtils.inside(px, py, x + w, (y + h2)
1930:                            - (BARSIZE / 2), BARSIZE, BARSIZE)) {
1931:                        return Cursor.E_RESIZE_CURSOR;
1932:                    }
1933:                }
1934:
1935:                return Cursor.DEFAULT_CURSOR;
1936:            }
1937:
1938:            // XXX HACKY CODE! Clean up once we agree on the UI & operation for this!
1939:            public void paintSelHierarchy(Graphics2D g2d) {
1940:                if (!PAINT_SELECTION_HIERARCHY) {
1941:                    return;
1942:                }
1943:
1944:                if (isSelectionEmpty()) {
1945:                    return;
1946:                }
1947:
1948:                PageBox pageBox = webform.getPane().getPageBox();
1949:
1950:                if (pageBox == null) {
1951:                    return;
1952:                }
1953:
1954:                JViewport viewport = pageBox.getViewport();
1955:                Dimension d = viewport.getExtentSize();
1956:                Point p = viewport.getViewPosition();
1957:                FontMetrics metrics = webform.getPane().getMetrics();
1958:                FontMetrics boldMetrics = webform.getPane().getBoldMetrics();
1959:
1960:                // Keep this positioning logic in sync with notifyScrolled!
1961:                int h = metrics.getHeight() + 1;
1962:                int x = SELECTIONVIEW_LEFT;
1963:                int y = (p.y + d.height) - h;
1964:                int yadj = (y + metrics.getHeight()) - metrics.getDescent();
1965:                selectionViewPos = y;
1966:
1967:                ColorManager colors = webform.getColors();
1968:                g2d.setColor(colors.hierarchyBackgroundColor);
1969:                g2d.fillRect(x, y, d.width, h);
1970:                g2d.setColor(colors.hierarchyForegroundColor);
1971:
1972:                // Draw for the first selected item
1973:                //        Iterator it = selected.iterator();
1974:                //        assert it.hasNext();
1975:                //
1976:                //        FormObject fo = (FormObject)it.next();
1977:                //        MarkupDesignBean currentBean = fo.component;
1978:                Iterator<SelectedComponent> it = selectedComponents.iterator();
1979:                assert it.hasNext();
1980:                SelectedComponent sc = it.next();
1981:                //        MarkupDesignBean currentBean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(sc.componentRootElement);
1982:
1983:                //        MarkupDesignBean leafBean = leaf;
1984:                //        MarkupDesignBean leafBean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(leaf);
1985:
1986:                //        if (leafBean == null) {
1987:                //            leafBean = currentBean;
1988:                //        }
1989:                if (leaf == null) {
1990:                    leaf = sc.componentRootElement;
1991:                }
1992:
1993:                //        paintOrSelectAncestor(g2d, metrics, boldMetrics, leafBean, x, y, yadj, currentBean, -1);
1994:                paintOrSelectAncestor(g2d, metrics, boldMetrics, leaf, x, y,
1995:                        yadj, sc.componentRootElement, -1);
1996:            }
1997:
1998:            // XXX HACKY CODE! Clean up once we agree on the UI & operation for this!
1999:            public void notifyScrolled() {
2000:                if (!PAINT_SELECTION_HIERARCHY) {
2001:                    return;
2002:                }
2003:
2004:                // Gotta repaint to ensure that we place the selection
2005:                // hierarchy view on the right line
2006:                if (isSelectionEmpty()) {
2007:                    return;
2008:                }
2009:
2010:                PageBox pageBox = webform.getPane().getPageBox();
2011:
2012:                if (pageBox == null) {
2013:                    return;
2014:                }
2015:
2016:                JViewport viewport = pageBox.getViewport();
2017:                Point p = viewport.getViewPosition();
2018:                Dimension d = viewport.getExtentSize();
2019:                FontMetrics metrics = webform.getPane().getMetrics();
2020:                int h = metrics.getHeight() + 1;
2021:                int y = (p.y + d.height) - h;
2022:
2023:                if (y != selectionViewPos) {
2024:                    webform.getPane().repaint();
2025:                }
2026:            }
2027:
2028:            // XXX HACKY CODE! Clean up once we agree on the UI & operation for this!
2029:            private int paintOrSelectAncestor(Graphics2D g2d,
2030:                    FontMetrics metrics, FontMetrics boldMetrics,
2031:                    Element componentRootElement, /*MarkupDesignBean bean,*/
2032:                    int x, int ytop, int y,
2033:                    Element selectedComponentRootElement, /*DesignBean selected,*/
2034:                    int target) {
2035:                //        if (bean.getBeanParent() instanceof MarkupDesignBean &&
2036:                ////                !FacesSupport.isSpecialBean(/*webform, */bean)) {
2037:                ////                !Util.isSpecialBean(bean)) {
2038:                //                !WebForm.getDomProviderService().isSpecialComponent(
2039:                //                    WebForm.getDomProviderService().getComponentRootElementForMarkupDesignBean(bean))) {
2040:                if (!webform.getDomProviderService().isSpecialComponent(
2041:                        componentRootElement)) {
2042:                    //            x = paintOrSelectAncestor(g2d, metrics, boldMetrics,
2043:                    //                    (MarkupDesignBean)bean.getBeanParent(), x, ytop, y, selected, target);
2044:                    x = paintOrSelectAncestor(g2d, metrics, boldMetrics,
2045:                            webform.getDomProviderService().getParentComponent(
2046:                                    componentRootElement), x, ytop, y,
2047:                            selectedComponentRootElement, target);
2048:
2049:                    if (x < 0) {
2050:                        return x;
2051:                    }
2052:                }
2053:
2054:                //        String s = bean.getInstanceName();
2055:                //
2056:                //        if (s == null) {
2057:                //            s = "<unknown>";
2058:                //        }
2059:                //
2060:                //        if (x > SELECTIONVIEW_LEFT) {
2061:                //            s = "- " + bean.getInstanceName();
2062:                //        }
2063:                String s = webform.getDomProviderService().getInstanceName(
2064:                        componentRootElement);
2065:                if (s == null) {
2066:                    s = "<unknown>"; // TODO I18N
2067:                }
2068:
2069:                if (g2d != null) { // painting, not selecting
2070:
2071:                    //            if (bean == selected) {
2072:                    if (componentRootElement == selectedComponentRootElement) {
2073:                        g2d.setFont(boldMetrics.getFont());
2074:                    } else {
2075:                        g2d.setFont(metrics.getFont());
2076:                    }
2077:
2078:                    // TODO - icon here?
2079:                }
2080:
2081:                if (paintBeanIcon) {
2082:                    //            BeanInfo bi = bean.getBeanInfo();
2083:                    //            Image icon = null;
2084:                    //
2085:                    //            if (bi != null) {
2086:                    //                icon = bi.getIcon(BeanInfo.ICON_COLOR_16x16);
2087:                    Image icon = webform.getDomProviderService().getIcon(
2088:                            componentRootElement);
2089:
2090:                    if (icon != null) {
2091:                        if (g2d != null) {
2092:                            float ix = (float) x;
2093:                            float iy = (float) ytop;
2094:                            transform.setToTranslation(ix, iy);
2095:                            g2d.drawImage(icon, transform, null);
2096:                        }
2097:
2098:                        x += (16 + 2); // spacing
2099:                    }
2100:                    //            }
2101:                }
2102:
2103:                if (g2d != null) {
2104:                    g2d.drawString(s, x, y);
2105:
2106:                    // XXX restore font?
2107:                }
2108:
2109:                //        if (bean == selected) {
2110:                if (componentRootElement == selectedComponentRootElement) {
2111:                    x += boldMetrics.stringWidth(s);
2112:                } else {
2113:                    x += metrics.stringWidth(s);
2114:                }
2115:
2116:                x += 5; // spacing
2117:
2118:                if (g2d == null) {
2119:                    // See if we've gone past the x position where the user
2120:                    // clicked on a component, thus this must be the item we're
2121:                    // interested in
2122:                    if (x > target) {
2123:                        //                setSelected(bean, true);
2124:                        setSelected(componentRootElement, true);
2125:
2126:                        return -1;
2127:                    }
2128:                }
2129:
2130:                return x;
2131:            }
2132:
2133:            // XXX HACKY CODE! Clean up once we agree on the UI & operation for this!
2134:            void selectAncestor(int targetx, int targety) {
2135:                if (isSelectionEmpty()) {
2136:                    return;
2137:                }
2138:
2139:                PageBox pageBox = webform.getPane().getPageBox();
2140:
2141:                if (pageBox == null) {
2142:                    return;
2143:                }
2144:
2145:                FontMetrics metrics = webform.getPane().getMetrics();
2146:                FontMetrics boldMetrics = webform.getPane().getBoldMetrics();
2147:                int x = 1;
2148:                int y = selectionViewPos;
2149:                int yadj = (y + metrics.getHeight()) - metrics.getDescent();
2150:                //        Iterator it = selected.iterator();
2151:                //        assert it.hasNext();
2152:                //
2153:                //        FormObject fo = (FormObject)it.next();
2154:                //        MarkupDesignBean currentBean = fo.component;
2155:                Iterator<SelectedComponent> it = selectedComponents.iterator();
2156:                assert it.hasNext();
2157:                SelectedComponent sc = it.next();
2158:                //        MarkupDesignBean currentBean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(sc.componentRootElement);
2159:
2160:                //        MarkupDesignBean leafBean = leaf;
2161:                //        MarkupDesignBean leafBean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(leaf);
2162:
2163:                //        if (leafBean == null) {
2164:                //            leafBean = currentBean;
2165:                //        }
2166:                if (leaf == null) {
2167:                    leaf = sc.componentRootElement;
2168:                }
2169:
2170:                //        paintOrSelectAncestor(null, metrics, boldMetrics, leafBean, x, y, yadj, currentBean, targetx);
2171:                paintOrSelectAncestor(null, metrics, boldMetrics, leaf, x, y,
2172:                        yadj, sc.componentRootElement, targetx);
2173:            }
2174:
2175:            /**
2176:             * Set the activated nodes for the top component bound to this selection
2177:             * manager to match the current component.
2178:             * If there is a component (or multiple components) selected,
2179:             * the nodes will reflect these components, otherwise a document node
2180:             * is chosen.
2181:             * @todo If the selection MATCHES what is already shown, don't do anything.
2182:             */
2183:            public void updateNodes() {
2184:                /* No - this is too risky; for example, if you right click on
2185:                   a component it must be selected immediately (since the context
2186:                   menu is keyed off the activated nodes list). So I've gotta
2187:                   call updateNodesImmediate() in that case. Gotta think about
2188:                   this some more before doing it.
2189:                 */
2190:                if (refreshTimer != null) {
2191:                    refreshTimer.stop();
2192:                    refreshTimer = null;
2193:                }
2194:
2195:                refreshTimer = new Timer(NODE_REFRESH_DELAY,
2196:                        new ActionListener() {
2197:                            public void actionPerformed(ActionEvent evt) {
2198:                                refreshTimer = null;
2199:                                updateNodesImmediate();
2200:                            }
2201:                        });
2202:                refreshTimer.setRepeats(false);
2203:                refreshTimer.setCoalesce(true);
2204:                refreshTimer.start();
2205:            }
2206:
2207:            /** Return true iff there is a pending node update scheduled */
2208:            public boolean isNodeUpdatePending() {
2209:                return refreshTimer != null;
2210:            }
2211:
2212:            //    private void releaseNodes() {
2213:            //        // There is most likely a better way to do this Tor, its to allow me to get further with
2214:            //        // leaks.
2215:            //        if (prevNodes != null) {
2216:            ////            // Ensure that the property change listeners are cleared out.
2217:            ////            // We could consider using weak listeners too.
2218:            ////            for (int i = 0; i < prevNodes.length; i++) {
2219:            ////                if (prevNodes[i] instanceof DesignBeanNode) {
2220:            ////                    ((DesignBeanNode)prevNodes[i]).setDataObject(null);
2221:            //////                } else if (prevNodes[i] instanceof DocumentCompNode) {
2222:            //////                    ((DocumentCompNode)prevNodes[i]).setDataObject(null);
2223:            ////                } else {
2224:            ////                    ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
2225:            ////                            new IllegalStateException("Not expected node=" + prevNodes[i])); // NOI18N
2226:            ////                }
2227:            ////            }
2228:            //
2229:            //            prevNodes = null;
2230:            //        }
2231:            //    }
2232:
2233:            /**
2234:             * Same as {@link updateNodes} but this request is processed immediately/synchronously
2235:             */
2236:            public void updateNodesImmediate() {
2237:                if (refreshTimer != null) {
2238:                    refreshTimer.stop();
2239:                    refreshTimer = null;
2240:                }
2241:
2242:                ////        releaseNodes();
2243:                //
2244:                ////        DataObject dobj = webform.getDataObject();
2245:                ////        DesignerTopComp topcomp = webform.getTopComponent();
2246:                //
2247:                ////        // Ensure that the tray is no longer appearing selected
2248:                ////        topcomp.clearTraySelection();
2249:                //
2250:                ////        if ((selected != null) && (selected.size() > 0)) {
2251:                //////            Iterator it = selected.iterator();
2252:                ////
2253:                ////            //Node[] nodes = new Node[selected.size()];
2254:                ////            ArrayList nodes = new ArrayList(selected.size());
2255:                ////
2256:                //////            while (it.hasNext()) {
2257:                //////                FormObject fo = (FormObject)it.next();
2258:                ////            for (FormObject fo : selected) {
2259:                ////                DesignBean component = fo.component;
2260:                //        if (!selectedComponents.isEmpty()) {
2261:                //            //Node[] nodes = new Node[selected.size()];
2262:                //            List<Node> nodes = new ArrayList<Node>(selectedComponents.size());
2263:                //            for (SelectedComponent sc : selectedComponents) {
2264:                ////                DesignBean component = WebForm.getDomProviderService().getMarkupDesignBeanForElement(sc.componentRootElement);
2265:                ////                Node n = DesigntimeIdeBridgeProvider.getDefault().getNodeRepresentation(component);
2266:                //                Node n = WebForm.getDomProviderService().getNodeRepresentation(sc.componentRootElement);
2267:                ////                n.setDataObject(dobj);
2268:                //                nodes.add(n);
2269:                //            }
2270:                //
2271:                //            Node[] nds = nodes.toArray(new Node[nodes.size()]);
2272:                //
2273:                ////            if (topcomp.isShowing()) {
2274:                ////                topcomp.requestActive();
2275:                ////            }
2276:                //
2277:                ////            DesignerUtils.setActivatedNodes(topcomp, nds);
2278:                //            webform.tcSetActivatedNodes(nds);
2279:                ////            prevNodes = nds;
2280:                //            
2281:                //        } else {
2282:                //// <>
2283:                ////            Node[] nodes = new Node[1];
2284:                ////
2285:                ////            if (documentComponent == null) {
2286:                ////                documentComponent = new DocumentComp(webform);
2287:                ////            } else {
2288:                ////                documentComponent.sync();
2289:                ////            }
2290:                ////
2291:                ////            DocumentCompNode node = new DocumentCompNode(documentComponent, dobj);
2292:                ////
2293:                ////            //node.setDataObject(dobj);
2294:                ////            nodes[0] = node;
2295:                ////
2296:                ////            if (topcomp.isShowing()) {
2297:                ////                topcomp.requestActive();
2298:                ////            }
2299:                ////
2300:                ////            DesignerUtils.setActivatedNodes(topcomp, nodes);
2301:                ////            prevNodes = nodes;
2302:                //// ====
2303:                //            // XXX Ugly way of maintaining activated nodes.
2304:                //            // TODO Redesign activated nodes retrieval/setting.
2305:                //            Node[] nodes;
2306:                ////            FacesModel facesModel = webform.getModel();
2307:                ////            DesignBean rootBean = facesModel.getRootBean();
2308:                ////            if (rootBean == null) {
2309:                ////                // XXX If the model is busted then it is supposed to be OK, there is an error, see e.g. #6478860.
2310:                ////                if (!facesModel.isBusted()) {
2311:                ////                    ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
2312:                ////                            new IllegalStateException("Invalid FacesModel, it is not busted and its root design bean is null, facesModel=" + facesModel)); // NOI18N
2313:                ////                }
2314:                ////                nodes = new Node[0];
2315:                ////            } else {
2316:                ////                Node n = DesigntimeIdeBridgeProvider.getDefault().getNodeRepresentation(rootBean);
2317:                //////                n.setDataObject(dobj);
2318:                ////                nodes = new Node[] {n};
2319:                ////            }
2320:                //            Node rootNode = webform.getRootBeanNode();
2321:                //            nodes = rootNode == null ? new Node[0] : new Node[] {rootNode};
2322:                //            
2323:                ////            DesignerUtils.setActivatedNodes(topcomp, nodes);
2324:                //            webform.tcSetActivatedNodes(nodes);
2325:                ////            // XXX Why is this here? Why it should get active based on node setting?
2326:                ////            if (topcomp.isShowing()) {
2327:                ////                topcomp.requestActive();
2328:                ////            }
2329:                ////            prevNodes = nodes;
2330:                //// </>
2331:                //        }
2332:                //
2333:                //        // XXX #101248 This seems to be needless.
2334:                ////        if(!webform.isGridMode()) {
2335:                ////            selectTextBetweenSelectedNodes();
2336:                ////        }
2337:                webform
2338:                        .fireSelectionChanged(new SelectionDesignerEvent(
2339:                                webform));
2340:            }
2341:
2342:            private static class SelectionDesignerEvent implements 
2343:                    DesignerEvent {
2344:                private final WebForm webForm;
2345:
2346:                public SelectionDesignerEvent(WebForm webForm) {
2347:                    this .webForm = webForm;
2348:                }
2349:
2350:                public Designer getDesigner() {
2351:                    return webForm;
2352:                }
2353:
2354:                public Box getBox() {
2355:                    return null;
2356:                }
2357:            } // End of SelectionDesignerEvent.
2358:
2359:            //    private void selectTextBetweenSelectedNodes() {
2360:            ////        Position start = null, end = null;
2361:            //        DomPosition start = null;
2362:            //        DomPosition end = null;
2363:            //        
2364:            ////        if ((selected != null) && (selected.size() > 0)) {
2365:            //////            Iterator it = selected.iterator();
2366:            ////            Position startNode, endNode;
2367:            //////            while (it.hasNext()) {
2368:            //////                FormObject fo = (FormObject)it.next();
2369:            ////            for (FormObject fo : selected) {
2370:            ////                startNode = Position.create(fo.component.getElement(), false);
2371:            //        if (!selectedComponents.isEmpty()) {
2372:            ////            Position startNode, endNode;
2373:            //            DomPosition startNode;
2374:            //            DomPosition endNode;
2375:            //            
2376:            //            for (SelectedComponent sc : selectedComponents) {
2377:            ////                Element sourceElement = WebForm.getDomProviderService().getMarkupDesignBeanForElement(sc.componentRootElement).getElement();
2378:            //                Element sourceElement = WebForm.getDomProviderService().getSourceElement(sc.componentRootElement);
2379:            ////                startNode = Position.create(sourceElement, false);
2380:            //                startNode = webform.createDomPosition(sourceElement, false);
2381:            //                
2382:            //                if(start == null || startNode.isEarlierThan(start)) {
2383:            //                    start = startNode;
2384:            //                }
2385:            ////                endNode = Position.create(fo.component.getElement(), true);
2386:            ////                endNode = Position.create(sourceElement, true);
2387:            //                endNode = webform.createDomPosition(sourceElement, true);
2388:            //                
2389:            //                if(end == null || end.isEarlierThan(endNode)) {
2390:            //                    end = endNode;
2391:            //                }
2392:            //            }
2393:            //        } else {
2394:            ////            start = Position.NONE;
2395:            ////            end   = Position.NONE;
2396:            //            start = DomPosition.NONE;
2397:            //            end   = DomPosition.NONE;
2398:            //        }
2399:            ////        if(webform.getPane().getCaret() != null) {
2400:            //        if(webform.getPane().hasCaret()) {
2401:            ////            webform.getPane().getCaret().setDot(start);
2402:            ////            webform.getPane().getCaret().moveDot(end);
2403:            //            webform.getPane().setCaretDot(start);
2404:            //            webform.getPane().moveCaretDot(end);
2405:            //        }
2406:            //    }
2407:
2408:            //    /** Return set of currently selected nodes */
2409:            //    public Node[] getSelectedNodes() {
2410:            //        if (refreshTimer != null) {
2411:            //            // The nodes may not be current - there's a pending update. Cancel the
2412:            //            // update request and update the nodes immediately instead
2413:            //            refreshTimer.stop();
2414:            //            refreshTimer = null;
2415:            //            updateNodesImmediate();
2416:            //        }
2417:            //
2418:            ////        return webform.getTopComponent().getActivatedNodes();
2419:            //        return webform.tcGetActivatedNodes();
2420:            //    }
2421:
2422:            /** Return the primary selection, if any. The primary is the most recently
2423:             * "touched" DesignBean in the selection. For example, if you swipe select
2424:             * a set of 10 components and then right click on one of them, all are selected
2425:             * but the clicked-on component is primary. Similarly, if you shift-click toggle
2426:             * components in the selection, the most recently clicked component is primary.
2427:             * This component is highlighted using a different color than the rest.
2428:             */
2429:            public/*MarkupDesignBean*/Element getPrimary() {
2430:                return primary;
2431:                //        return WebForm.getDomProviderService().getMarkupDesignBeanForElement(primary);
2432:            }
2433:
2434:            /**
2435:             * Choose a bean as the primary selection bean
2436:             */
2437:            public void setPrimary(/*MarkupDesignBean*/Element primary) {
2438:                this .primary = primary;
2439:                //        this.primary = getComponentRootElementForMarkupDesignBean(primary);
2440:            }
2441:
2442:            /**
2443:             * XXX Bad architecture.
2444:             * TODO Get rid of this, and update the primary as selection changes.
2445:             * 
2446:             * Ask the selection manager to pick a primary selection object, if it has
2447:             * one or more selection objects but none designated as primary.
2448:             * If one is already primary, it is kept as the primary.
2449:             */
2450:            public void pickPrimary() {
2451:                if (primary == null) {
2452:                    //            Iterator it = selected.iterator();
2453:                    //            FormObject fob = (FormObject)it.next();
2454:                    //            primary = fob.component;
2455:                    Iterator<SelectedComponent> it = selectedComponents
2456:                            .iterator();
2457:                    SelectedComponent sc = it.next();
2458:                    primary = sc.componentRootElement;
2459:                }
2460:            }
2461:
2462:            //    /**
2463:            //     * Return an iterator for iterating through the MarkupDesignBeans in the
2464:            //     * selection set.
2465:            //     */
2466:            //    public Iterator<MarkupDesignBean> iterator() {
2467:            //        return new BeanIterator();
2468:            //    }
2469:
2470:            //    public MarkupDesignBean[] getSelectedMarkupDesignBeans() {
2471:            //        List<MarkupDesignBean> markupDesignBeans = new ArrayList<MarkupDesignBean>();
2472:            //        for (Iterator<MarkupDesignBean> it = iterator(); it.hasNext(); ) {
2473:            //            MarkupDesignBean markupDesignBean = it.next();
2474:            //            if (markupDesignBean != null && !markupDesignBeans.contains(markupDesignBean)) {
2475:            //                markupDesignBeans.add(markupDesignBean);
2476:            //            }
2477:            //        }
2478:            //        return markupDesignBeans.toArray(new MarkupDesignBean[markupDesignBeans.size()]);
2479:            //    }
2480:            public Element[] getSelectedComponentRootElements() {
2481:                List<Element> componentRootElements = new ArrayList<Element>();
2482:                List<SelectedComponent> scs = new ArrayList<SelectedComponent>(
2483:                        selectedComponents);
2484:                for (SelectedComponent selectedComponent : scs) {
2485:                    if (selectedComponent == null) {
2486:                        continue;
2487:                    }
2488:                    Element componentRootElement = selectedComponent.componentRootElement;
2489:                    if (componentRootElement != null) {
2490:                        componentRootElements.add(componentRootElement);
2491:                    }
2492:                }
2493:                return componentRootElements
2494:                        .toArray(new Element[componentRootElements.size()]);
2495:            }
2496:
2497:            // --------------------------------------------------------------------
2498:            // Selection Management: Deal with the selection-set
2499:            // --------------------------------------------------------------------
2500:            // The selection set consists of FormObjects, where each page object
2501:            // represents a selectable object on the page (which may correspond
2502:            // to toolbar components).
2503:
2504:            //    // TODO JSF specific, get rid of it, replace it with the latter.
2505:            //    /** Represents a "component" in the view. Not called component to avoid
2506:            //     * confusion with the component class of the actual component from the
2507:            //     * toolbar. This is simply a wrapper object used to hold information
2508:            //     * pertaining to selections etc. */
2509:            //    private static class FormObject { // TODO Rename SelectedComponent
2510:            //
2511:            //        MarkupDesignBean component = null;
2512:            //
2513:            //        /** Resizability of this component. A bit mask representing state
2514:            //         * according to Constants.ResizeConstraints. */
2515:            //        int resizeConstraints;
2516:            //    }
2517:
2518:            // TODO This should replace the above usage.
2519:            /** Represents a "component" in the view. Not called component to avoid
2520:             * confusion with the component class of the actual component from the
2521:             * toolbar. This is simply a wrapper object used to hold information
2522:             * pertaining to selections etc. */
2523:            private static class SelectedComponent {
2524:                private Element componentRootElement;
2525:                /** Resizability of this component. A bit mask representing state
2526:                 * according to Constants.ResizeConstraints. */
2527:                //        private int resizeConstraints;
2528:                private ResizeConstraint[] resizeConstraints;
2529:            } // End of SelectedComponent.
2530:
2531:            //    /** Iterator for iterating through the selection contents */
2532:            //    private class BeanIterator implements Iterator<MarkupDesignBean> {
2533:            //        private Iterator<SelectedComponent> iterator;
2534:            //
2535:            //        private BeanIterator() {
2536:            ////            if ((selected != null) && (selected.size() > 0)) {
2537:            ////                iterator = selected.iterator();
2538:            ////            }
2539:            //            iterator = selectedComponents.iterator();
2540:            //        }
2541:            //
2542:            //        public boolean hasNext() {
2543:            //            if (iterator != null) {
2544:            //                return iterator.hasNext();
2545:            //            } else {
2546:            //                return false;
2547:            //            }
2548:            //        }
2549:            //
2550:            //        public MarkupDesignBean next() {
2551:            ////            FormObject fo = (FormObject)iterator.next();
2552:            ////
2553:            ////            return fo.component;
2554:            //            SelectedComponent sc = iterator.next();
2555:            //            return WebForm.getDomProviderService().getMarkupDesignBeanForElement(sc.componentRootElement);
2556:            //        }
2557:            //
2558:            //        public void remove() {
2559:            //            throw new UnsupportedOperationException();
2560:            //        }
2561:            //    }
2562:
2563:            void selectBean(/*DesignBean select*/Element componentRootElement) {
2564:                //        // XXX SelectionManager properly dispatches to DesignerTopComp now
2565:                //        if (select != null) {
2566:                ////            if (DesignerTopComp.SHOW_TRAY && LiveUnit.isTrayBean(select)) {
2567:                ////                webform.getTopComponent().selectTrayBean(select);
2568:                ////            } else
2569:                ////            if (LiveUnit.isVisualBean(select)) {
2570:                //                selectComponents(new DesignBean[] { select }, true);
2571:                ////            } else {
2572:                ////                // Some non-tray, non-visual bean, such as a validator.
2573:                ////                // Simply show it as selected for now.
2574:                ////                webform.getTopComponent().selectNonTrayBeans(new DesignBean[] { select });
2575:                ////            }
2576:                //
2577:                //            select = null;
2578:                //        }
2579:                if (componentRootElement != null) {
2580:                    selectComponents(new Element[] { componentRootElement },
2581:                            true);
2582:                }
2583:            }
2584:
2585:            //    /** XXX Copied from DesignerActions. */
2586:            //    public static void selectParent(/*DesignBean designBean*/Element componentRootElement) {
2587:            ////        if (designBean == null) {
2588:            ////            return;
2589:            ////        }
2590:            ////        WebForm webform = WebForm.findWebFormForDesignContext(designBean.getDesignContext());
2591:            ////        if (webform == null) {
2592:            ////            return;
2593:            ////        }
2594:            ////        
2595:            ////        webform.getSelection().doSelectParent(designBean);
2596:            //        if (componentRootElement == null) {
2597:            //            return;
2598:            //        }
2599:            //        WebForm webform = WebForm.findWebFormForElement(componentRootElement);
2600:            //        if (webform == null) {
2601:            //            return;
2602:            //        }
2603:            //        
2604:            //        webform.getSelection().doSelectParent(componentRootElement);
2605:            //    }
2606:            //    
2607:            //    private void doSelectParent(/*DesignBean designBean*/Element componentRootElement) {
2608:            //        webform.getManager().finishInlineEditing(false);
2609:            //
2610:            ////        SelectionManager sm = webform.getSelection();
2611:            //
2612:            ////        DesignBean designBean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(componentRootElement);
2613:            ////        if (designBean == null) {
2614:            ////            return;
2615:            ////        }
2616:            //        if (componentRootElement == null) {
2617:            //            return;
2618:            //        }
2619:            //        
2620:            ////        if (!canSelectParent(designBean)) {
2621:            //        if (!canSelectParent(componentRootElement)) {
2622:            //            if (!webform.isGridMode()) {
2623:            //                // in flow mode, allow you to escape your way to the top;
2624:            //                // clear selection and show document properties
2625:            //                clearSelection(true);
2626:            //            }
2627:            //
2628:            //            return;
2629:            //        }
2630:            //
2631:            //        // Find the closest selectable parent that is actually
2632:            //        // selectable!
2633:            ////        DesignBean parent = designBean.getBeanParent();
2634:            //        Element parentComponentRootElement = WebForm.getDomProviderService().getParentComponent(componentRootElement);
2635:            ////        ModelViewMapper mapper = webform.getMapper();
2636:            //
2637:            ////        while (parent != null) {
2638:            //        while (parentComponentRootElement != null) {
2639:            //            // Find the visual (non-form, non-root) parent and select it
2640:            ////            Element element = FacesSupport.getElement(parent);
2641:            ////            Element element = Util.getElement(parent);
2642:            ////            Element element = WebForm.getDomProviderService().getElement(parent);
2643:            //            Element element = WebForm.getDomProviderService().getSourceElement(parentComponentRootElement);
2644:            //
2645:            //            if (element != null) {
2646:            ////                CssBox box = mapper.findBox(element);
2647:            //                CssBox box = ModelViewMapper.findBox(webform.getPane().getPageBox(), element);
2648:            //
2649:            //                if (box != null) {
2650:            ////                    selectComponents(new DesignBean[] { parent }, true);
2651:            ////                    if (parent instanceof MarkupDesignBean) {
2652:            //                        selectComponents(new Element[] { parentComponentRootElement }, true);
2653:            //                        break;
2654:            ////                    }
2655:            //                }
2656:            //            }
2657:            //
2658:            ////            parent = parent.getBeanParent();
2659:            //            parentComponentRootElement = WebForm.getDomProviderService().getParentComponent(parentComponentRootElement);
2660:            //        }
2661:            //    }
2662:
2663:            void selectComponent(Element componentRootElement) {
2664:                if (componentRootElement == null) {
2665:                    return;
2666:                }
2667:
2668:                CssBox box = ModelViewMapper.findBox(webform.getPane()
2669:                        .getPageBox(), componentRootElement);
2670:                if (box != null) {
2671:                    selectComponents(new Element[] { componentRootElement },
2672:                            true);
2673:                }
2674:            }
2675:
2676:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.