001: /*
002: * Copyright (c) 2004 JETA Software, Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without modification,
005: * are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JETA Software nor the names of its contributors may
015: * be used to endorse or promote products derived from this software without
016: * specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
021: * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
022: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
023: * INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
024: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
025: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026: * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: */
029:
030: package com.jeta.forms.gui.form;
031:
032: import java.awt.BorderLayout;
033: import java.awt.Component;
034: import java.awt.Container;
035: import java.awt.Dimension;
036: import java.util.Collection;
037: import java.util.HashMap;
038: import java.util.Iterator;
039:
040: import com.jeta.forms.components.panel.FormPanel;
041: import com.jeta.forms.gui.beans.DynamicBeanInfo;
042: import com.jeta.forms.gui.beans.JETABean;
043: import com.jeta.forms.gui.beans.JETABeanFactory;
044: import com.jeta.forms.gui.beans.JETAPropertyDescriptor;
045: import com.jeta.forms.gui.common.FormException;
046: import com.jeta.forms.gui.common.FormUtils;
047: import com.jeta.forms.gui.formmgr.FormManager;
048: import com.jeta.forms.logger.FormsLogger;
049: import com.jeta.forms.project.ProjectManager;
050: import com.jeta.forms.store.bean.BeanDeserializer;
051: import com.jeta.forms.store.bean.BeanSerializer;
052: import com.jeta.forms.store.bean.BeanSerializerFactory;
053: import com.jeta.forms.store.memento.BeanMemento;
054: import com.jeta.forms.store.memento.CellConstraintsMemento;
055: import com.jeta.forms.store.memento.ComponentMemento;
056: import com.jeta.forms.store.memento.FocusPolicyMemento;
057: import com.jeta.forms.store.memento.FormMemento;
058: import com.jeta.forms.store.memento.PropertiesMemento;
059: import com.jeta.forms.store.memento.StateRequest;
060: import com.jeta.open.registry.JETARegistry;
061:
062: /**
063: * A <code>FormComponent</code> is a type of GridComponent that contains a
064: * nested form in a GridView. A FormComponent represents a top-level form or
065: * nested form whereas StandardComponents represent Swing components (Java
066: * beans).
067: *
068: * Forms come in two types: Embedded and Linked. An embedded form is a nested
069: * form that is fully encapsulated and stored in the parent. A linked form
070: * refers to a form file on disk, but it can exist as a child in another form.
071: *
072: * All GridComponents have a single JETABean has a child. The FormComponent has
073: * a JETABean child which is a wrapper around a GridView bean.
074: *
075: * Containment Hierarchy:
076: *
077: * <pre>
078: * FormComponent
079: * |
080: * -- JETABean -maintains the properties for the form.
081: * |
082: * -- GridView -a GridView has N child components that occupy the cells in the view
083: * |
084: * //-- GridView.FormContainer ---------------------> FormLayout
085: * | (layoutmgr)
086: * -- GridComponent1
087: * |
088: * -- GridComponent2
089: * |
090: * -- GridComponentN
091: * -each GridComponent is either a StandardComponent(Swing component)
092: * or a nested form (FormComponent)
093: * </pre>
094: *
095: * @author Jeff Tassin
096: */
097: public class FormComponent extends GridComponent {
098: /**
099: * A unique id for this form. If the form is linked, then this value will be
100: * the absolute file path.
101: */
102: private String m_id;
103:
104: /**
105: * Flag that indicates if this form is embedded.
106: */
107: private boolean m_embedded = false;
108:
109: /**
110: * The path for this form on the local file system. Note that we don't store
111: * the full path in the FormMemento (only the relative package).
112: */
113: private String m_abspath = null;
114:
115: /**
116: * This is a flag used to indicate is this is the top-most form when saving
117: * this form. This reason for the flag is if this form is linked,we only
118: * store the path to the linked form and not the contents. However, a
119: * top-level form can be linked, and in this case we need to store
120: * everything.
121: */
122: private boolean m_top_level_form = false;
123:
124: /**
125: * The focus policy for this form. This applies to top-level forms only.
126: *
127: * @deprecated The designer is no longer supporting focus.
128: */
129: private FocusPolicyMemento m_focus_policy;
130:
131: /**
132: * Creates a <code>FormComponent</code> instance.
133: */
134: protected FormComponent() {
135:
136: }
137:
138: /**
139: * Creates a <code>FormComponent</code> instance with the specified id,
140: * child bean, and parent view.
141: *
142: * @param id
143: * the unique id for this form.
144: * @param jbean
145: * the underlying GridView
146: * @param parentView
147: * the parent for this form.
148: * @param embedded
149: * flag that indicates if this form is embedded
150: */
151: protected FormComponent(String id, JETABean jbean,
152: GridView parentView, boolean embedded) throws FormException {
153: super (jbean, parentView);
154: m_id = id;
155: FormUtils.safeAssert(jbean.getDelegate() instanceof GridView);
156: setBean(getBean());
157: m_embedded = embedded;
158: }
159:
160: /**
161: * Creates a form component.
162: */
163: public static FormComponent create() {
164: FormComponentFactory factory = (FormComponentFactory) JETARegistry
165: .lookup(FormComponentFactory.COMPONENT_ID);
166: if (factory == null) {
167: FormUtils.safeAssert(!FormUtils.isDesignMode());
168: return new FormComponent();
169: } else {
170: return factory.createFormComponent();
171: }
172: }
173:
174: /**
175: * Returns the absolute path to this form. If the form is embedded, this
176: * value will be null.
177: *
178: * @return the absolute path to this form if the form is a linked form.
179: */
180: public String getAbsolutePath() {
181: return m_abspath;
182: }
183:
184: /**
185: * Returns the total width in pixels of the cells occupied by this
186: * component.
187: *
188: * @return the total width in pixels of the cells occupied by this component
189: */
190: public int getCellWidth() {
191: if (getParentView() == null)
192: return getWidth();
193: else
194: return super .getCellWidth();
195: }
196:
197: /**
198: * Returns the total height in pixels of the cells occupied by this
199: * component.
200: *
201: * @return the total height in pixels of the cells occupied by this
202: * component
203: */
204: public int getCellHeight() {
205: if (getParentView() == null)
206: return getHeight();
207: else
208: return super .getCellHeight();
209: }
210:
211: /**
212: * Returns the left location of this component's cell in the parent
213: * coordinates.
214: *
215: * @return the left location of this component's cell in the parent
216: * coordinates.
217: */
218: public int getCellX() {
219: if (getParentView() == null)
220: return getX();
221: else
222: return super .getCellX();
223: }
224:
225: /**
226: * Returns the top location of this component's cell in the parent
227: * coordinates.
228: *
229: * @return the top location of this component's cell in the parent
230: * coordinates.
231: */
232: public int getCellY() {
233: if (getParentView() == null)
234: return getY();
235: else
236: return super .getCellY();
237: }
238:
239: /**
240: * Returns the GridView that is associated with this form.
241: *
242: * @return the child view associated with this component
243: */
244: public GridView getChildView() {
245: JETABean bean = getBean();
246: if (bean != null) {
247: return (GridView) bean.getDelegate();
248: }
249: return null;
250: }
251:
252: /**
253: * Returns the number of columns in this form.
254: *
255: * @return the number of columns in this form
256: */
257: public int getColumnCount() {
258: GridView view = getChildView();
259: return (view == null ? 0 : view.getColumnCount());
260: }
261:
262: /**
263: * Returns the filename of this form. If the form is embedded, this value is
264: * null.
265: *
266: * @return the filename portion of the path to this form (only if this form
267: * is linked)
268: */
269: public String getFileName() {
270: if (isLinked()) {
271: String path = getAbsolutePath();
272: if (path != null) {
273: int pos = path.lastIndexOf('/');
274: if (pos < 0)
275: pos = path.lastIndexOf('\\');
276:
277: if (pos >= 0) {
278: return path.substring(pos + 1, path.length());
279: } else {
280: return path;
281: }
282: }
283: }
284: return null;
285: }
286:
287: /**
288: * Returns the focus policy assigned to this form.
289: *
290: * @return the focus policy for this form (not currently used)
291: * @deprecated the designer no longer supports focus policy.
292: */
293: public FocusPolicyMemento getFocusPolicy() {
294: return m_focus_policy;
295: }
296:
297: /**
298: * Returns the child grid component that occupies the given row and column
299: * in this form.
300: *
301: * @return the GridComponent at the specificed column and row
302: */
303: public GridComponent getGridComponent(int col, int row) {
304: GridView view = getChildView();
305: return (view == null ? null : view.getGridComponent(col, row));
306: }
307:
308: /**
309: * Traverses the container hiearchy for the given form starting from its
310: * parent and traversing until it encounters a FormComponent instance.
311: *
312: * @return the formcomponent that is the closest ancestor of the given form.
313: * Null is returned if this the topmost parent form.
314: */
315: public static FormComponent getParentForm(Component comp) {
316: if (comp == null)
317: return null;
318:
319: comp = comp.getParent();
320: while (comp != null) {
321: if (comp instanceof FormComponent)
322: return (FormComponent) comp;
323:
324: comp = comp.getParent();
325: }
326: return null;
327: }
328:
329: /**
330: * Traverses the container hiearchy for this form starting from its parent
331: * and traversing until it encounters a FormComponent instance.
332: *
333: * @return the formcomponent that is the closest ancestor of this form. Null
334: * is returned if this the topmost parent form.
335: */
336: public FormComponent getParentForm() {
337: return getParentForm(this );
338: }
339:
340: /**
341: * Returns the selected child component in this form. The is the component
342: * that is selected by the user in design mode.
343: *
344: * @returns the first selected component it finds in the component hierarhcy
345: * of this container. Null is returned if no component is selected.
346: */
347: public GridComponent getSelectedComponent() {
348: if (isSelected())
349: return this ;
350: else
351: return getChildView().getSelectedComponent();
352: }
353:
354: /**
355: * Always call this method instead of getState when saving a top level form.
356: * Saves this form's state to a memento.
357: *
358: * @return the form state as a memento.
359: */
360: public FormMemento getExternalState(StateRequest si)
361: throws FormException {
362: try {
363: JETARegistry.rebind(StateRequest.COMPONENT_ID, si);
364: setTopLevelForm(true);
365: return (FormMemento) getState(si);
366: } finally {
367: setTopLevelForm(false);
368: JETARegistry.rebind(StateRequest.COMPONENT_ID, null);
369: }
370: }
371:
372: /**
373: * Returns the number of rows in this form.
374: *
375: * @return the number of rows in this form
376: */
377: public int getRowCount() {
378: GridView view = getChildView();
379: return (view == null ? 0 : view.getRowCount());
380: }
381:
382: /**
383: * Saves this form's state as a memento object.
384: *
385: * @param si
386: * a state request that has some control over how the form state
387: * is stored. For example, in some cases we want to store full
388: * copy of a linked form in the memento as oposed to the link
389: * reference.
390: * @return the state of this object as a mememento
391: */
392: public ComponentMemento getState(StateRequest si)
393: throws FormException {
394: FormMemento state = new FormMemento();
395: GridView view = getChildView();
396:
397: state.setId(getId());
398: state.setComponentClass(FormComponent.class.getName());
399: state.setFocusPolicy(m_focus_policy);
400:
401: if (getParentView() != null) {
402: state.setCellConstraints(getConstraints()
403: .createCellConstraints());
404: }
405:
406: if (isLinked() && si.isShallowCopy()) {
407: state.setRelativePath(getRelativePath());
408: if (!isTopLevelForm()) {
409: return state;
410: }
411: }
412:
413: state.setRowGroups(view.getRowGroups());
414: state.setColumnGroups(view.getColumnGroups());
415: state.setRowSpecs(view.getRowSpecs());
416: state.setColumnSpecs(view.getColumnSpecs());
417: state.setCellPainters(view.getCellPainters());
418: Iterator iter = view.gridIterator();
419: while (iter.hasNext()) {
420: GridComponent gc = (GridComponent) iter.next();
421: if (gc.getBean() != null) {
422: ComponentMemento ccm = gc.getState(si);
423: state.addComponent(ccm);
424: }
425: }
426:
427: /** store the view properties */
428: BeanSerializerFactory fac = (BeanSerializerFactory) JETARegistry
429: .lookup(BeanSerializerFactory.COMPONENT_ID);
430: BeanSerializer bs = fac.createSerializer();
431: JETABean jbean = getBean();
432: FormUtils.safeAssert(jbean.getDelegate() == view);
433: PropertiesMemento pm = bs.writeBean(jbean);
434: state.setPropertiesMemento(pm);
435: return state;
436: }
437:
438: /**
439: * Returns a unique id for this form. If the form is embedded, the id is
440: * based on this object's hashCode. If the form is linked, the id is the
441: * absolute path to the form.
442: *
443: * @return the unique id of this form.
444: */
445: public String getId() {
446: if (isEmbedded()) {
447: if (m_id == null)
448: m_id = "embedded." + String.valueOf(hashCode());
449:
450: return m_id;
451: } else {
452: if (m_abspath == null) {
453: if (m_id == null)
454: m_id = "linked." + String.valueOf(hashCode());
455:
456: return m_id;
457: } else
458: return m_abspath;
459: }
460: }
461:
462: /**
463: * Returns the relative path to this form. The path is determined by the
464: * source paths defined in the project settings. If this form is embedded,
465: * null is returned.
466: *
467: * @return the relative path.
468: */
469: public String getRelativePath() {
470: ProjectManager pmgr = (ProjectManager) JETARegistry
471: .lookup(ProjectManager.COMPONENT_ID);
472: return pmgr.getRelativePath(m_abspath);
473: }
474:
475: /**
476: * Traverses the container hierarchy for the given component and returns the
477: * first parent that is a top-level FormComponent. Most components only have
478: * one top level parent. However, if a component is in a JTabbedPane, it
479: * will have two top-level parents.
480: *
481: * @param comp
482: * the comp that determines where the traversal will start.
483: * @return the first FormComponent ancestor found in the container
484: * heirarchy.
485: */
486: public static FormComponent getTopLevelForm(Component comp) {
487: if (comp == null)
488: return null;
489:
490: while (comp != null && !(comp instanceof java.awt.Window)) {
491: if (comp instanceof FormComponent
492: && ((FormComponent) comp).isTopLevelForm())
493: return (FormComponent) comp;
494: comp = comp.getParent();
495: }
496: return null;
497: }
498:
499: /**
500: * Returns true if this form is an embedded form. An embedded form is stored
501: * within the parent form.
502: *
503: * @return true if this form is an embedded form.
504: */
505: public boolean isEmbedded() {
506: return m_embedded;
507: }
508:
509: /**
510: * Returns true if this form is linked. A linked form is stored in its own
511: * form file on disk.
512: *
513: * @return true if this form is a linked form.
514: */
515: public boolean isLinked() {
516: return !isEmbedded();
517: }
518:
519: /**
520: * Returns an interator that iterates over the grid components in a child
521: * view.
522: *
523: * @return an iterator that iterates over the grid components (GridComponent
524: * objects) in the child view
525: */
526: public Iterator gridIterator() {
527: return getChildView().gridIterator();
528: }
529:
530: /**
531: * Return true if this form is the top-most form in the container hierarchy.
532: *
533: * @return the flag used to indicate is this is the top-most form when
534: * saving this form.
535: */
536: public boolean isTopLevelForm() {
537: return m_top_level_form;
538: }
539:
540: /**
541: * Creates and initializes a FormComponent from the given form memento.
542: */
543: protected FormComponent openLinkedForm(FormMemento fm)
544: throws FormException {
545: FormComponent fc = com.jeta.forms.gui.formmgr.FormManagerUtils
546: .openPackagedForm(fm.getRelativePath());
547: return fc;
548: }
549:
550: /**
551: * PostInitialize is called once after all components in a FormPanel have
552: * been instantiated at runtime (not design time). This gives each property
553: * and component a chance to do some last minute initializations that might
554: * depend on the top level parent. FormComponent simply forwards the call to
555: * any children.
556: *
557: * @param panel
558: * the top-level form container
559: * @param cc
560: * a container whose child components are to be
561: * (post)intitialized.
562: */
563: public void _postInitialize(FormPanel panel, Container cc) {
564: if (cc == null)
565: return;
566:
567: for (int index = 0; index < cc.getComponentCount(); index++) {
568: Component comp = cc.getComponent(index);
569: if (comp instanceof GridComponent)
570: ((GridComponent) comp).postInitialize(panel);
571: else if (comp instanceof Container)
572: _postInitialize(panel, (Container) comp);
573: }
574: }
575:
576: /**
577: * PostInitialize is called once after all components in a form have been
578: * re-instantiated at runtime (not design time). This gives each property
579: * and component a chance to do some last minute initializations that might
580: * depend on the top level parent. An example of this is button groups which
581: * are global to a form. FormComponent simply forwards the call to any
582: * children.
583: *
584: * @param panel
585: * the top-level form container
586: */
587: public void postInitialize(FormPanel panel) {
588: _postInitialize(panel, this );
589: }
590:
591: /**
592: * Performs any final initialization of this form component after it's state
593: * has been restored. The main operation is to add empty components where
594: * needed. When in design mode, every cell in the grid has a GridComponent.
595: * The reason is because we need to enforce a minimum size for the cell when
596: * the user sets the row/col size to preferred. If not, the cell size would
597: * be zero if nothing were there. However, in run mode, we don't want to
598: * create an empty component for every single cell. For example, a 20x20
599: * grid would require 400 components. To prevent this, we only add 1 empty
600: * component per row and column. This allows the runtime form to look
601: * approximately like the design time forms with rows/cols that have no
602: * components. We use the grid_cache to keep track of which columns and rows
603: * have had empty components added.
604: */
605: protected void postSetState(ComponentMemento cm) {
606: GridView view = getChildView();
607: for (int col = 1; col <= view.getColumnCount(); col++) {
608: for (int row = 1; row <= view.getRowCount(); row++) {
609: GridComponent gc = view.getGridComponent(col, row);
610: if (gc == null) {
611: gc = new StandardComponent(null, view);
612: gc.setPreferredSize(new Dimension(
613: GridComponent.EMPTY_CELL_WIDTH,
614: GridComponent.EMPTY_CELL_HEIGHT));
615: gc.setMinimumSize(new Dimension(
616: GridComponent.EMPTY_CELL_WIDTH,
617: GridComponent.EMPTY_CELL_HEIGHT));
618: view.addComponent(gc, new ReadOnlyConstraints(col,
619: row));
620: break;
621: }
622: }
623: }
624:
625: for (int row = 2; row <= view.getRowCount(); row++) {
626: for (int col = 1; col <= view.getColumnCount(); col++) {
627: GridComponent gc = view.getGridComponent(col, row);
628: if (gc == null) {
629: gc = new StandardComponent(null, view);
630: gc.setPreferredSize(new Dimension(
631: GridComponent.EMPTY_CELL_WIDTH,
632: GridComponent.EMPTY_CELL_HEIGHT));
633: gc.setMinimumSize(new Dimension(
634: GridComponent.EMPTY_CELL_WIDTH,
635: GridComponent.EMPTY_CELL_HEIGHT));
636: view.addComponent(gc, new ReadOnlyConstraints(col,
637: row));
638: break;
639: }
640: }
641: }
642:
643: }
644:
645: /**
646: * Print for debugging
647: */
648: public void print() {
649: FormsLogger.debug("FormComponent name = " + getName()
650: + " uid = " + getId() + " path = "
651: + getAbsolutePath() + " hash: " + hashCode()
652: + " parentView: " + getParentView());
653: }
654:
655: /**
656: * Override revalidate so we can forward the call to the underlying GridView
657: * as well.
658: */
659: public void revalidate() {
660: GridView view = getChildView();
661: if (view != null)
662: view.revalidate();
663: super .revalidate();
664: }
665:
666: /**
667: * Override GridComponent implementation so we can add the child to this
668: * container for the design view.
669: */
670: protected void setBean(JETABean jbean) {
671: super .setBean(jbean);
672:
673: FormUtils.safeAssert(jbean.getDelegate() instanceof GridView);
674: setLayout(new BorderLayout());
675:
676: FormUtils.safeAssert(getComponentCount() == 0);
677:
678: /** remove any existing components */
679: removeAll();
680:
681: add(jbean, BorderLayout.CENTER);
682: }
683:
684: /**
685: * Sets the absolute path for this form.
686: */
687: public void setAbsolutePath(String path) {
688: m_abspath = path;
689: if (path != null)
690: m_embedded = false;
691: }
692:
693: public void setControlButtonsVisible(boolean bVisible) {
694: // no op
695: }
696:
697: /**
698: * Sets the focus policy for this form
699: *
700: * @deprecated The designer no longer supports focus.
701: */
702: public void setFocusPolicy(FocusPolicyMemento fm) {
703: m_focus_policy = fm;
704: }
705:
706: /**
707: * Override setSelected so we can deselect everything in the child view when
708: * being dselected.
709: */
710: public void setSelected(boolean bsel) {
711: super .setSelected(bsel);
712: if (!bsel) {
713: GridView gv = (GridView) getChildView();
714: gv.deselectAll();
715: }
716: }
717:
718: /**
719: * Resets this component from a previously saved state.
720: *
721: * @param memento
722: */
723: public void setState(ComponentMemento memento) throws FormException {
724: FormMemento state = (FormMemento) memento;
725:
726: if (state.getRelativePath() == null)
727: m_embedded = true;
728:
729: m_focus_policy = state.getFocusPolicy();
730:
731: FormManager fmgr = (FormManager) JETARegistry
732: .lookup(FormManager.COMPONENT_ID);
733: if (FormUtils.isDesignMode()) {
734: FormUtils.safeAssert(fmgr != null);
735: }
736:
737: JETABean viewbean = JETABeanFactory.createBean(
738: "com.jeta.forms.gui.form.GridView", "gridview", true,
739: true);
740: GridView view = (GridView) viewbean.getDelegate();
741: view.initialize(state.getColumnSpecs(), state.getRowSpecs());
742: view.setCellPainters(state.getCellPainters());
743: setBean(viewbean);
744: view.setRowGroups(state.getRowGroups());
745: view.setColumnGroups(state.getColumnGroups());
746:
747: /** set the view properties */
748: PropertiesMemento pm = state.getPropertiesMemento();
749: if (pm != null) {
750: BeanSerializerFactory fac = (BeanSerializerFactory) JETARegistry
751: .lookup(BeanSerializerFactory.COMPONENT_ID);
752: BeanDeserializer bds = fac.createDeserializer(pm);
753: bds.initializeBean(viewbean);
754: } else {
755: /** encountered a deprecated form state. */
756: try {
757: HashMap props = state.getProperties();
758: DynamicBeanInfo beaninfo = viewbean.getBeanInfo();
759: Collection jpds = beaninfo.getPropertyDescriptors();
760: Iterator iter = jpds.iterator();
761: while (iter.hasNext()) {
762: JETAPropertyDescriptor jpd = (JETAPropertyDescriptor) iter
763: .next();
764: Object value = props.get(jpd.getName());
765: if (value != null) {
766: jpd.setPropertyValue(viewbean, value);
767: }
768: }
769: } catch (Exception e) {
770: e.printStackTrace();
771: }
772: }
773:
774: Iterator iter = state.iterator();
775: while (iter.hasNext()) {
776: ComponentMemento cm = (ComponentMemento) iter.next();
777: try {
778: if (cm instanceof FormMemento) {
779: FormMemento fm = (FormMemento) cm;
780: /** form is linked if the path is valid */
781: if (fm.getRelativePath() != null) {
782: try {
783: FormComponent fc = openLinkedForm(fm);
784: /**
785: * @todo check if the linked form has already been
786: * opened in this view. need to handle the
787: * case where the user wants to embed two or
788: * more of the same linked forms in a single
789: * view. This is an exceedinly rare case
790: */
791: view.addComponent(fc, fm
792: .getCellConstraintsMemento()
793: .createCellConstraints());
794: } catch (Exception e) {
795: javax.swing.JLabel elabel = new javax.swing.JLabel(
796: "Error: " + fm.getRelativePath());
797: elabel.setForeground(java.awt.Color.red);
798: JETABean bean = new JETABean(elabel);
799: StandardComponent gc = new StandardComponent(
800: bean, view);
801: view.addComponent(gc, fm
802: .getCellConstraintsMemento()
803: .createCellConstraints());
804:
805: /**
806: * Unable to add form.
807: */
808: FormsLogger.severe(e);
809: }
810: continue;
811: }
812: }
813:
814: CellConstraintsMemento ccm = cm
815: .getCellConstraintsMemento();
816:
817: /**
818: * If we are here, then the child component is either a standard
819: * Java Bean or an embedded form.
820: */
821: if (StandardComponent.class.getName().equals(
822: cm.getComponentClass())
823: && cm instanceof BeanMemento) {
824: BeanMemento bm = (BeanMemento) cm;
825: if (bm.getBeanClass() == null) {
826: // ignore empty components here.
827: continue;
828: }
829: }
830:
831: GridComponent gc = null;
832: Class gc_class = Class.forName(cm.getComponentClass());
833: if (FormComponent.class.isAssignableFrom(gc_class))
834: gc = FormComponent.create();
835: else
836: gc = (GridComponent) gc_class.newInstance();
837:
838: gc.setState(cm);
839: if (ccm == null) {
840: /** this should never happen */
841: System.out
842: .println("FormComponent.setState cellconstraints memento is null: ");
843: gc.print();
844: FormUtils.safeAssert(false);
845: } else {
846: view.addComponent(gc, ccm.createCellConstraints());
847: }
848: } catch (Exception e) {
849: FormsLogger.severe(e);
850: }
851: }
852:
853: // now traverse the grid cache and add an empty components where needed
854: postSetState(memento);
855:
856: view.refreshView();
857: }
858:
859: /**
860: * Sets the flag used to indicate is this is the top-most form when saving
861: * this form.
862: *
863: * @param topLevel
864: * set to true to make this a top-level form.
865: */
866: public void setTopLevelForm(boolean topLevel) {
867: m_top_level_form = topLevel;
868: }
869:
870: }
|