KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > form > CopySupport


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.form;
21
22 import java.awt.datatransfer.DataFlavor JavaDoc;
23 import java.awt.datatransfer.Transferable JavaDoc;
24 import java.awt.datatransfer.UnsupportedFlavorException JavaDoc;
25 import java.io.IOException JavaDoc;
26 import org.netbeans.modules.form.layoutdesign.LayoutComponent;
27 import org.netbeans.modules.form.layoutdesign.LayoutModel;
28 import org.netbeans.modules.form.palette.BeanInstaller;
29 import org.netbeans.modules.form.project.ClassPathUtils;
30 import org.netbeans.modules.form.project.ClassSource;
31 import org.openide.DialogDisplayer;
32 import org.openide.ErrorManager;
33 import org.openide.NotifyDescriptor;
34 import org.openide.filesystems.FileObject;
35 import org.openide.loaders.DataObject;
36 import org.openide.nodes.Node;
37 import org.openide.nodes.NodeTransfer;
38 import org.openide.util.Mutex;
39 import org.openide.util.MutexException;
40 import org.openide.util.datatransfer.ExTransferable;
41 import org.openide.util.datatransfer.PasteType;
42
43 /**
44  * Support class for copy/cut/paste operations in form editor.
45  *
46  * @author Tomas Pavek
47  */

48
49 class CopySupport {
50
51     private static final String JavaDoc flavorMimeType =
52         "application/x-form-metacomponent;class=java.lang.Object"; // NOI18N
53

54     private static DataFlavor JavaDoc copyFlavor;
55     private static DataFlavor JavaDoc cutFlavor;
56
57     static DataFlavor JavaDoc getComponentCopyFlavor() {
58         if (copyFlavor == null) {
59             copyFlavor = new DataFlavor JavaDoc(flavorMimeType,
60                                         "COMPONENT_COPY_FLAVOR"); // NOI18N
61
}
62         return copyFlavor;
63     }
64
65     static DataFlavor JavaDoc getComponentCutFlavor() {
66         if (cutFlavor == null) {
67             cutFlavor = new DataFlavor JavaDoc(flavorMimeType,
68                                        "COMPONENT_CUT_FLAVOR"); // NOI18N
69
}
70         return cutFlavor;
71     }
72
73     // -----------
74

75     static class RADTransferable implements Transferable JavaDoc {
76         private RADComponent radComponent;
77         private DataFlavor JavaDoc[] flavors;
78
79         RADTransferable(DataFlavor JavaDoc flavor, RADComponent radComponent) {
80             this(new DataFlavor JavaDoc[] { flavor }, radComponent);
81         }
82
83         RADTransferable(DataFlavor JavaDoc[] flavors, RADComponent radComponent) {
84             this.flavors = flavors;
85             this.radComponent = radComponent;
86         }
87
88         public DataFlavor JavaDoc[] getTransferDataFlavors() {
89             return flavors;
90         }
91
92         public boolean isDataFlavorSupported(DataFlavor JavaDoc flavor) {
93             for (int i = 0; i < flavors.length; i++) {
94                 if (flavors[i] == flavor) {
95                     return true;
96                 }
97             }
98             return false;
99         }
100
101         public Object JavaDoc getTransferData(DataFlavor JavaDoc flavor)
102             throws UnsupportedFlavorException JavaDoc, IOException JavaDoc
103         {
104             if ("x-form-metacomponent".equals(flavor.getSubType())) // NOI18N
105
return radComponent;
106
107             throw new UnsupportedFlavorException JavaDoc(flavor);
108         }
109     }
110
111     // -----------
112

113     /** Checks whether a component can be moved to a container (the component
114      * cannot be pasted to its own sub-container or even to itself). */

115     public static boolean canPasteCut(RADComponent sourceComponent,
116                                       FormModel targetForm,
117                                       RADComponent targetComponent)
118     {
119         if (!sourceComponent.isInModel())
120             return false;
121         if (sourceComponent.getFormModel() != targetForm)
122             return true;
123
124         if (targetComponent == null)
125             return targetForm.getModelContainer().getIndexOf(sourceComponent) < 0;
126
127         return sourceComponent != targetComponent
128                && sourceComponent.getParentComponent() != targetComponent
129                && !sourceComponent.isParentComponent(targetComponent);
130     }
131
132     // -----------
133

134     /** Paste type for meta components.
135      */

136     static class RADPaste extends PasteType implements Mutex.ExceptionAction {
137         private Transferable JavaDoc transferable;
138         private FormModel targetForm;
139         private RADComponent targetComponent;
140
141         public RADPaste(Transferable JavaDoc t,
142                         FormModel targetForm,
143                         RADComponent targetComponent)
144         {
145             this.transferable = t;
146             this.targetForm = targetForm;
147             this.targetComponent = targetComponent;
148         }
149
150         public String JavaDoc getName() {
151             return FormUtils.getBundleString(isComponentCut() ?
152                                              "CTL_CutPaste" : "CTL_CopyPaste"); // NOI18N
153
}
154
155         public Transferable JavaDoc paste() throws IOException JavaDoc {
156             if (java.awt.EventQueue.isDispatchThread())
157                 return doPaste();
158             else { // reinvoke synchronously in AWT thread
159
try {
160                     return (Transferable JavaDoc) Mutex.EVENT.readAccess(this);
161                 }
162                 catch (MutexException ex) {
163                     Exception JavaDoc e = ex.getException();
164                     if (e instanceof IOException JavaDoc)
165                         throw (IOException JavaDoc) e;
166                     else { // should not happen, ignore
167
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
168                         return ExTransferable.EMPTY;
169                     }
170                 }
171             }
172         }
173
174         public Object JavaDoc run() throws Exception JavaDoc {
175             return doPaste();
176         }
177
178         private Transferable JavaDoc doPaste() throws IOException JavaDoc {
179             boolean fromCut = isComponentCut();
180             RADComponent sourceComponent = getSourceComponent(fromCut);
181
182             if (sourceComponent == null)
183                 return null;
184
185             if (!fromCut || sourceComponent.getCodeExpression() == null) {
186                 // pasting copy of RADComponent
187
targetForm.getComponentCreator()
188                               .copyComponent(sourceComponent, targetComponent);
189                 return null;
190 // return new RADTransferable(getComponentCopyFalvor(),
191
// sourceComponent);
192
}
193
194             // pasting cut
195
FormModel sourceForm = sourceComponent.getFormModel();
196             if (sourceForm != targetForm
197                 || (targetComponent != null
198                     && !sourceComponent.getClass().isAssignableFrom(
199                                          targetComponent.getClass())))
200             { // cut from another form or pasting to an incompatible container
201
if (targetForm.getComponentCreator()
202                                 .copyComponent(sourceComponent, targetComponent)
203                     != null)
204                 {
205                     Node sourceNode = sourceComponent.getNodeReference();
206                     // delete component in the source form
207
if (sourceNode != null)
208                         sourceNode.destroy();
209                     else throw new IllegalStateException JavaDoc();
210                 }
211                 else return null; // paste not performed
212
}
213             else { // moving component within the same form
214
if (!canPasteCut(sourceComponent, targetForm, targetComponent)
215                     || !MetaComponentCreator.canAddComponent(
216                                                sourceComponent.getBeanClass(),
217                                                targetComponent))
218                     return null; // not allowed, ignore paste
219

220                 sourceForm.startCompoundEdit(true);
221                 boolean resetConstraintProperties = false;
222                 LayoutModel layoutModel = sourceForm.getLayoutModel();
223                 LayoutComponent layoutComponent = null;
224                 if (layoutModel != null) {
225                     layoutComponent = layoutModel.getLayoutComponent(sourceComponent.getId());
226                     if (layoutComponent != null) {
227                         resetConstraintProperties = true;
228                         Object JavaDoc layoutUndoMark = layoutModel.getChangeMark();
229                         javax.swing.undo.UndoableEdit JavaDoc ue = layoutModel.getUndoableEdit();
230                         boolean autoUndo = true;
231                         boolean fromModel = (!(targetComponent instanceof RADVisualContainer)
232                                             || ((RADVisualContainer)targetComponent).getLayoutSupport() != null)
233                                             && !layoutComponent.isLayoutContainer();
234                         try {
235                             layoutModel.removeComponent(sourceComponent.getId(), fromModel);
236                             autoUndo = false;
237                         } finally {
238                             if (!layoutUndoMark.equals(layoutModel.getChangeMark())) {
239                                 sourceForm.addUndoableEdit(ue);
240                             }
241                             if (autoUndo) {
242                                 sourceForm.forceUndoOfCompoundEdit();
243                             }
244                         }
245                     }
246                 }
247                 
248                 // remove source component from its parent
249
sourceForm.removeComponent(sourceComponent, false);
250
251                 if (sourceComponent instanceof RADVisualComponent
252                     && targetComponent instanceof RADVisualContainer)
253                 {
254                     RADVisualComponent visualComp = (RADVisualComponent) sourceComponent;
255                     RADVisualContainer visualCont = (RADVisualContainer) targetComponent;
256
257                     if (visualCont.getLayoutSupport() == null) {
258                         targetForm.addComponent(visualComp, visualCont, false);
259                         LayoutComponent parent = layoutModel.getLayoutComponent(visualCont.getId());
260                         Object JavaDoc layoutUndoMark = layoutModel.getChangeMark();
261                         javax.swing.undo.UndoableEdit JavaDoc ue = layoutModel.getUndoableEdit();
262                         boolean autoUndo = true;
263                         if (layoutComponent == null) {
264                             layoutComponent = new LayoutComponent(visualComp.getId(),
265                                 MetaComponentCreator.shouldBeLayoutContainer(visualComp));
266                         }
267                         resetConstraintProperties = true;
268                         try {
269                             layoutModel.addNewComponent(layoutComponent, parent, null);
270                             autoUndo = false;
271                         } finally {
272                             if (!layoutUndoMark.equals(layoutModel.getChangeMark())) {
273                                 sourceForm.addUndoableEdit(ue);
274                             }
275                             if (autoUndo) {
276                                 sourceForm.forceUndoOfCompoundEdit();
277                             }
278                         }
279                     }
280                     else {
281                         try {
282                             targetForm.addVisualComponent(visualComp, visualCont,
283                                     visualCont.getLayoutSupport().getStoredConstraints(visualComp),
284                                     false);
285                         }
286                         catch (RuntimeException JavaDoc ex) {
287                             // layout support does not accept the component
288
org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
289                             return transferable;
290                         }
291                     }
292                 }
293                 else {
294                     ComponentContainer targetContainer =
295                         targetComponent instanceof ComponentContainer ?
296                             (ComponentContainer) targetComponent : null;
297
298                     // add the component to the target container
299
targetForm.addComponent(sourceComponent, targetContainer, false);
300                 }
301                 if (resetConstraintProperties) {
302                     ((RADVisualComponent)sourceComponent).resetConstraintsProperties();
303                 }
304             }
305
306             return ExTransferable.EMPTY;
307         }
308
309         boolean isComponentCut() {
310             return transferable.isDataFlavorSupported(getComponentCutFlavor());
311         }
312
313         RADComponent getSourceComponent(boolean fromCut) throws IOException JavaDoc {
314             RADComponent sourceComponent = null;
315             try {
316                 Object JavaDoc obj = transferable.getTransferData(
317                                fromCut ? getComponentCutFlavor() :
318                                          getComponentCopyFlavor());
319                 if (obj instanceof RADComponent)
320                     sourceComponent = (RADComponent) obj;
321             }
322             catch (UnsupportedFlavorException JavaDoc e) { // ignore - should not happen
323
}
324
325             return sourceComponent;
326         }
327     }
328
329     // ------------
330

331     /** Paste type for a class (java node).
332      */

333     static class ClassPaste extends PasteType implements Mutex.ExceptionAction {
334
335         private Transferable JavaDoc transferable;
336         private ClassSource classSource;
337         private FormModel targetForm;
338         private RADComponent targetComponent; // may be null if pasting to Other Components
339

340         public ClassPaste(Transferable JavaDoc t,
341                           ClassSource classSource,
342                           FormModel targetForm,
343                           RADComponent targetComponent)
344         {
345             this.transferable = t;
346             this.classSource = classSource;
347             this.targetForm = targetForm;
348             this.targetComponent = targetComponent;
349         }
350
351         public Transferable JavaDoc paste() throws IOException JavaDoc {
352             if (java.awt.EventQueue.isDispatchThread()) {
353                 return doPaste();
354             }
355             else { // reinvoke synchronously in AWT thread
356
try {
357                     return (Transferable JavaDoc) Mutex.EVENT.readAccess(this);
358                 }
359                 catch (MutexException ex) {
360                     Exception JavaDoc e = ex.getException();
361                     if (e instanceof IOException JavaDoc)
362                         throw (IOException JavaDoc) e;
363                     else { // should not happen, ignore
364
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
365                         return transferable;
366                     }
367                 }
368             }
369         }
370
371         public Object JavaDoc run() throws Exception JavaDoc {
372             return doPaste();
373         }
374
375         private Transferable JavaDoc doPaste() throws IOException JavaDoc {
376             if ((classSource.getClassName().indexOf('.') == -1) // Issue 79573
377
&& !FormJavaSource.isInDefaultPackage(targetForm)) {
378                 String JavaDoc message = FormUtils.getBundleString("MSG_DefaultPackageBean"); // NOI18N
379
NotifyDescriptor nd = new NotifyDescriptor.Message(message, NotifyDescriptor.WARNING_MESSAGE);
380                 DialogDisplayer.getDefault().notify(nd);
381             } else {
382                 targetForm.getComponentCreator().createComponent(
383                                         classSource, targetComponent, null);
384             }
385             return transferable;
386         }
387     }
388
389     static String JavaDoc getCopiedBeanClassName(final FileObject fo) {
390         return BeanInstaller.findJavaBeanName(fo);
391     }
392
393     static ClassSource getCopiedBeanClassSource(Transferable JavaDoc t) {
394         DataObject dobj = (DataObject)
395             NodeTransfer.cookie(t, NodeTransfer.COPY, DataObject.class);
396         FileObject fo = dobj != null ? dobj.getPrimaryFile() : null;
397         if (fo == null)
398             return null;
399
400         String JavaDoc clsName = getCopiedBeanClassName(fo);
401         if (clsName == null)
402             return null;
403
404         return ClassPathUtils.getProjectClassSource(fo, clsName);
405     }
406
407 }
408
Popular Tags