KickJava   Java API By Example, From Geeks To Geeks.

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


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.*;
23 import javax.swing.*;
24 import java.util.*;
25
26 import org.openide.ErrorManager;
27
28 import org.netbeans.modules.form.fakepeer.FakePeerSupport;
29 import org.netbeans.modules.form.layoutsupport.*;
30 //import org.netbeans.modules.form.layoutdesign.LayoutDesigner.VisualMapper;
31
import org.netbeans.modules.form.layoutdesign.support.SwingLayoutBuilder;
32
33 /**
34  * This class replicates (clones) the reference instances from meta-components
35  * of a form. This way an equal and independent hierarchy of real instances is
36  * built. Components cloned this way are used in the ComponentLayer presenting
37  * the form in designer, or by the TestAction. Thanks to mapping from meta
38  * components to clones (and viceversa), effective incremental updates of
39  * changes from metadata are possible.
40  * Note: After updating replicated components, revalidate() and repaint()
41  * should be called on the top component.
42  *
43  * @author Tomas Pavek
44  */

45
46 public class VisualReplicator { //implements VisualMapper
47

48 // Object topClonedComponent;
49
private RADVisualComponent topMetaComponent;
50
51     private Map idToClone = new HashMap();
52     private Map cloneToId = new HashMap();
53
54     private Map layoutBuilders = new HashMap();
55
56     private int designRestrictions;
57
58     // design restrictions flags
59
static final int ATTACH_FAKE_PEERS = 1;
60     static final int DISABLE_FOCUSING = 2;
61
62     // restrictions
63
private Class JavaDoc requiredTopClass;
64     private Class JavaDoc[] forbiddenClasses;
65
66     // ---------
67

68     public VisualReplicator() {
69     }
70
71     public VisualReplicator(Class JavaDoc requiredClass,
72                             Class JavaDoc[] forbiddenClasses,
73                             int designRestrictions)
74     {
75         setRequiredTopVisualClass(requiredClass);
76         setForbiddenTopVisualClasses(forbiddenClasses);
77         setDesignRestrictions(designRestrictions);
78 // this.layoutBuilder = layoutBuilder;
79
}
80
81     // ---------
82
// mapping
83

84     public Object JavaDoc getClonedComponent(RADComponent metacomponent) {
85         return idToClone.get(metacomponent.getId());
86     }
87
88     public Object JavaDoc getClonedComponent(String JavaDoc id) {
89         return idToClone.get(id);
90     }
91
92     public String JavaDoc getClonedComponentId(Object JavaDoc component) {
93         return (String JavaDoc) cloneToId.get(component);
94     }
95
96     // ---------
97

98     private FormModel getFormModel() {
99         return getTopMetaComponent().getFormModel();
100     }
101
102     SwingLayoutBuilder getLayoutBuilder(String JavaDoc containerId) {
103         SwingLayoutBuilder builder = (SwingLayoutBuilder) layoutBuilders.get(containerId);
104         if (builder == null) {
105             RADVisualContainer metacont = (RADVisualContainer)
106                 getFormModel().getMetaComponent(containerId);
107             Container cont = (Container) getClonedComponent(containerId);
108             Container contDelegate = metacont.getContainerDelegate(cont);
109
110             builder = new SwingLayoutBuilder(getFormModel().getLayoutModel(),
111                                              contDelegate, containerId,
112                                              getDesignRestrictions() != 0);
113             layoutBuilders.put(containerId, builder);
114         }
115         return builder;
116     }
117
118     // ---------
119
// getters & setters
120

121 // public Object getTopClonedComponent() {
122
// return topClonedComponent;
123
// }
124

125     public RADVisualComponent getTopMetaComponent() {
126         return topMetaComponent;
127     }
128
129     public void setTopMetaComponent(RADVisualComponent metacomponent) {
130 // topClonedComponent = null;
131
topMetaComponent = metacomponent;
132         idToClone.clear();
133         cloneToId.clear();
134         layoutBuilders.clear();
135     }
136
137     public int getDesignRestrictions() {
138         return designRestrictions;
139     }
140
141     public void setDesignRestrictions(int restrictions) {
142         designRestrictions = restrictions;
143     }
144
145     public Class JavaDoc getRequiredTopVisualClass() {
146         return requiredTopClass;
147     }
148
149     public void setRequiredTopVisualClass(Class JavaDoc requiredClass) {
150         requiredTopClass = requiredClass;
151     }
152
153     public Class JavaDoc[] getForbiddenTopVisualClasses() {
154         return forbiddenClasses;
155     }
156
157     public void setForbiddenTopVisualClasses(Class JavaDoc[] forbiddenClasses) {
158         this.forbiddenClasses = forbiddenClasses;
159     }
160
161     // --------
162
// executive public methods
163

164     public Object JavaDoc createClone() {
165         return createClone(getTopMetaComponent());
166     }
167
168     public Object JavaDoc createClone(RADComponent metacomp) {
169         if (metacomp == null)
170             return null;
171
172         Object JavaDoc clone;
173         ArrayList relativeProperties = new ArrayList();
174
175         try {
176             // clone the whole visual hierarchy recursively
177
clone = cloneComponent(metacomp, relativeProperties);
178
179             // set relative properties additionally
180
if (!relativeProperties.isEmpty())
181                 copyRelativeProperties(relativeProperties);
182         }
183         catch (Exception JavaDoc ex) {
184             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
185             clone = null;
186         }
187
188         return clone;
189     }
190
191     public void reorderComponents(ComponentContainer metacont) {
192         if (metacont instanceof RADVisualContainer) {
193             updateContainerLayout((RADVisualContainer) metacont);
194         }
195         else if (metacont instanceof RADMenuComponent) {
196             Container cont = (Container) getClonedComponent((RADComponent)metacont);
197             if (cont == null) // should not happen
198
return;
199
200             cont.removeAll();
201
202             RADComponent[] metacomps = ((RADMenuComponent)metacont).getSubBeans();
203             for (int i = 0; i < metacomps.length; i++) {
204                 addToMenu(cont, getClonedComponent(metacomps[i]));
205             }
206         }
207     }
208
209     public void updateContainerLayout(RADVisualContainer metacont) {
210         Container cont = (Container) getClonedComponent(metacont);
211         if (cont == null) // The container is not cloned by the replicator
212
return; // see issue 63654
213
Container contDelegate = metacont.getContainerDelegate(cont);
214         LayoutSupportManager laysup = metacont.getLayoutSupport();
215         SwingLayoutBuilder layoutBuilder;
216
217         // clear the container first before setting/changing the layout
218
if (laysup != null) { // old layout support
219
layoutBuilder = null;
220             layoutBuilders.remove(metacont.getId());
221             laysup.clearContainer(cont, contDelegate);
222         }
223         else { // new layout support
224
layoutBuilder = getLayoutBuilder(metacont.getId());
225             layoutBuilder.clearContainer();
226         }
227
228         // update visual components
229
RADVisualComponent[] metacomps = metacont.getSubComponents();
230         Component[] comps = new Component[metacomps.length];
231         String JavaDoc[] compIds = new String JavaDoc[metacomps.length];
232
233         for (int i = 0; i < metacomps.length; i++) {
234             RADVisualComponent metacomp = metacomps[i];
235
236             Component comp = (Component) getClonedComponent(metacomp);
237             if (comp == null)
238                 comp = (Component) createClone(metacomp);
239             else {
240                 if (comp.getParent() != null)
241                     comp.getParent().remove(comp);
242             }
243
244             // make the component visible, but preserve explicit or original visibility
245
Boolean JavaDoc visible = null;
246             FormProperty visibilityProp = metacomp.getBeanProperty("visible"); // NOI18N
247
if (visibilityProp != null && visibilityProp.isChanged()) {
248                 Object JavaDoc value;
249                 try {
250                     value = visibilityProp.getRealValue();
251                 } catch (Exception JavaDoc ex) { // should not happen
252
value = null;
253                 }
254                 if (value instanceof Boolean JavaDoc)
255                     visible = (Boolean JavaDoc) value;
256             }
257             if (visible == null) {
258                 Component defaultComp = (Component) BeanSupport.getDefaultInstance(comp.getClass());
259                 if (defaultComp != null)
260                     visible = defaultComp.isVisible() ? Boolean.TRUE : Boolean.FALSE;
261             }
262             if (visible != null) {
263                 comp.setVisible(visible.booleanValue());
264             }
265
266             // re-attach fake peer
267
FakePeerSupport.attachFakePeer(comp);
268             if (comp instanceof Container)
269                 FakePeerSupport.attachFakePeerRecursively((Container)comp);
270
271             comps[i] = comp;
272             compIds[i] = metacomp.getId();
273         }
274
275         // set the layout and re-add the components
276
if (laysup != null) { // old layout support
277
laysup.setLayoutToContainer(cont, contDelegate);
278             if (comps.length > 0)
279                 laysup.addComponentsToContainer(cont, contDelegate, comps, 0);
280             laysup.arrangeContainer(cont, contDelegate);
281         }
282         else { // new layout support
283
// Re-attach fake peers
284
contDelegate.removeAll();
285             for (int i=0; i<comps.length; i++) {
286                 FakePeerSupport.attachFakePeer(comps[i]);
287                 if (comps[i] instanceof Container)
288                     FakePeerSupport.attachFakePeerRecursively((Container)comps[i]);
289             }
290
291             setupContainerLayout(layoutBuilder, comps, compIds);
292         }
293     }
294
295     public void updateAddedComponents(ComponentContainer metacont) {
296         Container container = null;
297         if (metacont instanceof RADComponent) {
298             Object JavaDoc contClone = getClonedComponent((RADComponent)metacont);
299             if (contClone instanceof Container) {
300                 if (metacont instanceof RADVisualContainer) {
301                     RADVisualContainer visualMetaCont = (RADVisualContainer)metacont;
302                     if (visualMetaCont.getLayoutSupport() == null) {
303                         // don't try incremental update with new layout support
304
updateContainerLayout(visualMetaCont);
305                         //return;
306
}
307                     container = visualMetaCont.getContainerDelegate((Container)contClone);
308                 }
309                 else container = (Container)contClone;
310             }
311         }
312
313         RADComponent[] subComps = metacont.getSubBeans();
314         for (int i=0; i < subComps.length; i++) {
315             Object JavaDoc compClone = getClonedComponent(subComps[i]);
316             if (compClone == null)
317                 addComponent(subComps[i]);
318             else if (compClone instanceof Component) {
319                 Container cloneCont = ((Component)compClone).getParent();
320                 if (cloneCont != container && cloneToId.get(cloneCont) != null)
321                     return; // the clone is placed in another container in
322
} // replicator, there's going to be another update
323
}
324     }
325
326     // for adding just one component, for adding more components use
327
// updateAddedComponents
328
public void addComponent(RADComponent metacomp) {
329         if (metacomp == null)
330             return;
331         if (getClonedComponent(metacomp) != null)
332             return;
333
334         if (metacomp instanceof RADVisualComponent) {
335             Object JavaDoc clone = createClone(metacomp);
336             if (!(clone instanceof Component))
337                 return;
338
339             RADVisualContainer metacont = (RADVisualContainer)
340                                           metacomp.getParentComponent();
341             LayoutSupportManager laysup = metacont.getLayoutSupport();
342
343             if (laysup != null) { // old layout support
344
Container cont = (Container) getClonedComponent(metacont);
345                 if (cont == null) return;
346                 Container contDelegate = metacont.getContainerDelegate(cont);
347                 laysup.addComponentsToContainer(
348                         cont,
349                         contDelegate,
350                         new Component[] { (Component) clone },
351                         ((RADVisualComponent)metacomp).getComponentIndex());
352                 laysup.arrangeContainer(cont, contDelegate);
353             }
354 // else { // new layout support
355
// getLayoutBuilder(metacont.getId()).addComponentsToContainer(
356
// new Component[] { (Component) clone },
357
// new String[] { metacomp.getId() } );
358
// }
359
}
360         else if (metacomp instanceof RADMenuItemComponent) {
361             Object JavaDoc clone = createClone(metacomp);
362
363             RADComponent menuCont = metacomp.getParentComponent();
364             if (menuCont == null)
365                 return; // should not happen
366

367             Object JavaDoc cont = getClonedComponent(menuCont);
368             if (menuCont instanceof RADVisualContainer)
369                 setContainerMenu((Container)cont, clone);
370             else
371                 addToMenu(cont, clone);
372         }
373     }
374
375     public void removeComponent(RADComponent metacomp,
376                                 ComponentContainer metacont)
377     {
378         if (metacomp == null)
379             return;
380
381         Object JavaDoc clone = getClonedComponent(metacomp);
382         if (clone == null)
383             return;
384
385         if (clone instanceof JMenuBar) { // JMenuBar meta component was removed
386
// reset JMenuBar in JRootPane
387
Container menuParent = ((Component)clone).getParent();
388             Container cont = menuParent;
389             while (cont != null && !(cont instanceof JRootPane))
390                 cont = cont.getParent();
391
392             if (cont != null)
393                 ((JRootPane)cont).setJMenuBar(null);
394             else if (menuParent != null)
395                 menuParent.remove((Component)clone);
396             else return;
397         }
398         else if (clone instanceof Component) { // visual meta component was removed
399
Component comp = (Component) clone;
400             // do we know the parent container of the removed meta component?
401
RADVisualContainer parentCont =
402                 metacont instanceof RADVisualContainer ?
403                     (RADVisualContainer) metacont : null;
404             Container cont = parentCont != null ?
405                              (Container) getClonedComponent(parentCont) : null;
406
407             if (cont == null) {
408                 // we don't know the meta container (layout support), so will
409
// just simply remove the component from its parent
410
if (comp.getParent() != null)
411                     comp.getParent().remove(comp);
412             }
413             else { // let the layout support remove the visual component
414
Container contDelegate = parentCont.getContainerDelegate(cont);
415                 LayoutSupportManager laysup = parentCont.getLayoutSupport();
416                 if (laysup != null) { // old layout support
417
if (!laysup.removeComponentFromContainer(
418                                     cont, contDelegate, comp))
419                     { // layout delegate cannot remove individual components,
420
// we must clear the container and add the components again
421
laysup.clearContainer(cont, contDelegate);
422
423                         RADVisualComponent[] metacomps = parentCont.getSubComponents();
424                         if (metacomps.length > 0) {
425                             // we assume the metacomponent is already removed
426
Component[] comps = new Component[metacomps.length];
427                             for (int i=0; i < metacomps.length; i++) {
428                                 comp = (Component) getClonedComponent(metacomps[i]);
429                                 // becaues the components were removed, we must
430
// re-attach their fake peers (if needed)
431
FakePeerSupport.attachFakePeer(comp);
432                                 if (comp instanceof Container)
433                                     FakePeerSupport.attachFakePeerRecursively(
434                                                                (Container)comp);
435                                 comps[i] = comp;
436                             }
437                             laysup.addComponentsToContainer(cont, contDelegate, comps, 0);
438                         }
439                     }
440                 }
441                 else { // new layout support
442
// Re-attach fake peers
443
contDelegate.removeAll();
444                     RADVisualComponent[] metacomps = parentCont.getSubComponents();
445                     for (int i=0; i<metacomps.length; i++) {
446                         Component component = (Component)getClonedComponent(metacomps[i]);
447                         FakePeerSupport.attachFakePeer(component);
448                         if (component instanceof Container)
449                             FakePeerSupport.attachFakePeerRecursively((Container)component);
450                     }
451
452                     getLayoutBuilder(parentCont.getId()).removeComponentsFromContainer(
453                         new Component[] { comp },
454                         new String JavaDoc[] { metacomp.getId() } );
455                 }
456             }
457         }
458         else if (clone instanceof MenuComponent) { // AWT menu
459
MenuComponent menuComp = (MenuComponent) clone;
460             MenuContainer menuCont = menuComp.getParent();
461             if (menuCont != null)
462                 menuCont.remove(menuComp);
463             else return;
464         }
465
466         removeMapping(metacomp);
467     }
468
469     public void updateComponentProperty(RADProperty property) {
470         if (property == null)
471             return;
472
473         RADComponent metacomp = property.getRADComponent();
474
475         // target component of the property
476
Object JavaDoc targetComp = getClonedComponent(metacomp);
477         if (targetComp == null)
478             return;
479
480         // Scrollbar hack - to change some properties of AWT Scrollbar we
481
// must create a new instance of Scrollbar (peer must be recreated)
482
// [maybe this should be done for all AWT components]
483
if (targetComp instanceof java.awt.Scrollbar JavaDoc) {
484             // remove the component and add a new clone
485
removeComponent(metacomp, null);
486             addComponent(metacomp);
487             return;
488         }
489
490         // keep double buffering turned off for JComponent in fake peer container
491
// and also keep debugGraphicsOptions turned off
492
if (targetComp instanceof JComponent
493             && (getDesignRestrictions() & ATTACH_FAKE_PEERS) != 0
494             && (("doubleBuffered".equals(property.getName()) // NOI18N
495
&& hasAwtParent(metacomp))
496               || "debugGraphicsOptions".equals(property.getName()))) // NOI18N
497
return;
498
499         // Mnemonics support - start -
500
if ("text".equals(property.getName()) // NOI18N
501
&& (targetComp instanceof AbstractButton
502                 || targetComp instanceof JLabel)
503             && JavaCodeGenerator.isUsingMnemonics(property.getRADComponent()))
504         {
505             try {
506                 String JavaDoc str = (String JavaDoc) property.getRealValue();
507                 if (targetComp instanceof JLabel)
508                     org.openide.awt.Mnemonics.setLocalizedText(
509                                                 (JLabel)targetComp, str);
510                 else
511                     org.openide.awt.Mnemonics.setLocalizedText(
512                                                 (AbstractButton)targetComp, str);
513                 return;
514             }
515             catch (Exception JavaDoc ex) {} // ignore and continue
516
}
517         // Mnemonics support - end -
518

519         java.lang.reflect.Method JavaDoc writeMethod =
520             property.getPropertyDescriptor().getWriteMethod();
521         if (writeMethod == null)
522             return;
523
524         if (!writeMethod.getDeclaringClass().isAssignableFrom(
525                                                targetComp.getClass()))
526         { // try to use same method of different (target) class
527
try {
528                 writeMethod = targetComp.getClass().getMethod(
529                                   writeMethod.getName(),
530                                   writeMethod.getParameterTypes());
531             }
532             catch (Exception JavaDoc ex) { // ignore
533
return;
534             }
535         }
536
537         try {
538             Object JavaDoc value = property.getValue();
539             
540             if (value instanceof RADComponent.ComponentReference) {
541                 value = ((RADComponent.ComponentReference)value).getComponent();
542             }
543             
544             if (value instanceof RADConnectionPropertyEditor.RADConnectionDesignValue
545                 && (((RADConnectionPropertyEditor.RADConnectionDesignValue)value).type
546                 == RADConnectionPropertyEditor.RADConnectionDesignValue.TYPE_BEAN)) {
547                 value = ((RADConnectionPropertyEditor.RADConnectionDesignValue)value).getRADComponent();
548             }
549
550             if (value instanceof RADComponent) {
551                 // the value is another component (relative property )
552
Object JavaDoc propertyComp =
553                     getClonedComponent((RADComponent)value);
554                 if (propertyComp == null) // there's no cloned instance yet
555
propertyComp = createClone((RADComponent)value);
556
557                 value = propertyComp;
558             }
559             else {
560                 value = property.getRealValue();
561                 
562                 if (value == FormDesignValue.IGNORED_VALUE)
563                     return; // ignore the value, as it is not a real value
564

565                 value = FormUtils.cloneObject(value, property.getPropertyContext().getFormModel());
566             }
567
568             writeMethod.invoke(targetComp, new Object JavaDoc[] { value });
569
570             if (targetComp instanceof Component)
571                 ((Component)targetComp).invalidate();
572         }
573         catch (Exception JavaDoc ex) {
574             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
575         }
576     }
577
578     // ---------
579
// executive private methods
580

581     // recursive method
582
private Object JavaDoc cloneComponent(RADComponent metacomp,
583                                   java.util.List JavaDoc relativeProperties)
584         throws Exception JavaDoc
585     {
586         Object JavaDoc clone; // mapped clone instance
587
Object JavaDoc compClone = null; // clone of the component, might appear under 'clone'
588

589         if (needsConversion(metacomp)) { // clone with conversion
590
clone = cloneComponentWithConversion(
591                     metacomp,
592                     metacomp == getTopMetaComponent() ? requiredTopClass : null,
593                     relativeProperties);
594
595             if (clone instanceof RootPaneContainer
596                 && !(metacomp.getBeanInstance() instanceof RootPaneContainer))
597             { // the cloned component was put to the content pane
598
compClone = ((RootPaneContainer)clone).getContentPane().getComponent(0);
599             }
600         }
601         else if ("java.awt.ScrollPane".equals(metacomp.getBeanClass().getName()) // NOI18N
602
&& ((getDesignRestrictions() & ATTACH_FAKE_PEERS) != 0)
603             && (System.getProperty("java.version").startsWith("1.4"))) // NOI18N
604
{ // Issue 36629 - ScrollPane attempts to place
605
// components with a lightweight peer into a Panel
606
clone = new java.awt.ScrollPane JavaDoc() {
607                         public void addNotify() {
608                             if (getComponentCount()>0) {
609                                 Component comp = getComponent(0);
610                                 remove(0);
611                                 super.addNotify();
612                                 FakePeerSupport.attachFakePeer(comp);
613                                 add(comp);
614                             }
615                         }
616                     };
617         }
618         else { // just clone the bean
619
clone = metacomp.cloneBeanInstance(relativeProperties);
620         }
621
622         if (clone == null)
623             return null;
624
625         if (compClone == null)
626             compClone = clone;
627
628         idToClone.put(metacomp.getId(), compClone);
629         cloneToId.put(compClone, metacomp.getId());
630
631         if (compClone instanceof java.beans.DesignMode JavaDoc)
632             ((java.beans.DesignMode JavaDoc)compClone).setDesignTime(
633                                                  getDesignRestrictions() != 0);
634
635         if (metacomp instanceof RADVisualContainer) {
636             RADVisualContainer metacont = (RADVisualContainer) metacomp;
637             final Container cont = (Container) compClone;
638             final Container contDelegate = metacont.getContainerDelegate(cont);
639
640             // clone menu
641
if (metacont.getContainerMenu() != null) {
642                 Object JavaDoc menu = cloneComponent(metacont.getContainerMenu(),
643                                              relativeProperties);
644                 setContainerMenu(cont, menu);
645             }
646
647             // clone subcomponents
648
RADVisualComponent[] metacomps = metacont.getSubComponents();
649             final Component[] comps = new Component[metacomps.length];
650             String JavaDoc[] compIds = new String JavaDoc[metacomps.length];
651             for (int i=0; i < metacomps.length; i++) {
652                 comps[i] = (Component) cloneComponent(metacomps[i],
653                                                       relativeProperties);
654                 compIds[i] = metacomps[i].getId();
655             }
656
657             // set layout
658
final LayoutSupportManager laysup = metacont.getLayoutSupport();
659             if (laysup != null) { // old layout support
660
laysup.setLayoutToContainer(cont, contDelegate);
661                 if (comps.length > 0) { // add cloned subcomponents to container
662
if (!(cont instanceof JToolBar))
663                         laysup.addComponentsToContainer(cont, contDelegate, comps, 0);
664                     else { // a L&F workaround for JToolBar (MetalToobarUI)
665
SwingUtilities.invokeLater(new Runnable JavaDoc() {
666                             public void run() {
667                                 laysup.addComponentsToContainer(cont, contDelegate,
668                                                                 comps, 0);
669                             }
670                         });
671                     }
672                 }
673                 laysup.arrangeContainer(cont, contDelegate);
674             }
675             else { // new layout support
676
setupContainerLayout(getLayoutBuilder(metacont.getId()), comps, compIds);
677             }
678         }
679         else if (metacomp instanceof RADMenuComponent) {
680             RADComponent[] metacomps = ((RADMenuComponent)metacomp).getSubBeans();
681             for (int i = 0; i < metacomps.length; i++) {
682                 Object JavaDoc menuItem = cloneComponent(
683                         (RADMenuItemComponent)metacomps[i], relativeProperties);
684                 addToMenu(compClone, menuItem);
685             }
686         }
687
688         if (clone instanceof Component) {
689             int restrictions = getDesignRestrictions();
690             if ((restrictions & ATTACH_FAKE_PEERS) != 0) {
691                 FakePeerSupport.attachFakePeer((Component)clone);
692                 if (clone instanceof Container)
693                     FakePeerSupport.attachFakePeerRecursively((Container)clone);
694
695                 if (clone instanceof JComponent) {
696                     // turn off double buffering for JComponent in fake peer container
697
if (hasAwtParent(metacomp))
698                         setDoubleBufferedRecursively((JComponent)clone, false);
699                     // make sure debug graphics options is turned off
700
((JComponent)clone).setDebugGraphicsOptions(
701                                             DebugGraphics.NONE_OPTION);
702                 }
703             }
704
705             if ((restrictions & DISABLE_FOCUSING) != 0) {
706                 disableFocusing((Component)clone);
707
708                 // patch for JDK 1.4 - hide glass pane of JInternalFrame
709
if (clone instanceof JInternalFrame)
710                     ((JInternalFrame)clone).getGlassPane().setVisible(false);
711             }
712         }
713
714         // Mnemonics support - start -
715
if ((clone instanceof AbstractButton || clone instanceof JLabel)
716             && JavaCodeGenerator.isUsingMnemonics(metacomp))
717         {
718             FormProperty prop = metacomp.getBeanProperty("text"); // NOI18N
719
if (prop != null && prop.isChanged()) {
720                 try {
721                     String JavaDoc str = (String JavaDoc) prop.getRealValue();
722                     if (clone instanceof JLabel)
723                         org.openide.awt.Mnemonics.setLocalizedText(
724                                                     (JLabel)clone, str);
725                     else
726                         org.openide.awt.Mnemonics.setLocalizedText(
727                                                     (AbstractButton)clone, str);
728                 }
729                 catch (Exception JavaDoc ex) {} // ignore
730
}
731         }
732         // Mnemonics support - end -
733

734         return clone;
735     }
736     
737     private void setupContainerLayout(SwingLayoutBuilder layoutBuilder, Component[] comps, String JavaDoc[] compIds) {
738         Throwable JavaDoc th = null;
739         try {
740             layoutBuilder.setupContainerLayout(comps, compIds);
741         } catch (Exception JavaDoc ex) {
742             th = ex;
743         } catch (Error JavaDoc err) {
744             th = err;
745         }
746         if (th != null) {
747             ErrorManager.getDefault().notify(th);
748             getFormModel().forceUndoOfCompoundEdit();
749         }
750     }
751
752     private boolean needsConversion(RADComponent metacomp) {
753         Class JavaDoc beanClass = metacomp.getBeanClass();
754
755         if (forbiddenClasses != null) {
756             for (int i=0; i < forbiddenClasses.length; i++) {
757                 if (forbiddenClasses[i].isAssignableFrom(beanClass))
758                     return true;
759             }
760         }
761
762         return metacomp == getTopMetaComponent()
763                && requiredTopClass != null
764                && !requiredTopClass.isAssignableFrom(beanClass);
765     }
766
767     private static void disableFocusing(Component comp) {
768         comp.setFocusable(false);
769         if (comp instanceof Container) {
770             Container cont = (Container) comp;
771             for (int i=0, n=cont.getComponentCount(); i < n; i++)
772                 disableFocusing(cont.getComponent(i));
773         }
774     }
775
776     private static void setContainerMenu(Container cont,
777                                          Object JavaDoc menu) {
778         if (cont instanceof RootPaneContainer) {
779             if (menu instanceof JMenuBar)
780                 ((RootPaneContainer)cont).getRootPane()
781                                             .setJMenuBar((JMenuBar)menu);
782         }
783         else if (cont instanceof JRootPane) {
784             if (menu instanceof JMenuBar)
785                 ((JRootPane)cont).setJMenuBar((JMenuBar)menu);
786         }
787         else if (cont instanceof Frame) {
788             if (menu instanceof MenuBar)
789                 ((Frame)cont).setMenuBar((MenuBar)menu);
790         }
791     }
792
793     private static void addToMenu(Object JavaDoc menu, Object JavaDoc menuItem) {
794         if (menu instanceof JMenuBar) {
795             ((JMenuBar)menu).add((JMenu)menuItem);
796         }
797         else if (menu instanceof JMenu) {
798             if (menuItem instanceof JMenuItem)
799                 ((JMenu)menu).add((JMenuItem)menuItem);
800             else
801                 ((JMenu)menu).addSeparator();
802         }
803         else if (menu instanceof MenuBar) {
804             ((MenuBar)menu).add((Menu)menuItem);
805         }
806         else if (menu instanceof Menu) {
807             if (menuItem instanceof MenuItem)
808                 ((Menu)menu).add((MenuItem)menuItem);
809             else
810                 ((Menu)menu).addSeparator();
811         }
812     }
813
814     // Special non-recursive method for cloning a component with conversion
815
// to another class (e.g. JFrame -> JPanel).
816
private static Component cloneComponentWithConversion(
817                                         RADComponent metacomp,
818                                         Class JavaDoc requiredClass,
819                                         java.util.List JavaDoc relativeProperties)
820     throws Exception JavaDoc {
821         Class JavaDoc beanClass = metacomp.getBeanClass();
822
823         if (requiredClass == null) {
824             // required class not specified, do some default conversions
825
if (RootPaneContainer.class.isAssignableFrom(beanClass)
826                     || Frame.class.isAssignableFrom(beanClass))
827                 requiredClass = JRootPane.class;
828             else if (Window.class.isAssignableFrom(beanClass)
829                      || Panel.class.isAssignableFrom(beanClass))
830                 requiredClass = Panel.class;
831             else if (Component.class.isAssignableFrom(beanClass))
832                 requiredClass = JPanel.class;
833             else if (MenuComponent.class.isAssignableFrom(beanClass))
834                 requiredClass = convertMenuClassToSwing(beanClass);
835             else
836                 requiredClass = Object JavaDoc.class;
837         }
838
839         Component component =
840             (Component) CreationFactory.createDefaultInstance(requiredClass);
841
842         if (component instanceof RootPaneContainer) {
843             if (!RootPaneContainer.class.isAssignableFrom(beanClass)
844                 && !Window.class.isAssignableFrom(beanClass) // AWT
845
&& !java.applet.Applet JavaDoc.class.isAssignableFrom(beanClass))
846             { // conversion to RootPaneContainer is required => add the
847
// clone to the content pane
848
Component clone = (Component)
849                     metacomp.cloneBeanInstance(relativeProperties);
850                 ((RootPaneContainer)component).getContentPane().add(clone);
851                 return component;
852             }
853         }
854         else if (component instanceof JRootPane) {
855             // RootPaneContainer or Frame converted to JRootPane
856
Class JavaDoc contentClass =
857                 RootPaneContainer.class.isAssignableFrom(beanClass) ?
858                     JPanel.class : Panel.class;
859             Container contentCont =
860                 (Container) CreationFactory.createDefaultInstance(contentClass);
861
862             // set the content pane
863
((JRootPane)component).setContentPane(contentCont);
864         }
865         else if (MenuItem.class.isAssignableFrom(beanClass)
866                  && JMenuItem.class.isAssignableFrom(requiredClass)) {
867             ((JMenuItem)component).setText(
868                             ((MenuItem)metacomp.getBeanInstance()).getLabel());
869             
870             ((JMenuItem)component).setFont(
871                             ((MenuItem)metacomp.getBeanInstance()).getFont());
872         }
873
874         // just try to copy all possible properties
875
FormUtils.copyPropertiesToBean(metacomp.getKnownBeanProperties(),
876                                        component,
877                                        relativeProperties);
878         return component;
879     }
880
881     // mapping of AWT menu component to a Swing equivalent
882
private static Class JavaDoc convertMenuClassToSwing(Class JavaDoc menuClass) {
883         if (MenuBar.class.isAssignableFrom(menuClass))
884             return JMenuBar.class;
885         if (PopupMenu.class.isAssignableFrom(menuClass))
886             return JPopupMenu.class;
887         if (Menu.class.isAssignableFrom(menuClass))
888             return JMenu.class;
889         if (CheckboxMenuItem.class.isAssignableFrom(menuClass))
890             return JCheckBoxMenuItem.class;
891         if (MenuItem.class.isAssignableFrom(menuClass))
892             return JMenuItem.class;
893
894         return menuClass;
895     }
896
897     private static boolean hasAwtParent(RADComponent metacomp) {
898         RADComponent parent = metacomp.getParentComponent();
899         while (parent != null) {
900             Class JavaDoc beanClass = parent.getBeanClass();
901             if (Component.class.isAssignableFrom(beanClass)
902                 && !JComponent.class.isAssignableFrom(beanClass)
903                 && !RootPaneContainer.class.isAssignableFrom(beanClass))
904             { // this is AWT component
905
return true;
906             }
907
908             parent = parent.getParentComponent();
909         }
910         return false;
911     }
912
913     private static void setDoubleBufferedRecursively(JComponent component,
914                                                      boolean value)
915     {
916         component.setDoubleBuffered(value);
917         Component[] subcomps = component.getComponents();
918         for (int i=0; i < subcomps.length; i++)
919             if (subcomps[i] instanceof JComponent)
920                 setDoubleBufferedRecursively((JComponent)subcomps[i], value);
921     }
922
923     // -------
924

925     // method for setting "relative" component properties additionaly
926
private void copyRelativeProperties(java.util.List JavaDoc relativeProperties) {
927         for (int i=0; i < relativeProperties.size(); i++) {
928             RADProperty property = (RADProperty) relativeProperties.get(i);
929             try {
930                 Object JavaDoc value = property.getValue();
931                 if (value instanceof RADComponent.ComponentReference)
932                     value =
933                         ((RADComponent.ComponentReference)value).getComponent();
934
935                 if (value instanceof RADConnectionPropertyEditor.RADConnectionDesignValue) {
936                     RADConnectionPropertyEditor.RADConnectionDesignValue connection =
937                         (RADConnectionPropertyEditor.RADConnectionDesignValue)value;
938                     assert connection.type == RADConnectionPropertyEditor.RADConnectionDesignValue.TYPE_BEAN;
939                     value = connection.getRADComponent();
940                 }
941
942                 if (value instanceof RADComponent) {
943                     // the value is another component (relative property )
944
Object JavaDoc propertyComp =
945                         getClonedComponent((RADComponent)value);
946                     if (propertyComp == null) // there's no cloned instance yet
947
propertyComp = cloneComponent((RADComponent)value,
948                                                       relativeProperties);
949
950                     // target component of the property
951
Object JavaDoc targetComp =
952                         getClonedComponent(property.getRADComponent());
953
954                     java.lang.reflect.Method JavaDoc writeMethod =
955                         property.getPropertyDescriptor().getWriteMethod();
956                     if (writeMethod != null) {
957                         writeMethod.invoke(targetComp,
958                                            new Object JavaDoc[] { propertyComp });
959                     }
960                     else if (propertyComp instanceof ButtonGroup
961                              && targetComp instanceof AbstractButton)
962                     { // special case - add button to button group
963
((ButtonGroup)propertyComp).remove((AbstractButton)targetComp);
964                         ((ButtonGroup)propertyComp).add((AbstractButton)targetComp);
965                     }
966                 }
967             }
968             catch (Exception JavaDoc ex) {} // should not happen, ignore
969
}
970     }
971
972     private void removeMapping(RADComponent metacomp) {
973         Object JavaDoc comp = idToClone.remove(metacomp.getId());
974         if (comp != null)
975             cloneToId.remove(comp);
976
977         if (metacomp instanceof ComponentContainer) {
978             layoutBuilders.remove(metacomp.getId());
979             RADComponent[] subcomps = ((ComponentContainer)metacomp).getSubBeans();
980             for (int i=0; i < subcomps.length; i++)
981                 removeMapping(subcomps[i]);
982         }
983     }
984 }
985
Popular Tags