/** * Copyright (C) 2001-2017 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.gui.properties; import java.awt.BorderLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.util.Collections; import java.util.LinkedList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.border.EtchedBorder; import com.rapidminer.gui.properties.tablepanel.TablePanel; import com.rapidminer.gui.tools.ResourceAction; import com.rapidminer.gui.tools.ResourceActionAdapter; import com.rapidminer.gui.tools.dialogs.ButtonDialog; import com.rapidminer.operator.Operator; import com.rapidminer.operator.preprocessing.filter.ExampleFilter; import com.rapidminer.parameter.ParameterTypeFilter; import com.rapidminer.parameter.ParameterTypeList; import com.rapidminer.parameter.ParameterTypeTupel; import com.rapidminer.tools.I18N; /** * This dialog displays the custom filters for the {@link ExampleFilter} operator. * * @author Marco Boeck * */ public class FilterPropertyDialog extends PropertyDialog { private static final long serialVersionUID = 2417533731869697659L; /** the operator for this dialog */ private final Operator operator; /** the model of the TablePanel for this dialog */ private FilterTableModel model; private JRadioButton radioButtonAND; private JRadioButton radioButtonOR; private JCheckBox checkBoxMetadata; /** * Creates a new {@link FilterPropertyDialog}. * * @param type * @param key */ public FilterPropertyDialog(final Operator operator, final ParameterTypeFilter type, final String key) { super(type, key); if (operator == null) { throw new IllegalArgumentException("operator must not be null!"); } this.operator = operator; initGUI(type); initOperatorSettings(); } /** * Initializes the GUI. */ private void initGUI(final ParameterTypeFilter type) { JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); model = new FilterTableModel(type.getInputPort()); final TablePanel innerPanel = new TablePanel(model, true, false); innerPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED)); JButton okButton = new JButton(new ResourceAction("ok") { private static final long serialVersionUID = 2265489760585034488L; @Override public void actionPerformed(final ActionEvent e) { okAction(); } }); // deliberately not the normal ButtonDialog OK button -> it's very irritating to press Enter // to confirm your value // and have your dialog vanish. This behavior is ok for powerusers who love their keyboard // to death, // and know everything inside out, but the vast majority are NOT powerusers // and for them the default behavior is just annoying okButton.setMnemonic(I18N.getMessage(I18N.getGUIBundle(), "gui.action.settings_ok.mne").charAt(0)); JButton cancelButton = makeCancelButton(); JButton addRowButton = new JButton(new ResourceAction("list.add_row") { private static final long serialVersionUID = 5289974084350157673L; @Override public void actionPerformed(final ActionEvent e) { innerPanel.getModel().appendRow(); } }); // add radio buttons to chose between AND and OR for the filters JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new GridBagLayout()); ButtonGroup logicRadioButtonGroup = new ButtonGroup(); radioButtonAND = new JRadioButton(new ResourceActionAdapter(true, "filter_property_dialog.radio_and") { private static final long serialVersionUID = -7003906588940462016L; @Override public void actionPerformed(final ActionEvent e) {} // only used as a flag }); radioButtonAND.setSelected(true); radioButtonOR = new JRadioButton(new ResourceActionAdapter(true, "filter_property_dialog.radio_or") { private static final long serialVersionUID = -7003906588940462016L; @Override public void actionPerformed(final ActionEvent e) {} // only used as a flag }); checkBoxMetadata = new JCheckBox(new ResourceActionAdapter(true, "filter_property_dialog.check_metadata") { private static final long serialVersionUID = -7003906588940462016L; @Override public void actionPerformed(final ActionEvent e) { if (checkBoxMetadata.isSelected()) { model.setCheckMetaDataForComparators(true); } else { model.setCheckMetaDataForComparators(false); } } }); checkBoxMetadata.setSelected(true); logicRadioButtonGroup.add(radioButtonAND); logicRadioButtonGroup.add(radioButtonOR); GridBagConstraints gbc = new GridBagConstraints(); JLabel labelLogic = new JLabel(I18N.getMessage(I18N.getGUIBundle(), "gui.dialog.filter_property_dialog.logic.title")); labelLogic.setToolTipText(I18N.getMessage(I18N.getGUIBundle(), "gui.dialog.filter_property_dialog.logic.tip")); gbc.gridx = 1; gbc.weightx = 0.0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.insets = new Insets(5, 5, 5, 5); buttonPanel.add(labelLogic, gbc); gbc.gridx = 2; buttonPanel.add(radioButtonAND, gbc); gbc.gridx = 3; buttonPanel.add(radioButtonOR, gbc); gbc.gridx = 4; gbc.insets = new Insets(5, 25, 5, 5); buttonPanel.add(checkBoxMetadata, gbc); gbc.insets = new Insets(5, 5, 5, 5); gbc.weightx = 1.0; gbc.gridx = 5; buttonPanel.add(Box.createHorizontalBox(), gbc); gbc.weightx = 0.0; gbc.gridx = 6; buttonPanel.add(addRowButton, gbc); gbc.gridx = 7; buttonPanel.add(okButton, gbc); gbc.gridx = 8; buttonPanel.add(cancelButton, gbc); panel.add(innerPanel, BorderLayout.CENTER); setLocationRelativeTo(null); setDefaultSize(ButtonDialog.LARGE); layoutDefault(panel, buttonPanel); } /** * Initializes this dialog with the existing filters stored for the operator. */ private void initOperatorSettings() { // add filters to model List<String[]> tupelList = new LinkedList<>(); // this is necessary as operator.getParameterList() replaces '%{test}' by 'test' String rawParameterString = operator.getParameters().getParameterAsSpecified(ExampleFilter.PARAMETER_FILTERS_LIST); List<String[]> operatorFilterList = rawParameterString != null ? ParameterTypeList .transformString2List(rawParameterString) : Collections.<String[]> emptyList(); for (String[] entry : operatorFilterList) { tupelList.add(ParameterTypeTupel.transformString2Tupel(entry[1])); } model.setRowTupels(tupelList); // set logic operation in dialog if (operator.getParameterAsBoolean(ExampleFilter.PARAMETER_FILTERS_LOGIC_AND)) { radioButtonAND.setSelected(true); } else { radioButtonOR.setSelected(true); } // set selection for checking meta data if (!operator.getParameterAsBoolean(ExampleFilter.PARAMETER_FILTERS_CHECK_METADATA)) { checkBoxMetadata.setSelected(false); model.setCheckMetaDataForComparators(false); } } /** * Stores the settings from the model to the operator via its parameters. */ private void okAction() { // add filters to hidden filter list parameter List<String[]> filterList = new LinkedList<>(); for (String[] tupel : model.getRowTupels()) { filterList.add(new String[] { ExampleFilter.PARAMETER_FILTERS_ENTRY_KEY, ParameterTypeTupel.transformTupel2String(tupel) }); } operator.setListParameter(ExampleFilter.PARAMETER_FILTERS_LIST, filterList); // set logic operation operator.setParameter(ExampleFilter.PARAMETER_FILTERS_LOGIC_AND, Boolean.toString(radioButtonAND.isSelected())); // add selection about checking meta data to hidden filter parameter operator.setParameter(ExampleFilter.PARAMETER_FILTERS_CHECK_METADATA, Boolean.toString(checkBoxMetadata.isSelected())); dispose(); } @Override public void setVisible(final boolean b) { if (model.getRowCount() == 0) { model.appendRow(); } super.setVisible(b); } }