KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.form;
21
22 import java.util.*;
23 import javax.swing.event.UndoableEditEvent JavaDoc;
24 import javax.swing.undo.*;
25
26 import org.openide.awt.UndoRedo;
27 import org.openide.util.Mutex;
28 import org.openide.util.MutexException;
29
30 import org.netbeans.modules.form.layoutsupport.*;
31 import org.netbeans.modules.form.codestructure.CodeStructure;
32 import org.netbeans.modules.form.layoutdesign.*;
33
34 /**
35  * Holds all data of a form.
36  *
37  * @author Tran Duc Trung, Tomas Pavek
38  */

39
40 public class FormModel
41 {
42     // name of the form (name of the DataObject)
43
private String JavaDoc formName;
44
45     private boolean readOnly = false;
46
47     // the class on which the form is based (which is extended in the java file)
48
private Class JavaDoc formBaseClass;
49
50     // the top metacomponent of the form (null if form is based on Object)
51
private RADComponent topRADComponent;
52
53     // other components - out of the main hierarchy under topRADComponent
54
private ArrayList<RADComponent> otherComponents = new ArrayList(10);
55
56     // holds both topRADComponent and otherComponents
57
private ComponentContainer modelContainer;
58
59     private LayoutModel layoutModel;
60
61     private Map<String JavaDoc,RADComponent> idToComponents = new HashMap();
62
63     private boolean formLoaded = false;
64
65     private UndoRedo.Manager undoRedoManager;
66     private boolean undoRedoRecording = false;
67     private CompoundEdit compoundEdit;
68     private boolean autoEndCoumpoundEdit;
69     private boolean undoCompoundEdit = false;
70
71     private FormEvents formEvents;
72
73     // list of listeners registered on FormModel
74
private ArrayList listeners;
75     private EventBroker eventBroker;
76
77     private MetaComponentCreator metaCreator;
78
79     private CodeStructure codeStructure = new CodeStructure(false);
80     
81     private FormSettings settings = new FormSettings(this);
82     
83     private boolean freeDesignDefaultLayout = false;
84
85     // -------------
86
// initialization
87

88     FormModel() {
89     }
90
91     /** This methods sets the form base class (which is in fact the superclass
92      * of the form class in source java file). It is used for initializing
93      * the top meta component, and is also presented as the top component
94      * in designer and inspector.
95      */

96     public void setFormBaseClass(Class JavaDoc formClass) throws Exception JavaDoc {
97         if (formBaseClass != null)
98             throw new IllegalStateException JavaDoc("Form type already initialized."); // NOI18N
99

100         RADComponent topComp;
101         if (java.awt.Component JavaDoc.class.isAssignableFrom(formClass)) {
102             if (FormUtils.isContainer(formClass)) {
103                 topComp = new RADVisualFormContainer();
104             }
105             else {
106                 topComp = new RADVisualComponent() {
107                     // top-level component does not have a variable
108
public String JavaDoc getName() {
109                         return FormUtils.getBundleString("CTL_FormTopContainerName"); // NOI18N
110
}
111                     public void setName(String JavaDoc value) {}
112                 };
113             }
114         }
115         else if (java.lang.Object JavaDoc.class != formClass)
116             topComp = new RADFormContainer();
117         else topComp = null;
118
119         if (topComp != null) {
120             topRADComponent = topComp;
121             topComp.initialize(this);
122             topComp.initInstance(formClass);
123             topComp.setInModel(true);
124         }
125
126         formBaseClass = formClass;
127 // topRADComponent = topComp;
128
layoutModel = new LayoutModel();
129         layoutModel.setChangeRecording(false);
130     }
131
132     public Class JavaDoc getFormBaseClass() {
133         return formBaseClass;
134     }
135
136     void setName(String JavaDoc name) {
137         formName = name;
138     }
139
140     void setReadOnly(boolean readOnly) {
141         this.readOnly = readOnly;
142     }
143
144     // -----------
145
// getters
146

147     public final String JavaDoc getName() {
148         return formName;
149     }
150
151     public final boolean isReadOnly() {
152         return readOnly;
153     }
154
155     public final boolean isFormLoaded() {
156         return formLoaded;
157     }
158
159     public final boolean wasCorrected() {
160         return formLoaded && layoutModel != null && layoutModel.wasCorrected();
161     }
162
163 // public final FormDesigner getFormDesigner() {
164
// return FormEditorSupport.getFormDesigner(this);
165
// }
166
//
167
// // for compatibility with previous version
168
// public final FormDataObject getFormDataObject() {
169
// return FormEditorSupport.getFormDataObject(this);
170
// }
171

172     public final RADComponent getTopRADComponent() {
173         return topRADComponent;
174     }
175
176     public ComponentContainer getModelContainer() {
177         if (modelContainer == null)
178             modelContainer = new ModelContainer();
179         return modelContainer;
180     }
181
182     public Collection<RADComponent> getOtherComponents() {
183         return Collections.unmodifiableCollection(otherComponents);
184     }
185
186     public final LayoutModel getLayoutModel() {
187         return layoutModel;
188     }
189
190     public final RADComponent getMetaComponent(String JavaDoc id) {
191         return (RADComponent) idToComponents.get(id);
192     }
193
194     public RADComponent findRADComponent(String JavaDoc name) {
195         Iterator allComps = idToComponents.values().iterator(); // getMetaComponents().iterator();
196
while (allComps.hasNext()) {
197             RADComponent comp = (RADComponent) allComps.next();
198             if (name.equals(comp.getName()))
199                 return comp;
200         }
201         return null;
202     }
203
204     /**
205      * Returns list of all components in the model. A new List instance is
206      * created. The order of the components is random.
207      */

208     public java.util.List JavaDoc<RADComponent> getComponentList() {
209         return new ArrayList(idToComponents.values());
210     }
211
212     /**
213      * Returns list of all components in the model. A new instance of list is
214      * created and the components are added to the list in the traversal order
215      * (used e.g. by code generator or persistence manager).
216      */

217     public java.util.List JavaDoc<RADComponent> getOrderedComponentList() {
218         java.util.List JavaDoc<RADComponent> list = new ArrayList(idToComponents.size());
219         collectMetaComponents(getModelContainer(), list);
220         return list;
221     }
222
223     /**
224      * Returns an unmodifiable collection of all components in the model
225      * in random order.
226      */

227     public Collection<RADComponent> getAllComponents() {
228         return Collections.unmodifiableCollection(idToComponents.values());
229     }
230
231     public Collection<RADComponent> getNonVisualComponents() {
232         List<RADComponent> list = new ArrayList<RADComponent>(otherComponents.size());
233         for (RADComponent metacomp : otherComponents) {
234             if (!java.awt.Component JavaDoc.class.isAssignableFrom(metacomp.getBeanClass()))
235                 list.add(metacomp);
236         }
237         return list;
238     }
239
240     public FormEvents getFormEvents() {
241         if (formEvents == null)
242             formEvents = new FormEvents(this);
243         return formEvents;
244     }
245
246     private static void collectMetaComponents(ComponentContainer cont,
247                                               java.util.List JavaDoc list) {
248         RADComponent[] comps = cont.getSubBeans();
249         for (int i = 0; i < comps.length; i++) {
250             RADComponent comp = comps[i];
251             list.add(comp);
252             if (comp instanceof ComponentContainer)
253                 collectMetaComponents((ComponentContainer) comp, list);
254         }
255     }
256
257     private static void collectVisualMetaComponents(RADVisualContainer cont,
258                                                     java.util.List JavaDoc list) {
259         RADVisualComponent[] comps = cont.getSubComponents();
260         for (int i = 0; i < comps.length; i++) {
261             RADComponent comp = comps[i];
262             list.add(comp);
263             if (comp instanceof RADVisualContainer)
264                 collectVisualMetaComponents((RADVisualContainer) comp, list);
265         }
266     }
267
268     // -----------
269
// adding/deleting components, setting layout, etc
270

271     /**
272      * @return MetaComponentCreator responsible for creating new components and
273      * adding them to the model.
274      */

275     public MetaComponentCreator getComponentCreator() {
276         if (metaCreator == null)
277             metaCreator = new MetaComponentCreator(this);
278         return metaCreator;
279     }
280
281     /** Adds a new component to given (non-visual) container in the model. If
282      * the container is not specified, the component is added to the
283      * "other components". */

284     public void addComponent(RADComponent metacomp,
285                              ComponentContainer parentContainer,
286                              boolean newlyAdded)
287     {
288         if (newlyAdded || !metacomp.isInModel()) {
289             setInModelRecursively(metacomp, true);
290             newlyAdded = true;
291         }
292
293         if (parentContainer != null) {
294             parentContainer.add(metacomp);
295         }
296         else {
297             metacomp.setParentComponent(null);
298             otherComponents.add(metacomp);
299         }
300
301         FormModelEvent ev = fireComponentAdded(metacomp, newlyAdded);
302     }
303
304     /** Adds a new visual component to given container managed by the old
305      * layout support. */

306     public void addVisualComponent(RADVisualComponent metacomp,
307                                    RADVisualContainer parentContainer,
308                                    Object JavaDoc constraints,
309                                    boolean newlyAdded)
310     {
311         LayoutSupportManager layoutSupport = parentContainer.getLayoutSupport();
312         if (layoutSupport != null) {
313             RADVisualComponent[] compArray = new RADVisualComponent[] { metacomp };
314             LayoutConstraints c = constraints instanceof LayoutConstraints ?
315                                   (LayoutConstraints) constraints : null;
316             LayoutConstraints[] constrArray = new LayoutConstraints[] { c };
317             int index = constraints instanceof Integer JavaDoc ? ((Integer JavaDoc)constraints).intValue() : -1;
318
319             // component needs to be "in model" (have code expression) before added to layout
320
if (newlyAdded || !metacomp.isInModel()) {
321                 setInModelRecursively(metacomp, true);
322                 newlyAdded = true;
323             }
324
325             try {
326                 layoutSupport.acceptNewComponents(compArray, constrArray, index);
327             }
328             catch (RuntimeException JavaDoc ex) {
329                 // LayoutSupportDelegate may not accept the component
330
if (newlyAdded)
331                     setInModelRecursively(metacomp, false);
332                 throw ex;
333             }
334
335             parentContainer.add(metacomp, index);
336
337             layoutSupport.addComponents(compArray, constrArray, index);
338
339             FormModelEvent ev = fireComponentAdded(metacomp, newlyAdded);
340         }
341         else {
342             addComponent(metacomp, parentContainer, newlyAdded);
343         }
344     }
345
346     public void setContainerLayoutImpl(RADVisualContainer metacont,
347                                    LayoutSupportDelegate layoutDelegate,
348                                    java.awt.LayoutManager JavaDoc initInstance)
349         throws Exception JavaDoc
350     {
351         LayoutSupportManager currentLS = metacont.getLayoutSupport();
352         LayoutSupportDelegate currentDel =
353             currentLS != null ? currentLS.getLayoutDelegate() : null;
354
355         if (currentLS == null) { // switching to old layout support
356
metacont.setOldLayoutSupport(true);
357         }
358         metacont.setLayoutSupportDelegate(layoutDelegate, initInstance);
359
360         fireContainerLayoutExchanged(metacont, currentDel, layoutDelegate);
361     }
362
363     public void setContainerLayout(RADVisualContainer metacont,
364                                    LayoutSupportDelegate layoutDelegate,
365                                    java.awt.LayoutManager JavaDoc initInstance)
366         throws Exception JavaDoc {
367         LayoutSupportManager currentLS = metacont.getLayoutSupport();
368         setContainerLayoutImpl(metacont, layoutDelegate, initInstance);
369         if (currentLS == null) { // switching to old layout support
370
Object JavaDoc layoutStartMark = layoutModel.getChangeMark();
371             UndoableEdit ue = layoutModel.getUndoableEdit();
372             boolean autoUndo = true;
373             try {
374                 layoutModel.changeContainerToComponent(metacont.getId());
375                 autoUndo = false;
376             } finally {
377                 if (layoutStartMark != null && !layoutStartMark.equals(layoutModel.getChangeMark())) {
378                     addUndoableEdit(ue);
379                 }
380                 if (autoUndo) {
381                     forceUndoOfCompoundEdit();
382                 }
383             }
384         }
385     }
386     
387     void setNaturalContainerLayoutImpl(RADVisualContainer metacont) {
388         LayoutSupportManager currentLS = metacont.getLayoutSupport();
389         LayoutSupportDelegate currentDel = currentLS.getLayoutDelegate();
390         metacont.setOldLayoutSupport(false);
391         fireContainerLayoutExchanged(metacont, currentDel, null);
392     }
393
394     public void setNaturalContainerLayout(RADVisualContainer metacont) {
395         LayoutSupportManager currentLS = metacont.getLayoutSupport();
396         if (currentLS == null)
397             return; // already set (no old layout support)
398

399         setNaturalContainerLayoutImpl(metacont);
400         Object JavaDoc layoutStartMark = layoutModel.getChangeMark();
401         UndoableEdit ue = layoutModel.getUndoableEdit();
402         boolean autoUndo = true;
403         try {
404             if (!layoutModel.changeComponentToContainer(metacont.getId())) {
405                 layoutModel.addRootComponent(
406                         new LayoutComponent(metacont.getId(), true));
407             }
408             autoUndo = false;
409         } finally {
410             if (layoutStartMark != null && !layoutStartMark.equals(layoutModel.getChangeMark())) {
411                 addUndoableEdit(ue);
412             }
413             if (autoUndo) {
414                 forceUndoOfCompoundEdit();
415             }
416         }
417     }
418
419     public void removeComponent(RADComponent metacomp, boolean fromModel) {
420         Object JavaDoc layoutStartMark = null;
421         UndoableEdit ue = null;
422         boolean autoUndo = true;
423         try {
424             if (fromModel && (layoutModel != null)) {
425                 layoutStartMark = layoutModel.getChangeMark();
426                 ue = layoutModel.getUndoableEdit();
427                 layoutModel.removeComponent(metacomp.getId(), true);
428                 removeLayoutComponentsRecursively(metacomp);
429             }
430
431             // [TODO need effective multi-component remove from LayoutModel (start in ComponentInspector.DeleteActionPerformer)]
432
autoUndo = false;
433         } finally {
434             removeComponentImpl(metacomp, fromModel);
435             if (layoutStartMark != null && !layoutStartMark.equals(layoutModel.getChangeMark())) {
436                 addUndoableEdit(ue); // is added to a compound edit
437
}
438             if (autoUndo) {
439                 forceUndoOfCompoundEdit();
440             }
441         }
442     }
443
444     void removeComponentImpl(RADComponent metacomp, boolean fromModel) {
445         if (fromModel && formEvents != null) {
446             removeEventHandlersRecursively(metacomp);
447         }
448
449         RADComponent parent = metacomp.getParentComponent();
450         ComponentContainer parentContainer =
451             parent instanceof ComponentContainer ?
452                 (ComponentContainer) parent : getModelContainer();
453
454         int index = parentContainer.getIndexOf(metacomp);
455         parentContainer.remove(metacomp);
456
457         if (fromModel) {
458             setInModelRecursively(metacomp, false);
459         }
460
461         FormModelEvent ev = fireComponentRemoved(metacomp, parentContainer, index, fromModel);
462     }
463
464     // needed for the case of mixed hierarchy of new/old layout support
465
private void removeLayoutComponentsRecursively(RADComponent metacomp) {
466         if (metacomp instanceof ComponentContainer) {
467             RADComponent[] comps = ((ComponentContainer)metacomp).getSubBeans();
468             for (int i=0; i<comps.length; i++) {
469                 removeLayoutComponentsRecursively(comps[i]);
470             }
471         }
472         LayoutComponent layoutComp = layoutModel == null ? null : layoutModel.getLayoutComponent(metacomp.getId());
473         if (layoutComp != null && layoutComp.getParent() == null) {
474             // remove only root components
475
layoutModel.removeComponent(layoutComp.getId(), true);
476         }
477     }
478
479     void updateMapping(RADComponent metacomp, boolean register) {
480         if (register)
481             idToComponents.put(metacomp.getId(), metacomp);
482         else
483             idToComponents.remove(metacomp.getId());
484     }
485
486     // removes all event handlers attached to given component and all
487
// its subcomponents
488
private void removeEventHandlersRecursively(RADComponent comp) {
489         if (comp instanceof ComponentContainer) {
490             RADComponent[] subcomps = ((ComponentContainer)comp).getSubBeans();
491             for (int i=0; i<subcomps.length; i++)
492                 removeEventHandlersRecursively(subcomps[i]);
493         }
494
495         Event[] events = comp.getKnownEvents();
496         for (int i=0; i < events.length; i++)
497             if (events[i].hasEventHandlers())
498                 getFormEvents().detachEvent(events[i]);
499     }
500
501     static void setInModelRecursively(RADComponent metacomp, boolean inModel) {
502         if (metacomp instanceof ComponentContainer) {
503             RADComponent[] comps = ((ComponentContainer)metacomp).getSubBeans();
504             for (int i=0; i < comps.length; i++)
505                 setInModelRecursively(comps[i], inModel);
506         }
507         metacomp.setInModel(inModel);
508     }
509
510     // ----------
511
// undo and redo
512

513     public void setUndoRedoRecording(boolean record) {
514         t("turning undo/redo recording "+(record?"on":"off")); // NOI18N
515
undoRedoRecording = record;
516     }
517
518     public boolean isUndoRedoRecording() {
519         return undoRedoRecording;
520     }
521
522     public boolean startCompoundEdit(boolean endAutomatically) {
523         if (compoundEdit == null) {
524             t("starting compound edit"); // NOI18N
525
compoundEdit = new CompoundEdit();
526             autoEndCoumpoundEdit = endAutomatically;
527             return true;
528         }
529         return false;
530     }
531
532     public CompoundEdit endCompoundEdit(boolean commit) {
533         if (compoundEdit != null) {
534             t("ending compound edit: "+commit); // NOI18N
535
compoundEdit.end();
536             autoEndCoumpoundEdit = false;
537             if (commit && undoRedoRecording && compoundEdit.isSignificant()) {
538                 getUndoRedoManager().undoableEditHappened(
539                     new UndoableEditEvent JavaDoc(this, compoundEdit));
540             } else {
541                 undoCompoundEdit = false;
542             }
543             CompoundEdit edit = compoundEdit;
544             compoundEdit = null;
545             return edit;
546         }
547         return null;
548     }
549     
550     public void forceUndoOfCompoundEdit() {
551         if (compoundEdit != null) {
552             undoCompoundEdit = true;
553         }
554     }
555
556     public boolean isCompoundEditInProgress() {
557         return compoundEdit != null && compoundEdit.isInProgress();
558     }
559
560     public void addUndoableEdit(UndoableEdit edit) {
561         t("adding undoable edit"); // NOI18N
562
if (isCompoundEditInProgress())
563             compoundEdit.addEdit(edit);
564         else
565             getUndoRedoManager().undoableEditHappened(
566                      new UndoableEditEvent JavaDoc(this, edit));
567     }
568
569     UndoRedo.Manager getUndoRedoManager() {
570 // if (undoRedoManager == null) {
571
// undoRedoManager = new UndoRedoManager();
572
// undoRedoManager.setLimit(50);
573
// }
574
return undoRedoManager;
575     }
576
577     // [Undo manager performing undo/redo in AWT event thread should not be
578
// probably implemented here - in FormModel - but seperately.]
579
class UndoRedoManager extends UndoRedo.Manager {
580         private Mutex.ExceptionAction runUndo = new Mutex.ExceptionAction() {
581             public Object JavaDoc run() throws Exception JavaDoc {
582                 superUndo();
583                 return null;
584             }
585         };
586         private Mutex.ExceptionAction runRedo = new Mutex.ExceptionAction() {
587             public Object JavaDoc run() throws Exception JavaDoc {
588                 superRedo();
589                 return null;
590             }
591         };
592
593         public void superUndo() throws CannotUndoException {
594             super.undo();
595         }
596         public void superRedo() throws CannotRedoException {
597             super.redo();
598         }
599
600         public void undo() throws CannotUndoException {
601             if (java.awt.EventQueue.isDispatchThread()) {
602                 superUndo();
603             }
604             else {
605                 try {
606                     Mutex.EVENT.readAccess(runUndo);
607                 }
608                 catch (MutexException ex) {
609                     Exception JavaDoc e = ex.getException();
610                     if (e instanceof CannotUndoException)
611                         throw (CannotUndoException) e;
612                     else // should not happen, ignore
613
e.printStackTrace();
614                 }
615             }
616         }
617
618         public void redo() throws CannotRedoException {
619             if (java.awt.EventQueue.isDispatchThread()) {
620                 superRedo();
621             }
622             else {
623                 try {
624                     Mutex.EVENT.readAccess(runRedo);
625                 }
626                 catch (MutexException ex) {
627                     Exception JavaDoc e = ex.getException();
628                     if (e instanceof CannotRedoException)
629                         throw (CannotRedoException) e;
630                     else // should not happen, ignore
631
e.printStackTrace();
632                 }
633             }
634         }
635     }
636
637     // ----------
638
// listeners registration, firing methods
639

640     public synchronized void addFormModelListener(FormModelListener l) {
641         if (listeners == null)
642             listeners = new ArrayList();
643         listeners.add(l);
644     }
645
646     public synchronized void removeFormModelListener(FormModelListener l) {
647         if (listeners != null)
648             listeners.remove(l);
649     }
650
651     /** Fires an event informing about that the form has been just loaded. */
652     public void fireFormLoaded() {
653         t("firing form loaded"); // NOI18N
654

655         formLoaded = true;
656         eventBroker = new EventBroker();
657 // if (undoRedoManager != null)
658
// undoRedoManager.discardAllEdits();
659
if (!readOnly && !Boolean.getBoolean("netbeans.form.no_undo")) { // NOI18N
660
undoRedoManager = new UndoRedoManager();
661             undoRedoManager.setLimit(50);
662             setUndoRedoRecording(true);
663             if (layoutModel != null)
664                 layoutModel.setChangeRecording(true);
665         }
666 // initializeCodeGenerator(); // [should go away]
667

668         sendEventLater(new FormModelEvent(this, FormModelEvent.FORM_LOADED));
669     }
670
671     /** Fires an event informing about that the form is just about to be saved. */
672     public void fireFormToBeSaved() {
673         t("firing form to be saved"); // NOI18N
674

675         sendEventImmediately(
676             new FormModelEvent(this, FormModelEvent.FORM_TO_BE_SAVED));
677     }
678
679     /** Fires an event informing about that the form is just about to be closed. */
680     public void fireFormToBeClosed() {
681         t("firing form to be closed"); // NOI18N
682

683         if (undoRedoManager != null)
684             undoRedoManager.discardAllEdits();
685
686         sendEventImmediately(
687             new FormModelEvent(this, FormModelEvent.FORM_TO_BE_CLOSED));
688     }
689
690     /** Fires an event informing about changing layout manager of a container.
691      * An undoable edit is created and registered automatically. */

692     public FormModelEvent fireContainerLayoutExchanged(
693                               RADVisualContainer metacont,
694                               LayoutSupportDelegate oldLayout,
695                               LayoutSupportDelegate newLayout)
696     {
697         t("firing container layout exchange, container: " // NOI18N
698
+ (metacont != null ? metacont.getName() : "null")); // NOI18N
699

700         FormModelEvent ev =
701             new FormModelEvent(this, FormModelEvent.CONTAINER_LAYOUT_EXCHANGED);
702         ev.setLayout(metacont, oldLayout, newLayout);
703         sendEvent(ev);
704
705         if (undoRedoRecording && metacont != null && oldLayout != newLayout)
706             addUndoableEdit(ev.getUndoableEdit());
707
708         return ev;
709     }
710
711     /** Fires an event informing about changing a property of container layout.
712      * An undoable edit is created and registered automatically. */

713     public FormModelEvent fireContainerLayoutChanged(
714                               RADVisualContainer metacont,
715                               String JavaDoc propName,
716                               Object JavaDoc oldValue,
717                               Object JavaDoc newValue)
718     {
719         t("firing container layout change, container: " // NOI18N
720
+ (metacont != null ? metacont.getName() : "null") // NOI18N
721
+ ", property: " + propName); // NOI18N
722

723         FormModelEvent ev =
724             new FormModelEvent(this, FormModelEvent.CONTAINER_LAYOUT_CHANGED);
725         ev.setComponentAndContainer(metacont, metacont);
726         ev.setProperty(propName, oldValue, newValue);
727         sendEvent(ev);
728
729         if (undoRedoRecording
730             && metacont != null && (propName == null || oldValue != newValue))
731         {
732             addUndoableEdit(ev.getUndoableEdit());
733         }
734
735         return ev;
736     }
737
738     /** Fires an event informing about changing a property of component layout
739      * constraints. An undoable edit is created and registered automatically. */

740     public FormModelEvent fireComponentLayoutChanged(
741                               RADVisualComponent metacomp,
742                               String JavaDoc propName,
743                               Object JavaDoc oldValue,
744                               Object JavaDoc newValue)
745     {
746         t("firing component layout change: " // NOI18N
747
+ (metacomp != null ? metacomp.getName() : "null")); // NOI18N
748

749         FormModelEvent ev =
750             new FormModelEvent(this, FormModelEvent.COMPONENT_LAYOUT_CHANGED);
751         ev.setComponentAndContainer(metacomp, null);
752         ev.setProperty(propName, oldValue, newValue);
753         sendEvent(ev);
754
755         if (undoRedoRecording
756             && metacomp != null && propName != null && oldValue != newValue)
757         {
758             addUndoableEdit(ev.getUndoableEdit());
759         }
760
761         return ev;
762     }
763
764     /** Fires an event informing about adding a component to the form.
765      * An undoable edit is created and registered automatically. */

766     public FormModelEvent fireComponentAdded(RADComponent metacomp,
767                                              boolean addedNew)
768     {
769         t("firing component added: " // NOI18N
770
+ (metacomp != null ? metacomp.getName() : "null")); // NOI18N
771

772         FormModelEvent ev =
773             new FormModelEvent(this, FormModelEvent.COMPONENT_ADDED);
774         ev.setAddData(metacomp, null, addedNew);
775         sendEvent(ev);
776
777         if (undoRedoRecording && metacomp != null)
778             addUndoableEdit(ev.getUndoableEdit());
779
780         return ev;
781     }
782
783     /** Fires an event informing about removing a component from the form.
784      * An undoable edit is created and registered automatically. */

785     public FormModelEvent fireComponentRemoved(RADComponent metacomp,
786                                                ComponentContainer metacont,
787                                                int index,
788                                                boolean removedFromModel)
789     {
790         t("firing component removed: " // NOI18N
791
+ (metacomp != null ? metacomp.getName() : "null")); // NOI18N
792

793         FormModelEvent ev =
794             new FormModelEvent(this, FormModelEvent.COMPONENT_REMOVED);
795         ev.setRemoveData(metacomp, metacont, index, removedFromModel);
796         sendEvent(ev);
797
798         if (undoRedoRecording && metacomp != null && metacont != null)
799             addUndoableEdit(ev.getUndoableEdit());
800
801         return ev;
802     }
803
804     /** Fires an event informing about reordering components in a container.
805      * An undoable edit is created and registered automatically. */

806     public FormModelEvent fireComponentsReordered(ComponentContainer metacont,
807                                                   int[] perm)
808     {
809         t("firing components reorder in container: " // NOI18N
810
+ (metacont instanceof RADComponent ?
811              ((RADComponent)metacont).getName() : "<top>")); // NOI18N
812

813         FormModelEvent ev =
814             new FormModelEvent(this, FormModelEvent.COMPONENTS_REORDERED);
815         ev.setComponentAndContainer(null, metacont);
816         ev.setReordering(perm);
817         sendEvent(ev);
818
819         if (undoRedoRecording && metacont != null)
820             addUndoableEdit(ev.getUndoableEdit());
821
822         return ev;
823     }
824
825     /** Fires an event informing about changing a property of a component.
826      * An undoable edit is created and registered automatically. */

827     public FormModelEvent fireComponentPropertyChanged(RADComponent metacomp,
828                                                        String JavaDoc propName,
829                                                        Object JavaDoc oldValue,
830                                                        Object JavaDoc newValue)
831     {
832         t("firing component property change, component: " // NOI18N
833
+ (metacomp != null ? metacomp.getName() : "<null component>") // NOI18N
834
+ ", property: " + propName); // NOI18N
835

836         FormModelEvent ev =
837             new FormModelEvent(this, FormModelEvent.COMPONENT_PROPERTY_CHANGED);
838         ev.setComponentAndContainer(metacomp, null);
839         ev.setProperty(propName, oldValue, newValue);
840         sendEvent(ev);
841
842         if (undoRedoRecording
843             && metacomp != null && propName != null && oldValue != newValue)
844         {
845             addUndoableEdit(ev.getUndoableEdit());
846         }
847
848         return ev;
849     }
850
851
852     /** Fires an event informing about changing a synthetic property of
853      * a component. An undoable edit is created and registered automatically. */

854     public FormModelEvent fireSyntheticPropertyChanged(RADComponent metacomp,
855                                                        String JavaDoc propName,
856                                                        Object JavaDoc oldValue,
857                                                        Object JavaDoc newValue)
858     {
859         t("firing synthetic property change, component: " // NOI18N
860
+ (metacomp != null ? metacomp.getName() : "null") // NOI18N
861
+ ", property: " + propName); // NOI18N
862

863         FormModelEvent ev =
864             new FormModelEvent(this, FormModelEvent.SYNTHETIC_PROPERTY_CHANGED);
865         ev.setComponentAndContainer(metacomp, null);
866         ev.setProperty(propName, oldValue, newValue);
867         sendEvent(ev);
868
869         if (undoRedoRecording && propName != null && oldValue != newValue)
870         {
871             addUndoableEdit(ev.getUndoableEdit());
872         }
873
874         return ev;
875     }
876
877     /** Fires an event informing about attaching a new event to an event handler
878      * (createdNew parameter indicates whether the event handler was created
879      * first). An undoable edit is created and registered automatically. */

880     public FormModelEvent fireEventHandlerAdded(Event event,
881                                                 String JavaDoc handler,
882                                                 String JavaDoc bodyText,
883                                                 boolean createdNew)
884     {
885         t("event handler added: "+handler); // NOI18N
886

887         FormModelEvent ev =
888             new FormModelEvent(this, FormModelEvent.EVENT_HANDLER_ADDED);
889         ev.setEvent(event, handler, bodyText, createdNew);
890         sendEvent(ev);
891
892         if (undoRedoRecording && event != null && handler != null)
893             addUndoableEdit(ev.getUndoableEdit());
894
895         return ev;
896     }
897
898     /** Fires an event informing about detaching an event from event handler
899      * (handlerDeleted parameter indicates whether the handler was deleted as
900      * the last event was detached). An undoable edit is created and registered
901      * automatically. */

902     public FormModelEvent fireEventHandlerRemoved(Event event,
903                                                   String JavaDoc handler,
904                                                   boolean handlerDeleted)
905     {
906         t("firing event handler removed: "+handler); // NOI18N
907

908         FormModelEvent ev =
909             new FormModelEvent(this, FormModelEvent.EVENT_HANDLER_REMOVED);
910         ev.setEvent(event, handler, null, handlerDeleted);
911         sendEvent(ev);
912
913         if (undoRedoRecording && event != null && handler != null)
914             addUndoableEdit(ev.getUndoableEdit());
915
916         return ev;
917     }
918
919     /** Fires an event informing about renaming an event handler. An undoable
920      * edit is created and registered automatically. */

921     public FormModelEvent fireEventHandlerRenamed(String JavaDoc oldHandlerName,
922                                                   String JavaDoc newHandlerName)
923     {
924         t("event handler renamed: "+oldHandlerName+" to "+newHandlerName); // NOI18N
925

926         FormModelEvent ev =
927             new FormModelEvent(this, FormModelEvent.EVENT_HANDLER_RENAMED);
928         ev.setEvent(oldHandlerName, newHandlerName);
929         sendEvent(ev);
930
931         if (undoRedoRecording && oldHandlerName != null && newHandlerName != null)
932             addUndoableEdit(ev.getUndoableEdit());
933
934         return ev;
935     }
936
937     /** Fires an event informing about general form change. */
938     public FormModelEvent fireFormChanged(boolean immediately) {
939         t("firing form change"); // NOI18N
940

941         FormModelEvent ev = new FormModelEvent(this, FormModelEvent.OTHER_CHANGE);
942         if (immediately)
943             sendEventImmediately(ev);
944         else
945             sendEvent(ev);
946
947         return ev;
948     }
949
950     public void fireEvents(FormModelEvent[] events) {
951         java.util.List JavaDoc targets;
952         synchronized(this) {
953             if (listeners == null)
954                 return;
955             targets = (ArrayList) listeners.clone();
956         }
957
958         for (int i=0; i < targets.size(); i++) {
959             FormModelListener l = (FormModelListener) targets.get(i);
960             l.formChanged(events);
961         }
962     }
963
964     // ---------
965
// firing methods for batch event processing
966

967     void sendEvent(FormModelEvent ev) {
968         EventBroker broker = getEventBroker();
969         if (broker != null)
970             broker.sendEvent(ev);
971         else {
972             t("no event broker, firing event directly: "+ev.getChangeType()); // NOI18N
973
fireEvents(new FormModelEvent[] { ev });
974         }
975     }
976
977     void sendEventLater(FormModelEvent ev) {
978         EventBroker broker = getEventBroker();
979         if (broker != null)
980             broker.sendEventLater(ev);
981         else {
982             t("no event broker, firing event directly: "+ev.getChangeType()); // NOI18N
983
fireEvents(new FormModelEvent[] { ev });
984         }
985     }
986
987     void sendEventImmediately(FormModelEvent ev) {
988         fireEvents(new FormModelEvent[] { ev });
989     }
990
991     EventBroker getEventBroker() {
992         // event broker is created when the form is loaded
993
// if (eventBroker == null && isFormLoaded())
994
// eventBroker = new EventBroker();
995
return eventBroker;
996     }
997     
998     public FormSettings getSettings() {
999         return settings;
1000    }
1001
1002    /** Class that collects events and fires them on FormModel in one batch
1003     * later. Collecting the events works only if the events are passed
1004     * to the broker from AWT event dispatch thread.
1005     */

1006    private class EventBroker implements Runnable JavaDoc {
1007        private List eventList;
1008
1009        public void sendEvent(FormModelEvent ev) {
1010            if (shouldSendLater(ev))
1011                sendEventLater(ev);
1012            else
1013                sendEventImmediately(ev);
1014        }
1015
1016        public void sendEventImmediately(FormModelEvent ev) {
1017            t("firing event directly from event broker: "+ev.getChangeType()); // NOI18N
1018
FormModel.this.fireEvents(new FormModelEvent[] { ev });
1019        }
1020
1021        public void sendEventLater(FormModelEvent ev) {
1022            // works properly only if called from AWT event dispatch thread
1023
if (!java.awt.EventQueue.isDispatchThread()) {
1024                sendEventImmediately(ev);
1025                return;
1026            }
1027
1028            if (eventList == null) {
1029                eventList = new ArrayList();
1030                if (ev.isModifying()
1031                    && FormModel.this.isUndoRedoRecording()
1032                    && FormModel.this.startCompoundEdit(true))
1033                    t("compound undoable edit started from event broker"); // NOI18N
1034

1035                java.awt.EventQueue.invokeLater(this);
1036            }
1037
1038            eventList.add(ev);
1039            t("event "+ev.getChangeType()+" added to queue in event broker"); // NOI18N
1040
}
1041
1042        private boolean shouldSendLater(FormModelEvent ev) {
1043            return eventList != null || ev.isModifying();
1044        }
1045
1046        private List pickUpEvents() {
1047            List list = eventList;
1048            eventList = null;
1049            return list;
1050        }
1051
1052        public void run() {
1053            List list = pickUpEvents();
1054            boolean firedSuccessfully = false;
1055            try {
1056                if (list != null && !list.isEmpty()) {
1057                    FormModelEvent[] events = new FormModelEvent[list.size()];
1058                    list.toArray(events);
1059                    t("firing event batch of "+list.size()+" events from event broker"); // NOI18N
1060
FormModel.this.fireEvents(events);
1061                }
1062                firedSuccessfully = true;
1063            } finally {
1064                if (FormModel.this.autoEndCoumpoundEdit) {
1065                    CompoundEdit edit = FormModel.this.endCompoundEdit(true);
1066                    if (edit != null) {
1067                        t("coumpound undoable edit ended automatically"); // NOI18N
1068
if ((undoCompoundEdit || !firedSuccessfully) && getUndoRedoManager().canUndo()) {
1069                            undoCompoundEdit = false;
1070                            getUndoRedoManager().undo();
1071                        }
1072                    }
1073                    undoCompoundEdit = false;
1074                }
1075            }
1076        }
1077    }
1078
1079    // -------------
1080

1081    CodeStructure getCodeStructure() {
1082        return codeStructure;
1083    }
1084    
1085    public boolean isFreeDesignDefaultLayout() {
1086        return freeDesignDefaultLayout;
1087    }
1088    
1089    void setFreeDesignDefaultLayout(boolean freeDesignDefaultLayout) {
1090        this.freeDesignDefaultLayout = freeDesignDefaultLayout;
1091    }
1092
1093// CodeGenerator getCodeGenerator() {
1094
//// return FormEditorSupport.getCodeGenerator(this);
1095
// if (codeGenerator == null)
1096
// codeGenerator = new JavaCodeGenerator();
1097
// return codeGenerator;
1098
// }
1099
//
1100
// void initializeCodeGenerator() {
1101
// getCodeGenerator().initialize(this);
1102
// }
1103

1104    // ---------------
1105
// ModelContainer innerclass
1106

1107    final class ModelContainer implements ComponentContainer {
1108        public RADComponent[] getSubBeans() {
1109            int n = otherComponents.size();
1110            if (topRADComponent != null)
1111                n++;
1112            RADComponent[] comps = new RADComponent[n];
1113            otherComponents.toArray(comps);
1114            if (topRADComponent != null)
1115                comps[n-1] = topRADComponent;
1116            return comps;
1117        }
1118
1119        public void initSubComponents(RADComponent[] initComponents) {
1120            otherComponents.clear();
1121            for (int i = 0; i < initComponents.length; i++)
1122                if (initComponents[i] != topRADComponent)
1123                    otherComponents.add(initComponents[i]);
1124        }
1125
1126        public void reorderSubComponents(int[] perm) {
1127            RADComponent[] components = new RADComponent[otherComponents.size()];
1128            for (int i=0; i < perm.length; i++)
1129                components[perm[i]] = (RADComponent) otherComponents.get(i);
1130
1131            otherComponents.clear();
1132            otherComponents.addAll(Arrays.asList(components));
1133        }
1134
1135        public void add(RADComponent comp) {
1136            comp.setParentComponent(null);
1137            otherComponents.add(comp);
1138        }
1139
1140        public void remove(RADComponent comp) {
1141            if (otherComponents.remove(comp))
1142                comp.setParentComponent(null);
1143        }
1144
1145        public int getIndexOf(RADComponent comp) {
1146            int index = otherComponents.indexOf(comp);
1147            if (index < 0 && comp == topRADComponent)
1148                index = otherComponents.size();
1149            return index;
1150        }
1151    }
1152
1153    // ---------------
1154

1155    /** For debugging purposes only. */
1156    static private int traceCount = 0;
1157    /** For debugging purposes only. */
1158    static private final boolean TRACE = false;
1159    /** For debugging purposes only. */
1160    static void t(String JavaDoc str) {
1161        if (TRACE)
1162            if (str != null)
1163                System.out.println("FormModel "+(++traceCount)+": "+str); // NOI18N
1164
else
1165                System.out.println(""); // NOI18N
1166
}
1167}
1168
Popular Tags