KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.awt.event.*;
24 import java.util.*;
25 import java.util.List JavaDoc;
26 import java.util.prefs.PreferenceChangeEvent JavaDoc;
27 import javax.swing.*;
28 import javax.swing.border.*;
29 import java.beans.*;
30 import java.util.prefs.PreferenceChangeListener JavaDoc;
31 import javax.swing.undo.UndoableEdit JavaDoc;
32
33 import org.jdesktop.layout.Baseline;
34 import org.jdesktop.layout.LayoutStyle;
35
36 import org.netbeans.core.spi.multiview.*;
37 import org.netbeans.modules.form.palette.PaletteItem;
38 import org.openide.DialogDisplayer;
39 import org.openide.NotifyDescriptor;
40 import org.openide.actions.FileSystemAction;
41 import org.openide.util.actions.SystemAction;
42 import org.openide.windows.TopComponent;
43 import org.openide.nodes.Node;
44 import org.openide.util.*;
45 import org.openide.util.lookup.*;
46 import org.openide.awt.UndoRedo;
47 import org.openide.explorer.ExplorerUtils;
48 import org.openide.ErrorManager;
49 import org.openide.explorer.ExplorerManager;
50
51 import org.netbeans.modules.form.assistant.*;
52 import org.netbeans.modules.form.wizard.ConnectionWizard;
53 import org.netbeans.modules.form.layoutsupport.LayoutSupportManager;
54 import org.netbeans.modules.form.layoutdesign.*;
55 import org.netbeans.modules.form.palette.PaletteUtils;
56
57
58 /**
59  * This is a TopComponent subclass holding the form designer. It consist of two
60  * layers - HandleLayer (responsible for interaction with user) and
61  * ComponentLayer (presenting the components, not accessible to the user).
62  *
63  * FormDesigner
64  * +- AssistantView
65  * +- JScrollPane
66  * +- JLayeredPane
67  * +- HandleLayer
68  * +- ComponentLayer
69  *
70  * @author Tran Duc Trung, Tomas Pavek, Josef Kozak
71  */

72
73 public class FormDesigner extends TopComponent implements MultiViewElement
74 {
75     static final String JavaDoc PROP_DESIGNER_SIZE = "designerSize"; // NOI18N
76

77     // UI components composition
78
private JLayeredPane layeredPane;
79     private ComponentLayer componentLayer;
80     private HandleLayer handleLayer;
81     private NonVisualTray nonVisualTray;
82     private FormToolBar formToolBar;
83     
84     // in-place editing
85
private InPlaceEditLayer textEditLayer;
86     private FormProperty editedProperty;
87     private InPlaceEditLayer.FinishListener finnishListener;
88             
89     // metadata
90
private FormModel formModel;
91     private FormModelListener formModelListener;
92     private RADVisualComponent topDesignComponent;
93
94     private FormEditor formEditor;
95
96     // layout visualization and interaction
97
private List JavaDoc selectedComponents = new ArrayList();
98     private List JavaDoc selectedLayoutComponents = new ArrayList();
99     private VisualReplicator replicator;
100     private LayoutDesigner layoutDesigner;
101     private List JavaDoc designerActions;
102     private List JavaDoc resizabilityActions;
103     
104     private JToggleButton[] resizabilityButtons;
105             
106     private int designerMode;
107     static final int MODE_SELECT = 0;
108     static final int MODE_CONNECT = 1;
109     static final int MODE_ADD = 2;
110     
111     private boolean initialized = false;
112     private boolean firstLayout;
113
114     private RADComponent connectionSource;
115     private RADComponent connectionTarget;
116
117     MultiViewElementCallback multiViewObserver;
118
119     private ExplorerManager explorerManager;
120     private FormProxyLookup lookup;
121
122     private AssistantView assistantView;
123     private PreferenceChangeListener JavaDoc settingsListener;
124
125     /** The icons for FormDesigner */
126     private static String JavaDoc iconURL =
127         "org/netbeans/modules/form/resources/formDesigner.gif"; // NOI18N
128

129     private boolean hasPropertyChangeListener = false;
130
131     // ----------
132
// constructors and setup
133

134     FormDesigner(FormEditor formEditor) {
135         setIcon(Utilities.loadImage(iconURL));
136         setLayout(new BorderLayout());
137
138         FormLoaderSettings settings = FormLoaderSettings.getInstance();
139         Color backgroundColor = settings.getFormDesignerBackgroundColor();
140         Color borderColor = settings.getFormDesignerBorderColor();
141
142         JPanel loadingPanel = new JPanel();
143         loadingPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 12, 12 + (settings.getAssistantShown() ? 40 : 0)));
144         loadingPanel.setBackground(backgroundColor);
145         JLabel loadingLbl = new JLabel(FormUtils.getBundleString("LBL_FormLoading")); // NOI18N
146
loadingLbl.setOpaque(true);
147         loadingLbl.setPreferredSize(new Dimension(410,310));
148         loadingLbl.setHorizontalAlignment(SwingConstants.CENTER);
149         loadingPanel.add(loadingLbl);
150         loadingLbl.setBorder(new CompoundBorder(new LineBorder(borderColor, 5),
151             new EmptyBorder(new Insets(6, 6, 6, 6))));
152         add(loadingPanel, BorderLayout.CENTER);
153
154         this.formEditor = formEditor;
155         
156         if (formEditor != null) { // Issue 67879
157
explorerManager = new ExplorerManager();
158
159             // add FormDataObject to lookup so it can be obtained from multiview TopComponent
160
ActionMap map = ComponentInspector.getInstance().setupActionMap(getActionMap());
161             final FormDataObject formDataObject = formEditor.getFormDataObject();
162             lookup = new FormProxyLookup(new Lookup[] {
163                 ExplorerUtils.createLookup(explorerManager, map),
164                 Lookups.fixed(new Object JavaDoc[] { formDataObject }),
165                 PaletteUtils.getPaletteLookup(formDataObject.getPrimaryFile()),
166                 formDataObject.getNodeDelegate().getLookup()
167             });
168             associateLookup(lookup);
169
170             formToolBar = new FormToolBar(this);
171         }
172     }
173     
174     void initialize() {
175         initialized = true;
176         firstLayout = true;
177         removeAll();
178
179         componentLayer = new ComponentLayer();
180         handleLayer = new HandleLayer(this);
181         nonVisualTray = FormEditor.isNonVisualTrayEnabled() ?
182                         new NonVisualTray(formEditor.getFormModel()) : null;
183
184         JPanel designPanel = new JPanel(new BorderLayout());
185         designPanel.add(componentLayer, BorderLayout.CENTER);
186         if (nonVisualTray != null) {
187             designPanel.add(nonVisualTray, BorderLayout.SOUTH);
188         }
189         
190         layeredPane = new JLayeredPane() {
191             // hack: before each paint make sure the dragged components have
192
// bounds set out of visible area (as they physically stay in their
193
// container and the layout manager may lay them back if some
194
// validation occurs)
195
protected void paintChildren(Graphics g) {
196                 handleLayer.maskDraggingComponents();
197                 super.paintChildren(g);
198             }
199         };
200         layeredPane.setLayout(new OverlayLayout(layeredPane));
201         layeredPane.add(designPanel, new Integer JavaDoc(1000));
202         layeredPane.add(handleLayer, new Integer JavaDoc(1001));
203
204         formModel = formEditor.getFormModel();
205
206         FormLoaderSettings settings = FormLoaderSettings.getInstance();
207         updateAssistant();
208         settingsListener = new PreferenceChangeListener JavaDoc() {
209             public void preferenceChange(PreferenceChangeEvent JavaDoc evt) {
210                 if (FormLoaderSettings.PROP_ASSISTANT_SHOWN.equals(evt.getKey())) {
211                     updateAssistant();
212                 }
213             }
214
215         };
216         settings.getPreferences().addPreferenceChangeListener(settingsListener);
217
218         JScrollPane scrollPane = new JScrollPane(layeredPane);
219         scrollPane.setBorder(null); // disable border, winsys will handle borders itself
220
scrollPane.setViewportBorder(null); // disable also GTK L&F viewport border
221
scrollPane.getVerticalScrollBar().setUnitIncrement(5); // Issue 50054
222
scrollPane.getHorizontalScrollBar().setUnitIncrement(5);
223         add(scrollPane, BorderLayout.CENTER);
224
225         explorerManager.setRootContext(formEditor.getFormRootNode());
226         
227         if(!hasPropertyChangeListener) {
228             addPropertyChangeListener("activatedNodes", new PropertyChangeListener() { // NOI18N
229
public void propertyChange(PropertyChangeEvent evt) {
230                     try {
231                         Lookup[] lookups = lookup.getSubLookups();
232                         Node[] oldNodes = (Node[])evt.getOldValue();
233                         Node[] nodes = (Node[])evt.getNewValue();
234                         Lookup lastLookup = lookups[lookups.length-1];
235                         Node delegate = formEditor.getFormDataObject().getNodeDelegate();
236                         if (!(lastLookup instanceof NoNodeLookup)
237                             && (oldNodes.length >= 1)
238                             && (!oldNodes[0].equals(delegate))) {
239                             switchLookup();
240                         } else if ((lastLookup instanceof NoNodeLookup)
241                             && (nodes.length == 0)) {
242                             switchLookup();
243                         }
244                         List JavaDoc list = new ArrayList(nodes.length);
245                         list.addAll(Arrays.asList(nodes));
246                         list.remove(delegate);
247                         explorerManager.setSelectedNodes((Node[])list.toArray(new Node[list.size()]));
248                     } catch (PropertyVetoException ex) {
249                         ex.printStackTrace();
250                     }
251                 }
252             });
253             hasPropertyChangeListener = true;
254         }
255
256         if (formModelListener == null)
257             formModelListener = new FormListener();
258         formModel.addFormModelListener(formModelListener);
259
260         replicator = new VisualReplicator(
261             null,
262             new Class JavaDoc[] { Window.class,
263                           java.applet.Applet JavaDoc.class,
264                           MenuComponent.class },
265             VisualReplicator.ATTACH_FAKE_PEERS | VisualReplicator.DISABLE_FOCUSING);
266
267         resetTopDesignComponent(false);
268         handleLayer.setViewOnly(formModel.isReadOnly());
269
270         // Beans without layout model doesn't require layout designer
271
if (formModel.getLayoutModel() != null) {
272             layoutDesigner = new LayoutDesigner(formModel.getLayoutModel(),
273                                             new LayoutMapper());
274         }
275         
276         updateWholeDesigner();
277         
278         // not very nice hack - it's better FormEditorSupport has its
279
// listener registered after FormDesigner
280
formEditor.reinstallListener();
281
282         if (formEditor.getFormDesigner() == null) {
283             // 70940: Make sure some form designer is registered
284
formEditor.setFormDesigner(this);
285         }
286     }
287     
288     void reset(FormEditor formEditor) {
289         if (initialized) {
290             clearSelection();
291         }
292         initialized = false;
293
294         removeAll();
295                 
296         componentLayer = null;
297         handleLayer = null;
298         nonVisualTray = null;
299         layeredPane = null;
300         if(textEditLayer!=null) {
301             if (textEditLayer.isVisible()){
302                 textEditLayer.finishEditing(false);
303             }
304             textEditLayer.removeFinishListener(getFinnishListener());
305             textEditLayer=null;
306         }
307                 
308         if (formModel != null) {
309             if (formModelListener != null) {
310                 formModel.removeFormModelListener(formModelListener);
311             }
312             topDesignComponent = null;
313             formModel = null;
314         }
315         
316         replicator = null;
317         layoutDesigner = null;
318         
319         connectionSource = null;
320         connectionTarget = null;
321         this.formEditor = formEditor;
322     }
323     
324     private void switchLookup() {
325         Lookup[] lookups = lookup.getSubLookups();
326         Lookup nodeLookup = formEditor.getFormDataObject().getNodeDelegate().getLookup();
327         int index = lookups.length - 1;
328         if (lookups[index] instanceof NoNodeLookup) {
329             lookups[index] = nodeLookup;
330         } else {
331             // should not affect selected nodes, but should provide cookies etc.
332
lookups[index] = new NoNodeLookup(nodeLookup);
333         }
334         lookup.setSubLookups(lookups);
335     }
336
337     private void updateAssistant() {
338         if (FormLoaderSettings.getInstance().getAssistantShown()) {
339             AssistantModel assistant = FormEditor.getAssistantModel(formModel);
340             assistantView = new AssistantView(assistant);
341             assistant.setContext("select"); // NOI18N
342
add(assistantView, BorderLayout.NORTH);
343         } else {
344             if (assistantView != null) {
345                 remove(assistantView);
346                 assistantView = null;
347             }
348         }
349         revalidate();
350     }
351
352
353     // ------
354
// important getters
355

356     public FormModel getFormModel() {
357         return formModel;
358     }
359
360     HandleLayer getHandleLayer() {
361         return handleLayer;
362     }
363
364     ComponentLayer getComponentLayer() {
365         return componentLayer;
366     }
367     
368     NonVisualTray getNonVisualTray() {
369         return nonVisualTray;
370     }
371
372     FormToolBar getFormToolBar() {
373         return formToolBar;
374     }
375
376     public LayoutDesigner getLayoutDesigner() {
377         return layoutDesigner;
378     }
379     
380     FormEditor getFormEditor() {
381         return formEditor;
382     }
383     
384     public javax.swing.Action JavaDoc[] getActions() {
385         Action[] actions = super.getActions();
386         SystemAction fsAction = SystemAction.get(FileSystemAction.class);
387         if (!Arrays.asList(actions).contains(fsAction)) {
388             Action[] newActions = new Action[actions.length+1];
389             System.arraycopy(actions, 0, newActions, 0, actions.length);
390             newActions[actions.length] = fsAction;
391             actions = newActions;
392         }
393         return actions;
394     }
395
396     // ------------
397
// designer content
398

399     public Object JavaDoc getComponent(RADComponent metacomp) {
400         return replicator.getClonedComponent(metacomp.getId());
401     }
402
403     public Object JavaDoc getComponent(String JavaDoc componentId) {
404         return replicator.getClonedComponent(componentId);
405     }
406
407     public RADComponent getMetaComponent(Object JavaDoc comp) {
408         String JavaDoc id = replicator.getClonedComponentId(comp);
409         return id != null ? formModel.getMetaComponent(id) : null;
410     }
411
412 // public RADComponent getMetaComponent(String componentId) {
413
// return formModel.getMetaComponent(componentId);
414
// }
415

416     public RADVisualComponent getTopDesignComponent() {
417         return topDesignComponent;
418     }
419
420     boolean isTopRADComponent() {
421         RADComponent topMetaComp = formModel.getTopRADComponent();
422         return topMetaComp != null && topMetaComp == topDesignComponent;
423     }
424     
425     public void setTopDesignComponent(RADVisualComponent component,
426                                       boolean update) {
427         
428         highlightTopDesignComponentName(false);
429         topDesignComponent = component;
430         highlightTopDesignComponentName(!isTopRADComponent());
431         
432         FormDataObject formDO = formEditor.getFormDataObject();
433         if(formDO!=null) {
434             formDO.getFormEditorSupport().updateMVTCDisplayName();
435         }
436         if (update) {
437             setSelectedComponent(topDesignComponent);
438             updateWholeDesigner();
439         }
440     }
441     
442     private void highlightTopDesignComponentName(boolean bl) {
443         if(topDesignComponent!=null) {
444             RADComponentNode node = topDesignComponent.getNodeReference();
445             if(node!=null) {
446                 node.highlightDisplayName(bl);
447             }
448         }
449     }
450     
451     public void resetTopDesignComponent(boolean update) {
452         setTopDesignComponent(
453             formModel.getTopRADComponent() instanceof RADVisualComponent ?
454                     (RADVisualComponent) formModel.getTopRADComponent() : null,
455             update);
456     }
457
458     /** Tests whether top designed container is some parent of given component
459      * (whether the component is in the tree under top designed container).
460      */

461     public boolean isInDesignedTree(RADComponent metacomp) {
462         return topDesignComponent != null
463                && (topDesignComponent == metacomp
464                    || topDesignComponent.isParentComponent(metacomp));
465     }
466
467     void updateWholeDesigner() {
468         if (formModelListener != null)
469             formModelListener.formChanged(null);
470     }
471
472     private void updateComponentLayer(final boolean fireChange) {
473         boolean firstLayout = this.firstLayout;
474         this.firstLayout = false;
475         if (getLayoutDesigner() == null)
476             return;
477
478         // Ensure that the components are laid out
479
componentLayer.revalidate(); // Add componentLayer among components to validate
480
RepaintManager.currentManager(componentLayer).validateInvalidComponents();
481
482         LayoutModel layoutModel = formModel.getLayoutModel();
483         Object JavaDoc layoutUndoMark = layoutModel.getChangeMark();
484         UndoableEdit JavaDoc layoutUndoEdit = layoutModel.getUndoableEdit();
485         boolean autoUndo = true;
486
487         try {
488             if (getLayoutDesigner().updateCurrentState() && fireChange) {
489                 formModel.fireFormChanged(true); // hack: to regenerate code once again
490
}
491             autoUndo = false;
492         } finally {
493             if ((!firstLayout || autoUndo) && !layoutUndoMark.equals(layoutModel.getChangeMark())) {
494                 formModel.addUndoableEdit(layoutUndoEdit);
495             } // note: change is ignored if done as part of adjusting newly
496
// opened form - this should not be undoable
497
if (autoUndo) {
498                 formModel.forceUndoOfCompoundEdit();
499             }
500         }
501
502         layoutModel.endUndoableEdit();
503         updateResizabilityActions();
504         componentLayer.repaint();
505     }
506
507     // updates layout of a container in designer to match current model - used
508
// by HandleLayer when canceling component dragging
509
void updateContainerLayout(RADVisualContainer metacont) {
510         replicator.updateContainerLayout(metacont);
511         componentLayer.revalidate();
512         componentLayer.repaint();
513     }
514
515     public static Container createFormView(final RADVisualComponent metacomp,
516                                            final Class JavaDoc contClass,
517                                            final Class JavaDoc previewLaf)
518         throws Exception JavaDoc
519     {
520         final UIDefaults uiDefaults = FormLAF.initPreviewLaf(previewLaf);
521         Container result = null;
522         Locale defaultLocale = switchToDesignLocale(metacomp.getFormModel());
523         try {
524             FormLAF.setUsePreviewDefaults(true, previewLaf, uiDefaults);
525             result = (Container) FormLAF.executeWithLookAndFeel(
526             new Mutex.ExceptionAction () {
527                 public Object JavaDoc run() throws Exception JavaDoc {
528                     VisualReplicator r = new VisualReplicator(
529                         contClass, null, 0);
530                     r.setTopMetaComponent(metacomp);
531                     Object JavaDoc container = r.createClone();
532                     if (container instanceof RootPaneContainer) {
533                         JRootPane rootPane = ((RootPaneContainer)container).getRootPane();
534                         JLayeredPane newPane = new JLayeredPane() {
535                             public void paint(Graphics g) {
536                                 try {
537                                     FormLAF.setUsePreviewDefaults(true, previewLaf, uiDefaults);
538                                     super.paint(g);
539                                 } finally {
540                                     FormLAF.setUsePreviewDefaults(false, null, null);
541                                 }
542                             }
543                         };
544                         // Copy components from the original layered pane into our one
545
JLayeredPane oldPane = rootPane.getLayeredPane();
546                         Component[] comps = oldPane.getComponents();
547                         for (int i=0; i<comps.length; i++) {
548                             newPane.add(comps[i], Integer.valueOf(oldPane.getLayer(comps[i])));
549                         }
550                         // Use our layered pane that knows about LAF switching
551
rootPane.setLayeredPane(newPane);
552                         // Make the glass pane visible to force repaint of the whole layered pane
553
rootPane.getGlassPane().setVisible(true);
554                         // Mark it as design preview
555
rootPane.putClientProperty("designPreview", Boolean.TRUE); // NOI18N
556
} // else AWT Frame - we don't care that the L&F of the Swing
557
// components may not look good - it is a strange use case
558
return container;
559                 }
560             }
561         );
562         } finally {
563             FormLAF.setUsePreviewDefaults(false, null, null);
564             if (defaultLocale != null)
565                 Locale.setDefault(defaultLocale);
566         }
567         return result;
568     }
569
570     private static Locale switchToDesignLocale(FormModel formModel) {
571         Locale defaultLocale = null;
572         String JavaDoc locale = FormEditor.getI18nSupport(formModel).getDesignLocale();
573         if (locale != null && !locale.equals("")) { // NOI18N
574
defaultLocale = Locale.getDefault();
575
576             String JavaDoc[] parts = locale.split("_"); // NOI18N
577
int i = 0;
578             if ("".equals(parts[i])) // NOI18N
579
i++;
580             String JavaDoc language = i < parts.length ? parts[i++] : null;
581             String JavaDoc country = i < parts.length ? parts[i++] : ""; // NOI18N
582
String JavaDoc variant = i < parts.length ? parts[i] : ""; // NOI18N
583
if (language != null)
584                 Locale.setDefault(new Locale(language, country, variant));
585         }
586         return defaultLocale;
587     }
588
589     Container getTopVisualContainer() {
590         RADVisualComponent topComp = replicator.getTopMetaComponent();
591         if (!(topComp instanceof RADVisualContainer))
592             return null;
593
594         return ((RADVisualContainer)topComp).getContainerDelegate(
595                              replicator.getClonedComponent(topComp));
596     }
597
598     // NOTE: does not create a new Point instance
599
Point pointFromComponentToHandleLayer(Point p, Component sourceComp) {
600         Component commonParent = layeredPane;
601         Component comp = sourceComp;
602         while (comp != commonParent) {
603             p.x += comp.getX();
604             p.y += comp.getY();
605             comp = comp.getParent();
606         }
607         comp = handleLayer;
608         while (comp != commonParent) {
609             p.x -= comp.getX();
610             p.y -= comp.getY();
611             comp = comp.getParent();
612         }
613         return p;
614     }
615
616     // NOTE: does not create a new Point instance
617
Point pointFromHandleToComponentLayer(Point p, Component targetComp) {
618         Component commonParent = layeredPane;
619         Component comp = handleLayer;
620         while (comp != commonParent) {
621             p.x += comp.getX();
622             p.y += comp.getY();
623             comp = comp.getParent();
624         }
625         comp = targetComp;
626         while (comp != commonParent) {
627             p.x -= comp.getX();
628             p.y -= comp.getY();
629             comp = comp.getParent();
630         }
631         return p;
632     }
633     
634     boolean isCoordinatesRoot(Component comp) {
635         return (layeredPane == comp);
636     }
637
638     private Rectangle componentBoundsToTop(Component component) {
639         if (component == null)
640             return null;
641
642         Component top = getTopVisualContainer();
643
644         int dx = 0;
645         int dy = 0;
646
647         if (component != top) {
648             Component comp = component.getParent();
649             while (comp != top) {
650                 if (comp == null) {
651                     break;//return null;
652
}
653                 dx += comp.getX();
654                 dy += comp.getY();
655                 comp = comp.getParent();
656             }
657         }
658         else {
659             dx = -top.getX();
660             dy = -top.getY();
661         }
662
663         Rectangle bounds = component.getBounds();
664         bounds.x += dx;
665         bounds.y += dy;
666
667         return bounds;
668     }
669
670     // -------
671
// designer mode
672

673     void setDesignerMode(int mode) {
674         formToolBar.updateDesignerMode(mode);
675
676         if (mode == designerMode)
677             return;
678
679         if (mode == MODE_ADD) {
680             PaletteItem pitem = PaletteUtils.getSelectedItem();
681             if ((pitem != null) && "chooseBean".equals(pitem.getExplicitComponentType())) { // NOI18N
682
NotifyDescriptor.InputLine desc = new NotifyDescriptor.InputLine(
683                     FormUtils.getBundleString("MSG_Choose_Bean"), // NOI18N
684
FormUtils.getBundleString("TITLE_Choose_Bean")); // NOI18N
685
DialogDisplayer.getDefault().notify(desc);
686                 if (NotifyDescriptor.OK_OPTION.equals(desc.getValue())) {
687                     pitem.setComponentClassSource(desc.getInputText(), null, null);
688                 } else {
689                     toggleSelectionMode();
690                     return;
691                 }
692             }
693         }
694
695         designerMode = mode;
696
697         resetConnection();
698         if (mode == MODE_CONNECT)
699             clearSelection();
700
701         handleLayer.endDragging(null);
702         updateResizabilityActions();
703         AssistantModel aModel = FormEditor.getAssistantModel(formModel);
704         switch (mode) {
705             case MODE_CONNECT: aModel.setContext("connectSource"); break; // NOI18N
706
case MODE_SELECT: aModel.setContext("select"); break; // NOI18N
707
}
708     }
709
710     int getDesignerMode() {
711         return designerMode;
712     }
713
714     void toggleSelectionMode() {
715         setDesignerMode(MODE_SELECT);
716         PaletteUtils.clearPaletteSelection();
717     }
718
719     void toggleConnectionMode() {
720         setDesignerMode(MODE_CONNECT);
721         PaletteUtils.clearPaletteSelection();
722     }
723
724     void toggleAddMode() {
725         setDesignerMode(MODE_ADD);
726         PaletteUtils.clearPaletteSelection();
727     }
728
729     // -------
730
// designer size
731

732     Dimension getDesignerSize() {
733         return componentLayer.getDesignerSize();
734     }
735
736     void setDesignerSize(Dimension size, Dimension oldSize) {
737         if (topDesignComponent instanceof RADVisualFormContainer) {
738             ((RADVisualFormContainer)topDesignComponent).setDesignerSize(size);
739         }
740         else if (topDesignComponent != null) {
741             if (topDesignComponent == formModel.getTopRADComponent()) {
742                 oldSize = (Dimension) topDesignComponent.getAuxValue(PROP_DESIGNER_SIZE);
743                 topDesignComponent.setAuxValue(PROP_DESIGNER_SIZE, size);
744             }
745             if (oldSize == null)
746                 oldSize = getDesignerSize();
747
748             getFormModel().fireSyntheticPropertyChanged(topDesignComponent,
749                     FormDesigner.PROP_DESIGNER_SIZE, oldSize, size);
750         }
751     }
752
753     public void resetDesignerSize() {
754         setDesignerSize(null, null);
755     }
756
757     void storeDesignerSize(Dimension size) { // without firing model change
758
if (topDesignComponent instanceof RADVisualFormContainer)
759             ((RADVisualFormContainer)topDesignComponent).setDesignerSizeImpl(size);
760         else if (topDesignComponent == formModel.getTopRADComponent()) // root not a visual container
761
topDesignComponent.setAuxValue(PROP_DESIGNER_SIZE, size);
762     }
763
764     private void setupDesignerSize() {
765         Dimension size = null;
766         RADVisualFormContainer formCont = topDesignComponent instanceof RADVisualFormContainer ?
767                                           (RADVisualFormContainer) topDesignComponent : null;
768         if (formCont == null
769             || formCont.hasExplicitSize()
770             || !RADVisualContainer.isFreeDesignContainer(topDesignComponent))
771         { // try to obtain stored designer size
772
if (formCont != null)
773                 size = formCont.getDesignerSize();
774             if (size == null)
775                 size = (Dimension) topDesignComponent.getAuxValue(PROP_DESIGNER_SIZE);
776             if (size == null
777                 && (!formModel.isFreeDesignDefaultLayout()
778                      || topDesignComponent == formModel.getTopRADComponent()))
779             { // use default size if no stored size is available and
780
// old layout form or top design comp is root in the form (but not a container)
781
size = new Dimension(400, 300);
782             }
783         }
784
785         Dimension setSize = componentLayer.setDesignerSize(size); // null computes preferred size
786
storeDesignerSize(setSize);
787     }
788
789     private void checkDesignerSize() {
790         if ((formModel.isFreeDesignDefaultLayout()
791                 || RADVisualContainer.isFreeDesignContainer(topDesignComponent))
792             && topDesignComponent instanceof RADVisualComponent
793             && (!(topDesignComponent instanceof RADVisualFormContainer)
794                 || !((RADVisualFormContainer)topDesignComponent).hasExplicitSize()))
795         { // new layout container defining designer size
796
// designer size not defined explicitly - check minimum size
797
Component topComp = (Component) getComponent(topDesignComponent);
798             Component topCont = getTopVisualContainer(); // container delegate
799
if (topCont == null)
800                 topCont = topComp;
801             // can't rely on minimum size of the container wrap - e.g. menu bar
802
// returns wrong min height
803
int wDiff = topComp.getWidth() - topCont.getWidth();
804             int hDiff = topComp.getHeight() - topCont.getHeight();
805
806             Dimension designerSize = new Dimension(getDesignerSize());
807             designerSize.width -= wDiff;
808             designerSize.height -= hDiff;
809             Dimension minSize = topCont.getMinimumSize();
810             boolean corrected = false;
811             if (designerSize.width < minSize.width) {
812                 designerSize.width = minSize.width;
813                 corrected = true;
814             }
815             if (designerSize.height < minSize.height) {
816                 designerSize.height = minSize.height;
817                 corrected = true;
818             }
819
820             if (corrected) {
821                 designerSize.width += wDiff;
822                 designerSize.height += hDiff;
823
824                 // hack: we need the size correction in the undo/redo
825
if (formModel.isCompoundEditInProgress()) {
826                     FormModelEvent ev = new FormModelEvent(formModel, FormModelEvent.SYNTHETIC_PROPERTY_CHANGED);
827                     ev.setComponentAndContainer(topDesignComponent, null);
828                     ev.setProperty(PROP_DESIGNER_SIZE, getDesignerSize(), designerSize);
829                     formModel.addUndoableEdit(ev.getUndoableEdit());
830                 }
831
832                 componentLayer.setDesignerSize(designerSize);
833                 storeDesignerSize(designerSize);
834             }
835         }
836     }
837
838     // ---------
839
// components selection
840

841     java.util.List JavaDoc getSelectedComponents() {
842         return selectedComponents;
843     }
844
845     Node[] getSelectedComponentNodes() {
846         Node[] selectedNodes = new Node[selectedComponents.size()];
847         Iterator iter = selectedComponents.iterator();
848         int i = 0;
849         while (iter.hasNext()) {
850             RADComponent metacomp = (RADComponent) iter.next();
851             selectedNodes[i++] = metacomp.getNodeReference();
852         }
853         return selectedNodes;
854     }
855     
856     java.util.List JavaDoc getSelectedLayoutComponents() {
857         return selectedLayoutComponents;
858     }
859
860     boolean isComponentSelected(RADComponent metacomp) {
861         return selectedComponents.contains(metacomp);
862     }
863
864     void setSelectedComponent(RADComponent metacomp) {
865         clearSelectionImpl();
866         addComponentToSelectionImpl(metacomp);
867         repaintSelection();
868         updateComponentInspector();
869     }
870
871     void setSelectedComponents(RADComponent[] metacomps) {
872         clearSelectionImpl();
873
874         for (int i=0; i < metacomps.length; i++)
875             addComponentToSelectionImpl(metacomps[i]);
876
877         repaintSelection();
878         updateComponentInspector();
879     }
880
881     void setSelectedNode(FormNode node) {
882         if (node instanceof RADComponentNode)
883             setSelectedComponent(((RADComponentNode)node).getRADComponent());
884         else {
885             clearSelectionImpl();
886             repaintSelection();
887
888             ComponentInspector ci = ComponentInspector.getInstance();
889             if (ci.getFocusedForm() != formEditor)
890                 return;
891
892
893             Node[] selectedNodes = new Node[] { node };
894             try {
895                 ci.setSelectedNodes(selectedNodes, formEditor);
896                 // sets also the activated nodes (both for ComponentInspector
897
// and FormDesigner)
898
}
899             catch (java.beans.PropertyVetoException JavaDoc ex) {
900                 ex.printStackTrace();
901             }
902         }
903     }
904
905     void addComponentToSelection(RADComponent metacomp) {
906         addComponentToSelectionImpl(metacomp);
907         repaintSelection();
908         updateComponentInspector();
909     }
910
911     void addComponentsToSelection(RADComponent[] metacomps) {
912         for (int i=0; i < metacomps.length; i++)
913             addComponentToSelectionImpl(metacomps[i]);
914
915         repaintSelection();
916         updateComponentInspector();
917     }
918
919     void removeComponentFromSelection(RADComponent metacomp) {
920         removeComponentFromSelectionImpl(metacomp);
921         repaintSelection();
922         updateComponentInspector();
923     }
924
925     public void clearSelection() {
926         clearSelectionImpl();
927         repaintSelection();
928         updateComponentInspector();
929     }
930
931     void addComponentToSelectionImpl(RADComponent metacomp) {
932         if (metacomp != null) {
933             selectedComponents.add(metacomp);
934             RADVisualComponent layoutComponent = componentToLayoutComponent(metacomp);
935             if (layoutComponent != null) {
936                 selectedLayoutComponents.add(layoutComponent);
937                 ensureComponentIsShown((RADVisualComponent)metacomp);
938                 selectionChanged();
939             }
940         }
941     }
942     
943     RADVisualComponent componentToLayoutComponent(RADComponent metacomp) {
944         if (metacomp instanceof RADVisualComponent) {
945             RADVisualComponent visualComp = (RADVisualComponent) metacomp;
946             RADVisualContainer metacont = visualComp.getParentContainer();
947             if ((metacont != null) && JScrollPane.class.isAssignableFrom(metacont.getBeanInstance().getClass())
948                  && isInDesignedTree(metacont))
949             { // substitute with scroll pane...
950
return metacont;
951             }
952             // otherwise just check if it is visible in the designer
953
return isInDesignedTree(visualComp) ? visualComp : null;
954         }
955         return null;
956     }
957
958     void removeComponentFromSelectionImpl(RADComponent metacomp) {
959         selectedComponents.remove(metacomp);
960         selectedLayoutComponents.remove(metacomp);
961         selectionChanged();
962     }
963
964     void clearSelectionImpl() {
965         selectedComponents.clear();
966         selectedLayoutComponents.clear();
967         selectionChanged();
968     }
969
970     void selectionChanged() {
971         updateDesignerActions();
972         updateResizabilityActions();
973         updateAssistantContext();
974     }
975
976     void repaintSelection() {
977         handleLayer.repaint();
978     }
979
980     private void updateDesignerActions() {
981         Collection selectedIds = selectedLayoutComponentIds();
982         boolean enabled = false;
983         if (selectedIds.size() >= 2) {
984             RADComponent parent = commonParent(selectedIds);
985             if (parent != null) {
986                 LayoutModel layoutModel = formModel.getLayoutModel();
987                 LayoutComponent parentLC = layoutModel.getLayoutComponent(parent.getId());
988                 if ((parentLC != null) && (parentLC.isLayoutContainer())) {
989                     enabled = true;
990                 }
991             }
992         }
993         Iterator iter = getDesignerActions(true).iterator();
994         while (iter.hasNext()) {
995             Action action = (Action)iter.next();
996             action.setEnabled(enabled);
997         }
998     }
999
1000    void setResizabilityButtons(JToggleButton[] buttons) {
1001        this.resizabilityButtons = buttons;
1002    }
1003    
1004    public JToggleButton[] getResizabilityButtons() {
1005        return resizabilityButtons;
1006    }
1007
1008    public void updateResizabilityActions() {
1009        Collection componentIds = componentIds();
1010        LayoutModel layoutModel = getFormModel().getLayoutModel();
1011        LayoutDesigner layoutDesigner = getLayoutDesigner();
1012        Iterator iter = componentIds.iterator();
1013        boolean resizable[] = new boolean[2];
1014        boolean nonResizable[] = new boolean[2];
1015        while (iter.hasNext()) {
1016            String JavaDoc id = (String JavaDoc)iter.next();
1017            LayoutComponent comp = layoutModel.getLayoutComponent(id);
1018            for (int i=0; i<2; i++) {
1019                if (layoutDesigner.isComponentResizing(comp,
1020                        (i == 0) ? LayoutConstants.HORIZONTAL : LayoutConstants.VERTICAL)) {
1021                    resizable[i] = true;
1022                } else {
1023                    nonResizable[i] = true;
1024                }
1025            }
1026        }
1027        for (int i=0; i<2; i++) {
1028            boolean match;
1029            boolean miss;
1030            match = resizable[i];
1031            miss = nonResizable[i];
1032            getResizabilityButtons()[i].setSelected(!miss && match);
1033            ((ResizabilityAction)getResizabilityActions().toArray()[i]).setEnabled(match || miss);
1034// getResizabilityButtons()[i].setPaintDisabledIcon(match && miss);
1035
}
1036    }
1037
1038    private void updateAssistantContext() {
1039        String JavaDoc context = "select"; // NOI18N
1040
List JavaDoc selComps = getSelectedComponents();
1041        if (selComps.size() == 1) {
1042            RADComponent metacomp = (RADComponent)selComps.get(0);
1043            Object JavaDoc bean = metacomp.getBeanInstance();
1044            if (bean instanceof JTabbedPane) {
1045                JTabbedPane pane = (JTabbedPane)bean;
1046                int count = pane.getTabCount();
1047                switch (count) {
1048                    case 0: context = "tabbedPaneEmpty"; break; // NOI18N
1049
case 1: context = "tabbedPaneOne"; break; // NOI18N
1050
default: context = "tabbedPane"; break; // NOI18N
1051
}
1052            } else if (bean instanceof JRadioButton) {
1053                Node.Property property = metacomp.getPropertyByName("buttonGroup"); // NOI18N
1054
try {
1055                    if ((property != null) && (property.getValue() == null)) {
1056                        context = "buttonGroup"; // NOI18N
1057
}
1058                } catch (Exception JavaDoc ex) {
1059                    ex.printStackTrace();
1060                }
1061            } else if ((bean instanceof JPanel) && (getTopDesignComponent() != metacomp) && (Math.random() < 0.2)) {
1062                context = "designThisContainer"; // NOI18N
1063
} else if ((bean instanceof JComboBox) && (Math.random() < 0.4)) {
1064                context = "comboBoxModel"; // NOI18N
1065
} else if ((bean instanceof JList) && (Math.random() < 0.4)) {
1066                context = "listModel"; // NOI18N
1067
} else if ((bean instanceof JTable) && (Math.random() < 0.4)) {
1068                context = "tableModel"; // NOI18N
1069
} else if (bean instanceof JScrollPane) {
1070                JScrollPane scrollPane = (JScrollPane)bean;
1071                if (scrollPane.getViewport().getView() == null) {
1072                    context = "scrollPaneEmpty"; // NOI18N
1073
} else if (Math.random() < 0.5) {
1074                    context = "scrollPane"; // NOI18N
1075
}
1076            }
1077        }
1078        FormEditor.getAssistantModel(formModel).setContext(context);
1079    }
1080
1081    /** Finds out what component follows after currently selected component
1082     * when TAB (forward true) or Shift+TAB (forward false) is pressed.
1083     * @return the next or previous component for selection
1084     */

1085    RADVisualComponent getNextVisualComponent(boolean forward) {
1086        RADVisualComponent currentComp = null;
1087        int n = selectedComponents.size();
1088        if (n > 0) {
1089            if (n > 1)
1090                return null;
1091            Object JavaDoc sel = selectedComponents.get(0);
1092            if (sel instanceof RADVisualComponent)
1093                currentComp = (RADVisualComponent) sel;
1094            else return null;
1095        }
1096
1097        return getNextVisualComponent(currentComp, forward);
1098    }
1099
1100    /** @return the next or prevoius component to component comp
1101     */

1102    RADVisualComponent getNextVisualComponent(RADVisualComponent comp,
1103                                              boolean forward)
1104    {
1105        if (comp == null)
1106            return topDesignComponent;
1107        if (getComponent(comp) == null)
1108            return null;
1109
1110        RADVisualContainer cont;
1111        RADVisualComponent[] subComps;
1112
1113        if (forward) {
1114            // try the first sub-component
1115
if (comp instanceof RADVisualContainer) {
1116                subComps = ((RADVisualContainer)comp).getSubComponents();
1117                if (subComps.length > 0)
1118                    return subComps[0];
1119            }
1120
1121            // try the next component (or the next of the parent then)
1122
if (comp == topDesignComponent)
1123                return topDesignComponent;
1124            cont = comp.getParentContainer();
1125            if (cont == null)
1126                return null; // should not happen
1127

1128            int i = cont.getIndexOf(comp);
1129            while (i >= 0) {
1130                subComps = cont.getSubComponents();
1131                if (i+1 < subComps.length)
1132                    return subComps[i+1];
1133
1134                if (cont == topDesignComponent)
1135                    break;
1136                comp = cont; // one level up
1137
cont = comp.getParentContainer();
1138                if (cont == null)
1139                    return null; // should not happen
1140
i = cont.getIndexOf(comp);
1141            }
1142
1143            return topDesignComponent;
1144        }
1145        else { // backward
1146
// take the previuos component
1147
if (comp != topDesignComponent) {
1148                cont = comp.getParentContainer();
1149                if (cont == null)
1150                    return null; // should not happen
1151
int i = cont.getIndexOf(comp);
1152                if (i >= 0) { // should be always true
1153
if (i == 0) return cont; // the opposite to the 1st forward step
1154

1155                    subComps = cont.getSubComponents();
1156                    comp = subComps[i-1];
1157                }
1158                else comp = topDesignComponent;
1159            }
1160
1161            // find the last subcomponent of it
1162
do {
1163                if (comp instanceof RADVisualContainer) {
1164                    subComps = ((RADVisualContainer)comp).getSubComponents();
1165                    if (subComps.length > 0) { // one level down
1166
comp = subComps[subComps.length-1];
1167                        continue;
1168                    }
1169                }
1170                break;
1171            }
1172            while (true);
1173            return comp;
1174        }
1175    }
1176    
1177    /**
1178     * Aligns selected components in the specified direction.
1179     *
1180     * @param closed determines if closed group should be created.
1181     * @param dimension dimension to align in.
1182     * @param alignment requested alignment.
1183     */

1184    void align(boolean closed, int dimension, int alignment) {
1185        // Check that the action is enabled
1186
Action action = null;
1187        Iterator iter = getDesignerActions(true).iterator();
1188        while (iter.hasNext()) {
1189            Action candidate = (Action)iter.next();
1190            if (candidate instanceof AlignAction) {
1191                AlignAction alignCandidate = (AlignAction)candidate;
1192                if ((alignCandidate.getAlignment() == alignment) && (alignCandidate.getDimension() == dimension)) {
1193                    action = alignCandidate;
1194                    break;
1195                }
1196            }
1197        }
1198        if ((action == null) || (!action.isEnabled())) {
1199            return;
1200        }
1201        Collection selectedIds = selectedLayoutComponentIds();
1202        RADComponent parent = commonParent(selectedIds);
1203        LayoutModel layoutModel = formModel.getLayoutModel();
1204        Object JavaDoc layoutUndoMark = layoutModel.getChangeMark();
1205        javax.swing.undo.UndoableEdit JavaDoc ue = layoutModel.getUndoableEdit();
1206        boolean autoUndo = true;
1207        try {
1208            getLayoutDesigner().align(selectedIds, closed, dimension, alignment);
1209            autoUndo = false;
1210        } finally {
1211            formModel.fireContainerLayoutChanged((RADVisualContainer)parent, null, null, null);
1212            if (!layoutUndoMark.equals(layoutModel.getChangeMark())) {
1213                formModel.addUndoableEdit(ue);
1214            }
1215            if (autoUndo) {
1216                formModel.forceUndoOfCompoundEdit();
1217            }
1218        }
1219    }
1220    
1221    /**
1222     * Returns designer actions (they will be displayed in toolbar).
1223     *
1224     * @param forToolbar determines whether the method should return
1225     * all designer actions or just the subset for the form toolbar.
1226     * @return <code>Collection</code> of <code>Action</code> objects.
1227     */

1228    public Collection getDesignerActions(boolean forToolbar) {
1229        if (designerActions == null) {
1230            designerActions = new LinkedList();
1231            // Grouping actions
1232
designerActions.add(new AlignAction(LayoutConstants.HORIZONTAL, LayoutConstants.LEADING, true));
1233            designerActions.add(new AlignAction(LayoutConstants.HORIZONTAL, LayoutConstants.TRAILING, true));
1234            designerActions.add(new AlignAction(LayoutConstants.VERTICAL, LayoutConstants.LEADING, true));
1235            designerActions.add(new AlignAction(LayoutConstants.VERTICAL, LayoutConstants.TRAILING, true));
1236            // Align actions
1237
designerActions.add(new AlignAction(LayoutConstants.HORIZONTAL, LayoutConstants.LEADING, false));
1238            designerActions.add(new AlignAction(LayoutConstants.HORIZONTAL, LayoutConstants.TRAILING, false));
1239            designerActions.add(new AlignAction(LayoutConstants.VERTICAL, LayoutConstants.LEADING, false));
1240            designerActions.add(new AlignAction(LayoutConstants.VERTICAL, LayoutConstants.TRAILING, false));
1241        }
1242        return forToolbar ? designerActions.subList(0, 4) : designerActions;
1243    }
1244    
1245    public Collection getResizabilityActions() {
1246        if (resizabilityActions == null) {
1247            resizabilityActions = new LinkedList();
1248            resizabilityActions.add(new ResizabilityAction(LayoutConstants.HORIZONTAL));
1249            resizabilityActions.add(new ResizabilityAction(LayoutConstants.VERTICAL));
1250        }
1251        return resizabilityActions;
1252    }
1253    
1254    /**
1255     * Returns collection of ids of the selected layout components.
1256     *
1257     * @return <code>Collection</code> of <code>String</code> objects.
1258     */

1259    Collection selectedLayoutComponentIds() {
1260        Iterator metacomps = getSelectedLayoutComponents().iterator();
1261        Collection selectedIds = new LinkedList();
1262        while (metacomps.hasNext()) {
1263            RADComponent metacomp = (RADComponent)metacomps.next();
1264            selectedIds.add(metacomp.getId());
1265        }
1266        return selectedIds;
1267    }
1268    
1269    /**
1270     * Checks whether the given components are in the same containter.
1271     *
1272     * @param compIds <code>Collection</code> of component IDs.
1273     * @return common container parent or <code>null</code>
1274     * if the components are not from the same container.
1275     */

1276    private RADComponent commonParent(Collection compIds) {
1277        RADComponent parent = null;
1278        Iterator iter = compIds.iterator();
1279        FormModel formModel = getFormModel();
1280        while (iter.hasNext()) {
1281            String JavaDoc compId = (String JavaDoc)iter.next();
1282            RADComponent metacomp = formModel.getMetaComponent(compId);
1283            RADComponent metacont = metacomp.getParentComponent();
1284            if (parent == null) {
1285                parent = metacont;
1286            }
1287            if ((metacont == null) || (parent != metacont)) {
1288                return null;
1289            }
1290        }
1291        return parent;
1292    }
1293
1294    // ---------
1295
// visibility update
1296

1297    // synchronizes ComponentInspector with selection in FormDesigner
1298
// [there is a hardcoded relationship between these two views]
1299
void updateComponentInspector() {
1300        ComponentInspector ci = ComponentInspector.getInstance();
1301        if (ci.getFocusedForm() != formEditor)
1302            return;
1303
1304        Node[] selectedNodes = getSelectedComponentNodes();
1305        try {
1306            setActivatedNodes(selectedNodes); // Issue 62356
1307
ci.setSelectedNodes(selectedNodes, formEditor);
1308            // sets also the activated nodes (both for ComponentInspector
1309
// and FormDesigner)
1310
}
1311        catch (java.beans.PropertyVetoException JavaDoc ex) {
1312            ex.printStackTrace();
1313        }
1314    }
1315
1316    void updateVisualSettings() {
1317        componentLayer.updateVisualSettings();
1318        if (nonVisualTray != null) {
1319            nonVisualTray.updateVisualSettings();
1320        }
1321        layeredPane.revalidate();
1322        layeredPane.repaint(); // repaints both HanleLayer and ComponentLayer
1323
}
1324
1325    private void ensureComponentIsShown(RADVisualComponent metacomp) {
1326        Component comp = (Component) getComponent(metacomp);
1327        if (comp == null)
1328            return; // component is not in the visualized tree
1329

1330// if (comp == null) { // visual component doesn't exist yet
1331
// if (metacont != null)
1332
// metacont.getLayoutSupport().selectComponent(
1333
// metacont.getIndexOf(metacomp));
1334
// return;
1335
// }
1336

1337        if (comp.isShowing())
1338            return; // component is showing
1339
if (!isInDesignedTree(metacomp))
1340            return; // component is not in designer
1341

1342        Component topComp = (Component) getComponent(topDesignComponent);
1343        if (topComp == null || !topComp.isShowing())
1344            return; // designer is not showing
1345

1346        RADVisualContainer metacont = metacomp.getParentContainer();
1347        RADVisualComponent child = metacomp;
1348
1349        while (metacont != null) {
1350            Container cont = (Container) getComponent(metacont);
1351
1352            LayoutSupportManager laysup = metacont.getLayoutSupport();
1353            if (laysup != null) {
1354                Container contDelegate = metacont.getContainerDelegate(cont);
1355                laysup.selectComponent(child.getComponentIndex());
1356                laysup.arrangeContainer(cont, contDelegate);
1357            }
1358
1359            if (metacont == topDesignComponent || cont.isShowing())
1360                break;
1361
1362            child = metacont;
1363            metacont = metacont.getParentContainer();
1364        }
1365    }
1366
1367    // --------------
1368
// bean connection
1369

1370    void connectBean(RADComponent metacomp, boolean showDialog) {
1371        if (connectionSource == null) {
1372            connectionSource = metacomp;
1373            FormEditor.getAssistantModel(formModel).setContext("connectTarget"); // NOI18N
1374
handleLayer.repaint();
1375        }
1376        else {
1377            if (metacomp == connectionSource) {
1378                if (connectionTarget != null) {
1379                    resetConnection();
1380                    toggleSelectionMode();
1381                }
1382                return;
1383            }
1384            connectionTarget = metacomp;
1385            handleLayer.repaint();
1386            if (showDialog) {
1387                if (connectionTarget != null) {
1388                    FormEditor.getAssistantModel(formModel).setContext("connectWizard"); // NOI18N
1389
createConnection(connectionSource, connectionTarget);
1390                }
1391// resetConnection();
1392
toggleSelectionMode();
1393            }
1394        }
1395    }
1396
1397    public RADComponent getConnectionSource() {
1398        return connectionSource;
1399    }
1400
1401    public RADComponent getConnectionTarget() {
1402        return connectionTarget;
1403    }
1404
1405    public void resetConnection() {
1406        if (connectionSource != null || connectionTarget != null) {
1407            connectionSource = null;
1408            connectionTarget = null;
1409            handleLayer.repaint();
1410        }
1411    }
1412
1413    private void createConnection(RADComponent source, RADComponent target) {
1414        ConnectionWizard cw = new ConnectionWizard(formModel, source,target);
1415
1416        if (cw.show()) {
1417            final Event event = cw.getSelectedEvent();
1418            final String JavaDoc eventName = cw.getEventName();
1419            String JavaDoc bodyText = cw.getGeneratedCode();
1420
1421            formModel.getFormEvents().attachEvent(event, eventName, bodyText);
1422
1423            // hack: after all updates, switch to editor
1424
SwingUtilities.invokeLater(new Runnable JavaDoc() {
1425                public void run() {
1426                    formModel.getFormEvents().attachEvent(event, eventName, null);
1427                }
1428            });
1429        }
1430    }
1431
1432    // -----------------
1433
// in-place editing
1434

1435    public void startInPlaceEditing(RADComponent metacomp) {
1436        
1437        if (formModel.isReadOnly())
1438            return;
1439        if (textEditLayer != null && textEditLayer.isVisible())
1440            return;
1441        if (!isEditableInPlace(metacomp)) // check for sure
1442
return;
1443
1444        Component comp = (Component) getComponent(metacomp);
1445        if (comp == null) { // component is not visible
1446
notifyCannotEditInPlace();
1447            return;
1448        }
1449
1450        FormProperty property = null;
1451        if (JTabbedPane.class.isAssignableFrom(metacomp.getBeanClass())) {
1452            JTabbedPane tabbedPane = (JTabbedPane)comp;
1453            int index = tabbedPane.getSelectedIndex();
1454            RADVisualContainer metacont = (RADVisualContainer)metacomp;
1455            RADVisualComponent tabComp = metacont.getSubComponent(index);
1456            Node.Property[] props = tabComp.getConstraintsProperties();
1457            for (int i=0; i<props.length; i++) {
1458                if (props[i].getName().equals("TabConstraints.tabTitle")) { // NOI18N
1459
if (props[i] instanceof FormProperty) {
1460                        property = (FormProperty)props[i];
1461                    } else {
1462                        return;
1463                    }
1464                }
1465            }
1466            if (property == null) return;
1467        } else {
1468            property = metacomp.getBeanProperty("text"); // NOI18N
1469
if (property == null)
1470                return; // should not happen
1471
}
1472
1473        String JavaDoc editText = null;
1474        try {
1475            Object JavaDoc text = property.getRealValue();
1476            if (!(text instanceof String JavaDoc)) text = ""; // or return?
1477
editText = (String JavaDoc) text;
1478        }
1479        catch (Exception JavaDoc ex) { // should not happen
1480
ex.printStackTrace();
1481            return;
1482        }
1483
1484        editedProperty = property;
1485
1486        if (textEditLayer == null) {
1487            textEditLayer = new InPlaceEditLayer();
1488            textEditLayer.setVisible(false);
1489            textEditLayer.addFinishListener(getFinnishListener());
1490            layeredPane.add(textEditLayer, new Integer JavaDoc(2001));
1491        }
1492        try {
1493            textEditLayer.setEditedComponent(comp, editText);
1494        }
1495        catch (IllegalArgumentException JavaDoc ex) {
1496            notifyCannotEditInPlace();
1497            return;
1498        }
1499
1500        textEditLayer.setVisible(true);
1501        handleLayer.setVisible(false);
1502        textEditLayer.requestFocus();
1503    }
1504
1505    private InPlaceEditLayer.FinishListener getFinnishListener() {
1506        if(finnishListener==null) {
1507           finnishListener = new InPlaceEditLayer.FinishListener() {
1508                public void editingFinished(boolean textChanged) {
1509                    finishInPlaceEditing(textEditLayer.isTextChanged());
1510                }
1511            };
1512        }
1513        return finnishListener;
1514    }
1515        
1516    
1517        
1518    private void finishInPlaceEditing(boolean applyChanges) {
1519        if (applyChanges) {
1520            try {
1521        Object JavaDoc value = editedProperty.getValue();
1522        if(value instanceof String JavaDoc) {
1523            editedProperty.setValue(textEditLayer.getEditedText());
1524        } else {
1525            PropertyEditor prEd = editedProperty.findDefaultEditor();
1526            editedProperty.setValue(new FormProperty.ValueWithEditor(textEditLayer.getEditedText(), prEd));
1527        }
1528        } catch (Exception JavaDoc ex) { // should not happen
1529
ex.printStackTrace();
1530            }
1531        }
1532    
1533        textEditLayer.setVisible(false);
1534        handleLayer.setVisible(true);
1535        handleLayer.requestFocus();
1536        editedProperty = null;
1537    }
1538
1539    public boolean isEditableInPlace(RADComponent metacomp) {
1540        Component comp = (Component) getComponent(metacomp);
1541        if (comp == null)
1542            return false;
1543
1544        // don't allow in-place editing if there's some AWT parent (it may
1545
// cause problems with fake peers on some platforms)
1546
RADComponent parent = metacomp.getParentComponent();
1547        while (parent != null) {
1548            if (!JComponent.class.isAssignableFrom(parent.getBeanClass())
1549                && !RootPaneContainer.class.isAssignableFrom(
1550                                        parent.getBeanClass()))
1551                return false;
1552            parent = parent.getParentComponent();
1553        }
1554
1555        Class JavaDoc beanClass = metacomp.getBeanClass();
1556        return InPlaceEditLayer.supportsEditingFor(beanClass, false)
1557            && (!JTabbedPane.class.isAssignableFrom(beanClass) || ((JTabbedPane)comp).getTabCount() != 0);
1558    }
1559
1560    private void notifyCannotEditInPlace() {
1561        DialogDisplayer.getDefault().notify(
1562            new NotifyDescriptor.Message(
1563                FormUtils.getBundleString("MSG_ComponentNotShown"), // NOI18N
1564
NotifyDescriptor.WARNING_MESSAGE));
1565    }
1566
1567    // --------
1568
// methods of TopComponent
1569

1570    // only MultiViewDescriptor is stored, not MultiViewElement
1571
public int getPersistenceType() {
1572        return TopComponent.PERSISTENCE_NEVER;
1573    }
1574
1575    public HelpCtx getHelpCtx() {
1576        return new HelpCtx("gui.formeditor"); // NOI18N
1577
}
1578
1579    public void componentActivated() {
1580        if (formModel == null)
1581            return;
1582
1583        formEditor.setFormDesigner(this);
1584        ComponentInspector ci = ComponentInspector.getInstance();
1585        if (ci.getFocusedForm() != formEditor) {
1586            ci.focusForm(formEditor);
1587            if (getDesignerMode() == MODE_CONNECT)
1588                clearSelection();
1589            else
1590                updateComponentInspector();
1591        }
1592
1593        ci.attachActions();
1594        if (textEditLayer == null || !textEditLayer.isVisible())
1595            handleLayer.requestFocus();
1596    }
1597
1598    public void componentDeactivated() {
1599        if (formModel == null)
1600            return;
1601        
1602        if (textEditLayer != null && textEditLayer.isVisible())
1603            textEditLayer.finishEditing(false);
1604
1605        ComponentInspector.getInstance().detachActions();
1606        resetConnection();
1607    }
1608
1609    public UndoRedo getUndoRedo() {
1610        UndoRedo ur = formModel != null ? formModel.getUndoRedoManager() : null;
1611        return ur != null ? ur : super.getUndoRedo();
1612    }
1613    
1614    protected String JavaDoc preferredID() {
1615        return formEditor.getFormDataObject().getName();
1616    }
1617
1618    // ------
1619
// multiview stuff
1620

1621    public JComponent getToolbarRepresentation() {
1622        return getFormToolBar();
1623    }
1624
1625    public JComponent getVisualRepresentation() {
1626        return this;
1627    }
1628
1629    public void setMultiViewCallback(MultiViewElementCallback callback) {
1630        multiViewObserver = callback;
1631
1632        // add FormDesigner as a client property so it can be obtained
1633
// from multiview TopComponent (it is not sufficient to put
1634
// it into lookup - only content of the lookup of the active
1635
// element is accessible)
1636
callback.getTopComponent().putClientProperty("formDesigner", this); // NOI18N
1637

1638        // needed for deserialization...
1639
if (formEditor != null) {
1640            // this is used (or misused?) to obtain the deserialized multiview
1641
// topcomponent and set it to FormEditorSupport
1642
FormDataObject formDO = formEditor.getFormDataObject();
1643            formDO.getFormEditorSupport().setTopComponent(callback.getTopComponent());
1644        }
1645    }
1646
1647    public void requestVisible() {
1648        if (multiViewObserver != null)
1649            multiViewObserver.requestVisible();
1650        else
1651            super.requestVisible();
1652    }
1653
1654    public void requestActive() {
1655        if (multiViewObserver != null)
1656            multiViewObserver.requestActive();
1657        else
1658            super.requestActive();
1659    }
1660
1661    public void componentClosed() {
1662        super.componentClosed();
1663        formDesignerOpened = false;
1664        if (formModel != null) {
1665            if (formModelListener != null)
1666                formModel.removeFormModelListener(formModelListener);
1667            topDesignComponent = null;
1668            formModel = null;
1669        }
1670        if (settingsListener != null) {
1671            FormLoaderSettings.getInstance().getPreferences().removePreferenceChangeListener(settingsListener);
1672        }
1673    }
1674
1675    public void componentShowing() {
1676        super.componentShowing();
1677        if (!formEditor.isFormLoaded()) {
1678            formEditor.loadFormDesigner();
1679            if (!formEditor.isFormLoaded()) { // there was a loading error
1680
removeAll();
1681                return;
1682            }
1683        }
1684        if (!initialized) {
1685            initialize();
1686        }
1687        FormEditorSupport.checkFormGroupVisibility();
1688    }
1689
1690    public void componentHidden() {
1691        super.componentHidden();
1692        FormEditorSupport.checkFormGroupVisibility();
1693    }
1694
1695    public void componentOpened() {
1696        super.componentOpened();
1697        formDesignerOpened = true;
1698        if ((formEditor == null) && (multiViewObserver != null)) { // Issue 67879
1699
multiViewObserver.getTopComponent().close();
1700            EventQueue.invokeLater(new Runnable JavaDoc() {
1701                public void run() {
1702                    FormEditorSupport.checkFormGroupVisibility();
1703                }
1704            });
1705        }
1706    }
1707
1708    private boolean formDesignerOpened;
1709    public boolean isClosed() {
1710        return !formDesignerOpened;
1711    }
1712
1713    public CloseOperationState canCloseElement() {
1714        // if this is not the last cloned designer, closing is OK
1715
if (!FormEditorSupport.isLastView(multiViewObserver.getTopComponent()))
1716            return CloseOperationState.STATE_OK;
1717
1718        // return a placeholder state - to be sure our CloseHandler is called
1719
return MultiViewFactory.createUnsafeCloseState(
1720            "ID_FORM_CLOSING", // dummy ID // NOI18N
1721
MultiViewFactory.NOOP_CLOSE_ACTION,
1722            MultiViewFactory.NOOP_CLOSE_ACTION);
1723    }
1724
1725    // -----------
1726
// innerclasses
1727

1728    private class LayoutMapper implements VisualMapper, LayoutConstants {
1729
1730        // -------
1731

1732// public String getTopComponentId() {
1733
// return getTopDesignComponent().getId();
1734
// }
1735

1736        public Rectangle getComponentBounds(String JavaDoc componentId) {
1737            Component visual = getVisualComponent(componentId, true, false);
1738            Rectangle rect = null;
1739            if (visual != null) {
1740                rect = componentBoundsToTop(visual);
1741            }
1742            
1743            if (getLayoutDesigner().logTestCode()) {
1744                getLayoutDesigner().testCode.add(" compBounds.put(\"" + componentId + "\", new Rectangle(" + //NOI18N
1745
rect.x + ", " + rect.y + ", " + rect.width + ", " + rect.height + "));"); //NOI18N
1746
}
1747            
1748            return rect;
1749        }
1750
1751        public Rectangle getContainerInterior(String JavaDoc componentId) {
1752            Component visual = getVisualComponent(componentId, true, false);
1753            if (visual == null)
1754                return null;
1755
1756            RADVisualContainer metacont = (RADVisualContainer)
1757                                          getMetaComponent(componentId);
1758            Container cont = metacont.getContainerDelegate(visual);
1759
1760            Rectangle rect = componentBoundsToTop(cont);
1761            Insets insets = cont.getInsets();
1762            rect.x += insets.left;
1763            rect.y += insets.top;
1764            rect.width -= insets.left + insets.right;
1765            rect.height -= insets.top + insets.bottom;
1766
1767            if (getLayoutDesigner().logTestCode()) {
1768                getLayoutDesigner().testCode.add(" contInterior.put(\"" + componentId + "\", new Rectangle(" + //NOI18N
1769
rect.x + ", " + rect.y + ", " + rect.width + ", " + rect.height + "));"); //NOI18N
1770
}
1771            
1772            return rect;
1773        }
1774
1775        public Dimension getComponentMinimumSize(String JavaDoc componentId) {
1776            Component visual = getVisualComponent(componentId, false, false);
1777            Dimension dim = null;
1778            if (visual != null) {
1779                dim = visual.getMinimumSize();
1780            }
1781            if (getLayoutDesigner().logTestCode()) {
1782                getLayoutDesigner().testCode.add(" compMinSize.put(\"" + componentId + "\", new Dimension(" + //NOI18N
1783
new Double JavaDoc(dim.getWidth()).intValue() + ", " + new Double JavaDoc(dim.getHeight()).intValue() + "));"); //NOI18N
1784
}
1785            return dim;
1786        }
1787
1788        public Dimension getComponentPreferredSize(String JavaDoc componentId) {
1789            Component visual = getVisualComponent(componentId, false, false);
1790            Dimension dim = null;
1791            if (visual != null) {
1792                dim = visual.getPreferredSize();
1793            }
1794            if (getLayoutDesigner().logTestCode()) {
1795                getLayoutDesigner().testCode.add(" compPrefSize.put(\"" + componentId + "\", new Dimension(" + //NOI18N
1796
new Double JavaDoc(dim.getWidth()).intValue() + ", " + new Double JavaDoc(dim.getHeight()).intValue() + "));"); //NOI18N
1797
}
1798            return dim;
1799        }
1800
1801        public boolean hasExplicitPreferredSize(String JavaDoc componentId) {
1802            JComponent visual = (JComponent) getVisualComponent(componentId, false, true);
1803            boolean hasExplPrefSize = false;
1804            if (visual != null) {
1805                hasExplPrefSize = visual.isPreferredSizeSet();
1806            }
1807            if (getLayoutDesigner().logTestCode()) {
1808                getLayoutDesigner().testCode.add(" hasExplicitPrefSize.put(\"" + componentId + "\", new Boolean(" + hasExplPrefSize + "));"); //NOI18N
1809
}
1810            return hasExplPrefSize;
1811        }
1812
1813        public int getBaselinePosition(String JavaDoc componentId, int width, int height) {
1814            int baseLinePos = -1;
1815            JComponent comp = (JComponent) getVisualComponent(componentId, true, true);
1816            // [hack - vertically resizable components cannot be baseline aligned]
1817
// [this should be either solved or filtered in LayoutDragger according to vertical resizability of the component]
1818
if (comp != null && (comp instanceof JScrollPane
1819                                 || comp.getClass().equals(JPanel.class)
1820                                 || comp instanceof JTabbedPane)) {
1821// || comp instanceof JTextArea
1822
// || comp instanceof JTree || comp instanceof JTable || comp instanceof JList
1823
baseLinePos = 0;
1824            }
1825
1826            if (baseLinePos == -1) {
1827                if (comp != null) {
1828                     baseLinePos = Baseline.getBaseline(comp, width, height);
1829                } else {
1830                    baseLinePos = 0;
1831                }
1832            }
1833
1834            if (getLayoutDesigner().logTestCode()) {
1835                String JavaDoc id = componentId + "-" + width + "-" + height; //NOI18N
1836
getLayoutDesigner().testCode.add(" baselinePosition.put(\"" + id + "\", new Integer(" + baseLinePos + "));"); //NOI18N
1837
}
1838
1839            return baseLinePos;
1840        }
1841
1842        public int getPreferredPadding(String JavaDoc comp1Id,
1843                                       String JavaDoc comp2Id,
1844                                       int dimension,
1845                                       int comp2Alignment,
1846                                       int paddingType)
1847        {
1848            String JavaDoc id = null;
1849        if (getLayoutDesigner().logTestCode()) {
1850        id = comp1Id + "-" + comp2Id + "-" + dimension + "-" + comp2Alignment + "-" + paddingType; //NOI18N
1851
}
1852            
1853            JComponent comp1 = (JComponent) getVisualComponent(comp1Id, true, true);
1854            JComponent comp2 = (JComponent) getVisualComponent(comp2Id, true, true);
1855            if (comp1 == null || comp2 == null) { // not JComponents...
1856
if (getLayoutDesigner().logTestCode()) {
1857                    getLayoutDesigner().testCode.add(" prefPadding.put(\"" + id + //NOI18N
1858
"\", new Integer(10)); // comp1Id-comp2Id-dimension-comp2Alignment-paddingType"); //NOI18N
1859
}
1860                return 10; // default distance between components (for non-JComponents)
1861
}
1862
1863            assert dimension == HORIZONTAL || dimension == VERTICAL;
1864            assert comp2Alignment == LEADING || comp2Alignment == TRAILING;
1865            assert paddingType == PADDING_RELATED || paddingType == PADDING_UNRELATED || paddingType == INDENT;
1866
1867            int type = paddingType == INDENT ? LayoutStyle.INDENT :
1868                (paddingType == PADDING_RELATED ? LayoutStyle.RELATED : LayoutStyle.UNRELATED);
1869            int position = 0;
1870            if (dimension == HORIZONTAL) {
1871                if (paddingType == INDENT) {
1872                    position = comp2Alignment == LEADING ?
1873                               SwingConstants.WEST : SwingConstants.EAST;
1874                } else {
1875                    position = comp2Alignment == LEADING ?
1876                               SwingConstants.EAST : SwingConstants.WEST;
1877                }
1878            }
1879            else {
1880                position = comp2Alignment == LEADING ?
1881                           SwingConstants.SOUTH : SwingConstants.NORTH;
1882            }
1883
1884            int prefPadding = FormLAF.getDesignerLayoutStyle().getPreferredGap(comp1, comp2, type, position, null);
1885            
1886            if (getLayoutDesigner().logTestCode()) {
1887                getLayoutDesigner().testCode.add(" prefPadding.put(\"" + id + "\", new Integer(" + prefPadding + //NOI18N
1888
")); // comp1Id-comp2Id-dimension-comp2Alignment-paddingType"); //NOI18N
1889
}
1890            
1891            return prefPadding;
1892        }
1893
1894        public int getPreferredPaddingInParent(String JavaDoc parentId,
1895                                               String JavaDoc compId,
1896                                               int dimension,
1897                                               int compAlignment)
1898        {
1899            String JavaDoc id = null;
1900        if (getLayoutDesigner().logTestCode()) {
1901        id = parentId + "-" + compId + "-" + dimension + "-" + compAlignment; //NOI18N
1902
}
1903            
1904            JComponent comp = null;
1905            Container parent = (Container)getVisualComponent(parentId, true, false);
1906            if (parent != null) {
1907                RADVisualContainer metacont = (RADVisualContainer)
1908                                              getMetaComponent(parentId);
1909                parent = metacont.getContainerDelegate(parent);
1910                comp = (JComponent) getVisualComponent(compId, true, true);
1911            }
1912            if (comp == null) {
1913                if (getLayoutDesigner().logTestCode()) {
1914                    getLayoutDesigner().testCode.add(" prefPaddingInParent.put(\"" + id + //NOI18N
1915
"\", new Integer(10)); // parentId-compId-dimension-compAlignment"); //NOI18N
1916
}
1917                return 10; // default distance from parent border (for non-JComponents)
1918
}
1919            
1920            assert dimension == HORIZONTAL || dimension == VERTICAL;
1921            assert compAlignment == LEADING || compAlignment == TRAILING;
1922
1923            int alignment;
1924
1925            if (dimension == HORIZONTAL) {
1926                if (compAlignment == LEADING) {
1927                    alignment = SwingConstants.WEST;
1928                }
1929                else {
1930                    alignment = SwingConstants.EAST;
1931                }
1932            }
1933            else {
1934                if (compAlignment == LEADING) {
1935                    alignment = SwingConstants.NORTH;
1936                }
1937                else {
1938                    alignment = SwingConstants.SOUTH;
1939                }
1940            }
1941            int prefPadding = FormLAF.getDesignerLayoutStyle().getContainerGap(comp, alignment, parent);
1942
1943            if (getLayoutDesigner().logTestCode()) {
1944                getLayoutDesigner().testCode.add(" prefPaddingInParent.put(\"" + id + "\", new Integer(" + //NOI18N
1945
prefPadding + ")); // parentId-compId-dimension-compAlignment"); //NOI18N
1946
}
1947
1948            return prefPadding;
1949        }
1950
1951        public boolean[] getComponentResizability(String JavaDoc compId, boolean[] resizability) {
1952            resizability[0] = resizability[1] = true;
1953            // [real resizability spec TBD]
1954
return resizability;
1955        }
1956
1957        public void rebuildLayout(String JavaDoc contId) {
1958            replicator.updateContainerLayout((RADVisualContainer)getMetaComponent(contId));
1959            replicator.getLayoutBuilder(contId).doLayout();
1960        }
1961
1962        // -------
1963

1964        private RADComponent getMetaComponent(String JavaDoc compId) {
1965            RADComponent metacomp = formModel.getMetaComponent(compId);
1966            if (metacomp == null) {
1967                RADComponent precreated =
1968                    formModel.getComponentCreator().getPrecreatedMetaComponent();
1969                if (precreated != null && precreated.getId().equals(compId)) {
1970                    metacomp = precreated;
1971                }
1972            }
1973            return metacomp;
1974        }
1975
1976        private Component getVisualComponent(String JavaDoc compId, boolean needVisible, boolean needJComponent) {
1977            Object JavaDoc comp = getComponent(compId);
1978            if (comp == null) {
1979                RADVisualComponent precreated =
1980                    formModel.getComponentCreator().getPrecreatedMetaComponent();
1981                if (precreated != null && precreated.getId().equals(compId)) {
1982                    comp = precreated.getBeanInstance();
1983                }
1984                if (comp == null && !needVisible) {
1985                    RADComponent metacomp = getMetaComponent(compId);
1986                    if (metacomp != null) {
1987                        comp = metacomp.getBeanInstance();
1988                    }
1989                }
1990            }
1991            Class JavaDoc type = needJComponent ? JComponent.class : Component.class;
1992            return comp != null && type.isAssignableFrom(comp.getClass()) ?
1993                   (Component) comp : null;
1994        }
1995
1996    }
1997
1998    // --------
1999

2000    private Collection componentIds() {
2001        List JavaDoc componentIds = new LinkedList();
2002        List JavaDoc selectedComps = getSelectedLayoutComponents();
2003        LayoutModel layoutModel = getFormModel().getLayoutModel();
2004        Iterator iter = selectedComps.iterator();
2005        while (iter.hasNext()) {
2006            RADVisualComponent visualComp = (RADVisualComponent)iter.next();
2007            if ((visualComp.getParentContainer() != null)
2008                && (visualComp.getParentLayoutSupport() == null)
2009                && layoutModel.getLayoutComponent(visualComp.getId()) != null)
2010                componentIds.add(visualComp.getId());
2011        }
2012        return componentIds;
2013    }
2014    
2015    // Listener on FormModel - ensures updating of designer view.
2016
private class FormListener implements FormModelListener, Runnable JavaDoc {
2017
2018        private FormModelEvent[] events;
2019
2020        public void formChanged(final FormModelEvent[] events) {
2021            if (!EventQueue.isDispatchThread()) {
2022                EventQueue.invokeLater(new Runnable JavaDoc() {
2023                    public void run() {
2024                        processEvents(events);
2025                    }
2026                });
2027            } else {
2028                processEvents(events);
2029            }
2030        }
2031
2032        private void processEvents(FormModelEvent[] events) {
2033            boolean lafBlock;
2034            if (events == null) {
2035                lafBlock = true;
2036            }
2037            else {
2038                lafBlock = false;
2039                boolean modifying = false;
2040                for (int i=0; i < events.length; i++) {
2041                    FormModelEvent ev = events[i];
2042                    if (ev.isModifying())
2043                        modifying = true;
2044                    if (ev.getChangeType() == FormModelEvent.COMPONENT_ADDED) {
2045                        lafBlock = true;
2046                        break;
2047                    }
2048                }
2049                if (!modifying)
2050                    return;
2051
2052                assert EventQueue.isDispatchThread();
2053            }
2054
2055            this.events = events;
2056
2057            if (lafBlock) { // Look&Feel UI defaults remapping needed
2058
Locale defaultLocale = switchToDesignLocale(getFormModel());
2059                try {
2060                    FormLAF.executeWithLookAndFeel(this);
2061                }
2062                finally {
2063                    if (defaultLocale != null)
2064                        Locale.setDefault(defaultLocale);
2065                }
2066            }
2067            else run();
2068        }
2069
2070        public void run() {
2071            if (events == null) {
2072                Object JavaDoc originalVisualComp = (topDesignComponent == null) ? null : replicator.getClonedComponent(topDesignComponent);
2073                Dimension originalSize = originalVisualComp instanceof Component ?
2074                    ((Component)originalVisualComp).getSize() : null;
2075
2076                replicator.setTopMetaComponent(topDesignComponent);
2077                Component formClone = (Component) replicator.createClone();
2078                if (formClone != null) {
2079                    formClone.setVisible(true);
2080                    componentLayer.setTopDesignComponent(formClone);
2081                    if (originalSize != null) {
2082                        componentLayer.setDesignerSize(originalSize);
2083                        checkDesignerSize();
2084                    }
2085                    else setupDesignerSize();
2086                    if (getLayoutDesigner() != null)
2087                        getLayoutDesigner().externalSizeChangeHappened();
2088                    // Must be invoked later. ComponentLayer doesn't have a peer (yet)
2089
// when the form is opened and validate does nothing on components
2090
// without peer.
2091
EventQueue.invokeLater(new Runnable JavaDoc() {
2092                        public void run() {
2093                            updateComponentLayer(false);
2094                        }
2095                    });
2096                }
2097                return;
2098            }
2099
2100            FormModelEvent[] events = this.events;
2101            this.events = null;
2102
2103            int prevType = 0;
2104            ComponentContainer prevContainer = null;
2105            boolean updateDone = false;
2106            boolean deriveDesignerSize = false;
2107
2108            for (int i=0; i < events.length; i++) {
2109                FormModelEvent ev = events[i];
2110                int type = ev.getChangeType();
2111                ComponentContainer metacont = ev.getContainer();
2112
2113                if (type == FormModelEvent.CONTAINER_LAYOUT_EXCHANGED
2114                    || type == FormModelEvent.CONTAINER_LAYOUT_CHANGED
2115                    || type == FormModelEvent.COMPONENT_LAYOUT_CHANGED)
2116                {
2117                    if ((prevType != FormModelEvent.CONTAINER_LAYOUT_EXCHANGED
2118                         && prevType != FormModelEvent.CONTAINER_LAYOUT_CHANGED
2119                         && prevType != FormModelEvent.COMPONENT_LAYOUT_CHANGED)
2120                        || prevContainer != metacont)
2121                    {
2122                        replicator.updateContainerLayout((RADVisualContainer)
2123                                                         metacont);
2124                        updateDone = true;
2125                    }
2126                }
2127                else if (type == FormModelEvent.COMPONENT_ADDED) {
2128                    if ((metacont instanceof RADVisualContainer
2129                            || metacont instanceof RADMenuComponent)
2130                        && (prevType != FormModelEvent.COMPONENT_ADDED
2131                            || prevContainer != metacont))
2132                    {
2133                        replicator.updateAddedComponents(metacont);
2134                        updateDone = true;
2135                    }
2136                }
2137                else if (type == FormModelEvent.COMPONENT_REMOVED) {
2138                    RADComponent removed = ev.getComponent();
2139
2140                    // if the top designed component (or some of its parents)
2141
// was removed then whole designer view must be recreated
2142
if (removed instanceof RADVisualComponent
2143                        && (removed == topDesignComponent
2144                            || removed.isParentComponent(topDesignComponent)))
2145                    {
2146                        resetTopDesignComponent(false);
2147                        updateWholeDesigner();
2148                        return;
2149                    }
2150                    else {
2151                        replicator.removeComponent(ev.getComponent(),
2152                                                   ev.getContainer());
2153                        updateDone = true;
2154                    }
2155                }
2156                else if (type == FormModelEvent.COMPONENTS_REORDERED) {
2157                    if (prevType != FormModelEvent.COMPONENTS_REORDERED
2158                        || prevContainer != metacont)
2159                    {
2160                        replicator.reorderComponents(metacont);
2161                        updateDone = true;
2162                    }
2163                }
2164                else if (type == FormModelEvent.COMPONENT_PROPERTY_CHANGED) {
2165
2166                    RADProperty eventProperty = ev.getComponentProperty();
2167                    RADComponent eventComponent = ev.getComponent();
2168                    
2169                    replicator.updateComponentProperty(eventProperty);
2170                    updateConnectedProperties(eventProperty, eventComponent);
2171                    
2172                    updateDone = true;
2173                }
2174                else if (type == FormModelEvent.SYNTHETIC_PROPERTY_CHANGED
2175                         && PROP_DESIGNER_SIZE.equals(ev.getPropertyName()))
2176                {
2177                    Dimension size = (Dimension) ev.getNewPropertyValue();
2178                    if (size != null) {
2179                        componentLayer.setDesignerSize(size);
2180                        deriveDesignerSize = false;
2181                        updateDone = true;
2182                    }
2183                    else { // null size to compute designer size based on content (from resetDesignerSize)
2184
deriveDesignerSize = true;
2185                        updateDone = true;
2186                    }
2187                }
2188
2189                prevType = type;
2190                prevContainer = metacont;
2191            }
2192
2193            if (updateDone) {
2194                if (deriveDesignerSize) { // compute from preferred size
2195
setupDesignerSize();
2196                }
2197                else { // check if not smaller than minimum size
2198
checkDesignerSize();
2199                }
2200                LayoutDesigner layoutDesigner = getLayoutDesigner();
2201                if ((layoutDesigner != null) && formModel.isCompoundEditInProgress()) {
2202                    getLayoutDesigner().externalSizeChangeHappened();
2203                }
2204                updateComponentLayer(true);
2205            }
2206        }
2207        
2208        private void updateConnectedProperties(RADProperty eventProperty, RADComponent eventComponent){
2209            for (RADComponent component : formModel.getAllComponents()){
2210                RADProperty[] properties = component.getKnownBeanProperties();
2211                for(int i = 0; i < properties.length; i++){
2212                    try{
2213                        if (properties[i].isChanged()) {
2214                            Object JavaDoc value = properties[i].getValue();
2215                            if (value instanceof RADConnectionPropertyEditor.RADConnectionDesignValue) {
2216                                RADConnectionPropertyEditor.RADConnectionDesignValue propertyValue =
2217                                    (RADConnectionPropertyEditor.RADConnectionDesignValue)value;
2218
2219                                if (propertyValue.getRADComponent() != null
2220                                   && propertyValue.getProperty() != null
2221                                   && eventComponent.getName().equals(propertyValue.getRADComponent().getName())
2222                                   && eventProperty.getName().equals(propertyValue.getProperty().getName())) {
2223
2224                                    replicator.updateComponentProperty(properties[i]);
2225                                }
2226                            }
2227                        }
2228                    } catch(Exception JavaDoc e){
2229                        ErrorManager.getDefault().notify(e);
2230                    }
2231                }
2232            }
2233                                
2234        }
2235    }
2236    
2237    /** Lookup that excludes nodes. */
2238    private static class NoNodeLookup extends Lookup {
2239        private final Lookup delegate;
2240        
2241        public NoNodeLookup(Lookup delegate) {
2242            this.delegate = delegate;
2243        }
2244        
2245        public Object JavaDoc lookup(Class JavaDoc clazz) {
2246            return (clazz == Node.class) ? null : delegate.lookup(clazz);
2247        }
2248        
2249        public Lookup.Result lookup(Lookup.Template template) {
2250            if (template.getType() == Node.class) {
2251                return Lookup.EMPTY.lookup(new Lookup.Template(Node.class));
2252            } else {
2253                return delegate.lookup(template);
2254            }
2255        }
2256    }
2257    
2258    /**
2259     * Action that aligns selected components in the specified direction.
2260     */

2261    private class AlignAction extends AbstractAction {
2262        // PENDING change to icons provided by Dusan
2263
private static final String JavaDoc ICON_BASE = "org/netbeans/modules/form/resources/align_"; // NOI18N
2264
/** Dimension to align in. */
2265        private int dimension;
2266        /** Requested alignment. */
2267        private int alignment;
2268        /** Group/Align action. */
2269        private boolean closed;
2270        
2271        /**
2272         * Creates action that aligns selected components in the specified direction.
2273         *
2274         * @param dimension dimension to align in.
2275         * @param alignment requested alignment.
2276         */

2277        AlignAction(int dimension, int alignment, boolean closed) {
2278            this.dimension = dimension;
2279            this.alignment = alignment;
2280            this.closed = closed;
2281            boolean horizontal = (dimension == LayoutConstants.HORIZONTAL);
2282            boolean leading = (alignment == LayoutConstants.LEADING);
2283            String JavaDoc code;
2284            if (alignment == LayoutConstants.CENTER) {
2285                code = (horizontal ? "ch" : "cv"); // NOI18N
2286
} else {
2287                code = (horizontal ? (leading ? "l" : "r") : (leading ? "u" : "d")); // NOI18N
2288
}
2289            String JavaDoc iconResource = ICON_BASE + code + ".png"; // NOI18N
2290
putValue(Action.SMALL_ICON, new ImageIcon(Utilities.loadImage(iconResource)));
2291            putValue(Action.SHORT_DESCRIPTION, FormUtils.getBundleString("CTL_AlignAction_" + code)); // NOI18N
2292
setEnabled(false);
2293        }
2294        
2295        /**
2296         * Performs the alignment of selected components.
2297         *
2298         * @param e event that invoked the action.
2299         */

2300        public void actionPerformed(ActionEvent e) {
2301            align(closed, dimension, alignment);
2302        }
2303        
2304        public int getDimension() {
2305            return dimension;
2306        }
2307        
2308        public int getAlignment() {
2309            return alignment;
2310        }
2311        
2312    }
2313    /**
2314     * Action that aligns selected components in the specified direction.
2315     */

2316    private class ResizabilityAction extends AbstractAction {
2317        // PENDING change to icons provided by Dusan
2318
private static final String JavaDoc ICON_BASE = "org/netbeans/modules/form/resources/resize_"; // NOI18N
2319
/** Dimension of resizability. */
2320        private int dimension;
2321        
2322        /**
2323         * Creates action that changes the resizability of the component.
2324         *
2325         * @param dimension dimension of the resizability
2326         */

2327        ResizabilityAction(int dimension) {
2328            this.dimension = dimension;
2329            String JavaDoc code = (dimension == LayoutConstants.HORIZONTAL) ? "h" : "v"; // NOI18N
2330
String JavaDoc iconResource = ICON_BASE + code + ".png"; // NOI18N
2331
putValue(Action.SMALL_ICON, new ImageIcon(Utilities.loadImage(iconResource)));
2332            putValue(Action.SHORT_DESCRIPTION, FormUtils.getBundleString("CTL_ResizeButton_" + code)); // NOI18N
2333
setEnabled(false);
2334        }
2335        
2336        /**
2337         * Performs the resizability change of selected components.
2338         *
2339         * @param e event that invoked the action.
2340         */

2341        public void actionPerformed(ActionEvent e) {
2342            FormModel formModel = getFormModel();
2343            LayoutModel layoutModel = formModel.getLayoutModel();
2344            Object JavaDoc layoutUndoMark = layoutModel.getChangeMark();
2345            javax.swing.undo.UndoableEdit JavaDoc ue = layoutModel.getUndoableEdit();
2346            boolean autoUndo = true;
2347            LayoutDesigner layoutDesigner = getLayoutDesigner();
2348            Collection componentIds = componentIds();
2349            Set containers = new HashSet();
2350            try {
2351                Iterator iter = componentIds.iterator();
2352                while (iter.hasNext()) {
2353                    String JavaDoc compId = (String JavaDoc)iter.next();
2354                    LayoutComponent layoutComp = layoutModel.getLayoutComponent(compId);
2355                    boolean resizing = (getResizabilityButtons()[dimension]).isSelected();
2356                    if (layoutDesigner.isComponentResizing(layoutComp, dimension) != resizing) {
2357                        layoutDesigner.setComponentResizing(layoutComp, dimension, resizing);
2358                        RADVisualComponent comp = (RADVisualComponent)formModel.getMetaComponent(compId);
2359                        containers.add(comp.getParentContainer());
2360                    }
2361                }
2362                autoUndo = false;
2363            } finally {
2364                Iterator iter = containers.iterator();
2365                while (iter.hasNext()) {
2366                    formModel.fireContainerLayoutChanged((RADVisualContainer)iter.next(), null, null, null);
2367                }
2368                if (!layoutUndoMark.equals(layoutModel.getChangeMark())) {
2369                    formModel.addUndoableEdit(ue);
2370                }
2371                if (autoUndo) {
2372                    formModel.forceUndoOfCompoundEdit();
2373                }
2374            }
2375        }
2376    }
2377    
2378    static class FormProxyLookup extends ProxyLookup {
2379        
2380        FormProxyLookup(Lookup[] lookups) {
2381            super(lookups);
2382        }
2383        
2384        Lookup[] getSubLookups() {
2385            return getLookups();
2386        }
2387        
2388        void setSubLookups(Lookup[] lookups) {
2389            setLookups(lookups);
2390        }
2391        
2392    }
2393    
2394}
2395
Popular Tags