/*
* Encog(tm) Workbench v3.4
* http://www.heatonresearch.com/encog/
* https://github.com/encog/encog-java-workbench
*
* Copyright 2008-2016 Heaton Research, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* For more information on Heaton Research copyrights, licenses
* and trademarks visit:
* http://www.heatonresearch.com/copyright
*/
package org.encog.workbench.editor;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import org.encog.workbench.WorkBenchError;
import org.encog.workbench.frames.EncogCommonFrame;
import org.encog.workbench.util.MouseUtil;
public class ObjectEditorFrame extends EncogCommonFrame implements
TreeSelectionListener {
private Object data;
private JTable table;
private JTree tree;
private JScrollPane scrollTree;
private JScrollPane scrollTable;
private DefaultTreeModel treeModel;
private DefaultMutableTreeNode root;
private PropertyCollection properties;
private JPopupMenu popup;
private JMenuItem popupAdd;
private JMenuItem popupDelete;
public ObjectEditorFrame(Object data) {
setSize(400, 400);
setTitle("Editing " + data.getClass().getSimpleName());
this.data = data;
this.properties = new PropertyCollection(data);
Container content = this.getContentPane();
content.setLayout(new BorderLayout());
this.root = new DefaultMutableTreeNode(data);
this.treeModel = new DefaultTreeModel(this.root);
this.tree = new JTree(this.treeModel);
this.scrollTable = new JScrollPane();
this.scrollTree = new JScrollPane(this.tree);
if( this.containsCollections(data) )
{
content.add(this.scrollTree, BorderLayout.WEST);
content.add(this.scrollTable, BorderLayout.EAST);
}
else
{
content.add(this.scrollTable,BorderLayout.CENTER);
}
this.tree.addTreeSelectionListener(this);
this.tree.addMouseListener(this);
this.removeMouseListener(this);
this.popup = new JPopupMenu();
this.popupAdd = this.addItem(this.popup, "Add", 'a');
this.popupDelete = this.addItem(this.popup, "Delete", 'd');
resetTable();
generateTree();
}
private boolean containsCollections(Object obj) {
try {
Field[] fields = obj.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
Object fieldObj = field.get(obj);
if( fieldObj instanceof Collection )
return true;
}
} catch (IllegalArgumentException e) {
throw new WorkBenchError(e);
} catch (IllegalAccessException e) {
throw new WorkBenchError(e);
} finally {
}
return false;
}
private void resetTable() {
this.table = new JTable(this.properties.getModel());
this.table.getColumnModel().getColumn(1).setCellEditor(
new EditorCellEditor());
this.scrollTable.setViewportView(this.table);
}
public void windowOpened(WindowEvent e) {
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == this.popupAdd) {
performAdd();
} else if (e.getSource() == this.popupDelete) {
performDelete();
}
}
public void performDelete() {
try {
TreePath path = this.tree.getSelectionPath();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
.getLastPathComponent();
Collection collection = null;
Object object = null;
if (node.getUserObject() instanceof String) {
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node
.getParent();
String fieldName = (String) node.getUserObject();
Field field = parent.getUserObject().getClass()
.getDeclaredField(fieldName);
field.setAccessible(true);
collection = (Collection) field.get(parent.getUserObject());
object = null;
} else {
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node
.getParent();
DefaultMutableTreeNode grandParent = (DefaultMutableTreeNode) parent
.getParent();
String fieldName = (String) parent.getUserObject();
Field field = grandParent.getUserObject().getClass()
.getDeclaredField(fieldName);
field.setAccessible(true);
collection = (Collection) field
.get(grandParent.getUserObject());
object = node.getUserObject();
}
if (object == null)
collection.clear();
else
collection.remove(object);
generateTree();
} catch (SecurityException e) {
throw new WorkBenchError(e);
} catch (IllegalArgumentException e) {
throw new WorkBenchError(e);
} catch (NoSuchFieldException e) {
throw new WorkBenchError(e);
} catch (IllegalAccessException e) {
throw new WorkBenchError(e);
} finally {
}
}
private void performAdd() {
try {
TreePath path = this.tree.getSelectionPath();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
.getLastPathComponent();
if (!(node.getUserObject() instanceof String)) {
node = (DefaultMutableTreeNode) node.getParent();
}
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node
.getParent();
Object obj = parent.getUserObject();
String fieldName = node.getUserObject().toString();
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
Object fieldObject = field.get(obj);
if (fieldObject instanceof Collection) {
ParameterizedType gtype = (ParameterizedType) field
.getGenericType();
java.lang.reflect.Type[] types = gtype.getActualTypeArguments();
Object item = ((Class) types[0]).newInstance();
((Collection) fieldObject).add(item);
generateTree();
}
} catch (SecurityException e) {
throw new WorkBenchError(e);
} catch (NoSuchFieldException e) {
throw new WorkBenchError(e);
} catch (IllegalAccessException e) {
throw new WorkBenchError(e);
} catch (InstantiationException e) {
throw new WorkBenchError(e);
}
}
protected void generateTree() {
try {
this.root.removeAllChildren();
Field fields[] = this.data.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
Class c = field.getClass();
Object value = field.get(this.data);
if (value instanceof Collection) {
DefaultMutableTreeNode n = new DefaultMutableTreeNode(field
.getName());
this.root.add(n);
generateTreeCollection(n, (Collection) value);
}
}
treeModel.reload();
tree.invalidate();
TreePath path = new TreePath(this.root);
tree.setSelectionPath(path);
pack();
} catch (IllegalAccessException e) {
throw new WorkBenchError(e);
}
}
private void generateTreeCollection(DefaultMutableTreeNode parentNode,
Collection parentObject) {
for (Object obj : parentObject) {
DefaultMutableTreeNode n = new DefaultMutableTreeNode(obj);
parentNode.add(n);
}
}
public void valueChanged(TreeSelectionEvent e) {
TreePath path = this.tree.getSelectionPath();
if (path != null) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) path
.getLastPathComponent();
Object obj = n.getUserObject();
// clear the selection pointer
resetTable();
// if its a String, then it is just a label
if (obj instanceof String)
this.properties.setData(null);
else
this.properties.setData(obj);
}
}
public void setData(Object data) {
this.data = data;
}
public void mouseClicked(final MouseEvent e) {
if (MouseUtil.isRightClick(e)) {
TreePath path = this.tree.getPathForLocation(e.getX(), e.getY());
Object obj = path.getLastPathComponent();
TreeNode node = (DefaultMutableTreeNode) obj;
TreeNode parent = node.getParent();
if (parent != null) {
this.tree.setSelectionPath(path);
this.popup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
}