/** * 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.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.GridLayout; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Properties; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import com.rapidminer.gui.properties.SettingsItem.Type; import com.rapidminer.gui.properties.celleditors.value.PropertyValueCellEditor; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.operator.Operator; import com.rapidminer.parameter.ParameterType; import com.rapidminer.tools.I18N; import com.rapidminer.tools.ParameterService; /** * The SettingsPropertyPanel is used to display settings of the same group. The used settings items * are read from the {@link ParameterService}. This class also holds a method for applying changes * in the value back to the {@link ParameterService}. * * @author Sebastian Land, Simon Fischer, Adrian Wilke */ public class SettingsPropertyPanel extends PropertyPanel { private static final long serialVersionUID = 313811558626370370L; private static final int FIRST_SUBGROUP_TOP_MARGIN = 6; private static final int SUBGROUP_TOP_MARGIN = 20; private final Collection<ParameterType> shownParameterTypes; private final Collection<ParameterType> allParameterTypes; private final Properties allParameterValues; private final String groupTitle; /** Only draw sub-groups, if information about them exist */ private boolean useSubGroups = false; /** The first sub-group has special margins */ private boolean isFirstSubGroup = true; /** Sub-group 'Miscellaneous' should one be used one time */ private boolean subGroupMiscUsed = false; /** Sub-group with the title of the tab should one be used one time */ private boolean subGroupTabNameUsed = false; public SettingsPropertyPanel(String groupTitle, List<SettingsItem> itemSubGroups, List<SettingsItem> itemParameters, String filter, Properties propertyCache) { this.groupTitle = groupTitle; // These data structures are used to provide overwritten PropertyPanel methods shownParameterTypes = new LinkedList<>(); allParameterTypes = new LinkedList<>(); if (propertyCache != null) { allParameterValues = propertyCache; } else { allParameterValues = new Properties(); } // Add parameters of sub-groups first for (SettingsItem subGroup : itemSubGroups) { for (SettingsItem item : subGroup.getChildren(Type.PARAMETER, filter)) { shownParameterTypes.add(item.getParameterType()); } for (SettingsItem item : subGroup.getChildren(Type.PARAMETER)) { allParameterTypes.add(item.getParameterType()); if (propertyCache == null || !propertyCache.containsKey(item.getKey())) { allParameterValues.put(item.getKey(), ParameterService.getParameterValue(item.getKey())); } } } // Add parameters without sub-group for (SettingsItem item : itemParameters) { allParameterTypes.add(item.getParameterType()); shownParameterTypes.add(item.getParameterType()); if (propertyCache == null || !propertyCache.containsKey(item.getKey())) { allParameterValues.put(item.getKey(), ParameterService.getParameterValue(item.getKey())); } } if (!itemSubGroups.isEmpty()) { useSubGroups = true; } setupComponents(); } @Override protected Collection<ParameterType> getProperties() { return shownParameterTypes; } @Override protected String getValue(ParameterType type) { String value = allParameterValues.getProperty(type.getKey()); if (value == null) { return null; } else { return type.transformNewValue(value); } } @Override protected void setValue(Operator operator, ParameterType type, String value) { allParameterValues.put(type.getKey(), value); if (!SettingsItems.INSTANCE.containsKey(type.getKey())) { // Object is automatically added to an internal list SettingsItems.createAndAddItem(type.getKey(), Type.PARAMETER); } } /** Applies the properties without saving them. */ public void applyProperties() { for (ParameterType type : allParameterTypes) { String value = allParameterValues.getProperty(type.getKey()); ParameterService.setParameterValue(type, value); } } @Override protected Operator getOperator() { return null; } /** * Creates a panel with a heading. * * @param labelText * The text for the heading * * @return The panel */ private JPanel createSubGroupPanel(String labelText) { JLabel subGroupLabel = new JLabel(); Font font = subGroupLabel.getFont(); font = font.deriveFont(Font.BOLD, 14f); subGroupLabel.setFont(font); subGroupLabel.setForeground(SettingsTabs.COLOR_SUBGROUP); subGroupLabel.setText(labelText); int top = SUBGROUP_TOP_MARGIN; if (isFirstSubGroup) { isFirstSubGroup = false; top = FIRST_SUBGROUP_TOP_MARGIN; } subGroupLabel.setBorder(BorderFactory.createEmptyBorder(top, 0, 7, 0)); JPanel subGroupPanel = new JPanel(); subGroupPanel.setLayout(new BoxLayout(subGroupPanel, BoxLayout.LINE_AXIS)); subGroupPanel.add(subGroupLabel); subGroupPanel.add(Box.createHorizontalGlue()); return subGroupPanel; } /** * Checks, if parent item should be added as heading. * * @param parent * The parent settings item * @return if the parent item should be added */ private boolean useParentAsHeading(SettingsItem parent) { if (!parent.getType().equals(Type.SUB_GROUP)) { // Only sub-groups are added as headings return false; } else if (parent.isUsedInDialog()) { // No sub-group should be added twice return false; } else { return true; } } /** * Checks, if a heading 'miscellaneous' should be added. * * @param parent * The parent settings item * @return if the heading 'misc' should be added */ private boolean useMiscHeading(SettingsItem parent) { if (parent.getType().equals(Type.SUB_GROUP)) { // Do not add Miscellaneous, if the is a sub-group with a better title return false; } else if (subGroupMiscUsed) { // The sub group 'Misc' should not be added twice return false; } else if (!useSubGroups) { // Only use 'Misc', if there are other known sub-groups return false; } else { return true; } } /** * Checks, if a heading with the tab name should be added. * * @param parent * The parent settings item * @return if the tab name should be added as heading */ private boolean useTabHeading(SettingsItem parent) { if (parent.getType().equals(Type.SUB_GROUP)) { // Do not add tab name, if the is a sub-group with a better title return false; } else if (subGroupTabNameUsed) { // The heading should only be added one time return false; } else if (useSubGroups) { // Only use tab name, if no other sub-groups are used return false; } else { return true; } } @Override protected JPanel createParameterPanel(ParameterType type, PropertyValueCellEditor editor, final Component editorComponent) { // Remove default tool tip, which is set in superclass if (editorComponent instanceof JComponent) { ((JComponent) editorComponent).setToolTipText(null); } JPanel containerPanel = new JPanel(); containerPanel.setLayout(new BoxLayout(containerPanel, BoxLayout.PAGE_AXIS)); SettingsItem settingsItem = SettingsItems.INSTANCE.get(type.getKey()); // Add sub-group title before adding properties SettingsItem parent = settingsItem.getParent(); if (parent != null) { if (useParentAsHeading(parent)) { parent.setUsedInDialog(true); containerPanel.add(createSubGroupPanel(parent.getTitle())); } else if (useMiscHeading(parent)) { subGroupMiscUsed = true; containerPanel.add(createSubGroupPanel(I18N.getGUIMessage("gui.dialog.settings.misc"))); } else if (useTabHeading(parent)) { subGroupTabNameUsed = true; containerPanel.add(createSubGroupPanel(groupTitle)); } } // Add parameter JPanel contentsPanel = new JPanel(); contentsPanel.setOpaque(isOpaque()); contentsPanel.setPreferredSize( new Dimension((int) contentsPanel.getPreferredSize().getWidth(), VALUE_CELL_EDITOR_HEIGHT)); JPanel parameterPanel = null; if (editor.rendersLabel()) { // Editor renders label for: Checkboxes parameterPanel = new JPanel(new BorderLayout()); // Contents panel contains component contentsPanel.setLayout(new BorderLayout()); contentsPanel.add(editorComponent, editorComponent instanceof JCheckBox ? BorderLayout.WEST : BorderLayout.CENTER); parameterPanel.add(contentsPanel); // Replace checkbox text // (For default implementation see DefaultCellEditor.java) Component[] components = contentsPanel.getComponents(); if (components.length != 0) { Component component = components[0]; if (component instanceof JCheckBox) { JCheckBox jcheckbox = (JCheckBox) component; jcheckbox.setText(settingsItem.getTitle()); jcheckbox.setFont(jcheckbox.getFont().deriveFont(~Font.ITALIC)); } } } else { // Editor does not render label for: Input and selection boxes parameterPanel = new JPanel(); parameterPanel.setLayout(new BoxLayout(parameterPanel, BoxLayout.LINE_AXIS)); // Contents panel contains label and component contentsPanel.setLayout(new GridLayout(1, 2)); JLabel label = new JLabel(settingsItem.getTitle()); label.setOpaque(isOpaque()); label.setFont(getFont()); label.setBackground(getBackground()); int style = Font.PLAIN; if (!type.isOptional()) { style |= Font.BOLD; } label.setFont(label.getFont().deriveFont(style)); label.setLabelFor(editorComponent); if (!isEnabled()) { SwingTools.setEnabledRecursive(label, false); } contentsPanel.add(label); contentsPanel.add(editorComponent); parameterPanel.add(contentsPanel); } JPanel surroundingPanel = new JPanel(new BorderLayout()); surroundingPanel.add(parameterPanel, BorderLayout.CENTER); addHelpLabel(type.getKey(), settingsItem.getTitle(), settingsItem.getDescription(), type.getRange(), type.isOptional(), surroundingPanel); containerPanel.add(surroundingPanel); return containerPanel; } }