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.awt.Font;
0044: import java.awt.FontMetrics;
0045: import java.awt.Rectangle;
0046: import java.awt.Toolkit;
0047: import javax.swing.SwingUtilities;
0048:
0049: import org.openide.ErrorManager;
0050: import org.openide.windows.TopComponent;
0051:
0052: // For CVS archaeology: This file used to be called com.sun.rave.css2.Utillities
0053:
0054: /**
0055: * Miscellaneous utilities for the designer
0056: *
0057: * @author Tor Norbye
0058: */
0059: public class DesignerUtils {
0060:
0061: /** Debugging flag. */
0062: static final boolean DEBUG = ErrorManager.getDefault().getInstance(
0063: DesignerUtils.class.getName()).isLoggable(
0064: ErrorManager.INFORMATIONAL);
0065:
0066: // XXX Moved into insync/DesignBeanNodeHelper.
0067: // static char[] hexdigits =
0068: // { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
0069:
0070: // XXX Moved to designer/jsf/../DesignerServiceHackImpl.
0071: // // Same as style set in Text renderer and in default style sheet
0072: // private static final String ignoreClass = "rave-uninitialized-text"; // NOI18N
0073:
0074: // /** Return true if the extension indicates that this is an image */
0075: // public static boolean isImage(String extension) {
0076: // return (extension.equalsIgnoreCase("jpg") || // NOI18N
0077: // extension.equalsIgnoreCase("gif") || // NOI18N
0078: // extension.equalsIgnoreCase("png") || // NOI18N
0079: // extension.equalsIgnoreCase("jpeg")); // NOI18N
0080: // }
0081:
0082: // public static boolean isStylesheet(String extension) {
0083: // return extension.equalsIgnoreCase("css"); // NOI18N
0084: // }
0085:
0086: // /** Return the relative path of the given GenericItem to the page folder */
0087: // public static String getPageRelativePath(WebForm webform, FileObject fo) {
0088: // FileObject webroot;
0089: // webroot = JSFProjectUtil.getDocumentRoot(webform.getProject());
0090: //
0091: // String rootName = webroot.getPath();
0092: // String fileName = fo.getPath();
0093: //
0094: // if (fileName.startsWith(rootName)) {
0095: // return fileName.substring(rootName.length());
0096: // }
0097: //
0098: // return null;
0099: // }
0100:
0101: // XXX Moved to FormComponentBox.
0102: // /**
0103: // * Add all the text content you can find under the given node into
0104: // * the given StringBuffer.
0105: // */
0106: // public static void addNodeText(StringBuffer sb, Node n, boolean skipSpace) {
0107: // int type = n.getNodeType();
0108: //
0109: // if (type == Node.TEXT_NODE) {
0110: // if (skipSpace && onlyWhitespace(n.getNodeValue())) {
0111: // return;
0112: // }
0113: //
0114: // sb.append(n.getNodeValue());
0115: // } else if (type == Node.COMMENT_NODE) {
0116: // String comment = n.getNodeValue();
0117: // int newline = comment.indexOf('\n');
0118: //
0119: // if (newline != -1) {
0120: // sb.append(comment.substring(newline + 1));
0121: // }
0122: // } else if (type == Node.CDATA_SECTION_NODE) {
0123: // if (skipSpace && onlyWhitespace(n.getNodeValue())) {
0124: // return;
0125: // }
0126: //
0127: // sb.append(n.getNodeValue());
0128: // } else {
0129: // NodeList children = n.getChildNodes();
0130: //
0131: // for (int i = 0; i < children.getLength(); i++) {
0132: // addNodeText(sb, children.item(i), skipSpace);
0133: // }
0134: // }
0135: // }
0136:
0137: // This function is used by the experimental designer JavaScript support
0138:
0139: /** Return the literal string in the given node. If comments are encountered, everything on the
0140: * first line is ignored, then the rest is included. This matches browser behavior where
0141: * for example
0142: * <pre>
0143: * <script><-- Here's some javascript code:<br/>
0144: * alert('hello world');
0145: * </script>
0146: * </pre>
0147: * is going to add the text "alert('hello world')" only.
0148: */
0149:
0150: //static void addScriptNodeText(StringBuffer sb, Node n) {
0151: // int type = n.getNodeType();
0152: //
0153: // if (type == Node.TEXT_NODE) {
0154: // sb.append(n.getNodeValue());
0155: // } else if (type == Node.COMMENT_NODE) {
0156: // String comment = n.getNodeValue();
0157: // int newline = comment.indexOf('\n');
0158: //
0159: // if (newline != -1) {
0160: // sb.append(comment.substring(newline + 1));
0161: // }
0162: // } else if (type == Node.ELEMENT_NODE) {
0163: // // TODO - insetead of formatting, simply pull attributes out directly
0164: // sb.append(FacesSupport.getHtmlStream((Element)n));
0165: // } else if (type == Node.CDATA_SECTION_NODE) {
0166: // sb.append(n.getNodeValue());
0167: // } else if ((type == Node.DOCUMENT_FRAGMENT_NODE) && (n.getChildNodes().getLength() == 1) &&
0168: // ((n.getChildNodes().item(0).getNodeType() == Node.TEXT_NODE) ||
0169: // (n.getChildNodes().item(0).getNodeType() == Node.COMMENT_NODE) ||
0170: // (n.getChildNodes().item(0).getNodeType() == Node.CDATA_SECTION_NODE))) {
0171: // sb.append(n.getChildNodes().item(0).getNodeValue());
0172: // }
0173: //}
0174: /** XXX Copy also in insync/FacesDnDSupport.
0175: * Return true iff the string contains only whitespace */
0176: public static boolean onlyWhitespace(String s) {
0177: if (DEBUG) {
0178: debugLog(DesignerUtils.class.getName()
0179: + ".onlyWhitespace(String)");
0180: }
0181: if (s == null) {
0182: return true;
0183: }
0184: int n = s.length();
0185:
0186: for (int i = 0; i < n; i++) {
0187: char c = s.charAt(i);
0188:
0189: /* See the "empty-cells" documentation in CSS2.1 for example:
0190: * it sounds like only SOME of the whitespace characters are
0191: * truly considered ignorable whitespace: \r, \n, \t, and space.
0192: * So do something more clever in some of these cases.
0193: */
0194: if (!Character.isWhitespace(c)) {
0195: return false;
0196: }
0197: }
0198:
0199: return true;
0200: }
0201:
0202: // XXX Copied into insync/DesignBeanNodeHelper.
0203: // public static String colorToHex(Color c) {
0204: // if (c == null) {
0205: // return null;
0206: // }
0207: //
0208: // int r = c.getRed();
0209: // int g = c.getGreen();
0210: // int b = c.getBlue();
0211: //
0212: // return "#" + hexdigits[(r & 0xF0) >> 4] + hexdigits[r & 0x0F] + hexdigits[(g & 0xF0) >> 4] +
0213: // hexdigits[g & 0x0F] + hexdigits[(b & 0xF0) >> 4] + hexdigits[b & 0x0F];
0214: // }
0215:
0216: // public static String colorToRgb(Color c) {
0217: // if (c == null) {
0218: // return null;
0219: // }
0220: //
0221: // int r = c.getRed();
0222: // int g = c.getGreen();
0223: // int b = c.getBlue();
0224: //
0225: // return "rgb(" + r + "," + g + "," + b + ")";
0226: // }
0227:
0228: // XXX Moved to TextBox.
0229: // /**
0230: // * Unlike the methods in javax.swing.text I'm returning the text offset itself, not the distance
0231: // * from the passed in segment/string offset
0232: // */
0233: // public static final int getNonTabbedTextOffset(char[] s, int txtOffset, int len,
0234: // FontMetrics metrics, int x0, int x) {
0235: // if (x0 >= x) {
0236: // // x before x0, return.
0237: // return txtOffset;
0238: // }
0239: //
0240: // int currX = x0;
0241: // int nextX = currX;
0242: //
0243: // // s may be a shared segment, so it is copied prior to calling
0244: // // the tab expander
0245: // int n = txtOffset + len;
0246: // final boolean round = true;
0247: //
0248: // for (int i = txtOffset; i < n; i++) {
0249: // char c = s[i];
0250: //
0251: // // TODO if there are successive spaces, ignore them
0252: // // TODO count a newline as a space!
0253: // if ((c == '\t') || (c == '\n')) {
0254: // nextX += metrics.charWidth(' ');
0255: // } else {
0256: // nextX += metrics.charWidth(c);
0257: // }
0258: //
0259: // if ((x >= currX) && (x < nextX)) {
0260: // // found the hit position... return the appropriate side
0261: // if ((round == false) || ((x - currX) < (nextX - x))) {
0262: // return i;
0263: // } else {
0264: // return i + 1;
0265: // }
0266: // }
0267: //
0268: // currX = nextX;
0269: // }
0270: //
0271: // return txtOffset;
0272: // }
0273:
0274: /** Based on similar routine in javax.swing.text.Utilities */
0275: public static final int getNonTabbedTextWidth(char[] s,
0276: int beginOffset, int endOffset, FontMetrics metrics) {
0277: int nextX = 0;
0278:
0279: for (int i = beginOffset; i < endOffset; i++) {
0280: char c = s[i];
0281:
0282: if ((c == '\t') || (c == '\n')) {
0283: nextX += metrics.charWidth(' ');
0284: } else {
0285: nextX += metrics.charWidth(c);
0286: }
0287:
0288: // Ignore newlines, they take up space and we shouldn't be
0289: // counting them.
0290: }
0291:
0292: return nextX;
0293: }
0294:
0295: // XXX Moved to DomInspector.
0296: // /**
0297: // * Get the name of the given bean, e.g. "button1", "textField5", etc.
0298: // *
0299: // * @return the name of the bean, or null if a bean can not be found for this view's element
0300: // */
0301: // public static String getBeanName(DesignBean bean) {
0302: // if (bean != null) {
0303: // return "<" + bean.getInstanceName() + ">";
0304: // }
0305: //
0306: // return null;
0307: // }
0308: //
0309: // /**
0310: // * If the element corresponds to a bean, return the bean name.
0311: // *
0312: // * @return the name of the bean, or null if a bean can not be found for this element
0313: // */
0314: // public static String getBeanName(Element element) {
0315: //// DesignBean bean = FacesSupport.getDesignBean(element);
0316: // DesignBean bean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(element);
0317: //
0318: // if (bean != null) {
0319: // return getBeanName(bean);
0320: // } else {
0321: // return null;
0322: // }
0323: // }
0324:
0325: // XXX Moved to SelectionManager.
0326: // /** Locate the JTable within the property sheet in the IDE.
0327: // * WARNING: Implementation hacks!
0328: // * @param focus If set, focus the top component
0329: // * @param visible If set, ensure the top component is fronted
0330: // */
0331: // public static JTable findPropSheetTable(boolean focus, boolean visible) {
0332: // WindowManager mgr = WindowManager.getDefault();
0333: // TopComponent properties = mgr.findTopComponent("properties"); // NOI18N
0334: //
0335: // if ((properties != null) && (visible || properties.isShowing())) {
0336: // if (focus) {
0337: // properties.requestActive();
0338: // }
0339: //
0340: // if (visible) {
0341: // properties.requestVisible();
0342: // }
0343: //
0344: // return findTable(properties);
0345: // }
0346: //
0347: // return null;
0348: // }
0349: //
0350: // /** Fish the given Container hierarchy for a JTable */
0351: // private static JTable findTable(Container c) {
0352: // if(DEBUG) {
0353: // debugLog(DesignerUtils.class.getName() + ".findTable(Container)");
0354: // }
0355: // if(c == null) {
0356: // return(null);
0357: // }
0358: // if (c instanceof JTable) {
0359: // return (JTable)c;
0360: // }
0361: //
0362: // int n = c.getComponentCount();
0363: //
0364: // for (int i = 0; i < n; i++) {
0365: // Component comp = c.getComponent(i);
0366: //
0367: // if (comp instanceof JTable) {
0368: // return (JTable)comp;
0369: // }
0370: //
0371: // if (comp instanceof Container) {
0372: // JTable table = findTable((Container)comp);
0373: //
0374: // if (table != null) {
0375: // return table;
0376: // }
0377: // }
0378: // }
0379: //
0380: // return null;
0381: // }
0382:
0383: // XXX Moved to SelectionManager.
0384: // /** Find the first TextNode child under this element, or null
0385: // * if no such node is found.
0386: // * @todo How do we avoid returning for example the blank
0387: // * textnode between <table> and <tr> in a table? I want
0388: // * the <td> !
0389: // */
0390: // public static Node findFirstTextChild(Node node) {
0391: // if(DEBUG) {
0392: // debugLog(DesignerUtils.class.getName() + ".findFirstTextChild(Node)");
0393: // }
0394: // if(node == null) {
0395: // return(null);
0396: // }
0397: // if ((node.getNodeType() == Node.TEXT_NODE) ||
0398: // (node.getNodeType() == Node.CDATA_SECTION_NODE)) {
0399: // return node;
0400: // }
0401: //
0402: // NodeList nl = node.getChildNodes();
0403: //
0404: // for (int i = 0, n = nl.getLength(); i < n; i++) {
0405: // Node result = findFirstTextChild(nl.item(i));
0406: //
0407: // if (result != null) {
0408: // return result;
0409: // }
0410: // }
0411: //
0412: // return null;
0413: // }
0414:
0415: // XXX Moved to Document.
0416: // /** For the given node, locate a parent list item element, or return
0417: // * null if no such parent is found.
0418: // */
0419: // public static Element getListItemParent(Node node) {
0420: // while (node != null) {
0421: // if (node.getNodeType() == Node.ELEMENT_NODE) {
0422: // Element element = (Element)node;
0423: //
0424: // if (element.getTagName().equals(HtmlTag.LI.name)) {
0425: // return element;
0426: // }
0427: // }
0428: //
0429: // node = node.getParentNode();
0430: // }
0431: //
0432: // return null;
0433: // }
0434:
0435: // XXX Moved to ModelViewMapper.
0436: // /**
0437: // * Given a position in the DOM, find the closest valid position.
0438: // * In particular, the position is not allowed to be inside any
0439: // * "renders children" nodes. It also doesn't allow positions
0440: // * that are "adjacent" (before, after) an absolutely positioned
0441: // * element.
0442: // *
0443: // * @param pos Position to be checked
0444: // * @param adjust If true, adjust the position to the nearest (above)
0445: // * position that is valid.
0446: // * @param inline inlineEditor which is in the game in the designer or null.
0447: // * @todo This method is mostly used to determine if a position is a valid
0448: // * caret position now. Perhaps rename it to that (isValidCaretPosition).
0449: // * @param dom The JSPX document DOM
0450: // */
0451: // public static Position checkPosition(Position pos, boolean adjust, /*WebForm webform*/InlineEditor inline) {
0452: // if(DEBUG) {
0453: // debugLog(DesignerUtils.class.getName() + ".checkPosition(Position, boolean, WebForm)");
0454: // }
0455: //// if(pos == null || webform == null) {
0456: // if (pos == null) {
0457: // return null;
0458: // }
0459: // if (pos == Position.NONE) {
0460: // return pos;
0461: // }
0462: //
0463: // Node node = pos.getNode();
0464: //
0465: // if (!adjust) {
0466: //// InlineEditor inline = webform.getManager().getInlineEditor();
0467: //
0468: // if (inline != null) {
0469: // if (inline.checkPosition(pos)) {
0470: // return pos;
0471: // } else {
0472: // return Position.NONE;
0473: // }
0474: // }
0475: // }
0476: //
0477: // // Don't accept positions adjacent to an absolutely or relatively positioned container
0478: // if (!adjust) {
0479: //// RaveElement target = pos.getTargetElement();
0480: //// if ((target != null) && target.isRendered()) {
0481: // Element target = pos.getTargetElement();
0482: // if (MarkupService.isRenderedNode(target)) {
0483: //// Value val = CssLookup.getValue(target, XhtmlCss.POSITION_INDEX);
0484: // CssValue cssValue = CssProvider.getEngineService().getComputedValueForElement(target, XhtmlCss.POSITION_INDEX);
0485: //
0486: //// if ((val == CssValueConstants.ABSOLUTE_VALUE) ||
0487: //// (val == CssValueConstants.RELATIVE_VALUE) ||
0488: //// (val == CssValueConstants.FIXED_VALUE)) {
0489: // if (CssProvider.getValueService().isAbsoluteValue(cssValue)
0490: // || CssProvider.getValueService().isRelativeValue(cssValue)
0491: // || CssProvider.getValueService().isFixedValue(cssValue)) {
0492: // return Position.NONE;
0493: // }
0494: // }
0495: // }
0496: //
0497: // while (node != null) {
0498: //// if (node instanceof RaveRenderNode) {
0499: //// RaveRenderNode rn = (RaveRenderNode)node;
0500: //// if (rn.isRendered() && (rn.getSourceNode() == null)) {
0501: // if (MarkupService.isRenderedNode(node) && MarkupService.getSourceNodeForNode(node) == null) {
0502: // if (adjust) {
0503: // Node curr = node;
0504: //
0505: // while (curr != null) {
0506: // if (curr.getNodeType() == Node.ELEMENT_NODE) {
0507: //// RaveElement e = (RaveElement)curr;
0508: // Element e = (Element)curr;
0509: //
0510: //// if (e.getSource() != null) {
0511: // if (MarkupService.getSourceElementForElement(e) != null) {
0512: //// MarkupDesignBean bean = e.getDesignBean();
0513: //// MarkupDesignBean bean = InSyncService.getProvider().getMarkupDesignBeanForElement(e);
0514: // MarkupDesignBean bean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(e);
0515: //
0516: // if (bean != null) {
0517: // bean = /*FacesSupport.*/findRendersChildren(bean);
0518: //// e = (RaveElement)bean.getElement();
0519: // e = bean.getElement();
0520: // }
0521: //
0522: // return Position.create(e, pos.getOffset() > 0);
0523: // }
0524: // }
0525: //
0526: // curr = curr.getParentNode();
0527: //
0528: // if (curr == null) {
0529: // return Position.NONE;
0530: // }
0531: // }
0532: // } else {
0533: // return Position.NONE;
0534: // }
0535: //// }
0536: // }
0537: //
0538: //// if (node instanceof RaveElement) {
0539: //// RaveElement element = (RaveElement)node;
0540: // if (node instanceof Element) {
0541: // Element element = (Element)node;
0542: //
0543: //// if (element.getDesignBean() != null) {
0544: //// MarkupDesignBean bean = element.getDesignBean();
0545: //// MarkupDesignBean bean = InSyncService.getProvider().getMarkupDesignBeanForElement(element);
0546: // MarkupDesignBean bean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(element);
0547: //
0548: // if (bean != null) {
0549: // MarkupDesignBean parent = /*FacesSupport.*/findRendersChildren(bean);
0550: //
0551: // // XXX what if bean itself is a renders children?
0552: // if (parent != bean) {
0553: // if (adjust) {
0554: // // There was a renders-children parent we
0555: // // should skip
0556: // Element parentElement = parent.getElement();
0557: //
0558: // return Position.create(parentElement, pos.getOffset() > 0);
0559: // } else {
0560: // return Position.NONE;
0561: // }
0562: // }
0563: //
0564: // break;
0565: // }
0566: // }
0567: //
0568: // node = node.getParentNode();
0569: // }
0570: //
0571: //// InlineEditor inline = webform.getManager().getInlineEditor();
0572: //
0573: // if (((pos != Position.NONE) && ((inline != null) && inline.checkPosition(pos))) ||
0574: //// !pos.isRendered()) {
0575: // !MarkupService.isRenderedNode(pos.getNode())) {
0576: // return pos;
0577: // } else if (adjust) {
0578: // // Try to find the corresponding source
0579: // node = pos.getNode();
0580: //
0581: // while (node != null) {
0582: //// if (node instanceof RaveElement) {
0583: //// RaveElement element = (RaveElement)node;
0584: // if (node instanceof Element) {
0585: // Element element = (Element)node;
0586: //
0587: //// if (element.getDesignBean() != null) {
0588: //// DesignBean bean = element.getDesignBean();
0589: //// DesignBean bean = InSyncService.getProvider().getMarkupDesignBeanForElement(element);
0590: // DesignBean bean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(element);
0591: // if (bean != null) {
0592: // Element el = FacesSupport.getElement(bean);
0593: //
0594: // return Position.create(el, pos.getOffset() > 0);
0595: // }
0596: // }
0597: //
0598: // node = node.getParentNode();
0599: // }
0600: //
0601: // return Position.NONE;
0602: // } else {
0603: // // // XXX shouldn't this be return pos; ? Try to click somewhere in BoxModelTest
0604: // // // layout-floats3.html
0605: // // return Position.NONE;
0606: // // }
0607: // return pos;
0608: // }
0609: // }
0610: //
0611: // // XXX Moved from FacesSupport.
0612: // /** Find outermost renders-children bean above the given bean, or
0613: // * the bean itself if there is no such parent.
0614: // */
0615: // private /*public*/ static MarkupDesignBean findRendersChildren(MarkupDesignBean bean) {
0616: // // Similar to FacesSupport.findHtmlContainer(bean), but
0617: // // we need to return the outermost html container itself, not
0618: // // the parent, since we're not looking for its container but
0619: // // the bean to be moved itself.
0620: // MarkupDesignBean curr = bean;
0621: //
0622: //// for (; curr != null; curr = FacesSupport.getBeanParent(curr)) {
0623: // for (; curr != null; curr = getBeanParent(curr)) {
0624: // if (curr.getInstance() instanceof F_Verbatim) {
0625: // // If you have a verbatim, we're okay to add html comps below it
0626: // return bean;
0627: // }
0628: //
0629: // if (curr.getInstance() instanceof UIComponent) {
0630: // // Need to set the Thread's context classloader to be the Project's ClassLoader.
0631: // ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
0632: // try {
0633: //// Thread.currentThread().setContextClassLoader(InSyncService.getProvider().getContextClassLoader(curr));
0634: // Thread.currentThread().setContextClassLoader(WebForm.getDomProviderService().getContextClassLoaderForDesignContext(curr.getDesignContext()));
0635: // if (((UIComponent)curr.getInstance()).getRendersChildren()) {
0636: // bean = curr;
0637: // // Can't break here - there could be an outer
0638: // // renders-children parent
0639: // }
0640: // } finally {
0641: // Thread.currentThread().setContextClassLoader(oldContextClassLoader);
0642: // }
0643: // }
0644: // }
0645: //
0646: // return bean;
0647: // }
0648: //
0649: // // XXX Moved from FacesSupport.
0650: // /**
0651: // * Return the parent of the given markup design bean, if the parent is
0652: // * a MarkupDesignBean.
0653: // */
0654: // private static MarkupDesignBean getBeanParent(MarkupDesignBean bean) {
0655: // DesignBean parent = bean.getBeanParent();
0656: //
0657: // if (parent instanceof MarkupDesignBean) {
0658: // return (MarkupDesignBean)parent;
0659: // }
0660: //
0661: // return null;
0662: // }
0663:
0664: // /** Add item to a popup menu or a menu. Only one of the fields
0665: // * should be non null. */
0666: // public static void addMenuItem(JPopupMenu popup, JMenu menu, JMenuItem item) {
0667: // if(DEBUG) {
0668: // debugLog(DesignerUtils.class.getName() + ".addMenuItem(JPopupMenu, JMenu, JMenuItem)");
0669: // }
0670: // if(item == null) {
0671: // throw(new IllegalArgumentException("Null menu item"));
0672: // }
0673: // if (menu != null) {
0674: // menu.add(item);
0675: // } else {
0676: // if(popup != null) {
0677: // popup.add(item);
0678: // } else {
0679: // throw(new IllegalArgumentException("Both menu and popup are null."));// NOI18N
0680: // }
0681: // }
0682: // }
0683: //
0684: // /** Add a separator a popup menu or a menu - unless the previous item
0685: // * was a popup! Only one of the fields should be non null. */
0686: // public static void addSeparator(JPopupMenu popup, JMenu menu) {
0687: // if (menu != null) {
0688: // // Make sure previous item wasn't a separator
0689: // int n = menu.getItemCount();
0690: //
0691: // if ((n > 0) && (menu.getMenuComponent(n - 1) instanceof JSeparator)) {
0692: // return;
0693: // }
0694: //
0695: // menu.addSeparator();
0696: // } else {
0697: // if(popup != null) {
0698: // int n = popup.getComponentCount();
0699: //
0700: // if ((n > 0) && (popup.getComponent(n - 1) instanceof JSeparator)) {
0701: // return;
0702: // }
0703: //
0704: // popup.addSeparator();
0705: // } else {
0706: // throw(new IllegalArgumentException("Both menu and popup are null."));// NOI18N
0707: // }
0708: // }
0709: // }
0710: //
0711: // /** Add menu items to the iven popup menu for the given DesignBean.
0712: // * @param bean The DesignBean whose context menu items plus customizer action
0713: // * @param menu The popup menu to add items to
0714: // * @param showAncestors If true, include context menu items in parents of the given bean.
0715: // * These will be pullright menus whose menu name is the bean name of the ancestor.
0716: // * @param webform May be null, but can also point to a webform for this bean. This is used
0717: // * to do batch processing on the element when a live customizer is run on the bean.
0718: // * @param mouseElement May be null, but can also point to a node in
0719: // * the render tree which has been marked up with a MarkupMouseRegion.
0720: // * which could contribute menu items.
0721: // * */
0722: // public static void addMenuItems(final DesignBean bean, JPopupMenu menu,
0723: // org.openide.nodes.Node[] nodes, JComponent parent, boolean showAncestors,
0724: // final WebForm webform, Element mouseElement, JComponent addItem) {
0725: // if(DEBUG) {
0726: // debugLog(DesignerUtils.class.getName() + ".addMenuItems(DesignBean, JPopupMenu, Node[], JComponent, boolean, WebForm, Element, JComponent");
0727: // }
0728: // if(bean == null) {
0729: // throw(new IllegalArgumentException("Null menu."));// NOI18N
0730: // }
0731: // if(parent == null) {
0732: // throw(new IllegalArgumentException("Null parent component."));// NOI18N
0733: // }
0734: // while (mouseElement != null) {
0735: //// if (mouseElement.getMarkupMouseRegion() != null) {
0736: //// MarkupMouseRegion region = mouseElement.getMarkupMouseRegion();
0737: // MarkupMouseRegion region = InSyncService.getProvider().getMarkupMouseRegionForElement(mouseElement);
0738: // if (region != null) {
0739: // DisplayAction[] context = region.getContextItems();
0740: //
0741: // if ((context != null) && (context.length > 0)) {
0742: // buildMenu(menu, null, context, webform);
0743: // DesignerUtils.addSeparator(menu, null);
0744: // }
0745: // }
0746: //
0747: //// if (mouseElement.getParentNode() instanceof RaveElement) {
0748: //// mouseElement = (RaveElement)mouseElement.getParentNode();
0749: // if (mouseElement.getParentNode() instanceof Element) {
0750: // mouseElement = (Element)mouseElement.getParentNode();
0751: // } else {
0752: // break;
0753: // }
0754: // }
0755: //
0756: // if (nodes != null) {
0757: // Action[] actions = NodeOp.findActions(nodes);
0758: //
0759: // if ((actions.length > 0) && ((actions.length > 1) || (actions[0] != null))) {
0760: // Utilities_RAVE.actionsToPopup(actions, parent,
0761: // menu);
0762: // menu.addSeparator();
0763: // }
0764: // }
0765: //
0766: // if(bean == null) {
0767: // throw(new IllegalArgumentException("Null bean."));// NOI18N
0768: // }
0769: // // Construct context menu.
0770: // boolean separate = false;
0771: // DesignInfo bi = bean.getDesignInfo();
0772: //
0773: // if (bi != null) {
0774: // DisplayAction[] context = bi.getContextItems(bean);
0775: //
0776: // if ((context != null) && (context.length > 0)) {
0777: // buildMenu(menu, null, context, webform);
0778: // separate = true;
0779: // }
0780: // }
0781: //
0782: // // "Add" pullright
0783: // if (addItem != null) {
0784: // menu.add(addItem);
0785: // }
0786: //
0787: // // Add a Property Binding dialog? (this is not separated from other
0788: // // context menus)
0789: // if (bean instanceof FacesDesignBean) {
0790: // buildMenu(menu, null,
0791: // new DisplayAction[] { PropertyBindingHelper.getContextItem(bean) }, webform);
0792: // separate = true;
0793: // }
0794: //
0795: // if (separate) {
0796: // DesignerUtils.addSeparator(menu, null);
0797: // }
0798: //
0799: // // Add Customizer?
0800: // BeanDescriptor descriptor = bean.getBeanInfo().getBeanDescriptor();
0801: //
0802: // // XXX where do I look for Customizer2?
0803: // Class customizer = descriptor.getCustomizerClass();
0804: //
0805: // if (customizer != null) {
0806: // String label = NbBundle.getMessage(SelectionManager.class, "Customize"); // NOI18N
0807: // JMenuItem customizeItem = new JMenuItem(label);
0808: // menu.add(customizeItem);
0809: // customizeItem.addActionListener(new ActionListener() {
0810: // public void actionPerformed(ActionEvent evt) {
0811: // webform.getManager().finishInlineEditing(false);
0812: // customize(bean);
0813: // }
0814: // });
0815: // menu.addSeparator();
0816: // }
0817: //
0818: // // For each LiveParent that has menu items, add in their
0819: // // actions
0820: // DesignerUtils.addSeparator(menu, null);
0821: //
0822: // if (showAncestors) {
0823: // DesignBean bparent = bean.getBeanParent();
0824: //
0825: // while (bparent != null) {
0826: // // Cut off at form bean!
0827: // // Construct context menu
0828: // bi = bparent.getDesignInfo();
0829: //
0830: // if (bi != null) {
0831: // DisplayAction[] context = bi.getContextItems(bparent);
0832: //
0833: // if ((context != null) && (context.length > 0)) {
0834: // JMenu submenu = new JMenu(bparent.getInstanceName());
0835: // DesignerUtils.addMenuItem(menu, null, submenu);
0836: // buildMenu(null, submenu, context, webform); // recurse
0837: // }
0838: // }
0839: //
0840: // bparent = bparent.getBeanParent();
0841: // }
0842: //
0843: // DesignerUtils.addSeparator(menu, null);
0844: // }
0845: // }
0846: //
0847: // /**
0848: // * Add a single menu item to the given menu
0849: // */
0850: // public static void addMenuItem(JPopupMenu popup, DisplayAction item, WebForm webform) {
0851: // buildMenu(popup, null, new DisplayAction[] { item }, webform);
0852: // }
0853: //
0854: // /** Recursively build up a potentially hierarchical popup menu
0855: // * structure for the given bean's DesignInfo
0856: // * @todo The fact that I'm passing in BOTH a JPopup and a JMenu
0857: // * is really lame. The problem is that at the top level, I need
0858: // * to populate a JPopupMenu - but I can't add JPopupMenu items
0859: // * for submenus - they must be JMenus. Annoyingly, a JPopupMenu
0860: // * isn't a JMenu. Thus, I have to pass in one or the other,
0861: // * and check which is non-null to figure out what this recursive
0862: // * method is adding to now. To avoid duplicating this logic
0863: // * this method will call addMenuItem for insertion.
0864: // * @todo Properly handle separators such that if I have a submenu
0865: // * with only a popup set for example, I don't get separators at
0866: // * the top and the bottom of the menu
0867: // * @return true iff the last item added was a separator
0868: // */
0869: // private static void buildMenu(JPopupMenu popup, JMenu menu, DisplayAction[] items,
0870: // WebForm webform) {
0871: // if(DEBUG) {
0872: // debugLog(DesignerUtils.class.getName() + ".addMenuItems(DesignBean, JPopupMenu, Node[], JComponent, boolean, WebForm, Element, JComponent");
0873: // }
0874: // if(items == null) {
0875: // throw(new IllegalArgumentException("Null display actions array."));// NOI18N
0876: // }
0877: // if(webform == null) {
0878: // throw(new IllegalArgumentException("Null webform."));// NOI18N
0879: // }
0880: // for (int i = 0; i < items.length; i++) {
0881: // DisplayAction action = items[i];
0882: //
0883: // if (action instanceof DisplayActionSet) {
0884: // DisplayActionSet set = (DisplayActionSet)action;
0885: //
0886: // if (set.isPopup()) {
0887: // // It's a pullright menu
0888: // //JPopupMenu submenu = new org.openide.awt.JPopupMenuPlus();
0889: // JMenu submenu = new JMenu(set.getDisplayName());
0890: //
0891: // // XXX set tooltip? action.getDescription()
0892: // // XXX set icon? action.getSmallIcon()
0893: // //item.setEnabled(action.isEnabled()); // XXX?
0894: // DesignerUtils.addMenuItem(popup, menu, submenu);
0895: //
0896: // /* XXX JPopupMenu doesn't have action listeners....
0897: // if (set.isInvokable()) {
0898: // // XXX this doesn't get called on menu traverse,
0899: // // right? I don't think this is really compatible
0900: // // with swing menus...
0901: // submenu.addActionListener(new ActionListener() {
0902: // public void actionPerformed(ActionEvent event) {
0903: // webform.getManager().finishEditing(false);
0904: // action.invoke();
0905: // }
0906: // }
0907: // );
0908: // }
0909: // */
0910: // DisplayAction[] actions = set.getDisplayActions();
0911: //
0912: // if (actions.length > 0) {
0913: // buildMenu(null, submenu, actions, webform); // recurse
0914: // }
0915: // } else {
0916: // // It's a flat container - inline it in this menu
0917: // DisplayAction[] actions = set.getDisplayActions();
0918: //
0919: // if (actions.length > 0) {
0920: // DesignerUtils.addSeparator(popup, menu);
0921: // buildMenu(popup, menu, actions, webform); // recurse
0922: //
0923: // // Only add separator if it's not the end of the menu
0924: // // (Except in the popup/toplevel case, where we d
0925: // if (i < (items.length - 1)) {
0926: // DesignerUtils.addSeparator(popup, menu);
0927: // }
0928: // }
0929: //
0930: // // XXX ignoring set.isInvokable in this case...
0931: // // There's no "user visible" representation
0932: // // of the group, other than the fact that its
0933: // // items are displayed within a pair of separators
0934: // // (but the items themselves of course have their
0935: // // own actions that are invokable when the items
0936: // // are selected)
0937: // }
0938: // } else if (action instanceof CheckedDisplayAction) {
0939: // // Plain item
0940: // JMenuItem item = new JCheckBoxMenuItem(action.getDisplayName());
0941: //
0942: // // XXX set tooltip? action.getDescription()
0943: // // XXX set icon? action.getSmallIcon()
0944: // item.setEnabled(action.isEnabled());
0945: // item.setSelected(((CheckedDisplayAction)action).isChecked());
0946: // DesignerUtils.addMenuItem(popup, menu, item);
0947: //
0948: // item.addActionListener(new MenuActionListener(action, webform));
0949: // } else {
0950: // // Plain item
0951: // JMenuItem item = new JMenuItem(action.getDisplayName());
0952: //
0953: // // XXX set tooltip? action.getDescription()
0954: // // XXX set icon? action.getSmallIcon()
0955: // item.setEnabled(action.isEnabled());
0956: // DesignerUtils.addMenuItem(popup, menu, item);
0957: //
0958: // item.addActionListener(new MenuActionListener(action, webform));
0959: // }
0960: // }
0961: // }
0962: //
0963: // private static void customize(DesignBean bean) {
0964: // // Instead of stashing the object to operate on
0965: // // along with the menu item, can we just look up
0966: // // the selection set?
0967: // if(DEBUG) {
0968: // debugLog(DesignerUtils.class.getName() + ".customize(DesignBean)");
0969: // }
0970: // if (bean == null) {
0971: // return;
0972: // }
0973: //
0974: // BeanDescriptor descriptor = bean.getBeanInfo().getBeanDescriptor();
0975: //
0976: // // The following code based on
0977: // // core/src/org/netbeans/core/ModuleFSSection.java
0978: // Class customizer = descriptor.getCustomizerClass();
0979: //
0980: // if (customizer == null) {
0981: // // XXX should not happen - we only add/enable
0982: // // the action if we've found one
0983: // return;
0984: // }
0985: //
0986: // if (Customizer2.class.isAssignableFrom(customizer)) {
0987: // // Found live customizer
0988: // try {
0989: // Customizer2 cust = (Customizer2)customizer.newInstance();
0990: // Component panel = cust.getCustomizerPanel(bean);
0991: // DialogDescriptor dd = new DialogDescriptor(panel, cust.getDisplayName());
0992: //
0993: // // DialogDescriptor dd = new DialogDescriptor(panel,
0994: // // NbBundle.getMessage(SelectionManager.class,
0995: // // "CustomizeBean"));
0996: // DialogDisplayer.getDefault().createDialog(dd).show();
0997: //
0998: // return;
0999: // } catch (Exception ex) {
1000: // ErrorManager.getDefault().notify(ex);
1001: //
1002: // return;
1003: // }
1004: // }
1005: //
1006: // try {
1007: // Customizer cust = (Customizer)customizer.newInstance();
1008: // cust.setObject(bean.getInstance());
1009: //
1010: // if (cust instanceof Window) {
1011: // // Customizer was already a window (probably a
1012: // // dialog). Just show it. Presumably it has
1013: // // some window listener and knows to do
1014: // // something when it is closed.
1015: // ((Window)cust).setVisible(true);
1016: // } else if (cust instanceof Component) {
1017: // // Some customizer panel. Show it in an
1018: // // OK/Cancel dialog.
1019: // Component c = (Component)cust;
1020: // DialogDescriptor dd =
1021: // new DialogDescriptor(c,
1022: // NbBundle.getMessage(SelectionManager.class, "CustomizeBean"));
1023: // DialogDisplayer.getDefault().createDialog(dd).show();
1024: // } else {
1025: // ErrorManager.getDefault().log("Non-Component Customizer for bean " +
1026: // bean.getClass().getName());
1027: //
1028: // return;
1029: // }
1030: // } catch (Exception ex) {
1031: // //IOException e = new IOException (ex.toString ());
1032: // //ErrorManager.getDefault ().annotate (e, ex);
1033: // //throw e;
1034: // ErrorManager.getDefault().notify(ex);
1035: // }
1036: // }
1037:
1038: // Moved to designer/jsf/../DesignerServiceHackImpl.
1039: // /** Recursively remove the rave-uninitialized-text class attribute
1040: // * from a node tree.
1041: // * @return True iff any nodes were actually changed
1042: // */
1043: // public static boolean stripDesignStyleClasses(Node node) {
1044: // boolean changedStyles = false;
1045: //
1046: // if(DEBUG) {
1047: // debugLog(DesignerUtils.class.getName() + ".stripDesignStyleClasses(Node)");
1048: // }
1049: // if(node == null) {
1050: // throw(new IllegalArgumentException("Null node."));// NOI18N
1051: // }
1052: //
1053: // if (node.getNodeType() == Node.ELEMENT_NODE) {
1054: // Element e = (Element)node;
1055: //
1056: // if (e.getAttribute(HtmlAttribute.CLASS).indexOf(ignoreClass) != -1) {
1057: // String newClass = e.getAttribute(HtmlAttribute.CLASS).replaceAll(ignoreClass, ""); // ignore stripped out
1058: // e.setAttribute(HtmlAttribute.CLASS, newClass);
1059: // changedStyles = true;
1060: // }
1061: // }
1062: //
1063: // NodeList nl = node.getChildNodes();
1064: //
1065: // for (int i = 0, n = nl.getLength(); i < n; i++) {
1066: // changedStyles |= stripDesignStyleClasses(nl.item(i)); // recurse
1067: // }
1068: //
1069: // return changedStyles;
1070: // }
1071:
1072: // /** Strip the given string to the given maximum length of
1073: // * characters. If the string is not that long, just return
1074: // * it. If it needs to be truncated, truncate it and append
1075: // * "...". maxLength must be at least 4. */
1076: // public static String truncateString(String s, int maxLength) {
1077: // assert maxLength >= 4;
1078: //
1079: // if(DEBUG) {
1080: // debugLog(DesignerUtils.class.getName() + ".truncateString(String, int)");
1081: // }
1082: // if(s == null) {
1083: // throw(new IllegalArgumentException("Null string to truncate."));// NOI18N
1084: // }
1085: //
1086: // if (s.length() > maxLength) {
1087: // // Should "..." be localizable?
1088: // return s.substring(0, maxLength - 3) + "...";
1089: // } else {
1090: // return s;
1091: // }
1092: // }
1093:
1094: // XXX Copy also in designer/jsf/../DomProviderImpl
1095: /** Thread-safe method to set the activated nodes of a TopComponent;
1096: * this can only be done from the event dispatch thread. If called
1097: * from another thread it will post a runnable on the event dispatch
1098: * thread instead.
1099: */
1100: public static void setActivatedNodes(final TopComponent tc,
1101: final org.openide.nodes.Node[] nodes) {
1102: if (DEBUG) {
1103: debugLog(DesignerUtils.class.getName()
1104: + ".setActivatedNodes(TopComponent, Node[])");
1105: }
1106: if (nodes == null) {
1107: throw (new IllegalArgumentException("Null node array."));// NOI18N
1108: }
1109: if (tc == null) {
1110: throw (new IllegalArgumentException("Null TopComponent."));// NOI18N
1111: }
1112: if (SwingUtilities.isEventDispatchThread()) {
1113: tc.setActivatedNodes(nodes);
1114: } else {
1115: SwingUtilities.invokeLater(new Runnable() {
1116: public void run() {
1117: tc.setActivatedNodes(nodes);
1118: }
1119: });
1120: }
1121: }
1122:
1123: // Moved to WebForm.
1124: // /** Locate the webform associated with the given data object. Will return
1125: // * null if no such object is found.
1126: // * @param dobj The data object for which a webform should be located
1127: // * @param initialize If false, don't initialize a webform that has
1128: // * not yet been open - return null instead.
1129: // */
1130: // public static WebForm getWebForm(DomProvider domProvider, DataObject dobj) {
1131: // if (WebForm.isWebFormDataObject(dobj)) {
1132: // return WebForm.getWebFormForDataObject(domProvider, dobj);
1133: // }
1134: //
1135: // return null;
1136: // }
1137:
1138: // /**
1139: // * Return true iff the drag is coming from a NetBeans "explorer" window,
1140: // * since drags with this origin have funky behavior
1141: // */
1142: // public static boolean isExplorerDrag(DropTargetDragEvent dtde) {
1143: // if(DEBUG) {
1144: // debugLog(DesignerUtils.class.getName() + ".isExplorerDrag(DropTargetDragEvent)");
1145: // }
1146: // if(dtde == null) {
1147: // throw(new IllegalArgumentException("Null DropTargetDragEvent."));// NOI18N
1148: // }
1149: // DataFlavor[] df = dtde.getCurrentDataFlavors();
1150: //
1151: // for (int i = 0; i < df.length; i++) {
1152: // DataFlavor f = df[i];
1153: //
1154: // if (f.getRepresentationClass() == org.openide.nodes.Node.class) {
1155: // return true;
1156: // }
1157: // }
1158: //
1159: // return false;
1160: // }
1161:
1162: // /** Fidn a markup bean by id! */
1163: // public static DesignBean findById(WebForm webform, String id) {
1164: // if(DEBUG) {
1165: // debugLog(DesignerUtils.class.getName() + ".findById(WebForm)");
1166: // }
1167: // if(webform == null) {
1168: // throw(new IllegalArgumentException("Null DropTargetDragEvent."));// NOI18N
1169: // }
1170: // return webform.getModel().getLiveUnit().getBeanByName(id);
1171: // }
1172:
1173: /** Check to see if the given point is inside of the rectangle
1174: * positioned at (tx,ty) of dimensions (w,h). */
1175: public static final boolean inside(int x, int y, int tx, int ty,
1176: int w, int h) {
1177: if (x < tx) {
1178: return false;
1179: }
1180:
1181: if (y < ty) {
1182: return false;
1183: }
1184:
1185: if (x > (tx + w)) {
1186: return false;
1187: }
1188:
1189: if (y > (ty + h)) {
1190: return false;
1191: }
1192:
1193: return true;
1194: }
1195:
1196: /**
1197: * Taken from java.awt.Rectangle; changed to be static and
1198: * to compare with specified x,y,w,h instead of another Rectangle
1199: *
1200: * Determines whether or not this <code>Rectangle</code> and the specified
1201: * <code>Rectangle</code> intersect. Two rectangles intersect if
1202: * their intersection is nonempty.
1203: *
1204: * @param r the specified <code>Rectangle</code>
1205: * @return <code>true</code> if the specified <code>Rectangle</code>
1206: * and this <code>Rectangle</code> intersect;
1207: * <code>false</code> otherwise.
1208: */
1209: public static boolean intersects(Rectangle r, int rx, int ry,
1210: int rw, int rh) {
1211: if (DEBUG) {
1212: debugLog(DesignerUtils.class.getName()
1213: + ".intersects(Rectangle, int, int, int, int)");
1214: }
1215: if (r == null) {
1216: throw (new IllegalArgumentException("Null rectangle."));// NOI18N
1217: }
1218: int tw = r.width;
1219: int th = r.height;
1220:
1221: if ((rw <= 0) || (rh <= 0) || (tw <= 0) || (th <= 0)) {
1222: return false;
1223: }
1224:
1225: int tx = r.x;
1226: int ty = r.y;
1227: rw += rx;
1228: rh += ry;
1229: tw += tx;
1230: th += ty;
1231:
1232: // overflow || intersect
1233: return (((rw < rx) || (rw > tx)) && ((rh < ry) || (rh > ty))
1234: && ((tw < tx) || (tw > rx)) && ((th < ty) || (th > ry)));
1235: }
1236:
1237: // /**
1238: // * Return true iff the given document represents a Braveheart page. A braveheart
1239: // * page is one using Braveheart components
1240: // * @param document The document to be checked
1241: // */
1242: // public static boolean isBraveheartPage(Document document) {
1243: // if(DEBUG) {
1244: // debugLog(DesignerUtils.class.getName() + ".isBraveheartPage(Document)");
1245: // }
1246: // if(document == null) {
1247: // throw(new IllegalArgumentException("Null document."));// NOI18N
1248: // }
1249: // // Many possibilities here:
1250: // // (1) Scan through all tags, look to see if we find any ui: tags
1251: // // (2) Look on the jsp:root, see if we include the braveheart taglib
1252: // // (3) See if the top most tag under f:view is a braveheart one
1253: // // (4) See if the body is a plain html <body> tag or if it's rendered from
1254: // // another component
1255: // Element element = document.getDocumentElement();
1256: //
1257: // if (element.hasAttribute("xmlns:ui")) { // NOI18N
1258: // assert element.getAttribute("xmlns:ui").equals("http://www.sun.com/web/ui"); // NOI18N
1259: //
1260: // return true;
1261: // }
1262: //
1263: // return false;
1264: // }
1265:
1266: // /** Class which is attached to display actions in context menus */
1267: // private static class MenuActionListener implements ActionListener {
1268: // private DisplayAction action;
1269: // private WebForm webform;
1270: //
1271: // MenuActionListener(DisplayAction action, WebForm webform) {
1272: // if(DEBUG) {
1273: // debugLog(DesignerUtils.class.getName() + ".MenuActionListener");
1274: // }
1275: // if(action == null) {
1276: // throw(new IllegalStateException("Null action."));// NOI18N
1277: // }
1278: // if(webform == null) {
1279: // throw(new IllegalStateException("Null webform."));// NOI18N
1280: // }
1281: // this.action = action;
1282: // this.webform = webform;
1283: // }
1284: //
1285: // public void actionPerformed(ActionEvent event) {
1286: // webform.getManager().finishInlineEditing(false);
1287: //
1288: // String label = action.getDisplayName();
1289: //
1290: // if (label.endsWith("...")) { // NOI18N
1291: // label = label.substring(0, label.length() - 3);
1292: // }
1293: //
1294: //// webform.getDocument().writeLock("\"" + label + "\""); // NOI18N
1295: // UndoEvent undoEvent = webform.getModel().writeLock("\"" + label + "\""); // NOI18N
1296: //
1297: // try {
1298: // Result r = action.invoke();
1299: // ResultHandler.handleResult(r, (webform != null) ? webform.getModel() : null);
1300: // } finally {
1301: //// webform.getDocument().writeUnlock();
1302: // webform.getModel().writeUnlock(undoEvent);
1303: // }
1304: // }
1305: // }
1306:
1307: /** Logs debug message. Use only after checking <code>DEBUG</code> flag. */
1308: static void debugLog(String message) {
1309: ErrorManager.getDefault().getInstance(
1310: DesignerUtils.class.getName()).log(message);
1311: }
1312:
1313: // XXX Moved to BasicDragGestureRecognizer.
1314: // /** XXX Copied from SunDragSourceContextPeer, to avoid dependency on sun jdk. */
1315: // public static int convertModifiersToDropAction(final int modifiers,
1316: // final int supportedActions) {
1317: // int dropAction = DnDConstants.ACTION_NONE;
1318: //
1319: // /*
1320: // * Fix for 4285634.
1321: // * Calculate the drop action to match Motif DnD behavior.
1322: // * If the user selects an operation (by pressing a modifier key),
1323: // * return the selected operation or ACTION_NONE if the selected
1324: // * operation is not supported by the drag source.
1325: // * If the user doesn't select an operation search the set of operations
1326: // * supported by the drag source for ACTION_MOVE, then for
1327: // * ACTION_COPY, then for ACTION_LINK and return the first operation
1328: // * found.
1329: // */
1330: // switch (modifiers & (InputEvent.SHIFT_DOWN_MASK |
1331: // InputEvent.CTRL_DOWN_MASK)) {
1332: // case InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK:
1333: // dropAction = DnDConstants.ACTION_LINK; break;
1334: // case InputEvent.CTRL_DOWN_MASK:
1335: // dropAction = DnDConstants.ACTION_COPY; break;
1336: // case InputEvent.SHIFT_DOWN_MASK:
1337: // dropAction = DnDConstants.ACTION_MOVE; break;
1338: // default:
1339: // if ((supportedActions & DnDConstants.ACTION_MOVE) != 0) {
1340: // dropAction = DnDConstants.ACTION_MOVE;
1341: // } else if ((supportedActions & DnDConstants.ACTION_COPY) != 0) {
1342: // dropAction = DnDConstants.ACTION_COPY;
1343: // } else if ((supportedActions & DnDConstants.ACTION_LINK) != 0) {
1344: // dropAction = DnDConstants.ACTION_LINK;
1345: // }
1346: // }
1347: //
1348: // return dropAction & supportedActions;
1349: // }
1350:
1351: /** XXX To keep the deprecated Toolkit.getFrontMetrics method separated.
1352: /* TODO Find out how actually is one suppose replace the Toolkit.getFontMetrics method. */
1353: public static FontMetrics getFontMetrics(Font font) {
1354: return Toolkit.getDefaultToolkit().getFontMetrics(font);
1355: }
1356:
1357: // This seems to be not needed yet.
1358: // public static Element getNextSiblingElement(Element element) {
1359: // if (element == null) {
1360: // return null;
1361: // }
1362: // Node sibling = element.getNextSibling();
1363: // while (sibling != null) {
1364: // if (sibling instanceof Element) {
1365: // return (Element)sibling;
1366: // }
1367: // sibling = sibling.getNextSibling();
1368: // }
1369: // return null;
1370: // }
1371: //
1372: // public static Element getPreviousSiblingElement(Element element) {
1373: // if (element == null) {
1374: // return null;
1375: // }
1376: // Node sibling = element.getPreviousSibling();
1377: // while (sibling != null) {
1378: // if (sibling instanceof Element) {
1379: // return (Element)sibling;
1380: // }
1381: // sibling = sibling.getPreviousSibling();
1382: // }
1383: // return null;
1384: // }
1385:
1386: }
|