001: /*
002: * Copyright (C) 2005 Jeff Tassin
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package com.jeta.swingbuilder.gui.formmgr;
020:
021: import java.awt.Component;
022: import java.awt.Container;
023: import java.io.File;
024: import java.io.FileInputStream;
025: import java.util.Collection;
026: import java.util.HashMap;
027: import java.util.Iterator;
028:
029: import com.jeta.forms.gui.common.FormException;
030: import com.jeta.forms.gui.common.FormUtils;
031: import com.jeta.forms.gui.components.ComponentSource;
032: import com.jeta.forms.gui.form.FormComponent;
033: import com.jeta.forms.gui.form.GridComponent;
034: import com.jeta.forms.gui.form.GridView;
035: import com.jeta.forms.gui.form.StandardComponent;
036: import com.jeta.forms.gui.formmgr.FormManager;
037: import com.jeta.forms.gui.formmgr.FormManagerUtils;
038: import com.jeta.forms.logger.FormsLogger;
039: import com.jeta.forms.project.ProjectManager;
040: import com.jeta.forms.store.memento.FormMemento;
041: import com.jeta.open.registry.JETARegistry;
042: import com.jeta.swingbuilder.gui.editor.DesignFormComponent;
043: import com.jeta.swingbuilder.gui.editor.FormEditor;
044: import com.jeta.swingbuilder.gui.handler.FormCellHandler;
045: import com.jeta.swingbuilder.gui.handler.FormKeyboardHandler;
046: import com.jeta.swingbuilder.gui.handler.StandardCellHandler;
047: import com.jeta.swingbuilder.gui.handler.StandardKeyboardHandler;
048: import com.jeta.swingbuilder.gui.handler.TabPaneCellHandler;
049: import com.jeta.swingbuilder.gui.utils.FormDesignerUtils;
050:
051: /**
052: * Provides some common form management operations.
053: *
054: * @author Jeff Tassin
055: */
056: public abstract class AbstractFormManager implements FormManager {
057: /**
058: * A map of formIds to FormComponents m_formcache<String,FormComponent>
059: */
060: private HashMap m_formcache = new HashMap();
061:
062: /**
063: * Required for initializing newly created forms.
064: */
065: private ComponentSource m_compsrc;
066:
067: /**
068: * The object responsible for managing the opened FormEditors
069: */
070: private EditorManager m_editor_mgr;
071:
072: /**
073: * ctor
074: */
075: public AbstractFormManager(ComponentSource compSrc,
076: EditorManager emgr) {
077: m_compsrc = compSrc;
078: m_editor_mgr = emgr;
079: }
080:
081: /**
082: * Activates an AWT container. We search for all child components and
083: * replace any nested forms with a surrogate. This is needed for components
084: * like JTabbedPanes where we can embed a form at design time.
085: */
086: public void activateContainer(Container cc) {
087: if (cc == null)
088: return;
089:
090: for (int index = 0; index < cc.getComponentCount(); index++) {
091: Component comp = cc.getComponent(index);
092: if (comp instanceof FormComponent) {
093: activateForm((FormComponent) comp);
094: } else if (comp instanceof Container) {
095: activateContainer((Container) comp);
096: }
097: }
098: }
099:
100: /**
101: * Activates this form. Basically, we need to search for all nested
102: * FormSurrogates contained here and replace with the actual form from the
103: * FormManager.
104: */
105: public void activateForm(FormComponent form) {
106: if (form == null)
107: return;
108:
109: GridView view = form.getChildView();
110: Collection children = view.listComponents();
111: Iterator iter = children.iterator();
112: // System.out.println( "FormManager.activateForm: id: " + form.getId() +
113: // "
114: // children: " + children.size() );
115:
116: while (iter.hasNext()) {
117: GridComponent gc = (GridComponent) iter.next();
118: if (gc instanceof FormSurrogate) {
119: FormSurrogate fs = (FormSurrogate) gc;
120: FormComponent fc = (FormComponent) getForm(fs.getId());
121: if (fc == null && FormUtils.isDebug()) {
122: System.out
123: .println("FormManager.activateForm: failed for: "
124: + fs.getId());
125: FormUtils.safeAssert(false);
126: }
127: view.replaceComponent(fc, fs);
128: fc.setControlButtonsVisible(true);
129: activateForm(fc);
130: } else if (gc instanceof FormComponent) {
131: FormComponent fc = (FormComponent) gc;
132: fc.setControlButtonsVisible(true);
133: activateForm(fc);
134: } else if (gc instanceof StandardComponent) {
135: StandardComponent sc = (StandardComponent) gc;
136: Component comp = sc.getBeanDelegate();
137: if (comp instanceof Container)
138: activateContainer((Container) comp);
139: }
140: }
141: form.revalidate();
142: }
143:
144: /**
145: * Activates and shows the form in the application workspace. Additionally,
146: * any nested forms are synchronized with the latest changes in the new
147: * view. This is important because we can have multiple views of the same
148: * form.
149: */
150: public void activateForm(String formId) {
151: FormComponent fc = getForm(formId);
152: assert (fc != null);
153: if (fc != null) {
154: activateForm(fc);
155: }
156: }
157:
158: /**
159: * Deactivates an AWT container. We search for all child components and
160: * replace any nested forms with a surrogate. This is needed for components
161: * like JTabbedPanes where we can embed a form at design time.
162: */
163: public void deactivateContainer(Container cc) {
164: if (cc == null)
165: return;
166:
167: for (int index = 0; index < cc.getComponentCount(); index++) {
168: Component comp = cc.getComponent(index);
169: if (comp instanceof FormComponent) {
170: deactivateForm((FormComponent) comp);
171: } else if (comp instanceof Container) {
172: deactivateContainer((Container) comp);
173: }
174: }
175: }
176:
177: /**
178: * Deactivates this form. Basically, we need to search for all nested
179: * FormComponents and replace with surrogates.
180: */
181: public void deactivateForm(FormComponent form) {
182: if (form == null)
183: return;
184:
185: GridView view = form.getChildView();
186: Collection children = view.listComponents();
187: // System.out.println( "FormManager.deactivate: id: " + form.getId() + "
188: // children: " + children.size() );
189:
190: Iterator iter = children.iterator();
191: while (iter.hasNext()) {
192: GridComponent gc = (GridComponent) iter.next();
193: if (gc instanceof FormComponent) {
194: FormComponent childform = (FormComponent) gc;
195: FormSurrogate fs = new FormSurrogate(childform);
196:
197: // System.out.println( "FormComponent.deactivate child form: " +
198: // childform.getName() + " id: " + childform.getId() + " replace
199: // child form at: col: " + childform.getColumn() + " row: " +
200: // childform.getRow() );
201:
202: view.replaceComponent(fs, childform);
203:
204: /**
205: * We register the form each time because the child form could
206: * be embedded an not registered with the form manager yet.
207: */
208: registerForm(childform);
209: deactivateForm(childform);
210: } else if (gc instanceof StandardComponent) {
211: StandardComponent sc = (StandardComponent) gc;
212: Component comp = sc.getBeanDelegate();
213: if (comp instanceof Container) {
214: deactivateContainer((Container) comp);
215: }
216: }
217: }
218: }
219:
220: /**
221: * DesActivates the forms in the given editor. Additionally, any nested
222: * forms are synchronized with the latest changes in the new view. This is
223: * important because we can have multiple views of the same form.
224: */
225: public void deactivateForms(Container parent) {
226: if (parent == null)
227: return;
228:
229: assert (parent instanceof FormEditor);
230: FormEditor editor = (FormEditor) parent;
231: editor.deactivate();
232: FormComponent fc = editor.getTopParent();
233: assert (fc != null);
234: if (fc != null) {
235: deactivateForm(fc);
236: }
237: }
238:
239: /**
240: * @return the object responsible for managing the form editors.
241: */
242: public EditorManager getEditorManager() {
243: return m_editor_mgr;
244: }
245:
246: /**
247: * Searches the list of cached forms for a form that has the given file
248: * path.
249: */
250: protected FormComponent findForm(String path) {
251: Iterator iter = m_formcache.values().iterator();
252: while (iter.hasNext()) {
253: FormComponent comp = (FormComponent) iter.next();
254: if (path.equals(comp.getAbsolutePath())) {
255: return comp;
256: }
257: }
258: return null;
259: }
260:
261: /**
262: * @return the form that has current formId. Null is returned if the form is
263: * not in cache.
264: */
265: public FormComponent getForm(String formId) {
266: return (FormComponent) m_formcache.get(formId);
267: }
268:
269: /**
270: * @return a collection of Form Ids that are current opened in the manager.
271: */
272: public Collection getForms() {
273: Collection form_ids = m_formcache.keySet();
274: return form_ids;
275: }
276:
277: /**
278: * Installs the event handlers for this component (keyboard and mouse). We
279: * need the componentsouce because some handlers are responsible for
280: * creating child components in the form.
281: */
282: public void installFormHandlers(ComponentSource compsrc,
283: FormComponent fc) {
284: /**
285: * the only time fc is not an instanceof DesignFormComponent is when a
286: * custom bean is being used that itself uses a FormPanel. This is a
287: * very special case
288: */
289: if (fc instanceof DesignFormComponent) {
290: FormCellHandler cchandler = new FormCellHandler(fc, compsrc);
291: FormKeyboardHandler keyhandler = new FormKeyboardHandler(
292: fc, compsrc);
293: fc.setMouseHandler(cchandler);
294: fc.setKeyboardHandler(keyhandler);
295:
296: GridView view = fc.getChildView();
297: Iterator iter = view.gridIterator();
298: while (iter.hasNext()) {
299: GridComponent gc = (GridComponent) iter.next();
300: installHandlers(compsrc, gc);
301: }
302: }
303: }
304:
305: /**
306: * Install event handlers (mouse and keyboard) for this component
307: */
308: public void installStandardHandlers(ComponentSource compsrc,
309: StandardComponent sc) {
310: if (sc.getBeanDelegate() instanceof javax.swing.JTabbedPane) {
311: TabPaneCellHandler handler = new TabPaneCellHandler(sc,
312: compsrc);
313: sc.setMouseHandler(handler);
314: } else {
315: StandardCellHandler handler = new StandardCellHandler(sc,
316: compsrc);
317: StandardKeyboardHandler keyhandler = new StandardKeyboardHandler(
318: sc, compsrc);
319: sc.setMouseHandler(handler);
320: sc.setKeyboardHandler(keyhandler);
321: }
322: }
323:
324: /**
325: * Installs the mouse and keyboard handlers for the given component. Note
326: * that we don't do this in the GridComponent itself because handlers are
327: * only installed in design mode.
328: */
329: public void installHandlers(ComponentSource compsrc,
330: Container gridComponent) {
331: if (gridComponent == null)
332: return;
333:
334: if (gridComponent instanceof StandardComponent) {
335: installStandardHandlers(compsrc,
336: (StandardComponent) gridComponent);
337: } else if (gridComponent instanceof FormComponent) {
338: installFormHandlers(compsrc, (FormComponent) gridComponent);
339: }
340:
341: for (int index = 0; index < gridComponent.getComponentCount(); index++) {
342: Component comp = gridComponent.getComponent(index);
343: if (comp instanceof Container) {
344: installHandlers(compsrc, (Container) comp);
345: }
346: }
347: }
348:
349: /**
350: * Opens a form from a absolute file path.
351: */
352: public FormComponent openLinkedForm(String path)
353: throws FormException {
354: return openForm(new File(path));
355: }
356:
357: /**
358: * Opens a form from a absolute file path.
359: */
360: public FormComponent openLinkedForm(File f) throws FormException {
361: return openForm(f);
362: }
363:
364: /**
365: * Opens the form from a file and puts it in the cache.
366: */
367: protected FormComponent openForm(File file) throws FormException {
368: try {
369: FormComponent fc = findForm(file.getPath());
370: if (fc == null) {
371:
372: FormMemento memento = FormManagerUtils
373: .loadForm(new FileInputStream(file));
374:
375: /**
376: * handle the case where the user may have copied the form to a
377: * different location/filename
378: */
379: ProjectManager pmgr = (ProjectManager) JETARegistry
380: .lookup(ProjectManager.COMPONENT_ID);
381: String relpath = pmgr.getRelativePath(file.getPath());
382: if (relpath == null) {
383: relpath = file.getPath();
384: }
385:
386: /**
387: * The linked form may already be opened. So, let's use the
388: * currently opened form if this is the case.
389: */
390: fc = getForm(relpath);
391: if (fc == null) {
392: fc = new DesignFormComponent();
393: fc.setState(memento);
394:
395: fc.setAbsolutePath(file.getPath());
396: // @JMT no need to reset id's because the embedded form id
397: // is
398: // derived from the hashCode of the form.
399: FormManagerDesignUtils.registerForms(this , fc);
400:
401: installHandlers(m_compsrc, fc);
402: }
403: } else {
404: // System.out.println( "AbstractFormManager.openForm found in
405: // cache:
406: // " + file.getPath() );
407: }
408: return fc;
409: } catch (Exception e) {
410: System.err
411: .println("Unable to load form: " + file.getPath());
412: FormsLogger.debug(e);
413: throw new FormException(e);
414: }
415: }
416:
417: /**
418: * Opens an embedded form.
419: */
420: public void openEmbeddedForm(FormComponent comp) {
421: FormComponent fc = getForm(comp.getId());
422: if (fc == null) {
423: m_formcache.put(comp.getId(), comp);
424: } else {
425: assert (fc == comp);
426: }
427: }
428:
429: /**
430: * Registers a form with this FormManager. This is mainly used for embedded
431: * forms.
432: */
433: public void registerForm(FormComponent fc) {
434: if (fc == null)
435: return;
436:
437: if (FormDesignerUtils.isDebug()) {
438: FormComponent exists = getForm(fc.getId());
439: if (exists != null) {
440: if (exists != fc) {
441: System.out
442: .println("AbstractFormManager.registerForm failed already exists. "
443: + fc.getId());
444: }
445: }
446: }
447: m_formcache.put(fc.getId(), fc);
448: }
449:
450: /**
451: * Clears a form from the cache. This happens when we save as a new form.
452: */
453: public void removeForm(String id) {
454: m_formcache.remove(id);
455: }
456:
457: /**
458: * Runs unit test routines on this FormManager.
459: */
460: public void unitTest() {
461: if (FormDesignerUtils.isTest()) {
462: // com.jeta.swingbuilder.test.JETATestFactory.runTest(
463: // "test.jeta.swingbuilder.gui.formmgr.FormManagerValidator", this
464: // );
465: }
466: }
467:
468: }
|