001: /*
002: * <copyright>
003: *
004: * Copyright 2002-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.tools.csmart.core.property;
027:
028: import org.cougaar.tools.csmart.core.property.name.CompositeName;
029: import org.cougaar.tools.csmart.core.property.range.Range;
030:
031: import javax.swing.*;
032: import javax.swing.event.TreeSelectionEvent;
033: import javax.swing.event.TreeSelectionListener;
034: import javax.swing.table.AbstractTableModel;
035: import javax.swing.tree.DefaultTreeModel;
036: import javax.swing.tree.TreeNode;
037: import javax.swing.tree.TreePath;
038: import javax.swing.tree.TreeSelectionModel;
039: import java.awt.*;
040: import java.lang.reflect.Array;
041: import java.util.*;
042: import java.util.List;
043:
044: public class TestGUI extends JPanel implements PropertyListener,
045: TreeSelectionListener {
046: static final long serialVersionUID = 148379972397960896L;
047:
048: public static final int LABEL_COL = 0;
049: public static final int VALUE_COL = 1;
050: public static final int FULLNAME_COL = 2;
051: public static final int DEFAULT_COL = 3;
052: public static final int ALLOWED_COL = 4;
053: public static final int CLASS_COL = 5;
054: public static final int NCOL = 6;
055: private MyTableModel model = new MyTableModel();
056: private JTable view = new JTable(model);
057: private JScrollPane detail = new JScrollPane(view);
058: // private TreeNode root;
059: private DefaultTreeModel treeModel = null;
060: private JTree tree = new JTree();
061:
062: private JSplitPane pane = new JSplitPane(
063: JSplitPane.HORIZONTAL_SPLIT);
064:
065: private Map nodeMap = new HashMap();
066:
067: private TreeNode getTreeNodeFor(ConfigurableComponent comp) {
068: if (comp == null)
069: return null;
070: TreeNode result = (TreeNode) nodeMap.get(comp);
071: if (result == null) {
072: result = new MyTreeNode(comp);
073: nodeMap.put(comp, result);
074: }
075: return result;
076: }
077:
078: private class MyTreeNode implements TreeNode,
079: ChildConfigurationListener {
080: private ConfigurableComponent component;
081:
082: public MyTreeNode(ConfigurableComponent component) {
083: this .component = component;
084: component.addChildConfigurationListener(this );
085: }
086:
087: public void finalize() {
088: component.removeChildConfigurationListener(this );
089: }
090:
091: public void childConfigurationChanged() {
092: nodeMap.clear();
093: if (treeModel != null)
094: treeModel.nodeStructureChanged(this );
095: }
096:
097: public String toString() {
098: return component.getFullName().toString();
099: }
100:
101: public Enumeration children() {
102: return new Enumeration() {
103: int i = 0;
104:
105: public boolean hasMoreElements() {
106: return i < component.getChildCount();
107: }
108:
109: public Object nextElement() {
110: return getTreeNodeFor((ConfigurableComponent) component
111: .getChild(i++));
112: }
113: };
114: }
115:
116: public boolean getAllowsChildren() {
117: return true;
118: }
119:
120: public TreeNode getChildAt(int childIndex) {
121: return getTreeNodeFor((ConfigurableComponent) component
122: .getChild(childIndex));
123: }
124:
125: public int getChildCount() {
126: return component.getChildCount();
127: }
128:
129: public int getIndex(TreeNode node) {
130: ConfigurableComponent child = ((MyTreeNode) node).component;
131: for (int i = 0, n = getChildCount(); i < n; i++) {
132: if (component.getChild(i) == child)
133: return i;
134: }
135: return -1;
136: }
137:
138: public TreeNode getParent() {
139: return getTreeNodeFor((ConfigurableComponent) component
140: .getParent());
141: }
142:
143: public boolean isLeaf() {
144: return getChildCount() == 0;
145: }
146: }
147:
148: public void valueChanged(TreeSelectionEvent e) {
149: TreePath path = e.getNewLeadSelectionPath();
150: if (path == null)
151: return;
152: MyTreeNode node = (MyTreeNode) path.getLastPathComponent();
153: setDetailComponent(node.component);
154: }
155:
156: private interface ArrayElementRenderer {
157: String render(Object ary, int ix);
158: }
159:
160: private static ArrayElementRenderer intRenderer = new ArrayElementRenderer() {
161: public String render(Object ary, int ix) {
162: return String.valueOf(((int[]) ary)[ix]);
163: }
164: };
165: private static ArrayElementRenderer longRenderer = new ArrayElementRenderer() {
166: public String render(Object ary, int ix) {
167: return String.valueOf(((long[]) ary)[ix]);
168: }
169: };
170: private static ArrayElementRenderer shortRenderer = new ArrayElementRenderer() {
171: public String render(Object ary, int ix) {
172: return String.valueOf(((short[]) ary)[ix]);
173: }
174: };
175: private static ArrayElementRenderer byteRenderer = new ArrayElementRenderer() {
176: public String render(Object ary, int ix) {
177: return String.valueOf(((byte[]) ary)[ix]);
178: }
179: };
180: private static ArrayElementRenderer charRenderer = new ArrayElementRenderer() {
181: public String render(Object ary, int ix) {
182: return String.valueOf(((char[]) ary)[ix]);
183: }
184: };
185: private static ArrayElementRenderer doubleRenderer = new ArrayElementRenderer() {
186: public String render(Object ary, int ix) {
187: return String.valueOf(((double[]) ary)[ix]);
188: }
189: };
190: private static ArrayElementRenderer floatRenderer = new ArrayElementRenderer() {
191: public String render(Object ary, int ix) {
192: return String.valueOf(((float[]) ary)[ix]);
193: }
194: };
195: private static ArrayElementRenderer booleanRenderer = new ArrayElementRenderer() {
196: public String render(Object ary, int ix) {
197: return String.valueOf(((boolean[]) ary)[ix]);
198: }
199: };
200:
201: private static class ObjectArrayElementRenderer implements
202: ArrayElementRenderer {
203: Class cls;
204:
205: public ObjectArrayElementRenderer(Class cls) {
206: this .cls = cls;
207: }
208:
209: public String render(Object ary, int ix) {
210: return renderValue(cls, ((Object[]) ary)[ix]);
211: }
212: }
213:
214: private static String renderValue(Class cls, Object val) {
215: if (val == null)
216: return "<not set>";
217: if (cls.isArray()) {
218: Class ccls = cls.getComponentType();
219: if (ccls.isPrimitive()) {
220: if (ccls == Integer.TYPE)
221: return renderArray(val, intRenderer);
222: if (ccls == Long.TYPE)
223: return renderArray(val, longRenderer);
224: if (ccls == Short.TYPE)
225: return renderArray(val, shortRenderer);
226: if (ccls == Byte.TYPE)
227: return renderArray(val, byteRenderer);
228: if (ccls == Character.TYPE)
229: return renderArray(val, charRenderer);
230: if (ccls == Double.TYPE)
231: return renderArray(val, doubleRenderer);
232: if (ccls == Float.TYPE)
233: return renderArray(val, floatRenderer);
234: if (ccls == Boolean.TYPE)
235: return renderArray(val, booleanRenderer);
236: } else {
237: return renderArray(val, new ObjectArrayElementRenderer(
238: ccls));
239: }
240: }
241: if (cls == Range.class) {
242: return renderRange((Range) val);
243: }
244: return val.toString();
245: }
246:
247: private static String renderRange(Range range) {
248: return range.getMinimumValue() + ".." + range.getMaximumValue();
249: }
250:
251: private static String renderAllowed(Class cls, Object allowed) {
252: return renderValue(cls, allowed);
253: }
254:
255: // private static String renderObjectArray(Class cls, Object ary) {
256: // return renderArray(ary, new ObjectArrayElementRenderer(cls));
257: // }
258:
259: private static String renderArray(Object ary,
260: ArrayElementRenderer renderer) {
261: StringBuffer buf = new StringBuffer();
262: for (int i = 0, n = Array.getLength(ary); i < n; i++) {
263: if (i == 0) {
264: buf.append("{");
265: } else {
266: buf.append(",");
267: }
268: buf.append(renderer.render(ary, i));
269: }
270: buf.append("}");
271: return buf.toString();
272: }
273:
274: public TestGUI() {
275: super (new BorderLayout());
276: pane.setLeftComponent(tree);
277: pane.setRightComponent(detail);
278: tree.getSelectionModel().setSelectionMode(
279: TreeSelectionModel.SINGLE_TREE_SELECTION);
280: tree.addTreeSelectionListener(this );
281: JPanel buttons = new JPanel();
282: JButton[] testButtons = getTestButtons();
283: for (int i = 0; i < testButtons.length; i++) {
284: buttons.add(testButtons[i]);
285: }
286: add(pane);
287: add(buttons, BorderLayout.SOUTH);
288: }
289:
290: protected JButton[] getTestButtons() {
291: return new JButton[0];
292: }
293:
294: public JFrame displayInFrame(ConfigurableComponent c) {
295: setConfigurableComponent(c);
296: JFrame frame = new JFrame();
297: frame.setDefaultCloseOperation(3);
298: frame.getContentPane().add(this );
299: frame.pack();
300: frame.show();
301: return frame;
302: }
303:
304: public void setConfigurableComponent(ConfigurableComponent c) {
305: TreeNode rootNode = getTreeNodeFor(c);
306: if (treeModel == null) {
307: treeModel = new DefaultTreeModel(rootNode);
308: tree.setModel(treeModel);
309: } else {
310: treeModel.setRoot(rootNode);
311: }
312: setDetailComponent(c);
313: }
314:
315: private void setDetailComponent(ConfigurableComponent c) {
316: List rows = new ArrayList();
317: view.removeAll();
318: model.clear();
319: for (Iterator i = c.getPropertyNames(); i.hasNext();) {
320: CompositeName name = (CompositeName) i.next();
321: Property prop = c.getProperty(name);
322: if (prop == null) {
323: System.err.println("Property " + name
324: + " not found in " + c.getFullName());
325: continue;
326: }
327: prop.addPropertyListener(this );
328: rows.add(prop);
329: }
330: model.addAll(rows);
331: }
332:
333: public void propertyValueChanged(PropertyEvent e) {
334: propertyChanged(e);
335: }
336:
337: public void propertyOtherChanged(PropertyEvent e) {
338: propertyChanged(e);
339: }
340:
341: public void propertyChanged(PropertyEvent e) {
342: Property prop = e.getProperty();
343: model.updateRow(prop);
344: }
345:
346: private static Comparator propComparator = new Comparator() {
347: public int compare(Object o1, Object o2) {
348: Property p1 = (Property) o1;
349: Property p2 = (Property) o2;
350: return p1.getName().compareTo(p2.getName());
351: }
352: };
353:
354: private static class MyTableModel extends AbstractTableModel {
355: private SortedSet rowSet = new TreeSet(propComparator);
356: private List rowList = new ArrayList();
357:
358: public void clear() {
359: int sz = rowSet.size();
360: rowSet.clear();
361: rowList.clear();
362: if (sz > 0)
363: fireTableRowsDeleted(0, sz - 1);
364: }
365:
366: public void add(Property prop) {
367: int insertionRow = rowSet.headSet(prop).size();
368: rowSet.add(prop);
369: rowList.clear();
370: fireTableRowsInserted(insertionRow, insertionRow);
371: }
372:
373: public void addAll(Collection c) {
374: rowSet.addAll(c);
375: rowList.clear();
376: fireTableDataChanged();
377: }
378:
379: public void updateRow(Property prop) {
380: int row = rowSet.headSet(prop).size();
381: fireTableRowsUpdated(row, row);
382: }
383:
384: public int getColumnCount() {
385: return NCOL;
386: }
387:
388: public String getColumnName(int col) {
389: switch (col) {
390: case LABEL_COL:
391: return "Label";
392: case VALUE_COL:
393: return "Value";
394: case FULLNAME_COL:
395: return "Full Name";
396: case DEFAULT_COL:
397: return "Default";
398: case ALLOWED_COL:
399: return "Allowed";
400: case CLASS_COL:
401: return "Class";
402: }
403: return null;
404: }
405:
406: public Class getColumnClass(int col) {
407: return String.class;
408: }
409:
410: public int getRowCount() {
411: return rowSet.size();
412: }
413:
414: public Object getValueAt(int row, int col) {
415: if (rowList.size() == 0)
416: rowList.addAll(rowSet);
417: Property prop = (Property) rowList.get(row);
418: Class cls = prop.getPropertyClass();
419: if (cls == null) {
420: System.err.println("getPropertyClass is null for "
421: + prop.getName());
422: Object value = prop.getValue();
423: if (value == null) {
424: cls = Object.class;
425: } else {
426: cls = value.getClass();
427: }
428: }
429: switch (col) {
430: case LABEL_COL:
431: return prop.getLabel();
432: case VALUE_COL:
433: return renderValue(cls, prop.getValue());
434: case FULLNAME_COL:
435: return prop.getName();
436: case DEFAULT_COL:
437: return renderValue(cls, prop.getDefaultValue());
438: case ALLOWED_COL:
439: return renderAllowed(cls, prop.getAllowedValues());
440: case CLASS_COL:
441: if (cls.isArray())
442: return "Array of "
443: + cls.getComponentType().getName();
444: else
445: return cls.getName();
446: }
447: return null;
448: }
449: }
450: }
|