/* * RapidMiner * * Copyright (C) 2001-2011 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.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.gui.templates; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileFilter; import java.util.Collection; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.TreeSet; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingConstants; import com.rapidminer.Process; import com.rapidminer.gui.tools.ExtendedJScrollPane; import com.rapidminer.gui.tools.ResourceLabel; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.gui.tools.dialogs.ButtonDialog; import com.rapidminer.operator.Operator; import com.rapidminer.operator.OperatorChain; import com.rapidminer.parameter.ParameterType; import com.rapidminer.parameter.UndefinedParameterError; import com.rapidminer.tools.FileSystemService; import com.rapidminer.tools.Tools; /** * The save as template dialog assists the user in creating a new process * template. Template processes are saved in the local .rapidminer directory of the * user. The name, description and additional parameters to set can be specified * by the user. * * @author Ingo Mierswa, Tobias Malbrecht */ public class SaveAsTemplateDialog extends ButtonDialog { private static final long serialVersionUID = -4892200177390173103L; private boolean ok = false; private final Set<OperatorParameterPair> selectedParameters = new HashSet<OperatorParameterPair>(); private final JTextField nameField = new JTextField(); private final JTextField groupField = new JTextField(); private final JTextArea descriptionField = new JTextArea(5, 40); private Process process; /** Creates a new save as template dialog. */ public SaveAsTemplateDialog(Process process) { super("save_as_template", true); this.process = process; descriptionField.setText(process.getRootOperator().getUserDescription()); descriptionField.setLineWrap(true); descriptionField.setWrapStyleWord(true); JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.anchor = GridBagConstraints.FIRST_LINE_START; JLabel label = new ResourceLabel("save_as_template.name"); c.fill = GridBagConstraints.NONE; c.weightx = 0; c.weighty = 0; c.gridwidth = GridBagConstraints.RELATIVE; c.insets = new Insets(0, 0, GAP, GAP); label.setLabelFor(nameField); panel.add(label, c); c.weightx = 1; c.gridwidth = GridBagConstraints.REMAINDER; c.insets = new Insets(0, 0, GAP, 0); c.fill = GridBagConstraints.BOTH; panel.add(nameField, c); label = new ResourceLabel("save_as_template.group"); c.fill = GridBagConstraints.NONE; c.weightx = 0; c.weighty = 0; c.gridwidth = GridBagConstraints.RELATIVE; c.insets = new Insets(0, 0, GAP, GAP); label.setLabelFor(groupField); panel.add(label, c); c.weightx = 1; c.gridwidth = GridBagConstraints.REMAINDER; c.insets = new Insets(0, 0, GAP, 0); c.fill = GridBagConstraints.BOTH; panel.add(groupField, c); label = new ResourceLabel("save_as_template.description"); c.insets = new Insets(0, 0, GAP, GAP); c.weightx = 0; c.gridwidth = GridBagConstraints.RELATIVE; c.fill = GridBagConstraints.NONE; label.setLabelFor(descriptionField); panel.add(label, c); c.weightx = 1; c.weighty = 0.1; c.gridwidth = GridBagConstraints.REMAINDER; c.insets = new Insets(0, 0, GAP, 0); c.fill = GridBagConstraints.BOTH; JScrollPane descriptionPane = new ExtendedJScrollPane(descriptionField); descriptionPane.setBorder(createBorder()); panel.add(descriptionPane, c); JScrollPane tablePane = new ExtendedJScrollPane(makeCheckboxTable(process.getRootOperator())); tablePane.setBorder(createBorder()); c.weightx = 1; c.weighty = .9; c.gridwidth = GridBagConstraints.REMAINDER; c.insets = new Insets(0, 0, 0, 0); panel.add(tablePane, c); JButton okButton = makeOkButton(); layoutDefault(panel, NORMAL, okButton, makeCancelButton()); getRootPane().setDefaultButton(okButton); } private JComponent makeCheckboxTable(Operator operator) { List<Operator> ops = new LinkedList<Operator>(); ops.add(operator); if (operator instanceof OperatorChain) { ops.addAll(((OperatorChain)operator).getAllInnerOperators()); } JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.weightx = 1; c.weighty = 0; c.insets = new Insets(0, 0, 0, 0); c.fill = GridBagConstraints.BOTH; c.gridwidth = GridBagConstraints.REMAINDER; for (Operator op : ops) { JPanel operatorPanel = new JPanel(new BorderLayout()); Collection<ParameterType> parameterTypes = op.getParameters().getParameterTypes(); if (parameterTypes.isEmpty()) { continue; } JLabel label = new JLabel("<html>"+op.getName()+"<br/><small>"+op.getOperatorDescription().getName()+"</small></html>"); //label.setFont(label.getFont().deriveFont(Font.BOLD)); label.setIcon(op.getOperatorDescription().getSmallIcon()); label.setPreferredSize(new Dimension(190,50)); label.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); label.setVerticalAlignment(SwingConstants.TOP); operatorPanel.add(label, BorderLayout.WEST); int size = parameterTypes.size(); GridLayout layout = new GridLayout(size, 2); layout.setHgap(GAP); layout.setVgap(GAP); JPanel parameterPanel = new JPanel(layout); for (final ParameterType type : parameterTypes) { final JCheckBox box = new JCheckBox(type.getKey()); final OperatorParameterPair opp = new OperatorParameterPair(op.getName(), type.getKey()); box.setSelected(false); parameterPanel.add(box); box.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (box.isSelected()) { selectedParameters.add(opp); } else { selectedParameters.remove(opp); } } }); String current; try { current = op.getParameterAsString(type.getKey()); if (current == null){ current = ""; } } catch (UndefinedParameterError e1) { current = ""; } JLabel currentLabel = new JLabel(current); if (!current.equals(type.toString(type.getDefaultValue()))) { currentLabel.setFont(currentLabel.getFont().deriveFont(Font.BOLD)); box.setSelected(true); selectedParameters.add(opp); } parameterPanel.add(currentLabel); } operatorPanel.add(parameterPanel, BorderLayout.CENTER); operatorPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.LIGHT_GRAY), BorderFactory.createEmptyBorder(4, 4, 4, 4))); panel.add(operatorPanel, c); } c.fill = GridBagConstraints.BOTH; c.weighty = 1; panel.add(new JPanel(new BorderLayout()), c); return panel; } private void addMandatoryParameters(Operator operator, Set<OperatorParameterPair> selectedOptional) { Iterator<ParameterType> i = operator.getParameters().getParameterTypes().iterator(); while (i.hasNext()) { ParameterType type = i.next(); if (!type.isOptional() && !operator.getParameters().isSet(type.getKey())) { selectedOptional.add(new OperatorParameterPair(operator.getName(), type.getKey())); } } if (operator instanceof OperatorChain) { for (Operator child : ((OperatorChain)operator).getImmediateChildren()) addMandatoryParameters(child, selectedOptional); } } public boolean isOk() { return ok; } public Template getTemplate() { String name = nameField.getText(); String group = groupField.getText(); Set<OperatorParameterPair> selectedOptional = new TreeSet<OperatorParameterPair>(new Comparator<OperatorParameterPair>() { @Override public int compare(OperatorParameterPair o1, OperatorParameterPair o2) { return o1.compareTo(o2); } }); selectedOptional.addAll(selectedParameters); addMandatoryParameters(process.getRootOperator(), selectedOptional); return new Template(name, group, descriptionField.getText(), name + ".xml", selectedOptional); } private boolean checkIfNameOk() { String name = nameField.getText(); if ((name == null) || (name.length() == 0)) { SwingTools.showVerySimpleErrorMessage("no_template_name"); return false; } // File[] preDefinedTemplateFiles = ParameterService.getConfigFile("templates").listFiles(new FileFilter() { // public boolean accept(File file) { // return file.getName().endsWith(".template"); // } // }); File[] userDefinedTemplateFiles = FileSystemService.getUserRapidMinerDir().listFiles(new FileFilter() { @Override public boolean accept(File file) { return file.getName().endsWith(".template"); } }); for (int i = 0; i < userDefinedTemplateFiles.length; i++) { String tempName = userDefinedTemplateFiles[i].getName().substring(0, userDefinedTemplateFiles[i].getName().lastIndexOf(".")); if (tempName.equals(name)) { SwingTools.showVerySimpleErrorMessage("Name '" + name + "' is already used." + Tools.getLineSeparator() + "Please change name or delete the old template!"); return false; } } return true; } @Override protected void ok() { if (checkIfNameOk()) { ok = true; dispose(); } } @Override protected void cancel() { ok = false; dispose(); } }