/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* KnowledgeFlowApp.java
* Copyright (C) 2005-2012 University of Waikato, Hamilton, New Zealand
*
*/
package weka.gui.beans;
import weka.core.Attribute;
import weka.core.Copyright;
import weka.core.Environment;
import weka.core.EnvironmentHandler;
import weka.core.Instances;
import weka.core.Memory;
import weka.core.PluginManager;
import weka.core.SerializedObject;
import weka.core.Utils;
import weka.core.WekaEnumeration;
import weka.core.WekaPackageClassLoaderManager;
import weka.core.WekaPackageManager;
import weka.core.converters.FileSourcedConverter;
import weka.core.xml.KOML;
import weka.core.xml.XStream;
import weka.gui.AttributeSelectionPanel;
import weka.gui.ExtensionFileFilter;
import weka.gui.GenericObjectEditor;
import weka.gui.GenericPropertiesCreator;
import weka.gui.HierarchyPropertyParser;
import weka.gui.LookAndFeel;
import weka.gui.beans.xml.XMLBeans;
import weka.gui.visualize.PrintablePanel;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.Point;
import java.awt.PopupMenu;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.beans.BeanInfo;
import java.beans.Customizer;
import java.beans.EventSetDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.beancontext.BeanContextChild;
import java.beans.beancontext.BeanContextSupport;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.SortedSet;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
/**
* Main GUI class for the KnowledgeFlow. Modifications to allow interoperability
* with swt provided by Davide Zerbetto (davide dot zerbetto at eng dot it).
*
* @author Mark Hall
* @version $Revision: 14497 $
* @since 1.0
* @see JPanel
* @see PropertyChangeListener
*/
public class KnowledgeFlowApp extends JPanel implements PropertyChangeListener,
BeanCustomizer.ModifyListener {
/** for serialization */
private static final long serialVersionUID = -7064906770289728431L;
/** Map of all plugin perspectives */
protected Map<String, String> m_pluginPerspectiveLookup =
new HashMap<String, String>();
/** Those perspectives that have been instantiated */
protected Map<String, KFPerspective> m_perspectiveCache =
new HashMap<String, KFPerspective>();
/**
* Holds the details needed to construct button bars for various supported
* classes of weka algorithms/tools
*/
private static Vector<Vector<?>> TOOLBARS = new Vector<Vector<?>>();
/**
* Add a plugin bean props file
*
* @param beanPropsFile the plugin properties to add
* @throws Exception if a problem occurs
*/
public static void addToPluginBeanProps(File beanPropsFile) throws Exception {
BeansProperties.addToPluginBeanProps(beanPropsFile);
}
/**
* Remove a plugin bean props file
*
* @param beanPropsFile the plugin properties to remove
* @throws Exception if a problem occurs
*/
public static void removeFromPluginBeanProps(File beanPropsFile)
throws Exception {
BeansProperties.removeFromPluginBeanProps(beanPropsFile);
}
/**
* Loads KnowledgeFlow properties and any plugins (adds jars to the classpath)
*/
public static synchronized void loadProperties() {
BeansProperties.loadProperties();
}
public static void reInitialize() {
loadProperties();
init();
}
/**
* Initializes the temporary files necessary to construct the toolbars from.
*/
private static void init() {
weka.core.logging.Logger.log(weka.core.logging.Logger.Level.INFO,
"[KnowledgeFlow] Initializing KF...");
// suppress these benign warnings when loading/deserializing XML flows
if (!XMLBeans.SUPPRESS_PROPERTY_WARNINGS.contains("visual.iconPath")) {
XMLBeans.SUPPRESS_PROPERTY_WARNINGS.add("visual.iconPath");
}
if (!XMLBeans.SUPPRESS_PROPERTY_WARNINGS
.contains("visual.animatedIconPath")) {
XMLBeans.SUPPRESS_PROPERTY_WARNINGS.add("visual.animatedIconPath");
}
try {
TOOLBARS = new Vector<Vector<?>>();
TreeMap<Integer, Object> wrapList = new TreeMap<Integer, Object>();
Properties GEOProps = GenericPropertiesCreator
.getGlobalOutputProperties();
if (GEOProps == null) {
GenericPropertiesCreator creator = new GenericPropertiesCreator();
if (creator.useDynamic()) {
creator.execute(false);
/*
* now process the keys in the GenericObjectEditor.props. For each key
* that has an entry in the Beans.props associating it with a bean
* component a button tool bar will be created
*/
GEOProps = creator.getOutputProperties();
} else {
// Read the static information from the GenericObjectEditor.props
GEOProps = Utils.readProperties("weka/gui/GenericObjectEditor.props");
}
}
Enumeration<?> en = GEOProps.propertyNames();
while (en.hasMoreElements()) {
String geoKey = (String) en.nextElement();
// System.err.println("GEOKey " + geoKey);
// try to match this key with one in the Beans.props file
String beanCompName = B