Java tutorial
/* * 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.WekaFileChooser; import weka.gui.beans.xml.XMLBeans; import weka.gui.visualize.PrintablePanel; import javax.swing.AbstractAction; import javax.swing.AbstractButton; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.JTree; import javax.swing.JWindow; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; 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$ * @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 = BeansProperties.BEAN_PROPERTIES.getProperty(geoKey); if (beanCompName != null) { // add details necessary to construct a button bar for this class // of algorithms Vector<Object> newV = new Vector<Object>(); // check for a naming alias for this toolbar String toolBarNameAlias = BeansProperties.BEAN_PROPERTIES.getProperty(geoKey + ".alias"); String toolBarName = (toolBarNameAlias != null) ? toolBarNameAlias : geoKey.substring(geoKey.lastIndexOf('.') + 1, geoKey.length()); // look for toolbar ordering information for this wrapper type String order = BeansProperties.BEAN_PROPERTIES.getProperty(geoKey + ".order"); Integer intOrder = (order != null) ? new Integer(order) : new Integer(0); // Name for the toolbar (name of weka algorithm class) newV.addElement(toolBarName); // Name of bean capable of handling this class of algorithm newV.addElement(beanCompName); // add the root package for this key String rootPackage = geoKey.substring(0, geoKey.lastIndexOf('.')); newV.addElement(rootPackage); // All the weka algorithms of this class of algorithm String wekaAlgs = GEOProps.getProperty(geoKey); Hashtable<String, String> roots = GenericObjectEditor.sortClassesByRoot(wekaAlgs); Hashtable<String, HierarchyPropertyParser> hpps = new Hashtable<String, HierarchyPropertyParser>(); Enumeration<String> enm = roots.keys(); while (enm.hasMoreElements()) { String root = enm.nextElement(); String classes = roots.get(root); weka.gui.HierarchyPropertyParser hpp = new weka.gui.HierarchyPropertyParser(); hpp.build(classes, ", "); // System.err.println(hpp.showTree()); hpps.put(root, hpp); } // ------ test the HierarchyPropertyParser /* * weka.gui.HierarchyPropertyParser hpp = new * weka.gui.HierarchyPropertyParser(); hpp.build(wekaAlgs, ", "); * * System.err.println(hpp.showTree()); */ // ----- end test the HierarchyPropertyParser // newV.addElement(hpp); // add the hierarchical property parser newV.addElement(hpps); // add the hierarchical property parser StringTokenizer st = new StringTokenizer(wekaAlgs, ", "); while (st.hasMoreTokens()) { String current = st.nextToken().trim(); newV.addElement(current); } wrapList.put(intOrder, newV); // TOOLBARS.addElement(newV); } } Iterator<Integer> keysetIt = wrapList.keySet().iterator(); while (keysetIt.hasNext()) { Integer key = keysetIt.next(); @SuppressWarnings("unchecked") Vector<Object> newV = (Vector<Object>) wrapList.get(key); if (newV != null) { TOOLBARS.addElement(newV); } } } catch (Exception ex) { JOptionPane.showMessageDialog(null, "Could not read a configuration file for the generic objecte editor" + ". An example file is included with the Weka distribution.\n" + "This file should be named \"GenericObjectEditor.props\" and\n" + "should be placed either in your user home (which is set\n" + "to \"" + System.getProperties().getProperty("user.home") + "\")\n" + "or the directory that java was started from\n", "KnowledgeFlow", JOptionPane.ERROR_MESSAGE); } try { String standardToolBarNames = BeansProperties.BEAN_PROPERTIES .getProperty("weka.gui.beans.KnowledgeFlow.standardToolBars"); StringTokenizer st = new StringTokenizer(standardToolBarNames, ", "); while (st.hasMoreTokens()) { String tempBarName = st.nextToken().trim(); // construct details for this toolbar Vector<String> newV = new Vector<String>(); // add the name of the toolbar newV.addElement(tempBarName); // indicate that this is a standard toolbar (no wrapper bean) newV.addElement("null"); String toolBarContents = BeansProperties.BEAN_PROPERTIES .getProperty("weka.gui.beans.KnowledgeFlow." + tempBarName); StringTokenizer st2 = new StringTokenizer(toolBarContents, ", "); while (st2.hasMoreTokens()) { String tempBeanName = st2.nextToken().trim(); newV.addElement(tempBeanName); } TOOLBARS.addElement(newV); } } catch (Exception ex) { JOptionPane.showMessageDialog(null, ex.getMessage(), "KnowledgeFlow", JOptionPane.ERROR_MESSAGE); } } protected class BeanIconRenderer extends DefaultTreeCellRenderer { /** Added ID to avoid warning. */ private static final long serialVersionUID = -4488876734500244945L; @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); if (leaf) { Object userO = ((DefaultMutableTreeNode) value).getUserObject(); if (userO instanceof JTreeLeafDetails) { Icon i = ((JTreeLeafDetails) userO).getIcon(); if (i != null) { setIcon(i); } } } return this; } } protected class InvisibleNode extends DefaultMutableTreeNode { /** * */ private static final long serialVersionUID = -9064396835384819887L; protected boolean m_isVisible; public InvisibleNode() { this(null); } public InvisibleNode(Object userObject) { this(userObject, true, true); } public InvisibleNode(Object userObject, boolean allowsChildren, boolean isVisible) { super(userObject, allowsChildren); this.m_isVisible = isVisible; } public TreeNode getChildAt(int index, boolean filterIsActive) { if (!filterIsActive) { return super.getChildAt(index); } if (children == null) { throw new ArrayIndexOutOfBoundsException("node has no children"); } int realIndex = -1; int visibleIndex = -1; Enumeration<TreeNode> e = new WekaEnumeration<TreeNode>(children); while (e.hasMoreElements()) { InvisibleNode node = (InvisibleNode) e.nextElement(); if (node.isVisible()) { visibleIndex++; } realIndex++; if (visibleIndex == index) { return (TreeNode) children.elementAt(realIndex); } } throw new ArrayIndexOutOfBoundsException("index unmatched"); } public int getChildCount(boolean filterIsActive) { if (!filterIsActive) { return super.getChildCount(); } if (children == null) { return 0; } int count = 0; Enumeration<TreeNode> e = new WekaEnumeration<TreeNode>(children); while (e.hasMoreElements()) { InvisibleNode node = (InvisibleNode) e.nextElement(); if (node.isVisible()) { count++; } } return count; } public void setVisible(boolean visible) { this.m_isVisible = visible; } public boolean isVisible() { return m_isVisible; } } protected class InvisibleTreeModel extends DefaultTreeModel { /** * */ private static final long serialVersionUID = 6940101211275068260L; protected boolean m_filterIsActive; public InvisibleTreeModel(TreeNode root) { this(root, false); } public InvisibleTreeModel(TreeNode root, boolean asksAllowsChildren) { this(root, false, false); } public InvisibleTreeModel(TreeNode root, boolean asksAllowsChildren, boolean filterIsActive) { super(root, asksAllowsChildren); this.m_filterIsActive = filterIsActive; } public void activateFilter(boolean newValue) { m_filterIsActive = newValue; } public boolean isActivatedFilter() { return m_filterIsActive; } @Override public Object getChild(Object parent, int index) { if (m_filterIsActive) { if (parent instanceof InvisibleNode) { return ((InvisibleNode) parent).getChildAt(index, m_filterIsActive); } } return ((TreeNode) parent).getChildAt(index); } @Override public int getChildCount(Object parent) { if (m_filterIsActive) { if (parent instanceof InvisibleNode) { return ((InvisibleNode) parent).getChildCount(m_filterIsActive); } } return ((TreeNode) parent).getChildCount(); } } /** * Inner class for encapsulating information about a bean that is represented * at a leaf in the JTree. */ protected class JTreeLeafDetails implements Serializable { /** * For serialization */ private static final long serialVersionUID = 6197221540272931626L; /** fully qualified bean name */ protected String m_fullyQualifiedCompName = ""; /** * the label (usually derived from the qualified name or wrapped algorithm) * for the leaf */ protected String m_leafLabel = ""; /** the fully qualified wrapped weka algorithm name */ protected String m_wekaAlgoName = ""; /** icon to display at the leaf (scaled appropriately) */ protected transient Icon m_scaledIcon = null; /** XML serialized MetaBean (if this is a user component) */ // protected StringBuffer m_metaBean = null; protected Vector<Object> m_metaBean = null; /** true if this is a MetaBean (user component) */ protected boolean m_isMeta = false; /** tool tip text to display */ protected String m_toolTipText = null; /** * Constructor. * * @param fullName flully qualified name of the bean * @param icon icon for the bean */ protected JTreeLeafDetails(String fullName, Icon icon) { this(fullName, "", icon); } /** * Constructor * * @param name fully qualified name of the bean * @param serializedMeta empty string or XML serialized MetaBean if this * leaf represents a "user" component * * @param icon icon for the bean */ protected JTreeLeafDetails(String name, Vector<Object> serializedMeta, Icon icon) { this(name, "", icon); // m_isMeta = isMeta; m_metaBean = serializedMeta; m_isMeta = true; m_toolTipText = "Hold down shift and click to remove"; } /** * Constructor * * @param fullName fully qualified name of the bean * @param wekaAlgoName fully qualified name of the encapsulated (wrapped) * weka algorithm, or null if this bean does not wrap a Weka * algorithm * * @param icon icon for the bean */ protected JTreeLeafDetails(String fullName, String wekaAlgoName, Icon icon) { m_fullyQualifiedCompName = fullName; m_wekaAlgoName = wekaAlgoName; m_leafLabel = (wekaAlgoName.length() > 0) ? wekaAlgoName : m_fullyQualifiedCompName; if (m_leafLabel.lastIndexOf('.') > 0) { m_leafLabel = m_leafLabel.substring(m_leafLabel.lastIndexOf('.') + 1, m_leafLabel.length()); } m_scaledIcon = icon; } /** * Get the tool tip for this leaf * * @return the tool tip */ protected String getToolTipText() { return m_toolTipText; } protected void setToolTipText(String tipText) { m_toolTipText = tipText; } /** * Returns the leaf label * * @return the leaf label */ @Override public String toString() { return m_leafLabel; } /** * Gets the icon for this bean * * @return the icon for this bean */ protected Icon getIcon() { return m_scaledIcon; } /** * Set the icon to use for this bean * * @param icon the icon to use */ protected void setIcon(Icon icon) { m_scaledIcon = icon; } /** * Returns true if this leaf represents a wrapped Weka algorithm (i.e. * filter, classifier, clusterer etc.). * * @return true if this leaf represents a wrapped algorithm */ protected boolean isWrappedAlgorithm() { return (m_wekaAlgoName != null && m_wekaAlgoName.length() > 0); } /** * Returns true if this leaf represents a MetaBean (i.e. "user" component) * * @return true if this leaf represents a MetaBean */ protected boolean isMetaBean() { return (m_metaBean != null); // return (m_wekaAlgoName.length() == 0); // return m_isMeta; } /** * Gets the XML serialized MetaBean and associated information (icon, * displayname) * * @return the XML serialized MetaBean as a 3-element Vector containing * display name serialized bean and icon */ protected Vector<Object> getMetaBean() { return m_metaBean; } /** * "Instantiates" the bean represented by this leaf. */ protected void instantiateBean() { try { if (isMetaBean()) { // MetaBean copy = copyMetaBean(m_metaBean, false); // copy.addPropertyChangeListenersSubFlow(KnowledgeFlowApp.this); m_toolBarBean = m_metaBean.get(1); } else { m_toolBarBean = WekaPackageClassLoaderManager.objectForName(m_fullyQualifiedCompName); //m_toolBarBean = Beans.instantiate(KnowledgeFlowApp.this.getClass() // .getClassLoader(), m_fullyQualifiedCompName); if (isWrappedAlgorithm()) { Object algo = WekaPackageClassLoaderManager.objectForName(m_wekaAlgoName); //Object algo = Beans.instantiate(KnowledgeFlowApp.this.getClass() // .getClassLoader(), m_wekaAlgoName); ((WekaWrapper) m_toolBarBean).setWrappedAlgorithm(algo); } } KnowledgeFlowApp.this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); m_mode = ADDING; m_pasteB.setEnabled(false); } catch (Exception ex) { System.err.println("Problem instantiating bean \"" + m_fullyQualifiedCompName + "\" (JTreeLeafDetails.instantiateBean()"); ex.printStackTrace(); } } } /** * Used for displaying the bean components and their visible connections * * @author <a href="mailto:mhall@cs.waikato.ac.nz">Mark Hall</a> * @version $Revision$ * @since 1.0 * @see PrintablePanel */ protected class BeanLayout extends PrintablePanel { /** for serialization */ private static final long serialVersionUID = -146377012429662757L; @Override public void paintComponent(Graphics gx) { double lz = m_layoutZoom / 100.0; ((Graphics2D) gx).scale(lz, lz); if (m_layoutZoom < 100) { ((Graphics2D) gx).setStroke(new BasicStroke(2)); } super.paintComponent(gx); ((Graphics2D) gx).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); ((Graphics2D) gx).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP); BeanInstance.paintLabels(gx, m_mainKFPerspective.getCurrentTabIndex()); BeanConnection.paintConnections(gx, m_mainKFPerspective.getCurrentTabIndex()); // BeanInstance.paintConnections(gx); if (m_mode == CONNECTING) { gx.drawLine(m_startX, m_startY, m_oldX, m_oldY); } else if (m_mode == SELECTING) { gx.drawRect((m_startX < m_oldX) ? m_startX : m_oldX, (m_startY < m_oldY) ? m_startY : m_oldY, Math.abs(m_oldX - m_startX), Math.abs(m_oldY - m_startY)); } } @Override public void doLayout() { super.doLayout(); Vector<Object> comps = BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()); for (int i = 0; i < comps.size(); i++) { BeanInstance bi = (BeanInstance) comps.elementAt(i); JComponent c = (JComponent) bi.getBean(); Dimension d = c.getPreferredSize(); c.setBounds(bi.getX(), bi.getY(), d.width, d.height); c.revalidate(); } } } /** * Interface for perspectives. */ public static interface KFPerspective { /** * Set instances (if the perspective accepts them) * * @param insts the instances */ void setInstances(Instances insts) throws Exception; /** * Returns true if this perspective accepts instances * * @return true if this perspective can accept instances */ boolean acceptsInstances(); /** * Get the title of this perspective * * @return the title of this perspective */ String getPerspectiveTitle(); /** * Get the tool tip text for this perspective. * * @return the tool tip text for this perspective */ String getPerspectiveTipText(); /** * Get the icon for this perspective. * * @return the Icon for this perspective (or null if the perspective does * not have an icon) */ Icon getPerspectiveIcon(); /** * Set active status of this perspective. True indicates that this * perspective is the visible active perspective in the KnowledgeFlow * * @param active true if this perspective is the active one */ void setActive(boolean active); /** * Set whether this perspective is "loaded" - i.e. whether or not the user * has opted to have it available in the perspective toolbar. The * perspective can make the decision as to allocating or freeing resources * on the basis of this. * * @param loaded true if the perspective is available in the perspective * toolbar of the KnowledgeFlow */ void setLoaded(boolean loaded); /** * Set a reference to the main KnowledgeFlow perspective - i.e. the * perspective that manages flow layouts. * * @param main the main KnowledgeFlow perspective. */ void setMainKFPerspective(KnowledgeFlowApp.MainKFPerspective main); } /** * Main Knowledge Flow perspective * */ public class MainKFPerspective extends JPanel implements KFPerspective { /** * */ private static final long serialVersionUID = 7666381888012259527L; /** Holds the tabs of the perspective */ protected JTabbedPane m_flowTabs = new JTabbedPane(); /** List of layouts - one for each tab */ protected List<BeanLayout> m_beanLayouts = new ArrayList<BeanLayout>(); /** List of zoom settings - one for each tab */ protected List<Integer> m_zoomSettings = new ArrayList<Integer>(); /** List of log panels - one for each tab */ protected List<KFLogPanel> m_logPanels = new ArrayList<KFLogPanel>(); /** List of environment variable settings - one for each tab */ protected List<Environment> m_environmentSettings = new ArrayList<Environment>(); /** List of flow file paths - one for each tab */ protected List<File> m_filePaths = new ArrayList<File>(); /** Keeps track of which tabs have been edited but not saved */ protected List<Boolean> m_editedList = new ArrayList<Boolean>(); /** Keeps track of which tabs have flows that are executing */ protected List<Boolean> m_executingList = new ArrayList<Boolean>(); /** Keeps track of the threads used for execution */ protected List<RunThread> m_executionThreads = new ArrayList<RunThread>(); /** Keeps track of any highlighted beans on the canvas for a tab */ protected List<Vector<Object>> m_selectedBeans = new ArrayList<Vector<Object>>(); /** Keeps track of the undo buffers for each tab */ protected List<Stack<File>> m_undoBufferList = new ArrayList<Stack<File>>(); protected Map<String, DefaultMutableTreeNode> m_nodeTextIndex = new LinkedHashMap<String, DefaultMutableTreeNode>(); @Override public void setActive(boolean active) { // nothing to do here } @Override public void setLoaded(boolean loaded) { // we are always loaded and part of the set of perspectives } @Override public void setMainKFPerspective(MainKFPerspective main) { // we don't need this :-) } public JTabbedPane getTabbedPane() { return m_flowTabs; } public synchronized int getNumTabs() { return m_flowTabs.getTabCount(); } public synchronized String getTabTitle(int index) { if (index < getNumTabs() && index >= 0) { return m_flowTabs.getTitleAt(index); } return null; } public synchronized int getCurrentTabIndex() { return m_flowTabs.getSelectedIndex(); } public synchronized KFLogPanel getCurrentLogPanel() { if (getCurrentTabIndex() >= 0) { return m_logPanels.get(getCurrentTabIndex()); } return null; } public synchronized KFLogPanel getLogPanel(int index) { if (index >= 0 && index < m_logPanels.size()) { return m_logPanels.get(index); } return null; } public synchronized BeanLayout getCurrentBeanLayout() { if (getCurrentTabIndex() >= 0) { return m_beanLayouts.get(getCurrentTabIndex()); } return null; } public synchronized BeanLayout getBeanLayout(int index) { if (index >= 0 && index < m_logPanels.size()) { return m_beanLayouts.get(getCurrentTabIndex()); } return null; } public synchronized int getCurrentZoomSetting() { if (getCurrentTabIndex() >= 0) { return m_zoomSettings.get(getCurrentTabIndex()).intValue(); } // no scaling return 100; } public synchronized int getZoomSetting(int index) { if (index >= 0 && index < m_zoomSettings.size()) { return m_zoomSettings.get(index); } // no scaling return 100; } public synchronized void setCurrentZoomSetting(int z) { if (getNumTabs() > 0) { setZoomSetting(getCurrentTabIndex(), z); } } public synchronized void setZoomSetting(int index, int z) { if (index < getNumTabs() && index >= 0) { m_zoomSettings.set(index, new Integer(z)); } } public synchronized void setActiveTab(int index) { if (index < getNumTabs() && index >= 0) { m_flowTabs.setSelectedIndex(index); // set the log and layout to the ones belonging to this tab m_logPanel = m_logPanels.get(index); m_beanLayout = m_beanLayouts.get(index); m_layoutZoom = m_zoomSettings.get(index); m_flowEnvironment = m_environmentSettings.get(index); m_saveB.setEnabled(!getExecuting()); m_saveBB.setEnabled(!getExecuting()); m_playB.setEnabled(!getExecuting()); m_playBB.setEnabled(!getExecuting()); m_saveB.setEnabled(!getExecuting()); m_saveBB.setEnabled(!getExecuting()); m_zoomOutB.setEnabled(!getExecuting()); m_zoomInB.setEnabled(!getExecuting()); if (m_layoutZoom == 50) { m_zoomOutB.setEnabled(false); } if (m_layoutZoom == 200) { m_zoomInB.setEnabled(false); } m_groupB.setEnabled(false); if (getSelectedBeans().size() > 0 && !getExecuting()) { // Able to group selected subflow? final Vector<Object> selected = m_mainKFPerspective.getSelectedBeans(); // check if sub flow is valid final Vector<Object> inputs = BeanConnection.inputs(selected, m_mainKFPerspective.getCurrentTabIndex()); final Vector<Object> outputs = BeanConnection.outputs(selected, m_mainKFPerspective.getCurrentTabIndex()); if (groupable(selected, inputs, outputs)) { m_groupB.setEnabled(true); } } m_cutB.setEnabled(getSelectedBeans().size() > 0 && !getExecuting()); m_copyB.setEnabled(getSelectedBeans().size() > 0 && !getExecuting()); m_deleteB.setEnabled(getSelectedBeans().size() > 0 && !getExecuting()); m_selectAllB.setEnabled( BeanInstance.getBeanInstances(getCurrentTabIndex()).size() > 0 && !getExecuting()); m_pasteB.setEnabled((m_pasteBuffer != null && m_pasteBuffer.length() > 0) && !getExecuting()); m_stopB.setEnabled(getExecuting()); m_undoB.setEnabled(!getExecuting() && getUndoBuffer().size() > 0); } } public synchronized void setExecuting(boolean executing) { if (getNumTabs() > 0) { setExecuting(getCurrentTabIndex(), executing); } } public synchronized void setExecuting(int index, boolean executing) { if (index < getNumTabs() && index >= 0) { m_executingList.set(index, new Boolean(executing)); ((CloseableTabTitle) m_flowTabs.getTabComponentAt(index)).setButtonEnabled(!executing); m_saveB.setEnabled(!getExecuting()); m_saveBB.setEnabled(!getExecuting()); m_playB.setEnabled(!getExecuting()); m_playBB.setEnabled(!getExecuting()); m_stopB.setEnabled(getExecuting()); m_groupB.setEnabled(false); if (getSelectedBeans().size() > 0 && !getExecuting()) { // Able to group selected subflow? final Vector<Object> selected = m_mainKFPerspective.getSelectedBeans(); // check if sub flow is valid final Vector<Object> inputs = BeanConnection.inputs(selected, m_mainKFPerspective.getCurrentTabIndex()); final Vector<Object> outputs = BeanConnection.outputs(selected, m_mainKFPerspective.getCurrentTabIndex()); if (groupable(selected, inputs, outputs)) { m_groupB.setEnabled(true); } } m_cutB.setEnabled(getSelectedBeans().size() > 0 && !getExecuting()); m_deleteB.setEnabled(getSelectedBeans().size() > 0 && !getExecuting()); m_selectAllB.setEnabled( BeanInstance.getBeanInstances(getCurrentTabIndex()).size() > 0 && !getExecuting()); m_copyB.setEnabled(getSelectedBeans().size() > 0 && !getExecuting()); m_pasteB.setEnabled((m_pasteBuffer != null && m_pasteBuffer.length() > 0) && !getExecuting()); m_undoB.setEnabled(!getExecuting() && getUndoBuffer().size() > 0); } } public synchronized boolean getExecuting() { return getExecuting(getCurrentTabIndex()); } public synchronized boolean getExecuting(int index) { if (index < getNumTabs() && index >= 0) { return m_executingList.get(index); } return false; } public synchronized void setExecutionThread(RunThread execution) { if (getNumTabs() > 0) { setExecutionThread(getCurrentTabIndex(), execution); } } public synchronized void setExecutionThread(int index, RunThread execution) { if (index < getNumTabs() && index >= 0) { m_executionThreads.set(index, execution); } } public synchronized RunThread getExecutionThread() { return getExecutionThread(getCurrentTabIndex()); } public synchronized RunThread getExecutionThread(int index) { if (index < getNumTabs() && index >= 0) { return m_executionThreads.get(index); } return null; } public synchronized File getFlowFile() { if (getNumTabs() > 0) { return getFlowFile(getCurrentTabIndex()); } return null; } public synchronized File getFlowFile(int index) { if (index >= 0 && index < getNumTabs()) { return m_filePaths.get(index); } return null; } public synchronized void setFlowFile(File flowFile) { if (getNumTabs() > 0) { setFlowFile(getCurrentTabIndex(), flowFile); } } public synchronized void setFlowFile(int index, File flowFile) { if (index < getNumTabs() && index >= 0) { m_filePaths.set(index, flowFile); } } public synchronized void setTabTitle(String title) { if (getNumTabs() > 0) { setTabTitle(getCurrentTabIndex(), title); } } public synchronized void setTabTitle(int index, String title) { if (index < getNumTabs() && index >= 0) { m_flowTabs.setTitleAt(index, title); ((CloseableTabTitle) m_flowTabs.getTabComponentAt(index)).revalidate(); } } public synchronized void setEditedStatus(boolean status) { if (getNumTabs() > 0) { int current = getCurrentTabIndex(); setEditedStatus(current, status); } } public synchronized void setEditedStatus(int index, boolean status) { if (index < getNumTabs() && index >= 0) { Boolean newStatus = new Boolean(status); m_editedList.set(index, newStatus); ((CloseableTabTitle) m_flowTabs.getTabComponentAt(index)).setBold(status); } } /** * Get the edited status of the currently selected tab. Returns false if * there are no tabs * * @return the edited status of the currently selected tab or false if there * are no tabs */ public synchronized boolean getEditedStatus() { if (getNumTabs() <= 0) { return false; } return getEditedStatus(getCurrentTabIndex()); } /** * Get the edited status of the tab at the supplied index. Returns false if * the index is out of bounds or there are no tabs * * @param index the index of the tab to check * @return the edited status of the tab */ public synchronized boolean getEditedStatus(int index) { if (index < getNumTabs() && index >= 0) { return m_editedList.get(index); } return false; } public synchronized void setUndoBuffer(Stack<File> buffer) { if (getNumTabs() > 0) { setUndoBuffer(getCurrentTabIndex(), buffer); } } public synchronized void setUndoBuffer(int index, Stack<File> buffer) { if (index < getNumTabs() && index >= 0) { m_undoBufferList.set(index, buffer); } } public synchronized Stack<File> getUndoBuffer() { if (getNumTabs() > 0) { return getUndoBuffer(getCurrentTabIndex()); } return null; } public synchronized Stack<File> getUndoBuffer(int index) { if (index >= 0 && index < getNumTabs()) { return m_undoBufferList.get(index); } return null; } public synchronized Vector<Object> getSelectedBeans() { if (getNumTabs() > 0) { return getSelectedBeans(getCurrentTabIndex()); } return null; } public synchronized Vector<Object> getSelectedBeans(int index) { if (index < getNumTabs() && index >= 0) { return m_selectedBeans.get(index); } return null; } public synchronized void setSelectedBeans(Vector<Object> beans) { if (getNumTabs() > 0) { setSelectedBeans(getCurrentTabIndex(), beans); m_groupB.setEnabled(false); if (getSelectedBeans().size() > 0 && !getExecuting()) { // Able to group selected subflow? final Vector<Object> selected = m_mainKFPerspective.getSelectedBeans(); // check if sub flow is valid final Vector<Object> inputs = BeanConnection.inputs(selected, m_mainKFPerspective.getCurrentTabIndex()); final Vector<Object> outputs = BeanConnection.outputs(selected, m_mainKFPerspective.getCurrentTabIndex()); if (groupable(selected, inputs, outputs)) { m_groupB.setEnabled(true); } } m_cutB.setEnabled(getSelectedBeans().size() > 0 && !getExecuting()); m_copyB.setEnabled(getSelectedBeans().size() > 0 && !getExecuting()); m_deleteB.setEnabled(getSelectedBeans().size() > 0 && !getExecuting()); } } public synchronized void setSelectedBeans(int index, Vector<Object> beans) { if (index < getNumTabs() && index >= 0) { // turn turn off any set ones for (int i = 0; i < m_selectedBeans.get(index).size(); i++) { BeanInstance temp = (BeanInstance) m_selectedBeans.get(index).elementAt(i); if (temp.getBean() instanceof Visible) { ((Visible) temp.getBean()).getVisual().setDisplayConnectors(false); } else if (temp.getBean() instanceof Note) { ((Note) temp.getBean()).setHighlighted(false); } } m_selectedBeans.set(index, beans); // highlight any new ones for (int i = 0; i < beans.size(); i++) { BeanInstance temp = (BeanInstance) beans.elementAt(i); if (temp.getBean() instanceof Visible) { ((Visible) temp.getBean()).getVisual().setDisplayConnectors(true); } else if (temp.getBean() instanceof Note) { ((Note) temp.getBean()).setHighlighted(true); } } } } public synchronized Environment getEnvironmentSettings() { if (getNumTabs() > 0) { return getEnvironmentSettings(getCurrentTabIndex()); } return null; } public synchronized Environment getEnvironmentSettings(int index) { if (index < getNumTabs() && index >= 0) { return m_environmentSettings.get(index); } return null; } @Override public void setInstances(Instances insts) { // nothing to do as we don't process externally supplied instances } @Override public boolean acceptsInstances() { // not needed return false; } /** * Get the title of this perspective */ @Override public String getPerspectiveTitle() { return "Data mining processes"; } /** * Get the tool tip text for this perspective */ @Override public String getPerspectiveTipText() { return "Knowledge Flow processes"; } /** * Get the icon for this perspective */ @Override public Icon getPerspectiveIcon() { Image wekaI = loadImage("weka/gui/weka_icon_new.png"); ImageIcon icon = new ImageIcon(wekaI); double width = icon.getIconWidth(); double height = icon.getIconHeight(); width *= 0.035; height *= 0.035; wekaI = wekaI.getScaledInstance((int) width, (int) height, Image.SCALE_SMOOTH); icon = new ImageIcon(wekaI); return icon; } @SuppressWarnings("unchecked") private void setUpToolsAndJTree() { JPanel toolBarPanel = new JPanel(); toolBarPanel.setLayout(new BorderLayout()); // modifications by Zerbetto // first construct the toolbar for saving, loading etc if (m_showFileMenu) { // set up an action for closing the curren tab final Action closeAction = new AbstractAction("Close") { /** * */ private static final long serialVersionUID = 4762166880144590384L; @Override public void actionPerformed(ActionEvent e) { if (m_mainKFPerspective.getCurrentTabIndex() >= 0) { m_mainKFPerspective.removeTab(getCurrentTabIndex()); } } }; KeyStroke closeKey = KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("Close", closeAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(closeKey, "Close"); JToolBar fixedTools = new JToolBar(); fixedTools.setOrientation(JToolBar.HORIZONTAL); m_groupB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "bricks.png"))); m_groupB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_groupB.setToolTipText("Group selected (Ctrl+Z)"); m_cutB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "cut.png"))); m_cutB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_cutB.setToolTipText("Cut selected (Ctrl+X)"); m_copyB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "page_copy.png"))); m_copyB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_copyB.setToolTipText("Copy selected (Ctrl+C)"); m_pasteB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "paste_plain.png"))); m_pasteB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_pasteB.setToolTipText("Paste from clipboard (Ctrl+V)"); m_deleteB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "delete.png"))); m_deleteB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_deleteB.setToolTipText("Delete selected (DEL)"); m_snapToGridB = new JToggleButton( new ImageIcon(loadImage(BeanVisual.ICON_PATH + "shape_handles.png"))); // m_snapToGridB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_snapToGridB.setToolTipText("Snap to grid (Ctrl+G)"); m_saveB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "disk.png"))); m_saveB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_saveB.setToolTipText("Save layout (Ctrl+S)"); m_saveBB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "disk_multiple.png"))); m_saveBB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_saveBB.setToolTipText("Save layout with new name"); m_loadB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "folder_add.png"))); m_loadB.setToolTipText("Open (Ctrl+O)"); m_loadB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_newB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "page_add.png"))); m_newB.setToolTipText("New layout (Ctrl+N)"); m_newB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_newB.setEnabled(getAllowMultipleTabs()); m_helpB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "help.png"))); m_helpB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_helpB.setToolTipText("Display help (Ctrl+H)"); m_togglePerspectivesB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "cog_go.png"))); m_togglePerspectivesB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_togglePerspectivesB.setToolTipText("Show/hide perspectives toolbar (Ctrl+P)"); m_templatesB = new JButton( new ImageIcon(loadImage(BeanVisual.ICON_PATH + "application_view_tile.png"))); m_templatesB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_templatesB.setToolTipText("Load a template layout"); m_noteB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "note_add.png"))); m_noteB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_noteB.setToolTipText("Add a note to the layout (Ctrl+I)"); m_selectAllB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "shape_group.png"))); m_selectAllB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_selectAllB.setToolTipText("Select all (Ctrl+A)"); m_zoomInB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "zoom_in.png"))); m_zoomInB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_zoomInB.setToolTipText("Zoom in (Ctrl++)"); m_zoomOutB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "zoom_out.png"))); m_zoomOutB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_zoomOutB.setToolTipText("Zoom out (Ctrl+-)"); m_undoB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "arrow_undo.png"))); m_undoB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_undoB.setToolTipText("Undo (Ctrl+U)"); fixedTools.add(m_zoomInB); fixedTools.add(m_zoomOutB); fixedTools.addSeparator(); fixedTools.add(m_selectAllB); fixedTools.add(m_groupB); fixedTools.add(m_cutB); fixedTools.add(m_copyB); fixedTools.add(m_deleteB); fixedTools.add(m_pasteB); fixedTools.add(m_undoB); fixedTools.add(m_noteB); fixedTools.addSeparator(); fixedTools.add(m_snapToGridB); fixedTools.addSeparator(); fixedTools.add(m_newB); fixedTools.add(m_saveB); fixedTools.add(m_saveBB); fixedTools.add(m_loadB); fixedTools.add(m_templatesB); fixedTools.addSeparator(); fixedTools.add(m_togglePerspectivesB); fixedTools.add(m_helpB); Dimension d = m_undoB.getPreferredSize(); Dimension d2 = fixedTools.getMinimumSize(); Dimension d3 = new Dimension(d2.width, d.height + 4); fixedTools.setPreferredSize(d3); fixedTools.setMaximumSize(d3); final Action saveAction = new AbstractAction("Save") { /** * */ private static final long serialVersionUID = 5182044142154404706L; @Override public void actionPerformed(ActionEvent e) { if (m_mainKFPerspective.getCurrentTabIndex() >= 0) { saveLayout(m_mainKFPerspective.getCurrentTabIndex(), false); } } }; KeyStroke saveKey = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("Save", saveAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(saveKey, "Save"); m_saveB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { saveAction.actionPerformed(e); } }); m_saveBB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { saveLayout(m_mainKFPerspective.getCurrentTabIndex(), true); } }); final Action openAction = new AbstractAction("Open") { /** * */ private static final long serialVersionUID = -5106547209818805444L; @Override public void actionPerformed(ActionEvent e) { m_flowEnvironment = new Environment(); loadLayout(); } }; KeyStroke openKey = KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("Open", openAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(openKey, "Open"); m_loadB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { openAction.actionPerformed(e); } }); final Action newAction = new AbstractAction("New") { /** * */ private static final long serialVersionUID = 8002244400334262966L; @Override public void actionPerformed(ActionEvent e) { clearLayout(); } }; KeyStroke newKey = KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("New", newAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(newKey, "New"); m_newB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { newAction.actionPerformed(ae); } }); final Action selectAllAction = new AbstractAction("SelectAll") { /** * */ private static final long serialVersionUID = -8086754050844707658L; @Override public void actionPerformed(ActionEvent e) { if (BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()).size() > 0) { // select all beans Vector<Object> allBeans = BeanInstance .getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()); Vector<Object> newSelected = new Vector<Object>(); for (int i = 0; i < allBeans.size(); i++) { newSelected.add(allBeans.get(i)); } // toggle if (newSelected.size() == m_mainKFPerspective.getSelectedBeans().size()) { // unselect all beans m_mainKFPerspective.setSelectedBeans(new Vector<Object>()); } else { // select all beans m_mainKFPerspective.setSelectedBeans(newSelected); } } revalidate(); repaint(); notifyIsDirty(); } }; KeyStroke selectAllKey = KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("SelectAll", selectAllAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(selectAllKey, "SelectAll"); m_selectAllB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { selectAllAction.actionPerformed(e); } }); final Action zoomInAction = new AbstractAction("ZoomIn") { /** * */ private static final long serialVersionUID = 1348383794897269484L; @Override public void actionPerformed(ActionEvent e) { m_layoutZoom += 25; m_zoomOutB.setEnabled(true); if (m_layoutZoom >= 200) { m_layoutZoom = 200; m_zoomInB.setEnabled(false); } m_mainKFPerspective.setCurrentZoomSetting(m_layoutZoom); revalidate(); repaint(); notifyIsDirty(); } }; KeyStroke zoomInKey = KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("ZoomIn", zoomInAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(zoomInKey, "ZoomIn"); m_zoomInB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { zoomInAction.actionPerformed(e); } }); final Action zoomOutAction = new AbstractAction("ZoomOut") { /** * */ private static final long serialVersionUID = -1120096894263455918L; @Override public void actionPerformed(ActionEvent e) { m_layoutZoom -= 25; m_zoomInB.setEnabled(true); if (m_layoutZoom <= 50) { m_layoutZoom = 50; m_zoomOutB.setEnabled(false); } m_mainKFPerspective.setCurrentZoomSetting(m_layoutZoom); revalidate(); repaint(); notifyIsDirty(); } }; KeyStroke zoomOutKey = KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("ZoomOut", zoomOutAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(zoomOutKey, "ZoomOut"); m_zoomOutB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { zoomOutAction.actionPerformed(e); } }); final Action groupAction = new AbstractAction("Group") { /** * */ private static final long serialVersionUID = -5752742619180091435L; @Override public void actionPerformed(ActionEvent e) { final Vector<Object> selected = m_mainKFPerspective.getSelectedBeans(); final Vector<Object> inputs = BeanConnection.inputs(selected, m_mainKFPerspective.getCurrentTabIndex()); final Vector<Object> outputs = BeanConnection.outputs(selected, m_mainKFPerspective.getCurrentTabIndex()); groupSubFlow(selected, inputs, outputs); } }; KeyStroke groupKey = KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("Group", groupAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(groupKey, "Group"); m_groupB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { groupAction.actionPerformed(e); } }); final Action cutAction = new AbstractAction("Cut") { /** * */ private static final long serialVersionUID = -4955878102742013040L; @Override public void actionPerformed(ActionEvent e) { // only delete if our copy was successful! if (copyToClipboard()) { deleteSelectedBeans(); } } }; KeyStroke cutKey = KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("Cut", cutAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(cutKey, "Cut"); m_cutB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { cutAction.actionPerformed(e); } }); final Action deleteAction = new AbstractAction("Delete") { /** * */ private static final long serialVersionUID = 4621688037874199553L; @Override public void actionPerformed(ActionEvent e) { deleteSelectedBeans(); } }; KeyStroke deleteKey = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0); MainKFPerspective.this.getActionMap().put("Delete", deleteAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(deleteKey, "Delete"); m_deleteB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { deleteAction.actionPerformed(e); } }); final Action copyAction = new AbstractAction("Copy") { /** * */ private static final long serialVersionUID = 117010390180468707L; @Override public void actionPerformed(ActionEvent e) { copyToClipboard(); m_mainKFPerspective.setSelectedBeans(new Vector<Object>()); } }; KeyStroke copyKey = KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("Copy", copyAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(copyKey, "Copy"); m_copyB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { copyAction.actionPerformed(e); } }); final Action pasteAction = new AbstractAction("Paste") { /** * */ private static final long serialVersionUID = 5935121051028929455L; @Override public void actionPerformed(ActionEvent e) { KnowledgeFlowApp.this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); m_mode = PASTING; } }; KeyStroke pasteKey = KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("Paste", pasteAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(pasteKey, "Paste"); m_pasteB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { pasteAction.actionPerformed(e); } }); final Action snapAction = new AbstractAction("Snap") { /** * */ private static final long serialVersionUID = 7820689847829357449L; @Override public void actionPerformed(ActionEvent e) { // toggle first m_snapToGridB.setSelected(!m_snapToGridB.isSelected()); if (m_snapToGridB.isSelected()) { snapSelectedToGrid(); } } }; KeyStroke snapKey = KeyStroke.getKeyStroke(KeyEvent.VK_G, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("Snap", snapAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(snapKey, "Snap"); m_snapToGridB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (m_snapToGridB.isSelected()) { snapSelectedToGrid(); } } }); fixedTools.setFloatable(false); toolBarPanel.add(fixedTools, BorderLayout.EAST); } final Action noteAction = new AbstractAction("Note") { /** * */ private static final long serialVersionUID = 2991743619130024875L; @Override public void actionPerformed(ActionEvent e) { Note n = new Note(); m_toolBarBean = n; KnowledgeFlowApp.this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); m_mode = ADDING; } }; KeyStroke noteKey = KeyStroke.getKeyStroke(KeyEvent.VK_I, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("Note", noteAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(noteKey, "Note"); m_noteB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { noteAction.actionPerformed(e); } }); final Action undoAction = new AbstractAction("Undo") { /** * */ private static final long serialVersionUID = 7248362305594881263L; @Override public void actionPerformed(ActionEvent e) { Stack<File> undo = m_mainKFPerspective.getUndoBuffer(); if (undo.size() > 0) { File undoF = undo.pop(); if (undo.size() == 0) { m_undoB.setEnabled(false); } loadLayout(undoF, false, true); } } }; KeyStroke undoKey = KeyStroke.getKeyStroke(KeyEvent.VK_U, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("Undo", undoAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(undoKey, "Undo"); m_undoB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { undoAction.actionPerformed(e); } }); m_playB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "resultset_next.png"))); m_playB.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); m_playB.setToolTipText("Run this flow (all start points launched in parallel)"); m_playB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()).size() == 0) { return; } boolean proceed = true; if (m_Memory.memoryIsLow()) { proceed = m_Memory.showMemoryIsLow(); } if (proceed) { runFlow(false); } } }); m_playBB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "resultset_last.png"))); m_playBB.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); m_playBB.setToolTipText("Run this flow (start points launched sequentially)"); m_playBB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()).size() == 0) { return; } if (!Utils.getDontShowDialog("weka.gui.beans.KnowledgeFlow.SequentialRunInfo")) { JCheckBox dontShow = new JCheckBox("Do not show this message again"); Object[] stuff = new Object[2]; stuff[0] = "The order that data sources are launched in can be\n" + "specified by setting a custom name for each data source that\n" + "that includes a number. E.g. \"1:MyArffLoader\". To set a name,\n" + "right-click over a data source and select \"Set name\"\n\n" + "If the prefix is not specified, then the order of execution\n" + "will correspond to the order that the components were added\n" + "to the layout. Note that it is also possible to prevent a data\n" + "source from executing by prefixing its name with a \"!\". E.g\n" + "\"!:MyArffLoader\""; stuff[1] = dontShow; JOptionPane.showMessageDialog(KnowledgeFlowApp.this, stuff, "Sequential execution information", JOptionPane.OK_OPTION); if (dontShow.isSelected()) { try { Utils.setDontShowDialog("weka.gui.beans.KnowledgeFlow.SequentialRunInfo"); } catch (Exception ex) { // quietly ignore } } } boolean proceed = true; if (m_Memory.memoryIsLow()) { proceed = m_Memory.showMemoryIsLow(); } if (proceed) { runFlow(true); } } }); m_stopB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "shape_square.png"))); m_stopB.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); m_stopB.setToolTipText("Stop all execution"); Image tempI = loadImage(BeanVisual.ICON_PATH + "cursor.png"); m_pointerB = new JButton(new ImageIcon(tempI)); m_pointerB.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); m_pointerB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { m_toolBarBean = null; m_mode = NONE; KnowledgeFlowApp.this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); m_componentTree.clearSelection(); } }); // Dimension dP = m_saveB.getPreferredSize(); // Dimension dM = m_saveB.getMaximumSize(); // Dimension dP = m_stopB.getPreferredSize(); // Dimension dM = m_stopB.getMaximumSize(); // m_pointerB.setPreferredSize(dP); // m_pointerB.setMaximumSize(dM); // m_toolBarGroup.add(m_pointerB); JToolBar fixedTools2 = new JToolBar(); fixedTools2.setOrientation(JToolBar.HORIZONTAL); fixedTools2.setFloatable(false); fixedTools2.add(m_pointerB); fixedTools2.add(m_playB); fixedTools2.add(m_playBB); fixedTools2.add(m_stopB); Dimension d = m_playB.getPreferredSize(); Dimension d2 = fixedTools2.getMinimumSize(); Dimension d3 = new Dimension(d2.width, d.height + 4); fixedTools2.setPreferredSize(d3); fixedTools2.setMaximumSize(d3); // m_helpB.setPreferredSize(dP); // m_helpB.setMaximumSize(dP); // m_helpB.setSize(m_pointerB.getSize().width, // m_pointerB.getSize().height); toolBarPanel.add(fixedTools2, BorderLayout.WEST); // end modifications by Zerbetto m_stopB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { m_logPanel.statusMessage("@!@[KnowledgeFlow]|Attempting to stop all components..."); stopFlow(); m_logPanel.statusMessage("@!@[KnowledgeFlow]|OK."); } }); final Action helpAction = new AbstractAction("Help") { /** * */ private static final long serialVersionUID = 3301809940717051925L; @Override public void actionPerformed(ActionEvent e) { popupHelp(); } }; KeyStroke helpKey = KeyStroke.getKeyStroke(KeyEvent.VK_H, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("Help", helpAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(helpKey, "Help"); m_helpB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { helpAction.actionPerformed(ae); } }); m_templatesB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { createTemplateMenuPopup(); } }); m_templatesB.setEnabled(BeansProperties.TEMPLATE_PATHS.size() > 0); final Action togglePerspectivesAction = new AbstractAction("Toggle perspectives") { /** * */ private static final long serialVersionUID = 5394622655137498495L; @Override public void actionPerformed(ActionEvent e) { if (m_firstUserComponentOpp) { installWindowListenerForSavingUserStuff(); m_firstUserComponentOpp = false; } if (!Utils.getDontShowDialog("weka.gui.beans.KnowledgeFlow.PerspectiveInfo")) { JCheckBox dontShow = new JCheckBox("Do not show this message again"); Object[] stuff = new Object[2]; stuff[0] = "Perspectives are environments that take over the\n" + "Knowledge Flow UI and provide major additional functionality.\n" + "Many perspectives will operate on a set of instances. Instances\n" + "Can be sent to a perspective by placing a DataSource on the\n" + "layout canvas, configuring it and then selecting \"Send to perspective\"\n" + "from the contextual popup menu that appears when you right-click on\n" + "it. Several perspectives are built in to the Knowledge Flow, others\n" + "can be installed via the package manager.\n"; stuff[1] = dontShow; JOptionPane.showMessageDialog(KnowledgeFlowApp.this, stuff, "Perspective information", JOptionPane.OK_OPTION); if (dontShow.isSelected()) { try { Utils.setDontShowDialog("weka.gui.beans.KnowledgeFlow.PerspectiveInfo"); } catch (Exception ex) { // quietly ignore } } } if (m_configAndPerspectivesVisible) { KnowledgeFlowApp.this.remove(m_configAndPerspectives); m_configAndPerspectivesVisible = false; } else { KnowledgeFlowApp.this.add(m_configAndPerspectives, BorderLayout.NORTH); m_configAndPerspectivesVisible = true; } revalidate(); repaint(); notifyIsDirty(); } }; KeyStroke togglePerspectivesKey = KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK); MainKFPerspective.this.getActionMap().put("Toggle perspectives", togglePerspectivesAction); MainKFPerspective.this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(togglePerspectivesKey, "Toggle perspectives"); m_togglePerspectivesB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { togglePerspectivesAction.actionPerformed(e); } }); final int standard_toolset = 0; final int wrapper_toolset = 1; int toolBarType = standard_toolset; DefaultMutableTreeNode jtreeRoot = new DefaultMutableTreeNode("Weka"); // set up wrapper toolsets for (int i = 0; i < TOOLBARS.size(); i++) { Vector<?> tempBarSpecs = TOOLBARS.elementAt(i); // name for the tool bar String tempToolSetName = (String) tempBarSpecs.elementAt(0); DefaultMutableTreeNode subTreeNode = new InvisibleNode(tempToolSetName); jtreeRoot.add(subTreeNode); // Used for weka leaf packages // Box singletonHolderPanel = null; // name of the bean component to handle this class of weka algorithms String tempBeanCompName = (String) tempBarSpecs.elementAt(1); // the root package for weka algorithms String rootPackage = ""; weka.gui.HierarchyPropertyParser hpp = null; Hashtable<String, HierarchyPropertyParser> hpps = null; // Is this a wrapper toolbar? if (tempBeanCompName.compareTo("null") != 0) { toolBarType = wrapper_toolset; rootPackage = (String) tempBarSpecs.elementAt(2); // hpp = (weka.gui.HierarchyPropertyParser)tempBarSpecs.elementAt(3); hpps = (Hashtable<String, HierarchyPropertyParser>) tempBarSpecs.elementAt(3); try { // modifications by Zerbetto // Beans.instantiate(null, tempBeanCompName); WekaPackageClassLoaderManager.objectForName(tempBeanCompName); //Beans.instantiate(this.getClass().getClassLoader(), // tempBeanCompName); // end modifications by Zerbetto } catch (Exception ex) { // ignore weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "[KnowledgeFlow] Failed to instantiate: " + tempBeanCompName); break; } } else { toolBarType = standard_toolset; } // a toolbar to hold buttons---one for each algorithm // JToolBar tempToolBar = new JToolBar(); // System.err.println(tempToolBar.getLayout()); // tempToolBar.setLayout(new FlowLayout()); int z = 2; if (toolBarType == wrapper_toolset) { Enumeration<String> enm = hpps.keys(); while (enm.hasMoreElements()) { String root = enm.nextElement(); hpp = hpps.get(root); if (!hpp.goTo(rootPackage)) { } String[] primaryPackages = hpp.childrenValues(); for (String primaryPackage : primaryPackages) { hpp.goToChild(primaryPackage); // check to see if this is a leaf - if so then there are no // sub packages if (hpp.isLeafReached()) { /* * if (singletonHolderPanel == null) { singletonHolderPanel = * Box.createHorizontalBox(); * singletonHolderPanel.setBorder(javax * .swing.BorderFactory.createTitledBorder( tempToolSetName)); } */ String algName = hpp.fullValue(); // -- tempBean = instantiateToolBarBean(true, tempBeanCompName, // algName); Object visibleCheck = instantiateBean((toolBarType == wrapper_toolset), tempBeanCompName, algName); // if (tempBean != null) { if (visibleCheck != null) { // tempToolBar.add(tempBean); // singletonHolderPanel.add(tempBean); /* * Object visibleCheck = instantiateBean((toolBarType == * wrapper_toolset), tempBeanCompName, algName); */ if (visibleCheck instanceof BeanContextChild) { m_bcSupport.add(visibleCheck); } ImageIcon scaledForTree = null; if (visibleCheck instanceof Visible) { BeanVisual bv = ((Visible) visibleCheck).getVisual(); if (bv != null) { scaledForTree = new ImageIcon(bv.scale(0.33)); // m_iconLookup.put(algName, scaledForTree); } } // try and get a tool tip String toolTip = ""; try { Object wrappedA = WekaPackageClassLoaderManager.objectForName(algName); // Object wrappedA = Class.forName(algName).newInstance(); toolTip = getGlobalInfo(wrappedA); } catch (Exception ex) { } JTreeLeafDetails leafData = new JTreeLeafDetails(tempBeanCompName, algName, scaledForTree); if (toolTip != null && toolTip.length() > 0) { leafData.setToolTipText(toolTip); } DefaultMutableTreeNode leafAlgo = new InvisibleNode(leafData); subTreeNode.add(leafAlgo); m_nodeTextIndex.put( algName.toLowerCase() + " " + (toolTip != null ? toolTip.toLowerCase() + " " : ""), leafAlgo); } hpp.goToParent(); } else { // make a titledborder JPanel to hold all the schemes in this // package // JPanel holderPanel = new JPanel(); /* * Box holderPanel = Box.createHorizontalBox(); * holderPanel.setBorder * (javax.swing.BorderFactory.createTitledBorder(userPrefix + * primaryPackages[kk])); */ DefaultMutableTreeNode firstLevelOfMainAlgoType = new InvisibleNode(primaryPackage); subTreeNode.add(firstLevelOfMainAlgoType); // processPackage(holderPanel, tempBeanCompName, hpp, // firstLevelOfMainAlgoType); processPackage(tempBeanCompName, hpp, firstLevelOfMainAlgoType, m_nodeTextIndex); // tempToolBar.add(holderPanel); } } /* * if (singletonHolderPanel != null) { * tempToolBar.add(singletonHolderPanel); singletonHolderPanel = * null; } */ } } else { /* * Box holderPanel = Box.createHorizontalBox(); * holderPanel.setBorder(javax.swing.BorderFactory.createTitledBorder( * tempToolSetName)); */ for (int j = z; j < tempBarSpecs.size(); j++) { tempBeanCompName = (String) tempBarSpecs.elementAt(j); Object visibleCheck = instantiateBean((toolBarType == wrapper_toolset), tempBeanCompName, ""); /* * -- tempBean = instantiateToolBarBean((toolBarType == * wrapper_toolset), tempBeanCompName, ""); */ // if (tempBean != null) { if (visibleCheck != null) { // set tool tip text (if any) // setToolTipText(tempBean) // holderPanel.add(tempBean); String treeName = tempBeanCompName; if (treeName.lastIndexOf('.') > 0) { treeName = treeName.substring(treeName.lastIndexOf('.') + 1, treeName.length()); } /* * Object visibleCheck = instantiateBean((toolBarType == * wrapper_toolset), tempBeanCompName, ""); */ if (visibleCheck instanceof BeanContextChild) { m_bcSupport.add(visibleCheck); } ImageIcon scaledForTree = null; if (visibleCheck instanceof Visible) { BeanVisual bv = ((Visible) visibleCheck).getVisual(); if (bv != null) { scaledForTree = new ImageIcon(bv.scale(0.33)); // m_iconLookup.put(treeName, scaledForTree); } } String tipText = null; tipText = getGlobalInfo(visibleCheck); // check for annotation and let this override any global info tool // tip Class<?> compClass = visibleCheck.getClass(); Annotation[] annotations = compClass.getDeclaredAnnotations(); String category = null; DefaultMutableTreeNode targetFolder = null; for (Annotation ann : annotations) { if (ann instanceof KFStep) { tipText = "<html><font color=blue>" + ((KFStep) ann).toolTipText() + "</font></html>"; category = ((KFStep) ann).category(); // Does this category already exist? Enumeration<TreeNode> children = jtreeRoot.children(); while (children.hasMoreElements()) { Object child = children.nextElement(); if (child instanceof DefaultMutableTreeNode) { if (((DefaultMutableTreeNode) child).getUserObject().toString() .equals(category)) { targetFolder = (DefaultMutableTreeNode) child; break; } } } break; } } JTreeLeafDetails leafData = new JTreeLeafDetails(tempBeanCompName, "", scaledForTree); if (tipText != null) { leafData.setToolTipText(tipText); } DefaultMutableTreeNode fixedLeafNode = new InvisibleNode(leafData); if (targetFolder != null) { targetFolder.add(fixedLeafNode); } else { subTreeNode.add(fixedLeafNode); } m_nodeTextIndex.put(tempBeanCompName.toLowerCase() + " " + (tipText != null ? tipText.toLowerCase() : ""), fixedLeafNode); } } // tempToolBar.add(holderPanel); } // JScrollPane tempJScrollPane = // createScrollPaneForToolBar(tempToolBar); // ok, now create tabbed pane to hold this toolbar // m_toolBars.addTab(tempToolSetName, null, tempJScrollPane, // tempToolSetName); } // / ---- // TODO Prescan for bean plugins and only create user tree node if there // are actually some beans (rather than just all perspectives) // Any plugin components to process? if (BeansProperties.BEAN_PLUGINS_PROPERTIES != null && BeansProperties.BEAN_PLUGINS_PROPERTIES.size() > 0) { boolean pluginBeans = false; DefaultMutableTreeNode userSubTree = null; for (int i = 0; i < BeansProperties.BEAN_PLUGINS_PROPERTIES.size(); i++) { Properties tempP = BeansProperties.BEAN_PLUGINS_PROPERTIES.get(i); String components = tempP.getProperty("weka.gui.beans.KnowledgeFlow.Plugins"); if (components != null && components.length() > 0) { StringTokenizer st2 = new StringTokenizer(components, ", "); while (st2.hasMoreTokens()) { String tempBeanCompName = st2.nextToken().trim(); String treeName = tempBeanCompName; if (treeName.lastIndexOf('.') > 0) { treeName = treeName.substring(treeName.lastIndexOf('.') + 1, treeName.length()); } // tempBean = instantiateToolBarBean(false, tempBeanCompName, ""); /* * if (m_pluginsToolBar == null) { // need to create the plugins * tab and toolbar setUpPluginsToolBar(); } * m_pluginsBoxPanel.add(tempBean); */ Object visibleCheck = instantiateBean((toolBarType == wrapper_toolset), tempBeanCompName, ""); if (visibleCheck instanceof BeanContextChild) { m_bcSupport.add(visibleCheck); } ImageIcon scaledForTree = null; if (visibleCheck instanceof Visible) { BeanVisual bv = ((Visible) visibleCheck).getVisual(); if (bv != null) { scaledForTree = new ImageIcon(bv.scale(0.33)); // m_iconLookup.put(tempBeanCompName, scaledForTree); } } String tipText = null; tipText = getGlobalInfo(visibleCheck); // check for annotation Class<?> compClass = visibleCheck.getClass(); Annotation[] annotations = compClass.getDeclaredAnnotations(); DefaultMutableTreeNode targetFolder = null; String category = null; for (Annotation ann : annotations) { if (ann instanceof KFStep) { category = ((KFStep) ann).category(); tipText = "<html><font color=red>" + ((KFStep) ann).toolTipText() + "</font></html>"; // Does this category already exist? Enumeration<TreeNode> children = jtreeRoot.children(); while (children.hasMoreElements()) { Object child = children.nextElement(); if (child instanceof DefaultMutableTreeNode) { if (((DefaultMutableTreeNode) child).getUserObject().toString() .equals(category)) { targetFolder = (DefaultMutableTreeNode) child; break; } } } break; } } JTreeLeafDetails leafData = new JTreeLeafDetails(tempBeanCompName, "", scaledForTree); if (tipText != null) { leafData.setToolTipText(tipText); } DefaultMutableTreeNode pluginLeaf = new InvisibleNode(leafData); m_nodeTextIndex.put(tempBeanCompName.toLowerCase() + (tipText != null ? " " + tipText.toLowerCase() : ""), pluginLeaf); if (targetFolder != null) { targetFolder.add(pluginLeaf); } else if (category != null) { // make a new category folder DefaultMutableTreeNode newCategoryNode = new InvisibleNode(category); jtreeRoot.add(newCategoryNode); newCategoryNode.add(pluginLeaf); } else { // add to the default "Plugins" folder if (!pluginBeans) { // make the Plugins tree node entry userSubTree = new InvisibleNode("Plugins"); jtreeRoot.add(userSubTree); pluginBeans = true; } userSubTree.add(pluginLeaf); } } } // check for perspectives String perspectives = tempP.getProperty(("weka.gui.beans.KnowledgeFlow.Perspectives")); if (perspectives != null && perspectives.length() > 0) { StringTokenizer st2 = new StringTokenizer(perspectives, ","); while (st2.hasMoreTokens()) { String className = st2.nextToken(); try { if (PluginManager.isInDisabledList(className)) { continue; } Object p = WekaPackageClassLoaderManager.objectForName(className); // Object p = Class.forName(className).newInstance(); if (p instanceof KFPerspective && p instanceof JPanel) { String title = ((KFPerspective) p).getPerspectiveTitle(); weka.core.logging.Logger.log(weka.core.logging.Logger.Level.INFO, "[KnowledgeFlow] loaded perspective: " + title); m_pluginPerspectiveLookup.put(className, title); // not selected as part of the users set of perspectives // yet... ((KFPerspective) p).setLoaded(false); // check to see if user has selected to use this perspective if (BeansProperties.VISIBLE_PERSPECTIVES.contains(className)) { // add to the perspective cache. After processing // all plugins we will iterate over the sorted // VISIBLE_PERSPECTIVES in order to add them // to the toolbar in consistent sorted order // ((KFPerspective)p).setMainKFPerspective(m_mainKFPerspective); m_perspectiveCache.put(className, (KFPerspective) p); } } } catch (Exception ex) { if (m_logPanel != null) { m_logPanel.logMessage("[KnowledgeFlow] WARNING: " + "unable to instantiate perspective \"" + className + "\""); ex.printStackTrace(); } else { System.err.println("[KnowledgeFlow] WARNING: " + "unable to instantiate perspective \"" + className + "\""); ex.printStackTrace(); } } } } } } m_togglePerspectivesB.setEnabled(m_pluginPerspectiveLookup.keySet().size() > 0); // toolBarPanel.add(m_toolBars, BorderLayout.CENTER); // add(m_toolBars, BorderLayout.NORTH); add(toolBarPanel, BorderLayout.NORTH); InvisibleTreeModel model = new InvisibleTreeModel(jtreeRoot);// new // DefaultTreeModel(jtreeRoot); model.activateFilter(true); // subclass JTree so that tool tips can be displayed for leaves (if // necessary) m_componentTree = new JTree(model) { /** * */ private static final long serialVersionUID = 6628795889296634120L; @Override public String getToolTipText(MouseEvent e) { if ((getRowForLocation(e.getX(), e.getY())) == -1) { return null; } TreePath currPath = getPathForLocation(e.getX(), e.getY()); if (currPath.getLastPathComponent() instanceof DefaultMutableTreeNode) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) currPath.getLastPathComponent(); if (node.isLeaf()) { JTreeLeafDetails leaf = (JTreeLeafDetails) node.getUserObject(); return leaf.getToolTipText(); } } return null; } }; m_componentTree.setEnabled(true); m_componentTree.setToolTipText(""); m_componentTree.setRootVisible(false); m_componentTree.setShowsRootHandles(true); m_componentTree.setCellRenderer(new BeanIconRenderer()); DefaultTreeSelectionModel selectionModel = new DefaultTreeSelectionModel(); selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); m_componentTree.setSelectionModel(selectionModel); m_componentTree.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (((e.getModifiers() & InputEvent.BUTTON1_MASK) != InputEvent.BUTTON1_MASK) || e.isAltDown()) { boolean clearSelection = true; if (clearSelection) { // right click cancels selected component m_toolBarBean = null; m_mode = NONE; KnowledgeFlowApp.this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); m_componentTree.clearSelection(); } } TreePath p = m_componentTree.getSelectionPath(); if (p != null) { if (p.getLastPathComponent() instanceof DefaultMutableTreeNode) { DefaultMutableTreeNode tNode = (DefaultMutableTreeNode) p.getLastPathComponent(); if (tNode.isLeaf()) { // System.err.println("Selected : " + // tNode.getUserObject().toString()); Object userObject = tNode.getUserObject(); if (userObject instanceof JTreeLeafDetails) { if ((e.getModifiers() & InputEvent.SHIFT_MASK) != 0 && ((JTreeLeafDetails) userObject).isMetaBean()) { if (m_firstUserComponentOpp) { installWindowListenerForSavingUserStuff(); m_firstUserComponentOpp = false; } Vector<Object> toRemove = ((JTreeLeafDetails) userObject).getMetaBean(); DefaultTreeModel model = (DefaultTreeModel) m_componentTree.getModel(); MutableTreeNode userRoot = (MutableTreeNode) tNode.getParent(); // The "User" folder model.removeNodeFromParent(tNode); m_userComponents.remove(toRemove); if (m_userComponents.size() == 0) { model.removeNodeFromParent(userRoot); m_userCompNode = null; } } else { ((JTreeLeafDetails) userObject).instantiateBean(); } } } } } } }); } public MainKFPerspective() { setLayout(new BorderLayout()); setUpToolsAndJTree(); JScrollPane treeView = new JScrollPane(m_componentTree); JPanel treeHolder = new JPanel(); treeHolder.setLayout(new BorderLayout()); treeHolder.setBorder(BorderFactory.createTitledBorder("Design")); treeHolder.add(treeView, BorderLayout.CENTER); final JTextField searchField = new JTextField(); treeHolder.add(searchField, BorderLayout.NORTH); searchField.setToolTipText("Search (clear field to reset)"); searchField.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { String searchTerm = searchField.getText(); List<DefaultMutableTreeNode> nonhits = new ArrayList<DefaultMutableTreeNode>(); List<DefaultMutableTreeNode> hits = new ArrayList<DefaultMutableTreeNode>(); DefaultTreeModel model = (DefaultTreeModel) m_componentTree.getModel(); model.reload(); // collapse all nodes first for (Map.Entry<String, DefaultMutableTreeNode> entry : m_nodeTextIndex.entrySet()) { if (entry.getValue() instanceof InvisibleNode) { ((InvisibleNode) entry.getValue()).setVisible(true); } if (searchTerm != null && searchTerm.length() > 0) { if (entry.getKey().contains(searchTerm.toLowerCase())) { hits.add(entry.getValue()); } else { nonhits.add(entry.getValue()); } } } if (searchTerm == null || searchTerm.length() == 0) { model.reload(); // just reset everything } // if we have some hits then set all the non-hits to invisible if (hits.size() > 0) { for (DefaultMutableTreeNode h : nonhits) { if (h instanceof InvisibleNode) { ((InvisibleNode) h).setVisible(false); } } model.reload(); // collapse all the nodes first // expand all the hits for (DefaultMutableTreeNode h : hits) { TreeNode[] path = model.getPathToRoot(h); TreePath tpath = new TreePath(path); tpath = tpath.getParentPath(); m_componentTree.expandPath(tpath); } } } }); // m_perspectiveHolder.add(treeHolder, BorderLayout.WEST); JSplitPane p2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeHolder, m_flowTabs); p2.setOneTouchExpandable(true); add(p2, BorderLayout.CENTER); Dimension d = treeView.getPreferredSize(); d = new Dimension((int) (d.getWidth() * 1.5), (int) d.getHeight()); treeView.setPreferredSize(d); treeView.setMinimumSize(d); m_flowTabs.addChangeListener(new ChangeListener() { // This method is called whenever the selected tab changes @Override public void stateChanged(ChangeEvent evt) { // Get current tab int sel = m_flowTabs.getSelectedIndex(); setActiveTab(sel); } }); } public synchronized void removeTab(int tabIndex) { if (tabIndex < 0 || tabIndex >= getNumTabs()) { return; } if (m_editedList.get(tabIndex)) { // prompt for save String tabTitle = m_flowTabs.getTitleAt(tabIndex); String message = "\"" + tabTitle + "\" has been modified. Save changes " + "before closing?"; int result = JOptionPane.showConfirmDialog(KnowledgeFlowApp.this, message, "Save changes", JOptionPane.YES_NO_CANCEL_OPTION); if (result == JOptionPane.YES_OPTION) { saveLayout(tabIndex, false); } else if (result == JOptionPane.CANCEL_OPTION) { return; } } BeanLayout bl = m_beanLayouts.get(tabIndex); BeanInstance.removeBeanInstances(bl, tabIndex); BeanConnection.removeConnectionList(tabIndex); m_beanLayouts.remove(tabIndex); m_zoomSettings.remove(tabIndex); m_logPanels.remove(tabIndex); m_editedList.remove(tabIndex); m_environmentSettings.remove(tabIndex); m_selectedBeans.remove(tabIndex); bl = null; m_flowTabs.remove(tabIndex); if (getCurrentTabIndex() < 0) { m_beanLayout = null; m_logPanel = null; m_saveB.setEnabled(false); } } public synchronized void addTab(String tabTitle) { // new beans for this tab BeanInstance.addBeanInstances(new Vector<Object>(), null); // new connections for this tab BeanConnection.addConnections(new Vector<BeanConnection>()); JPanel p1 = new JPanel(); p1.setLayout(new BorderLayout()); /* * p1.setBorder(javax.swing.BorderFactory.createCompoundBorder( * javax.swing.BorderFactory. createTitledBorder("Knowledge Flow Layout"), * javax.swing.BorderFactory.createEmptyBorder(0, 5, 5, 5) )); */ BeanLayout tabBeanLayout = new BeanLayout(); final JScrollPane js = new JScrollPane(tabBeanLayout); p1.add(js, BorderLayout.CENTER); js.getVerticalScrollBar().setUnitIncrement(m_ScrollBarIncrementLayout); js.getHorizontalScrollBar().setUnitIncrement(m_ScrollBarIncrementLayout); configureBeanLayout(tabBeanLayout); m_beanLayouts.add(tabBeanLayout); tabBeanLayout.setSize(m_FlowWidth, m_FlowHeight); Dimension d = tabBeanLayout.getPreferredSize(); tabBeanLayout.setMinimumSize(d); // tabBeanLayout.setMaximumSize(d); tabBeanLayout.setPreferredSize(d); m_zoomSettings.add(new Integer(100)); KFLogPanel tabLogPanel = new KFLogPanel(); setUpLogPanel(tabLogPanel); Dimension d2 = new Dimension(100, 170); tabLogPanel.setPreferredSize(d2); tabLogPanel.setMinimumSize(d2); m_logPanels.add(tabLogPanel); m_environmentSettings.add(new Environment()); m_filePaths.add(new File("-NONE-")); JSplitPane p2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT, p1, tabLogPanel); p2.setOneTouchExpandable(true); // p2.setDividerLocation(500); p2.setDividerLocation(0.7); p2.setResizeWeight(1.0); JPanel splitHolder = new JPanel(); splitHolder.setLayout(new BorderLayout()); splitHolder.add(p2, BorderLayout.CENTER); // add(splitHolder, BorderLayout.CENTER); m_editedList.add(new Boolean(false)); m_executingList.add(new Boolean(false)); m_executionThreads.add((RunThread) null); m_selectedBeans.add(new Vector<Object>()); m_undoBufferList.add(new Stack<File>()); m_flowTabs.addTab(tabTitle, splitHolder); int tabIndex = getNumTabs() - 1; m_flowTabs.setTabComponentAt(tabIndex, new CloseableTabTitle(m_flowTabs)); setActiveTab(getNumTabs() - 1); m_saveB.setEnabled(true); } } private class CloseableTabTitle extends JPanel { /** * */ private static final long serialVersionUID = -6844232025394346426L; private final JTabbedPane m_enclosingPane; private JLabel m_tabLabel; private TabButton m_tabButton; public CloseableTabTitle(final JTabbedPane pane) { super(new FlowLayout(FlowLayout.LEFT, 0, 0)); m_enclosingPane = pane; setOpaque(false); setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); // read the title from the JTabbedPane m_tabLabel = new JLabel() { /** * */ private static final long serialVersionUID = 8515052190461050324L; @Override public String getText() { int index = m_enclosingPane.indexOfTabComponent(CloseableTabTitle.this); if (index >= 0) { return m_enclosingPane.getTitleAt(index); } return null; } }; add(m_tabLabel); m_tabLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); m_tabButton = new TabButton(); add(m_tabButton); } public void setBold(boolean bold) { m_tabLabel.setEnabled(bold); } public void setButtonEnabled(boolean enabled) { m_tabButton.setEnabled(enabled); } private class TabButton extends JButton implements ActionListener { /** * */ private static final long serialVersionUID = -4915800749132175968L; public TabButton() { int size = 17; setPreferredSize(new Dimension(size, size)); setToolTipText("close this tab"); // Make the button looks the same for all Laf's setUI(new BasicButtonUI()); // Make it transparent setContentAreaFilled(false); // No need to be focusable setFocusable(false); setBorder(BorderFactory.createEtchedBorder()); setBorderPainted(false); // Making nice rollover effect // we use the same listener for all buttons addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { Component component = e.getComponent(); if (component instanceof AbstractButton) { AbstractButton button = (AbstractButton) component; button.setBorderPainted(true); int i = m_enclosingPane.indexOfTabComponent(CloseableTabTitle.this); if (i == m_mainKFPerspective.getCurrentTabIndex()) { button.setToolTipText("close this tab (Ctrl+W)"); } else { button.setToolTipText("close this tab"); } } } @Override public void mouseExited(MouseEvent e) { Component component = e.getComponent(); if (component instanceof AbstractButton) { AbstractButton button = (AbstractButton) component; button.setBorderPainted(false); } } }); setRolloverEnabled(true); // Close the proper tab by clicking the button addActionListener(this); } @Override public void actionPerformed(ActionEvent e) { int i = m_enclosingPane.indexOfTabComponent(CloseableTabTitle.this); if (i >= 0 && getAllowMultipleTabs()) { // m_enclosingPane.remove(i); m_mainKFPerspective.removeTab(i); } } // we don't want to update UI for this button @Override public void updateUI() { } // paint the cross @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g.create(); // shift the image for pressed buttons if (getModel().isPressed()) { g2.translate(1, 1); } g2.setStroke(new BasicStroke(2)); g2.setColor(Color.BLACK); if (!isEnabled()) { g2.setColor(Color.GRAY); } if (getModel().isRollover()) { g2.setColor(Color.MAGENTA); } int delta = 6; g2.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1); g2.drawLine(getWidth() - delta - 1, delta, delta, getHeight() - delta - 1); g2.dispose(); } } } // Used for measuring and splitting icon labels // over multiple lines FontMetrics m_fontM; // constants for operations in progress protected static final int NONE = 0; protected static final int MOVING = 1; protected static final int CONNECTING = 2; protected static final int ADDING = 3; protected static final int SELECTING = 4; protected static final int PASTING = 5; // which operation is in progress private int m_mode = NONE; /** the extension for the user components, when serialized to XML */ protected final static String USERCOMPONENTS_XML_EXTENSION = ".xml"; /** * Holds the selected toolbar bean */ private Object m_toolBarBean; /** Snap-to-grid spacing */ private final int m_gridSpacing = 40; /** Number of untitled tabs so far */ protected int m_untitledCount = 1; /** * The layout area */ private BeanLayout m_beanLayout = null;// new BeanLayout(); private int m_layoutZoom = 100; /** Whether to allow more than one tab or not */ private boolean m_allowMultipleTabs = true; private final Vector<Object> m_userComponents = new Vector<Object>(); private boolean m_firstUserComponentOpp = true; protected JButton m_pointerB; protected JButton m_saveB; protected JButton m_saveBB; protected JButton m_loadB; protected JButton m_stopB; protected JButton m_playB; protected JButton m_playBB; protected JButton m_helpB; protected JButton m_newB; protected JButton m_togglePerspectivesB; protected JButton m_templatesB; protected JButton m_groupB; protected JButton m_cutB; protected JButton m_copyB; protected JButton m_pasteB; protected JButton m_deleteB; protected JButton m_noteB; protected JButton m_selectAllB; protected JButton m_undoB; protected JButton m_zoomInB; protected JButton m_zoomOutB; protected JToggleButton m_snapToGridB; /** * Reference to bean being manipulated */ private BeanInstance m_editElement; /** * Event set descriptor for the bean being manipulated */ private EventSetDescriptor m_sourceEventSetDescriptor; /** * Used to record screen coordinates during move, select and connect * operations */ private int m_oldX, m_oldY; private int m_startX, m_startY; /** The file chooser for selecting layout files */ protected WekaFileChooser m_FileChooser = new WekaFileChooser(new File(System.getProperty("user.dir"))); protected class KFLogPanel extends LogPanel { /** * */ private static final long serialVersionUID = -2224509243343105276L; public synchronized void setMessageOnAll(boolean mainKFLine, String message) { for (String key : m_tableIndexes.keySet()) { if (!mainKFLine && key.equals("[KnowledgeFlow]")) { continue; } String tm = key + "|" + message; statusMessage(tm); } } } protected KFLogPanel m_logPanel = null; // new LogPanel();//new LogPanel(null, // true); /** Toolbar to hold the perspective buttons */ protected JToolBar m_perspectiveToolBar = new JToolBar(JToolBar.HORIZONTAL); /** Panel to hold the perspectives toolbar and config button */ protected JPanel m_configAndPerspectives; /** * Whether the perspectives toolbar is visible at present (will never be * visible if there are no plugin perspectives installed) */ protected boolean m_configAndPerspectivesVisible = true; /** * Button group to manage all perspective toggle buttons */ private final ButtonGroup m_perspectiveGroup = new ButtonGroup(); /** Component that holds the currently visible perspective */ protected JPanel m_perspectiveHolder; /** * Holds the list of currently loaded perspectives. Element at 0 is always the * main KF data mining flow perspective */ protected List<KFPerspective> m_perspectives = new ArrayList<KFPerspective>(); /** Thread for loading data for perspectives */ protected Thread m_perspectiveDataLoadThread = null; protected AttributeSelectionPanel m_perspectiveConfigurer; /** Shortcut to the main perspective */ protected MainKFPerspective m_mainKFPerspective; protected BeanContextSupport m_bcSupport = new BeanContextSupport(); /** the extension for the serialized setups (Java serialization) */ public final static String FILE_EXTENSION = ".kf"; /** the extension for the serialized setups (Java serialization) */ public final static String FILE_EXTENSION_XML = ".kfml"; /** * A filter to ensure only KnowledgeFlow files in binary format get shown in * the chooser */ protected FileFilter m_KfFilter = new ExtensionFileFilter(FILE_EXTENSION, "Binary KnowledgeFlow configuration files (*" + FILE_EXTENSION + ")"); /** * A filter to ensure only KnowledgeFlow files in KOML format get shown in the * chooser */ protected FileFilter m_KOMLFilter = new ExtensionFileFilter(KOML.FILE_EXTENSION + "kf", "XML KnowledgeFlow configuration files (*" + KOML.FILE_EXTENSION + "kf)"); /** * A filter to ensure only KnowledgeFlow files in XStream format get shown in * the chooser */ protected FileFilter m_XStreamFilter = new ExtensionFileFilter(XStream.FILE_EXTENSION + "kf", "XML KnowledgeFlow configuration files (*" + XStream.FILE_EXTENSION + "kf)"); /** * A filter to ensure only KnowledgeFlow layout files in XML format get shown * in the chooser */ protected FileFilter m_XMLFilter = new ExtensionFileFilter(FILE_EXTENSION_XML, "XML KnowledgeFlow layout files (*" + FILE_EXTENSION_XML + ")"); /** the scrollbar increment of the layout scrollpane */ protected int m_ScrollBarIncrementLayout = 20; /** the scrollbar increment of the components scrollpane */ protected int m_ScrollBarIncrementComponents = 50; /** the flow layout width */ protected int m_FlowWidth = 2560; /** the flow layout height */ protected int m_FlowHeight = 1440; /** the preferred file extension */ protected String m_PreferredExtension = FILE_EXTENSION; /** whether to store the user components in XML or in binary format */ protected boolean m_UserComponentsInXML = false; /** Environment variables for the current flow */ protected Environment m_flowEnvironment = new Environment(); /** Palette of components stored in a JTree */ protected JTree m_componentTree; /** The node of the JTree that holds "user" (metabean) components */ protected DefaultMutableTreeNode m_userCompNode; /** The clip board */ protected StringBuffer m_pasteBuffer; /** * Set the environment variables to use. NOTE: loading a new layout resets * back to the default set of variables * * @param env */ public void setEnvironment(Environment env) { m_flowEnvironment = env; setEnvironment(); } private void setEnvironment() { // pass m_flowEnvironment to all components // that implement EnvironmentHandler Vector<Object> beans = BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()); for (int i = 0; i < beans.size(); i++) { Object temp = ((BeanInstance) beans.elementAt(i)).getBean(); if (temp instanceof EnvironmentHandler) { ((EnvironmentHandler) temp).setEnvironment(m_flowEnvironment); } } } /** * Creates a new <code>KnowledgeFlowApp</code> instance. */ // modifications by Zerbetto // public KnowledgeFlowApp() { public KnowledgeFlowApp(boolean showFileMenu) { if (BeansProperties.BEAN_PROPERTIES == null) { loadProperties(); init(); } m_showFileMenu = showFileMenu; // end modifications by Zerbetto // Grab a fontmetrics object JWindow temp = new JWindow(); temp.setVisible(true); temp.getGraphics().setFont(new Font(null, Font.PLAIN, 9)); m_fontM = temp.getGraphics().getFontMetrics(); temp.setVisible(false); // some GUI defaults try { m_ScrollBarIncrementLayout = Integer.parseInt(BeansProperties.BEAN_PROPERTIES .getProperty("ScrollBarIncrementLayout", "" + m_ScrollBarIncrementLayout)); m_ScrollBarIncrementComponents = Integer.parseInt(BeansProperties.BEAN_PROPERTIES .getProperty("ScrollBarIncrementComponents", "" + m_ScrollBarIncrementComponents)); m_FlowWidth = Integer .parseInt(BeansProperties.BEAN_PROPERTIES.getProperty("FlowWidth", "" + m_FlowWidth)); m_FlowHeight = Integer .parseInt(BeansProperties.BEAN_PROPERTIES.getProperty("FlowHeight", "" + m_FlowHeight)); m_PreferredExtension = BeansProperties.BEAN_PROPERTIES.getProperty("PreferredExtension", m_PreferredExtension); m_UserComponentsInXML = Boolean.valueOf( BeansProperties.BEAN_PROPERTIES.getProperty("UserComponentsInXML", "" + m_UserComponentsInXML)) .booleanValue(); } catch (Exception ex) { ex.printStackTrace(); } // FileChooser m_FileChooser.addChoosableFileFilter(m_KfFilter); if (KOML.isPresent()) { m_FileChooser.addChoosableFileFilter(m_KOMLFilter); } if (XStream.isPresent()) { m_FileChooser.addChoosableFileFilter(m_XStreamFilter); } m_FileChooser.addChoosableFileFilter(m_XMLFilter); if (m_PreferredExtension.equals(FILE_EXTENSION_XML)) { m_FileChooser.setFileFilter(m_XMLFilter); } else if (KOML.isPresent() && m_PreferredExtension.equals(KOML.FILE_EXTENSION + "kf")) { m_FileChooser.setFileFilter(m_KOMLFilter); } else if (XStream.isPresent() && m_PreferredExtension.equals(XStream.FILE_EXTENSION + "kf")) { m_FileChooser.setFileFilter(m_XStreamFilter); } else { m_FileChooser.setFileFilter(m_KfFilter); } m_FileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); m_bcSupport.setDesignTime(true); m_perspectiveHolder = new JPanel(); m_perspectiveHolder.setLayout(new BorderLayout()); // TODO North will hold main perspective toggle buttons // WEST will hold JTree - perhaps not // CENTER will hold perspective /* * JPanel p2 = new JPanel(); p2.setLayout(new BorderLayout()); */ m_mainKFPerspective = new MainKFPerspective(); // m_perspectiveHolder.add(m_mainKFPerspective, BorderLayout.CENTER); m_perspectives.add(m_mainKFPerspective); // mainPanel.add(m_perspectiveHolder, BorderLayout.CENTER); setLayout(new BorderLayout()); add(m_perspectiveHolder, BorderLayout.CENTER); // setUpToolBars(p2); // setUpToolsAndJTree(m_mainKFPerspective); m_perspectiveHolder.add(m_mainKFPerspective, BorderLayout.CENTER); if (m_pluginPerspectiveLookup.size() > 0) { // add the main perspective first String titleM = m_mainKFPerspective.getPerspectiveTitle(); Icon icon = m_mainKFPerspective.getPerspectiveIcon(); JToggleButton tBut = new JToggleButton(titleM, icon, true); tBut.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { KFPerspective current = (KFPerspective) m_perspectiveHolder.getComponent(0); current.setActive(false); m_perspectiveHolder.remove(0); m_perspectiveHolder.add((JComponent) m_perspectives.get(0), BorderLayout.CENTER); m_perspectives.get(0).setActive(true); // KnowledgeFlowApp.this.invalidate(); KnowledgeFlowApp.this.revalidate(); KnowledgeFlowApp.this.repaint(); notifyIsDirty(); } }); m_perspectiveToolBar.add(tBut); m_perspectiveGroup.add(tBut); // set up the perspective toolbar toggle buttons // first load the perspectives list in sorted order (kf perspective // is always at index 0) setupUserPerspectives(); } if (m_pluginPerspectiveLookup.size() > 0) { m_configAndPerspectives = new JPanel(); m_configAndPerspectives.setLayout(new BorderLayout()); m_configAndPerspectives.add(m_perspectiveToolBar, BorderLayout.CENTER); try { Properties visible = Utils.readProperties(BeansProperties.VISIBLE_PERSPECTIVES_PROPERTIES_FILE); Enumeration<?> keys = visible.propertyNames(); if (keys.hasMoreElements()) { String toolBarIsVisible = visible .getProperty("weka.gui.beans.KnowledgeFlow.PerspectiveToolBarVisisble"); if (toolBarIsVisible != null && toolBarIsVisible.length() > 0) { m_configAndPerspectivesVisible = toolBarIsVisible.equalsIgnoreCase("yes"); } } } catch (Exception ex) { System.err.println("Problem reading visible perspectives property file"); ex.printStackTrace(); } // add the perspectives toolbar // does the user want it visible? if (m_configAndPerspectivesVisible) { add(m_configAndPerspectives, BorderLayout.NORTH); } JButton configB = new JButton(new ImageIcon(loadImage(BeanVisual.ICON_PATH + "cog.png"))); configB.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 1)); configB.setToolTipText("Enable/disable perspectives"); m_configAndPerspectives.add(configB, BorderLayout.WEST); configB.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (!Utils.getDontShowDialog("weka.gui.beans.KnowledgeFlow.PerspectiveInfo")) { JCheckBox dontShow = new JCheckBox("Do not show this message again"); Object[] stuff = new Object[2]; stuff[0] = "Perspectives are environments that take over the\n" + "Knowledge Flow UI and provide major additional functionality.\n" + "Many perspectives will operate on a set of instances. Instances\n" + "Can be sent to a perspective by placing a DataSource on the\n" + "layout canvas, configuring it and then selecting \"Send to perspective\"\n" + "from the contextual popup menu that appears when you right-click on\n" + "it. Several perspectives are built in to the Knowledge Flow, others\n" + "can be installed via the package manager.\n"; stuff[1] = dontShow; JOptionPane.showMessageDialog(KnowledgeFlowApp.this, stuff, "Perspective information", JOptionPane.OK_OPTION); if (dontShow.isSelected()) { try { Utils.setDontShowDialog("weka.gui.beans.KnowledgeFlow.PerspectiveInfo"); } catch (Exception ex) { // quietly ignore } } } popupPerspectiveConfigurer(); } }); } // set main perspective on all cached perspectives for (String pName : m_perspectiveCache.keySet()) { m_perspectiveCache.get(pName).setMainKFPerspective(m_mainKFPerspective); } loadUserComponents(); clearLayout(); // add an initial "Untitled" tab } /** * Gets the main knowledge flow perspective * * @return the main knowledge flow perspective */ public MainKFPerspective getMainPerspective() { return m_mainKFPerspective; } private void popupPerspectiveConfigurer() { if (m_perspectiveConfigurer == null) { m_perspectiveConfigurer = new AttributeSelectionPanel(true, true, true, true); } if (m_firstUserComponentOpp) { installWindowListenerForSavingUserStuff(); m_firstUserComponentOpp = false; } ArrayList<Attribute> atts = new ArrayList<Attribute>(); final ArrayList<String> pClasses = new ArrayList<String>(); SortedSet<String> sortedPerspectives = new TreeSet<String>(); for (String clName : m_pluginPerspectiveLookup.keySet()) { sortedPerspectives.add(clName); } for (String clName : sortedPerspectives) { pClasses.add(clName); String pName = m_pluginPerspectiveLookup.get(clName); atts.add(new Attribute(pName)); } Instances perspectiveInstances = new Instances("Perspectives", atts, 1); boolean[] selectedPerspectives = new boolean[perspectiveInstances.numAttributes()]; for (String selected : BeansProperties.VISIBLE_PERSPECTIVES) { String pName = m_pluginPerspectiveLookup.get(selected); // check here - just in case the user has uninstalled/deleted a plugin // perspective since the last time that the user-selected visible // perspectives // list was written out to the props file if (pName != null) { int index = perspectiveInstances.attribute(pName).index(); selectedPerspectives[index] = true; } } m_perspectiveConfigurer.setInstances(perspectiveInstances); try { m_perspectiveConfigurer.setSelectedAttributes(selectedPerspectives); } catch (Exception ex) { ex.printStackTrace(); return; } final JDialog d = new JDialog((JFrame) KnowledgeFlowApp.this.getTopLevelAncestor(), "Manage Perspectives", ModalityType.DOCUMENT_MODAL); d.setLayout(new BorderLayout()); JPanel holder = new JPanel(); holder.setLayout(new BorderLayout()); holder.add(m_perspectiveConfigurer, BorderLayout.CENTER); JButton okBut = new JButton("OK"); JButton cancelBut = new JButton("Cancel"); JPanel butHolder = new JPanel(); butHolder.setLayout(new GridLayout(1, 2)); butHolder.add(okBut); butHolder.add(cancelBut); holder.add(butHolder, BorderLayout.SOUTH); okBut.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { BeansProperties.VISIBLE_PERSPECTIVES = new TreeSet<String>(); int[] selected = m_perspectiveConfigurer.getSelectedAttributes(); for (int element : selected) { String selectedClassName = pClasses.get(element); // first check to see if it's in the cache already if (m_perspectiveCache.get(selectedClassName) == null) { // need to instantiate and add to the cache try { Object p = WekaPackageClassLoaderManager.objectForName(selectedClassName); // Object p = Class.forName(selectedClassName).newInstance(); if (p instanceof KFPerspective && p instanceof JPanel) { String title = ((KFPerspective) p).getPerspectiveTitle(); weka.core.logging.Logger.log(weka.core.logging.Logger.Level.INFO, "[KnowledgeFlow] loaded perspective: " + title); ((KFPerspective) p).setLoaded(true); ((KFPerspective) p).setMainKFPerspective(m_mainKFPerspective); m_perspectiveCache.put(selectedClassName, (KFPerspective) p); } } catch (Exception ex) { ex.printStackTrace(); } } BeansProperties.VISIBLE_PERSPECTIVES.add(selectedClassName); } setupUserPerspectives(); d.dispose(); } }); cancelBut.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { d.dispose(); } }); d.getContentPane().add(holder, BorderLayout.CENTER); /* * d.addWindowListener(new java.awt.event.WindowAdapter() { public void * windowClosing(java.awt.event.WindowEvent e) { * * * d.dispose(); } }); */ d.pack(); d.setLocationRelativeTo(SwingUtilities.getWindowAncestor(this)); d.setVisible(true); } private void setupUserPerspectives() { // first clear the toolbar for (int i = m_perspectiveToolBar.getComponentCount() - 1; i > 0; i--) { m_perspectiveToolBar.remove(i); m_perspectives.remove(i); } int index = 1; for (String c : BeansProperties.VISIBLE_PERSPECTIVES) { KFPerspective toAdd = m_perspectiveCache.get(c); if (toAdd instanceof JComponent) { toAdd.setLoaded(true); m_perspectives.add(toAdd); String titleM = toAdd.getPerspectiveTitle(); Icon icon = toAdd.getPerspectiveIcon(); JToggleButton tBut = null; if (icon != null) { tBut = new JToggleButton(titleM, icon, false); } else { tBut = new JToggleButton(titleM, false); } tBut.setToolTipText(toAdd.getPerspectiveTipText()); final int theIndex = index; tBut.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setActivePerspective(theIndex); } }); m_perspectiveToolBar.add(tBut); m_perspectiveGroup.add(tBut); index++; } } KFPerspective current = (KFPerspective) m_perspectiveHolder.getComponent(0); if (current != m_mainKFPerspective) { current.setActive(false); m_perspectiveHolder.remove(0); m_perspectiveHolder.add(m_mainKFPerspective); ((JToggleButton) m_perspectiveToolBar.getComponent(0)).setSelected(true); } revalidate(); repaint(); notifyIsDirty(); } protected void setActivePerspective(int theIndex) { if (theIndex < 0 || theIndex > m_perspectives.size() - 1) { return; } KFPerspective current = (KFPerspective) m_perspectiveHolder.getComponent(0); current.setActive(false); m_perspectiveHolder.remove(0); m_perspectiveHolder.add((JComponent) m_perspectives.get(theIndex), BorderLayout.CENTER); m_perspectives.get(theIndex).setActive(true); ((JToggleButton) m_perspectiveToolBar.getComponent(theIndex)).setSelected(true); // KnowledgeFlowApp.this.invalidate(); KnowledgeFlowApp.this.revalidate(); KnowledgeFlowApp.this.repaint(); notifyIsDirty(); } private void snapSelectedToGrid() { Vector<Object> v = m_mainKFPerspective.getSelectedBeans(); if (v.size() > 0) { for (int i = 0; i < v.size(); i++) { BeanInstance b = (BeanInstance) v.get(i); // if (!(b.getBean() instanceof Note)) { int x = b.getX(); int y = b.getY(); b.setXY(snapToGrid(x), snapToGrid(y)); // } } revalidate(); m_beanLayout.repaint(); notifyIsDirty(); m_mainKFPerspective.setEditedStatus(true); } } private int snapToGrid(int val) { int r = val % m_gridSpacing; val /= m_gridSpacing; if (r > (m_gridSpacing / 2)) { val++; } val *= m_gridSpacing; return val; } private void configureBeanLayout(final BeanLayout layout) { layout.setLayout(null); // handle mouse events layout.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent me) { layout.requestFocusInWindow(); double z = m_layoutZoom / 100.0; double px = me.getX(); double py = me.getY(); py /= z; px /= z; if (m_toolBarBean == null) { if (((me.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) && m_mode == NONE) { /* * BeanInstance bi = BeanInstance.findInstance(me.getPoint(), * m_mainKFPerspective.getCurrentTabIndex()); */ BeanInstance bi = BeanInstance.findInstance(new Point((int) px, (int) py), m_mainKFPerspective.getCurrentTabIndex()); JComponent bc = null; if (bi != null) { bc = (JComponent) (bi.getBean()); } if (bc != null /* && (bc instanceof Visible) */) { m_editElement = bi; /* * m_oldX = me.getX(); m_oldY = me.getY(); */ m_oldX = (int) px; m_oldY = (int) py; m_mode = MOVING; } if (m_mode != MOVING) { m_mode = SELECTING; /* * m_oldX = me.getX(); m_oldY = me.getY(); */ m_oldX = (int) px; m_oldY = (int) py; m_startX = m_oldX; m_startY = m_oldY; Graphics2D gx = (Graphics2D) layout.getGraphics(); gx.setXORMode(java.awt.Color.white); // gx.drawRect(m_oldX, m_oldY, m_oldX, m_oldY); // gx.drawLine(m_startX, m_startY, m_startX, m_startY); gx.dispose(); m_mode = SELECTING; } } } } @Override public void mouseReleased(MouseEvent me) { layout.requestFocusInWindow(); if (m_editElement != null && m_mode == MOVING) { if (m_snapToGridB.isSelected()) { int x = snapToGrid(m_editElement.getX()); int y = snapToGrid(m_editElement.getY()); m_editElement.setXY(x, y); snapSelectedToGrid(); } m_editElement = null; revalidate(); layout.repaint(); m_mode = NONE; } if (m_mode == SELECTING) { revalidate(); layout.repaint(); m_mode = NONE; double z = m_layoutZoom / 100.0; double px = me.getX(); double py = me.getY(); py /= z; px /= z; // highlightSubFlow(m_startX, m_startY, me.getX(), me.getY()); highlightSubFlow(m_startX, m_startY, (int) px, (int) py); } } @Override public void mouseClicked(MouseEvent me) { layout.requestFocusInWindow(); Point p = me.getPoint(); Point np = new Point(); double z = m_layoutZoom / 100.0; np.setLocation(p.getX() / z, p.getY() / z); BeanInstance bi = BeanInstance.findInstance(np, m_mainKFPerspective.getCurrentTabIndex()); if (m_mode == ADDING || m_mode == NONE) { // try and popup a context sensitive menu if we have // been clicked over a bean. if (bi != null) { JComponent bc = (JComponent) bi.getBean(); // if we've been double clicked, then popup customizer // as long as we're not a meta bean if (me.getClickCount() == 2 && !(bc instanceof MetaBean)) { try { Class<?> custClass = Introspector.getBeanInfo(bc.getClass()).getBeanDescriptor() .getCustomizerClass(); if (custClass != null) { if (bc instanceof BeanCommon) { if (!((BeanCommon) bc).isBusy() && !m_mainKFPerspective.getExecuting()) { popupCustomizer(custClass, bc); } } else { popupCustomizer(custClass, bc); } } } catch (IntrospectionException ex) { ex.printStackTrace(); } } else if (((me.getModifiers() & InputEvent.BUTTON1_MASK) != InputEvent.BUTTON1_MASK) || me.isAltDown()) { // doPopup(me.getPoint(), bi, me.getX(), me.getY()); doPopup(me.getPoint(), bi, (int) (p.getX() / z), (int) (p.getY() / z)); return; } else { // just select this bean Vector<Object> v = m_mainKFPerspective.getSelectedBeans(); if (me.isShiftDown()) { } else { v = new Vector<Object>(); } v.add(bi); m_mainKFPerspective.setSelectedBeans(v); return; } } else { if (((me.getModifiers() & InputEvent.BUTTON1_MASK) != InputEvent.BUTTON1_MASK) || me.isAltDown()) { double px = me.getX(); double py = me.getY(); py /= z; px /= z; // find connections if any close to this point if (!m_mainKFPerspective.getExecuting()) { // rightClickCanvasPopup(me.getX(), me.getY()); rightClickCanvasPopup((int) px, (int) py); revalidate(); repaint(); notifyIsDirty(); } return; /* * int delta = 10; deleteConnectionPopup(BeanConnection. * getClosestConnections(new Point(me.getX(), me.getY()), delta, * m_mainKFPerspective.getCurrentTabIndex()), me.getX(), * me.getY()); */ } else if (m_toolBarBean != null) { // otherwise, if a toolbar button is active then // add the component // snap to grid double x = me.getX(); double y = me.getY(); x /= z; y /= z; if (m_snapToGridB.isSelected()) { // x = snapToGrid(me.getX()); x = snapToGrid((int) x); // y = snapToGrid(me.getY()); y = snapToGrid((int) y); } addUndoPoint(); if (m_toolBarBean instanceof StringBuffer) { // serialized user meta bean pasteFromClipboard((int) x, (int) y, (StringBuffer) m_toolBarBean, false); m_mode = NONE; KnowledgeFlowApp.this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); m_toolBarBean = null; } else { // saveLayout(m_mainKFPerspective.getCurrentTabIndex(), false); addComponent((int) x, (int) y); } m_componentTree.clearSelection(); m_mainKFPerspective.setEditedStatus(true); } } revalidate(); repaint(); notifyIsDirty(); } double px = me.getX(); double py = me.getY(); px /= z; py /= z; if (m_mode == PASTING && m_pasteBuffer.length() > 0) { // pasteFromClipboard(me.getX(), me.getY(), m_pasteBuffer, true); pasteFromClipboard((int) px, (int) py, m_pasteBuffer, true); m_mode = NONE; KnowledgeFlowApp.this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); return; } if (m_mode == CONNECTING) { // turn off connecting points and remove connecting line layout.repaint(); Vector<Object> beanInstances = BeanInstance .getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()); for (int i = 0; i < beanInstances.size(); i++) { JComponent bean = (JComponent) ((BeanInstance) beanInstances.elementAt(i)).getBean(); if (bean instanceof Visible) { ((Visible) bean).getVisual().setDisplayConnectors(false); } } if (bi != null) { boolean doConnection = false; if (!(bi.getBean() instanceof BeanCommon)) { doConnection = true; } else { // Give the target bean a chance to veto the proposed // connection if (((BeanCommon) bi.getBean()). // connectionAllowed(m_sourceEventSetDescriptor.getName())) { connectionAllowed(m_sourceEventSetDescriptor)) { doConnection = true; } } if (doConnection) { addUndoPoint(); // attempt to connect source and target beans if (bi.getBean() instanceof MetaBean) { BeanConnection.doMetaConnection(m_editElement, bi, m_sourceEventSetDescriptor, layout, m_mainKFPerspective.getCurrentTabIndex()); } else { new BeanConnection(m_editElement, bi, m_sourceEventSetDescriptor, m_mainKFPerspective.getCurrentTabIndex()); } m_mainKFPerspective.setEditedStatus(true); } layout.repaint(); } m_mode = NONE; m_editElement = null; m_sourceEventSetDescriptor = null; } if (m_mainKFPerspective.getSelectedBeans().size() > 0) { m_mainKFPerspective.setSelectedBeans(new Vector<Object>()); } } }); layout.addMouseMotionListener(new MouseMotionAdapter() { @Override public void mouseDragged(MouseEvent me) { double z = m_layoutZoom / 100.0; double px = me.getX(); double py = me.getY(); px /= z; py /= z; if (m_editElement != null && m_mode == MOVING) { /* * int deltaX = me.getX() - m_oldX; int deltaY = me.getY() - m_oldY; */ int deltaX = (int) px - m_oldX; int deltaY = (int) py - m_oldY; m_editElement.setXY(m_editElement.getX() + deltaX, m_editElement.getY() + deltaY); if (m_mainKFPerspective.getSelectedBeans().size() > 0) { Vector<Object> v = m_mainKFPerspective.getSelectedBeans(); for (int i = 0; i < v.size(); i++) { BeanInstance b = (BeanInstance) v.get(i); if (b != m_editElement) { b.setXY(b.getX() + deltaX, b.getY() + deltaY); } } } layout.repaint(); // note the new points /* * m_oldX = me.getX(); m_oldY = me.getY(); */ m_oldX = (int) px; m_oldY = (int) py; m_mainKFPerspective.setEditedStatus(true); } if (m_mode == SELECTING) { layout.repaint(); /* * m_oldX = me.getX(); m_oldY = me.getY(); */ m_oldX = (int) px; m_oldY = (int) py; } } @Override public void mouseMoved(MouseEvent e) { double z = m_layoutZoom / 100.0; double px = e.getX(); double py = e.getY(); px /= z; py /= z; if (m_mode == CONNECTING) { layout.repaint(); // note the new coordinates /* * m_oldX = e.getX(); m_oldY = e.getY(); */ m_oldX = (int) px; m_oldY = (int) py; } } }); } private void setUpLogPanel(final LogPanel logPanel) { String date = (new SimpleDateFormat("EEEE, d MMMM yyyy")).format(new Date()); logPanel.logMessage("Weka Knowledge Flow was written by Mark Hall"); logPanel.logMessage("Weka Knowledge Flow"); logPanel.logMessage( "(c) 2002-" + Copyright.getToYear() + " " + Copyright.getOwner() + ", " + Copyright.getAddress()); logPanel.logMessage("web: " + Copyright.getURL()); logPanel.logMessage(date); logPanel.statusMessage("@!@[KnowledgeFlow]|Welcome to the Weka Knowledge Flow"); logPanel.getStatusTable().addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (logPanel.getStatusTable().rowAtPoint(e.getPoint()) == 0) { if (((e.getModifiers() & InputEvent.BUTTON1_MASK) != InputEvent.BUTTON1_MASK) || e.isAltDown()) { System.gc(); Runtime currR = Runtime.getRuntime(); long freeM = currR.freeMemory(); long totalM = currR.totalMemory(); long maxM = currR.maxMemory(); logPanel.logMessage("[KnowledgeFlow] Memory (free/total/max.) in bytes: " + String.format("%,d", freeM) + " / " + String.format("%,d", totalM) + " / " + String.format("%,d", maxM)); logPanel.statusMessage("@!@[KnowledgeFlow]|Memory (free/total/max.) in bytes: " + String.format("%,d", freeM) + " / " + String.format("%,d", totalM) + " / " + String.format("%,d", maxM)); } } } }); } private Image loadImage(String path) { Image pic = null; // Modified by Zerbetto // java.net.URL imageURL = ClassLoader.getSystemResource(path); java.net.URL imageURL = this.getClass().getClassLoader().getResource(path); // end modifications if (imageURL == null) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "Unable to load " + path); } else { pic = Toolkit.getDefaultToolkit().getImage(imageURL); } return pic; } protected class RunThread extends Thread { int m_flowIndex; boolean m_sequential; boolean m_wasUserStopped = false; public RunThread(boolean sequential) { m_sequential = sequential; } @Override public void run() { m_flowIndex = m_mainKFPerspective.getCurrentTabIndex(); String flowName = m_mainKFPerspective.getTabTitle(m_flowIndex); m_mainKFPerspective.setExecuting(true); m_mainKFPerspective.getLogPanel(m_flowIndex).clearStatus(); m_mainKFPerspective.getLogPanel(m_flowIndex).statusMessage("@!@[KnowledgeFlow]|Executing..."); FlowRunner runner = new FlowRunner(false, false); runner.setStartSequentially(m_sequential); runner.setEnvironment(m_flowEnvironment); runner.setLog(m_logPanel); Vector<Object> comps = BeanInstance.getBeanInstances(m_flowIndex); runner.setFlows(comps); try { runner.run(); runner.waitUntilFinished(); } catch (InterruptedException ie) { } catch (Exception ex) { m_logPanel.logMessage("An error occurred while running the flow: " + ex.getMessage()); } finally { if (m_flowIndex >= m_mainKFPerspective.getNumTabs() - 1 || !m_mainKFPerspective.getTabTitle(m_flowIndex).equals(flowName)) { // try and find which index our flow is at (user must have closed some // other tabs at lower indexes than us)! for (int i = 0; i < m_mainKFPerspective.getNumTabs(); i++) { String tabT = m_mainKFPerspective.getTabTitle(i); if (tabT != null && tabT.equals(flowName)) { m_flowIndex = i; break; } } } m_mainKFPerspective.setExecuting(m_flowIndex, false); m_mainKFPerspective.setExecutionThread(m_flowIndex, null); if (m_wasUserStopped) { // TODO global Stop message to the status area KFLogPanel lp = m_mainKFPerspective.getLogPanel(m_flowIndex); lp.setMessageOnAll(false, "Stopped."); } else { m_mainKFPerspective.getLogPanel(m_flowIndex).statusMessage("@!@[KnowledgeFlow]|OK."); } } } public void stopAllFlows() { Vector<Object> components = BeanInstance.getBeanInstances(m_flowIndex); if (components != null) { for (int i = 0; i < components.size(); i++) { Object temp = ((BeanInstance) components.elementAt(i)).getBean(); if (temp instanceof BeanCommon) { ((BeanCommon) temp).stop(); } } m_wasUserStopped = true; } } } /** * Run all start-points in a layout in parallel or sequentially. Order of * execution is arbitrary if the user has not prefixed the names of the start * points with "<num> :" in order to specify the order. In both parallel and * sequential mode, a start point can be ommitted from exectution by prefixing * its name with "! :". * * @param sequential true if the flow layout is to have its start points run * sequentially rather than in parallel * */ private void runFlow(final boolean sequential) { if (m_mainKFPerspective.getNumTabs() > 0) { RunThread runThread = new RunThread(sequential); m_mainKFPerspective.setExecutionThread(runThread); runThread.start(); } } private void stopFlow() { if (m_mainKFPerspective.getCurrentTabIndex() >= 0) { RunThread running = m_mainKFPerspective.getExecutionThread(); if (running != null) { running.stopAllFlows(); } /* * Vector components = * BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex * ()); * * if (components != null) { for (int i = 0; i < components.size(); i++) { * Object temp = ((BeanInstance) components.elementAt(i)).getBean(); * * if (temp instanceof BeanCommon) { ((BeanCommon) temp).stop(); } } } */ } } private void processPackage(String tempBeanCompName, weka.gui.HierarchyPropertyParser hpp, DefaultMutableTreeNode parentNode, Map<String, DefaultMutableTreeNode> nodeTextIndex) { if (hpp.isLeafReached()) { // instantiate a bean and add it to the holderPanel // System.err.println("Would add "+hpp.fullValue()); /* * String algName = hpp.fullValue(); JPanel tempBean = * instantiateToolBarBean(true, tempBeanCompName, algName); if (tempBean * != null && holderPanel != null) { holderPanel.add(tempBean); } */ hpp.goToParent(); return; } String[] children = hpp.childrenValues(); for (String element : children) { hpp.goToChild(element); DefaultMutableTreeNode child = null; if (hpp.isLeafReached()) { String algName = hpp.fullValue(); Object visibleCheck = instantiateBean(true, tempBeanCompName, algName); if (visibleCheck != null) { if (visibleCheck instanceof BeanContextChild) { m_bcSupport.add(visibleCheck); } ImageIcon scaledForTree = null; if (visibleCheck instanceof Visible) { BeanVisual bv = ((Visible) visibleCheck).getVisual(); if (bv != null) { scaledForTree = new ImageIcon(bv.scale(0.33)); // m_iconLookup.put(algName, scaledForTree); } } // try and get a tool tip String toolTip = ""; try { Object wrappedA = WekaPackageClassLoaderManager.objectForName(algName); // Object wrappedA = Class.forName(algName).newInstance(); toolTip = getGlobalInfo(wrappedA); } catch (Exception ex) { } JTreeLeafDetails leafData = new JTreeLeafDetails(tempBeanCompName, algName, scaledForTree); if (toolTip != null && toolTip.length() > 0) { leafData.setToolTipText(toolTip); } child = new InvisibleNode(leafData); nodeTextIndex.put(algName.toLowerCase() + " " + (toolTip != null ? toolTip.toLowerCase() : ""), child); } } else { child = new InvisibleNode(element); } if (child != null) { parentNode.add(child); } processPackage(tempBeanCompName, hpp, child, nodeTextIndex); } hpp.goToParent(); } private Object instantiateBean(boolean wekawrapper, String tempBeanCompName, String algName) { Object tempBean; if (wekawrapper) { try { // modifications by Zerbetto // tempBean = Beans.instantiate(null, tempBeanCompName); tempBean = WekaPackageClassLoaderManager.objectForName(tempBeanCompName); //tempBean = Beans.instantiate(this.getClass().getClassLoader(), // tempBeanCompName); // end modifications by Zerbetto } catch (Exception ex) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "[KnowledgeFlow] Failed to instantiate :" + tempBeanCompName + "KnowledgeFlowApp.instantiateBean()"); return null; } if (tempBean instanceof WekaWrapper) { // algName = (String)tempBarSpecs.elementAt(j); Class<?> c = null; try { c = WekaPackageClassLoaderManager.forName(algName); // c = Class.forName(algName); // check for ignore for (Annotation a : c.getAnnotations()) { if (a instanceof KFIgnore) { return null; } } } catch (Exception ex) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "[KnowledgeFlow] Can't find class called: " + algName); return null; } try { Object o = c.newInstance(); ((WekaWrapper) tempBean).setWrappedAlgorithm(o); } catch (Exception ex) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "[KnowledgeFlow] Failed to configure " + tempBeanCompName + " with " + algName); return null; } } } else { try { // modifications by Zerbetto // tempBean = Beans.instantiate(null, tempBeanCompName); tempBean = WekaPackageClassLoaderManager.objectForName(tempBeanCompName); //tempBean = Beans.instantiate(this.getClass().getClassLoader(), // tempBeanCompName); // end modifications } catch (Exception ex) { ex.printStackTrace(); weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "[KnowledgeFlow] Failed to instantiate :" + tempBeanCompName + "KnowledgeFlowApp.instantiateBean()"); return null; } } return tempBean; } /** * Pop up a help window */ private void popupHelp() { final JButton tempB = m_helpB; try { tempB.setEnabled(false); // Modified by Zerbetto // InputStream inR = // ClassLoader. // getSystemResourceAsStream("weka/gui/beans/README_KnowledgeFlow"); InputStream inR = this.getClass().getClassLoader() .getResourceAsStream("weka/gui/beans/README_KnowledgeFlow"); // end modifications StringBuffer helpHolder = new StringBuffer(); LineNumberReader lnr = new LineNumberReader(new InputStreamReader(inR)); String line; while ((line = lnr.readLine()) != null) { helpHolder.append(line + "\n"); } lnr.close(); final javax.swing.JFrame jf = new javax.swing.JFrame(); jf.getContentPane().setLayout(new java.awt.BorderLayout()); final JTextArea ta = new JTextArea(helpHolder.toString()); ta.setFont(new Font("Monospaced", Font.PLAIN, 12)); ta.setEditable(false); final JScrollPane sp = new JScrollPane(ta); jf.getContentPane().add(sp, java.awt.BorderLayout.CENTER); jf.addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(java.awt.event.WindowEvent e) { tempB.setEnabled(true); jf.dispose(); } }); jf.setSize(600, 600); jf.setVisible(true); } catch (Exception ex) { tempB.setEnabled(true); } } public void closeAllTabs() { for (int i = m_mainKFPerspective.getNumTabs() - 1; i >= 0; i--) { m_mainKFPerspective.removeTab(i); } } public void clearLayout() { stopFlow(); // try and stop any running components if (m_mainKFPerspective.getNumTabs() == 0 || getAllowMultipleTabs()) { m_mainKFPerspective.addTab("Untitled" + m_untitledCount++); } if (!getAllowMultipleTabs()) { BeanConnection.setConnections(new Vector<BeanConnection>(), m_mainKFPerspective.getCurrentTabIndex()); BeanInstance.setBeanInstances(new Vector<Object>(), m_mainKFPerspective.getBeanLayout(m_mainKFPerspective.getCurrentTabIndex()), m_mainKFPerspective.getCurrentTabIndex()); } /* * BeanInstance.reset(m_beanLayout); BeanConnection.reset(); * m_beanLayout.revalidate(); m_beanLayout.repaint(); * m_logPanel.clearStatus(); * m_logPanel.statusMessage("[KnowledgeFlow]|Welcome to the Weka Knowledge Flow" * ); */ } /** * Pops up the menu for selecting template layouts */ private void createTemplateMenuPopup() { PopupMenu templatesMenu = new PopupMenu(); // MenuItem addToUserTabItem = new MenuItem("Add to user tab"); for (int i = 0; i < BeansProperties.TEMPLATE_PATHS.size(); i++) { String mE = BeansProperties.TEMPLATE_DESCRIPTIONS.get(i); final String path = BeansProperties.TEMPLATE_PATHS.get(i); MenuItem m = new MenuItem(mE); m.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ee) { try { ClassLoader resourceClassLoader = WekaPackageClassLoaderManager .getWekaPackageClassLoaderManager().findClassloaderForResource(path); InputStream inR = resourceClassLoader.getResourceAsStream(path); //InputStream inR = this.getClass().getClassLoader() // .getResourceAsStream(path); m_mainKFPerspective.addTab("Untitled" + m_untitledCount++); XMLBeans xml = new XMLBeans(m_beanLayout, m_bcSupport, m_mainKFPerspective.getCurrentTabIndex()); InputStreamReader isr = new InputStreamReader(inR); @SuppressWarnings("unchecked") Vector<Vector<?>> v = (Vector<Vector<?>>) xml.read(isr); @SuppressWarnings("unchecked") Vector<Object> beans = (Vector<Object>) v.get(XMLBeans.INDEX_BEANINSTANCES); @SuppressWarnings("unchecked") Vector<BeanConnection> connections = (Vector<BeanConnection>) v .get(XMLBeans.INDEX_BEANCONNECTIONS); isr.close(); integrateFlow(beans, connections, false, false); notifyIsDirty(); revalidate(); } catch (Exception ex) { m_mainKFPerspective.getCurrentLogPanel() .logMessage("Problem loading template: " + ex.getMessage()); } } }); templatesMenu.add(m); } m_templatesB.add(templatesMenu); templatesMenu.show(m_templatesB, 0, 0); } /** * Popup a context sensitive menu for the bean component * * @param pt holds the panel coordinates for the component * @param bi the bean component over which the user right clicked the mouse * @param x the x coordinate at which to popup the menu * @param y the y coordinate at which to popup the menu * * Modified by Zerbetto: javax.swing.JPopupMenu transformed into * java.awt.PopupMenu * */ private void doPopup(Point pt, final BeanInstance bi, int x, int y) { final JComponent bc = (JComponent) bi.getBean(); final int xx = x; final int yy = y; int menuItemCount = 0; // modifications by Zerbetto PopupMenu beanContextMenu = new PopupMenu(); // JPopupMenu beanContextMenu = new JPopupMenu(); // beanContextMenu.insert(new JLabel("Edit", // SwingConstants.CENTER), // menuItemCount); boolean executing = m_mainKFPerspective.getExecuting(); MenuItem edit = new MenuItem("Edit:"); edit.setEnabled(false); beanContextMenu.insert(edit, menuItemCount); menuItemCount++; if (m_mainKFPerspective.getSelectedBeans().size() > 0) { MenuItem copyItem = new MenuItem("Copy"); copyItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { copyToClipboard(); m_mainKFPerspective.setSelectedBeans(new Vector<Object>()); } }); beanContextMenu.add(copyItem); copyItem.setEnabled(!executing); menuItemCount++; } if (bc instanceof MetaBean) { // JMenuItem ungroupItem = new JMenuItem("Ungroup"); MenuItem ungroupItem = new MenuItem("Ungroup"); ungroupItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // ungroup bi.removeBean(m_beanLayout, m_mainKFPerspective.getCurrentTabIndex()); Vector<Object> group = ((MetaBean) bc).getBeansInSubFlow(); Vector<BeanConnection> associatedConnections = ((MetaBean) bc).getAssociatedConnections(); ((MetaBean) bc).restoreBeans(xx, yy); for (int i = 0; i < group.size(); i++) { BeanInstance tbi = (BeanInstance) group.elementAt(i); addComponent(tbi, false); tbi.addBean(m_beanLayout, m_mainKFPerspective.getCurrentTabIndex()); } for (int i = 0; i < associatedConnections.size(); i++) { BeanConnection tbc = associatedConnections.elementAt(i); tbc.setHidden(false); } m_beanLayout.repaint(); m_mainKFPerspective.setEditedStatus(true); notifyIsDirty(); } }); ungroupItem.setEnabled(!executing); beanContextMenu.add(ungroupItem); menuItemCount++; // Add to user tab // JMenuItem addToUserTabItem = new JMenuItem("Add to user tab"); MenuItem addToUserTabItem = new MenuItem("Add to user tab"); addToUserTabItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // addToUserToolBar((MetaBean) bi.getBean(), true); // addToUserTreeNode((MetaBean) bi.getBean(), true); addToUserTreeNode(bi, true); notifyIsDirty(); } }); addToUserTabItem.setEnabled(!executing); beanContextMenu.add(addToUserTabItem); menuItemCount++; } // JMenuItem deleteItem = new JMenuItem("Delete"); MenuItem deleteItem = new MenuItem("Delete"); deleteItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { BeanConnection.removeConnections(bi, m_mainKFPerspective.getCurrentTabIndex()); bi.removeBean(m_beanLayout, m_mainKFPerspective.getCurrentTabIndex()); if (bc instanceof BeanCommon) { String key = ((BeanCommon) bc).getCustomName() + "$" + bc.hashCode(); m_logPanel.statusMessage(key + "|remove"); } // delete any that have been actively selected if (m_mainKFPerspective.getSelectedBeans().size() > 0) { deleteSelectedBeans(); } revalidate(); m_mainKFPerspective.setEditedStatus(true); notifyIsDirty(); m_selectAllB.setEnabled( BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()).size() > 0); } }); deleteItem.setEnabled(!executing); if (bc instanceof BeanCommon) { if (((BeanCommon) bc).isBusy()) { deleteItem.setEnabled(false); } } beanContextMenu.add(deleteItem); menuItemCount++; if (bc instanceof BeanCommon) { MenuItem nameItem = new MenuItem("Set name"); nameItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String oldName = ((BeanCommon) bc).getCustomName(); String name = JOptionPane.showInputDialog(KnowledgeFlowApp.this, "Enter a name for this component", oldName); if (name != null) { ((BeanCommon) bc).setCustomName(name); m_mainKFPerspective.setEditedStatus(true); } } }); if (bc instanceof BeanCommon) { if (((BeanCommon) bc).isBusy()) { nameItem.setEnabled(false); } } nameItem.setEnabled(!executing); beanContextMenu.add(nameItem); menuItemCount++; } try { // BeanInfo [] compInfo = null; // JComponent [] associatedBeans = null; Vector<BeanInfo> compInfo = new Vector<BeanInfo>(1); Vector<Object> associatedBeans = null; if (bc instanceof MetaBean) { compInfo = ((MetaBean) bc).getBeanInfoSubFlow(); associatedBeans = ((MetaBean) bc).getBeansInSubFlow(); ((MetaBean) bc).getBeansInOutputs(); ((MetaBean) bc).getBeanInfoOutputs(); } else { compInfo.add(Introspector.getBeanInfo(bc.getClass())); } final Vector<Object> tempAssociatedBeans = associatedBeans; if (compInfo == null) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "[KnowledgeFlow] Error in doPopup()"); } else { // System.err.println("Got bean info"); for (int zz = 0; zz < compInfo.size(); zz++) { final int tt = zz; final Class<?> custClass = compInfo.elementAt(zz).getBeanDescriptor().getCustomizerClass(); if (custClass != null) { // System.err.println("Got customizer class"); // popupCustomizer(custClass, bc); // JMenuItem custItem = null; MenuItem custItem = null; boolean customizationEnabled = !executing; if (!(bc instanceof MetaBean)) { // custItem = new JMenuItem("Configure..."); custItem = new MenuItem("Configure..."); if (bc instanceof BeanCommon) { customizationEnabled = (!executing && !((BeanCommon) bc).isBusy()); } } else { String custName = custClass.getName(); BeanInstance tbi = (BeanInstance) associatedBeans.elementAt(zz); if (tbi.getBean() instanceof BeanCommon) { custName = ((BeanCommon) tbi.getBean()).getCustomName(); } else { if (tbi.getBean() instanceof WekaWrapper) { custName = ((WekaWrapper) tbi.getBean()).getWrappedAlgorithm().getClass() .getName(); } else { custName = custName.substring(0, custName.indexOf("Customizer")); } custName = custName.substring(custName.lastIndexOf('.') + 1, custName.length()); } // custItem = new JMenuItem("Configure: "+ custName); custItem = new MenuItem("Configure: " + custName); if (tbi.getBean() instanceof BeanCommon) { customizationEnabled = (!executing && !((BeanCommon) tbi.getBean()).isBusy()); } } custItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (bc instanceof MetaBean) { popupCustomizer(custClass, (JComponent) ((BeanInstance) tempAssociatedBeans.elementAt(tt)) .getBean()); } else { popupCustomizer(custClass, bc); } notifyIsDirty(); } }); custItem.setEnabled(customizationEnabled); beanContextMenu.add(custItem); menuItemCount++; } else { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.INFO, "[KnowledgeFlow] No customizer class"); } } Vector<EventSetDescriptor[]> esdV = new Vector<EventSetDescriptor[]>(); // for (int i = 0; i < compInfoOutputs.size(); i++) { for (int i = 0; i < compInfo.size(); i++) { EventSetDescriptor[] temp = // ((BeanInfo) // compInfoOutputs.elementAt(i)).getEventSetDescriptors(); compInfo.elementAt(i).getEventSetDescriptors(); if ((temp != null) && (temp.length > 0)) { esdV.add(temp); } } // EventSetDescriptor [] esds = compInfo.getEventSetDescriptors(); // if (esds != null && esds.length > 0) { if (esdV.size() > 0) { // beanContextMenu.insert(new JLabel("Connections", // SwingConstants.CENTER), // menuItemCount); MenuItem connections = new MenuItem("Connections:"); connections.setEnabled(false); beanContextMenu.insert(connections, menuItemCount); menuItemCount++; } // final Vector finalOutputs = outputBeans; final Vector<Object> finalOutputs = associatedBeans; for (int j = 0; j < esdV.size(); j++) { final int fj = j; String sourceBeanName = ""; if (bc instanceof MetaBean) { // Object sourceBean = ((BeanInstance) // outputBeans.elementAt(j)).getBean(); Object sourceBean = ((BeanInstance) associatedBeans.elementAt(j)).getBean(); if (sourceBean instanceof BeanCommon) { sourceBeanName = ((BeanCommon) sourceBean).getCustomName(); } else { if (sourceBean instanceof WekaWrapper) { sourceBeanName = ((WekaWrapper) sourceBean).getWrappedAlgorithm().getClass() .getName(); } else { sourceBeanName = sourceBean.getClass().getName(); } sourceBeanName = sourceBeanName.substring(sourceBeanName.lastIndexOf('.') + 1, sourceBeanName.length()); } sourceBeanName += ": "; } EventSetDescriptor[] esds = esdV.elementAt(j); for (final EventSetDescriptor esd : esds) { // System.err.println(esds[i].getName()); // add each event name to the menu // JMenuItem evntItem = new JMenuItem(sourceBeanName // +esds[i].getName()); MenuItem evntItem = new MenuItem(sourceBeanName + esd.getName()); // Check EventConstraints (if any) here boolean ok = true; evntItem.setEnabled(!executing); if (bc instanceof EventConstraints) { ok = ((EventConstraints) bc).eventGeneratable(esd.getName()); } if (ok) { evntItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { connectComponents(esd, (bc instanceof MetaBean) ? ((BeanInstance) finalOutputs.elementAt(fj)) : bi, xx, yy); notifyIsDirty(); } }); } else { evntItem.setEnabled(false); } beanContextMenu.add(evntItem); menuItemCount++; } } } } catch (IntrospectionException ie) { ie.printStackTrace(); } // System.err.println("Just before look for other options"); // now look for other options for this bean if (bc instanceof UserRequestAcceptor || bc instanceof Startable) { Enumeration<String> req = null; if (bc instanceof UserRequestAcceptor) { req = ((UserRequestAcceptor) bc).enumerateRequests(); } if (/* (bc instanceof Startable) || */(req != null && req.hasMoreElements())) { // beanContextMenu.insert(new JLabel("Actions", // SwingConstants.CENTER), // menuItemCount); MenuItem actions = new MenuItem("Actions:"); actions.setEnabled(false); beanContextMenu.insert(actions, menuItemCount); menuItemCount++; } /* * if (bc instanceof Startable) { String tempS = * ((Startable)bc).getStartMessage(); insertUserOrStartableMenuItem(bc, * true, tempS, beanContextMenu); } */ while (req != null && req.hasMoreElements()) { String tempS = req.nextElement(); insertUserOrStartableMenuItem(bc, false, tempS, beanContextMenu); menuItemCount++; } } // Send to perspective menu item? if (bc instanceof weka.gui.beans.Loader && m_perspectives.size() > 1 && m_perspectiveDataLoadThread == null) { final weka.core.converters.Loader theLoader = ((weka.gui.beans.Loader) bc).getLoader(); boolean ok = true; if (theLoader instanceof FileSourcedConverter) { String fileName = ((FileSourcedConverter) theLoader).retrieveFile().getPath(); Environment env = m_mainKFPerspective.getEnvironmentSettings(); try { fileName = env.substitute(fileName); } catch (Exception ex) { } File tempF = new File(fileName); String fileNameFixedPathSep = fileName.replace(File.separatorChar, '/'); if (!tempF.isFile() && this.getClass().getClassLoader().getResource(fileNameFixedPathSep) == null) { ok = false; } } if (ok) { beanContextMenu.addSeparator(); menuItemCount++; if (m_perspectives.size() > 2) { MenuItem sendToAllPerspectives = new MenuItem("Send to all perspectives"); menuItemCount++; sendToAllPerspectives.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { loadDataAndSendToPerspective(theLoader, 0, true); } }); beanContextMenu.add(sendToAllPerspectives); } Menu sendToPerspective = new Menu("Send to perspective..."); beanContextMenu.add(sendToPerspective); menuItemCount++; for (int i = 1; i < m_perspectives.size(); i++) { final int pIndex = i; if (m_perspectives.get(i).acceptsInstances()) { String pName = m_perspectives.get(i).getPerspectiveTitle(); MenuItem pI = new MenuItem(pName); pI.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { loadDataAndSendToPerspective(theLoader, pIndex, false); } }); sendToPerspective.add(pI); } } } } // System.err.println("Just before showing menu"); // popup the menu if (menuItemCount > 0) { // beanContextMenu.show(m_beanLayout, x, y); double z = m_layoutZoom / 100.0; double px = x * z; double py = y * z; m_beanLayout.add(beanContextMenu); // beanContextMenu.show(m_beanLayout, x, y); beanContextMenu.show(m_beanLayout, (int) px, (int) py); } } private synchronized void loadDataAndSendToPerspective(final weka.core.converters.Loader loader, final int perspectiveIndex, final boolean sendToAll) { if (m_perspectiveDataLoadThread == null) { m_perspectiveDataLoadThread = new Thread() { @Override public void run() { try { Environment env = m_mainKFPerspective.getEnvironmentSettings(); if (loader instanceof EnvironmentHandler) { ((EnvironmentHandler) loader).setEnvironment(env); } loader.reset(); m_logPanel.statusMessage("@!@[KnowledgeFlow]|Sending data to perspective(s)..."); Instances data = loader.getDataSet(); if (data != null) { // make sure the perspective toolbar is visible!! if (!m_configAndPerspectivesVisible) { KnowledgeFlowApp.this.add(m_configAndPerspectives, BorderLayout.NORTH); m_configAndPerspectivesVisible = true; } // need to disable all the perspective buttons for (int i = 0; i < m_perspectives.size(); i++) { m_perspectiveToolBar.getComponent(i).setEnabled(false); } if (sendToAll) { for (int i = 1; i < m_perspectives.size(); i++) { if (m_perspectives.get(i).acceptsInstances()) { m_perspectives.get(i).setInstances(data); } } } else { KFPerspective currentP = (KFPerspective) m_perspectiveHolder.getComponent(0); if (currentP != m_perspectives.get(perspectiveIndex)) { m_perspectives.get(perspectiveIndex).setInstances(data); currentP.setActive(false); m_perspectiveHolder.remove(0); m_perspectiveHolder.add((JComponent) m_perspectives.get(perspectiveIndex), BorderLayout.CENTER); m_perspectives.get(perspectiveIndex).setActive(true); ((JToggleButton) m_perspectiveToolBar.getComponent(perspectiveIndex)) .setSelected(true); // KnowledgeFlowApp.this.invalidate(); KnowledgeFlowApp.this.revalidate(); KnowledgeFlowApp.this.repaint(); notifyIsDirty(); } } } } catch (Exception ex) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "[KnowledgeFlow] problem loading data for " + "perspective(s) : " + ex.getMessage()); ex.printStackTrace(); } finally { // re-enable all the perspective buttons for (int i = 0; i < m_perspectives.size(); i++) { m_perspectiveToolBar.getComponent(i).setEnabled(true); } m_perspectiveDataLoadThread = null; m_logPanel.statusMessage("@!@[KnowledgeFlow]|OK"); } } }; m_perspectiveDataLoadThread.setPriority(Thread.MIN_PRIORITY); m_perspectiveDataLoadThread.start(); } } private void insertUserOrStartableMenuItem(final JComponent bc, final boolean startable, String tempS, PopupMenu beanContextMenu) { boolean disabled = false; boolean confirmRequest = false; // check to see if this item is currently disabled if (tempS.charAt(0) == '$') { tempS = tempS.substring(1, tempS.length()); disabled = true; } // check to see if this item requires confirmation if (tempS.charAt(0) == '?') { tempS = tempS.substring(1, tempS.length()); confirmRequest = true; } final String tempS2 = tempS; // JMenuItem custItem = new JMenuItem(tempS2); MenuItem custItem = new MenuItem(tempS2); if (confirmRequest) { custItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // int result = JOptionPane.showConfirmDialog(KnowledgeFlowApp.this, tempS2, "Confirm action", JOptionPane.YES_NO_OPTION); if (result == JOptionPane.YES_OPTION) { Thread startPointThread = new Thread() { @Override public void run() { try { if (startable) { ((Startable) bc).start(); } else if (bc instanceof UserRequestAcceptor) { ((UserRequestAcceptor) bc).performRequest(tempS2); } notifyIsDirty(); } catch (Exception ex) { ex.printStackTrace(); } } }; startPointThread.setPriority(Thread.MIN_PRIORITY); startPointThread.start(); } } }); } else { custItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Thread startPointThread = new Thread() { @Override public void run() { try { if (startable) { ((Startable) bc).start(); } else if (bc instanceof UserRequestAcceptor) { ((UserRequestAcceptor) bc).performRequest(tempS2); } notifyIsDirty(); } catch (Exception ex) { ex.printStackTrace(); } } }; startPointThread.setPriority(Thread.MIN_PRIORITY); startPointThread.start(); } }); } if (disabled) { custItem.setEnabled(false); } beanContextMenu.add(custItem); } /** * Tells us about the modified status of a particular object - typically a * customizer that is editing a flow component. Allows us to set the modified * flag for the current flow. */ @Override public void setModifiedStatus(Object source, boolean modified) { if (source instanceof BeanCustomizer && modified) { m_mainKFPerspective.setEditedStatus(modified); } } /** * Popup the customizer for this bean * * @param custClass the class of the customizer * @param bc the bean to be customized */ private void popupCustomizer(Class<?> custClass, JComponent bc) { try { // instantiate final Object customizer = custClass.newInstance(); // set environment **before** setting object!! if (customizer instanceof EnvironmentHandler) { ((EnvironmentHandler) customizer).setEnvironment(m_flowEnvironment); } if (customizer instanceof BeanCustomizer) { ((BeanCustomizer) customizer).setModifiedListener(this); } ((Customizer) customizer).setObject(bc); // final javax.swing.JFrame jf = new javax.swing.JFrame(); final JDialog d = new JDialog((java.awt.Frame) KnowledgeFlowApp.this.getTopLevelAncestor(), ModalityType.DOCUMENT_MODAL); d.setLayout(new BorderLayout()); d.getContentPane().add((JComponent) customizer, BorderLayout.CENTER); // jf.getContentPane().setLayout(new BorderLayout()); // jf.getContentPane().add((JComponent)customizer, BorderLayout.CENTER); if (customizer instanceof CustomizerCloseRequester) { ((CustomizerCloseRequester) customizer).setParentWindow(d); } d.addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(java.awt.event.WindowEvent e) { if (customizer instanceof CustomizerClosingListener) { ((CustomizerClosingListener) customizer).customizerClosing(); } d.dispose(); } }); // jf.pack(); // jf.setVisible(true); d.pack(); d.setLocationRelativeTo(KnowledgeFlowApp.this); d.setVisible(true); } catch (Exception ex) { ex.printStackTrace(); } } private void addToUserTreeNode(BeanInstance meta, boolean installListener) { DefaultTreeModel model = (DefaultTreeModel) m_componentTree.getModel(); DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); if (m_userCompNode == null) { m_userCompNode = new InvisibleNode("User"); model.insertNodeInto(m_userCompNode, root, 0); } Vector<Object> beanHolder = new Vector<Object>(); beanHolder.add(meta); try { StringBuffer serialized = copyToBuffer(beanHolder); String displayName = ""; ImageIcon scaledIcon = null; // if (meta.getBean() instanceof Visible) { // ((Visible)copy).getVisual().scale(3); scaledIcon = new ImageIcon(((Visible) meta.getBean()).getVisual().scale(0.33)); displayName = ((Visible) meta.getBean()).getVisual().getText(); } Vector<Object> metaDetails = new Vector<Object>(); metaDetails.add(displayName); metaDetails.add(serialized); metaDetails.add(scaledIcon); SerializedObject so = new SerializedObject(metaDetails); @SuppressWarnings("unchecked") Vector<Object> copy = (Vector<Object>) so.getObject(); JTreeLeafDetails metaLeaf = new JTreeLeafDetails(displayName, copy, scaledIcon); DefaultMutableTreeNode newUserComp = new InvisibleNode(metaLeaf); model.insertNodeInto(newUserComp, m_userCompNode, 0); // add to the list of user components m_userComponents.add(copy); if (installListener && m_firstUserComponentOpp) { try { installWindowListenerForSavingUserStuff(); m_firstUserComponentOpp = false; } catch (Exception ex) { ex.printStackTrace(); } } } catch (Exception ex) { ex.printStackTrace(); } /* * java.awt.Color bckC = getBackground(); Vector beans = * BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()); * detachFromLayout(beans); */ // Disconnect any beans connected to the inputs or outputs // of this MetaBean (prevents serialization of the entire // KnowledgeFlow!!) /* * Vector tempRemovedConnections = new Vector(); Vector allConnections = * BeanConnection.getConnections(m_mainKFPerspective.getCurrentTabIndex()); * Vector inputs = bean.getInputs(); Vector outputs = bean.getOutputs(); * Vector allComps = bean.getSubFlow(); * * for (int i = 0; i < inputs.size(); i++) { BeanInstance temp = * (BeanInstance)inputs.elementAt(i); // is this input a target for some * event? for (int j = 0; j < allConnections.size(); j++) { BeanConnection * tempC = (BeanConnection)allConnections.elementAt(j); if * (tempC.getTarget() == temp) { tempRemovedConnections.add(tempC); } * * // also check to see if this input is a source for // some target that is * *not* in the subFlow if (tempC.getSource() == temp && * !bean.subFlowContains(tempC.getTarget())) { * tempRemovedConnections.add(tempC); } } } * * for (int i = 0; i < outputs.size(); i++) { BeanInstance temp = * (BeanInstance)outputs.elementAt(i); // is this output a source for some * target? for (int j = 0; j < allConnections.size(); j++) { BeanConnection * tempC = (BeanConnection)allConnections.elementAt(j); if * (tempC.getSource() == temp) { tempRemovedConnections.add(tempC); } } } * * * for (int i = 0; i < tempRemovedConnections.size(); i++) { BeanConnection * temp = (BeanConnection)tempRemovedConnections.elementAt(i); * temp.remove(m_mainKFPerspective.getCurrentTabIndex()); } * * MetaBean copy = copyMetaBean(bean, true); * * String displayName =""; ImageIcon scaledIcon = null; // if (copy * instanceof Visible) { //((Visible)copy).getVisual().scale(3); scaledIcon * = new ImageIcon(((Visible)copy).getVisual().scale(0.33)); displayName = * ((Visible)copy).getVisual().getText(); } * * JTreeLeafDetails metaLeaf = new JTreeLeafDetails(displayName, copy, * scaledIcon); DefaultMutableTreeNode newUserComp = new * DefaultMutableTreeNode(metaLeaf); model.insertNodeInto(newUserComp, * m_userCompNode, 0); * * // add to the list of user components m_userComponents.add(copy); * * if (installListener && m_firstUserComponentOpp) { try { * installWindowListenerForSavingUserBeans(); m_firstUserComponentOpp = * false; } catch (Exception ex) { ex.printStackTrace(); } } * * // Now reinstate any deleted connections to the original MetaBean for * (int i = 0; i < tempRemovedConnections.size(); i++) { BeanConnection temp * = (BeanConnection)tempRemovedConnections.elementAt(i); BeanConnection * newC = new BeanConnection(temp.getSource(), temp.getTarget(), * temp.getSourceEventSetDescriptor(), * m_mainKFPerspective.getCurrentTabIndex()); } */ /* * for (int i = 0; i < beans.size(); i++) { BeanInstance tempB = * (BeanInstance)beans.elementAt(i); if (tempB.getBean() instanceof Visible) * { ((Visible)(tempB.getBean())).getVisual(). * addPropertyChangeListener(KnowledgeFlowApp.this); * * if (tempB.getBean() instanceof MetaBean) { ((MetaBean)tempB.getBean()). * addPropertyChangeListenersSubFlow(KnowledgeFlowApp.this); } // Restore * the default background colour ((Visible)(tempB.getBean())).getVisual(). * setBackground(bckC); ((JComponent)(tempB.getBean())).setBackground(bckC); * } } */ } /** * Set the contents of the "paste" buffer and enable the paste from cliboard * toolbar button * * @param b the buffer to use */ public void setPasteBuffer(StringBuffer b) { m_pasteBuffer = b; if (m_pasteBuffer != null && m_pasteBuffer.length() > 0) { m_pasteB.setEnabled(true); } } /** * Get the contents of the paste buffer * * @return the contents of the paste buffer */ public StringBuffer getPasteBuffer() { return m_pasteBuffer; } /** * Utility routine that serializes the supplied Vector of BeanInstances to XML * * @param selectedBeans the vector of BeanInstances to serialize * @return a StringBuffer containing the serialized vector * @throws Exception if a problem occurs */ public StringBuffer copyToBuffer(Vector<Object> selectedBeans) throws Exception { Vector<BeanConnection> associatedConnections = BeanConnection .getConnections(m_mainKFPerspective.getCurrentTabIndex()); /* * BeanConnection.associatedConnections(selectedBeans, * m_mainKFPerspective.getCurrentTabIndex()); */ // xml serialize to a string and store in the // clipboard variable Vector<Vector<?>> v = new Vector<Vector<?>>(); v.setSize(2); v.set(XMLBeans.INDEX_BEANINSTANCES, selectedBeans); v.set(XMLBeans.INDEX_BEANCONNECTIONS, associatedConnections); XMLBeans xml = new XMLBeans(m_beanLayout, m_bcSupport, m_mainKFPerspective.getCurrentTabIndex()); java.io.StringWriter sw = new java.io.StringWriter(); xml.write(sw, v); return sw.getBuffer(); // System.out.println(m_pasteBuffer.toString()); } private boolean copyToClipboard() { Vector<Object> selectedBeans = m_mainKFPerspective.getSelectedBeans(); if (selectedBeans == null || selectedBeans.size() == 0) { return false; } // m_mainKFPerspective.setSelectedBeans(new Vector()); try { m_pasteBuffer = copyToBuffer(selectedBeans); } catch (Exception ex) { m_logPanel.logMessage("[KnowledgeFlow] problem copying beans: " + ex.getMessage()); ex.printStackTrace(); return false; } m_pasteB.setEnabled(true); revalidate(); repaint(); notifyIsDirty(); return true; } protected boolean pasteFromBuffer(int x, int y, StringBuffer pasteBuffer, boolean addUndoPoint) { if (addUndoPoint) { addUndoPoint(); } java.io.StringReader sr = new java.io.StringReader(pasteBuffer.toString()); try { XMLBeans xml = new XMLBeans(m_beanLayout, m_bcSupport, m_mainKFPerspective.getCurrentTabIndex()); @SuppressWarnings("unchecked") Vector<Vector<?>> v = (Vector<Vector<?>>) xml.read(sr); @SuppressWarnings("unchecked") Vector<Object> beans = (Vector<Object>) v.get(XMLBeans.INDEX_BEANINSTANCES); @SuppressWarnings("unchecked") Vector<BeanConnection> connections = (Vector<BeanConnection>) v.get(XMLBeans.INDEX_BEANCONNECTIONS); for (int i = 0; i < beans.size(); i++) { BeanInstance b = (BeanInstance) beans.get(i); if (b.getBean() instanceof MetaBean) { Vector<Object> subFlow = ((MetaBean) b.getBean()).getSubFlow(); for (int j = 0; j < subFlow.size(); j++) { BeanInstance subB = (BeanInstance) subFlow.get(j); subB.removeBean(m_beanLayout, m_mainKFPerspective.getCurrentTabIndex()); if (subB.getBean() instanceof Visible) { ((Visible) subB.getBean()).getVisual().removePropertyChangeListener(this); } } } } // adjust beans coords with respect to x, y. Look for // the smallest x and the smallest y (top left corner of the bounding) // box. int minX = Integer.MAX_VALUE; int minY = Integer.MAX_VALUE; boolean adjust = false; for (int i = 0; i < beans.size(); i++) { BeanInstance b = (BeanInstance) beans.get(i); if (b.getX() < minX) { minX = b.getX(); adjust = true; } if (b.getY() < minY) { minY = b.getY(); adjust = true; } } if (adjust) { int deltaX = x - minX; int deltaY = y - minY; for (int i = 0; i < beans.size(); i++) { BeanInstance b = (BeanInstance) beans.get(i); /* * b.setX(b.getX() + deltaX); b.setY(b.getY() + deltaY); */ b.setXY(b.getX() + deltaX, b.getY() + deltaY); } } // integrate these beans integrateFlow(beans, connections, false, false); for (int i = 0; i < beans.size(); i++) { checkForDuplicateName((BeanInstance) beans.get(i)); } setEnvironment(); notifyIsDirty(); m_mainKFPerspective.setSelectedBeans(beans); } catch (Exception e) { m_logPanel.logMessage("[KnowledgeFlow] problem pasting beans: " + e.getMessage()); e.printStackTrace(); } revalidate(); notifyIsDirty(); return true; } private boolean pasteFromClipboard(int x, int y, StringBuffer pasteBuffer, boolean addUndoPoint) { return pasteFromBuffer(x, y, pasteBuffer, addUndoPoint); } private void deleteSelectedBeans() { Vector<Object> v = m_mainKFPerspective.getSelectedBeans(); if (v.size() > 0) { m_mainKFPerspective.setSelectedBeans(new Vector<Object>()); } addUndoPoint(); for (int i = 0; i < v.size(); i++) { BeanInstance b = (BeanInstance) v.get(i); BeanConnection.removeConnections(b, m_mainKFPerspective.getCurrentTabIndex()); b.removeBean(m_beanLayout, m_mainKFPerspective.getCurrentTabIndex()); if (b instanceof BeanCommon) { String key = ((BeanCommon) b).getCustomName() + "$" + b.hashCode(); m_logPanel.statusMessage(key + "|remove"); } } m_mainKFPerspective.setSelectedBeans(new Vector<Object>()); revalidate(); notifyIsDirty(); m_selectAllB.setEnabled(BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()).size() > 0); } private void addUndoPoint() { try { Stack<File> undo = m_mainKFPerspective.getUndoBuffer(); File tempFile = File.createTempFile("knowledgeFlow", FILE_EXTENSION_XML); tempFile.deleteOnExit(); if (saveLayout(tempFile, m_mainKFPerspective.getCurrentTabIndex(), true)) { undo.push(tempFile); // keep no more than 20 undo points if (undo.size() > 20) { undo.remove(0); } m_undoB.setEnabled(true); } } catch (Exception ex) { m_logPanel.logMessage("[KnowledgeFlow] a problem occurred while trying to " + "create a undo point : " + ex.getMessage()); } } private boolean groupable(Vector<Object> selected, Vector<Object> inputs, Vector<Object> outputs) { boolean groupable = true; // screen the inputs and outputs if (inputs.size() == 0 || outputs.size() == 0) { return false; } // dissallow MetaBeans in the selected set (for the // time being). for (int i = 0; i < selected.size(); i++) { BeanInstance temp = (BeanInstance) selected.elementAt(i); if (temp.getBean() instanceof MetaBean) { groupable = false; return false; } } // show connector dots for input beans for (int i = 0; i < inputs.size(); i++) { BeanInstance temp = (BeanInstance) inputs.elementAt(i); if (temp.getBean() instanceof Visible) { ((Visible) temp.getBean()).getVisual().setDisplayConnectors(true, java.awt.Color.red); } } // show connector dots for output beans for (int i = 0; i < outputs.size(); i++) { BeanInstance temp = (BeanInstance) outputs.elementAt(i); if (temp.getBean() instanceof Visible) { ((Visible) temp.getBean()).getVisual().setDisplayConnectors(true, java.awt.Color.green); } } return groupable; } // right click over empty canvas (not on a bean) private void rightClickCanvasPopup(final int x, final int y) { Vector<BeanConnection> closestConnections = BeanConnection.getClosestConnections(new Point(x, y), 10, m_mainKFPerspective.getCurrentTabIndex()); PopupMenu rightClickMenu = new PopupMenu(); int menuItemCount = 0; if (m_mainKFPerspective.getSelectedBeans().size() > 0 || closestConnections.size() > 0 || (m_pasteBuffer != null && m_pasteBuffer.length() > 0)) { if (m_mainKFPerspective.getSelectedBeans().size() > 0) { MenuItem snapItem = new MenuItem("Snap selected to grid"); snapItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { snapSelectedToGrid(); } }); rightClickMenu.add(snapItem); menuItemCount++; MenuItem copyItem = new MenuItem("Copy selected"); copyItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { copyToClipboard(); m_mainKFPerspective.setSelectedBeans(new Vector<Object>()); } }); rightClickMenu.add(copyItem); menuItemCount++; MenuItem cutItem = new MenuItem("Cut selected"); cutItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // only delete if our copy was successful! if (copyToClipboard()) { deleteSelectedBeans(); } } }); rightClickMenu.add(cutItem); menuItemCount++; MenuItem deleteSelected = new MenuItem("Delete selected"); deleteSelected.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { deleteSelectedBeans(); } }); rightClickMenu.add(deleteSelected); menuItemCount++; // Able to group selected subflow? final Vector<Object> selected = m_mainKFPerspective.getSelectedBeans(); // check if sub flow is valid final Vector<Object> inputs = BeanConnection.inputs(selected, m_mainKFPerspective.getCurrentTabIndex()); final Vector<Object> outputs = BeanConnection.outputs(selected, m_mainKFPerspective.getCurrentTabIndex()); boolean groupable = groupable(selected, inputs, outputs); if (groupable) { MenuItem groupItem = new MenuItem("Group selected"); groupItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { groupSubFlow(selected, inputs, outputs); } }); rightClickMenu.add(groupItem); menuItemCount++; } } if (m_pasteBuffer != null && m_pasteBuffer.length() > 0) { rightClickMenu.addSeparator(); menuItemCount++; MenuItem pasteItem = new MenuItem("Paste"); pasteItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // deserialize, integerate and // position at x, y pasteFromClipboard(x, y, m_pasteBuffer, true); } }); rightClickMenu.add(pasteItem); menuItemCount++; } if (closestConnections.size() > 0) { rightClickMenu.addSeparator(); menuItemCount++; MenuItem deleteConnection = new MenuItem("Delete Connection:"); deleteConnection.setEnabled(false); rightClickMenu.insert(deleteConnection, menuItemCount); menuItemCount++; for (int i = 0; i < closestConnections.size(); i++) { final BeanConnection bc = closestConnections.elementAt(i); String connName = bc.getSourceEventSetDescriptor().getName(); // JMenuItem deleteItem = new JMenuItem(connName); String targetName = ""; if (bc.getTarget().getBean() instanceof BeanCommon) { targetName = ((BeanCommon) bc.getTarget().getBean()).getCustomName(); } else { targetName = bc.getTarget().getBean().getClass().getName(); targetName = targetName.substring(targetName.lastIndexOf('.') + 1, targetName.length()); } MenuItem deleteItem = new MenuItem(connName + "-->" + targetName); deleteItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { addUndoPoint(); bc.remove(m_mainKFPerspective.getCurrentTabIndex()); m_beanLayout.revalidate(); m_beanLayout.repaint(); m_mainKFPerspective.setEditedStatus(true); if (m_mainKFPerspective.getSelectedBeans().size() > 0) { m_mainKFPerspective.setSelectedBeans(new Vector<Object>()); } notifyIsDirty(); } }); rightClickMenu.add(deleteItem); menuItemCount++; } } } if (menuItemCount > 0) { rightClickMenu.addSeparator(); menuItemCount++; } MenuItem noteItem = new MenuItem("New note"); noteItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Note n = new Note(); m_toolBarBean = n; KnowledgeFlowApp.this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); m_mode = ADDING; } }); rightClickMenu.add(noteItem); menuItemCount++; m_beanLayout.add(rightClickMenu); // make sure that popup location takes current scaling into account double z = m_layoutZoom / 100.0; double px = x * z; double py = y * z; rightClickMenu.show(m_beanLayout, (int) px, (int) py); } /** * Initiates the connection process for two beans * * @param esd the EventSetDescriptor for the source bean * @param bi the source bean * @param x the x coordinate to start connecting from * @param y the y coordinate to start connecting from */ private void connectComponents(EventSetDescriptor esd, BeanInstance bi, int x, int y) { // unselect any selected beans on the canvas if (m_mainKFPerspective.getSelectedBeans(m_mainKFPerspective.getCurrentTabIndex()).size() > 0) { m_mainKFPerspective.setSelectedBeans(m_mainKFPerspective.getCurrentTabIndex(), new Vector<Object>()); } // record the event set descriptior for this event m_sourceEventSetDescriptor = esd; Class<?> listenerClass = esd.getListenerType(); // class of the listener JComponent source = (JComponent) bi.getBean(); // now determine which (if any) of the other beans implement this // listener int targetCount = 0; Vector<Object> beanInstances = BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()); for (int i = 0; i < beanInstances.size(); i++) { JComponent bean = (JComponent) ((BeanInstance) beanInstances.elementAt(i)).getBean(); boolean connectable = false; boolean canContinue = false; if (bean != source) { if (bean instanceof MetaBean) { if (((MetaBean) bean).canAcceptConnection(listenerClass)) { canContinue = true; } } else if (listenerClass.isInstance(bean) && bean != source) { canContinue = true; } } if (canContinue) { if (!(bean instanceof BeanCommon)) { connectable = true; // assume this bean is happy to receive a // connection } else { // give this bean a chance to veto any proposed connection via // the listener interface if (((BeanCommon) bean). // connectionAllowed(esd.getName())) { connectionAllowed(esd)) { connectable = true; } } if (connectable) { if (bean instanceof Visible) { targetCount++; ((Visible) bean).getVisual().setDisplayConnectors(true); } } } } // have some possible beans to connect to? if (targetCount > 0) { // System.err.println("target count "+targetCount); if (source instanceof Visible) { ((Visible) source).getVisual().setDisplayConnectors(true); m_editElement = bi; Point closest = ((Visible) source).getVisual().getClosestConnectorPoint(new Point(x, y)); m_startX = (int) closest.getX(); m_startY = (int) closest.getY(); m_oldX = m_startX; m_oldY = m_startY; Graphics2D gx = (Graphics2D) m_beanLayout.getGraphics(); gx.setXORMode(java.awt.Color.white); gx.drawLine(m_startX, m_startY, m_startX, m_startY); gx.dispose(); m_mode = CONNECTING; } } revalidate(); repaint(); notifyIsDirty(); } private void checkForDuplicateName(BeanInstance comp) { if (comp.getBean() instanceof BeanCommon) { String currentName = ((BeanCommon) comp.getBean()).getCustomName(); if (currentName != null && currentName.length() > 0) { Vector<Object> layoutBeans = BeanInstance .getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()); boolean exactMatch = false; int maxCopyNum = 1; for (int i = 0; i < layoutBeans.size(); i++) { BeanInstance b = (BeanInstance) layoutBeans.get(i); if (b.getBean() instanceof BeanCommon) { String compName = ((BeanCommon) b.getBean()).getCustomName(); if (currentName.equals(compName) && (b.getBean() != comp.getBean())) { exactMatch = true; } else { if (compName.startsWith(currentName)) { // see if the comparison bean has a number at the end String num = compName.replace(currentName, ""); try { int compNum = Integer.parseInt(num); if (compNum > maxCopyNum) { maxCopyNum = compNum; } } catch (NumberFormatException e) { } } } } } if (exactMatch) { maxCopyNum++; currentName += "" + maxCopyNum; ((BeanCommon) comp.getBean()).setCustomName(currentName); } } } } private void addComponent(BeanInstance comp, boolean repaint) { if (comp.getBean() instanceof Visible) { ((Visible) comp.getBean()).getVisual().addPropertyChangeListener(this); } if (comp.getBean() instanceof BeanCommon) { ((BeanCommon) comp.getBean()).setLog(m_logPanel); } if (comp.getBean() instanceof MetaBean) { // re-align sub-beans Vector<Object> list; list = ((MetaBean) comp.getBean()).getInputs(); for (int i = 0; i < list.size(); i++) { ((BeanInstance) list.get(i)).setX(comp.getX()); ((BeanInstance) list.get(i)).setY(comp.getY()); } list = ((MetaBean) comp.getBean()).getOutputs(); for (int i = 0; i < list.size(); i++) { ((BeanInstance) list.get(i)).setX(comp.getX()); ((BeanInstance) list.get(i)).setY(comp.getY()); } } if (comp.getBean() instanceof EnvironmentHandler) { ((EnvironmentHandler) comp.getBean()).setEnvironment(m_flowEnvironment); } // check for a duplicate name checkForDuplicateName(comp); KnowledgeFlowApp.this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); if (repaint) { m_beanLayout.repaint(); } m_pointerB.setSelected(true); m_mode = NONE; m_selectAllB.setEnabled(BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()).size() > 0); } private void addComponent(int x, int y) { if (m_toolBarBean instanceof MetaBean) { // need to add the MetaBean's internal connections // to BeanConnection's vector Vector<BeanConnection> associatedConnections = ((MetaBean) m_toolBarBean).getAssociatedConnections(); BeanConnection.getConnections(m_mainKFPerspective.getCurrentTabIndex()).addAll(associatedConnections); // ((MetaBean)m_toolBarBean).setXDrop(x); // ((MetaBean)m_toolBarBean).setYDrop(y); ((MetaBean) m_toolBarBean).addPropertyChangeListenersSubFlow(KnowledgeFlowApp.this); } if (m_toolBarBean instanceof BeanContextChild) { m_bcSupport.add(m_toolBarBean); } BeanInstance bi = new BeanInstance(m_beanLayout, m_toolBarBean, x, y, m_mainKFPerspective.getCurrentTabIndex()); // addBean((JComponent)bi.getBean()); m_toolBarBean = null; addComponent(bi, true); } private void highlightSubFlow(int startX, int startY, int endX, int endY) { java.awt.Rectangle r = new java.awt.Rectangle((startX < endX) ? startX : endX, (startY < endY) ? startY : endY, Math.abs(startX - endX), Math.abs(startY - endY)); // System.err.println(r); Vector<Object> selected = BeanInstance.findInstances(r, m_mainKFPerspective.getCurrentTabIndex()); // show connector dots for selected beans /* * for (int i = 0; i < selected.size(); i++) { BeanInstance temp = * (BeanInstance)selected.elementAt(i); if (temp.getBean() instanceof * Visible) { * ((Visible)temp.getBean()).getVisual().setDisplayConnectors(true); } } */ m_mainKFPerspective.setSelectedBeans(selected); } private void groupSubFlow(Vector<Object> selected, Vector<Object> inputs, Vector<Object> outputs) { int upperLeftX = Integer.MAX_VALUE; int upperLeftY = Integer.MAX_VALUE; int lowerRightX = Integer.MIN_VALUE; int lowerRightY = Integer.MIN_VALUE; for (int i = 0; i < selected.size(); i++) { BeanInstance b = (BeanInstance) selected.get(i); if (b.getX() < upperLeftX) { upperLeftX = b.getX(); } if (b.getY() < upperLeftY) { upperLeftY = b.getY(); } if (b.getX() > lowerRightX) { // ImageIcon ic = ((Visible)b.getBean()).getVisual().getStaticIcon(); // lowerRightX = (b.getX() + ic.getIconWidth()); lowerRightX = b.getX(); } if (b.getY() > lowerRightY) { // ImageIcon ic = ((Visible)b.getBean()).getVisual().getStaticIcon(); // lowerRightY = (b.getY() + ic.getIconHeight()); lowerRightY = b.getY(); } } int bx = upperLeftX + ((lowerRightX - upperLeftX) / 2); int by = upperLeftY + ((lowerRightY - upperLeftY) / 2); new java.awt.Rectangle(upperLeftX, upperLeftY, lowerRightX, lowerRightY); /* * BufferedImage subFlowPreview = null; try { subFlowPreview = * createImage(m_beanLayout, r); } catch (IOException ex) { * ex.printStackTrace(); // drop through quietly } */ // Confirmation pop-up int result = JOptionPane.showConfirmDialog(KnowledgeFlowApp.this, "Group this sub-flow?", "Group Components", JOptionPane.YES_NO_OPTION); if (result == JOptionPane.YES_OPTION) { Vector<BeanConnection> associatedConnections = BeanConnection.associatedConnections(selected, m_mainKFPerspective.getCurrentTabIndex()); String name = JOptionPane.showInputDialog(KnowledgeFlowApp.this, "Enter a name for this group", "MyGroup"); if (name != null) { MetaBean group = new MetaBean(); // group.setXCreate(bx); group.setYCreate(by); // group.setXDrop(bx); group.setYDrop(by); group.setSubFlow(selected); group.setAssociatedConnections(associatedConnections); group.setInputs(inputs); group.setOutputs(outputs); // group.setSubFlowPreview(new ImageIcon(subFlowPreview)); if (name.length() > 0) { // group.getVisual().setText(name); group.setCustomName(name); } // if (group instanceof BeanContextChild) { // m_bcSupport.add(group); // } // int bx = (int)r.getCenterX() - // group.getVisual().m_icon.getIconWidth(); // int by = (int)r.getCenterY() - // group.getVisual().m_icon.getIconHeight(); /* * BeanInstance bi = new BeanInstance(m_beanLayout, group, * (int)r.getX()+(int)(r.getWidth()/2), * (int)r.getY()+(int)(r.getHeight()/2), * m_mainKFPerspective.getCurrentTabIndex()); */ Dimension d = group.getPreferredSize(); ; int dx = (int) (d.getWidth() / 2); int dy = (int) (d.getHeight() / 2); BeanInstance bi = new BeanInstance(m_beanLayout, group, bx + dx, by + dy, m_mainKFPerspective.getCurrentTabIndex()); for (int i = 0; i < selected.size(); i++) { BeanInstance temp = (BeanInstance) selected.elementAt(i); temp.removeBean(m_beanLayout, m_mainKFPerspective.getCurrentTabIndex()); if (temp.getBean() instanceof Visible) { ((Visible) temp.getBean()).getVisual().removePropertyChangeListener(this); } } for (int i = 0; i < associatedConnections.size(); i++) { BeanConnection temp = associatedConnections.elementAt(i); temp.setHidden(true); } group.shiftBeans(bi, true); addComponent(bi, true); } } for (int i = 0; i < selected.size(); i++) { BeanInstance temp = (BeanInstance) selected.elementAt(i); if (temp.getBean() instanceof Visible) { ((Visible) temp.getBean()).getVisual().setDisplayConnectors(false); } } m_mainKFPerspective.setSelectedBeans(new Vector<Object>()); revalidate(); notifyIsDirty(); } /** * Accept property change events * * @param e a <code>PropertyChangeEvent</code> value */ @Override public void propertyChange(PropertyChangeEvent e) { revalidate(); m_beanLayout.repaint(); } /** * Load a pre-saved layout */ private void loadLayout() { m_loadB.setEnabled(false); m_saveB.setEnabled(false); m_playB.setEnabled(false); m_playBB.setEnabled(false); int returnVal = m_FileChooser.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { // stopFlow(); // determine filename File oFile = m_FileChooser.getSelectedFile(); // set internal flow directory environment variable // add extension if necessary if (m_FileChooser.getFileFilter() == m_KfFilter) { if (!oFile.getName().toLowerCase().endsWith(FILE_EXTENSION)) { oFile = new File(oFile.getParent(), oFile.getName() + FILE_EXTENSION); } } else if (m_FileChooser.getFileFilter() == m_KOMLFilter) { if (!oFile.getName().toLowerCase().endsWith(KOML.FILE_EXTENSION + "kf")) { oFile = new File(oFile.getParent(), oFile.getName() + KOML.FILE_EXTENSION + "kf"); } } else if (m_FileChooser.getFileFilter() == m_XMLFilter) { if (!oFile.getName().toLowerCase().endsWith(FILE_EXTENSION_XML)) { oFile = new File(oFile.getParent(), oFile.getName() + FILE_EXTENSION_XML); } } else if (m_FileChooser.getFileFilter() == m_XStreamFilter) { if (!oFile.getName().toLowerCase().endsWith(XStream.FILE_EXTENSION + "kf")) { oFile = new File(oFile.getParent(), oFile.getName() + XStream.FILE_EXTENSION + "kf"); } } String flowName = oFile.getName(); if (flowName.lastIndexOf('.') > 0) { flowName = flowName.substring(0, flowName.lastIndexOf('.')); } loadLayout(oFile, getAllowMultipleTabs()); } m_loadB.setEnabled(true); m_playB.setEnabled(true); m_playBB.setEnabled(true); m_saveB.setEnabled(true); } /** * Load a layout from a file. Supports loading binary and XML serialized flow * files * * @param oFile the file to load from * @param newTab true if the loaded layout should be displayed in a new tab */ public void loadLayout(File oFile, boolean newTab) { loadLayout(oFile, newTab, false); } /** * Load a layout from a file * * @param oFile the file to load from * @param newTab true if the loaded layout should be displayed in a new tab * @param isUndo is this file an "undo" file? */ @SuppressWarnings("unchecked") protected void loadLayout(File oFile, boolean newTab, boolean isUndo) { // stop any running flow first (if we are loading into this tab) if (!newTab) { stopFlow(); } m_loadB.setEnabled(false); m_saveB.setEnabled(false); m_playB.setEnabled(false); m_playBB.setEnabled(false); if (newTab) { String flowName = oFile.getName(); if (flowName.lastIndexOf('.') > 0) { flowName = flowName.substring(0, flowName.lastIndexOf('.')); } m_mainKFPerspective.addTab(flowName); // m_mainKFPerspective.setActiveTab(m_mainKFPerspective.getNumTabs() - 1); m_mainKFPerspective.setFlowFile(oFile); m_mainKFPerspective.setEditedStatus(false); } if (!isUndo) { File absolute = new File(oFile.getAbsolutePath()); // m_flowEnvironment.addVariable("Internal.knowledgeflow.directory", // absolute.getParent()); m_mainKFPerspective.getEnvironmentSettings().addVariable("Internal.knowledgeflow.directory", absolute.getParent()); } try { Vector<Object> beans = new Vector<Object>(); Vector<BeanConnection> connections = new Vector<BeanConnection>(); // KOML? if ((KOML.isPresent()) && (oFile.getAbsolutePath().toLowerCase().endsWith(KOML.FILE_EXTENSION + "kf"))) { Vector<Vector<?>> v = (Vector<Vector<?>>) KOML.read(oFile.getAbsolutePath()); beans = (Vector<Object>) v.get(XMLBeans.INDEX_BEANINSTANCES); connections = (Vector<BeanConnection>) v.get(XMLBeans.INDEX_BEANCONNECTIONS); } /* XStream */else if ((XStream.isPresent()) && (oFile.getAbsolutePath().toLowerCase().endsWith(XStream.FILE_EXTENSION + "kf"))) { Vector<Vector<?>> v = (Vector<Vector<?>>) XStream.read(oFile.getAbsolutePath()); beans = (Vector<Object>) v.get(XMLBeans.INDEX_BEANINSTANCES); connections = (Vector<BeanConnection>) v.get(XMLBeans.INDEX_BEANCONNECTIONS); } /* XML? */else if (oFile.getAbsolutePath().toLowerCase().endsWith(FILE_EXTENSION_XML)) { XMLBeans xml = new XMLBeans(m_beanLayout, m_bcSupport, m_mainKFPerspective.getCurrentTabIndex()); Vector<Vector<?>> v = (Vector<Vector<?>>) xml.read(oFile); beans = (Vector<Object>) v.get(XMLBeans.INDEX_BEANINSTANCES); connections = (Vector<BeanConnection>) v.get(XMLBeans.INDEX_BEANCONNECTIONS); // connections = new Vector(); } /* binary */else { InputStream is = new FileInputStream(oFile); ObjectInputStream ois = new ObjectInputStream(is); beans = (Vector<Object>) ois.readObject(); connections = (Vector<BeanConnection>) ois.readObject(); ois.close(); } integrateFlow(beans, connections, true, false); setEnvironment(); if (newTab) { m_logPanel.clearStatus(); m_logPanel.statusMessage("@!@[KnowledgeFlow]|Flow loaded."); } } catch (Exception ex) { m_logPanel.statusMessage("@!@[KnowledgeFlow]|Unable to load flow (see log)."); m_logPanel.logMessage("[KnowledgeFlow] Unable to load flow (" + ex.getMessage() + ")."); ex.printStackTrace(); } m_loadB.setEnabled(true); m_saveB.setEnabled(true); m_playB.setEnabled(true); m_playBB.setEnabled(true); } /** * Load a flow file from an input stream. Only supports XML serialized flows. * * @param is the input stream to laod from * @param newTab whether to open a new tab in the UI for the flow * @param flowName the name of the flow * @throws Exception if a problem occurs during de-serialization */ public void loadLayout(InputStream is, boolean newTab, String flowName) throws Exception { InputStreamReader isr = new InputStreamReader(is); loadLayout(isr, newTab, flowName); } /** * Load a flow file from a reader. Only supports XML serialized flows. * * @param reader the reader to load from * @param newTab whether to open a new tab in the UI for the flow * @param flowName the name of the flow * @throws Exception if a problem occurs during de-serialization */ @SuppressWarnings("unchecked") public void loadLayout(Reader reader, boolean newTab, String flowName) throws Exception { // stop any running flow first (if we are loading into this tab) if (!newTab) { stopFlow(); } m_loadB.setEnabled(false); m_saveB.setEnabled(false); m_playB.setEnabled(false); m_playBB.setEnabled(false); if (newTab) { m_mainKFPerspective.addTab(flowName); m_mainKFPerspective.setEditedStatus(false); } XMLBeans xml = new XMLBeans(m_beanLayout, m_bcSupport, m_mainKFPerspective.getCurrentTabIndex()); Vector<Vector<?>> v = (Vector<Vector<?>>) xml.read(reader); Vector<Object> beans = (Vector<Object>) v.get(XMLBeans.INDEX_BEANINSTANCES); Vector<BeanConnection> connections = (Vector<BeanConnection>) v.get(XMLBeans.INDEX_BEANCONNECTIONS); integrateFlow(beans, connections, true, false); setEnvironment(); if (newTab) { m_logPanel.clearStatus(); m_logPanel.statusMessage("@!@[KnowledgeFlow]|Flow loaded."); } m_loadB.setEnabled(true); m_saveB.setEnabled(true); m_playB.setEnabled(true); m_playBB.setEnabled(true); } // Link the supplied beans into the KnowledgeFlow gui protected void integrateFlow(Vector<Object> beans, Vector<BeanConnection> connections, boolean replace, boolean notReplaceAndSourcedFromBinary) { java.awt.Color bckC = getBackground(); m_bcSupport = new BeanContextSupport(); m_bcSupport.setDesignTime(true); // register this panel as a property change listener with each // bean for (int i = 0; i < beans.size(); i++) { BeanInstance tempB = (BeanInstance) beans.elementAt(i); if (tempB.getBean() instanceof Visible) { ((Visible) (tempB.getBean())).getVisual().addPropertyChangeListener(this); // A workaround to account for JPanel's with their default // background colour not being serializable in Apple's JRE ((Visible) (tempB.getBean())).getVisual().setBackground(bckC); ((JComponent) (tempB.getBean())).setBackground(bckC); } if (tempB.getBean() instanceof BeanCommon) { ((BeanCommon) (tempB.getBean())).setLog(m_logPanel); } if (tempB.getBean() instanceof BeanContextChild) { m_bcSupport.add(tempB.getBean()); } } if (replace) { BeanInstance.setBeanInstances(beans, m_beanLayout, m_mainKFPerspective.getCurrentTabIndex()); BeanConnection.setConnections(connections, m_mainKFPerspective.getCurrentTabIndex()); } else if (notReplaceAndSourcedFromBinary) { BeanInstance.appendBeans(m_beanLayout, beans, m_mainKFPerspective.getCurrentTabIndex()); BeanConnection.appendConnections(connections, m_mainKFPerspective.getCurrentTabIndex()); } revalidate(); m_beanLayout.revalidate(); m_beanLayout.repaint(); notifyIsDirty(); m_selectAllB.setEnabled(BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()).size() > 0); } /** * Set the flow for the KnowledgeFlow to edit. Assumes that client has loaded * a Vector of beans and a Vector of connections. the supplied beans and * connections are deep-copied via serialization before being set in the * layout. The beans get added to the flow at position 0. * * @param v a Vector containing a Vector of beans and a Vector of connections * @exception Exception if something goes wrong */ @SuppressWarnings("unchecked") public void setFlow(Vector<Vector<?>> v) throws Exception { // Vector beansCopy = null, connectionsCopy = null; // clearLayout(); if (getAllowMultipleTabs()) { throw new Exception("[KnowledgeFlow] setFlow() - can only set a flow in " + "singe tab only mode"); } /* * int tabI = 0; * * BeanInstance. * removeAllBeansFromContainer((JComponent)m_mainKFPerspective. * getBeanLayout(tabI), tabI); BeanInstance.setBeanInstances(new Vector(), * m_mainKFPerspective.getBeanLayout(tabI)); * BeanConnection.setConnections(new Vector()); */ // m_mainKFPerspective.removeTab(0); // m_mainKFPerspective.addTab("Untitled"); m_beanLayout.removeAll(); BeanInstance.init(); BeanConnection.init(); SerializedObject so = new SerializedObject(v); Vector<Vector<?>> copy = (Vector<Vector<?>>) so.getObject(); Vector<Object> beans = (Vector<Object>) copy.elementAt(0); Vector<BeanConnection> connections = (Vector<BeanConnection>) copy.elementAt(1); // reset environment variables m_flowEnvironment = new Environment(); integrateFlow(beans, connections, true, false); revalidate(); notifyIsDirty(); } /** * Gets the current flow being edited. The flow is returned as a single Vector * containing two other Vectors: the beans and the connections. These two * vectors are deep-copied via serialization before being returned. * * @return the current flow being edited * @throws Exception if a problem occurs */ public Vector<Vector<?>> getFlow() throws Exception { Vector<Vector<?>> v = new Vector<Vector<?>>(); Vector<Object> beans = BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()); Vector<BeanConnection> connections = BeanConnection .getConnections(m_mainKFPerspective.getCurrentTabIndex()); detachFromLayout(beans); v.add(beans); v.add(connections); SerializedObject so = new SerializedObject(v); @SuppressWarnings("unchecked") Vector<Vector<?>> copy = (Vector<Vector<?>>) so.getObject(); // tempWrite(beans, connections); integrateFlow(beans, connections, true, false); return copy; } /** * Returns the current flow being edited in XML format. * * @return the current flow as an XML string * @throws Exception if a problem occurs */ public String getFlowXML() throws Exception { Vector<Object> beans = BeanInstance.getBeanInstances(m_mainKFPerspective.getCurrentTabIndex()); StringBuffer buff = copyToBuffer(beans); return buff.toString(); } /** * Utility method to create an image of a region of the given component * * @param component the component to create an image of * @param region the region of the component to put into the image * @return the image * @throws IOException */ protected static BufferedImage createImage(JComponent component, Rectangle region) throws IOException { boolean opaqueValue = component.isOpaque(); component.setOpaque(true); BufferedImage image = new BufferedImage(region.width, region.height, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = image.createGraphics(); g2d.translate(-region.getX(), -region.getY()); // g2d.setClip( region ); component.paint(g2d); g2d.dispose(); component.setOpaque(opaqueValue); return image; } // Remove this panel as a property changle listener from // each bean private void detachFromLayout(Vector<Object> beans) { for (int i = 0; i < beans.size(); i++) { BeanInstance tempB = (BeanInstance) beans.elementAt(i); if (tempB.getBean() instanceof Visible) { ((Visible) (tempB.getBean())).getVisual().removePropertyChangeListener(this); if (tempB.getBean() instanceof MetaBean) { ((MetaBean) tempB.getBean()).removePropertyChangeListenersSubFlow(this); } // A workaround to account for JPanel's with their default // background colour not being serializable in Apple's JRE. // JComponents are rendered with a funky stripy background // under OS X using java.awt.TexturePaint - unfortunately // TexturePaint doesn't implement Serializable. ((Visible) (tempB.getBean())).getVisual().setBackground(java.awt.Color.white); ((JComponent) (tempB.getBean())).setBackground(java.awt.Color.white); } } } public void saveLayout(File toFile, int tabIndex) { saveLayout(toFile, tabIndex, false); } protected boolean saveLayout(File sFile, int tabIndex, boolean isUndoPoint) { java.awt.Color bckC = getBackground(); Vector<Object> beans = BeanInstance.getBeanInstances(tabIndex); detachFromLayout(beans); detachFromLayout(beans); // now serialize components vector and connections vector try { // KOML? if ((KOML.isPresent()) && (sFile.getAbsolutePath().toLowerCase().endsWith(KOML.FILE_EXTENSION + "kf"))) { Vector<Vector<?>> v = new Vector<Vector<?>>(); v.setSize(2); v.set(XMLBeans.INDEX_BEANINSTANCES, beans); v.set(XMLBeans.INDEX_BEANCONNECTIONS, BeanConnection.getConnections(tabIndex)); KOML.write(sFile.getAbsolutePath(), v); } /* XStream */else if ((XStream.isPresent()) && (sFile.getAbsolutePath().toLowerCase().endsWith(XStream.FILE_EXTENSION + "kf"))) { Vector<Vector<?>> v = new Vector<Vector<?>>(); v.setSize(2); v.set(XMLBeans.INDEX_BEANINSTANCES, beans); v.set(XMLBeans.INDEX_BEANCONNECTIONS, BeanConnection.getConnections(tabIndex)); XStream.write(sFile.getAbsolutePath(), v); } /* XML? */else if (sFile.getAbsolutePath().toLowerCase().endsWith(FILE_EXTENSION_XML)) { Vector<Vector<?>> v = new Vector<Vector<?>>(); v.setSize(2); v.set(XMLBeans.INDEX_BEANINSTANCES, beans); v.set(XMLBeans.INDEX_BEANCONNECTIONS, BeanConnection.getConnections(tabIndex)); XMLBeans xml = new XMLBeans(m_beanLayout, m_bcSupport, tabIndex); // XML flows are tagged as encoded with UTF-8 BufferedWriter br = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(sFile), "UTF-8")); xml.write(br, v); } /* binary */else { OutputStream os = new FileOutputStream(sFile); ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(beans); oos.writeObject(BeanConnection.getConnections(tabIndex)); oos.flush(); oos.close(); } } catch (Exception ex) { m_logPanel.statusMessage("@!@[KnowledgeFlow]|Unable to save flow (see log)."); m_logPanel.logMessage("[KnowledgeFlow] Unable to save flow (" + ex.getMessage() + ")."); ex.printStackTrace(); return false; } finally { // restore this panel as a property change listener in the beans for (int i = 0; i < beans.size(); i++) { BeanInstance tempB = (BeanInstance) beans.elementAt(i); if (tempB.getBean() instanceof Visible) { ((Visible) (tempB.getBean())).getVisual().addPropertyChangeListener(this); if (tempB.getBean() instanceof MetaBean) { ((MetaBean) tempB.getBean()).addPropertyChangeListenersSubFlow(this); } // Restore the default background colour ((Visible) (tempB.getBean())).getVisual().setBackground(bckC); ((JComponent) (tempB.getBean())).setBackground(bckC); } } if (!isUndoPoint) { Environment e = m_mainKFPerspective.getEnvironmentSettings(tabIndex); e.addVariable("Internal.knowledgeflow.directory", new File(sFile.getAbsolutePath()).getParent()); m_mainKFPerspective.setEditedStatus(tabIndex, false); String tabTitle = sFile.getName(); tabTitle = tabTitle.substring(0, tabTitle.lastIndexOf('.')); m_mainKFPerspective.setTabTitle(tabIndex, tabTitle); } } return true; } /** * Serialize the layout to a file */ private void saveLayout(int tabIndex, boolean showDialog) { getBackground(); File sFile = m_mainKFPerspective.getFlowFile(tabIndex); int returnVal = JFileChooser.APPROVE_OPTION; boolean shownDialog = false; if (showDialog || sFile.getName().equals("-NONE-")) { returnVal = m_FileChooser.showSaveDialog(this); shownDialog = true; } if (returnVal == JFileChooser.APPROVE_OPTION) { // temporarily remove this panel as a property changle listener from // each bean Vector<Object> beans = BeanInstance.getBeanInstances(tabIndex); detachFromLayout(beans); // determine filename (if necessary) if (shownDialog) { sFile = m_FileChooser.getSelectedFile(); } // add extension if necessary if (m_FileChooser.getFileFilter() == m_KfFilter) { if (!sFile.getName().toLowerCase().endsWith(FILE_EXTENSION)) { sFile = new File(sFile.getParent(), sFile.getName() + FILE_EXTENSION); } } else if (m_FileChooser.getFileFilter() == m_KOMLFilter) { if (!sFile.getName().toLowerCase().endsWith(KOML.FILE_EXTENSION + "kf")) { sFile = new File(sFile.getParent(), sFile.getName() + KOML.FILE_EXTENSION + "kf"); } } else if (m_FileChooser.getFileFilter() == m_XStreamFilter) { if (!sFile.getName().toLowerCase().endsWith(XStream.FILE_EXTENSION + "kf")) { sFile = new File(sFile.getParent(), sFile.getName() + XStream.FILE_EXTENSION + "kf"); } } else if (m_FileChooser.getFileFilter() == m_XMLFilter) { if (!sFile.getName().toLowerCase().endsWith(FILE_EXTENSION_XML)) { sFile = new File(sFile.getParent(), sFile.getName() + FILE_EXTENSION_XML); } } saveLayout(sFile, m_mainKFPerspective.getCurrentTabIndex(), false); m_mainKFPerspective.setFlowFile(tabIndex, sFile); } } /** * Save the knowledge flow into the OutputStream passed at input. Only * supports saving the layout data (no trained models) to XML. * * @param out the output stream to save the layout in */ public void saveLayout(OutputStream out, int tabIndex) { // temporarily remove this panel as a property changle listener from // each bean Vector<Object> beans = BeanInstance.getBeanInstances(tabIndex); for (int i = 0; i < beans.size(); i++) { BeanInstance tempB = (BeanInstance) beans.elementAt(i); if (tempB.getBean() instanceof Visible) { ((Visible) (tempB.getBean())).getVisual().removePropertyChangeListener(this); if (tempB.getBean() instanceof MetaBean) { ((MetaBean) tempB.getBean()).removePropertyChangeListenersSubFlow(this); } } } // now serialize components vector and connections vector try { Vector<Vector<?>> v = new Vector<Vector<?>>(); v.setSize(2); v.set(XMLBeans.INDEX_BEANINSTANCES, beans); v.set(XMLBeans.INDEX_BEANCONNECTIONS, BeanConnection.getConnections(tabIndex)); XMLBeans xml = new XMLBeans(m_beanLayout, m_bcSupport, tabIndex); xml.write(out, v); } catch (Exception ex) { ex.printStackTrace(); } finally { // restore this panel as a property change listener in the beans for (int i = 0; i < beans.size(); i++) { BeanInstance tempB = (BeanInstance) beans.elementAt(i); if (tempB.getBean() instanceof Visible) { ((Visible) (tempB.getBean())).getVisual().addPropertyChangeListener(this); if (tempB.getBean() instanceof MetaBean) { ((MetaBean) tempB.getBean()).addPropertyChangeListenersSubFlow(this); } } } } } @SuppressWarnings("unchecked") private void loadUserComponents() { Vector<Vector<Object>> tempV = null; // String ext = ""; /* * if (m_UserComponentsInXML) ext = USERCOMPONENTS_XML_EXTENSION; */ File sFile = new File(weka.core.WekaPackageManager.WEKA_HOME.getPath() + File.separator + "knowledgeFlow" + File.separator + "userComponents"); /* * new File(System.getProperty("user.home") +File.separator + * ".knowledgeFlow" +File.separator + "userComponents" +ext); */ if (sFile.exists()) { try { /* * if (m_UserComponentsInXML) { XMLBeans xml = new * XMLBeans(m_beanLayout, m_bcSupport, XMLBeans.DATATYPE_USERCOMPONENTS, * 0); tempV = (Vector) xml.read(sFile); } else { */ InputStream is = new FileInputStream(sFile); ObjectInputStream ois = new ObjectInputStream(is); tempV = (Vector<Vector<Object>>) ois.readObject(); ois.close(); // } } catch (Exception ex) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "[KnowledgeFlow] Problem reading user components."); ex.printStackTrace(); return; } if (tempV.size() > 0) { DefaultTreeModel model = (DefaultTreeModel) m_componentTree.getModel(); DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); if (m_userCompNode == null) { m_userCompNode = new InvisibleNode("User"); model.insertNodeInto(m_userCompNode, root, 0); } // add the components for (int i = 0; i < tempV.size(); i++) { Vector<Object> tempB = tempV.elementAt(i); String displayName = (String) tempB.get(0); tempB.get(1); ImageIcon scaledIcon = (ImageIcon) tempB.get(2); JTreeLeafDetails treeLeaf = new JTreeLeafDetails(displayName, tempB, scaledIcon); DefaultMutableTreeNode newUserComp = new InvisibleNode(treeLeaf); model.insertNodeInto(newUserComp, m_userCompNode, 0); // add to the list of user components m_userComponents.add(tempB); // addToUserToolBar(tempB, false); // addToUserTreeNode(tempB, false); } } } } private void installWindowListenerForSavingUserStuff() { ((java.awt.Window) getTopLevelAncestor()).addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(java.awt.event.WindowEvent e) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.INFO, "[KnowledgeFlow] Saving user components...."); File sFile = new File(WekaPackageManager.WEKA_HOME.getPath() + File.separator + "knowledgeFlow"); if (!sFile.exists()) { if (!sFile.mkdir()) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "[KnowledgeFlow] Unable to create \"" + sFile.getPath() + "\" directory"); } } try { String ext = ""; /* * if (m_UserComponentsInXML) ext = USERCOMPONENTS_XML_EXTENSION; */ File sFile2 = new File(sFile.getAbsolutePath() + File.separator + "userComponents" + ext); /* * if (m_UserComponentsInXML) { XMLBeans xml = new * XMLBeans(m_beanLayout, m_bcSupport, * XMLBeans.DATATYPE_USERCOMPONENTS, * m_mainKFPerspective.getCurrentTabIndex()); xml.write(sFile2, * m_userComponents); } else { */ OutputStream os = new FileOutputStream(sFile2); ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(m_userComponents); oos.flush(); oos.close(); // } } catch (Exception ex) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "[KnowledgeFlow] Unable to save user components"); ex.printStackTrace(); } // if (VISIBLE_PERSPECTIVES.size() > 0) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.INFO, "Saving preferences for selected perspectives..."); sFile = new File(weka.core.WekaPackageManager.PROPERTIES_DIR.toString() + File.separator + "VisiblePerspectives.props"); try { FileWriter f = new FileWriter(sFile); f.write("weka.gui.beans.KnowledgeFlow.SelectedPerspectives="); int i = 0; for (String p : BeansProperties.VISIBLE_PERSPECTIVES) { if (i > 0) { f.write(","); } f.write(p); i++; } f.write("\n"); f.write("weka.gui.beans.KnowledgeFlow.PerspectiveToolBarVisisble=" + ((m_configAndPerspectivesVisible) ? "yes" : "no")); f.write("\n"); f.close(); } catch (Exception ex) { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "[KnowledgeFlow] Unable to save user perspectives preferences"); ex.printStackTrace(); } // } } }); } /** * Utility method for grabbing the global info help (if it exists) from an * arbitrary object * * @param tempBean the object to grab global info from * @return the global help info or null if global info does not exist */ public static String getGlobalInfo(Object tempBean) { return Utils.getGlobalInfo(tempBean, true); } /** * variable for the KnowLedgeFlow class which would be set to null by the * memory monitoring thread to free up some memory if we running out of * memory. */ private static KnowledgeFlowApp m_knowledgeFlow; /** for monitoring the Memory consumption */ private static Memory m_Memory = new Memory(true); // list of things to be notified when the startup process of // the KnowledgeFlow is complete public static Vector<StartUpListener> s_startupListeners = new Vector<StartUpListener>(); // modifications by Zerbetto // If showFileMenu is true, the file menu (open file, new file, save file // buttons) is showed private boolean m_showFileMenu = true; /** * Create the singleton instance of the KnowledgeFlow * * @param args can contain a file argument for loading a flow layout (format: * "file=[path to layout file]") Modified by Zerbetto: you can * specify the path of a knowledge flow layout file at input */ public static void createSingleton(String[] args) { // modifications by Zerbetto 05-12-2007 String fileName = null; boolean showFileMenu = true; if ((args != null) && (args.length > 0)) { for (String arg : args) { if (arg.startsWith("file=")) { fileName = arg.substring("file=".length()); } else if (arg.startsWith("showFileMenu=")) { showFileMenu = Boolean.parseBoolean(arg.substring("showFileMenu=".length())); } } } if (m_knowledgeFlow == null) { m_knowledgeFlow = new KnowledgeFlowApp(showFileMenu); } // end modifications by Zerbetto // notify listeners (if any) for (int i = 0; i < s_startupListeners.size(); i++) { s_startupListeners.elementAt(i).startUpComplete(); } // modifications by Zerbetto 05-12-2007 if (fileName != null) { m_knowledgeFlow.loadInitialLayout(fileName); } // end modifications } public static void disposeSingleton() { m_knowledgeFlow = null; } /** * Return the singleton instance of the KnowledgeFlow * * @return the singleton instance */ public static KnowledgeFlowApp getSingleton() { return m_knowledgeFlow; } /** * Add a listener to be notified when startup is complete * * @param s a listener to add */ public static void addStartupListener(StartUpListener s) { s_startupListeners.add(s); } /** * Loads the specified file at input * * Added by Zerbetto */ // modifications by Zerbetto 05-12-2007 private void loadInitialLayout(String fileName) { File oFile = new File(fileName); if (oFile.exists() && oFile.isFile()) { m_FileChooser.setSelectedFile(oFile); int index = fileName.lastIndexOf('.'); if (index != -1) { String extension = fileName.substring(index); if (FILE_EXTENSION_XML.equalsIgnoreCase(extension)) { m_FileChooser.setFileFilter(m_knowledgeFlow.m_XMLFilter); } else if (FILE_EXTENSION.equalsIgnoreCase(extension)) { m_FileChooser.setFileFilter(m_knowledgeFlow.m_KfFilter); } } } else { weka.core.logging.Logger.log(weka.core.logging.Logger.Level.WARNING, "[KnowledgeFlow] File '" + fileName + "' does not exists."); } loadLayout(oFile, true); } public void setAllowMultipleTabs(boolean multiple) { m_allowMultipleTabs = multiple; if (!multiple) { m_newB.setEnabled(false); if (m_configAndPerspectives != null) { remove(m_configAndPerspectives); } } } public boolean getAllowMultipleTabs() { return m_allowMultipleTabs; } // end modifications /** * Notifies to the parent swt that the layout is dirty * * Added by Zerbetto */ private void notifyIsDirty() { // this.firePropertyChange(new Integer(IEditorPart.PROP_DIRTY).toString(), // null, null); this.firePropertyChange("PROP_DIRTY", null, null); } /** * Main method. * * @param args a <code>String[]</code> value */ public static void main(String[] args) { LookAndFeel.setLookAndFeel(); try { // uncomment to disable the memory management: // m_Memory.setEnabled(false); final javax.swing.JFrame jf = new javax.swing.JFrame(); jf.getContentPane().setLayout(new java.awt.BorderLayout()); // final KnowledgeFlowApp tm = new KnowledgeFlowApp(); // m_knowledgeFlow = new KnowledgeFlowApp(true); for (int i = 0; i < args.length; i++) { if (args[i].toLowerCase().endsWith(".kf") || args[i].toLowerCase().endsWith(".kfml")) { args[i] = "file=" + args[i]; } } KnowledgeFlowApp.createSingleton(args); Image icon = Toolkit.getDefaultToolkit().getImage( m_knowledgeFlow.getClass().getClassLoader().getResource("weka/gui/weka_icon_new_48.png")); jf.setIconImage(icon); jf.getContentPane().add(m_knowledgeFlow, java.awt.BorderLayout.CENTER); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setSize(1024, 768); jf.setVisible(true); Thread memMonitor = new Thread() { @SuppressWarnings("static-access") @Override public void run() { while (true) { // try { // System.out.println("Before sleeping"); // this.sleep(10); if (m_Memory.isOutOfMemory()) { // clean up jf.dispose(); m_knowledgeFlow = null; System.gc(); // display error System.err.println("\n[KnowledgeFlow] displayed message:"); m_Memory.showOutOfMemory(); System.err.println("\nexiting"); System.exit(-1); } // } catch (InterruptedException ex) { // ex.printStackTrace(); // } } } }; memMonitor.setPriority(Thread.NORM_PRIORITY); memMonitor.start(); } catch (Exception ex) { ex.printStackTrace(); System.err.println(ex.getMessage()); } } }