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/>. */ /* * WekaInstanceViewer.java * Copyright (C) 2010-2017 University of Waikato, Hamilton, New Zealand */ package adams.flow.sink; import adams.data.report.DataType; import adams.data.report.Field; import adams.flow.core.Token; import adams.gui.core.BasePanel; import adams.gui.core.ExtensionFileFilter; import adams.gui.visualization.core.ColorProvider; import adams.gui.visualization.core.DefaultColorProvider; import adams.gui.visualization.instance.AbstractInstancePaintlet; import adams.gui.visualization.instance.AbstractInstancePanelUpdater; import adams.gui.visualization.instance.InstanceContainer; import adams.gui.visualization.instance.InstanceContainerManager; import adams.gui.visualization.instance.InstanceLinePaintlet; import adams.gui.visualization.instance.InstancePanel; import adams.gui.visualization.instance.SimpleInstancePanelUpdater; import java.awt.BorderLayout; /** <!-- globalinfo-start --> * Actor for displaying adams.data.instance.Instance objects in a graphical way (using the internal format), like the 'Instance Explorer' tool. * <br><br> <!-- globalinfo-end --> * <!-- flow-summary-start --> * Input/output:<br> * - accepts:<br> * weka.core.Instance<br> * adams.data.instance.Instance<br> * <br><br> <!-- flow-summary-end --> * <!-- options-start --> * <pre>-logging-level <OFF|SEVERE|WARNING|INFO|CONFIG|FINE|FINER|FINEST> (property: loggingLevel) * The logging level for outputting errors and debugging output. * default: WARNING * </pre> * * <pre>-name <java.lang.String> (property: name) * The name of the actor. * default: WekaInstanceViewer * </pre> * * <pre>-annotation <adams.core.base.BaseAnnotation> (property: annotations) * The annotations to attach to this actor. * default: * </pre> * * <pre>-skip <boolean> (property: skip) * If set to true, transformation is skipped and the input token is just forwarded * as it is. * default: false * </pre> * * <pre>-stop-flow-on-error <boolean> (property: stopFlowOnError) * If set to true, the flow gets stopped in case this actor encounters an error; * useful for critical actors. * default: false * </pre> * * <pre>-silent <boolean> (property: silent) * If enabled, then no errors are output in the console; Note: the enclosing * actor handler must have this enabled as well. * default: false * </pre> * * <pre>-short-title <boolean> (property: shortTitle) * If enabled uses just the name for the title instead of the actor's full * name. * default: false * </pre> * * <pre>-display-in-editor <boolean> (property: displayInEditor) * If enabled displays the panel in a tab in the flow editor rather than in * a separate frame. * default: false * </pre> * * <pre>-width <int> (property: width) * The width of the dialog. * default: 800 * minimum: -1 * </pre> * * <pre>-height <int> (property: height) * The height of the dialog. * default: 500 * minimum: -1 * </pre> * * <pre>-x <int> (property: x) * The X position of the dialog (>=0: absolute, -1: left, -2: center, -3: right * ). * default: -1 * minimum: -3 * </pre> * * <pre>-y <int> (property: y) * The Y position of the dialog (>=0: absolute, -1: top, -2: center, -3: bottom * ). * default: -1 * minimum: -3 * </pre> * * <pre>-writer <adams.gui.print.JComponentWriter> (property: writer) * The writer to use for generating the graphics output. * default: adams.gui.print.NullWriter * </pre> * * <pre>-color-provider <adams.gui.visualization.core.ColorProvider> (property: colorProvider) * The color provider in use for coloring the instances. * default: adams.gui.visualization.core.DefaultColorProvider * </pre> * * <pre>-paintlet <adams.gui.visualization.instance.AbstractInstancePaintlet> (property: paintlet) * The paintlet to use for drawing the instances. * default: adams.gui.visualization.instance.InstanceLinePaintlet * </pre> * * <pre>-zoom-overview <boolean> (property: zoomOverview) * If enabled, a zoom overview panel gets displayed as well. * default: false * </pre> * * <pre>-id <java.lang.String> (property: ID) * The name of the attribute/field to use as the ID in the display. * default: * </pre> * * <pre>-updater <adams.gui.visualization.instance.AbstractInstancePanelUpdater> (property: updater) * The updater in use for updating the visualization. * default: adams.gui.visualization.instance.SimpleInstancePanelUpdater * </pre> * <!-- options-end --> * * @author fracpete (fracpete at waikato dot ac dot nz) * @version $Revision$ */ public class WekaInstanceViewer extends AbstractGraphicalDisplay implements DisplayPanelProvider, TextSupplier { /** for serialization. */ private static final long serialVersionUID = 1283926389472133810L; /** the panel with the instances. */ protected InstancePanel m_InstancePanel; /** the color provider to use. */ protected ColorProvider m_ColorProvider; /** the paintlet to use. */ protected AbstractInstancePaintlet m_Paintlet; /** whether to display the zoom overview. */ protected boolean m_ZoomOverview; /** the name of the attribute/field to use as ID. */ protected String m_ID; /** the updater to use. */ protected AbstractInstancePanelUpdater m_Updater; /** * Returns a string describing the object. * * @return a description suitable for displaying in the gui */ @Override public String globalInfo() { return "Actor for displaying adams.data.instance.Instance objects in a " + "graphical way (using the internal format), like the 'Instance Explorer' tool."; } /** * Adds options to the internal list of options. */ @Override public void defineOptions() { super.defineOptions(); m_OptionManager.add("color-provider", "colorProvider", new DefaultColorProvider()); m_OptionManager.add("paintlet", "paintlet", new InstanceLinePaintlet()); m_OptionManager.add("zoom-overview", "zoomOverview", false); m_OptionManager.add("id", "ID", ""); m_OptionManager.add("updater", "updater", new SimpleInstancePanelUpdater()); } /** * Returns the default width for the dialog. * * @return the default width */ @Override protected int getDefaultWidth() { return 800; } /** * Returns the default height for the dialog. * * @return the default height */ @Override protected int getDefaultHeight() { return 500; } /** * Sets the color provider to use. * * @param value the color provider */ public void setColorProvider(ColorProvider value) { m_ColorProvider = value; reset(); } /** * Returns the color provider in use. * * @return the color provider */ public ColorProvider getColorProvider() { return m_ColorProvider; } /** * Returns the tip text for this property. * * @return tip text for this property suitable for * displaying in the GUI or for listing the options. */ public String colorProviderTipText() { return "The color provider in use for coloring the instances."; } /** * Sets the paintlet to use. * * @param value the paintlet */ public void setPaintlet(AbstractInstancePaintlet value) { m_Paintlet = value; reset(); } /** * Returns the paintlet in use. * * @return the paintlet */ public AbstractInstancePaintlet getPaintlet() { return m_Paintlet; } /** * Returns the tip text for this property. * * @return tip text for this property suitable for * displaying in the GUI or for listing the options. */ public String paintletTipText() { return "The paintlet to use for drawing the instances."; } /** * Sets whether to display the zoom overview. * * @param value if true then the zoom overview will get displayed */ public void setZoomOverview(boolean value) { m_ZoomOverview = value; reset(); } /** * Returns whether the zoom overview gets displayed. * * @return true if the zoom overview gets displayed */ public boolean getZoomOverview() { return m_ZoomOverview; } /** * Returns the tip text for this property. * * @return tip text for this property suitable for * displaying in the GUI or for listing the options. */ public String zoomOverviewTipText() { return "If enabled, a zoom overview panel gets displayed as well."; } /** * Sets the name of the attribute/field to use as ID in the display. * * @param value the attribute/field name */ public void setID(String value) { m_ID = value; reset(); } /** * Returns the name of the attribute/field to use as ID in the display. * * @return the attribute/field name */ public String getID() { return m_ID; } /** * Returns the tip text for this property. * * @return tip text for this property suitable for * displaying in the GUI or for listing the options. */ public String IDTipText() { return "The name of the attribute/field to use as the ID in the display."; } /** * Sets the updater to use. * * @param value the updater */ public void setUpdater(AbstractInstancePanelUpdater value) { m_Updater = value; reset(); } /** * Returns the updater in use. * * @return the updater */ public AbstractInstancePanelUpdater getUpdater() { return m_Updater; } /** * Returns the tip text for this property. * * @return tip text for this property suitable for * displaying in the GUI or for listing the options. */ public String updaterTipText() { return "The updater in use for updating the visualization."; } /** * Clears the content of the panel. */ @Override public void clearPanel() { if (m_InstancePanel != null) m_InstancePanel.getContainerManager().clear(); } /** * Creates the panel to display in the dialog. * * @return the panel */ @Override protected BasePanel newPanel() { BasePanel result; result = new BasePanel(new BorderLayout()); m_InstancePanel = new InstancePanel(); m_InstancePanel.setZoomOverviewPanelVisible(m_ZoomOverview); m_InstancePanel.getContainerManager().setColorProvider(m_ColorProvider.shallowCopy(true)); m_InstancePanel.setDataPaintlet(m_Paintlet.shallowCopy(true)); result.add(m_InstancePanel, BorderLayout.CENTER); return result; } /** * Returns the class that the consumer accepts. * * @return <!-- flow-accepts-start -->weka.core.Instance.class, adams.data.instance.Instance.class<!-- flow-accepts-end --> */ public Class[] accepts() { return new Class[] { weka.core.Instance.class, adams.data.instance.Instance.class }; } /** * Displays the token (the panel and dialog have already been created at * this stage). * * @param token the token to display */ @Override protected void display(Token token) { InstanceContainerManager manager; InstanceContainer cont; weka.core.Instance winst; weka.core.Attribute att; String id; adams.data.instance.Instance inst; if (token.getPayload() instanceof weka.core.Instance) { winst = (weka.core.Instance) token.getPayload(); inst = new adams.data.instance.Instance(); inst.set(winst); if (!m_ID.isEmpty()) { att = winst.dataset().attribute(m_ID); if (att != null) { if (att.isNominal() || att.isString()) id = winst.stringValue(att.index()); else id = "" + winst.value(att.index()); inst.setID(id); } } } else { inst = (adams.data.instance.Instance) token.getPayload(); if (inst.hasReport() && inst.getReport().hasValue(m_ID)) inst.setID("" + inst.getReport().getValue(new Field(m_ID, DataType.UNKNOWN))); } manager = m_InstancePanel.getContainerManager(); cont = manager.newContainer(inst); manager.startUpdate(); manager.add(cont); m_Updater.update(m_InstancePanel, cont); } /** * Removes all graphical components. */ @Override protected void cleanUpGUI() { super.cleanUpGUI(); if (m_InstancePanel != null) m_InstancePanel.getContainerManager().clear(); } /** * Creates a new panel for the token. * * @param token the token to display in a new panel, can be null * @return the generated panel */ public AbstractDisplayPanel createDisplayPanel(Token token) { AbstractDisplayPanel result; result = new AbstractTextDisplayPanel(getClass().getSimpleName()) { private static final long serialVersionUID = -5618543590920864397L; protected InstancePanel m_InstancePanel; @Override protected void initGUI() { super.initGUI(); setLayout(new BorderLayout()); m_InstancePanel = new InstancePanel(); add(m_InstancePanel, BorderLayout.CENTER); } @Override public void display(Token token) { adams.data.instance.Instance inst = null; if (token.getPayload() instanceof weka.core.Instance) { inst = new adams.data.instance.Instance(); inst.set((weka.core.Instance) token.getPayload()); } else { inst = (adams.data.instance.Instance) token.getPayload(); } InstanceContainerManager manager = m_InstancePanel.getContainerManager(); InstanceContainer cont = manager.newContainer(inst); manager.add(cont); } @Override public ExtensionFileFilter getCustomTextFileFilter() { return new ExtensionFileFilter("ARFF file", "arff"); } @Override public String supplyText() { return WekaInstanceViewer.supplyText(m_InstancePanel); } @Override public void clearPanel() { m_InstancePanel.getContainerManager().clear(); } public void cleanUp() { m_InstancePanel.getContainerManager().clear(); } }; if (token != null) result.display(token); return result; } /** * Returns the text for the menu item. * * @return the menu item text, null for default */ public String getCustomSupplyTextMenuItemCaption() { return "Save instances as..."; } /** * Returns a custom file filter for the file chooser. * * @return the file filter, null if to use default one */ @Override public ExtensionFileFilter getCustomTextFileFilter() { return new ExtensionFileFilter("ARFF file", "arff"); } /** * Supplies the text. * * @return the text, null if none available */ public String supplyText() { return supplyText(m_InstancePanel); } /** * Returns the displayed instances as ARFF. * * @param panel the panel to obtain the data form * @return the generated ARFF content or null if no data available */ protected static String supplyText(InstancePanel panel) { InstanceContainerManager manager; weka.core.Instances data; int i; if (panel == null) return null; manager = panel.getContainerManager(); if (manager.countVisible() == 0) return null; data = new weka.core.Instances(manager.getVisible(0).getData().getDatasetHeader()); for (i = 0; i < manager.countVisible(); i++) data.add(manager.getVisible(i).getData().toInstance()); return data.toString(); } /** * Returns whether the created display panel requires a scroll pane or not. * * @return true if the display panel requires a scroll pane */ public boolean displayPanelRequiresScrollPane() { return true; } /** * Cleans up after the execution has finished. */ @Override public void wrapUp() { if (m_Panel != null) m_Updater.update(m_InstancePanel); super.wrapUp(); } }