001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: /*
042: * PaletteItemDataObjec t.java
043: *
044: * Created on August 2, 2006, 11:52 AM
045: *
046: * DataObject for palette item file. It reads the file and creates PaletteItem
047: * and node from it.
048: *
049: * @author Joelle Lam <joelle.lam@sun.com>
050: * @version %I%, %G%
051: */
052:
053: package org.netbeans.modules.visualweb.palette;
054:
055: import com.sun.rave.designtime.BeanCreateInfo;
056: import com.sun.rave.designtime.DesignBean;
057: import com.sun.rave.designtime.DisplayItem;
058: import com.sun.rave.designtime.Result;
059: import org.netbeans.modules.visualweb.palette.api.PaletteItemInfoCookie;
060: import java.awt.Image;
061: import java.awt.datatransfer.DataFlavor;
062: import java.awt.datatransfer.Transferable;
063: import java.awt.datatransfer.UnsupportedFlavorException;
064: import java.awt.dnd.DnDConstants;
065: import java.lang.reflect.InvocationTargetException;
066: import java.lang.reflect.Method;
067: import java.util.*;
068: import java.io.*;
069: import java.beans.*;
070: import java.util.logging.Level;
071: import java.util.logging.LogRecord;
072: import java.util.logging.Logger;
073: import org.openide.util.HelpCtx;
074: import org.openide.util.Lookup;
075: import org.openide.util.datatransfer.ExTransferable;
076:
077: import org.xml.sax.*;
078: import org.xml.sax.helpers.DefaultHandler;
079:
080: import org.openide.loaders.*;
081: import org.openide.filesystems.*;
082: import org.openide.nodes.*;
083: import org.openide.xml.XMLUtil;
084: import org.openide.actions.*;
085: import org.openide.util.Utilities;
086: import org.openide.util.NbBundle;
087: import org.openide.ErrorManager;
088:
089: public class PaletteItemDataObject extends MultiDataObject {
090:
091: static final String XML_ROOT = "palette_item"; // NOI18N
092: static final String ATTR_VERSION = "version"; // NOI18N
093: static final String TAG_COMPONENT = "component"; // NOI18N
094: static final String ATTR_CLASSNAME = "classname"; // NOI18N
095: static final String ATTR_TYPE = "type"; // NOI18N
096: // static final String ATTR_IS_CONTAINER = "is-container"; // NOI18N
097: static final String TAG_CLASSPATH = "classpath"; // NOI18N
098: static final String TAG_RESOURCE = "resource"; // NOI18N
099: static final String ATTR_NAME = "name"; // NOI18N
100: static final String TAG_DESCRIPTION = "description"; // NOI18N
101: static final String ATTR_BUNDLE = "localizing-bundle"; // NOI18N
102: static final String ATTR_DISPLAY_NAME_KEY = "display-name-key"; // NOI18N
103: static final String ATTR_TOOLTIP_KEY = "tooltip-key"; // NOI18N
104: static final String ATTR_HELP_KEY = "help-key"; // NOI18N
105: static final String TAG_ICON16 = "icon16"; // NOI18N
106: static final String ATTR_URL = "urlvalue"; // NOI18N
107: static final String TAG_ICON32 = "icon32"; // NOI18N
108: // component types: "visual", "menu", "layout", "border"
109: // classpath resource types: "jar", "library", "project" (defined in ClassSource)
110:
111: private static final Node.PropertySet[] NO_PROPERTIES = new Node.PropertySet[0];
112: private static final Logger UI_LOG = Logger
113: .getLogger("org.netbeans.ui.visualweb.palette"); //NOI18N
114:
115: private boolean fileLoaded; // at least tried to load
116:
117: // private PaletteItem paletteItem;
118: private String componentClassName;
119:
120: // some raw data read from the file (other passed to PaletteItem)
121: private String displayName_key;
122: private String tooltip_key;
123: private String help_key;
124: private String bundleName;
125: private String icon16URL;
126: private String icon32URL;
127:
128: // resolved data (derived from raw data)
129: String displayName;
130: String tooltip;
131: java.awt.Image icon16;
132: java.awt.Image icon32;
133:
134: // --------
135:
136: PaletteItemDataObject(FileObject fo, MultiFileLoader loader)
137: throws DataObjectExistsException {
138: super (fo, loader);
139: }
140:
141: boolean isFileRead() {
142: return fileLoaded;
143: }
144:
145: boolean isItemValid() {
146: return true;
147: }
148:
149: public HelpCtx getHelpCtx() {
150: // System.out.println("\nHelp Context Being Called.");
151: if (help_key == null) {
152: System.out.println("Help Context Found: " + help_key);
153: return super .getHelpCtx();
154: }
155: return new HelpCtx(help_key);
156: }
157:
158: public Node createNodeDelegate() {
159: return new ItemNode();
160: }
161:
162: @Override
163: public <T extends Node.Cookie> T getCookie(Class<T> cookieClass) {
164:
165: if (PaletteItemInfoCookie.class.isAssignableFrom(cookieClass)) {
166: return cookieClass.cast(new PaletteItemInfoImpl(this ));
167: }
168: return cookieClass.cast(super .getCookie(cookieClass));
169: }
170:
171: // -------
172:
173: private void loadFile() {
174: fileLoaded = true;
175:
176: FileObject file = getPrimaryFile();
177: if (file.getSize() == 0L) { // item file is empty
178: return;
179: }
180:
181: // parse the XML file
182: try {
183: XMLReader reader = XMLUtil.createXMLReader();
184: PaletteItemHandler handler = new PaletteItemHandler();
185: reader.setContentHandler(handler);
186: InputSource input = new InputSource(getPrimaryFile()
187: .getURL().toExternalForm());
188: reader.parse(input);
189: // TODO report errors, validate using DTD?
190:
191: if (handler.componentClassName != null
192: || displayName_key != null) {
193: String[] cpTypes = null;
194: String[] cpNames = null;
195: if (handler.cpTypeList.size() > 0) {
196: cpTypes = new String[handler.cpTypeList.size()];
197: handler.cpTypeList.toArray(cpTypes);
198: cpNames = new String[handler.cpNameList.size()];
199: handler.cpNameList.toArray(cpNames);
200: }
201:
202: componentClassName = handler.componentClassName;
203: }
204: } catch (SAXException saxex) {
205: ErrorManager.getDefault().notify(
206: ErrorManager.INFORMATIONAL, saxex);
207: } catch (IOException ioex) {
208: ErrorManager.getDefault().notify(
209: ErrorManager.INFORMATIONAL, ioex);
210: }
211: }
212:
213: /**
214: * @param folder folder of category where to create new file
215: * @param classname name of the component class
216: * @param source classpath source type - "jar", "library", "project"
217: * @param classpath names of classpath roots - e.g. JAR file paths
218: */
219: // static void createFile(FileObject folder, ClassSource classSource)
220: // throws IOException
221: // {
222: // String classname = classSource.getClassName();
223: //
224: // int idx = classname.lastIndexOf('.');
225: // String fileName = FileUtil.findFreeFileName(
226: // folder,
227: // idx >= 0 ? classname.substring(idx+1) : classname,
228: // PaletteItemDataLoader.ITEM_EXT);
229: //
230: // FileObject itemFile = folder.createData(fileName,
231: // PaletteItemDataLoader.ITEM_EXT);
232: //
233: // StringBuffer buff = new StringBuffer(512);
234: // buff.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n"); // NOI18N
235: // buff.append("<palette_item version=\"1.0\">\n"); // NOI18N
236: // buff.append(" <component classname=\""); // NOI18N
237: // buff.append(classname);
238: // buff.append("\" />\n"); // NOI18N
239: // buff.append(" <classpath>\n"); // NOI18N
240: // for (int i=0, n=classSource.getCPRootCount(); i < n; i++) {
241: // buff.append(" <resource type=\""); // NOI18N
242: // buff.append(classSource.getCPRootType(i));
243: // buff.append("\" name=\""); // NOI18N
244: // buff.append(classSource.getCPRootName(i));
245: // buff.append("\" />\n"); // NOI18N
246: // buff.append(" </classpath>\n"); // NOI18N
247: // buff.append("</palette_item>\n"); // NOI18N
248: // }
249: //
250: // FileLock lock = itemFile.lock();
251: // OutputStream os = itemFile.getOutputStream(lock);
252: // try {
253: // os.write(buff.toString().getBytes());
254: // }
255: // finally {
256: // os.close();
257: // lock.releaseLock();
258: // }
259: // }
260: // -------
261: /** DataLoader for the palette item files. */
262: public static final class PaletteItemDataLoader extends
263: UniFileLoader {
264:
265: static final String ITEM_EXT = "comp_palette_item"; // NOI18N
266:
267: PaletteItemDataLoader() {
268: super (
269: "org.netbeans.modules.visualweb.palette.PaletteItemDataObject"); // NOI18N
270:
271: ExtensionList ext = new ExtensionList();
272: ext.addExtension(ITEM_EXT);
273: setExtensions(ext);
274: }
275:
276: /** Gets default display name. Overides superclass method. */
277: protected String defaultDisplayName() {
278: return NbBundle.getBundle(PaletteItemDataObject.class)
279: .getString("PROP_PaletteItemLoader_Name"); // NOI18N
280: }
281:
282: protected MultiDataObject createMultiObject(
283: FileObject primaryFile)
284: throws DataObjectExistsException, IOException {
285: return new PaletteItemDataObject(primaryFile, this );
286: }
287: }
288:
289: public static final class PaletteItemDataLoaderBeanInfo extends
290: SimpleBeanInfo {
291: private static String iconURL = "org/netbeans/modules/visualweb/palette/resources/palette_manager.png"; // NOI18N
292:
293: public BeanInfo[] getAdditionalBeanInfo() {
294: try {
295: return new BeanInfo[] { Introspector
296: .getBeanInfo(UniFileLoader.class) };
297: } catch (IntrospectionException ie) {
298: org.openide.ErrorManager.getDefault().notify(ie);
299: return null;
300: }
301: }
302:
303: public java.awt.Image getIcon(final int type) {
304: return Utilities.loadImage(iconURL);
305: }
306:
307: }
308:
309: // --------
310:
311: /** Node representing the palette item (node delegate for the DataObject). */
312: class ItemNode extends DataNode {
313:
314: ItemNode() {
315: //classname = PaletteItemDataObject.this.componentClassName;
316: super (PaletteItemDataObject.this , Children.LEAF);
317: }
318:
319: public String getDisplayName() {
320: if (!fileLoaded)
321: loadFile();
322:
323: if (displayName == null) {
324: displayName = getExplicitDisplayName();
325: if (displayName == null) { // no explicit name
326: displayName = super .getDisplayName();
327: }
328: }
329: return displayName;
330: }
331:
332: public String getShortDescription() {
333: if (!fileLoaded)
334: loadFile();
335:
336: if (tooltip == null) {
337: tooltip = getExplicitTooltip();
338: if (tooltip == null) { // no explicit tooltip
339: tooltip = getDisplayName();
340: }
341:
342: }
343: return tooltip;
344: }
345:
346: public boolean canRename() {
347: return true;
348: }
349:
350: public java.awt.Image getIcon(int type) {
351: if (!fileLoaded)
352: loadFile();
353: // System.out.println("\nPaletteItemDataObject: getIcon.");
354: // System.out.println("File: " + PaletteItemDataObject.this.getPrimaryFile());
355:
356: if (type == BeanInfo.ICON_COLOR_32x32
357: || type == BeanInfo.ICON_MONO_32x32) {
358: if (icon32 == null) {
359: icon32 = getExplicitIcon(type);
360: // if (icon32 == null && isItemValid())
361: // icon32 = paletteItem.getIcon(type);
362: if (icon32 == null)
363: icon32 = Utilities
364: .loadImage("org/netbeans/modules/visualweb/palette/resources/custom_component_32.png"); // NOI18N
365: }
366: return icon32;
367: } else { // small icon by default
368: // System.out.println("Small Icon");
369: if (icon16 == null) {
370: // System.out.println("Small Icon is null");
371: icon16 = getExplicitIcon(type);
372: // if (icon16 == null && isItemValid())
373: // icon16 = paletteItem.getIcon(type);
374: if (icon16 == null) {
375: // System.out.println("Small Icon is null after assignment");
376: icon16 = Utilities
377: .loadImage("org/netbeans/modules/visualweb/palette/resources/custom_component.png"); // NOI18N
378: }
379: }
380: return icon16;
381: }
382: // TODO badged icon for invalid item?
383: }
384:
385: // TODO properties
386: public Node.PropertySet[] getPropertySets() {
387: return NO_PROPERTIES;
388: }
389:
390: // ------
391:
392: private String getExplicitDisplayName() {
393: String displayName = null;
394: if (displayName_key != null) {
395: if (bundleName != null) {
396: try {
397: displayName = NbBundle.getBundle(bundleName)
398: .getString(displayName_key);
399: } catch (Exception ex) {
400: } // ignore failure
401: }
402: if (displayName == null)
403: displayName = displayName_key;
404: }
405: return displayName;
406: }
407:
408: private String getExplicitTooltip() {
409: String tooltip = null;
410: if (tooltip_key != null) {
411: if (bundleName != null) {
412: try {
413: tooltip = NbBundle.getBundle(bundleName)
414: .getString(tooltip_key);
415: } catch (Exception ex) {
416: } // ignore failure
417: }
418: if (tooltip == null)
419: tooltip = tooltip_key;
420: }
421: return tooltip;
422: }
423:
424: private java.awt.Image getExplicitIcon(int type) {
425: if (type == BeanInfo.ICON_COLOR_32x32
426: || type == BeanInfo.ICON_MONO_32x32) {
427: if (icon32URL != null) { // explicit icon specified in file
428: try {
429: return java.awt.Toolkit.getDefaultToolkit()
430: .getImage(new java.net.URL(icon32URL));
431: } catch (java.net.MalformedURLException ex) {
432: } // ignore
433: } else if (getPrimaryFile().getAttribute(
434: "SystemFileSystem.icon32") != null) // NOI18N
435: return super .getIcon(type);
436: } else { // get small icon in other cases
437: if (icon16URL != null) { // explicit icon specified in file
438: try {
439: return java.awt.Toolkit.getDefaultToolkit()
440: .getImage(new java.net.URL(icon16URL));
441: } catch (java.net.MalformedURLException ex) {
442: } // ignore
443: } else if (getPrimaryFile().getAttribute(
444: "SystemFileSystem.icon") != null) // NOI18N
445: return super .getIcon(type);
446: }
447: return null;
448: }
449:
450: public Transferable clipboardCopy() throws IOException {
451: Transferable t = super .clipboardCopy();
452: addPaletteFlavor(t);
453:
454: return t;
455:
456: }
457:
458: public Transferable clipboardCut() throws IOException {
459: Transferable t = super .clipboardCut();
460: addPaletteFlavor(t);
461: return t;
462: }
463:
464: public Transferable drag() throws IOException {
465: Transferable t = super .drag();
466: addPaletteFlavor(t);
467:
468: LogRecord rec = new LogRecord(Level.CONFIG,
469: "COMPONENT_NAME"); //NOI18N
470: rec.setParameters(new Object[] { getDisplayName(),
471: componentClassName });
472: rec.setResourceBundle(NbBundle.getBundle(ItemNode.class));
473: rec.setResourceBundleName(ItemNode.class.getPackage()
474: .getName()
475: + ".Bundle");
476: rec.setLoggerName(UI_LOG.getName());
477: UI_LOG.log(rec);
478:
479: // XXX NB#82645, when the issue is fixed, remove this.
480: hackExplorerDnD(this , t);
481:
482: return t;
483:
484: }
485:
486: private Transferable addPaletteFlavor(Transferable t) {
487:
488: String DISPLAY_ITEM_HUMAN_NAME = NbBundle.getMessage(
489: PaletteItemDataObject.class,
490: "DISPLAY_ITEM_HUMAN_NAME"); //NOIl8N
491:
492: // System.out.println("\nPaletteItemDataObject: Transferable: " + t);
493: // System.out.println("Flavors: " + Arrays.asList(t.getTransferDataFlavors()));
494:
495: //ExTransferable allows you to add additional flavors.
496: ExTransferable et = ExTransferable.create(t);
497:
498: //The DisplayItem Flavor make items dropable.
499: DataFlavor df = new DataFlavor(
500: DataFlavor.javaJVMLocalObjectMimeType + "; class="
501: + DisplayItem.class.getName(), // NOI18N
502: DISPLAY_ITEM_HUMAN_NAME);
503:
504: // DataFlavor df = new DataFlavor(
505: // DataFlavor.javaJVMLocalObjectMimeType + "; class=" + DisplayItem.class.getName(), // NOI18N
506: // "DISPLAY_ITEM_HUMAN_NAME");
507:
508: ExTransferable.Single ex_sgl = new ExTransferable.Single(df) {
509: protected Object getData() throws IOException,
510: UnsupportedFlavorException {
511:
512: return new PlainBeanCreateInfo(
513: PaletteItemDataObject.this .componentClassName,
514: PaletteItemDataObject.this .displayName);
515: }
516:
517: };
518: et.put(ex_sgl);
519:
520: return t;
521: }
522:
523: }
524:
525: private class PaletteItemHandler extends DefaultHandler {
526: List<String> cpTypeList; // list for classpath type entries
527: List<String> cpNameList; // list for classpath root name entries
528: String componentClassName;
529:
530: public void startDocument() throws SAXException {
531: cpTypeList = new ArrayList<String>();
532: cpNameList = new ArrayList<String>();
533: componentClassName = null;
534: }
535:
536: public void startElement(String uri, String localName,
537: String qName, Attributes attributes)
538: throws SAXException {
539: if (XML_ROOT.equals(qName)) {
540: String version = attributes.getValue(ATTR_VERSION);
541: if (version == null) {
542: String message = NbBundle.getBundle(
543: PaletteItemDataObject.class).getString(
544: "MSG_UnknownPaletteItemVersion"); // NOI18N
545: throw new SAXException(message);
546: } else if (!version.startsWith("1.")) { // NOI18N
547: String message = NbBundle.getBundle(
548: PaletteItemDataObject.class).getString(
549: "MSG_UnsupportedPaletteItemVersion"); // NOI18N
550: throw new SAXException(message);
551: }
552: // TODO item ID (for now we take the class name as the ID)
553: } else if (TAG_COMPONENT.equals(qName)) {
554: String className = attributes.getValue(ATTR_CLASSNAME);
555: componentClassName = className;
556: } else if (TAG_CLASSPATH.equals(qName)) {
557: // Content is processed in the next branch
558: } else if (TAG_RESOURCE.equals(qName)) {
559: String type = attributes.getValue(ATTR_TYPE);
560: String name = attributes.getValue(ATTR_NAME);
561: if ((type != null) && (name != null)) {
562: cpTypeList.add(type);
563: cpNameList.add(name);
564: }
565: } else if (TAG_DESCRIPTION.equals(qName)) {
566: String bundle = attributes.getValue(ATTR_BUNDLE);
567: if (bundle != null) {
568: PaletteItemDataObject.this .bundleName = bundle;
569: }
570: String displayNameKey = attributes
571: .getValue(ATTR_DISPLAY_NAME_KEY);
572: if (displayNameKey != null) {
573: PaletteItemDataObject.this .displayName_key = displayNameKey;
574: }
575: String tooltipKey = attributes
576: .getValue(ATTR_TOOLTIP_KEY);
577: if (tooltipKey != null) {
578: PaletteItemDataObject.this .tooltip_key = tooltipKey;
579: }
580: String help_key = attributes.getValue(ATTR_HELP_KEY);
581: if (help_key != null) {
582: PaletteItemDataObject.this .help_key = help_key;
583: }
584: } else if (TAG_ICON16.equals(qName)) {
585: String url = attributes.getValue(ATTR_URL);
586: if (url != null) {
587: PaletteItemDataObject.this .icon16URL = url;
588: }
589: // TODO support also class resource name for icons
590: } else if (TAG_ICON32.equals(qName)) {
591: String url = attributes.getValue(ATTR_URL);
592: if (url != null) {
593: PaletteItemDataObject.this .icon32URL = url;
594: }
595: // TODO support also class resource name for icons
596: }
597: }
598: }
599:
600: private static class PlainBeanCreateInfo implements BeanCreateInfo {
601:
602: private final String beanClassName;
603: private final String displayName;
604:
605: public PlainBeanCreateInfo(String beanClassName,
606: String displayName) {
607: this .beanClassName = beanClassName;
608: this .displayName = displayName;
609: }
610:
611: public String getBeanClassName() {
612: return beanClassName;
613: }
614:
615: public Result beanCreatedSetup(DesignBean designBean) {
616: // XXX Don't do anything?
617: return null;
618: }
619:
620: public String getDisplayName() {
621: return displayName;
622: }
623:
624: public String getDescription() {
625: return null;
626: }
627:
628: public Image getLargeIcon() {
629: return null;
630: }
631:
632: public Image getSmallIcon() {
633: return null;
634: }
635:
636: public String getHelpKey() {
637: return null;
638: }
639:
640: }
641:
642: private static class DisplayItemTransferable implements
643: Transferable {
644: private String componentClassName;
645: private String displayName;
646:
647: private static final String HUMAN_NAME = NbBundle.getMessage(
648: PaletteItemDataObject.class, "HUMAN_NAME");
649:
650: private static final DataFlavor FLAVOR_DISPLAY_ITEM = new DataFlavor(
651: DataFlavor.javaJVMLocalObjectMimeType + "; class="
652: + DisplayItem.class.getName(), // NOI18N
653: HUMAN_NAME);
654:
655: public DisplayItemTransferable(String componentClassName,
656: String displayName) {
657: this .componentClassName = componentClassName;
658: this .displayName = displayName;
659: }
660:
661: public DataFlavor[] getTransferDataFlavors() {
662: return new DataFlavor[] { FLAVOR_DISPLAY_ITEM };
663: }
664:
665: public boolean isDataFlavorSupported(DataFlavor flavor) {
666: if (FLAVOR_DISPLAY_ITEM.equals(flavor)) {
667: return true;
668: }
669: return false;
670: }
671:
672: public Object getTransferData(DataFlavor flavor)
673: throws UnsupportedFlavorException, IOException {
674: if (!FLAVOR_DISPLAY_ITEM.equals(flavor)) {
675: throw new UnsupportedFlavorException(flavor);
676: }
677: return new PlainBeanCreateInfo(componentClassName,
678: displayName);
679:
680: }
681:
682: }
683:
684: private static class PaletteItemInfoImpl implements
685: PaletteItemInfoCookie {
686:
687: private final PaletteItemDataObject pido;
688:
689: PaletteItemInfoImpl(PaletteItemDataObject pido) {
690: this .pido = pido;
691: }
692:
693: public String getClassName() {
694: return pido.componentClassName;
695: }
696:
697: public Image getIcon() {
698: return pido.getNodeDelegate().getIcon(
699: BeanInfo.ICON_COLOR_16x16);
700: }
701:
702: public String getDisplayName() {
703: return pido.getNodeDelegate().getDisplayName();
704: }
705:
706: }
707:
708: //////////////////////
709: // >>> Hack workaround.
710: /** XXX Workaround of NB #82645. */
711: private static void hackExplorerDnD(ItemNode itemNode,
712: Transferable trans) {
713: Object explorerDnDManager = getExplorerDnDManager();
714: if (explorerDnDManager != null) {
715: setNodeAllowedActions(explorerDnDManager,
716: DnDConstants.ACTION_MOVE);
717: setDraggedTransferable(explorerDnDManager, trans, true);
718: setDraggedNodes(explorerDnDManager, new Node[] { itemNode });
719: setDnDActive(explorerDnDManager, true);
720: }
721: }
722:
723: private static void setNodeAllowedActions(
724: Object explorerDnDManager, int actions) {
725: invokeOnExplorerDnDManager(explorerDnDManager,
726: "setNodeAllowedActions", // NOI18N
727: new Class[] { Integer.TYPE }, new Object[] { Integer
728: .valueOf(actions) });
729: }
730:
731: private static void setDraggedTransferable(
732: Object explorerDnDManager, Transferable trans, boolean isCut) {
733: invokeOnExplorerDnDManager(
734: explorerDnDManager,
735: "setDraggedTransferable", // NOI18N
736: new Class[] { Transferable.class, Boolean.TYPE },
737: new Object[] { trans, Boolean.valueOf(isCut) });
738: }
739:
740: private static void setDraggedNodes(Object explorerDnDManager,
741: Node[] nodes) {
742: invokeOnExplorerDnDManager(explorerDnDManager,
743: "setDraggedNodes", // NOI18N
744: new Class[] { Node[].class }, new Object[] { nodes });
745: }
746:
747: private static void setDnDActive(Object explorerDnDManager,
748: boolean active) {
749: invokeOnExplorerDnDManager(explorerDnDManager, "setDnDActive", // NOI18N
750: new Class[] { Boolean.TYPE }, new Object[] { Boolean
751: .valueOf(active) });
752: }
753:
754: private static Object getExplorerDnDManager() {
755: ClassLoader contextCL = (ClassLoader) Lookup.getDefault()
756: .lookup(ClassLoader.class);
757: try {
758: Class explorerDnDClass = Class.forName(
759: "org.openide.explorer.view.ExplorerDnDManager",
760: true, contextCL); // NOI18N
761: Method getDefaultMethod = explorerDnDClass
762: .getDeclaredMethod("getDefault", new Class[0]); // NOI18N
763: getDefaultMethod.setAccessible(true);
764: return getDefaultMethod.invoke(null, new Object[0]);
765: } catch (IllegalArgumentException ex) {
766: ErrorManager.getDefault().notify(
767: ErrorManager.INFORMATIONAL, ex);
768: } catch (InvocationTargetException ex) {
769: ErrorManager.getDefault().notify(
770: ErrorManager.INFORMATIONAL, ex);
771: } catch (IllegalAccessException ex) {
772: ErrorManager.getDefault().notify(
773: ErrorManager.INFORMATIONAL, ex);
774: } catch (SecurityException ex) {
775: ErrorManager.getDefault().notify(
776: ErrorManager.INFORMATIONAL, ex);
777: } catch (NoSuchMethodException ex) {
778: ErrorManager.getDefault().notify(
779: ErrorManager.INFORMATIONAL, ex);
780: } catch (ClassNotFoundException ex) {
781: ErrorManager.getDefault().notify(
782: ErrorManager.INFORMATIONAL, ex);
783: }
784: return null;
785: }
786:
787: private static void invokeOnExplorerDnDManager(
788: Object explorerDnDManager, String methodName,
789: Class[] argumentTypes, Object[] arguments) {
790: try {
791: Method setNodeAllowedActions = explorerDnDManager
792: .getClass().getDeclaredMethod(methodName,
793: argumentTypes);
794: setNodeAllowedActions.setAccessible(true);
795: setNodeAllowedActions.invoke(explorerDnDManager, arguments);
796: } catch (IllegalArgumentException ex) {
797: ErrorManager.getDefault().notify(
798: ErrorManager.INFORMATIONAL, ex);
799: } catch (IllegalAccessException ex) {
800: ErrorManager.getDefault().notify(
801: ErrorManager.INFORMATIONAL, ex);
802: } catch (InvocationTargetException ex) {
803: ErrorManager.getDefault().notify(
804: ErrorManager.INFORMATIONAL, ex);
805: } catch (SecurityException ex) {
806: ErrorManager.getDefault().notify(
807: ErrorManager.INFORMATIONAL, ex);
808: } catch (NoSuchMethodException ex) {
809: ErrorManager.getDefault().notify(
810: ErrorManager.INFORMATIONAL, ex);
811: }
812: }
813: // <<< Hack workaround.
814: //////////////////////
815:
816: }
|