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: package org.netbeans.modules.visualweb.designer;
0042:
0043: import java.beans.PropertyVetoException;
0044: import org.netbeans.modules.visualweb.api.designer.Designer;
0045: import org.netbeans.modules.visualweb.api.designer.Designer.Box;
0046: import org.netbeans.modules.visualweb.api.designer.DomProvider.DomPosition;
0047: import org.netbeans.modules.visualweb.api.designer.DomProvider.DomPosition.Bias;
0048: import org.netbeans.modules.visualweb.api.designer.markup.MarkupService;
0049: import org.netbeans.modules.visualweb.css2.ExternalDocumentBox;
0050: import org.netbeans.modules.visualweb.spi.designer.Decoration;
0051: import java.awt.Component;
0052: import java.awt.Cursor;
0053: import java.awt.Dimension;
0054: import java.awt.EventQueue;
0055: import java.awt.Graphics2D;
0056: import java.awt.Image;
0057: import java.awt.Point;
0058: import java.awt.Rectangle;
0059: import java.awt.datatransfer.Transferable;
0060: import java.awt.event.ActionEvent;
0061: import java.awt.event.ActionListener;
0062: import java.awt.event.MouseAdapter;
0063: import java.awt.event.MouseEvent;
0064: import java.awt.event.MouseMotionListener;
0065: import java.io.IOException;
0066: import java.lang.ref.WeakReference;
0067: import java.util.ArrayList;
0068: import java.util.List;
0069: import java.util.logging.Level;
0070: import java.util.logging.Logger;
0071: import javax.swing.Action;
0072:
0073: import javax.swing.SwingUtilities;
0074: import javax.swing.Timer;
0075: import org.netbeans.modules.visualweb.api.designer.Designer.DesignerClickEvent;
0076: import org.netbeans.modules.visualweb.api.designer.Designer.DesignerEvent;
0077: import org.netbeans.modules.visualweb.api.designer.Designer.DesignerPopupEvent;
0078: import org.netbeans.modules.visualweb.api.designer.cssengine.CssProvider;
0079: import org.netbeans.modules.visualweb.api.designer.cssengine.CssValue;
0080: import org.netbeans.modules.visualweb.api.designer.cssengine.XhtmlCss;
0081: import org.netbeans.spi.palette.PaletteController;
0082:
0083: import org.openide.awt.MouseUtils;
0084: import org.openide.nodes.Node;
0085: import org.openide.util.ContextAwareAction;
0086: import org.openide.util.Lookup;
0087: import org.openide.windows.TopComponent;
0088: import org.openide.windows.WindowManager;
0089: import org.w3c.dom.Element;
0090:
0091: import org.netbeans.modules.visualweb.css2.BoxType;
0092: import org.netbeans.modules.visualweb.css2.ContainerBox;
0093: import org.netbeans.modules.visualweb.css2.CssBox;
0094: import org.netbeans.modules.visualweb.css2.DomInspector;
0095: import org.netbeans.modules.visualweb.css2.LineBox;
0096: import org.netbeans.modules.visualweb.css2.LineBoxGroup;
0097: import org.netbeans.modules.visualweb.css2.ModelViewMapper;
0098: import org.netbeans.modules.visualweb.css2.PageBox;
0099: import org.netbeans.modules.visualweb.css2.SpaceBox;
0100: import org.netbeans.modules.visualweb.css2.TextBox;
0101:
0102: import org.netbeans.modules.visualweb.designer.WebForm.DefaultDesignerEvent;
0103: import org.openide.explorer.ExplorerManager;
0104:
0105: import org.w3c.dom.Text;
0106:
0107: // For CVS archaeology: Most of the code in this file used to be in SelectionManager.java
0108:
0109: /**
0110: * This class manages the interactions in the designer surface:
0111: * mouse gestures, keyboard gestures, and sequence operations like
0112: * drags, moves, resizes, etc.
0113: *
0114: * @author Tor Norbye
0115: */
0116: public class InteractionManager {
0117:
0118: // XXX Moved from former MouseUtils_RAVE. What is this?
0119: private static int DOUBLE_CLICK_DELTA = 300;
0120:
0121: // Log info pertaining to selection drawing
0122: public static final boolean ENABLE_DOM_INSPECTOR = true; // DOM inspector
0123:
0124: // No cursor feedback - used to avoid triggering
0125: // box-search related methods during development
0126: private static final boolean SKIP_MOUSE_MOTION = false;
0127: private final WebForm webform;
0128: private InlineEditor inlineEditor; // TODO - make this an Interaction as well
0129: private Interaction interaction;
0130:
0131: // XXX Should the insert mode box logic reside within the PageBox?
0132: private CssBox insertModeBox = null;
0133: private CssBox selectedBox = null;
0134: // private DesignBean highlighted = null;
0135: private Element highlightedComponentRootElement;
0136: // private MarkupMouseRegion highlightedRegion = null;
0137: private Element highlightedRegionElement;
0138:
0139: /** Mouse handler tracking mouse motion, clicks, dragging, etc. */
0140: private MouseHandler mouseHandler;
0141: private Marquee sizer;
0142: private Dragger dragger;
0143: private Cursor insertCursor = null;
0144: private Cursor linkedCursor = null;
0145:
0146: /** Creates a new instance of InteractionManager */
0147: public InteractionManager(WebForm webform) {
0148: if (webform == null) {
0149: throw new NullPointerException("Parameter webform is null!"); // NOI18N
0150: }
0151:
0152: this .webform = webform;
0153: }
0154:
0155: /** Notify the selection manager that the box hierarchy has changed,
0156: * so update the insert box reference if necessary */
0157: public void updateInsertBox() {
0158: if (insertModeBox == null) {
0159: return;
0160: }
0161:
0162: if (insertModeBox instanceof PageBox) {
0163: insertModeBox = webform.getPane().getPageBox();
0164:
0165: return;
0166: }
0167:
0168: Element element = insertModeBox.getElement();
0169: // insertModeBox = CssBox.getBox(element);
0170: insertModeBox = webform.findCssBoxForElement(element);
0171: }
0172:
0173: /** Return the box whose contents are being edited. Will be null when we're
0174: * not in edit mode.
0175: * @todo Rename from "insert mode" to "text edit" mode or something like that.
0176: */
0177: public CssBox getInsertModeBox() {
0178: return insertModeBox;
0179: }
0180:
0181: void drawInlineEditorBox(Graphics2D g2d, Rectangle rect) {
0182: // Tied closely to selection nib painting so implemented in the SelectionManager
0183: webform.getSelection().paintInlineEditorBox(g2d, rect);
0184: }
0185:
0186: /** Set the view which should be in "insert mode" (have an insert
0187: * cursor and a thick component marker rectangle). May be null
0188: * to turn off insert mode.
0189: */
0190: public void setInsertBox(CssBox box, MouseEvent event) {
0191: DesignerPane pane = webform.getPane();
0192:
0193: // if ((box != null) && (box == pane.getPageBox()) && webform.getDocument().isGridMode()) {
0194: // if ((box != null) && (box == pane.getPageBox()) && webform.isGridModeDocument()) {
0195: if ((box != null) && (box == pane.getPageBox())
0196: && webform.isGridMode()) {
0197: box = null;
0198: }
0199:
0200: if (insertModeBox != box) {
0201: insertModeBox = box;
0202:
0203: // See if this is a simple div which only contains a jsp include tag.
0204: // Those should not be inline editable.
0205: if (box != null) {
0206: // DesignBean bean = box.getDesignBean();
0207: // DesignBean bean = CssBox.getMarkupDesignBeanForCssBox(box);
0208: // if ((bean != null) && bean.getInstance() instanceof org.netbeans.modules.visualweb.xhtml.Div) {
0209: // if ((bean.getChildBeanCount() == 1) &&
0210: // bean.getChildBean(0).getInstance() instanceof org.netbeans.modules.visualweb.xhtml.Jsp_Directive_Include) {
0211: // insertModeBox = null;
0212: //
0213: // return;
0214: // }
0215: // }
0216: // XXX Doesn't allow to insert into include (fragment).
0217: Element componentRootElement = CssBox
0218: .getElementForComponentRootCssBox(box);
0219: if (webform.getDomProviderService()
0220: .isIncludeComponentBox(componentRootElement)) {
0221: insertModeBox = null;
0222: return;
0223: }
0224: }
0225:
0226: // DesignerCaret dc = pane.getCaret();
0227:
0228: // boolean showCaret = (box != null) || !webform.getDocument().isGridMode();
0229: // boolean showCaret = (box != null) || !webform.isGridModeDocument();
0230: boolean showCaret = (box != null) || !webform.isGridMode();
0231:
0232: // if (showCaret == (dc != null)) {
0233: if (showCaret == pane.hasCaret()) {
0234: return;
0235: }
0236:
0237: if (showCaret) {
0238: // dc = pane.getPaneUI().createCaret();
0239: // pane.setCaret(dc);
0240: pane.createCaret();
0241:
0242: // Position pos = Position.NONE;
0243: DomPosition pos = DomPosition.NONE;
0244:
0245: if (event != null) {
0246: // pos = pane.viewToModel(event.getPoint());
0247: pos = webform.viewToModel(event.getPoint());
0248:
0249: // if (pos != Position.NONE) {
0250: if (pos != DomPosition.NONE) {
0251: // pos = DesignerUtils.checkPosition(pos, true, /*webform*/webform.getManager().getInlineEditor());
0252: // pos = ModelViewMapper.findValidPosition(pos, true, /*webform*/webform.getManager().getInlineEditor());
0253: pos = ModelViewMapper
0254: .findValidPosition(webform, pos, true, /*webform*/
0255: webform.getManager()
0256: .getInlineEditor());
0257: }
0258:
0259: // if ((pos != Position.NONE) && (box.getDesignBean() != null)) {
0260: // pos = new Position(box.getDesignBean().getElement(), 0, Bias.FORWARD);
0261: // MarkupDesignBean markupDesignBean = CssBox.getMarkupDesignBeanForCssBox(box);
0262: // if ((pos != Position.NONE) && (markupDesignBean != null)) {
0263: // pos = new Position(markupDesignBean.getElement(), 0, Bias.FORWARD);
0264: Element componentRootElement = CssBox
0265: .getElementForComponentRootCssBox(box);
0266: // if ((pos != Position.NONE) && (componentRootElement != null)) {
0267: if ((pos != DomPosition.NONE)
0268: && (componentRootElement != null)) {
0269: Element sourceElement = MarkupService
0270: .getSourceElementForElement(componentRootElement);
0271: if (sourceElement != null) {
0272: // pos = new Position(sourceElement, 0, Bias.FORWARD);
0273: // pos = Position.create(sourceElement, 0, Bias.FORWARD);
0274: pos = webform.createDomPosition(
0275: sourceElement, 0, Bias.FORWARD);
0276: }
0277: }
0278: }
0279:
0280: // pane.setCaretPosition(pos);
0281: pane.setCaretDot(pos);
0282:
0283: pane.setCursor(Cursor
0284: .getPredefinedCursor(Cursor.TEXT_CURSOR));
0285:
0286: if (event != null) {
0287: // dc.mousePressed(event);
0288: // dc.mouseClicked(event);
0289: pane.mousePressed(event);
0290: pane.mouseClicked(event);
0291: }
0292:
0293: // dc.setVisible(true);
0294: pane.setCaretVisible(true);
0295: } else {
0296: pane.setCaret(null);
0297:
0298: // XXX Which cursor do we set?
0299: //mouseHandler.mouseMoved(event);
0300: }
0301:
0302: /* TODO: let users edit text-node property children
0303: if (box != null && box.getDesignBean() != null) {
0304: DesignBean lb = box.getDesignBean();
0305: BeanInfo bi = lb.getBeanInfo();
0306: if (bi != null) {
0307:
0308: BeanDescriptor bd = bi.getBeanDescriptor();
0309: Object o = bd.getValue(Constants.BeanDescriptor.TEXT_NODE_PROPERTY);
0310: }
0311: }
0312: */
0313: }
0314: }
0315:
0316: /** Given a box, locate its nearest insert-box. Eg. for a text box,
0317: * the insert box would be the surrounding paragraph box (not for
0318: * example its surrounding italic span box.)
0319: */
0320: private CssBox findInsertBox(CssBox box) {
0321: if (!webform.isGridMode()) {
0322: // XXX No, go wrap up jsf rendered document fragments as
0323: // a single unit so we avoid editing outside its boundaries
0324: // This does however mean that things like jsf buttons
0325: // will be treated as isolated units
0326: return webform.getPane().getPageBox();
0327: }
0328:
0329: // This would be the first block or absolutely positioned
0330: // child of a grid box - where lineboxes don't count.
0331:
0332: /* No longer applicable - markup beans breaks this
0333: while (box != null && box.getDesignBean() != null) {
0334: box = box.getParent();
0335: }
0336: */
0337: CssBox leaf = box;
0338:
0339: while (box != null) {
0340: // We're within a grid panel - no possible insert box
0341: if (box.isGrid()) {
0342: return null;
0343: }
0344:
0345: if (box.getBoxType().isAbsolutelyPositioned()) {
0346: // Allow inserts on something like a <span>, disallow
0347: // it on something like an <img>
0348: if (box instanceof ContainerBox) {
0349: break;
0350: } else {
0351: return null;
0352: }
0353: }
0354:
0355: if ((box.getParent() == null) || box.getParent().isGrid()) {
0356: // We're the child of a grid box; if we're a block or
0357: // absolutely positioned child, this is an insert box,
0358: if ((box.getBoxType() != BoxType.LINEBOX)
0359: && box.isBlockLevel()
0360: && (box instanceof ContainerBox)) {
0361: break;
0362: } else {
0363: // if not we're unattached text within a grid panel;
0364: // this is not editable with an insert box
0365: return null;
0366: }
0367: }
0368:
0369: box = box.getParent();
0370: }
0371:
0372: // Ensure that we're not inside a jsf component, in which case
0373: // we should use the normal hiearchy instead
0374: CssBox curr = (leaf == null) ? null : leaf.getParent();
0375:
0376: while ((curr != null) && (curr != box)) {
0377: // DesignBean b = curr.getDesignBean();
0378: // DesignBean b = CssBox.getMarkupDesignBeanForCssBox(curr);
0379: Element componentRootElement = CssBox
0380: .getElementForComponentRootCssBox(curr);
0381:
0382: // if ((b != null) && FacesSupport.isFacesComponent(b)) {
0383: // if ((b != null) && isFacesComponent(b)) {
0384: // if (b != null && WebForm.getDomProviderService().isFacesComponentBean(b)) {
0385: if (componentRootElement != null
0386: && webform.getDomProviderService()
0387: .isFacesComponent(componentRootElement)) {
0388: return null;
0389: }
0390:
0391: curr = curr.getParent();
0392: }
0393:
0394: return box;
0395: }
0396:
0397: // // XXX Moved from FacesSupport.
0398: // /** Indicate whether this bean represents a JSF bean (vs an html bean) */
0399: // private static boolean isFacesComponent(DesignBean bean) {
0400: // return bean.getInstance() instanceof UIComponent;
0401: // }
0402:
0403: /**
0404: * Report whether we're inline editing a component
0405: */
0406: public boolean isInlineEditing() {
0407: return inlineEditor != null;
0408: }
0409:
0410: public InlineEditor getInlineEditor() {
0411: return inlineEditor;
0412: }
0413:
0414: public void startInlineEditing(Element componentRootElement,
0415: String propertyName) {
0416: if (isInlineEditing()
0417: && getInlineEditor().isEditing(componentRootElement,
0418: propertyName)) {
0419: return;
0420: } else {
0421: finishInlineEditing(false);
0422: }
0423:
0424: CssBox box = ModelViewMapper.findBoxForComponentRootElement(
0425: webform.getPane().getPageBox(), componentRootElement);
0426: //// webform.getTopComponent().requestActive();
0427: // webform.tcRequestActive();
0428: startInlineEditing(componentRootElement, propertyName, box,
0429: true, true, null, false);
0430: }
0431:
0432: /**
0433: * Inline edit the given DesignBean, if the bean supports it.
0434: * If so, inline edit the given bean and return true.
0435: * Otherwise, return false.
0436: *
0437: * @param ensureSelected If true, make sure that the component to be inline edited is also selected
0438: * @param selectText If true, select all the text in the inline section after initiating editing
0439: * @param initialEdit If a non empty string, initiate editing as if the user had typed the string
0440: * @param box The box corresponding to the component click, if any
0441: * @param property The component to be inline edited
0442: * @param propertyName May be null; if so, either the property corresponding to the box clicked should be edited,
0443: * or the default property provided allow default is true
0444: * @param useDefault If true, start editing the property marked default (if any) (marked with a "*" in the metadata)
0445: */
0446: public boolean startInlineEditing(Element componentRootElement, /*MarkupDesignBean lb,*/
0447: String property, CssBox box, boolean ensureSelected,
0448: boolean selectText, String initialEdit, boolean useDefault) {
0449: finishInlineEditing(false);
0450:
0451: if (box == null) {
0452: // box = webform.getMapper().findBox(lb);
0453: box = ModelViewMapper.findBoxForComponentRootElement(
0454: webform.getPane().getPageBox(),
0455: componentRootElement);
0456: }
0457:
0458: // inlineEditor = InlineEditor.getInlineEditor(webform, box, lb, property, useDefault);
0459: inlineEditor = InlineEditor.getInlineEditor(webform, box,
0460: componentRootElement, property, useDefault);
0461:
0462: if (inlineEditor != null) {
0463: SelectionManager sm = webform.getSelection();
0464:
0465: // if (ensureSelected && (!sm.isSelected(lb) || (sm.getNumSelected() > 1))) {
0466: // sm.setSelected(lb, true);
0467: if (ensureSelected
0468: && (!sm.isSelected(componentRootElement) || (sm
0469: .getNumSelected() > 1))) {
0470: sm.setSelected(componentRootElement, true);
0471: }
0472:
0473: //// webform.getTopComponent().requestActive();
0474: // webform.tcRequestActive();
0475:
0476: DesignerPane pane = webform.getPane();
0477: pane.setCursor(Cursor
0478: .getPredefinedCursor(Cursor.TEXT_CURSOR));
0479: inlineEditor.start(selectText, initialEdit);
0480: pane.repaint();
0481:
0482: return true;
0483: }
0484:
0485: return false;
0486: }
0487:
0488: /** If there is an inline editor, finish editing in it. */
0489: public void finishInlineEditing(boolean cancel) {
0490: if (inlineEditor != null) {
0491: try {
0492: inlineEditor.finish(cancel);
0493: } finally {
0494: inlineEditor = null;
0495: }
0496:
0497: webform.getPane().repaint();
0498: }
0499: }
0500:
0501: // /** The user double clicked on the component during -initial- inline editing
0502: // * (e.g. we entered inline editing as part of the first click in a double
0503: // * click) so cancel inline editing and process the double click in the normal
0504: // * way: as a request to open the default event handler. However if there is
0505: // * no default event handler, stay in inline edit mode. */
0506: // public void notifyEditedDoubleClick() {
0507: //// if (webform.getActions().handleDoubleClick(true)) {
0508: //// if (handleDoubleClick(true)) {
0509: // if (handleDoubleClick()) {
0510: // finishInlineEditing(true);
0511: // }
0512: // }
0513: //
0514: // // XXX Moved from DesignerActions.
0515: // /** Perform the equivalent of a double click on the first item
0516: // * in the selection (if any).
0517: // * @param selOnly If true, only do something if the selection is nonempty
0518: // * @todo Rename to handleDefaultAction
0519: // * @return True iff the double click resulted in opening an event handler
0520: // */
0521: // public boolean handleDoubleClick(/*boolean selOnly*/) {
0522: // CssBox box = null;
0523: // SelectionManager sm = webform.getSelection();
0524: //
0525: // if (!sm.isSelectionEmpty()) {
0526: //// Iterator it = sm.iterator();
0527: ////
0528: //// while (it.hasNext()) {
0529: //// DesignBean bean = (DesignBean)it.next();
0530: // for (Element componentRootElement : sm.getSelectedComponentRootElements()) {
0531: //// DesignBean bean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(componentRootElement);
0532: //// if (bean != null) {
0533: // if (componentRootElement != null) {
0534: //// box = webform.getMapper().findBox(bean);
0535: // box = ModelViewMapper.findBoxForComponentRootElement(webform.getPane().getPageBox(), componentRootElement);
0536: //
0537: // if (box != null) {
0538: // break;
0539: // }
0540: // }
0541: // }
0542: //// } else if (selOnly) {
0543: // } else {
0544: // return false;
0545: // }
0546: //
0547: // return handleDoubleClick(box);
0548: // }
0549: //
0550: // // XXX Moved from DesignerActions.
0551: // /** Handle double clicks with the given box as the target.
0552: // * @todo Rename to handleDefaultAction
0553: // * @return Return true iff the double click resulted in opening an event handler
0554: // */
0555: // private boolean handleDoubleClick(CssBox box) {
0556: // if (box instanceof ExternalDocumentBox) {
0557: // ((ExternalDocumentBox)box).open();
0558: //
0559: // return false;
0560: // } else if ((box != null) && (box.getTag() == HtmlTag.DIV) && (box.getBoxCount() == 1) &&
0561: // box.getBox(0) instanceof ExternalDocumentBox) {
0562: // // IF user has clicked on a large div containing only a
0563: // // jsp include, treat this as an attempt to open the page
0564: // // fragment child.
0565: // ((ExternalDocumentBox)box.getBox(0)).open();
0566: //
0567: // return false;
0568: // } else {
0569: // return editEventHandler();
0570: // }
0571: // }
0572: //
0573: // // XXX Copied from DesignerActions.
0574: // /** Return true iff an event handler was found and created/opened */
0575: // private boolean editEventHandler() {
0576: //// SelectionManager sm = webform.getSelection();
0577: ////
0578: //// if (sm.isSelectionEmpty()) {
0579: //// webform.getModel().openDefaultHandler();
0580: ////
0581: //// return false;
0582: //// }
0583: ////
0584: //// // TODO - get the component under the mouse, not the
0585: //// // whole selection!
0586: //// DesignBean component = getDefaultSelectionBean();
0587: ////
0588: //// if (component != null) {
0589: //// // See if it's an XHTML element; if so just show it in
0590: //// // the JSP source
0591: ////// if (FacesSupport.isXhtmlComponent(component)) {
0592: //// if (isXhtmlComponent(component)) {
0593: ////// MarkupBean mb = FacesSupport.getMarkupBean(component);
0594: //// MarkupBean mb = Util.getMarkupBean(component);
0595: ////
0596: //// MarkupUnit unit = webform.getMarkup();
0597: //// // <markup_separation>
0598: ////// Util.show(null, unit.getFileObject(),
0599: ////// unit.computeLine((RaveElement)mb.getElement()), 0, true);
0600: //// // ====
0601: ////// MarkupService.show(unit.getFileObject(), unit.computeLine((RaveElement)mb.getElement()), 0, true);
0602: //// showLineAt(unit.getFileObject(), unit.computeLine(mb.getElement()), 0);
0603: //// // </markup_separation>
0604: //// } else {
0605: //// webform.getModel().openDefaultHandler(component);
0606: //// }
0607: ////
0608: //// return true;
0609: //// }
0610: ////
0611: //// return false;
0612: // SelectionManager sm = webform.getSelection();
0613: //// DesignBean component;
0614: // Element componentRootElement;
0615: // if (sm.isSelectionEmpty()) {
0616: //// webform.getModel().openDefaultHandler();
0617: ////
0618: //// return false;
0619: //// component = null;
0620: // componentRootElement = null;
0621: // } else {
0622: //// component = getDefaultSelectionBean();
0623: //// Element componentRootElement = getDefaultSelectionComponentRootElement();
0624: //// component = WebForm.getDomProviderService().getMarkupDesignBeanForElement(componentRootElement);
0625: // componentRootElement = getDefaultSelectionComponentRootElement();
0626: // }
0627: //
0628: //// return webform.editEventHandlerForDesignBean(component);
0629: // return webform.editEventHandlerForComponent(componentRootElement);
0630: // }
0631:
0632: // // XXX Copied from DesignerActions.
0633: // /** Return true iff the given DesignBean is an XHTML markup "component" */
0634: // private boolean isXhtmlComponent(DesignBean bean) {
0635: //// MarkupBean mb = FacesSupport.getMarkupBean(bean);
0636: // MarkupBean mb = Util.getMarkupBean(bean);
0637: //
0638: // return (mb != null) && !(mb instanceof FacesBean);
0639: // }
0640:
0641: // XXX Copy from DesignerActions
0642: // XXX Copy also in designer/jsf/../JsfDesignerListener.
0643: // private DesignBean getDefaultSelectionBean() {
0644: private Element getDefaultSelectionComponentRootElement() {
0645: // TODO - should this be a checkbox instead?
0646: SelectionManager sm = webform.getSelection();
0647: // DesignBean bean = sm.getPrimary();
0648: //
0649: // if ((bean == null) && !sm.isSelectionEmpty()) {
0650: Element primaryComponentRootElement = sm.getPrimary();
0651: // DesignBean bean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(primaryComponentRootElement);
0652: if (primaryComponentRootElement == null
0653: && !sm.isSelectionEmpty()) {
0654: // TODO - get the component under the mouse, not the
0655: // whole selection!
0656: // Iterator it = sm.iterator();
0657: //
0658: // while (it.hasNext()) {
0659: // bean = (DesignBean)it.next();
0660: for (Element componentRootElement : sm
0661: .getSelectedComponentRootElements()) {
0662: // bean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(componentRootElement);
0663: primaryComponentRootElement = componentRootElement;
0664: // if (bean != null) {
0665: if (primaryComponentRootElement != null) {
0666: break;
0667: }
0668: }
0669: }
0670:
0671: // return bean;
0672: return primaryComponentRootElement;
0673: }
0674:
0675: // // XXX Copied from MarkupUtilities.
0676: // // XXX Copied from DesignerActions.
0677: // private static void showLineAt(FileObject fo, int lineno, int column) {
0678: // DataObject dobj;
0679: // try {
0680: // dobj = DataObject.find(fo);
0681: // }
0682: // catch (DataObjectNotFoundException ex) {
0683: // ErrorManager.getDefault().notify(ex);
0684: // return;
0685: // }
0686: //
0687: // // Try to open doc before showing the line. This SHOULD not be
0688: // // necessary, except without this the IDE hangs in its attempt
0689: // // to open the file when the file in question is a CSS file.
0690: // // Probably a bug in the xml/css module's editorsupport code.
0691: // // This has the negative effect of first flashing the top
0692: // // of the file before showing the destination line, so
0693: // // this operation is made conditional so only clients who
0694: // // actually need it need to use it.
0695: // EditorCookie ec = (EditorCookie)dobj.getCookie(EditorCookie.class);
0696: // if (ec != null) {
0697: // try {
0698: // ec.openDocument(); // ensure that it has been opened - REDUNDANT?
0699: // //ec.open();
0700: // }
0701: // catch (IOException ex) {
0702: // ErrorManager.getDefault().notify(ex);
0703: // }
0704: // }
0705: //
0706: // LineCookie lc = (LineCookie)dobj.getCookie(LineCookie.class);
0707: // if (lc != null) {
0708: // Line.Set ls = lc.getLineSet();
0709: // if (ls != null) {
0710: // // -1: convert line numbers to be zero-based
0711: // Line line = ls.getCurrent(lineno-1);
0712: // // TODO - pass in a column too?
0713: // line.show(Line.SHOW_GOTO, column);
0714: // }
0715: // }
0716: // }
0717:
0718: /**
0719: * During drag and drop, given a mouse position, decide whether a caret
0720: * position applies (and if so, show the caret at that position, otherwise
0721: * hide it), show drag & drop feedback messages in the status message
0722: * area and highlight parents or link targets. If the dropped parameter
0723: * is set, perform drop setup too: set the insert position on the
0724: * drop handler, and clear other drop state. I used to have separate
0725: * feedback-while-dropping and now-dropping-setup-state methods, but
0726: * they went out of sync, so by combining them hopefully the feedback will
0727: * always reflect what will happen on a drop.
0728: * @todo I should have a method which sets the caret based on whether
0729: * there was a selection
0730: * @todo Should return caret to original pos if you cancel out of a drop
0731: * @param committed If false, we're dragging but haven't dropped; just update
0732: * status feedback and show caret etc. If true, we've committed to
0733: * the drop, so set up the dnd handler, and clear out temporary caret
0734: * feedback, etc.
0735: * @return The drop type
0736: */
0737: int updateDropState(Point p, boolean committed,
0738: Transferable transferable) {
0739: DesignerPane pane = webform.getPane();
0740: // CssBox box = webform.getMapper().findBox(p.x, p.y);
0741: CssBox box = ModelViewMapper.findBox(pane.getPageBox(), p.x,
0742: p.y);
0743: CssBox insertBox = findInsertBox(box);
0744:
0745: // if ((insertBox == pane.getPageBox()) && webform.getDocument().isGridMode()) {
0746: // if ((insertBox == pane.getPageBox()) && webform.isGridModeDocument()) {
0747: if ((insertBox == pane.getPageBox()) && webform.isGridMode()) {
0748: insertBox = null;
0749: }
0750:
0751: // Position pos = Position.NONE;
0752: DomPosition pos = DomPosition.NONE;
0753:
0754: // XXX #94219 We need to try to get the position for grid also!
0755: // if (!box.isGrid() /* && (insertBox != null)*/
0756: // // XXX #97697 Do not process external document boxes, like fragments.
0757: // // TODO Revise how to properly handle the fragments.
0758: // && !(box instanceof ExternalDocumentBox)) {
0759: // XXX #97697 Do not process external document boxes, like fragments.
0760: // TODO Revise how to properly handle the fragments.
0761: if (!(box instanceof ExternalDocumentBox)) {
0762: finishInlineEditing(true);
0763: assert getInlineEditor() == null;
0764: // pos = pane.viewToModel(p);
0765: pos = webform.viewToModel(p);
0766:
0767: // if (getInlineEditor() == null ||
0768: // !webform.getSelection().getInlineEditor().isDocumentEditor()) {
0769: // boolean findNearest = !webform.isGridMode();
0770: // pos = Utilities.checkPosition(pos, findNearest, webformwebform.getManager().getInlineEditor());
0771: // }
0772: // if (Document.isReadOnlyRegion(pos)) {
0773: if (isReadOnlyRegion(pos)) {
0774: // pos = Position.NONE;
0775: pos = DomPosition.NONE;
0776: }
0777:
0778: // XXX #115390 When in grid and the cursor is not in the highlighted don't provide position.
0779: if (box != null && box.isGrid()
0780: && highlightedComponentRootElement == null) {
0781: pos = DomPosition.NONE;
0782: }
0783:
0784: // See if the new position points to a location in a grid mode; for example,
0785: // you may be pointing at an absolutely positioned StaticText; the caret position
0786: // would now be adjusted to point to the left or right of this static text which
0787: // is really a grid location
0788: // if ((pos != Position.NONE) &&
0789: if ((pos != DomPosition.NONE)
0790: && (pos.getNode().getNodeType() == org.w3c.dom.Node.ELEMENT_NODE)) {
0791: Element parent = (Element) pos.getNode();
0792: // CssBox parentBox = CssBox.getBox(parent);
0793: CssBox parentBox = webform.findCssBoxForElement(parent);
0794:
0795: if ((parentBox != null) && (parentBox.isGrid())) {
0796: // pos = Position.NONE;
0797: pos = DomPosition.NONE;
0798: }
0799: }
0800: }
0801:
0802: DndHandler dndHandler = pane.getDndHandler();
0803: int dropType;
0804:
0805: if (transferable != null) {
0806: dropType = dndHandler.getDropType(p /*, pos*/,
0807: transferable, false);
0808: // } else if (mouseHandler.paletteItems != null) {
0809: // dropType =
0810: // dndHandler.getDropType(p, // insertPos,
0811: // mouseHandler.paletteItems, null, false);
0812: } else if (mouseHandler.isCnCInProgress()) {
0813: dropType = dndHandler.getDropType(p,
0814: mouseHandler.cncTransferable, false);
0815: } else {
0816: dropType = DndHandler.DROP_DENIED;
0817: }
0818:
0819: if (dropType == DndHandler.DROP_LINKED) {
0820: pane.setCursor(getLinkedCursor());
0821: } else if (dropType == DndHandler.DROP_PARENTED) {
0822: //pane.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
0823: pane.setCursor(getInsertCursor());
0824: } else {
0825: assert dropType == DndHandler.DROP_DENIED;
0826: pane.setCursor(Cursor
0827: .getPredefinedCursor(Cursor.DEFAULT_CURSOR));
0828: }
0829:
0830: // // If we're doing a parent drop or a link, we should clear the
0831: // // caret if it's outside of the component!
0832: // MarkupDesignBean target = null;
0833: //
0834: // // XXX Hack alert... getDropType sets the highlighted item so we can use
0835: // // that to infer the selected parent. We get DROP_DENIED a lot when
0836: // // using Dnd, so this is more reliable than just relying on
0837: // // DndHandler.getDropTarget(). I should debug this and clean it up.
0838: //// if ((highlighted != null) && highlighted instanceof MarkupDesignBean) {
0839: //// target = (MarkupDesignBean)highlighted;
0840: // target = WebForm.getDomProviderService().getMarkupDesignBeanForElement(highlightedComponentRootElement);
0841: // if (target != null) {
0842: // // XXX It was done already.
0843: // } else if ((dropType == DndHandler.DROP_LINKED) || (dropType == DndHandler.DROP_PARENTED)) {
0844: //// target = dndHandler.getDropTarget();
0845: //// target = dndHandler.getRecentDropTarget();
0846: // Element recentDropTargetComponnetRootElement = dndHandler.getRecentDropTargetComponentRootElement();
0847: // target = WebForm.getDomProviderService().getMarkupDesignBeanForElement(recentDropTargetComponnetRootElement);
0848: // }
0849: //
0850: // if (target != null) {
0851: // Element element = target.getElement();
0852: // if (!pos.isInside(element)) { // XXX todo: check front/end positions!
0853: // XXX Hacks, see above (the commented out) original code.
0854: Element targetSourceElement = MarkupService
0855: .getSourceElementForElement(highlightedComponentRootElement);
0856: if (targetSourceElement == null) {
0857: targetSourceElement = MarkupService
0858: .getSourceElementForElement(dndHandler
0859: .getRecentDropTargetComponentRootElement());
0860: }
0861:
0862: if (targetSourceElement != null) {
0863: org.w3c.dom.Node posNode = pos.getNode();
0864: if (posNode instanceof Element) {
0865:
0866: } else {
0867: pos = DomPosition.NONE;
0868: }
0869:
0870: // XXX #116867 Check whether the position belongs to hightligted component.
0871: if (!isPositionFromComponent(webform, pos,
0872: targetSourceElement)) {
0873: pos = DomPosition.NONE;
0874: } else if (!pos.isInside(targetSourceElement)) { // XXX todo: check front/end positions!
0875: // The position is outside of the targeted component
0876: // pos = Position.NONE;
0877: pos = DomPosition.NONE;
0878: }
0879: }
0880:
0881: if (committed) {
0882: // if (pos != Position.NONE) {
0883: if (pos != DomPosition.NONE) {
0884: dndHandler.setInsertPosition(pos);
0885: } else {
0886: dndHandler.setDropPoint(p);
0887: }
0888:
0889: setInsertBox(null, null);
0890:
0891: // What do we do with the caret here?
0892: // Definitely hide it in grid mode, but what about flow?
0893: // Revert to original value if dnd is cancelled, and if a component
0894: // is dropped, the new component should be selected so the caret
0895: // won't be shown anyway...
0896: if (webform.isGridMode()) {
0897: pane.setCaret(null);
0898: }
0899: } else {
0900: // Update caret
0901: // if (pos != Position.NONE) {
0902: if (pos != DomPosition.NONE) {
0903: // if (pane.getCaret() == null) {
0904: if (!pane.hasCaret()) {
0905: // DesignerCaret dc = pane.getPaneUI().createCaret();
0906: // pane.setCaret(dc);
0907: pane.createCaret();
0908: }
0909:
0910: // pane.getCaret().setVisible(true);
0911: pane.setCaretVisible(true);
0912: // pane.setCaretPosition(pos);
0913: pane.setCaretDot(pos);
0914: } else {
0915: // if (pane.getCaret() != null) {
0916: if (pane.hasCaret()) {
0917: pane.setCaret(null);
0918: }
0919: }
0920: }
0921:
0922: return dropType;
0923: }
0924:
0925: /** XXX #116867 Indicates whether specified position belongs to specified component, not its subcomponent. */
0926: private static boolean isPositionFromComponent(WebForm webForm,
0927: DomPosition pos, Element sourceComponentRootElement) {
0928: if (pos == null || sourceComponentRootElement == null) {
0929: return false;
0930: }
0931: org.w3c.dom.Node posNode = pos.getNode();
0932: if (posNode instanceof Element) {
0933: return ModelViewMapper.findClosestComponentRootElement(
0934: webForm, (Element) posNode) == sourceComponentRootElement;
0935: }
0936: return false;
0937: }
0938:
0939: /** We have a separate "current"/"highlighted" item, unrelated to selection,
0940: * which is used to for example indicate which box is being dropped upon.
0941: */
0942: // public void highlight(DesignBean bean, MarkupMouseRegion region) {
0943: public void highlight(Element componentRootElement,
0944: Element regionElement) {
0945: // if ((bean == highlighted) && (region == highlightedRegion)) {
0946: if ((componentRootElement == highlightedComponentRootElement)
0947: && (regionElement == highlightedRegionElement)) {
0948: return;
0949: }
0950:
0951: // highlighted = bean;
0952: highlightedComponentRootElement = componentRootElement;
0953: // highlightedRegion = region;
0954: highlightedRegionElement = regionElement;
0955: webform.getPane().repaint();
0956: }
0957:
0958: public boolean isHighlighted() {
0959: // return highlighted != null;
0960: return highlightedComponentRootElement != null;
0961: }
0962:
0963: /** Paint the selection on top of the given editor pane. */
0964: public void paint(Graphics2D g) {
0965: //getPageBox(); // ensure that colors etc. are synced
0966: webform.getColors().sync();
0967:
0968: // if (webform.isVirtualFormsEnabled()) {
0969: //// VirtualFormSupport.paint(webform, g);
0970: //// paintVirtualForms(webform, g);
0971: // webform.paintVirtualForms(g, new RenderContextImpl(webform));
0972: // }
0973: // XXX Generic support for various designer decorations (for now virtual forms, ajax transactions).
0974: webform.paintDesignerDecorations(g);
0975:
0976: // Paint both before and after
0977: webform.getSelection().paintSelection(g);
0978: paintInsertModeBox(g); // XXX REMOVE ME!
0979:
0980: if (inlineEditor != null) {
0981: inlineEditor.paint(g);
0982: }
0983:
0984: if (interaction != null) {
0985: interaction.paint(g);
0986: }
0987:
0988: // if (highlighted != null) {
0989: if (highlightedComponentRootElement != null) {
0990: Rectangle a = null;
0991: // ModelViewMapper mapper = webform.getMapper();
0992:
0993: // if (highlightedRegion != null) {
0994: //// a = mapper.getRegionBounds(highlightedRegion);
0995: // a = webform.getPane().getPageBox().computeRegionBounds(highlightedRegion, null);
0996: //
0997: // // Somehow the region isn't visible
0998: // highlightedRegion = null;
0999: // }
1000: if (highlightedRegionElement != null) {
1001: a = webform.getPane().getPageBox().computeRegionBounds(
1002: highlightedRegionElement, null);
1003:
1004: // Somehow the region isn't visible
1005: highlightedRegionElement = null;
1006: }
1007:
1008: if (a == null) {
1009: // a = mapper.getComponentBounds(highlighted);
1010: // a = ModelViewMapper.getComponentBounds(webform.getPane().getPageBox(), highlighted);
1011: // if (highlighted instanceof MarkupDesignBean) {
1012: // a = ModelViewMapper.getComponentBounds(webform.getPane().getPageBox(),
1013: // WebForm.getDomProviderService().getComponentRootElementForMarkupDesignBean((MarkupDesignBean) highlighted));
1014: // }
1015: a = ModelViewMapper.getComponentBounds(webform
1016: .getPane().getPageBox(),
1017: highlightedComponentRootElement);
1018: }
1019:
1020: if (a == null) {
1021: // Somehow the highlight rectangle hasn't been cleared
1022: // when the component disappeared. Ignore this one and
1023: // don't try again.
1024: // highlighted = null;
1025: highlightedComponentRootElement = null;
1026: } else {
1027: g.setColor(webform.getColors().dropTargetColor);
1028: g.drawRect(a.x, a.y, a.width, a.height);
1029: }
1030: }
1031:
1032: webform.getSelection().paintSelHierarchy(g);
1033: }
1034:
1035: private void paintInsertModeBox(Graphics2D g2d) {
1036: // Unfortunately editing the text under body gets translated
1037: // into a dom replacement, and I'm not handling that well
1038: if ((insertModeBox != null)
1039: && !(insertModeBox instanceof PageBox)) {
1040: Rectangle r = new Rectangle(insertModeBox.getAbsoluteX(),
1041: insertModeBox.getAbsoluteY(), insertModeBox
1042: .getWidth(), insertModeBox.getHeight());
1043: drawInlineEditorBox(g2d, r);
1044: }
1045: }
1046:
1047: // Draw drag handle
1048: // When the mouse is moved inside some large components, like
1049: // tables, draw a dragging/moving handle. Shown when mouse moves
1050: // inside the component, removed when it leaves.
1051: public MouseHandler getMouseHandler() {
1052: if (mouseHandler == null) {
1053: mouseHandler = new MouseHandler();
1054: }
1055:
1056: return mouseHandler;
1057: }
1058:
1059: public static void translateMousePos(Point loc, Component source) {
1060: // This method is no longer necessary; I used to need to do
1061: // SwingUtilities.convertPoint(source, loc, destination)
1062: // here since mouse clicks could happen on embedded JButtons etc.
1063: // But now I paint only on the DesignerPane myself.
1064: }
1065:
1066: Cursor getInsertCursor() {
1067: if (insertCursor == null) {
1068: Component component = webform.getPane();
1069: Image image = null;
1070: Point p = null;
1071:
1072: /* This was only with JDK1.4 in Jaguar (10.2). Fixed in
1073: Panther (10.3).
1074:
1075: if (Utilities.getOperatingSystem() == Utilities.OS_MAC) {
1076: // Icons on mac look compressed - use a 32x32 (twice as large)
1077: // version of the pointer
1078: image = Utilities.loadImage("org/netbeans/modules/visualweb/designer/resources/insert-cursor-mac.gif"); //NOI18N
1079: // WEIRD! Would have thought it should be 16,16 or 17,17
1080: // here, but apparently while the image needs to be
1081: // twice the size, the hotspot needs to be in the 16x16
1082: // grid instead of the 32x32 grid!
1083: p = new Point(9,9);
1084: } else {
1085: */
1086: image = org.openide.util.Utilities
1087: .loadImage("org/netbeans/modules/visualweb/designer/resources/insert-cursor.gif"); //NOI18N
1088: p = new Point(9, 9);
1089:
1090: /* This doesn't work well - want to set our own hotspot
1091: insertCursor = Utilities.createCustomCursor(component, image,
1092: "CROSSINSERT_CURSOR"); //NOI18N
1093: */
1094: java.awt.Toolkit t = component.getToolkit();
1095: insertCursor = t.createCustomCursor(image, p,
1096: "CROSSINSERT_CURSOR");
1097: }
1098:
1099: return insertCursor;
1100: }
1101:
1102: /** Get cursor to use when dropping over a bean that only allows linking */
1103: Cursor getLinkedCursor() {
1104: if (linkedCursor == null) {
1105: Component component = webform.getPane();
1106: Image image = null;
1107: Point p = null;
1108:
1109: /* This was only with JDK1.4 in Jaguar (10.2). Fixed in
1110: Panther (10.3).
1111:
1112: if (Utilities.getOperatingSystem() == Utilities.OS_MAC) {
1113: // Icons on mac look compressed - use a 32x32 (twice as large)
1114: // version of the pointer
1115: image = Utilities.loadImage("org/netbeans/modules/visualweb/designer/linked-cursor-mac.gif"); //NOI18N
1116: // WEIRD! Would have thought it should be 16,16 or 17,17
1117: // here, but apparently while the image needs to be
1118: // twice the size, the hotspot needs to be in the 16x16
1119: // grid instead of the 32x32 grid!
1120: p = new Point(9,9);
1121: } else {
1122: */
1123: image = org.openide.util.Utilities
1124: .loadImage("org/netbeans/modules/visualweb/designer/resources/linked-cursor.gif"); //NOI18N
1125: p = new Point(9, 9);
1126:
1127: /* This doesn't work well - want to set our own hotspot
1128: linkedCursor = Utilities.createCustomCursor(component, image,
1129: "CROSSLINKED_CURSOR"); //NOI18N
1130: */
1131: java.awt.Toolkit t = component.getToolkit();
1132: linkedCursor = t.createCustomCursor(image, p,
1133: "CROSSLINKED_CURSOR");
1134: }
1135:
1136: return linkedCursor;
1137: }
1138:
1139: // public static void clearPalette(final WebForm webform) {
1140: // SwingUtilities.invokeLater(new Runnable() {
1141: // public void run() {
1142: // if (webform != null) {
1143: //// webform.getManager().mouseHandler.clearPalette();
1144: // webform.getManager().mouseHandler.doClearPalette();
1145: // } else {
1146: // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
1147: // new IllegalStateException("No cleaning palette code. Should not be called!")); // NOI18N
1148: //// PaletteComponentModel palette = PaletteComponentModel.getInstance();
1149: ////
1150: //// if ((palette.getSelectedPalette() != null) &&
1151: //// (palette.getSelectedPalette().getSelectedPaletteSection() != null) &&
1152: //// (palette.getSelectedPalette().getSelectedPaletteSection()
1153: //// .getSelectedPaletteItem() != null)) {
1154: //// palette.getSelectedPalette().getSelectedPaletteSection()
1155: //// .setSelectedPaletteItem(null);
1156: //// }
1157: // }
1158: // }
1159: // });
1160: // }
1161: public static void stopCnCForWebForm(WebForm webform) {
1162: if (webform == null) {
1163: return;
1164: }
1165: webform.getManager().mouseHandler.stopCnC();
1166: }
1167:
1168: private/*static*/boolean isInsideBoxDecoration(CssBox box, int x,
1169: int y) {
1170: Decoration decoration = box.getDecoration();
1171: if (decoration != null) {
1172: // if (DesignerSettings.getInstance().isShowDecorations()) {
1173: if (webform.isShowDecorations()) {
1174: int x1 = box.getAbsoluteX() + box.getWidth();
1175: int y1 = box.getAbsoluteY();
1176: int x2 = x1 + decoration.getWidth();
1177: int y2 = y1 + decoration.getHeight();
1178: return x >= x1 && x <= x2 && y >= y1 && y <= y2;
1179: }
1180: }
1181:
1182: return false;
1183: }
1184:
1185: /** Return true iff the mouse event position is inside the
1186: * given box
1187: */
1188: private static boolean isInside(CssBox box, MouseEvent e) {
1189: return (e.getX() >= box.getAbsoluteX())
1190: && (e.getX() <= (box.getAbsoluteX() + box.getWidth()))
1191: && (e.getY() >= box.getAbsoluteY())
1192: && (e.getY() <= (box.getAbsoluteY() + box.getHeight()));
1193: }
1194:
1195: /** Return true iff the given box (curr) is below the root box */
1196: private static boolean isBelow(CssBox root, CssBox curr) {
1197: if (curr == root) {
1198: return true;
1199: }
1200:
1201: CssBox parent = curr.getParent();
1202:
1203: if (parent == null) {
1204: return false;
1205: }
1206:
1207: return isBelow(root, parent);
1208: }
1209:
1210: /** Return the text position at the given location - or Position.NONE if
1211: * we're not over a text flow area.
1212: * @todo Move to ModelViewMapper!
1213: */
1214: // public Position findTextPosition(int x, int y) {
1215: public DomPosition findTextPosition(int x, int y) {
1216: // ModelViewMapper mapper = webform.getMapper();
1217: // CssBox box = mapper.findBox(x, y);
1218: CssBox box = ModelViewMapper.findBox(webform.getPane()
1219: .getPageBox(), x, y);
1220: CssBox insertBox = findInsertBox(box);
1221:
1222: if (insertBox != null) {
1223: // Position pos = ModelViewMapper.viewToModel(webform, x, y);
1224: DomPosition pos = ModelViewMapper
1225: .viewToModel(webform, x, y);
1226:
1227: if ((getInlineEditor() == null)
1228: || !getInlineEditor().isDocumentEditor()) {
1229: // pos = DesignerUtils.checkPosition(pos, true, /*webform*/webform.getManager().getInlineEditor());
1230: // pos = ModelViewMapper.findValidPosition(pos, true, /*webform*/webform.getManager().getInlineEditor());
1231: pos = ModelViewMapper.findValidPosition(webform, pos,
1232: true, /*webform*/webform.getManager()
1233: .getInlineEditor());
1234: }
1235:
1236: return pos;
1237: } else {
1238: // return Position.NONE;
1239: return DomPosition.NONE;
1240: }
1241: }
1242:
1243: /**
1244: * For a given bean, find the closest ancestor (including itself) which
1245: * can be repositioned.
1246: * <p>
1247: * @param box The box whose bean we're trying to reposition
1248: */
1249: // private static MarkupDesignBean findMovableParent(CssBox box) {
1250: private static Element findMovableParentComponentRootElement(
1251: CssBox box) {
1252: // I'm using absolutely positioned rather than simply BoxType.isPositioned()
1253: // here because relative boxes are typically anchors from grid positioning
1254: // (like divs containing fragments and such)
1255: if (box.getBoxType().isAbsolutelyPositioned()
1256: || box.getParent().isGrid()) {
1257: // return box.getDesignBean();
1258: return CssBox.getElementForComponentRootCssBox(box);
1259: }
1260:
1261: CssBox prev = box;
1262: ContainerBox parent = box.getParent();
1263:
1264: while (parent != null) {
1265: // MarkupDesignBean prevMarkupDesignBean = CssBox.getMarkupDesignBeanForCssBox(prev);
1266: Element prevComponentRootElement = CssBox
1267: .getElementForComponentRootCssBox(prev);
1268: if (parent.isGrid()) {
1269: // return prev.getDesignBean();
1270: return prevComponentRootElement;
1271: }
1272:
1273: // MarkupDesignBean parentMarkupDesignBean = CssBox.getMarkupDesignBeanForCssBox(parent);
1274: Element parentComponentRootElement = CssBox
1275: .getElementForComponentRootCssBox(parent);
1276: // if ((parent.getDesignBean() != null) &&
1277: //// FacesSupport.isSpecialBean(/*webform, */parent.getDesignBean())) {
1278: // Util.isSpecialBean(parent.getDesignBean())) {
1279: // return prev.getDesignBean();
1280: // if ((parentMarkupDesignBean != null) &&
1281: //// FacesSupport.isSpecialBean(/*webform, */parent.getDesignBean())) {
1282: // Util.isSpecialBean(parentMarkupDesignBean)) {
1283: WebForm webForm = box.getWebForm();
1284: if (webForm.getDomProviderService().isSpecialComponent(
1285: parentComponentRootElement)) {
1286: return prevComponentRootElement;
1287: }
1288:
1289: if (parent.getBoxType().isPositioned()) {
1290: // return parent.getDesignBean();
1291: return parentComponentRootElement;
1292: }
1293:
1294: prev = parent;
1295: parent = parent.getParent();
1296: }
1297:
1298: return null;
1299: }
1300:
1301: /**
1302: * Call when the selection objects have changed under us. Try to
1303: * Update to the current equivalent objects.
1304: */
1305: public void syncSelection(boolean update) {
1306: // XXX #113141 Cancel the inline editing.
1307: // finishInlineEditing(false);
1308: finishInlineEditing(true);
1309:
1310: // highlighted = null;
1311: highlightedComponentRootElement = null;
1312: // highlightedRegion = null;
1313: highlightedRegionElement = null;
1314: }
1315:
1316: // --------------------------------------------------------------------
1317: // Utility Methods
1318: // --------------------------------------------------------------------
1319: private void selectDomInspectorBox(CssBox box) {
1320: DomInspector.show(box);
1321:
1322: // #6475554 This seems to be just messing up.
1323: // // Also set nodes locally such that if this top component
1324: // // retains focus the node selection reflects the selected box
1325: // SelectionManager sm = webform.getSelection();
1326: // ArrayList nodes = new ArrayList(sm.getNumSelected());
1327: // DataObject dobj = webform.getDataObject();
1328: // Node n = new DomInspector.BoxNode(box, dobj);
1329: //
1330: // //n.setDataObject(dobj);
1331: // nodes.add(n);
1332: //
1333: // Node[] nds = (Node[])nodes.toArray(new Node[nodes.size()]);
1334: // DesignerTopComp topcomp = webform.getTopComponent();
1335: //
1336: // if (topcomp.isShowing()) {
1337: // topcomp.requestActive();
1338: // }
1339: //
1340: // DesignerUtils.setActivatedNodes(topcomp, nds);
1341: // webform.getPane().getPageBox().setSelected(box);
1342: }
1343:
1344: /** Return true iff this event corresponds to a "toggle" event,
1345: * e.g. an event where you want to toggle the selection instead
1346: * of replacing it. This is typically the case when some modifier
1347: * key is pressed.
1348: */
1349: public static boolean isToggleEvent(MouseEvent e) {
1350: // Shift does it - as does control, unless you're on the mac
1351: // where we reserve the control key for popup menu use
1352: // (one button mouse ui!)
1353: return e.isShiftDown()
1354: || ((org.openide.util.Utilities.getOperatingSystem() != org.openide.util.Utilities.OS_MAC) && e
1355: .isControlDown());
1356: }
1357:
1358: /** Return true iff this event corresponds to a "menu" event,
1359: * e.g. an event where you want to post a popup menu.
1360: * This is typically the case when the "right" mouse button
1361: * is pressed.
1362: */
1363: public static boolean isMenuEvent(MouseEvent e) {
1364: if (e.isShiftDown()) {
1365: return false;
1366: }
1367:
1368: return e.isPopupTrigger() ||
1369: // XXX This seems necessary on Windows. Temporary workaround!
1370: // (Actually, the problem is that it will return true only on button RELEASE
1371: // in the case of Windows, and I'm calling it from mousePressed. I'll need
1372: // to rework this a bit to work right on Windows.
1373: (e.getButton() != 1);
1374: }
1375:
1376: public static boolean isLinkingEvent(MouseEvent e) {
1377: // IMPORTANT -- keep in sync with code in Dragger (getDragAction)
1378: return e.isShiftDown() && e.isControlDown();
1379: }
1380:
1381: /** Return true iff this event corresponds to a "dom inspector"
1382: * event, e.g. an event which overrides normal mouse handling
1383: * and causes CSS boxes to be selected and displayed in the
1384: * property sheet instead.
1385: */
1386: public static boolean isDomEvent(MouseEvent e) {
1387: boolean isMac = org.openide.util.Utilities.getOperatingSystem() == org.openide.util.Utilities.OS_MAC;
1388:
1389: return (ENABLE_DOM_INSPECTOR && isMac) ? e.isAltDown() : (e
1390: .isControlDown() && e.isAltDown());
1391: }
1392:
1393: /**
1394: * Class to watch the associated component and fire
1395: * hyperlink events on it when appropriate.
1396: */
1397: public class MouseHandler extends MouseAdapter implements
1398: MouseMotionListener {
1399:
1400: private Point currentPos = new Point(-1, -1);
1401:
1402: // XXX Moved from DesignerActions.
1403: private int menuPosX;
1404: private int menuPosY;
1405:
1406: /** Did the last mouse press change the selection? */
1407: private boolean dontCycleInClickHandler;
1408: private Timer cycleTimer;
1409: // String[] paletteItems = null;
1410:
1411: /** CnC (Click and Click) <code>Transferable</code>, if non-null then CnC is in progress.
1412: * Currently it may come from palette item or item in runtime window -> db sources. */
1413: private Transferable cncTransferable;
1414:
1415: // private ExplorerManager selectedManager = null;
1416: // private boolean paletteItemSelected = false;
1417:
1418: /** Report current or most recent known mouse position. */
1419: public Point getCurrentPos() {
1420: // TODO JDK15
1421: // With JDK 1.5, the mouse position can be read through
1422: // Component.getMousePosition() and the MouseInfo class.
1423: //
1424: // For now do ugly hack instead. The reason the menu position
1425: // is remember is that when we post a context menu, I want
1426: // the menu-post position to be returned, but the menu post
1427: // will cause a mouseExited event first which we'll use to
1428: // clear our position as is the case when the mouse actually
1429: // leave the window
1430: if ((currentPos.x >= 0) && (currentPos.y >= 0)) {
1431: return currentPos;
1432: // } else if (DesignerActions.menuPosX >= 0) { // JDK15 TODO Upgrade
1433: } else if (menuPosX >= 0) {
1434: // return new Point(DesignerActions.menuPosX, DesignerActions.menuPosY);
1435: return new Point(menuPosX, menuPosY);
1436: } else {
1437: return null;
1438: }
1439: }
1440:
1441: /** Clear out the current mouse position such that the next
1442: * getCurrentPos will return null until a new position is
1443: * known.
1444: */
1445: public void clearCurrentPos() {
1446: currentPos.x = -1;
1447: currentPos.y = -1;
1448: // DesignerActions.menuPosX = -1; // JDK15 TODO Upgrade
1449: // DesignerActions.menuPosY = -1;
1450: menuPosX = -1;
1451: menuPosY = -1;
1452: }
1453:
1454: /**
1455: On mouse down we need to handle the following cases:
1456: - If we're in inline editing mode, forward the mouse click to
1457: the caret handler (where a click is used to set the caret for
1458: example)
1459: - If it's a double click, we should apply the default action to
1460: the selected component (which typically means opening the backing
1461: file to show its event handler
1462: - If it's a single click, we may enter into inline editing mode
1463: for this component if it supports it; we enter into inline editing
1464: mode after two consecutive clicks (not a double click)
1465: - In the DOM inspector, select the box under the pointer
1466: - We should also cycle the selection - but not if the user is about
1467: to double click! Therefore, the cycling operation has a brief
1468: delay (equal to the mouse double click interval) after which point
1469: we know that a double click isn't happening. If on the other hand
1470: a double click occurs before the timer has expired, the timer is
1471: cancelled.
1472: */
1473: public void mouseClicked(MouseEvent e) {
1474: DesignerPane pane = webform.getPane();
1475:
1476: if (ENABLE_DOM_INSPECTOR) {
1477: if (isDomEvent(e)) {
1478: PageBox pageBox = webform.getPane().getPageBox();
1479: CssBox box = pageBox.findCssBox(e.getX(), e.getY()); // Use Box interface instead?
1480: selectDomInspectorBox(box);
1481:
1482: return;
1483: } else {
1484: PageBox pageBox = pane.getPageBox();
1485: pageBox.setSelected(null);
1486: }
1487: }
1488:
1489: // DesignerCaret caret = pane.getCaret();
1490: // ModelViewMapper mapper = webform.getMapper();
1491:
1492: if (inlineEditor != null) {
1493: inlineEditor.checkInitialDoubleClick(e);
1494: }
1495:
1496: // if (!paletteItemSelected && (inlineEditor != null) && (caret != null)
1497: // if (!isCnCInProgress() && (inlineEditor != null) && (caret != null)
1498: if (!isCnCInProgress()
1499: && (inlineEditor != null)
1500: && (pane.hasCaret())
1501: // && inlineEditor.isEdited(mapper.findBox(e.getX(), e.getY()))
1502: && inlineEditor.isEdited(ModelViewMapper.findBox(
1503: pane.getPageBox(), e.getX(), e.getY()))
1504: /* && !MouseUtils_RAVE.isDoubleClick(e)*/) {
1505: // Reroute the mouse press to the insert box
1506: // caret.mouseClicked(e);
1507: pane.mouseClicked(e);
1508:
1509: return;
1510: }
1511:
1512: SelectionManager sm = webform.getSelection();
1513: // CssBox box = mapper.findBox(e.getX(), e.getY());
1514: CssBox box = ModelViewMapper.findBox(pane.getPageBox(), e
1515: .getX(), e.getY());
1516: boolean isBoxSelected = sm.isBelowSelected(box);
1517: // MarkupMouseRegion region = FacesSupport.findRegion(box.getElement());
1518: // MarkupMouseRegion region = findRegion(box.getElement());
1519: //
1520: // if ((region != null) && region.isClickable()) {
1521: // Result r = region.regionClicked(e.getClickCount());
1522: // ResultHandler.handleResult(r, webform.getModel());
1523: // // #6353410 If there was performed click on the region
1524: // // then do not perform other actions on the same click.
1525: // return;
1526: // }
1527: // if (webform.handleMouseClickForElement(box.getElement(), e.getClickCount())) {
1528: // // #6353410 If there was performed click on the region
1529: // // then do not perform other actions on the same click.
1530: // return;
1531: // }
1532: DesignerClickEvent evt = new DefaultDesignerClickEvent(
1533: webform, box, e.getClickCount());
1534: webform.fireUserElementClicked(evt);
1535: if (evt.isConsumed()) {
1536: // #6353410 If there was performed click on the region
1537: // then do not perform other actions on the same click.
1538: return;
1539: }
1540:
1541: // if (!paletteItemSelected && (insertModeBox != null) && (caret != null)
1542: // if (!isCnCInProgress() && (insertModeBox != null) && (caret != null)
1543: if (!isCnCInProgress() && (insertModeBox != null)
1544: && pane.hasCaret()
1545: // && isInside(insertModeBox, e) && !MouseUtils_RAVE.isDoubleClick(e)) {
1546: && isInside(insertModeBox, e)
1547: && !MouseUtils.isDoubleClick(e)) {
1548: // Reroute the mouse press to the insert box
1549: // caret.mouseClicked(e);
1550: pane.mouseClicked(e);
1551:
1552: if ((inlineEditor == null) && isBoxSelected
1553: && !dontCycleInClickHandler) {
1554: if (box.getBoxType() == BoxType.TEXT) {
1555: box = box.getParent();
1556: }
1557:
1558: // if (startInlineEditing(box.getDesignBean(), null, box, true, true, null, false)) {
1559: // if (startInlineEditing(CssBox.getMarkupDesignBeanForCssBox(box), null, box, true, true, null, false)) {
1560: if (startInlineEditing(CssBox
1561: .getElementForComponentRootCssBox(box),
1562: null, box, true, true, null, false)) {
1563: return;
1564: }
1565: }
1566:
1567: return;
1568: // } else if (!webform.getDocument().isGridMode() && (caret != null)) {
1569: // } else if (!webform.isGridModeDocument() && (caret != null)) {
1570: // } else if (!webform.isGridModeDocument() && pane.hasCaret()) {
1571: } else if (!webform.isGridMode() && pane.hasCaret()) {
1572: // caret.mouseClicked(e);
1573: pane.mouseClicked(e);
1574:
1575: // fall through
1576: }
1577:
1578: // if (MouseUtils_RAVE.isDoubleClick(e)) {
1579: if (MouseUtils.isDoubleClick(e)) {
1580: if (!isInlineEditing()) {
1581: if (isInsideBoxDecoration(box, e.getX(), e.getY())) {
1582: processDefaultDecorationAction(box);
1583: } else {
1584: // LATER when I have markup beans check for Frame bean
1585: // instead in the selection, don't use box located above
1586: // webform.getActions().handleDoubleClick(box);
1587: // handleDoubleClick(box);
1588: DesignerEvent evt2 = new DefaultDesignerEvent(
1589: webform, box);
1590: webform.fireUserActionPerformed(evt2);
1591: }
1592: }
1593: } else if (isToggleEvent(e)) {
1594: // // Do nothing - already handled in mousePressed; but we don't
1595: // // want any selection cycling or inline editing
1596: // #94266 Toggle only on click not press or release
1597: selectAt(e, false);
1598: } else if (!dontCycleInClickHandler) {
1599: // Only cycle when we're clicking on faces beans; otherwise
1600: // clicking puts you in insert mode
1601: CssBox curr = box;
1602:
1603: while (curr != null) {
1604: // if (curr.getDesignBean() != null) {
1605: // FacesBean fb = FacesSupport.getFacesBean(curr.getDesignBean());
1606: //
1607: // if ((fb != null) &&
1608: //// !FacesSupport.isSpecialBean(/*webform, */curr.getDesignBean())) {
1609: // !Util.isSpecialBean(curr.getDesignBean())) {
1610: // MarkupDesignBean currMarkupDesignBean = CssBox.getMarkupDesignBeanForCssBox(curr);
1611: // Element currComponentRootElement = CssBox.getElementForComponentRootCssBox(curr);
1612: // XXX #113773
1613: Element currComponentRootElement = CssBox
1614: .getComponentRootElementForCssBox(curr);
1615: // if (currMarkupDesignBean != null) {
1616: //// FacesBean fb = FacesSupport.getFacesBean(currMarkupDesignBean);
1617: // FacesBean fb = Util.getFacesBean(currMarkupDesignBean);
1618: // if ((fb != null)
1619: // && !Util.isSpecialBean(currMarkupDesignBean)) {
1620: // break;
1621: // }
1622: // }
1623: // if (webform.isNormalAndHasFacesBean(currMarkupDesignBean)) {
1624: // if (webform.isNormalAndHasFacesComponent(currComponentRootElement)) {
1625: if (currComponentRootElement != null
1626: && currComponentRootElement != pane
1627: .getPageBox()) {
1628: break;
1629: }
1630:
1631: curr = curr.getParent();
1632: }
1633:
1634: if (curr == null) {
1635: // Click not below a faces bean - try to enter insert mode instead
1636: CssBox insertBox = findInsertBox(box);
1637: setInsertBox(insertBox, e);
1638: } else {
1639: // MarkupDesignBean currMarkupDesignBean = CssBox.getMarkupDesignBeanForCssBox(curr);
1640: // Inline editing takes precedence over selection
1641: // cycling!
1642: // if ((inlineEditor == null) && sm.isSelected(curr.getDesignBean())) {
1643: // if (startInlineEditing(curr.getDesignBean(), null, box, true, true, null,
1644: // Element componentRootElement = CssBox.getElementForComponentRootCssBox(curr);
1645: // XXX #113773.
1646: Element componentRootElement = CssBox
1647: .getComponentRootElementForCssBox(curr);
1648: if ((inlineEditor == null)
1649: && sm.isSelected(componentRootElement)) {
1650: // if (startInlineEditing(currMarkupDesignBean, null, box, true, true, null,
1651: if (startInlineEditing(componentRootElement,
1652: null, box, true, true, null, false)) {
1653: return;
1654: }
1655: }
1656:
1657: requestCycle(e.getX(), e.getY());
1658: }
1659: }
1660: }
1661:
1662: private void cancelCycleRequest() {
1663: if (cycleTimer != null) {
1664: cycleTimer.stop();
1665: cycleTimer = null;
1666: }
1667: }
1668:
1669: private void requestCycle(final int x, final int y) {
1670: cancelCycleRequest();
1671:
1672: // int delay = MouseUtils_RAVE.getDoubleClickInterval();
1673: int delay = DOUBLE_CLICK_DELTA;
1674: cycleTimer = new Timer(delay, new ActionListener() {
1675: public void actionPerformed(ActionEvent evt) {
1676: cycleTimer = null;
1677: cycleSelection(x, y);
1678: }
1679: });
1680: cycleTimer.setRepeats(false);
1681: cycleTimer.setCoalesce(true);
1682: cycleTimer.start();
1683: }
1684:
1685: private void cycleSelection(int x, int y) {
1686: // Cycle selection
1687: // ModelViewMapper mapper = webform.getMapper();
1688: // CssBox bx = mapper.findBox(x, y);
1689: CssBox bx = ModelViewMapper.findBox(webform.getPane()
1690: .getPageBox(), x, y);
1691:
1692: while (bx != null) {
1693: // if (bx.getDesignBean() != null) {
1694: // if (CssBox.getMarkupDesignBeanForCssBox(bx) != null) {
1695: // if (CssBox.getElementForComponentRootCssBox(bx) != null) {
1696: // XXX #113773.
1697: if (CssBox.getComponentRootElementForCssBox(bx) != null) {
1698: break;
1699: }
1700:
1701: bx = bx.getParent();
1702: }
1703:
1704: SelectionManager sm = webform.getSelection();
1705: CssBox ancestor = null;
1706:
1707: if (bx != null) {
1708: // MarkupDesignBean boxMarkupDesignBean = CssBox.getMarkupDesignBeanForCssBox(bx);
1709: // if ((bx.getDesignBean() != null) && sm.isSelected(bx.getDesignBean())) {
1710: // Element componentRootElement = CssBox.getElementForComponentRootCssBox(bx);
1711: // XXX #113773.
1712: Element componentRootElement = CssBox
1713: .getComponentRootElementForCssBox(bx);
1714: if ((componentRootElement != null)
1715: && sm.isSelected(componentRootElement)) {
1716: ancestor = bx;
1717: } else {
1718: ancestor = sm.getSelectedAncestor(bx);
1719: }
1720: }
1721:
1722: if (ancestor != null) {
1723: // "ancestor" is the currently selected component
1724: // we're over: "cycle" outwards
1725: // DesignBean parent = null;
1726: // Element parentComponentRootElement = null;
1727:
1728: // MarkupDesignBean ancestorMarkupDesignBean = CssBox.getMarkupDesignBeanForCssBox(ancestor);
1729: // if (webform.getActions().canSelectParent(ancestor.getDesignBean())) {
1730: // if (SelectionManager.canSelectParent(ancestor.getDesignBean())) {
1731: // parent = ancestor.getDesignBean().getBeanParent();
1732: // if (SelectionManager.canSelectParent(ancestorMarkupDesignBean)) {
1733: // Element ancestorComponentRootElement = CssBox.getElementForComponentRootCssBox(ancestor);
1734: // XXX #113773.
1735: Element ancestorComponentRootElement = CssBox
1736: .getComponentRootElementForCssBox(ancestor);
1737: // if (SelectionManager.canSelectParent(ancestorComponentRootElement)) {
1738: // if (canSelectParent(ancestorComponentRootElement)) {
1739: // parent = ancestorMarkupDesignBean.getBeanParent();
1740: // parentComponentRootElement = WebForm.getDomProviderService().getParentComponent(ancestorComponentRootElement);
1741: // }
1742: Element parentComponentRootElement = getSelectableParent(ancestorComponentRootElement);
1743:
1744: boolean found = false;
1745:
1746: // while (parent != null) {
1747: while (parentComponentRootElement != null) {
1748: // Find the visual (non-form, non-root) parent
1749: // and select it
1750: // Element element = FacesSupport.getElement(parent);
1751: // Element element = Util.getElement(parent);
1752:
1753: // Element element = WebForm.getDomProviderService().getElement(parent);
1754: // if (element != null) {
1755: // CssBox box = mapper.findBox(element);
1756: // CssBox box = ModelViewMapper.findBox(webform.getPane().getPageBox(), element);
1757: CssBox box = ModelViewMapper.findBox(webform
1758: .getPane().getPageBox(),
1759: parentComponentRootElement);
1760:
1761: if (box != null) {
1762: // sm.selectComponents(new DesignBean[] { parent }, true);
1763: // if (parent instanceof MarkupDesignBean) {
1764: sm
1765: .selectComponents(
1766: new Element[] { parentComponentRootElement },
1767: true);
1768: found = true;
1769:
1770: break;
1771: // }
1772: }
1773: // }
1774:
1775: // parent = parent.getBeanParent();
1776: parentComponentRootElement = webform
1777: .getDomProviderService()
1778: .getParentComponent(
1779: parentComponentRootElement);
1780: }
1781:
1782: if (!found && (bx != ancestor)) {
1783: // Select the box itself, if different from ancestor
1784: // sm.selectComponents(new DesignBean[] { bx.getDesignBean() }, true);
1785: // sm.selectComponents(new Element[] { CssBox.getElementForComponentRootCssBox(bx) }, true);
1786: // XXX #113773.
1787: sm.selectComponents(new Element[] { CssBox
1788: .getComponentRootElementForCssBox(bx) },
1789: true);
1790: }
1791: }
1792: }
1793:
1794: /**
1795: On mouse drag we need to handle the following cases:
1796: - If we're in inline editing mode, forward the mouse drag to
1797: the caret handler (where a drag is used to change the selected
1798: text range)
1799: - We may be dragging, resizing, or selection-swiping so update
1800: the handlers for these operations
1801: */
1802: public void mouseDragged(MouseEvent e) {
1803: // XXX #107532 There was interpreted also drag over popup menu (while right click pressed).
1804: // Accept only left click one.
1805: if (SwingUtilities.isLeftMouseButton(e)) {
1806: currentPos.x = e.getX();
1807: currentPos.y = e.getY();
1808: }
1809:
1810: if (interaction != null) {
1811: setInsertBox(null, null);
1812: }
1813:
1814: DesignerPane pane = webform.getPane();
1815: // DesignerCaret caret = pane.getCaret();
1816:
1817: // ModelViewMapper mapper = webform.getMapper();
1818:
1819: // if (!paletteItemSelected && (inlineEditor != null) && (caret != null)) {
1820: // if (!isCnCInProgress() && (inlineEditor != null) && (caret != null)) {
1821: if (!isCnCInProgress() && (inlineEditor != null)
1822: && pane.hasCaret()) {
1823: // caret.mouseDragged(e);
1824: pane.mouseDragged(e);
1825:
1826: return;
1827: // } else if (!paletteItemSelected && (insertModeBox != null) && (caret != null)
1828: // } else if (!isCnCInProgress() && (insertModeBox != null) && (caret != null)
1829: } else if (!isCnCInProgress() && (insertModeBox != null)
1830: && pane.hasCaret() && isInside(insertModeBox, e)) {
1831: // CssBox selBox = mapper.findBox(e.getX(), e.getY());
1832: CssBox selBox = ModelViewMapper.findBox(pane
1833: .getPageBox(), e.getX(), e.getY());
1834:
1835: // if (selBox.getDesignBean() == null) {
1836: // if (CssBox.getMarkupDesignBeanForCssBox(selBox) == null) {
1837: if (CssBox.getElementForComponentRootCssBox(selBox) == null) {
1838: // Reroute the mouse press to the insert box
1839: // caret.mouseDragged(e);
1840: pane.mouseDragged(e);
1841:
1842: return;
1843: } // else fall through: over something like a button in the insert box: let it
1844:
1845: // be selected in the normal way
1846: // } else if (!webform.getDocument().isGridMode() && (caret != null)) {
1847: // } else if (!webform.isGridModeDocument() && (caret != null)) {
1848: // } else if (!webform.isGridModeDocument() && pane.hasCaret()) {
1849: } else if (!webform.isGridMode() && pane.hasCaret()) {
1850: // caret.mouseDragged(e);
1851: pane.mouseDragged(e);
1852:
1853: // fall through
1854: }
1855:
1856: Point p = e.getPoint();
1857: translateMousePos(p, (Component) e.getSource());
1858:
1859: if (interaction != null) {
1860: interaction.mouseDragged(e);
1861: }
1862:
1863: // TODO Check for overlap with other components - if any
1864: // overlap is found, draw some kind of conflict icon
1865: // in the region! (This is only necessary when using layout
1866: // tables, not CSS2 - CSS2 allows overlap)
1867: }
1868:
1869: /**
1870: On mouse press we need to handle the following cases:
1871: - If it's a right click (platform dependent), and it's a
1872: popup trigger (which it will be on say Solaris but not
1873: Windows), popup a popup menu
1874: - If the mouse press is not over a component in the selection,
1875: the component should be selected
1876: - The mouse press can initiate various user operations depending
1877: on where the pointer is:
1878: * Over a component: this initiates a drag
1879: * Over a resize handle: this initiates a resize
1880: * Over the "background": this initiates a selection swipe
1881: operation
1882: - If we're in inline editing mode, forward the press event to the
1883: caret handler, which will use the event to move the caret and
1884: possibly immediately unselect its previous range)
1885: */
1886: public void mousePressed(MouseEvent e) {
1887: DesignerPane pane = webform.getPane();
1888: // ModelViewMapper mapper = webform.getMapper();
1889:
1890: pane.requestFocus();
1891: cancelCycleRequest();
1892: dontCycleInClickHandler = false;
1893:
1894: if (ENABLE_DOM_INSPECTOR) {
1895: if (isDomEvent(e)) {
1896: // mouse clicked will take care of this but suspend
1897: // normal click handling
1898: return;
1899: }
1900: }
1901:
1902: //Point p = e.getPoint();
1903: Point p = SwingUtilities.convertPoint(e.getComponent(), e
1904: .getX(), e.getY(), pane);
1905:
1906: //translateMousePos(p, (Component)e.getSource());
1907: int x = p.x;
1908: int y = p.y;
1909: SelectionManager sm = webform.getSelection();
1910: PageBox pageBox = pane.getPageBox();
1911: int maxWidth = pageBox.getWidth();
1912: int maxHeight = pageBox.getHeight();
1913: int resize = sm.getSelectionHandleDir(x, y, maxWidth,
1914: maxHeight);
1915:
1916: CssBox selBox;
1917: // MarkupDesignBean sel;
1918: Element sel;
1919:
1920: if (resize == Cursor.MOVE_CURSOR) {
1921: // sel = sm.getSelectionHandleView(x, y, maxWidth, maxHeight);
1922: sel = sm.getSelectionHandleView(x, y, maxWidth,
1923: maxHeight);
1924: // selBox = mapper.findBox(sel);
1925: selBox = ModelViewMapper
1926: .findBoxForComponentRootElement(pageBox, sel);
1927: } else {
1928: // selBox = mapper.findBox(x, y);
1929: selBox = ModelViewMapper.findBox(pageBox, x, y);
1930: // sel = ModelViewMapper.findComponent(selBox);
1931: // sel = ModelViewMapper.findMarkupDesignBean(selBox);
1932: sel = ModelViewMapper.findElement(selBox);
1933: }
1934:
1935: if (inlineEditor != null) {
1936: // CssBox clickedBox = mapper.findBox(e.getX(), e.getY());
1937: CssBox clickedBox = ModelViewMapper.findBox(pageBox, e
1938: .getX(), e.getY());
1939:
1940: if (!inlineEditor.isEdited(clickedBox)) {
1941: finishInlineEditing(false);
1942: }
1943: }
1944:
1945: // DesignerCaret caret = pane.getCaret();
1946:
1947: // if (!paletteItemSelected && (inlineEditor != null) && (caret != null)) {
1948: // if (!isCnCInProgress() && (inlineEditor != null) && (caret != null)) {
1949: if (!isCnCInProgress() && (inlineEditor != null)
1950: && pane.hasCaret()) {
1951: // if (((selBox.getDesignBean() == null) || (selBox == pageBox)) &&
1952: // if (((CssBox.getMarkupDesignBeanForCssBox(selBox) == null) || (selBox == pageBox)) &&
1953: if (((CssBox.getElementForComponentRootCssBox(selBox) == null) || (selBox == pageBox))
1954: && inlineEditor.isEdited(selBox)) {
1955: // Reroute the mouse press to the insert box
1956: // caret.mousePressed(e);
1957: pane.mousePressed(e);
1958:
1959: //return;
1960: } // else fall through: over something like a button in the insert box: let it
1961:
1962: // be selected in the normal way
1963: // } else if (!paletteItemSelected && (insertModeBox != null) && (caret != null)
1964: // } else if (!isCnCInProgress() && (insertModeBox != null) && (caret != null)
1965: } else if (!isCnCInProgress() && (insertModeBox != null)
1966: && pane.hasCaret() && isInside(insertModeBox, e)) {
1967: // Reroute the mouse press to the insert box
1968: // caret.mousePressed(e);
1969: pane.mousePressed(e);
1970:
1971: //return;
1972: // else fall through: over something like a button in the insert box: let it
1973: // be selected in the normal way
1974: // } else if (!paletteItemSelected && !webform.getDocument().isGridMode()) {
1975: // } else if (!paletteItemSelected && !webform.isGridModeDocument()) {
1976: // } else if (!isCnCInProgress() && !webform.isGridModeDocument()) {
1977: } else if (!isCnCInProgress() && !webform.isGridMode()) {
1978: // if (caret == null) {
1979: // caret = pane.getPaneUI().createCaret();
1980: // pane.setCaret(caret);
1981: // }
1982: if (!pane.hasCaret()) {
1983: pane.createCaret();
1984: }
1985:
1986: // caret.mousePressed(e);
1987: pane.mousePressed(e);
1988:
1989: // fall through
1990: }
1991:
1992: if (isMenuEvent(e)) {
1993: dontCycleInClickHandler = true;
1994: ensurePointSelected(e);
1995:
1996: // DesignerActions.menuPosX = e.getX();
1997: // DesignerActions.menuPosY = e.getY();
1998: menuPosX = e.getX();
1999: menuPosY = e.getY();
2000:
2001: // CssBox overBox = mapper.findBox(e.getX(), e.getY());
2002: CssBox overBox = ModelViewMapper.findBox(pageBox, e
2003: .getX(), e.getY());
2004: // RaveElement mouseElement = null;
2005: Element mouseElement = null;
2006:
2007: if (overBox != null) {
2008: mouseElement = overBox.getElement();
2009: }
2010:
2011: // <actions from layer>
2012: // DesignerActions actions = webform.getActions();
2013: // actions.createPopup(p.x, p.y, pane, sm.getSelectedNodes(), true, mouseElement);
2014: // ====
2015: if (isInsideBoxDecoration(overBox, e.getX(), e.getY())) {
2016: showDecorationPopupMenu(overBox, e.getComponent(),
2017: e.getX(), e.getY());
2018: } else {
2019: // webform.getTopComponent().showPopupMenu(p.x, p.y);
2020: // webform.tcShowPopupMenu(p.x, p.y);
2021: webform
2022: .fireUserPopupActionPerformed(new DefaultDesignerPopupEvent(
2023: webform, e.getComponent(), null,
2024: null, p.x, p.y));
2025: }
2026: // </actions from layer>
2027:
2028: return;
2029: }
2030:
2031: // In insert mode (component selected in the palette)
2032: // - let user swipe out a selection rectangle to set the
2033: // size of the inserted component
2034: // if (paletteItemSelected) {
2035: if (isCnCInProgress()) {
2036: setInsertBox(null, null);
2037:
2038: // XXX Marquee is not the right term here - we're
2039: // not wanting a selection. Make Marquee class more
2040: // flexible so we can set state which causes its
2041: // statusline updates to have the right icon, to
2042: // drop selection on release, to not use marching ants
2043: // (if the marquee starts using those for selection),
2044: // etc.
2045: // XXX Use subclass for this instead?
2046: CssBox gridBox = selBox.isGrid() ? selBox : null;
2047: sizer = new Marquee(webform, gridBox);
2048: sizer.setSelect(false);
2049: // sizer.setSnapToGrid(GridHandler.getInstance().snap());
2050: // sizer.setSnapToGrid(webform.getGridHandler().snap());
2051: // sizer.setSnapToGrid(GridHandler.getDefault().isSnap());
2052: sizer.setSnapToGrid(webform.isGridSnap());
2053: sizer.setInsertCursor(true);
2054: interaction = sizer;
2055: interaction.mousePressed(e);
2056:
2057: // TODO - status line position and size feedback?
2058: return;
2059: }
2060:
2061: if (y > sm.selectionViewPos) { // HACK FEATURE for now
2062:
2063: // User has selected one of the items in the selection hierarchy list
2064: sm.selectAncestor(x, y);
2065:
2066: return;
2067: }
2068:
2069: // Find out where the mouse press occurred.
2070: // If it's over a component - check modifier key, and
2071: // modify selection either by replacing it or adding to it
2072: // (or toggling a selected item).
2073: // Else, start a marque drag by forwarding to the marquee handler.
2074: if ((resize != Cursor.DEFAULT_CURSOR)
2075: && (resize != Cursor.MOVE_CURSOR)) {
2076: // MarkupDesignBean bean = sm.getSelectionHandleView(x, y, maxWidth, maxHeight);
2077: Element componentRootElement = sm
2078: .getSelectionHandleView(x, y, maxWidth,
2079: maxHeight);
2080: // MarkupDesignBean bean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(componentRootElement);
2081: // CssBox box = mapper.findBox(bean);
2082: CssBox box = ModelViewMapper
2083: .findBoxForComponentRootElement(webform
2084: .getPane().getPageBox(),
2085: componentRootElement);
2086: if (box == null) {
2087: // XXX 115639 Fixing possible NPE.
2088: return;
2089: }
2090:
2091: // ArrayList bounds = mapper.getComponentRectangles(bean);
2092: // List bounds = ModelViewMapper.getComponentRectangles(webform.getPane().getPageBox(), bean);
2093: List bounds = ModelViewMapper.getComponentRectangles(
2094: webform.getPane().getPageBox(),
2095: componentRootElement);
2096: Rectangle a;
2097:
2098: if ((bounds != null) && (bounds.size() > 0)) {
2099: a = (Rectangle) bounds.get(0);
2100: } else {
2101: // a = mapper.getComponentBounds(bean);
2102: // a = ModelViewMapper.getComponentBounds(webform.getPane().getPageBox(), bean);
2103: a = ModelViewMapper.getComponentBounds(webform
2104: .getPane().getPageBox(),
2105: componentRootElement);
2106: }
2107:
2108: boolean preserveAspect =
2109: // (Resizer.getResizeConstraints(webform, bean) &
2110: // (Resizer.getResizeConstraints(webform, componentRootElement) &
2111: // Constants.ResizeConstraints.MAINTAIN_ASPECT_RATIO) != 0;
2112: Resizer.hasMaintainAspectRatioResizeConstraint(Resizer
2113: .getResizeConstraints(webform,
2114: componentRootElement));
2115: // interaction = new Resizer(webform, bean, box, resize, a, preserveAspect);
2116: interaction = new Resizer(webform,
2117: componentRootElement, box, resize, a,
2118: preserveAspect);
2119: interaction.mousePressed(e);
2120: } else {
2121: if (isLinkingEvent(e)) {
2122: int size = 0;
2123: List<Rectangle> selections = new ArrayList<Rectangle>(
2124: size);
2125: List<CssBox> boxes = new ArrayList<CssBox>(size);
2126: // ArrayList beans = new ArrayList(size);
2127: Element[] componentRootElements = new Element[0];
2128:
2129: //Iterator it = selected.iterator();
2130: // dragger = new Dragger(webform, boxes, selections, beans);
2131: dragger = new Dragger(webform, boxes, selections,
2132: componentRootElements);
2133: interaction = dragger;
2134: interaction.mousePressed(e);
2135:
2136: return;
2137: }
2138:
2139: // See if user clicked on the "root" canvas (or a grid canvas)
2140: // or a component. Clicking on the background starts a marquee
2141: // selection whereas clicking on a component starts a drag
2142: // (or if you release over the same position, a selection.)
2143: // We want to allow marquee selection over grid areas if
2144: // control is pressed
2145: if ((sel == null)
2146: || (selBox == pane.getPageBox())
2147: || (selBox.isGrid() && (e.isShiftDown() || e
2148: .isControlDown()))) {
2149: setInsertBox(null, null);
2150:
2151: if ((selBox != null) && selBox.isGrid()) {
2152: // Start a Marquee selection
2153: interaction = new Marquee(webform, selBox);
2154: interaction.mousePressed(e);
2155: } else {
2156: // Clicking outside of components clears the selection
2157: // Arguably the property sheet could show the nearest
2158: // tag instead, e.g. at the caret position...
2159: if (!sm.isSelectionEmpty()) {
2160: sm.clearSelection(true);
2161: }
2162: }
2163: } else {
2164: // Fix such that text selection swiping in grid
2165: // mode isn't totally bjorken
2166: if (((selBox.getBoxType() == BoxType.TEXT) || (selBox
2167: .getBoxType() == BoxType.SPACE))
2168: && ((inlineEditor != null) && inlineEditor
2169: .isEdited(selBox))) {
2170: // You've clicked on a text box as part of inline text editing;
2171: // don't initiate a drag!
2172: //dontCycleInClickHandler = true;
2173: dontCycleInClickHandler = ensurePointSelected(e);
2174:
2175: /* TODO Hide caret when you've selected a component
2176: // What if the caret we picked is outside when there IS
2177: // an inside (albeit more distant) position we could have
2178: // used?
2179: if (selected != null && selected.size() > 0 &&
2180: caret != null &&
2181: caret.getDot() != Position.NONE) {
2182: Position pos = caret.getDot();
2183: Iterator it = selected.iterator();
2184: boolean inside = false;
2185: while (it.hasNext()) {
2186: FormObject fob = (FormObject)it.next();
2187: Element el = FacesSupport.getElement(fob.component);
2188: if (pos.isInside(el)) {
2189: inside = true;
2190: }
2191: }
2192: if (!inside) {
2193: pane.hideCaret();
2194: }
2195: }
2196: */
2197: return; // XXX is this why I can't select boxes around text?
2198: }
2199:
2200: // Fix such that text selection swiping in grid
2201: // mode isn't totally bjorken
2202: if (((selBox.getBoxType() == BoxType.TEXT) || (selBox
2203: .getBoxType() == BoxType.SPACE))
2204: && ((insertModeBox != null) && isBelow(
2205: insertModeBox, selBox))) {
2206: // XXX #110083 Possible ClassCastException
2207: // TextBox tb = (TextBox)selBox;
2208: Text selBoxText;
2209: DomPosition selBoxFirstPosition;
2210: if (selBox instanceof TextBox) {
2211: TextBox tb = (TextBox) selBox;
2212: selBoxText = tb.getNode();
2213: selBoxFirstPosition = tb.getFirstPosition();
2214: } else if (selBox instanceof SpaceBox) {
2215: SpaceBox sb = (SpaceBox) selBox;
2216: selBoxText = sb.getNode();
2217: selBoxFirstPosition = sb.getFirstPosition();
2218: } else {
2219: selBoxText = null;
2220: selBoxFirstPosition = DomPosition.NONE;
2221: }
2222:
2223: if ((selBoxText != null)
2224: // (DesignerUtils.checkPosition(tb.getFirstPosition(), false, /*webform*/webform.getManager().getInlineEditor()) != Position.NONE)) {
2225: // (ModelViewMapper.isValidPosition(tb.getFirstPosition(), false, /*webform*/webform.getManager().getInlineEditor()))) {
2226: && (ModelViewMapper.isValidPosition(
2227: webform, selBoxFirstPosition,
2228: false, /*webform*/webform
2229: .getManager()
2230: .getInlineEditor()))) {
2231: // You've clicked directly on text while in
2232: // flow mode, and the text is not part of a
2233: // jsf component: don't initiate a drag!
2234: if (!sm.isBelowSelected(selBox)
2235: && !sm.isSelectionEmpty()) {
2236: sm.clearSelection(true);
2237: }
2238:
2239: //dontCycleInClickHandler = true;
2240: dontCycleInClickHandler = ensurePointSelected(e);
2241:
2242: /* TODO Hide caret when you've selected a component
2243: // What if the caret we picked is outside when there IS
2244: // an inside (albeit more distant) position we could have
2245: // used?
2246: // Hide caret when you select something without internal positions
2247: if (selected != null && selected.size() > 0 &&
2248: caret != null &&
2249: caret.getDot() != Position.NONE) {
2250: Position pos = caret.getDot();
2251: Iterator it = selected.iterator();
2252: boolean inside = false;
2253: while (it.hasNext()) {
2254: FormObject fob = (FormObject)it.next();
2255: Element el = FacesSupport.getElement(fob.component);
2256: if (pos.isInside(el)) {
2257: inside = true;
2258: }
2259: }
2260: if (!inside) {
2261: pane.hideCaret();
2262: }
2263: }
2264: */
2265: return;
2266: }
2267: }
2268:
2269: // See if we're resizing a table
2270: interaction = selBox.getInternalResizer(x, y);
2271:
2272: if (interaction != null) {
2273: interaction.mousePressed(e);
2274:
2275: return;
2276: }
2277:
2278: // Start a drag
2279: // User has clicked on a component: either select or
2280: // drag, depending on whether the current position
2281: // is different from the original click position
2282: //selectAt(e, false);
2283: dontCycleInClickHandler = ensurePointSelected(e);
2284:
2285: int size = sm.getNumSelected() + 1;
2286: List<Rectangle> selections = new ArrayList<Rectangle>(
2287: size);
2288: List<CssBox> boxes = new ArrayList<CssBox>(size);
2289: // List<MarkupDesignBean> beans = new ArrayList<MarkupDesignBean>(size);
2290: List<Element> componentRootElements = new ArrayList<Element>(
2291: size);
2292: // Iterator it = sm.iterator();
2293: //
2294: // while (it.hasNext()) {
2295: // MarkupDesignBean bean = (MarkupDesignBean)it.next();
2296: for (Element componentRootElement : sm
2297: .getSelectedComponentRootElements()) {
2298: // MarkupDesignBean bean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(componentRootElement);
2299:
2300: // CssBox box = mapper.findBox(bean);
2301: CssBox box = ModelViewMapper
2302: .findBoxForComponentRootElement(webform
2303: .getPane().getPageBox(),
2304: componentRootElement);
2305:
2306: if (box == null) {
2307: // ErrorManager.getDefault().log("No box found for element " + bean);
2308: // ErrorManager.getDefault().log("No box found for element=" + componentRootElement);
2309: info("No box found for element="
2310: + componentRootElement);
2311:
2312: continue;
2313: }
2314:
2315: if (box == pane.getPageBox()) {
2316: continue;
2317: }
2318:
2319: // Rectangle a = mapper.getComponentBounds(bean);
2320: // Rectangle a = ModelViewMapper.getComponentBounds(webform.getPane().getPageBox(), bean);
2321: Rectangle a = ModelViewMapper
2322: .getComponentBounds(webform.getPane()
2323: .getPageBox(),
2324: componentRootElement);
2325:
2326: if (a != null) {
2327: addDragItem(selections, boxes,
2328: componentRootElements, /*beans,*/
2329: a, p, box);
2330: }
2331: }
2332:
2333: // if (!sm.isSelected(sel)) {
2334: if (!sm.isSelected(sel)) {
2335: // The currently clicked item is not in the selection
2336: // set yet
2337: // Rectangle a = mapper.findShape(sel);
2338: // CssBox box = mapper.findBox(sel);
2339: Rectangle a = ModelViewMapper.findShape(
2340: pageBox, sel);
2341: // CssBox box = ModelViewMapper.findBox(pageBox, sel);
2342: CssBox box = ModelViewMapper
2343: .findBoxForComponentRootElement(
2344: pageBox, sel);
2345:
2346: if (a != null) {
2347: addDragItem(selections, boxes,
2348: componentRootElements, /*beans,*/
2349: a, p, box);
2350: }
2351: }
2352:
2353: if (selections.size() > 0) {
2354: // dragger = new Dragger(webform, boxes, selections, beans);
2355: dragger = new Dragger(
2356: webform,
2357: boxes,
2358: selections,
2359: componentRootElements
2360: .toArray(new Element[componentRootElements
2361: .size()]));
2362: interaction = dragger;
2363: interaction.mousePressed(e);
2364: }
2365: }
2366: }
2367: }
2368:
2369: /** If the given mouse event is not over a component in
2370: * the selection, select the component at that location
2371: * (subject to modifier keys for toggling rather than
2372: * add etc.) It will also update the primary selection
2373: * object, if necessary, and in that case schedule a repaint.
2374: * @return true iff the selection was changed
2375: */
2376: private boolean ensurePointSelected(MouseEvent e) {
2377: // Make sure that the component is selected
2378: // ModelViewMapper mapper = webform.getMapper();
2379: // CssBox bx = mapper.findBox(e.getX(), e.getY());
2380: CssBox bx = ModelViewMapper.findBox(webform.getPane()
2381: .getPageBox(), e.getX(), e.getY());
2382:
2383: /* TODO - this sorta works, but I've gotta suppress it
2384: * when you select a text node below a jsf component!
2385: // In flow mode, clicking on text should not select the
2386: // surrounding component
2387: if (!webform.getDocument().isGridMode() &&
2388: bx instanceof TextBox) {
2389: boolean old = isSelectionEmpty();
2390: clearSelection(true);
2391: return !old;
2392: }
2393: */
2394: SelectionManager sm = webform.getSelection();
2395: CssBox ancestor = null;
2396:
2397: if (bx != null) {
2398: // MarkupDesignBean boxMarkupDesignBean = CssBox.getMarkupDesignBeanForCssBox(bx);
2399: // if ((bx.getDesignBean() != null) && sm.isSelected(bx.getDesignBean())) {
2400: Element componentRootElement = CssBox
2401: .getElementForComponentRootCssBox(bx);
2402: if ((componentRootElement != null)
2403: && sm.isSelected(componentRootElement)) {
2404: ancestor = bx;
2405: } else {
2406: ancestor = sm.getSelectedAncestor(bx);
2407: }
2408: }
2409:
2410: // #94266 Toggle only on click not press or release
2411: // if ((ancestor == null) !! !isToggleEvent(e)) { // didn't click over part of the selection
2412: // selectAt(e, !isToggleEvent(e));
2413: if ((ancestor == null) && !isToggleEvent(e)) { // didn't click over part of the selection
2414: selectAt(e, true);
2415:
2416: return true;
2417: } else {
2418:
2419: // MarkupDesignBean ancestorMarkupDesignBean = CssBox.getMarkupDesignBeanForCssBox(ancestor);
2420: // if (sm.getPrimary() != ancestor.getDesignBean()) {
2421: // sm.setPrimary(ancestor.getDesignBean());
2422: Element ancestorComponentRootElement = CssBox
2423: .getElementForComponentRootCssBox(ancestor);
2424: if (sm.getPrimary() != ancestorComponentRootElement) {
2425: sm.setPrimary(ancestorComponentRootElement);
2426: webform.getPane().repaint();
2427: }
2428:
2429: return false;
2430: }
2431: }
2432:
2433: private void addDragItem(List<Rectangle> selections,
2434: List<CssBox> boxes,
2435: List<Element> componentRootElements, /*List<MarkupDesignBean> beans,*/
2436: Rectangle r, Point p, CssBox box) {
2437: // MarkupDesignBean bean = box.getDesignBean();
2438: // MarkupDesignBean bean = CssBox.getMarkupDesignBeanForCssBox(box);
2439: Element componentRootElement = CssBox
2440: .getElementForComponentRootCssBox(box);
2441: // MarkupDesignBean pbean = findMovableParent(box);
2442: // MarkupDesignBean pbean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(findMovableParentComponentRootElement(box));
2443: Element pComponentRootElement = findMovableParentComponentRootElement(box);
2444:
2445: // if (pbean == null) {
2446: // pbean = bean;
2447: // }
2448: if (pComponentRootElement == null) {
2449: pComponentRootElement = componentRootElement;
2450: }
2451:
2452: // if (pbean != bean) {
2453: if (pComponentRootElement != componentRootElement) {
2454: // We're an "unrepositionable" child in another container,
2455: // so we want to move the parent container.
2456: // bean = pbean;
2457: componentRootElement = pComponentRootElement;
2458:
2459: // Since the user may have chosen multiple children in
2460: // this container, make sure that we don't already have
2461: // the parent in the list - if so, just skip it
2462: // int n = beans.size();
2463: // for (int i = 0; i < n; i++) {
2464: // if (beans.get(i) == bean) {
2465: // return;
2466: // }
2467: // }
2468: if (componentRootElements
2469: .contains(componentRootElement)) {
2470: return;
2471: }
2472:
2473: // Change the view rectangle to reflect the parent instead
2474: // box = webform.getMapper().findBox(pbean);
2475: // box = ModelViewMapper.findBoxForComponentRootElement(webform.getPane().getPageBox(),
2476: // WebForm.getDomProviderService().getComponentRootElementForMarkupDesignBean(pbean));
2477: box = ModelViewMapper.findBoxForComponentRootElement(
2478: webform.getPane().getPageBox(),
2479: pComponentRootElement);
2480:
2481: if (box == null) {
2482: // This item not draggable for some reason
2483: // ErrorManager.getDefault().log("Didn't find box for " + pComponentRootElement); // NOI18N
2484: info("Didn't find box for " + pComponentRootElement); // NOI18N
2485: return;
2486: }
2487:
2488: r = new Rectangle(box.getAbsoluteX(), box
2489: .getAbsoluteY(), box.getWidth(), box
2490: .getHeight());
2491: }
2492:
2493: // XXX OUCH - is this going to break when the
2494: // view scrolls?
2495: // TODO - can I just modify r instead of creating
2496: // a new view here?
2497: Rectangle nr = new Rectangle(r.x - p.x, r.y - p.y, r.width,
2498: r.height);
2499: selections.add(nr);
2500: boxes.add(box);
2501:
2502: //assert bean == fo.component; // why search again??? pass it in!
2503: // beans.add(bean);
2504: componentRootElements.add(componentRootElement);
2505: }
2506:
2507: /** escape-like things: cancel dragging, select parent, etc. */
2508: public void escape() {
2509: DesignerPane pane = webform.getPane();
2510: PageBox pageBox = pane.getPageBox();
2511: // ModelViewMapper mapper = webform.getMapper();
2512:
2513: if (inlineEditor != null) {
2514: // Restore cursor:
2515: // XXX can I use my stashed position from cut & paste pointer tracking? Also, JDK 1.5 has this directly lookupable!!
2516: // Don't have a mouse event: mouseMoved(e);
2517: pane.setCursor(Cursor
2518: .getPredefinedCursor(Cursor.DEFAULT_CURSOR));
2519:
2520: finishInlineEditing(true);
2521: } else if (ENABLE_DOM_INSPECTOR
2522: && (pageBox.getSelected() != null)) {
2523: CssBox parent = null;
2524: org.w3c.dom.Node parentNode = pageBox.getSelected()
2525: .getElement().getParentNode();
2526:
2527: if (parentNode instanceof Element) {
2528: // parent = mapper.findBox((Element)parentNode);
2529: parent = ModelViewMapper.findBox(pageBox,
2530: (Element) parentNode);
2531: }
2532:
2533: if (parent == null) {
2534: parent = pageBox.getSelected().getParent();
2535: }
2536:
2537: // Skip lineboxes since users shouldn't know they exist
2538: while (parent instanceof LineBox
2539: || parent instanceof LineBoxGroup) {
2540: parent = parent.getParent();
2541: }
2542:
2543: if (parent != null) {
2544: selectDomInspectorBox(parent);
2545: }
2546:
2547: return;
2548: }
2549:
2550: if (insertModeBox != null) {
2551: setInsertBox(null, null);
2552:
2553: // Restore cursor:
2554: // Don't have a mouse event: mouseMoved(e);
2555: // XXX can I use my stashed position from cut & paste pointer tracking? Also, JDK 1.5 has this directly lookupable!!
2556: pane.setCursor(Cursor
2557: .getPredefinedCursor(Cursor.DEFAULT_CURSOR));
2558: pane.repaint();
2559: } else if (interaction != null) {
2560: if (sizer != null) {
2561: sizer = null;
2562:
2563: // if (paletteItemSelected) { // XXX make part of sizer cleanup!
2564: if (isCnCInProgress()) { // XXX make part of sizer cleanup!
2565: // clearPalette();
2566: stopCnC();
2567: }
2568: }
2569:
2570: dragger = null;
2571:
2572: // Also get out of the insert mode
2573: interaction.cancel(pane);
2574: interaction = null;
2575:
2576: // Restore cursor:
2577: // Don't have a mouse event: mouseMoved(e);
2578: pane.setCursor(Cursor
2579: .getPredefinedCursor(Cursor.DEFAULT_CURSOR));
2580: // } else if (paletteItemSelected) {
2581: } else if (isCnCInProgress()) {
2582: // clearPalette();
2583: stopCnC();
2584:
2585: // Restore cursor:
2586: // Don't have a mouse event: mouseMoved(e);
2587: pane.setCursor(Cursor
2588: .getPredefinedCursor(Cursor.DEFAULT_CURSOR));
2589: } else {
2590: // webform.getActions().selectParent();
2591: // DesignBean defaultSelectionBean = getDefaultSelectionBean();
2592: // if (defaultSelectionBean instanceof MarkupDesignBean) {
2593: // SelectionManager.selectParent(WebForm.getDomProviderService().getComponentRootElementForMarkupDesignBean((MarkupDesignBean)defaultSelectionBean));
2594: // }
2595: // SelectionManager.selectParent(getDefaultSelectionComponentRootElement());
2596: // XXX #111692 Selecting parent.
2597: // FIXME Duplicates code in designer/jsf/../SelectParentAction, unify.
2598: Element defaultSelectionComponent = getDefaultSelectionComponentRootElement();
2599: Element selectableParent = getSelectableParent(defaultSelectionComponent);
2600: if (selectableParent != null) {
2601: webform.getSelection().selectComponent(
2602: selectableParent);
2603: }
2604: }
2605: }
2606:
2607: /**
2608: On mouse release we need to handle the following cases:
2609: - If it's a right click (platform dependent), and it's a
2610: popup trigger (which it will be on say Windows but not
2611: Solaris), popup a popup menu
2612: - If we were in a mouse-operation like dragging, resizing
2613: or selection swiping, that operation should be completed
2614: - If we're in inline editing mode, forward the press event
2615: to the caret handler, which uses the event to finalize
2616: the selection range swept during dragging)
2617: */
2618: public void mouseReleased(MouseEvent e) {
2619: DesignerPane pane = webform.getPane();
2620: // DesignerCaret caret = pane.getCaret();
2621: // ModelViewMapper mapper = webform.getMapper();
2622:
2623: // if (!paletteItemSelected && (inlineEditor != null) && (caret != null)) {
2624: // if (!isCnCInProgress() && (inlineEditor != null) && (caret != null)) {
2625: if (!isCnCInProgress() && (inlineEditor != null)
2626: && pane.hasCaret()) {
2627: // CssBox selBox = mapper.findBox(e.getX(), e.getY());
2628: CssBox selBox = ModelViewMapper.findBox(pane
2629: .getPageBox(), e.getX(), e.getY());
2630:
2631: // if ((selBox.getDesignBean() == null) && inlineEditor.isEdited(selBox)) {
2632: // if ((CssBox.getMarkupDesignBeanForCssBox(selBox) == null) && inlineEditor.isEdited(selBox)) {
2633: if ((CssBox.getElementForComponentRootCssBox(selBox) == null)
2634: && inlineEditor.isEdited(selBox)) {
2635: // Reroute the mouse press to the insert box
2636: // caret.mouseReleased(e);
2637: pane.mouseReleased(e);
2638:
2639: //return;
2640: } // else fall through: over something like a button in the insert box: let it
2641:
2642: // be selected in the normal way
2643: // } else if (!paletteItemSelected && (insertModeBox != null) && (caret != null)
2644: // } else if (!isCnCInProgress() && (insertModeBox != null) && (caret != null)
2645: } else if (!isCnCInProgress() && (insertModeBox != null)
2646: && pane.hasCaret() && isInside(insertModeBox, e)) {
2647: // CssBox selBox = mapper.findBox(e.getX(), e.getY());
2648: CssBox selBox = ModelViewMapper.findBox(pane
2649: .getPageBox(), e.getX(), e.getY());
2650:
2651: // if (selBox.getDesignBean() == null) {
2652: // if (CssBox.getMarkupDesignBeanForCssBox(selBox) == null) {
2653: if (CssBox.getElementForComponentRootCssBox(selBox) == null) {
2654: // Reroute the mouse press to the insert box
2655: // caret.mouseReleased(e);
2656: pane.mouseReleased(e);
2657:
2658: //return;
2659: } // else fall through: over something like a button in the insert box: let it
2660:
2661: // be selected in the normal way
2662: // } else if (!webform.getDocument().isGridMode() && (caret != null)) {
2663: // } else if (!webform.isGridModeDocument() && (caret != null)) {
2664: // } else if (!webform.isGridModeDocument() && pane.hasCaret()) {
2665: } else if (!webform.isGridMode() && pane.hasCaret()) {
2666: // caret.mouseReleased(e);
2667: pane.mouseReleased(e);
2668:
2669: // fall through
2670: }
2671:
2672: // XXX Do I have to compute a translated position here?
2673: // What if you release over a JButton?
2674: if (sizer != null) {
2675: // TODO Compute the size from the marquee!
2676: Rectangle r = sizer.getBounds();
2677: interaction.mouseReleased(e); // TODO - no selection here!
2678: interaction = null;
2679: sizer = null;
2680:
2681: // if (paletteItemSelected) {
2682: if (isCnCInProgress()) {
2683: // XXX We need to get rid of this dep, change impl.
2684: // Object item = getPaletteItem();
2685: Transferable item = cncTransferable;
2686: // clearPalette();
2687: stopCnC();
2688:
2689: // Insert Component
2690: DndHandler dth = pane.getDndHandler();
2691: dontCycleInClickHandler = true;
2692:
2693: Point ep;
2694:
2695: if ((r.width == 0) && (r.height == 0)) {
2696: // Not insert-sizing, just dropping at the given coordinate:
2697: // don't use sizer's position (which is generally snapped to grid)
2698: ep = e.getPoint();
2699: } else {
2700: ep = new Point(r.x, r.y);
2701: }
2702:
2703: updateDropState(ep, true, null);
2704:
2705: translateMousePos(ep, (Component) e.getSource());
2706:
2707: Dimension s = r.getSize();
2708:
2709: if ((s.width > 2) || (s.height > 2)) {
2710: dth.setDropSize(s);
2711: }
2712:
2713: Transferable transferable = null;
2714:
2715: if (item == null) {
2716: // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
2717: // new IllegalStateException("Invalid item=" + item)); // NOI18N
2718: info(new IllegalStateException("Invalid item="
2719: + item)); // NOI18N
2720:
2721: } else {
2722: transferable = item;
2723: }
2724: // else if (item instanceof PaletteItem) {
2725: // transferable =
2726: // PaletteItemTransferable.createTransferable((PaletteItem)item); //component
2727: // }
2728:
2729: int dropType = dth.getDropType(ep, transferable,
2730: false);
2731:
2732: if (dropType != DndHandler.DROP_DENIED) {
2733: // DndHandler.setActiveTransferable(transferable);
2734:
2735: // Drop it
2736: if (transferable != null) {
2737: dth.importData(pane, transferable);
2738: }
2739: }
2740:
2741: // Restore cursor:
2742: mouseMoved(e);
2743: }
2744: } else if (dragger != null) {
2745: // Handle dragging and selection of a new component
2746: // in the same place since clicking and releasing over
2747: // a component is both a (0,0) drag and selecting a new
2748: // component :)
2749: boolean hasMoved = dragger.hasMoved();
2750: interaction.mouseReleased(e);
2751: interaction = null;
2752: dragger = null;
2753:
2754: SelectionManager sm = webform.getSelection();
2755:
2756: // #94266 Toggle only on click not press or release
2757: // if (!hasMoved && !isToggleEvent(e) && (sm.getNumSelected() > 1)) {
2758: // // You've pressed the mouse button when there
2759: // // was more than one selected component, but
2760: // // you didn't drag and didn't press a toggle
2761: // // key: in this case you want to select only
2762: // // the component that received the click.
2763: // sm.clearSelection(false);
2764: // selectAt(e, false);
2765: // }
2766: } else if (interaction != null) {
2767: interaction.mouseReleased(e);
2768: interaction = null;
2769: }
2770:
2771: // TODO: transfer to the renderers
2772: //StatusDisplayer.getDefault().clearPositionLabel();
2773: }
2774:
2775: /**
2776: * Select the component at a position pointed to by the mouse event.
2777: * This typically finds the "closest" (e.g. furthest down the
2778: * element tree) match; however, if an ancestor of the element
2779: * at the mouse position is already selected, we will operate on
2780: * it instead.
2781: *
2782: * @param e Mouse event. The two fields that are considered are
2783: * the position, and the source. The source is used to translate
2784: * the position to the coordinate system of the design pane,
2785: * and the point is obviously used to determine which component
2786: * in the pane is being pointed at.
2787: * @param keepAncestorSelection This flag controls whether a mouse
2788: * click on a component that is contained within a selection
2789: * should unselect the parent and select the closest element,
2790: * or leave the parent selected. For example, when you right
2791: * click, you want to keep the parent selection, but when you
2792: * left click, you don't.
2793: */
2794: public void selectAt(MouseEvent e, boolean keepAncestorSelection) {
2795: // User has clicked on a component: either select or
2796: // drag, depending on whether the current position
2797: // is different from the original click position
2798: Point p = e.getPoint();
2799: translateMousePos(p, (Component) e.getSource());
2800:
2801: // TODO - consider impact of component hierarchy changes in GridHandler
2802: int x = p.x;
2803: int y = p.y;
2804:
2805: SelectionManager sm = webform.getSelection();
2806:
2807: if (p.y > sm.selectionViewPos) {
2808: sm.selectAncestor(p.x, p.y);
2809: }
2810:
2811: // MarkupDesignBean component = null;
2812: Element component = null;
2813:
2814: // ModelViewMapper mapper = webform.getMapper();
2815: // CssBox bx = mapper.findBox(x, y);
2816: CssBox bx = ModelViewMapper.findBox(webform.getPane()
2817: .getPageBox(), x, y);
2818:
2819: if ((bx != null) && !(bx instanceof PageBox)) { // can't select body
2820: // component = ModelViewMapper.findComponent(bx);
2821: // component = ModelViewMapper.findMarkupDesignBean(bx);
2822: component = ModelViewMapper
2823: .findComponentRootElement(bx);
2824: }
2825:
2826: if (component != null) {
2827: // sm.setPrimary(component);
2828: sm.setPrimary(component);
2829:
2830: // CssBox sel = mapper.findBox(component);
2831: CssBox sel = ModelViewMapper
2832: .findBoxForComponentRootElement(webform
2833: .getPane().getPageBox(), component);
2834: CssBox insertBox = null;
2835: CssBox ancestor;
2836:
2837: if (keepAncestorSelection) {
2838: ancestor = sm.getSelectedAncestor(sel);
2839:
2840: if ((ancestor != null) && (ancestor != sel)) {
2841: // component = ancestor.getDesignBean();
2842: // component = CssBox.getMarkupDesignBeanForCssBox(ancestor);
2843: component = CssBox
2844: .getElementForComponentRootCssBox(ancestor);
2845: }
2846: } else {
2847: // ancestor = sm.isSelected(component) ? sel : null;
2848: ancestor = sm.isSelected(component) ? sel : null;
2849: }
2850:
2851: boolean alreadySelected = ancestor != null;
2852:
2853: // I would -like- to do control-select to toggle
2854: // selection - but many IDEs use the shift key for this.
2855: // Also, control-click often means right-click
2856: // (context menu) - on OSX with a one button mouse it's
2857: // how you get the popup menu for example.
2858: if (isToggleEvent(e)) {
2859: dontCycleInClickHandler = true;
2860:
2861: // Toggle selected component
2862: if (alreadySelected) {
2863: // sm.removeSelected(component, false);
2864: sm.removeSelected(component, false);
2865: } else {
2866: // sm.addSelected(component, false);
2867: sm.addSelected(component, false);
2868: }
2869: } else if (alreadySelected && (e.getButton() == 1) /* &&
2870: (isInlineEditable(component))*/) {
2871: // Possibly go into inline mode (unless this component
2872: // does not support that
2873: insertBox = ancestor;
2874: } else {
2875: // Replace selection
2876: if (!alreadySelected) {
2877: sm.clearSelection(false);
2878: // sm.addSelected(component, false);
2879: sm.addSelected(component, false);
2880: }
2881: }
2882:
2883: insertBox = findInsertBox(insertBox);
2884: setInsertBox(insertBox, e);
2885:
2886: // sm.updateSelection();
2887: sm.updateSelectionImmediate();
2888:
2889: webform.getPane().repaint();
2890:
2891: // XXX I stopped disabling selection in clearSelection for false;
2892: // do I have to reenable this here?
2893: selectedBox = null;
2894: } else {
2895: if (bx != null) {
2896: bx = findInsertBox(bx);
2897:
2898: if (selectedBox == bx) {
2899: setInsertBox(bx, e);
2900: } else {
2901: // Clicked outside of a component: clear selection
2902: setInsertBox(null, null);
2903: }
2904: } else {
2905: setInsertBox(null, null);
2906: }
2907:
2908: selectedBox = bx;
2909:
2910: // #6450569 Nodes needs to update immediatelly.
2911: // sm.clearSelection(true);
2912: sm.clearSelectionImmediate();
2913: }
2914: }
2915:
2916: public void mouseEntered(MouseEvent e) {
2917: // if (!webform.getModel().isValid()) {
2918: // XXX Model validty shouldn't be checked here.
2919: // if (!webform.isModelValid()) {
2920: // return;
2921: // }
2922:
2923: // // Check to see if a selection is potentially in effect
2924: // paletteItemSelected = false;
2925:
2926: // PaletteComponentModel palette = PaletteComponentModel.getInstance();
2927: //
2928: // if ((palette.getSelectedPalette() != null) &&
2929: // (palette.getSelectedPalette().getSelectedPaletteSection() != null) &&
2930: // (palette.getSelectedPalette().getSelectedPaletteSection()
2931: // .getSelectedPaletteItem() != null)) {
2932: // PaletteItem item =
2933: // palette.getSelectedPalette().getSelectedPaletteSection().getSelectedPaletteItem();
2934: //
2935: // if (item instanceof BeanPaletteItem) {
2936: // BeanPaletteItem bitem = (BeanPaletteItem)item;
2937: //
2938: // BeanCreateInfo bci = bitem.getBeanCreateInfo();
2939: // BeanCreateInfoSet bcis = bitem.getBeanCreateInfoSet();
2940: //
2941: // // At most one of the above should be set...
2942: // assert !((bci != null) && (bcis != null));
2943: //
2944: // if (bcis != null) {
2945: // // Set us up for multiple bean creation
2946: // paletteItems = bcis.getBeanClassNames();
2947: // } else if (bci != null) {
2948: // paletteItems = new String[] { bci.getBeanClassName() };
2949: // } else {
2950: // paletteItems = new String[] { bitem.getBeanClassName() };
2951: // }
2952: // } else {
2953: // paletteItems = null;
2954: // }
2955: //
2956: // paletteItemSelected = true;
2957: //
2958: // return;
2959: // }
2960:
2961: // getSelectionFromPalette();
2962: if (e.getButton() == e.NOBUTTON) {
2963: // XXX #6245208 This is not DnD, allow CnC.
2964: setIgnoreCnC(false);
2965: }
2966: tryStartCnC();
2967: }
2968:
2969: // private void getSelectionFromPalette() {
2970: //// TopComponent comp = TopComponent.getRegistry().getActivated();
2971: //// if ((comp != null) && (comp != webform.getTopComponent()) &&
2972: //// (comp instanceof ExplorerManager.Provider)) {
2973: //// ExplorerManager.Provider provider = (ExplorerManager.Provider)comp;
2974: //// ExplorerManager m = provider.getExplorerManager();
2975: ////
2976: //// Node[] nodes = m.getSelectedNodes();
2977: ////
2978: //// for (int i = 0; (nodes != null) && (i < nodes.length); i++) {
2979: //// RavePaletteItemSetCookie pisc =
2980: //// (RavePaletteItemSetCookie)nodes[i].getCookie(RavePaletteItemSetCookie.class);
2981: ////
2982: //// if (pisc != null) {
2983: //// if (pisc.hasPaletteItems()) {
2984: //// paletteItemSelected = true;
2985: //// selectedManager = m;
2986: //// paletteItems = pisc.getClassNames();
2987: ////
2988: //// return;
2989: //// }
2990: //// }
2991: //// }
2992: //// }
2993: // TopComponent commonPalette = findCommonPaletteWindow();
2994: // if (commonPalette != null && commonPalette == TopComponent.getRegistry().getActivated()) {
2995: // Lookup selectedItem = webform.getPaletteController().getSelectedItem();
2996: //// String[] classNames = getClassNamesFromPaletteItem(selectedItem);
2997: //// if (classNames.length > 0) {
2998: //// paletteItemSelected = true;
2999: ////// selectedManager = m;
3000: ////// paletteItems = classNames;
3001: //// }
3002: // cncTransferable = getTransferableFromPaletteItem(selectedItem);
3003: // } else {
3004: // cncTransferable = null;
3005: // }
3006: //// paletteItemSelected = cncTransferable != null;
3007: // }
3008:
3009: // /**
3010: // * Locate whichever palette items are selected in other components,
3011: // * and return these. It will return a PaletteItem, if one is
3012: // * found directly, or a Transferable, if the Node only provides
3013: // * that.
3014: // */
3015: // private Transferable getSelectedPaletteItemTransferable() {
3016: //// PaletteComponentModel palette = PaletteComponentModel.getInstance();
3017: ////
3018: //// if ((palette.getSelectedPalette() != null) &&
3019: //// (palette.getSelectedPalette().getSelectedPaletteSection() != null) &&
3020: //// (palette.getSelectedPalette().getSelectedPaletteSection()
3021: //// .getSelectedPaletteItem() != null)) {
3022: //// return palette.getSelectedPalette().getSelectedPaletteSection()
3023: //// .getSelectedPaletteItem();
3024: //// } else
3025: //
3026: //// if (selectedManager != null) {
3027: //// Node[] nodes = selectedManager.getSelectedNodes();
3028: ////
3029: //// if (nodes == null) {
3030: //// return null;
3031: //// }
3032: ////
3033: //// for (int i = 0; i < nodes.length; i++) {
3034: //// RavePaletteItemSetCookie pisc =
3035: //// (RavePaletteItemSetCookie)nodes[i].getCookie(RavePaletteItemSetCookie.class);
3036: ////
3037: //// if ((pisc != null) && pisc.hasPaletteItems()) {
3038: //// // instead provide items directly, but that
3039: //// // means PaletteItem has to move into openide
3040: //// // etc. so I'll revisit this after TP.
3041: //// // (In addition to inefficiency, the problem with
3042: //// // this is it actually affects the clipbard.)
3043: //// try {
3044: //// return nodes[i].clipboardCopy();
3045: //// } catch (Exception ex) {
3046: //// ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
3047: //// return null;
3048: //// }
3049: //// }
3050: //// }
3051: //// }
3052: ////
3053: //// return null;
3054: // Lookup selectedItem = webform.getPaletteController().getSelectedItem();
3055: // return getTransferableFromPaletteItem(selectedItem);
3056: // }
3057:
3058: // private void clearPalette() {
3059: // paletteItemSelected = false;
3060: //
3061: //// PaletteComponentModel palette = PaletteComponentModel.getInstance();
3062: ////
3063: //// if ((palette.getSelectedPalette() != null) &&
3064: //// (palette.getSelectedPalette().getSelectedPaletteSection() != null) &&
3065: //// (palette.getSelectedPalette().getSelectedPaletteSection()
3066: //// .getSelectedPaletteItem() != null)) {
3067: //// palette.getSelectedPalette().getSelectedPaletteSection().setSelectedPaletteItem(null);
3068: //// } else
3069: // if (selectedManager != null) {
3070: // try {
3071: // selectedManager.setSelectedNodes(new Node[0]);
3072: // } catch (Exception e) {
3073: // ErrorManager.getDefault().notify(e);
3074: // }
3075: //
3076: // selectedManager = null;
3077: // }
3078: //
3079: // paletteItems = null;
3080: // }
3081:
3082: // private void doClearPalette() {
3083: //// TopComponent comp = TopComponent.getRegistry().getActivated();
3084: //// if ((comp != null) && (comp instanceof ExplorerManager.Provider)) {
3085: //// ExplorerManager.Provider provider = (ExplorerManager.Provider)comp;
3086: //// final ExplorerManager m = provider.getExplorerManager();
3087: ////
3088: //// Node[] nodes = m.getSelectedNodes();
3089: ////
3090: //// for (int i = 0; (nodes != null) && (i < nodes.length); i++) {
3091: //// RavePaletteItemSetCookie pisc =
3092: //// (RavePaletteItemSetCookie)nodes[i].getCookie(RavePaletteItemSetCookie.class);
3093: ////
3094: //// if (pisc != null) {
3095: //// if (pisc.hasPaletteItems()) {
3096: //// SwingUtilities.invokeLater(new Runnable() {
3097: //// public void run() {
3098: //// try {
3099: //// m.setSelectedNodes(new Node[0]);
3100: //// } catch (Exception e) {
3101: //// ErrorManager.getDefault().notify(e);
3102: //// }
3103: //// }
3104: //// });
3105: //// }
3106: //// }
3107: //// }
3108: //// }
3109: //
3110: //// paletteItemSelected = false;
3111: //
3112: //// TopComponent commonPalette = findCommonPaletteWindow();
3113: //// if (commonPalette != null && commonPalette == TopComponent.getRegistry().getActivated()) {
3114: //// webform.getPaletteController().clearSelection();
3115: //// }
3116: //
3117: //// paletteItems = null;
3118: // cncTransferable = null;
3119: // }
3120:
3121: // XXX #104464 To be albe to keep track to the origin of the cnc (in order to deselect it).
3122: private WeakReference<TopComponent> cncOriginWRef = new WeakReference<TopComponent>(
3123: null);
3124:
3125: /** Tries to start the CnC (Click and Click) operation.
3126: * Currently it simulates the operation from common palette or runtime window. */
3127: private void tryStartCnC() {
3128: if (isIgnoreCnC()) {
3129: // XXX #6245208 Should mean DnD is in progress or was and was escaped.
3130: setIgnoreCnC(false);
3131: cncTransferable = null;
3132: return;
3133: }
3134:
3135: TopComponent activated = TopComponent.getRegistry()
3136: .getActivated();
3137: cncOriginWRef = new WeakReference<TopComponent>(activated);
3138: if (activated == null) {
3139: cncTransferable = null;
3140: return;
3141: }
3142:
3143: if (activated == findCommonPaletteWindow()) {
3144: cncTransferable = getTransferableFromCommonPalette(webform);
3145: } else if (activated instanceof ExplorerManager.Provider) {
3146: cncTransferable = getTransferableFromExplorer(activated);
3147: } else {
3148: cncTransferable = null;
3149: }
3150: }
3151:
3152: private boolean isCnCInProgress() {
3153: return cncTransferable != null;
3154: }
3155:
3156: /** Stops CnC (Click and Click) operation. */
3157: private void stopCnC() {
3158: cncTransferable = null;
3159:
3160: TopComponent cncOrigin = cncOriginWRef.get();
3161: if (cncOrigin instanceof ExplorerManager.Provider) {
3162: clearExplorerManager(((ExplorerManager.Provider) cncOrigin)
3163: .getExplorerManager());
3164: } else {
3165: // XXX #6476367 They want to also deselect the palette item, like it was before.
3166: clearPaletteSelection();
3167: }
3168: }
3169:
3170: private void clearExplorerManager(
3171: ExplorerManager explorerManager) {
3172: try {
3173: if (explorerManager == null) {
3174: return;
3175: }
3176: explorerManager.setSelectedNodes(new Node[0]);
3177: } catch (PropertyVetoException ex) {
3178: fine(ex);
3179: }
3180: }
3181:
3182: private void clearPaletteSelection() {
3183: WebForm webForm = InteractionManager.this .webform;
3184: if (webForm == null) {
3185: return;
3186: }
3187: PaletteController paletteController = webForm
3188: .getPaletteController();
3189: if (paletteController == null) {
3190: return;
3191: }
3192: paletteController.clearSelection();
3193: }
3194:
3195: public void mouseExited(MouseEvent e) {
3196: //clearCurrentPos();
3197: // Don't clear out the menu position, since mouseExited will be
3198: // called when the popup menu pops up too and we don't want this
3199: // to clear the menu position we're trying to stash away
3200: currentPos.x = -1;
3201: currentPos.y = -1;
3202:
3203: // paletteItemSelected = false;
3204: // selectedManager = null;
3205: stopCnC();
3206:
3207: // if (!webform.getModel().isValid()) {
3208: // XXX Model validity shouldn't be checked here.
3209: // if (!webform.isModelValid()) {
3210: // return;
3211: // }
3212:
3213: webform.getPane().getDndHandler().clearDropMatch();
3214: }
3215:
3216: // track the moving of the mouse.
3217: public void mouseMoved(MouseEvent e) {
3218: // When pages are deleted mouse motion can happen over
3219: // the page briefly before it's taken down; ensure that
3220: // this is not the case here so we don't try to look at
3221: // the model
3222: // if (!webform.getModel().isValid()) {
3223: // XXX Model validity shouldn't be checked here.
3224: // if (!webform.isModelValid()) {
3225: // return;
3226: // }
3227:
3228: currentPos.x = e.getX();
3229: currentPos.y = e.getY();
3230:
3231: // When debugging mouse and findview events, mouse motion
3232: // triggering events is really annoying.
3233: if (SKIP_MOUSE_MOTION) {
3234: return;
3235: }
3236:
3237: if (dragger != null) {
3238: // HACK
3239: // Workaround for bug on Mac OSX where if the control
3240: // key is pressed when we start dragging, we receive mouse
3241: // moved events rather than mouse dragged events.
3242: // They should however be treated as mouse drags.
3243: try {
3244: interaction.mouseDragged(e);
3245: } catch (Exception ex) {
3246: // ErrorManager.getDefault().notify(ex);
3247: info(ex);
3248: escape();
3249: }
3250:
3251: return;
3252: }
3253:
3254: // Change the cursor to MOVE cursor over components.
3255: // Change it to directions over selection handles.
3256: // Change it to insert-cursor over flow-layout panels
3257: // (such as table cells)
3258: // Change it to table-column-resize-cursor over table borders.
3259: // Change it to pos-insert-cursor when a selection has
3260: // been made in the toolbox so clicking will dropp
3261: // (and dragging will drop & resize to drag area)
3262: // User has clicked on a component: either select or
3263: // drag, depending on whether the current position
3264: // is different from the original click position
3265: Point p = e.getPoint();
3266:
3267: // if ((sizer != null) || paletteItemSelected) {
3268: if ((sizer != null) || isCnCInProgress()) {
3269: updateDropState(p, false, null);
3270:
3271: return;
3272: }
3273:
3274: translateMousePos(p, (Component) e.getSource());
3275:
3276: int x = p.x;
3277: int y = p.y;
3278:
3279: // First see if we're over a selection dragbar. If so,
3280: // show resize cursor
3281: SelectionManager sm = webform.getSelection();
3282: DesignerPane pane = webform.getPane();
3283: PageBox pageBox = pane.getPageBox();
3284: if (pageBox == null) {
3285: // XXX #122515 NPE, it seems there is a deeper problem somewhere else (model?).
3286: return;
3287: }
3288:
3289: int maxWidth = pageBox.getWidth();
3290: int maxHeight = pageBox.getHeight();
3291: int resize = sm.getSelectionHandleDir(x, y, maxWidth,
3292: maxHeight);
3293:
3294: if (resize != Cursor.DEFAULT_CURSOR) {
3295: pane.setCursor(Cursor.getPredefinedCursor(resize));
3296:
3297: return;
3298: }
3299:
3300: // Else, see if we're over a component. If so, show motion
3301: // cursor.
3302: // ModelViewMapper mapper = webform.getMapper();
3303: // CssBox selBox = mapper.findBox(x, y);
3304: // DesignBean sel = mapper.findComponent(x, y);
3305: CssBox selBox = ModelViewMapper.findBox(pageBox, x, y);
3306: // MarkupDesignBean selMarkupDesignBean = CssBox.getMarkupDesignBeanForCssBox(selBox);
3307: Element selComponentRootElement = CssBox
3308: .getElementForComponentRootCssBox(selBox);
3309: // DesignBean sel = ModelViewMapper.findComponent(pageBox, x, y);
3310: // DesignBean sel = ModelViewMapper.findMarkupDesignBean(pageBox, x, y);
3311: Element sel = ModelViewMapper.findElement(pageBox, x, y);
3312:
3313: int internalResize = selBox
3314: .getInternalResizeDirection(x, y);
3315:
3316: if (internalResize != Cursor.DEFAULT_CURSOR) {
3317: pane.setCursor(Cursor
3318: .getPredefinedCursor(internalResize));
3319: } else if ((selectedBox != null)
3320: && isInside(selectedBox, e)) {
3321: pane.setCursor(Cursor
3322: .getPredefinedCursor(Cursor.TEXT_CURSOR));
3323: } else if ((inlineEditor != null)
3324: && inlineEditor.isEdited(selBox)) {
3325: // If you're pointing at an inline component like a button within a flow,
3326: // make it selectable. But if you're pointing below a rendered component that
3327: // has focus, like an output text, show a text cursor.
3328: // if ((selBox != pageBox) && (selBox.getDesignBean() != null)) {
3329: // if ((selBox != pageBox) && (selMarkupDesignBean != null)) {
3330: if ((selBox != pageBox)
3331: && (selComponentRootElement != null)) {
3332: pane.setCursor(Cursor
3333: .getPredefinedCursor(Cursor.MOVE_CURSOR));
3334: } else {
3335: pane.setCursor(Cursor
3336: .getPredefinedCursor(Cursor.TEXT_CURSOR));
3337: }
3338: } else if ((insertModeBox != null)
3339: && isInside(insertModeBox, e)) {
3340: // If you're pointing at an inline component like a button within a flow,
3341: // make it selectable. But if you're pointing below a rendered component that
3342: // has focus, like an output text, show a text cursor.
3343: // if ((selBox != pageBox) && (selBox.getDesignBean() != null)) {
3344: // if ((selBox != pageBox) && (selMarkupDesignBean != null)) {
3345: if ((selBox != pageBox)
3346: && (selComponentRootElement != null)) {
3347: pane.setCursor(Cursor
3348: .getPredefinedCursor(Cursor.MOVE_CURSOR));
3349: } else {
3350: pane.setCursor(Cursor
3351: .getPredefinedCursor(Cursor.TEXT_CURSOR));
3352: }
3353: } else if ((sel != null) && (selBox != pageBox)) {
3354: pane.setCursor(Cursor
3355: .getPredefinedCursor(Cursor.MOVE_CURSOR));
3356: } else {
3357: pane.setCursor(Cursor
3358: .getPredefinedCursor(Cursor.DEFAULT_CURSOR));
3359: }
3360: }
3361:
3362: } // End of MouseHandler.
3363:
3364: private static class DefaultDesignerClickEvent implements
3365: DesignerClickEvent {
3366: private boolean consumed;
3367: private final int clickCount;
3368: private final Designer designer;
3369: private final Box box;
3370:
3371: public DefaultDesignerClickEvent(Designer designer, Box box,
3372: int clickCount) {
3373: this .designer = designer;
3374: this .box = box;
3375: this .clickCount = clickCount;
3376: }
3377:
3378: public boolean isConsumed() {
3379: return consumed;
3380: }
3381:
3382: public void consume() {
3383: consumed = true;
3384: }
3385:
3386: public int getClickCount() {
3387: return clickCount;
3388: }
3389:
3390: public Designer getDesigner() {
3391: return designer;
3392: }
3393:
3394: public Box getBox() {
3395: return box;
3396: }
3397:
3398: } // DefaultDesignerClickEvent.
3399:
3400: /** XXX Copied from DesignerActions and SelectionManager later. */
3401: // private boolean canSelectParent(/*DesignBean designBean*/Element componentRootElement) {
3402: private Element getSelectableParent(
3403: /*DesignBean designBean*/Element componentRootElement) {
3404: if (componentRootElement == null) {
3405: return null;
3406: }
3407:
3408: // DesignBean designBean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(componentRootElement);
3409: // if (designBean == null) {
3410: // return false;
3411: // }
3412: //
3413: // DesignBean parent = designBean.getBeanParent();
3414: //
3415: //// WebForm webform = WebForm.findWebFormForDesignContext(designBean.getDesignContext());
3416: //// if (webform == null) {
3417: //// return false;
3418: //// }
3419: //// FacesModel model = webform.getModel();
3420: // DesignContext designContext = designBean.getDesignContext();
3421: // if (designContext == null) {
3422: // return false;
3423: // }
3424: Element parentComponentRootElement = webform
3425: .getDomProviderService().getParentComponent(
3426: componentRootElement);
3427:
3428: // while (parent != null) {
3429: while (parentComponentRootElement != null) {
3430:
3431: // XXX #111692 No corresponding box?
3432: if (ModelViewMapper.findBox(webform.getPane().getPageBox(),
3433: parentComponentRootElement) == null) {
3434: parentComponentRootElement = webform
3435: .getDomProviderService().getParentComponent(
3436: parentComponentRootElement);
3437: continue;
3438: }
3439:
3440: // if (parent == model.getRootBean()) {
3441: // if (parent == designContext.getRootContainer()) {
3442: if (webform.getDomProviderService()
3443: .isRootContainerComponent(
3444: parentComponentRootElement)) {
3445: return null;
3446: }
3447:
3448: // if (Util.isSpecialBean(/*webform, */parent)) {
3449: // if (parent instanceof MarkupDesignBean && WebForm.getDomProviderService().isSpecialComponent(
3450: // WebForm.getDomProviderService().getComponentRootElementForMarkupDesignBean((MarkupDesignBean)parent))) {
3451: if (webform.getDomProviderService().isSpecialComponent(
3452: parentComponentRootElement)) {
3453: return null;
3454: }
3455:
3456: /* No longer necessary
3457: if (unit.isVisualBean(parent)) {
3458: return true;
3459: } else {
3460: parent = parent.getLiveParent();
3461: }
3462: */
3463: break;
3464: }
3465:
3466: return parentComponentRootElement;
3467: }
3468:
3469: // // XXX Moved from FacesSupport.
3470: // /** Locate the closest mouse region to the given element */
3471: // private static MarkupMouseRegion findRegion(Element element) {
3472: // while (element != null) {
3473: //// if (element.getMarkupMouseRegion() != null) {
3474: //// return element.getMarkupMouseRegion();
3475: //// }
3476: //// MarkupMouseRegion region = InSyncService.getProvider().getMarkupMouseRegionForElement(element);
3477: // MarkupMouseRegion region = WebForm.getDomProviderService().getMarkupMouseRegionForElement(element);
3478: // if (region != null) {
3479: // return region;
3480: // }
3481: //
3482: // if (element.getParentNode() instanceof Element) {
3483: // element = (Element)element.getParentNode();
3484: // } else {
3485: // break;
3486: // }
3487: // }
3488: //
3489: // return null;
3490: // }
3491:
3492: private static void processDefaultDecorationAction(final CssBox box) {
3493: Decoration decoration = box.getDecoration();
3494: if (decoration == null) {
3495: return;
3496: }
3497:
3498: Action defaultAction = decoration.getDefaultAction();
3499: final Action action;
3500: if (defaultAction instanceof ContextAwareAction) {
3501: action = ((ContextAwareAction) defaultAction)
3502: .createContextAwareInstance(decoration.getContext());
3503: } else {
3504: action = defaultAction;
3505: }
3506:
3507: if (action != null) {
3508: EventQueue.invokeLater(new Runnable() {
3509: public void run() {
3510: action.actionPerformed(new ActionEvent(box, -1,
3511: null));
3512: }
3513: });
3514: }
3515: }
3516:
3517: private void showDecorationPopupMenu(final CssBox box,
3518: Component component, int x, int y) {
3519: Decoration decoration = box.getDecoration();
3520: if (decoration == null) {
3521: return;
3522: }
3523:
3524: Action[] actions = decoration.getActions();
3525: if (actions.length == 0) {
3526: return;
3527: }
3528:
3529: // JPopupMenu popup = Utilities.actionsToPopup(actions, decoration.getContext());
3530: //
3531: // // XXX Move somehow to the associated top component?
3532: //// popup.show(webform.getTopComponent(), x, y);
3533: // webform.tcShowPopupMenu(popup, x, y);
3534: webform
3535: .fireUserPopupActionPerformed(new DefaultDesignerPopupEvent(
3536: webform, component, actions, decoration
3537: .getContext(), x, y));
3538: }
3539:
3540: static class DefaultDesignerPopupEvent implements
3541: DesignerPopupEvent {
3542: private final Designer designer;
3543: private final Component component;
3544: private final Action[] actions;
3545: private final Lookup context;
3546: private final int x;
3547: private final int y;
3548:
3549: public DefaultDesignerPopupEvent(Designer designer,
3550: Component component, Action[] actions, Lookup context,
3551: int x, int y) {
3552: this .designer = designer;
3553: this .component = component;
3554: this .actions = actions;
3555: this .context = context;
3556: this .x = x;
3557: this .y = y;
3558: }
3559:
3560: public Component getComponent() {
3561: return component;
3562: }
3563:
3564: public Action[] getActions() {
3565: return actions;
3566: }
3567:
3568: public Lookup getContext() {
3569: return context;
3570: }
3571:
3572: public Designer getDesigner() {
3573: return designer;
3574: }
3575:
3576: public Box getBox() {
3577: return null;
3578: }
3579:
3580: public int getX() {
3581: return x;
3582: }
3583:
3584: public int getY() {
3585: return y;
3586: }
3587:
3588: } // End of DefaultDesignerPopupEvent.
3589:
3590: /** Put the designer in inline-editing mode for the first
3591: * eligible component in the inserted set of beans */
3592: // void inlineEdit(final List beans) {
3593: void inlineEdit(final Element[] componentRootElements) {
3594: SwingUtilities.invokeLater(new Runnable() {
3595: public void run() {
3596: // int n = beans.size();
3597: // for (int i = 0; i < n; i++) {
3598: // DesignBean lb = (DesignBean)beans.get(i);
3599: for (Element componentRootElement : componentRootElements) {
3600: // if (!(lb instanceof MarkupDesignBean)) {
3601: // continue;
3602: // }
3603: if (componentRootElement == null) {
3604: continue;
3605: }
3606:
3607: boolean editing =
3608: // startInlineEditing((MarkupDesignBean)lb, null,
3609: startInlineEditing(componentRootElement, null,
3610: null, false, true, null, true);
3611:
3612: if (editing) {
3613: return;
3614: }
3615:
3616: // See if any of the first level children are willing to inline edit as well
3617: // For example, for a hyperlink or a commandlink, we want the child output text
3618: // to be inline edited. For a TabSet we want the Tab to be edited.
3619: // We could consider searching recursively here but that's probably overkill.
3620: // for (int j = 0, m = lb.getChildBeanCount(); j < m; j++) {
3621: // DesignBean lbc = lb.getChildBean(j);
3622: Element[] children = webform
3623: .getDomProviderService()
3624: .getChildComponents(componentRootElement);
3625: for (Element child : children) {
3626:
3627: // if (lbc instanceof MarkupDesignBean) {
3628: // MarkupDesignBean mlbc = (MarkupDesignBean)lbc;
3629: if (child != null) {
3630:
3631: // editing =
3632: // startInlineEditing(mlbc, null, null,
3633: // false, true, null, true);
3634: editing = startInlineEditing(child, null,
3635: null, false, true, null, true);
3636: if (editing) {
3637: return;
3638: }
3639: }
3640: }
3641: }
3642: }
3643: });
3644: }
3645:
3646: // private static void paintVirtualForms(WebForm webform, Graphics2D g) {
3647: // VirtualFormRenderer virtualFormRenderer = (VirtualFormRenderer)Lookup.getDefault().lookup(VirtualFormRenderer.class);
3648: // if (virtualFormRenderer == null) {
3649: // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
3650: // new NullPointerException("No VirtualFormRenderer is available!")); // NOI18N
3651: // } else {
3652: // virtualFormRenderer.paintVirtualForms(g, new RenderContextImpl(webform));
3653: // }
3654: // }
3655:
3656: // private static class RenderContextImpl implements /*VirtualFormRenderer*/DomProvider.RenderContext {
3657: // private final WebForm webForm;
3658: //
3659: // public RenderContextImpl(WebForm webForm) {
3660: // this.webForm = webForm;
3661: // }
3662: //
3663: //// public DesignContext getDesignContext() {
3664: //// return webForm.getModel().getLiveUnit();
3665: //// }
3666: //// public DesignBean[] getBeansOfType(Class clazz) {
3667: //// return webForm.getBeansOfType(clazz);
3668: //// }
3669: //
3670: //// public Project getProject() {
3671: //// return webForm.getProject();
3672: //// }
3673: //
3674: // public Dimension getVieportDimension() {
3675: // return webForm.getPane().getPageBox().getViewport().getExtentSize();
3676: // }
3677: //
3678: // public Point getViewportPosition() {
3679: // return webForm.getPane().getPageBox().getViewport().getViewPosition();
3680: // }
3681: //
3682: // public int getNonTabbedTextWidth(char[] s, int offset, int length, FontMetrics metrics) {
3683: // return DesignerUtils.getNonTabbedTextWidth(s, offset, length, metrics);
3684: // }
3685: //
3686: // public Rectangle getBoundsForComponent(Element componentRootElement) {
3687: // if (componentRootElement != null) {
3688: // return ModelViewMapper.getComponentBounds(webForm.getPane().getPageBox(), componentRootElement);
3689: // } else {
3690: // return null;
3691: // }
3692: // }
3693: // } // End of RenderContextImpl.
3694:
3695: // XXX Moved from Document.
3696: /**
3697: * Report whether the given node is in a read-only region of
3698: * the document or not.
3699: */
3700: // static boolean isReadOnlyRegion(Position pos) {
3701: static boolean isReadOnlyRegion(DomPosition pos) {
3702: org.w3c.dom.Node node = pos.getNode();
3703:
3704: // XXX FIXME Determine if this node is in a DocumentFragment which means
3705: // it's read only
3706: while (node != null) {
3707: node = node.getParentNode();
3708:
3709: if (node instanceof org.w3c.dom.Document) {
3710: break;
3711: }
3712: }
3713:
3714: return node == null;
3715: }
3716:
3717: private static TopComponent findCommonPaletteWindow() {
3718: return findTopComponentOfId("CommonPalette"); // NOI18N
3719: }
3720:
3721: // private static TopComponent findRuntimeWindow() {
3722: // return findTopComponentOfId("runtime"); // NOI18N
3723: // }
3724:
3725: private static TopComponent findTopComponentOfId(String id) {
3726: TopComponent tc = WindowManager.getDefault().findTopComponent(
3727: id);
3728: if (tc == null) {
3729: // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
3730: // new NullPointerException("TopComponent of id=" + id + " not found!")); // NOI18N
3731: info(new NullPointerException("TopComponent of id=" + id
3732: + " not found!")); // NOI18N
3733:
3734: return null;
3735: }
3736: return tc;
3737: }
3738:
3739: private static Transferable getTransferableFromCommonPalette(
3740: WebForm webForm) {
3741: Lookup paletteItem = webForm.getPaletteController()
3742: .getSelectedItem();
3743: if (paletteItem == null) {
3744: return null;
3745: }
3746:
3747: Node node = (Node) paletteItem.lookup(Node.class);
3748: if (node == null) {
3749: return null;
3750: }
3751: try {
3752: return node.clipboardCopy();
3753: } catch (IOException ex) {
3754: // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
3755: info(ex);
3756: }
3757: return null;
3758: }
3759:
3760: private static Transferable getTransferableFromExplorer(
3761: TopComponent tc) {
3762: if (tc instanceof ExplorerManager.Provider) {
3763: ExplorerManager.Provider explorerManagerProvider = (ExplorerManager.Provider) tc;
3764: Node[] selectedNodes = explorerManagerProvider
3765: .getExplorerManager().getSelectedNodes();
3766: if (selectedNodes != null && selectedNodes.length == 1) {
3767: // XXX Only when one item selected?
3768: Node node = selectedNodes[0];
3769: if (node != null) {
3770: try {
3771: return node.clipboardCopy();
3772: } catch (IOException ex) {
3773: // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
3774: info(ex);
3775: }
3776: }
3777: }
3778: }
3779: return null;
3780: }
3781:
3782: /** XXX #6245208 Flag saying whether to ignore CnC because of progressing DnD. */
3783: private boolean ignoreCnC;
3784:
3785: void setIgnoreCnC(boolean ignore) {
3786: ignoreCnC = ignore;
3787: }
3788:
3789: private boolean isIgnoreCnC() {
3790: return ignoreCnC;
3791: }
3792:
3793: // XXX Moved from designer/jsf/../AbstractJsfTopComponent.
3794: /**
3795: * This method returns the position at which a component should be
3796: * pasted.
3797: * <p>
3798: * This implementation returns the current position of the mouse cursor.
3799: * If the cursor is outside the visual editor or hasn't moved
3800: * since the last time this method was invoked, this method will
3801: * return a position one grid box below and to the right of the
3802: * currently selected component. If no component is selected, this method
3803: * returns <code>null</code>.
3804: *
3805: * @return the point at which to paste a component or <code>null</code> if
3806: * there is no valid paste position
3807: */
3808: public/*protected*/Point getPastePoint() {
3809: // Point p = webform.getManager().getMouseHandler().getCurrentPos();
3810: // Point p = designer.getCurrentPos();
3811: Point p = getMouseHandler().getCurrentPos();
3812:
3813: if (p != null) {
3814: // Ensure that if user pastes multiple times without moving
3815: // the mouse, we don't reuse the mouse position but switch
3816: // to an offset from selection instead
3817: Point location = new Point(p);
3818: // webform.getManager().getMouseHandler().clearCurrentPos();
3819: // designer.clearCurrentPos();
3820: getMouseHandler().clearCurrentPos();
3821:
3822: return location;
3823: } else {
3824: // Element e = webform.getSelection().getPositionElement();
3825: // Element e = designer.getPositionElement();
3826: Element e = webform.getSelection().getPositionElement();
3827:
3828: if (e == null) {
3829: return null;
3830: }
3831:
3832: // int top = CssLookup.getLength(e, XhtmlCss.TOP_INDEX);
3833: // int left = CssLookup.getLength(e, XhtmlCss.LEFT_INDEX);
3834: int top = CssProvider.getValueService().getCssLength(e,
3835: XhtmlCss.TOP_INDEX);
3836: int left = CssProvider.getValueService().getCssLength(e,
3837: XhtmlCss.LEFT_INDEX);
3838:
3839: if ((top != CssValue.AUTO) || (left != CssValue.AUTO)) {
3840: if (left == CssValue.AUTO) {
3841: left = 0;
3842: }
3843:
3844: if (top == CssValue.AUTO) {
3845: top = 0;
3846: }
3847:
3848: // GridHandler gh = GridHandler.getInstance();
3849: // GridHandler gh = webform.getGridHandler();
3850: // return new Point(left + gh.getGridWidth(), top + gh.getGridHeight());
3851: // int gridWidth = designer.getGridWidth();
3852: // int gridHeight = designer.getGridHeight();
3853: // GridHandler gh = GridHandler.getDefault();
3854: // int gridWidth = gh.getGridWidth();
3855: // int gridHeight = gh.getGridHeight();
3856: int gridWidth = webform.getGridWidth();
3857: int gridHeight = webform.getGridHeight();
3858: return new Point(left + gridWidth, top + gridHeight);
3859: }
3860:
3861: return null;
3862: }
3863: }
3864:
3865: private static Logger getLogger() {
3866: return Logger.getLogger(InteractionManager.class.getName());
3867: }
3868:
3869: private static void fine(Exception ex) {
3870: getLogger().log(Level.FINE, null, ex);
3871: }
3872:
3873: private static void info(Exception ex) {
3874: getLogger().log(Level.INFO, null, ex);
3875: }
3876:
3877: private static void info(String message) {
3878: getLogger().info(message);
3879: }
3880: }
|