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