001: package org.osbl.client.wings.form;
002:
003: import org.osbl.client.wings.shell.Client;
004: import org.osbl.client.wings.shell.Environment;
005: import org.osbl.client.wings.XOptionPane;
006: import org.osbl.client.wings.XButton;
007: import org.osbl.client.action.*;
008: import org.wings.*;
009:
010: import javax.swing.*;
011: import javax.swing.tree.TreePath;
012: import java.awt.event.ActionEvent;
013: import java.awt.event.ActionListener;
014: import java.awt.*;
015: import java.lang.reflect.Constructor;
016: import java.util.*;
017: import java.util.List;
018:
019: /**
020: * Created by IntelliJ IDEA.
021: * User: hengels
022: * Date: Feb 13, 2007
023: * Time: 11:55:23 AM
024: * To change this template use File | Settings | File Templates.
025: */
026: public abstract class GenericObjectTreeEditor implements ObjectEditor,
027: ObjectContextAware {
028: protected DelegateEnvironment environment = new DelegateEnvironment(
029: true);
030: protected DelegateEnvironment nestedEnvironment = new DelegateEnvironment(
031: true);
032: protected ObjectList objectList;
033: protected NodeForm objectForm;
034: private SPanel panel;
035: private GridBagConstraints constraints;
036:
037: protected Object object;
038:
039: private SaveAction saveAction = new SaveAction(getType().getName());
040: private DeleteAction deleteAction = new DeleteAction(getType()
041: .getName());
042: private GenericObjectTreeNode transientNode;
043:
044: private List<AddChildAction> addChildActions = new ArrayList<AddChildAction>();
045: private GenericObjectTreeNode node;
046: private ObjectContext context;
047:
048: protected GenericObjectTreeEditor() {
049: initializeEditor();
050: environment.setNestedEnvironment(nestedEnvironment);
051: environment.setActive(true);
052: }
053:
054: public ObjectContext getContext() {
055: if (context == null) {
056: System.out.println("new context: " + context);
057: context = new ObjectContext();
058: }
059: return context;
060: }
061:
062: public void setContext(ObjectContext context) {
063: this .context = context;
064: }
065:
066: public Environment getEnvironment() {
067: if (panel == null) {
068: panel = new SPanel(new SGridBagLayout());
069: panel.setPreferredSize(SDimension.FULLAREA);
070:
071: constraints = new GridBagConstraints();
072: constraints.weighty = 1.0;
073: constraints.weightx = .33;
074: panel.add(getList().getComponent(), constraints);
075: constraints.weightx = .67;
076: constraints.insets = new Insets(4, 4, 4, 4);
077: panel.add(new SPanel(), constraints);
078: nestedEnvironment.setContentPane(panel);
079: nestedEnvironment.setTitle(getType().getName()
080: + ".editor.title");
081: initializeConntrols();
082: }
083: return environment;
084: }
085:
086: public void showList() {
087: }
088:
089: public void showForm() {
090: NodeForm nodeForm = ((NodeForm) getForm());
091: nodeForm.setNode(this , getNode());
092: panel.remove(1);
093: panel.add(nodeForm.getComponent(), constraints);
094:
095: nodeForm.setObject(getNode());
096: nodeForm.getValidationStatus()
097: .setEnvironment(nestedEnvironment);
098: nodeForm.getEnvironment().setActive(true);
099: }
100:
101: /**
102: * Initializations like installing global object actions go here.
103: * Override this method for your own initializations.
104: */
105: protected void initializeEditor() {
106: }
107:
108: public ObjectForm getForm() {
109: if (objectForm == null) {
110: objectForm = initializeForm();
111: if (objectForm instanceof ObjectContextAware)
112: ((ObjectContextAware) objectForm)
113: .setContext(getContext());
114: objectForm.getEnvironment().setDelegate(environment);
115: }
116: return objectForm;
117: }
118:
119: protected abstract NodeForm initializeForm();
120:
121: public ObjectList getList() {
122: if (objectList == null) {
123: objectList = initializeList();
124: if (objectList instanceof ObjectContextAware)
125: ((ObjectContextAware) objectList)
126: .setContext(getContext());
127: objectList.getEnvironment().setDelegate(environment);
128:
129: objectList.setLinkAction("key", new AbstractObjectAction() {
130: public void actionPerformed(
131: final ObjectActionEvent event) {
132: final GenericObjectTreeNode node = (GenericObjectTreeNode) event
133: .getTargets()[0];
134: if (node == getTransientNode())
135: return;
136:
137: if (getTransientNode() != null
138: || (objectForm != null && objectForm
139: .hasChanges())) {
140: String name = Client.getInstance()
141: .getResourceProvider().getMessage(
142: getType().getName());
143: String message = unsavedchangesMessage(name);
144: XOptionPane.showConfirmDialog(null, message,
145: name, new ActionListener() {
146: public void actionPerformed(
147: ActionEvent actionEvent) {
148: if (XOptionPane.YES_ACTION == actionEvent
149: .getActionCommand()) {
150: revert(getNode());
151: setNode(node);
152: }
153: }
154: });
155: } else
156: setNode(node);
157: }
158: });
159: }
160: return objectList;
161: }
162:
163: private void revert(GenericObjectTreeNode node) {
164: if (node == getTransientNode())
165: getTransientNode().removeFromParent();
166: else {
167: //node.setObject(node.loadObject());
168: }
169: }
170:
171: private String unsavedchangesMessage(String name) {
172: String message = Client.getInstance().getResourceProvider()
173: .getMessage("businessobject.messages.unsavedChanges",
174: name);
175: NodeForm nodeForm = objectForm;
176: String changes = nodeForm.getChangeStatus()
177: .composeMessageDetail();
178: message = message + "\n\n" + changes;
179: return message;
180: }
181:
182: protected void initializeConntrols() {
183: nestedEnvironment.addControl(new XButton(saveAction));
184: nestedEnvironment.addControl(new XButton(deleteAction));
185: }
186:
187: /**
188: * Create and initialize the list component.
189: * @return the list component
190: */
191: protected abstract GenericObjectTreeList initializeList();
192:
193: public GenericObjectTreeNode getNode() {
194: return node;
195: }
196:
197: public void setNode(GenericObjectTreeNode node) {
198: this .node = node;
199: objectList.setCurrent(node);
200: showForm();
201: setTransientNode(null);
202: }
203:
204: public Object getObject() {
205: return node != null ? node.getObject() : null;
206: }
207:
208: public void setObject(Object object) {
209: List objectPath = loadParentPath(object);
210: GenericObjectTreeModel genericObjectTreeModel = ((GenericObjectTreeList) getList())
211: .getModel();
212: GenericObjectTreeNode objectTreeNode = genericObjectTreeModel
213: .getRoot();
214:
215: List<GenericObjectTreeNode> nodePath = new ArrayList<GenericObjectTreeNode>(
216: objectPath.size());
217: nodePath.add(objectTreeNode);
218:
219: List path = search(objectPath, objectTreeNode);
220: System.out.println("path = " + path);
221: TreePath treePath = new TreePath(path.toArray());
222: ((GenericObjectTreeList) getList()).setSelectionPath(treePath);
223: setNode((GenericObjectTreeNode) treePath.getLastPathComponent());
224: }
225:
226: private List search(List objectPath, GenericObjectTreeNode node) {
227: List path = new ArrayList();
228: path.add(node);
229:
230: if (objectPath.size() == 0) {
231: System.out.println("reached leaf " + node.getObject());
232: return path;
233: }
234:
235: Object object = objectPath.remove(0);
236: System.out.println(node.getObject() + ": " + object);
237:
238: Enumeration<GenericObjectTreeNode> enumeration = node
239: .children();
240: while (enumeration.hasMoreElements()) {
241: GenericObjectTreeNode childNode = enumeration.nextElement();
242: if (object.equals(childNode.getObject())) {
243: List childPath = search(objectPath, childNode);
244: path.addAll(childPath);
245: return path;
246: }
247: }
248:
249: System.out.println("broad search " + object);
250: objectPath.add(0, object);
251: enumeration = node.children();
252: while (enumeration.hasMoreElements()) {
253: GenericObjectTreeNode childNode = enumeration.nextElement();
254: List childPath = search(objectPath, childNode);
255: if (childPath != null) {
256: path.addAll(childPath);
257: return path;
258: }
259: }
260:
261: System.out.println("give up on " + object);
262: return null;
263: }
264:
265: protected abstract List loadParentPath(Object object);
266:
267: public void setSelectionMode(int selectionMode) {
268: getList().setSelectionMode(selectionMode);
269: }
270:
271: public void setSelectedObject(Object object) {
272: getList().setSelectedObject(object);
273: }
274:
275: public Object getSelectedObject() {
276: return getList().getSelectedObject();
277: }
278:
279: public List getSelectedObjects() {
280: return getList().getSelectedObjects();
281: }
282:
283: public void setSelectedObjects(List objects) {
284: getList().setSelectedObjects(objects);
285: }
286:
287: public abstract Class getType();
288:
289: public abstract void saveObject(Object object);
290:
291: public abstract void deleteObject(Object object);
292:
293: public abstract void revertObject(Object object);
294:
295: protected GenericObjectTreeNode getTransientNode() {
296: return transientNode;
297: }
298:
299: protected void setTransientNode(GenericObjectTreeNode transientNode) {
300: if (this .transientNode != null)
301: this .transientNode.setTransient(false);
302:
303: this .transientNode = transientNode;
304:
305: if (this .transientNode != null)
306: this .transientNode.setTransient(true);
307:
308: boolean enabled = transientNode == null;
309: for (AddChildAction addChildAction : addChildActions)
310: addChildAction.setEnabled(enabled);
311: }
312:
313: public Action getAddChildAction(Class childType) {
314: AddChildAction addChildAction = new AddChildAction(childType);
315: addChildActions.add(addChildAction);
316: return addChildAction;
317: }
318:
319: protected class AddChildAction extends AbstractAction {
320: private Class childType;
321:
322: public AddChildAction(Class childType) {
323: this .childType = childType;
324: putValue(Action.NAME, Client.getInstance()
325: .getResourceProvider().getMessage(".buttons.add")
326: + ": "
327: + Client.getInstance().getResourceProvider()
328: .getMessage(childType.getName()));
329: putValue(Action.ACTION_COMMAND_KEY, childType.getName()
330: + "[w]");
331: }
332:
333: public void actionPerformed(ActionEvent event) {
334: GenericObjectTreeNode genericObjectTreeNode = getNode();
335: try {
336: Class<? extends GenericObjectTreeNode> childNodeType = genericObjectTreeNode
337: .getModel().nodeTypeFor(childType);
338: Constructor<? extends GenericObjectTreeNode> constructor = childNodeType
339: .getConstructor();
340: GenericObjectTreeNode childNode = constructor
341: .newInstance();
342: genericObjectTreeNode.insert(childNode, -1);
343:
344: setNode(childNode);
345: setTransientNode(childNode);
346: } catch (Exception e) {
347: throw new RuntimeException(e);
348: }
349: }
350: }
351:
352: protected class SaveAction extends AbstractAction {
353: public SaveAction(String base) {
354: putValue(Action.ACTION_COMMAND_KEY, base + ".buttons.save");
355: putValue(AuthorizedAction.PERMISSION_KEY, base + "[w]");
356: }
357:
358: public void actionPerformed(ActionEvent event) {
359: if (objectForm.hasValidationIssues())
360: return;
361:
362: GenericObjectTreeNode node = (GenericObjectTreeNode) objectForm
363: .getObject();
364: try {
365: saveObject(node);
366: String name = Client.getInstance()
367: .getResourceProvider().getMessage(
368: getType().getName());
369: String message = Client.getInstance()
370: .getResourceProvider().getMessage(
371: "businessobject.messages.saved", name);
372: nestedEnvironment.setStatusMessage(new Client.Message(
373: Client.Message.TYPE_INFO, message));
374: objectForm.setObject(node);
375: } catch (Exception e) {
376: nestedEnvironment.setStatusMessage(new Client.Message(
377: Client.Message.TYPE_ERROR, e.getMessage()));
378: e.printStackTrace();
379: }
380:
381: node.setObject(node.loadObject());
382: node.putClientProperty("transient", Boolean.FALSE);
383: GenericObjectTreeNode parent = node.getParent();
384: parent.remove(node);
385: parent.insert(node, -1);
386: setNode(node);
387: setTransientNode(null);
388: }
389: }
390:
391: private class DeleteAction extends AbstractAction {
392: public DeleteAction(String base) {
393: putValue(Action.ACTION_COMMAND_KEY, base
394: + ".buttons.delete");
395: putValue(AuthorizedAction.PERMISSION_KEY, base + "[w]");
396: }
397:
398: public void actionPerformed(ActionEvent event) {
399: if (getTransientNode() != null
400: || (objectForm != null && objectForm.hasChanges())) {
401: String name = Client.getInstance()
402: .getResourceProvider().getMessage(
403: getType().getName());
404: String message = unsavedchangesMessage(name);
405: XOptionPane.showConfirmDialog(null, message, name,
406: new ActionListener() {
407: public void actionPerformed(
408: ActionEvent actionEvent) {
409: if (XOptionPane.YES_ACTION == actionEvent
410: .getActionCommand()) {
411: GenericObjectTreeNode treeNode = getNode();
412: GenericObjectTreeNode parentTreeNode = treeNode
413: .getParent();
414: revert(treeNode);
415: setNode(parentTreeNode);
416: }
417: }
418: });
419: } else {
420: deleteObject(objectForm.getObject());
421: disconnectFromParentNode();
422: }
423: }
424:
425: private void disconnectFromParentNode() {
426: GenericObjectTreeNode genericObjectTreeNode = (GenericObjectTreeNode) objectForm
427: .getObject();
428: GenericObjectTreeNode parentTreeNode = genericObjectTreeNode
429: .getParent();
430: genericObjectTreeNode.removeFromParent();
431: setNode(parentTreeNode);
432: }
433: }
434: }
|