Java tutorial
/** * Copyright (C) 2001-2015 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.template.gui; import com.rapidminer.example.Attribute; import com.rapidminer.example.ExampleSet; import com.rapidminer.example.Statistics; import com.rapidminer.gui.tools.ResourceLabel; import com.rapidminer.template.RoleAssignment; import com.rapidminer.template.RoleRequirement; import com.rapidminer.template.TemplateController; import com.rapidminer.template.TemplateState; import com.rapidminer.tools.I18N; import com.rapidminer.tools.Ontology; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.HashMap; import java.util.Map; import java.util.Observable; import java.util.Observer; import java.util.SortedSet; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingConstants; import org.jdesktop.swingx.autocomplete.AutoCompleteDecorator; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.block.BlockBorder; import org.jfree.chart.plot.PiePlot; import org.jfree.data.general.DefaultPieDataset; /** * Used to specify an attribute for a {@link RoleRequirement}. Shows the * {@link RoleRequirement#getDescription()} and a small plot visualizing the distribution of the * currently selected attribute. * * @author Simon Fischer * */ public class RoleRequirementSelector extends JPanel { private static final long serialVersionUID = 1L; private TemplateController controller; private RoleRequirement requirement; // UI Components /** Label for displaying the help text. */ private JLabel helpLabel = new JLabel(""); /** Combo box to select attribute from. */ private JComboBox<String> attributeCombo = new JComboBox<>(); /** Combo box to select positive value in case of binomial label. */ private JComboBox<String> positiveClassCombo = new JComboBox<>(); /** * Caches positive classes for {@link RoleAssignment}s so we restore the original state after * switching. */ private Map<String, String> positiveClassesCache = new HashMap<>(); private ResourceLabel columnLabel = new ResourceLabel("template.column_label", SwingConstants.RIGHT) { private static final long serialVersionUID = 1L; @Override public Dimension getPreferredSize() { return new Dimension(110, (int) super.getPreferredSize().getHeight()); }; }; private ResourceLabel positiveClassLabel = new ResourceLabel("template.positive_class_label", SwingConstants.RIGHT) { private static final long serialVersionUID = 1L; @Override public Dimension getPreferredSize() { return new Dimension(110, (int) super.getPreferredSize().getHeight()); }; }; private ChartPanel chartPanel; private boolean areValuesAdjusting = false; private RoundTitledBorder border = new RoundTitledBorder(3, ""); public RoleRequirementSelector(final TemplateController controller) { super(new BorderLayout()); setBorder(border); this.controller = controller; setBackground(Color.WHITE); updateRequirement(); controller.getModel().addObserver(new Observer() { @Override public void update(Observable o, Object arg) { if (TemplateState.OBSERVER_EVENT_TEMPLATE.equals(arg)) { updateRequirement(); updateComponents(); } else if (TemplateState.OBSERVER_EVENT_ROLES.equals(arg)) { assignSelectionToCombo(); updateComponents(); attributeCombo.repaint(); } else if (TemplateState.OBSERVER_EVENT_INPUT.equals(arg)) { updateAttributes(); } } }); AutoCompleteDecorator.decorate(attributeCombo); AutoCompleteDecorator.decorate(positiveClassCombo); attributeCombo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (areValuesAdjusting) { return; } assignRoles(); } }); positiveClassCombo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (areValuesAdjusting) { return; } assignRoles(); } }); helpLabel.setHorizontalAlignment(SwingConstants.CENTER); add(helpLabel, BorderLayout.PAGE_START); chartPanel = new ChartPanel(null, 250, 250, 100, 100, 360, 360, true, false, false, false, false, false); chartPanel.setMinimumDrawWidth(0); chartPanel.setMaximumDrawWidth(Integer.MAX_VALUE); chartPanel.setMinimumDrawHeight(0); chartPanel.setMaximumDrawHeight(Integer.MAX_VALUE); attributeCombo.setPreferredSize(new Dimension(100, 30)); attributeCombo.setMaximumSize(new Dimension(150, 30)); add(chartPanel, BorderLayout.CENTER); JComponent comboPanel = new JPanel(); comboPanel.setLayout(new BoxLayout(comboPanel, BoxLayout.PAGE_AXIS)); JComponent comboPanelAtt = new JPanel(); comboPanelAtt.setBackground(Color.WHITE); comboPanelAtt.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); JComponent comboPanelClass = new JPanel(); comboPanelClass.setBackground(Color.WHITE); comboPanelClass.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); positiveClassCombo.setPreferredSize(new Dimension(100, 30)); positiveClassCombo.setMaximumSize(new Dimension(150, 30)); positiveClassLabel.setLabelFor(positiveClassCombo); positiveClassLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); positiveClassLabel.setToolTipText(positiveClassLabel.getText()); positiveClassLabel.setHorizontalAlignment(SwingConstants.RIGHT); columnLabel.setLabelFor(attributeCombo); columnLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); columnLabel.setToolTipText(columnLabel.getText()); columnLabel.setHorizontalAlignment(SwingConstants.RIGHT); comboPanelAtt.add(columnLabel); comboPanelAtt.add(attributeCombo); comboPanelClass.add(positiveClassLabel); comboPanelClass.add(positiveClassCombo); comboPanel.add(comboPanelAtt); comboPanel.add(comboPanelClass); add(comboPanel, BorderLayout.SOUTH); updateComponents(); } private void updateRequirement() { if (controller.getModel().getTemplate() != null) { RoleRequirement newRoleRequirement = controller.getModel().getTemplate().getRoleRequirement(0); if (newRoleRequirement != requirement) { requirement = newRoleRequirement; positiveClassesCache.clear(); if (Ontology.ATTRIBUTE_VALUE_TYPE.isA(requirement.getValueType(), Ontology.NOMINAL)) { positiveClassCombo.setVisible(true); positiveClassLabel.setVisible(true); } else { positiveClassCombo.setVisible(false); positiveClassLabel.setVisible(false); } } } } private void updateAttributes() { ExampleSet input = controller.getModel().getInputData(); if (input == null) { attributeCombo.removeAllItems(); attributeCombo.setSelectedItem(null); } else { attributeCombo.removeAllItems(); attributeCombo.setSelectedItem(null); SortedSet<String> sortedNames = controller.getCompatibleAttributes(requirement); for (String name : sortedNames) { attributeCombo.addItem(name); } if (attributeCombo.getItemCount() > 0) { attributeCombo.setSelectedIndex(0); } else { attributeCombo.setSelectedIndex(-1); } assignSelectionToCombo(); boolean enabled = attributeCombo.getItemCount() > 0; attributeCombo.setEnabled(enabled); positiveClassCombo.setEnabled(enabled); positiveClassLabel.setEnabled(enabled); } } private JFreeChart makeChart(ExampleSet exampleSet, Attribute att) { DefaultPieDataset pieDataset = new DefaultPieDataset(); if (att.isNominal()) { for (String val : att.getMapping().getValues()) { pieDataset.setValue(val, exampleSet.getStatistics(att, Statistics.COUNT, val)); } } JFreeChart chart = ChartFactory.createPieChart(null, pieDataset, true, false, false); chart.setBackgroundPaint(Color.WHITE); chart.getLegend().setFrame(BlockBorder.NONE); chart.setBackgroundImageAlpha(0.0f); chart.setBorderVisible(false); PiePlot plot = (PiePlot) chart.getPlot(); plot.setLabelGenerator(null); plot.setShadowPaint(null); plot.setOutlineVisible(false); plot.setBackgroundPaint(new Color(255, 255, 255, 0)); plot.setBackgroundImageAlpha(0.0f); plot.setCircular(true); return chart; } private void assignSelectionToCombo() { try { areValuesAdjusting = true; if ((requirement == null) || (controller.getModel().getInputData() == null)) { attributeCombo.setSelectedItem(null); positiveClassCombo.setSelectedItem(null); return; } TemplateState state = controller.getModel(); RoleAssignment assignment = state.getRoleAssignment(requirement.getRoleName()); if (assignment == null) { attributeCombo.setSelectedItem(null); return; } // Remember choice for assignRoles positiveClassesCache.put(assignment.getAttributeName(), assignment.getPositiveClass()); Attribute att = state.getInputData().getAttributes().get(assignment.getAttributeName()); if (att != null) { attributeCombo.setSelectedItem(att.getName()); positiveClassCombo.setSelectedItem(null); positiveClassCombo.removeAllItems(); if (att.isNominal()) { for (String value : att.getMapping().getValues()) { positiveClassCombo.addItem(value); } } positiveClassCombo.setSelectedItem(assignment.getPositiveClass()); } else { attributeCombo.setSelectedItem(null); positiveClassCombo.setSelectedItem(null); } if (att != null && attributeCombo.getSelectedItem() != null && attributeCombo.getSelectedItem().equals(att.getName())) { chartPanel.setChart(makeChart(state.getInputData(), att)); chartPanel.setVisible(true); } else { chartPanel.setChart(null); chartPanel.setVisible(false); } } finally { areValuesAdjusting = false; } } private void updateComponents() { if (requirement != null) { border.setTitle(I18N.getMessage(I18N.getGUIBundle(), "gui.label.template.select_role_title.label", requirement.getHumanName())); if (attributeCombo.getItemCount() > 0) { helpLabel.setText( "<html><div style=\"width: 280 px\">" + requirement.getDescription() + "</div></html>"); } else { helpLabel.setText("<html><div style=\"width: 280 px\"><strong><font color=\"#FF0000\">" + I18N.getMessage(I18N.getGUIBundle(), "gui.label.template.no_compatible_attribute.label", Ontology.ATTRIBUTE_VALUE_TYPE.mapIndex(requirement.getValueType())) + "</font></strong></div></html>"); } } else { helpLabel.setText(""); border.setTitle(""); } } private void assignRoles() { TemplateState state = controller.getModel(); String attributeName = (String) attributeCombo.getSelectedItem(); Attribute selectedAtt = null; if (attributeName != null) { selectedAtt = state.getInputData().getAttributes().get(attributeName); if (selectedAtt != null) { chartPanel.setChart(makeChart(state.getInputData(), selectedAtt)); } } String positiveClass = (String) positiveClassCombo.getSelectedItem(); if (positiveClass != null && selectedAtt != null) { if (!selectedAtt.getMapping().getValues().contains(positiveClass)) { positiveClass = null; } } if ((positiveClass == null) && (selectedAtt != null)) { String previousPositiveClass = positiveClassesCache.get(attributeName); if (previousPositiveClass != null) { controller.assignRole(requirement, attributeName, previousPositiveClass); } else { controller.assignRole(requirement, controller.makeRoleAssignment(requirement, selectedAtt)); } } else { controller.assignRole(requirement, attributeName, positiveClass); } } }