001: /*
002: * Copyright 2001-2006 C:1 Financial Services GmbH
003: *
004: * This software is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License Version 2.1, as published by the Free Software Foundation.
007: *
008: * This software is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011: * Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public
014: * License along with this library; if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
016: */
017:
018: package de.finix.contelligent.client.gui.composed;
019:
020: import java.awt.BorderLayout;
021: import java.awt.Container;
022: import java.awt.event.FocusAdapter;
023: import java.awt.event.FocusEvent;
024: import java.util.ArrayList;
025: import java.util.HashMap;
026: import java.util.Iterator;
027: import java.util.List;
028: import java.util.Map;
029: import java.util.Vector;
030: import java.util.logging.Level;
031: import java.util.logging.Logger;
032:
033: import javax.swing.JComponent;
034: import javax.swing.JPanel;
035: import javax.swing.JScrollPane;
036: import javax.swing.border.EmptyBorder;
037:
038: import com.jgoodies.forms.extras.DefaultFormBuilder;
039: import com.jgoodies.forms.layout.FormLayout;
040:
041: import de.finix.contelligent.client.base.ComponentFactory;
042: import de.finix.contelligent.client.base.ComponentNotFoundException;
043: import de.finix.contelligent.client.base.ContelligentComponent;
044: import de.finix.contelligent.client.base.Description;
045: import de.finix.contelligent.client.base.Type;
046: import de.finix.contelligent.client.base.category.ContelligentCategory;
047: import de.finix.contelligent.client.base.category.ContelligentCategoryManager;
048: import de.finix.contelligent.client.event.ContelligentEvent;
049: import de.finix.contelligent.client.gui.AbstractComponentEditor;
050: import de.finix.contelligent.client.gui.ComponentEditor;
051: import de.finix.contelligent.client.gui.ComponentRenderer;
052: import de.finix.contelligent.client.gui.GUI;
053: import de.finix.contelligent.client.gui.GUIFactory;
054: import de.finix.contelligent.client.gui.GUIRegistry;
055: import de.finix.contelligent.client.gui.UnsupportedGUIException;
056: import de.finix.contelligent.client.i18n.Resources;
057: import de.finix.contelligent.client.util.JTextUtil;
058: import de.finix.contelligent.client.util.TextUtil;
059:
060: public class FormEditor extends AbstractComponentEditor {
061:
062: private static Logger logger = Logger.getLogger(FormEditor.class
063: .getName());
064:
065: private JScrollPane scrollPane;
066:
067: private JPanel formPanel;
068:
069: private String subcomponentPath;
070:
071: private List<ComponentRenderer> nestedEditors;
072:
073: private List<String> elementOrder = new ArrayList<String>();
074:
075: private Map<String, FormGUIConfiguration.ElementConfiguration> elementConfiguration = new HashMap<String, FormGUIConfiguration.ElementConfiguration>();
076:
077: private int mode = FormGUIConfiguration.SHOW_UNCONFIGURED_ELEMENTS;
078:
079: public void init() {
080: scrollPane = new JScrollPane();
081: scrollPane
082: .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
083: scrollPane.setBorder(null);
084: scrollPane.getViewport().setOpaque(false);
085: scrollPane.setOpaque(false);
086: add(scrollPane, BorderLayout.CENTER);
087: compose();
088: update();
089: }
090:
091: public void setConfiguration(String configuration) {
092: FormGUIConfiguration guiConfiguration = new FormGUIConfiguration(
093: configuration);
094: mode = guiConfiguration.getMode();
095: elementOrder = guiConfiguration.getElementOrder();
096: elementConfiguration = new HashMap<String, FormGUIConfiguration.ElementConfiguration>();
097: for (Iterator i = guiConfiguration.getElements().iterator(); i
098: .hasNext();) {
099: FormGUIConfiguration.ElementConfiguration element = (FormGUIConfiguration.ElementConfiguration) i
100: .next();
101: elementConfiguration.put(element.getPath(), element);
102: }
103: }
104:
105: private synchronized void compose() {
106: try {
107: ContelligentComponent rootComponent = null;
108:
109: if (subcomponentPath == null) {
110: rootComponent = getComponent();
111: } else {
112: rootComponent = ComponentFactory.getInstance()
113: .getComponent(
114: getComponent().getPath() + "/"
115: + subcomponentPath);
116: }
117:
118: FormLayout formLayout = new FormLayout("pref:grow", "");
119: DefaultFormBuilder formBuilder = new DefaultFormBuilder(
120: formLayout);
121: formBuilder.setDefaultDialogBorder();
122:
123: nestedEditors = new Vector<ComponentRenderer>();
124:
125: // sort subcomponents by sort-constraints from configuration if
126: // available
127: if (elementOrder.size() == 0) {
128: // if no order is given, layout subcomponents in their natural
129: // order
130: elementOrder = rootComponent.getSubcomponents();
131: } else if (elementOrder.size() < rootComponent
132: .getSubcomponents().size()) {
133: // if order contains less elements than subcomponents, add the
134: // missing components at the end of the ordered list
135: for (Iterator iterator = rootComponent
136: .getSubcomponents().iterator(); iterator
137: .hasNext();) {
138: String subcomponentName = (String) iterator.next();
139: if (!elementOrder.contains(subcomponentName)) {
140: elementOrder.add(subcomponentName);
141: }
142: }
143: }
144: for (Iterator iterator = elementOrder.iterator(); iterator
145: .hasNext();) {
146: String subcomponentName = (String) iterator.next();
147: try {
148: ContelligentComponent subcomponent = ComponentFactory
149: .getInstance().getComponent(
150: rootComponent.getPath() + "/"
151: + subcomponentName);
152: // check for element configuration
153: String title = null;
154: String description = null;
155: boolean showElement = true;
156: String guiImpl = null, guiConfiguration = null;
157: if (elementConfiguration
158: .containsKey(subcomponentName)) {
159: FormGUIConfiguration.ElementConfiguration element = (FormGUIConfiguration.ElementConfiguration) elementConfiguration
160: .get(subcomponentName);
161: if (element.isHidden()) {
162: showElement = false;
163: } else {
164: Description elementDescription = element
165: .getDescription(Resources
166: .getLocale());
167: title = elementDescription.getTitle();
168: description = elementDescription.getText();
169: try {
170: guiImpl = GUIRegistry.getInstance()
171: .getImpl(element.getGui());
172: } catch (NullPointerException npe) {
173: // This happens if we already had an
174: // implementation
175: guiImpl = element.getGui();
176: }
177: guiConfiguration = element
178: .getGuiConfiguration();
179: }
180: } else {
181: if (mode == FormGUIConfiguration.HIDE_UNCONFIGURED_ELEMENTS) {
182: showElement = false;
183: } else {
184: title = TextUtil.toUpper(subcomponentName);
185: Type type = subcomponent.getType();
186: Description typeDescription = type
187: .getDescription(Resources
188: .getLocale());
189: if (typeDescription != null) {
190: title = title + " ("
191: + typeDescription.getTitle()
192: + ")";
193: description = typeDescription.getText();
194: } else {
195: description = "";
196: }
197: }
198: }
199: if (showElement) {
200: GUI gui;
201: if (guiImpl == null) {
202: GUI[] guis = GUIFactory.getInstance()
203: .getGUI(subcomponent, getView());
204: gui = guis[0];
205: } else {
206: gui = GUIFactory.getInstance()
207: .createGUIInstance(guiImpl);
208: gui.setComponent(subcomponent);
209: gui.setView(getView());
210: gui.setConfiguration(guiConfiguration);
211: gui.init();
212: }
213: if (gui.isCategorySensitive()) {
214: gui.setResourceCategoryMap(getGUI()
215: .getResourceCategoryMap());
216: }
217: if (!gui.isResourceSupported()) {
218: ContelligentCategory category = ContelligentCategoryManager
219: .getInstance()
220: .getCategoryByName(
221: gui
222: .getUnsupportedCategory());
223: JScrollPane unsupported = JTextUtil
224: .createErrorMessageArea(Resources
225: .getLocalString(
226: "resource_not_supported",
227: new String[] {
228: category
229: .getDescription(
230: Resources
231: .getLocale())
232: .getTitle(),
233: gui
234: .getUnsupportedCategoryValue() }));
235: formBuilder.append(unsupported);
236: formBuilder.nextLine();
237: } else {
238: try {
239: ComponentRenderer tableRenderer = null;
240: if (isEditable()) {
241: tableRenderer = gui
242: .getEditor(GUI.TABLE);
243: } else {
244: tableRenderer = gui
245: .getRenderer(GUI.TABLE);
246: }
247: nestedEditors.add(tableRenderer);
248: ((java.awt.Component) tableRenderer)
249: .setFocusable(false);
250: if (tableRenderer instanceof FormEditor) {
251: // remove scroll pane of nested form editor
252: ((JComponent) ((JScrollPane) ((Container) tableRenderer)
253: .getComponent(0))
254: .getViewport().getView())
255: .setBorder(new EmptyBorder(
256: 0, 5, 0, 0));
257: }
258: JComponent sep = formBuilder
259: .appendSeparator(title);
260: sep.setOpaque(false);
261: formBuilder.nextLine();
262: if (description.length() > 0) {
263: formBuilder.append(description);
264: formBuilder.nextLine();
265: }
266: if (tableRenderer.isScalable()) {
267: formBuilder
268: .appendRow("fill:pref:grow(1.0)");
269: }
270: formBuilder
271: .append((java.awt.Component) tableRenderer);
272: } catch (UnsupportedGUIException uge) {
273: // skip not renderable component...
274: }
275: }
276: }
277: } catch (ComponentNotFoundException cnfe) {
278: logger.log(Level.WARNING,
279: "Form editor could not find requested subcomponent '"
280: + subcomponentName + "'");
281: }
282: }
283: formPanel = formBuilder.getPanel();
284: formPanel.setOpaque(false);
285: formPanel.setFocusCycleRoot(true);
286: formPanel.addFocusListener(new FocusAdapter() {
287: public void focusGained(FocusEvent e) {
288: getView().setActions(getActions());
289: }
290: });
291: scrollPane.setViewportView(formPanel);
292: } catch (ComponentNotFoundException cnfe) {
293: logger.log(Level.SEVERE, "Could not compose", cnfe);
294: }
295: }
296:
297: public void update() {
298: for (Iterator i = nestedEditors.iterator(); i.hasNext();) {
299: ComponentRenderer nestedEditor = (ComponentRenderer) i
300: .next();
301: nestedEditor.update();
302: }
303: formPanel.validate();
304: formPanel.repaint();
305: }
306:
307: public void setSubcomponentPath(String subcomponentPath) {
308: this .subcomponentPath = subcomponentPath;
309: }
310:
311: public void setEditable(boolean editable) {
312: super .setEditable(editable);
313: if (formPanel != null) {
314: compose();
315: update();
316: }
317: }
318:
319: public void rollback() {
320: // rollback subcomponents
321: for (Iterator i = nestedEditors.iterator(); i.hasNext();) {
322: ComponentEditor nestedEditor = (ComponentEditor) i.next();
323: nestedEditor.rollback();
324: }
325: }
326:
327: public void commit() {
328: // commit subcomponents
329: for (Iterator i = nestedEditors.iterator(); i.hasNext();) {
330: ComponentEditor nestedEditor = (ComponentEditor) i.next();
331: nestedEditor.commit();
332: }
333: setEditable(false);
334: }
335:
336: protected void reloadComponent() {
337: // FIXME ensure we always have the valid component: always reloads
338: // component and all
339: // subcomponents. Can be quite slow when using mass containers! (bug
340: // #250)
341: try {
342: ComponentFactory.getInstance().reload(getComponent());
343: } catch (ComponentNotFoundException cnfe) {
344: logger.log(Level.SEVERE, "Could not update component!",
345: cnfe);
346: }
347: }
348:
349: protected void updateComponent() {
350: }
351:
352: protected void componentChanged(ContelligentEvent event) {
353: }
354:
355: protected void childComponentAdded(ContelligentEvent event) {
356: reloadComponent(); // XXX see reloadComponent(), fixed bug #263
357: compose();
358: }
359:
360: protected void childComponentRemoved(ContelligentEvent event) {
361: reloadComponent(); // XXX see reloadComponent(), fixed bug #263
362: compose();
363: }
364:
365: protected void childComponentChanged(ContelligentEvent event) {
366: }
367:
368: protected void descendentComponentChanged(ContelligentEvent event) {
369: }
370:
371: public boolean isScalable() {
372: return true;
373: }
374: }
|