~ubuntu-branches/ubuntu/trusty/netbeans/trusty

« back to all changes in this revision

Viewing changes to form/src/org/netbeans/modules/form/layoutsupport/LayoutSupportManager.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
6
 * The contents of this file are subject to the terms of either the GNU
 
7
 * General Public License Version 2 only ("GPL") or the Common
 
8
 * Development and Distribution License("CDDL") (collectively, the
 
9
 * "License"). You may not use this file except in compliance with the
 
10
 * License. You can obtain a copy of the License at
 
11
 * http://www.netbeans.org/cddl-gplv2.html
 
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 
13
 * specific language governing permissions and limitations under the
 
14
 * License.  When distributing the software, include this License Header
 
15
 * Notice in each file and include the License file at
 
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 
17
 * particular file as subject to the "Classpath" exception as provided
 
18
 * by Sun in the GPL Version 2 section of the License file that
 
19
 * accompanied this code. If applicable, add the following below the
 
20
 * License Header, with the fields enclosed by brackets [] replaced by
 
21
 * your own identifying information:
 
22
 * "Portions Copyrighted [year] [name of copyright owner]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
26
 * The Original Software is NetBeans. The Initial Developer of the Original
 
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 
28
 * Microsystems, Inc. All Rights Reserved.
 
29
 *
 
30
 * If you wish your version of this file to be governed by only the CDDL
 
31
 * or only the GPL Version 2, indicate your decision by adding
 
32
 * "[Contributor] elects to include this software in this distribution
 
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 
34
 * single choice of license, a recipient has the option to distribute
 
35
 * your version of this file under either the CDDL, the GPL Version 2 or
 
36
 * to extend the choice of license to its licensees as provided above.
 
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 
38
 * Version 2 license, then the option applies only if the new code is
 
39
 * made subject to such option by the copyright holder.
 
40
 */
 
41
 
 
42
package org.netbeans.modules.form.layoutsupport;
 
43
 
 
44
import java.awt.*;
 
45
import java.beans.*;
 
46
import java.util.*;
 
47
 
 
48
import org.openide.nodes.*;
 
49
 
 
50
import org.netbeans.modules.form.*;
 
51
import org.netbeans.modules.form.codestructure.*;
 
52
import org.netbeans.modules.form.layoutsupport.delegates.NullLayoutSupport;
 
53
import org.netbeans.modules.form.fakepeer.FakePeerSupport;
 
54
 
 
55
/**
 
56
 * Main class of general layout support infrastructure. Connects form editor
 
57
 * metadata with specialized LayoutSupportDelegate implementations (layout
 
58
 * specific functionality is delegated to the right LayoutSupportDelegate).
 
59
 *
 
60
 * @author Tomas Pavek
 
61
 */
 
62
 
 
63
public final class LayoutSupportManager implements LayoutSupportContext {
 
64
 
 
65
    // possible component resizing directions (bit flag constants)
 
66
    public static final int RESIZE_UP = 1;
 
67
    public static final int RESIZE_DOWN = 2;
 
68
    public static final int RESIZE_LEFT = 4;
 
69
    public static final int RESIZE_RIGHT = 8;
 
70
 
 
71
    private LayoutSupportDelegate layoutDelegate;
 
72
    private boolean needInit;
 
73
    private boolean initializeFromInstance;
 
74
    private boolean initializeFromCode;
 
75
 
 
76
    private Node.PropertySet[] propertySets;
 
77
 
 
78
    private LayoutListener layoutListener;
 
79
 
 
80
    private RADVisualContainer metaContainer;
 
81
 
 
82
    private Container primaryContainer; // bean instance from metaContainer
 
83
    private Container primaryContainerDelegate; // container delegate for it
 
84
 
 
85
    private CodeStructure codeStructure;
 
86
 
 
87
    private CodeExpression containerCodeExpression;
 
88
    private CodeExpression containerDelegateCodeExpression;
 
89
 
 
90
    // ----------
 
91
    // initialization
 
92
 
 
93
    // initialization for a new container, layout delegate is set to null
 
94
    public LayoutSupportManager(RADVisualContainer container,
 
95
                                CodeStructure codeStructure)
 
96
    {
 
97
        this.metaContainer = container;
 
98
        this.codeStructure = codeStructure;
 
99
    }
 
100
 
 
101
    /**
 
102
     * Creation and initialization of a layout delegate for a new container.
 
103
     * @return false if suitable layout delegate is not found
 
104
     * @throw IllegalArgumentException if the container instance is not empty
 
105
     */
 
106
    public boolean prepareLayoutDelegate(boolean fromCode, boolean initialize)
 
107
        throws Exception
 
108
    {
 
109
        LayoutSupportDelegate delegate = null;
 
110
        LayoutManager lmInstance = null;
 
111
 
 
112
        FormModel formModel = metaContainer.getFormModel();
 
113
        LayoutSupportRegistry layoutRegistry =
 
114
            LayoutSupportRegistry.getRegistry(formModel);
 
115
 
 
116
        // first try to find a dedicated layout delegate (for the container)
 
117
        Class layoutDelegateClass = layoutRegistry.getSupportClassForContainer(
 
118
                                                  metaContainer.getBeanClass());
 
119
 
 
120
        if (layoutDelegateClass != null) {
 
121
            delegate = LayoutSupportRegistry.createSupportInstance(layoutDelegateClass);
 
122
            if (!fromCode && !delegate.checkEmptyContainer(getPrimaryContainer())) {
 
123
                RuntimeException ex = new IllegalArgumentException();
 
124
                org.openide.ErrorManager.getDefault().annotate(
 
125
                    ex, AbstractLayoutSupport.getBundle().getString(
 
126
                                        "MSG_ERR_NonEmptyContainer")); // NOI18N
 
127
                throw ex;
 
128
            }
 
129
        }
 
130
        else {
 
131
            // find a general layout delegate (for LayoutManager of the container)
 
132
            if (fromCode) { // initialization from code
 
133
                Iterator it = CodeStructure.getDefinedStatementsIterator(
 
134
                                      getContainerDelegateCodeExpression());
 
135
                CodeStatement[] statements =
 
136
                    CodeStructure.filterStatements(
 
137
                        it, AbstractLayoutSupport.getSetLayoutMethod());
 
138
 
 
139
                if (statements.length > 0) { // setLayout method found
 
140
                    CodeExpressionOrigin layoutOrigin =
 
141
                        statements[0].getStatementParameters()[0].getOrigin();
 
142
                    delegate = layoutRegistry.createSupportForLayout(
 
143
                                                  layoutOrigin.getType());
 
144
                    // handle special case of null layout
 
145
                    if (delegate == null)
 
146
                        if (layoutOrigin.getType() == LayoutManager.class
 
147
                            && layoutOrigin.getCreationParameters().length == 0
 
148
                            && layoutOrigin.getParentExpression() == null
 
149
                            && "null".equals(layoutOrigin.getJavaCodeString( // NOI18N
 
150
                                                                  null, null)))
 
151
                        {
 
152
                            delegate = new NullLayoutSupport();
 
153
                        }
 
154
                        else return false;
 
155
                }
 
156
            }
 
157
 
 
158
            if (delegate == null) { // initialization from LayoutManager instance
 
159
                Container contDel = getPrimaryContainerDelegate();
 
160
                if (contDel.getComponentCount() == 0) {
 
161
                    // we can still handle only empty containers ...
 
162
                    lmInstance = contDel.getLayout();
 
163
                    delegate = lmInstance != null ?
 
164
                        layoutRegistry.createSupportForLayout(lmInstance.getClass()) :
 
165
                        new NullLayoutSupport();
 
166
                }
 
167
                else {
 
168
                    RuntimeException ex = new IllegalArgumentException();
 
169
                    org.openide.ErrorManager.getDefault().annotate(
 
170
                        ex, AbstractLayoutSupport.getBundle().getString(
 
171
                                            "MSG_ERR_NonEmptyContainer")); // NOI18N
 
172
                    throw ex;
 
173
                }
 
174
            }
 
175
        }
 
176
 
 
177
        if (delegate == null)
 
178
            return false;
 
179
 
 
180
        if (initialize) {
 
181
            setLayoutDelegate(delegate, fromCode);
 
182
        }
 
183
        else {
 
184
            layoutDelegate = delegate;
 
185
            needInit = true;
 
186
            initializeFromInstance = lmInstance != null;
 
187
            initializeFromCode = fromCode;
 
188
        }
 
189
 
 
190
        return true;
 
191
    }
 
192
 
 
193
    public void initializeLayoutDelegate() throws Exception {
 
194
        if (layoutDelegate != null && needInit) {
 
195
            LayoutManager lmInstance = initializeFromInstance ?
 
196
                    getPrimaryContainerDelegate().getLayout() : null;
 
197
            layoutDelegate.initialize(this, lmInstance, initializeFromCode);
 
198
            fillLayout(null);
 
199
            getPropertySets(); // force properties and listeners creation
 
200
            needInit = false;
 
201
        }
 
202
    }
 
203
 
 
204
    public void setLayoutDelegate(LayoutSupportDelegate newDelegate,
 
205
                                  boolean fromCode)
 
206
        throws Exception
 
207
    {
 
208
        LayoutConstraints[] oldConstraints;
 
209
        LayoutSupportDelegate oldDelegate = layoutDelegate;
 
210
 
 
211
        if (layoutDelegate != null
 
212
                && (layoutDelegate != newDelegate || !fromCode))
 
213
            oldConstraints = removeLayoutDelegate(true);
 
214
        else
 
215
            oldConstraints = null;
 
216
 
 
217
        layoutDelegate = newDelegate;
 
218
        propertySets = null;
 
219
        needInit = false;
 
220
 
 
221
        if (layoutDelegate != null) {
 
222
            try {
 
223
                layoutDelegate.initialize(this, null, fromCode);
 
224
                if (!fromCode)
 
225
                    fillLayout(oldConstraints);
 
226
                getPropertySets(); // force properties and listeners creation
 
227
            }
 
228
            catch (Exception ex) {
 
229
                removeLayoutDelegate(false);
 
230
                layoutDelegate = oldDelegate;
 
231
                if (layoutDelegate != null)
 
232
                    fillLayout(null);
 
233
                throw ex;
 
234
            }
 
235
        }
 
236
    }
 
237
 
 
238
    public LayoutSupportDelegate getLayoutDelegate() {
 
239
        return layoutDelegate;
 
240
    }
 
241
 
 
242
    public void setUnknownLayoutDelegate(boolean fromCode) {
 
243
        try {
 
244
            setLayoutDelegate(new UnknownLayoutSupport(), fromCode);
 
245
        }
 
246
        catch (Exception ex) { // nothing should happen, ignore
 
247
            ex.printStackTrace();
 
248
        }
 
249
    }
 
250
 
 
251
    public boolean isUnknownLayout() {
 
252
        return layoutDelegate == null
 
253
               || layoutDelegate instanceof UnknownLayoutSupport;
 
254
    }
 
255
 
 
256
    // copy layout delegate from another container
 
257
    public void copyLayoutDelegateFrom(
 
258
                    LayoutSupportManager sourceLayoutSupport,
 
259
                    RADVisualComponent[] newMetaComps)
 
260
    {
 
261
        LayoutSupportDelegate sourceDelegate =
 
262
            sourceLayoutSupport.getLayoutDelegate();
 
263
 
 
264
        int componentCount = sourceDelegate.getComponentCount();
 
265
 
 
266
        Container cont = getPrimaryContainer();
 
267
        Container contDel = getPrimaryContainerDelegate();
 
268
 
 
269
        if (layoutDelegate != null)
 
270
            removeLayoutDelegate(false);
 
271
 
 
272
        CodeExpression[] compExps = new CodeExpression[componentCount];
 
273
        Component[] primaryComps = new Component[componentCount];
 
274
 
 
275
        for (int i=0; i < componentCount; i++) {
 
276
            RADVisualComponent metacomp = newMetaComps[i];
 
277
            compExps[i] = metacomp.getCodeExpression();
 
278
            primaryComps[i] = (Component) metacomp.getBeanInstance();
 
279
            ensureFakePeerAttached(primaryComps[i]);
 
280
        }
 
281
 
 
282
        LayoutSupportDelegate newDelegate =
 
283
            sourceDelegate.cloneLayoutSupport(this, compExps);
 
284
 
 
285
        newDelegate.setLayoutToContainer(cont, contDel);
 
286
        newDelegate.addComponentsToContainer(cont, contDel, primaryComps, 0);
 
287
 
 
288
        layoutDelegate = newDelegate;
 
289
 
 
290
        // Ensure correct propagation of copied properties (issue 50011, 72351)
 
291
        try {
 
292
            layoutDelegate.acceptContainerLayoutChange(null);
 
293
        } catch (PropertyVetoException pvex) {
 
294
            // should not happen
 
295
        }
 
296
    }
 
297
 
 
298
    public void clearPrimaryContainer() {
 
299
        layoutDelegate.clearContainer(getPrimaryContainer(),
 
300
                                      getPrimaryContainerDelegate());
 
301
    }
 
302
 
 
303
    public RADVisualContainer getMetaContainer() {
 
304
        return metaContainer;
 
305
    }
 
306
 
 
307
//    public boolean supportsArranging() {
 
308
//        return layoutDelegate instanceof LayoutSupportArranging;
 
309
//    }
 
310
 
 
311
    private LayoutConstraints[] removeLayoutDelegate(
 
312
                                    boolean extractConstraints)
 
313
    {
 
314
        CodeGroup code = layoutDelegate.getLayoutCode();
 
315
        if (code != null)
 
316
            CodeStructure.removeStatements(code.getStatementsIterator());
 
317
 
 
318
        int componentCount = layoutDelegate.getComponentCount();
 
319
        LayoutConstraints[] constraints = null;
 
320
 
 
321
        if (componentCount > 0) {
 
322
            RADVisualComponent[] metacomps = metaContainer.getSubComponents();
 
323
            if (metacomps.length == componentCount) { // robustness: might be called after failed layout initialization
 
324
                if (extractConstraints)
 
325
                    constraints = new LayoutConstraints[componentCount];
 
326
 
 
327
                for (int i=0; i < componentCount; i++) {
 
328
                    LayoutConstraints constr = layoutDelegate.getConstraints(i);
 
329
                    if (extractConstraints)
 
330
                        constraints[i] = constr;
 
331
                    if (constr != null)
 
332
                        metacomps[i].setLayoutConstraints(layoutDelegate.getClass(),
 
333
                                                          constr);
 
334
                    code = layoutDelegate.getComponentCode(i);
 
335
                    if (code != null)
 
336
                        CodeStructure.removeStatements(code.getStatementsIterator());
 
337
                }
 
338
            }
 
339
        }
 
340
 
 
341
        layoutDelegate.removeAll();
 
342
        layoutDelegate.clearContainer(getPrimaryContainer(),
 
343
                                      getPrimaryContainerDelegate());
 
344
        layoutDelegate = null;
 
345
 
 
346
        return constraints;
 
347
    }
 
348
 
 
349
    private void fillLayout(LayoutConstraints[] oldConstraints) {
 
350
        RADVisualComponent[] metacomps = metaContainer.getSubComponents();
 
351
        int componentCount = metacomps.length;
 
352
 
 
353
        CodeExpression[] compExps = new CodeExpression[componentCount];
 
354
        Component[] designComps = new Component[componentCount];
 
355
        Component[] primaryComps = new Component[componentCount];
 
356
        LayoutConstraints[] newConstraints = new LayoutConstraints[componentCount];
 
357
 
 
358
        FormDesigner designer = FormEditor.getFormDesigner(metaContainer.getFormModel());
 
359
 
 
360
        for (int i=0; i < componentCount; i++) {
 
361
            RADVisualComponent metacomp = metacomps[i];
 
362
 
 
363
            compExps[i] = metacomp.getCodeExpression();
 
364
            primaryComps[i] = (Component) metacomp.getBeanInstance();
 
365
            ensureFakePeerAttached(primaryComps[i]);
 
366
            newConstraints[i] = metacomp.getLayoutConstraints(
 
367
                                             layoutDelegate.getClass());
 
368
 
 
369
            Component comp = designer != null ?
 
370
                            (Component) designer.getComponent(metacomp) : null;
 
371
            designComps[i] = comp != null ?
 
372
                             comp : (Component) metacomp.getBeanInstance();
 
373
        }
 
374
 
 
375
        if (oldConstraints != null)
 
376
            layoutDelegate.convertConstraints(oldConstraints,
 
377
                                              newConstraints,
 
378
                                              designComps);
 
379
 
 
380
        if (componentCount > 0) {
 
381
            layoutDelegate.acceptNewComponents(compExps, newConstraints, 0);
 
382
            layoutDelegate.addComponents(compExps, newConstraints, 0);
 
383
 
 
384
            for (int i=0; i < componentCount; i++)
 
385
                metacomps[i].resetConstraintsProperties();
 
386
        }
 
387
 
 
388
        // setup primary container
 
389
        Container cont = getPrimaryContainer();
 
390
        Container contDel = getPrimaryContainerDelegate();
 
391
//        layoutDelegate.clearContainer(cont, contDel);
 
392
        layoutDelegate.setLayoutToContainer(cont, contDel);
 
393
        if (componentCount > 0)
 
394
            layoutDelegate.addComponentsToContainer(cont, contDel,
 
395
                                                    primaryComps, 0);
 
396
    }
 
397
 
 
398
    // ---------
 
399
    // public API delegated to LayoutSupportDelegate
 
400
 
 
401
    public boolean isDedicated() {
 
402
        return layoutDelegate.isDedicated();
 
403
    }
 
404
 
 
405
    public Class getSupportedClass() {
 
406
        return layoutDelegate.getSupportedClass();
 
407
    }
 
408
 
 
409
    // node presentation
 
410
    public boolean shouldHaveNode() {
 
411
        return layoutDelegate.shouldHaveNode();
 
412
    }
 
413
 
 
414
    public String getDisplayName() {
 
415
        return layoutDelegate.getDisplayName();
 
416
    }
 
417
 
 
418
    public Image getIcon(int type) {
 
419
        return layoutDelegate.getIcon(type);
 
420
    }
 
421
 
 
422
    // properties and customizer
 
423
    public Node.PropertySet[] getPropertySets() {
 
424
        if (propertySets == null) {
 
425
            if (layoutDelegate == null) return new Node.PropertySet[0]; // Issue 63916
 
426
            propertySets = layoutDelegate.getPropertySets();
 
427
 
 
428
            for (int i=0; i < propertySets.length; i++) {
 
429
                Node.Property[] props = propertySets[i].getProperties();
 
430
                for (int j=0; j < props.length; j++)
 
431
                    if (props[j] instanceof FormProperty) {
 
432
                        FormProperty prop = (FormProperty) props[j];
 
433
                        prop.addVetoableChangeListener(getLayoutListener());
 
434
                        prop.addPropertyChangeListener(getLayoutListener());
 
435
                    }
 
436
            }
 
437
        }
 
438
        return propertySets;
 
439
    }
 
440
 
 
441
    public Node.Property[] getAllProperties() {
 
442
        if (layoutDelegate instanceof AbstractLayoutSupport)
 
443
            return ((AbstractLayoutSupport)layoutDelegate).getAllProperties();
 
444
 
 
445
        java.util.List<Node.Property> allPropsList = new ArrayList<Node.Property>();
 
446
        for (int i=0; i < propertySets.length; i++) {
 
447
            Node.Property[] props = propertySets[i].getProperties();
 
448
            for (int j=0; j < props.length; j++)
 
449
                allPropsList.add(props[j]);
 
450
        }
 
451
 
 
452
        Node.Property[] allProperties = new Node.Property[allPropsList.size()];
 
453
        allPropsList.toArray(allProperties);
 
454
        return allProperties;
 
455
    }
 
456
 
 
457
    public Node.Property getLayoutProperty(String name) {
 
458
        if (layoutDelegate instanceof AbstractLayoutSupport)
 
459
            return ((AbstractLayoutSupport)layoutDelegate).getProperty(name);
 
460
 
 
461
        Node.Property[] properties = getAllProperties();
 
462
        for (int i=0; i < properties.length; i++)
 
463
            if (name.equals(properties[i].getName()))
 
464
                return properties[i];
 
465
 
 
466
        return null;
 
467
    }
 
468
 
 
469
    public Class getCustomizerClass() {
 
470
        return layoutDelegate.getCustomizerClass();
 
471
    }
 
472
 
 
473
    public Component getSupportCustomizer() {
 
474
        return layoutDelegate.getSupportCustomizer();
 
475
    }
 
476
 
 
477
    // code meta data
 
478
    public CodeGroup getLayoutCode() {
 
479
        return layoutDelegate.getLayoutCode();
 
480
    }
 
481
 
 
482
    public CodeGroup getComponentCode(int index) {
 
483
        return layoutDelegate.getComponentCode(index);
 
484
    }
 
485
 
 
486
    public CodeGroup getComponentCode(RADVisualComponent metacomp) {
 
487
        int index = metaContainer.getIndexOf(metacomp);
 
488
        return index >= 0 && index < layoutDelegate.getComponentCount() ?
 
489
               layoutDelegate.getComponentCode(index) : null;
 
490
    }
 
491
 
 
492
    public int getComponentCount() {
 
493
        return layoutDelegate.getComponentCount();
 
494
    }
 
495
 
 
496
    // data validation
 
497
    public void acceptNewComponents(RADVisualComponent[] components,
 
498
                                    LayoutConstraints[] constraints,
 
499
                                    int index)
 
500
    {
 
501
        CodeExpression[] compExps = new CodeExpression[components.length];
 
502
        for (int i=0; i < components.length; i++)
 
503
            compExps[i] = components[i].getCodeExpression();
 
504
 
 
505
        layoutDelegate.acceptNewComponents(compExps, constraints, index);
 
506
    }
 
507
 
 
508
    // components adding/removing
 
509
    public void addComponents(RADVisualComponent[] components,
 
510
                              LayoutConstraints[] constraints,
 
511
                              int index)
 
512
    {
 
513
        CodeExpression[] compExps = new CodeExpression[components.length];
 
514
        Component[] comps = new Component[components.length];
 
515
 
 
516
        for (int i=0; i < components.length; i++) {
 
517
            compExps[i] = components[i].getCodeExpression();
 
518
            comps[i] = (Component) components[i].getBeanInstance();
 
519
            ensureFakePeerAttached(comps[i]);
 
520
        }
 
521
 
 
522
        if (index < 0)
 
523
            index = layoutDelegate.getComponentCount();
 
524
 
 
525
        layoutDelegate.addComponents(compExps, constraints, index);
 
526
 
 
527
        for (int i=0; i < components.length; i++)
 
528
            components[i].resetConstraintsProperties();
 
529
 
 
530
        layoutDelegate.addComponentsToContainer(getPrimaryContainer(),
 
531
                                                getPrimaryContainerDelegate(),
 
532
                                                comps, index);
 
533
    }
 
534
 
 
535
    public void removeComponent(RADVisualComponent metacomp, int index) {
 
536
        // first store constraints in the meta component
 
537
        LayoutConstraints constr = layoutDelegate.getConstraints(index);
 
538
        if (constr != null)
 
539
            metacomp.setLayoutConstraints(layoutDelegate.getClass(), constr);
 
540
 
 
541
        // remove code
 
542
        CodeStructure.removeStatements(
 
543
            layoutDelegate.getComponentCode(index).getStatementsIterator());
 
544
 
 
545
        // remove the component from layout
 
546
        layoutDelegate.removeComponent(index);
 
547
 
 
548
        // remove the component instance from the primary container instance
 
549
        if (!layoutDelegate.removeComponentFromContainer(
 
550
                                getPrimaryContainer(),
 
551
                                getPrimaryContainerDelegate(),
 
552
                                (Component)metacomp.getBeanInstance()))
 
553
        {   // layout delegate does not support removing individual components,
 
554
            // so we clear the container and add the remaining components again
 
555
            layoutDelegate.clearContainer(getPrimaryContainer(),
 
556
                                          getPrimaryContainerDelegate());
 
557
 
 
558
            RADVisualComponent[] metacomps = metaContainer.getSubComponents();
 
559
            if (metacomps.length > 1) {
 
560
                // we rely on that metacomp was not removed from the model yet
 
561
                Component[] comps = new Component[metacomps.length-1];
 
562
                for (int i=0; i < metacomps.length; i++) {
 
563
                    if (i != index) {
 
564
                        Component comp = (Component) metacomps[i].getBeanInstance();
 
565
                        ensureFakePeerAttached(comp);
 
566
                        comps[i < index ? i : i-1] = comp;
 
567
                    }
 
568
                }
 
569
                layoutDelegate.addComponentsToContainer(
 
570
                                   getPrimaryContainer(),
 
571
                                   getPrimaryContainerDelegate(),
 
572
                                   comps,
 
573
                                   0);
 
574
            }
 
575
        }
 
576
    }
 
577
 
 
578
    public void removeAll() {
 
579
        // first store constraints in meta components
 
580
        RADVisualComponent[] components = metaContainer.getSubComponents();
 
581
        for (int i=0; i < components.length; i++) {
 
582
            LayoutConstraints constr =
 
583
                layoutDelegate.getConstraints(i);
 
584
            if (constr != null)
 
585
                components[i].setLayoutConstraints(layoutDelegate.getClass(),
 
586
                                                   constr);
 
587
        }
 
588
 
 
589
        // remove code of all components
 
590
        for (int i=0, n=layoutDelegate.getComponentCount(); i < n; i++)
 
591
            CodeStructure.removeStatements(
 
592
                layoutDelegate.getComponentCode(i).getStatementsIterator());
 
593
 
 
594
        // remove components from layout
 
595
        layoutDelegate.removeAll();
 
596
 
 
597
        // clear the primary container instance
 
598
        layoutDelegate.clearContainer(getPrimaryContainer(),
 
599
                                      getPrimaryContainerDelegate());
 
600
    }
 
601
 
 
602
    public boolean isLayoutChanged() {
 
603
        Container defaultContainer = (Container)
 
604
                BeanSupport.getDefaultInstance(metaContainer.getBeanClass());
 
605
        Container defaultContDelegate =
 
606
                metaContainer.getContainerDelegate(defaultContainer);
 
607
 
 
608
        return layoutDelegate.isLayoutChanged(defaultContainer,
 
609
                                              defaultContDelegate);
 
610
    }
 
611
 
 
612
    // managing constraints
 
613
    public LayoutConstraints getConstraints(int index) {
 
614
        return layoutDelegate.getConstraints(index);
 
615
    }
 
616
 
 
617
    public LayoutConstraints getConstraints(RADVisualComponent metacomp) {
 
618
        if (layoutDelegate == null)
 
619
            return null;
 
620
 
 
621
        int index = metaContainer.getIndexOf(metacomp);
 
622
        return index >= 0 && index < layoutDelegate.getComponentCount() ?
 
623
               layoutDelegate.getConstraints(index) : null;
 
624
    }
 
625
 
 
626
    public static LayoutConstraints storeConstraints(
 
627
                                        RADVisualComponent metacomp)
 
628
    {
 
629
        RADVisualContainer parent = metacomp.getParentContainer();
 
630
        if (parent == null)
 
631
            return null;
 
632
 
 
633
        LayoutSupportManager layoutSupport = parent.getLayoutSupport();
 
634
        if (layoutSupport == null)
 
635
            return null;
 
636
        LayoutConstraints constr = layoutSupport.getConstraints(metacomp);
 
637
        if (constr != null)
 
638
            metacomp.setLayoutConstraints(
 
639
                         layoutSupport.getLayoutDelegate().getClass(),
 
640
                         constr);
 
641
        return constr;
 
642
    }
 
643
 
 
644
    public LayoutConstraints getStoredConstraints(RADVisualComponent metacomp) {
 
645
        return metacomp.getLayoutConstraints(layoutDelegate.getClass());
 
646
    }
 
647
 
 
648
    // managing live components
 
649
    public void setLayoutToContainer(Container container,
 
650
                                     Container containerDelegate)
 
651
    {
 
652
        layoutDelegate.setLayoutToContainer(container, containerDelegate);
 
653
    }
 
654
 
 
655
    public void addComponentsToContainer(Container container,
 
656
                                         Container containerDelegate,
 
657
                                         Component[] components,
 
658
                                         int index)
 
659
    {
 
660
        layoutDelegate.addComponentsToContainer(container, containerDelegate,
 
661
                                                components, index);
 
662
    }
 
663
 
 
664
    public boolean removeComponentFromContainer(Container container,
 
665
                                                Container containerDelegate,
 
666
                                                Component component)
 
667
    {
 
668
        return layoutDelegate.removeComponentFromContainer(
 
669
                            container, containerDelegate, component);
 
670
    }
 
671
 
 
672
    public boolean clearContainer(Container container,
 
673
                                  Container containerDelegate)
 
674
    {
 
675
        return layoutDelegate.clearContainer(container, containerDelegate);
 
676
    }
 
677
 
 
678
    // drag and drop support
 
679
    public LayoutConstraints getNewConstraints(Container container,
 
680
                                               Container containerDelegate,
 
681
                                               Component component,
 
682
                                               int index,
 
683
                                               Point posInCont,
 
684
                                               Point posInComp)
 
685
    {
 
686
        
 
687
        LayoutConstraints constraints =  layoutDelegate.getNewConstraints(container, containerDelegate,
 
688
                                                component, index,
 
689
                                                posInCont, posInComp);
 
690
        String context = null;
 
691
        Object[] params = null;
 
692
        if (layoutDelegate instanceof AbstractLayoutSupport) {
 
693
            AbstractLayoutSupport support = (AbstractLayoutSupport)layoutDelegate;
 
694
            context = support.getAssistantContext();
 
695
            params = support.getAssistantParams();
 
696
        }
 
697
        context = (context == null) ? "generalPosition" : context; // NOI18N
 
698
        FormEditor.getAssistantModel(metaContainer.getFormModel()).setContext(context, params);
 
699
        return constraints;
 
700
    }
 
701
 
 
702
    public int getNewIndex(Container container,
 
703
                           Container containerDelegate,
 
704
                           Component component,
 
705
                           int index,
 
706
                           Point posInCont,
 
707
                           Point posInComp)
 
708
    {
 
709
        return layoutDelegate.getNewIndex(container, containerDelegate,
 
710
                                          component, index,
 
711
                                          posInCont, posInComp);
 
712
    }
 
713
 
 
714
    public boolean paintDragFeedback(Container container, 
 
715
                                     Container containerDelegate,
 
716
                                     Component component,
 
717
                                     LayoutConstraints newConstraints,
 
718
                                     int newIndex,
 
719
                                     Graphics g)
 
720
    {
 
721
        return layoutDelegate.paintDragFeedback(container, containerDelegate,
 
722
                                                component,
 
723
                                                newConstraints, newIndex,
 
724
                                                g);
 
725
    }
 
726
 
 
727
    // resizing support
 
728
    public int getResizableDirections(Container container,
 
729
                                      Container containerDelegate,
 
730
                                      Component component,
 
731
                                      int index)
 
732
    {
 
733
        return layoutDelegate.getResizableDirections(container,
 
734
                                                     containerDelegate,
 
735
                                                     component, index);
 
736
    }
 
737
 
 
738
    public LayoutConstraints getResizedConstraints(Container container,
 
739
                                                   Container containerDelegate,
 
740
                                                   Component component,
 
741
                                                   int index,
 
742
                                                   Rectangle originalBounds,
 
743
                                                   Insets sizeChanges,
 
744
                                                   Point posInCont)
 
745
    {
 
746
        return layoutDelegate.getResizedConstraints(container,
 
747
                                                    containerDelegate,
 
748
                                                    component, index,
 
749
                                                    originalBounds,
 
750
                                                    sizeChanges,
 
751
                                                    posInCont);
 
752
    }
 
753
 
 
754
    // arranging support
 
755
    public void processMouseClick(Point p,
 
756
                                  Container cont,
 
757
                                  Container contDelegate)
 
758
    {
 
759
        layoutDelegate.processMouseClick(p, cont, contDelegate);
 
760
    }
 
761
 
 
762
    // arranging support
 
763
    public void selectComponent(int index) {
 
764
        layoutDelegate.selectComponent(index);
 
765
    }
 
766
 
 
767
    // arranging support
 
768
    public void arrangeContainer(Container container,
 
769
                                 Container containerDelegate)
 
770
    {
 
771
        layoutDelegate.arrangeContainer(container, containerDelegate);
 
772
    }
 
773
 
 
774
    // -----------
 
775
    // API for layout delegates (LayoutSupportContext implementation)
 
776
 
 
777
    public CodeStructure getCodeStructure() {
 
778
        return codeStructure;
 
779
    }
 
780
 
 
781
    public CodeExpression getContainerCodeExpression() {
 
782
        if (containerCodeExpression == null) {
 
783
            containerCodeExpression = metaContainer.getCodeExpression();
 
784
            containerDelegateCodeExpression = null;
 
785
        }
 
786
        return containerCodeExpression;
 
787
    }
 
788
 
 
789
    public CodeExpression getContainerDelegateCodeExpression() {
 
790
        if (containerDelegateCodeExpression == null) {
 
791
            containerDelegateCodeExpression =
 
792
                    containerDelegateCodeExpression(metaContainer, codeStructure);
 
793
        }
 
794
 
 
795
        return containerDelegateCodeExpression;
 
796
    }
 
797
    
 
798
    public static CodeExpression containerDelegateCodeExpression(
 
799
                                     RADVisualContainer metaContainer,
 
800
                                     CodeStructure codeStructure)
 
801
    {
 
802
        CodeExpression containerCodeExpression = metaContainer.getCodeExpression();
 
803
        CodeExpression containerDelegateCodeExpression;
 
804
        java.lang.reflect.Method delegateGetter =
 
805
            metaContainer.getContainerDelegateMethod();
 
806
 
 
807
        if (delegateGetter != null) { // there should be a container delegate
 
808
            Iterator it = CodeStructure.getDefinedExpressionsIterator(
 
809
                                              containerCodeExpression);
 
810
            CodeExpression[] expressions = CodeStructure.filterExpressions(
 
811
                                                        it, delegateGetter);
 
812
            if (expressions.length > 0) {
 
813
                // the expresion for the container delegate already exists
 
814
                containerDelegateCodeExpression = expressions[0];
 
815
            }
 
816
            else { // create a new expresion for the container delegate
 
817
                CodeExpressionOrigin origin = CodeStructure.createOrigin(
 
818
                                                containerCodeExpression,
 
819
                                                delegateGetter,
 
820
                                                null);
 
821
                containerDelegateCodeExpression =
 
822
                    codeStructure.createExpression(origin);
 
823
            }
 
824
        }
 
825
        else // no special container delegate
 
826
            containerDelegateCodeExpression = containerCodeExpression;
 
827
        return containerDelegateCodeExpression;
 
828
    }
 
829
 
 
830
    // return container instance of meta container
 
831
    public Container getPrimaryContainer() {
 
832
        return (Container) metaContainer.getBeanInstance();
 
833
    }
 
834
 
 
835
    // return container delegate of container instance of meta container
 
836
    public Container getPrimaryContainerDelegate() {
 
837
        Container defCont = (Container) metaContainer.getBeanInstance();
 
838
        if (primaryContainerDelegate == null || primaryContainer != defCont) {
 
839
            primaryContainer = defCont;
 
840
            primaryContainerDelegate =
 
841
                metaContainer.getContainerDelegate(defCont);
 
842
        }
 
843
        return primaryContainerDelegate;
 
844
    }
 
845
 
 
846
    // return component instance of meta component
 
847
    public Component getPrimaryComponent(int index) {
 
848
        return (Component) metaContainer.getSubComponent(index).getBeanInstance();
 
849
    }
 
850
 
 
851
    public void updatePrimaryContainer() {
 
852
        Container cont = getPrimaryContainer();
 
853
        Container contDel = getPrimaryContainerDelegate();
 
854
 
 
855
        layoutDelegate.clearContainer(cont, contDel);
 
856
        layoutDelegate.setLayoutToContainer(cont, contDel);
 
857
 
 
858
        RADVisualComponent[] components = metaContainer.getSubComponents();
 
859
        if (components.length > 0) {
 
860
            Component[] comps = new Component[components.length];
 
861
            for (int i=0; i < components.length; i++) {
 
862
                comps[i] = (Component) components[i].getBeanInstance();
 
863
                ensureFakePeerAttached(comps[i]);
 
864
            }
 
865
 
 
866
            layoutDelegate.addComponentsToContainer(cont, contDel, comps, 0);
 
867
        }
 
868
    }
 
869
 
 
870
    public void containerLayoutChanged(PropertyChangeEvent ev)
 
871
        throws PropertyVetoException
 
872
    {
 
873
        if (ev != null && ev.getPropertyName() != null) {
 
874
            layoutDelegate.acceptContainerLayoutChange(getEventWithValues(ev));
 
875
 
 
876
            FormModel formModel = metaContainer.getFormModel();
 
877
            formModel.fireContainerLayoutChanged(metaContainer,
 
878
                                                 ev.getPropertyName(),
 
879
                                                 ev.getOldValue(),
 
880
                                                 ev.getNewValue());
 
881
        }
 
882
        else propertySets = null;
 
883
 
 
884
        LayoutNode node = metaContainer.getLayoutNodeReference();
 
885
        if (node != null) {
 
886
            // propagate the change to node
 
887
            if (ev != null && ev.getPropertyName() != null)
 
888
                node.fireLayoutPropertiesChange();
 
889
            else
 
890
                node.fireLayoutPropertySetsChange();
 
891
        }
 
892
    }
 
893
 
 
894
    public void componentLayoutChanged(int index, PropertyChangeEvent ev)
 
895
        throws PropertyVetoException
 
896
    {
 
897
        RADVisualComponent metacomp = metaContainer.getSubComponent(index);
 
898
 
 
899
        if (ev != null && ev.getPropertyName() != null) {
 
900
            layoutDelegate.acceptComponentLayoutChange(index,
 
901
                                                       getEventWithValues(ev));
 
902
 
 
903
            FormModel formModel = metaContainer.getFormModel();
 
904
            formModel.fireComponentLayoutChanged(metacomp,
 
905
                                                 ev.getPropertyName(),
 
906
                                                 ev.getOldValue(),
 
907
                                                 ev.getNewValue());
 
908
 
 
909
            if (metacomp.getNodeReference() != null) // propagate the change to node
 
910
                metacomp.getNodeReference().firePropertyChangeHelper(
 
911
//                                                     null, null, null);
 
912
                                              ev.getPropertyName(),
 
913
                                              ev.getOldValue(),
 
914
                                              ev.getNewValue());
 
915
        }
 
916
        else {
 
917
            if (metacomp.getNodeReference() != null) // propagate the change to node
 
918
                metacomp.getNodeReference().fireComponentPropertySetsChange();
 
919
            metacomp.resetConstraintsProperties();
 
920
        }
 
921
    }
 
922
 
 
923
    private static PropertyChangeEvent getEventWithValues(PropertyChangeEvent ev) {
 
924
        Object oldVal = ev.getOldValue();
 
925
        Object newVal = ev.getNewValue();
 
926
        if (oldVal instanceof FormProperty.ValueWithEditor)
 
927
            ev = new PropertyChangeEvent(
 
928
                         ev.getSource(),
 
929
                         ev.getPropertyName(),
 
930
                         ((FormProperty.ValueWithEditor)oldVal).getValue(),
 
931
                         ((FormProperty.ValueWithEditor)newVal).getValue());
 
932
        return ev;
 
933
    }
 
934
 
 
935
    // ---------
 
936
 
 
937
    private LayoutListener getLayoutListener() {
 
938
        if (layoutListener == null)
 
939
            layoutListener = new LayoutListener();
 
940
        return layoutListener;
 
941
    }
 
942
 
 
943
    private class LayoutListener implements VetoableChangeListener,
 
944
                                            PropertyChangeListener
 
945
    {
 
946
        public void vetoableChange(PropertyChangeEvent ev)
 
947
            throws PropertyVetoException
 
948
        {
 
949
            Object source = ev.getSource();
 
950
            String eventName = ev.getPropertyName();
 
951
            if (source instanceof FormProperty
 
952
                && (FormProperty.PROP_VALUE.equals(eventName)
 
953
                    || FormProperty.PROP_VALUE_AND_EDITOR.equals(eventName)))
 
954
            {
 
955
                ev = new PropertyChangeEvent(layoutDelegate,
 
956
                                             ((FormProperty)source).getName(),
 
957
                                             ev.getOldValue(),
 
958
                                             ev.getNewValue());
 
959
 
 
960
                containerLayoutChanged(ev);
 
961
            }
 
962
        }
 
963
 
 
964
        public void propertyChange(PropertyChangeEvent ev) {
 
965
            Object source = ev.getSource();
 
966
            if (source instanceof FormProperty
 
967
                && FormProperty.CURRENT_EDITOR.equals(ev.getPropertyName()))
 
968
            {
 
969
                ev = new PropertyChangeEvent(layoutDelegate,
 
970
                                             null, null, null);
 
971
                try {
 
972
                    containerLayoutChanged(ev);
 
973
                }
 
974
                catch (PropertyVetoException ex) {} // should not happen
 
975
            }
 
976
        }
 
977
    }
 
978
 
 
979
    private static void ensureFakePeerAttached(Component comp) {
 
980
        // This method is called for components to be added to a container.
 
981
        // It might happen that the component is still in another container
 
982
        // (by error) and then when removed from this container before adding
 
983
        // to the new one, the peer would be null-ed. Trying to prevent this by
 
984
        // removing the component before attaching the fake peer. (For bug 115431.)
 
985
        if (comp != null && comp.getParent() != null) {
 
986
            comp.getParent().remove(comp);
 
987
        }
 
988
        FakePeerSupport.attachFakePeer(comp);
 
989
        if (comp instanceof Container)
 
990
            FakePeerSupport.attachFakePeerRecursively((Container)comp);
 
991
    }
 
992
}